asllisting.c revision 202771
1
2/******************************************************************************
3 *
4 * Module Name: asllisting - Listing file generation
5 *
6 *****************************************************************************/
7
8/******************************************************************************
9 *
10 * 1. Copyright Notice
11 *
12 * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp.
13 * All rights reserved.
14 *
15 * 2. License
16 *
17 * 2.1. This is your license from Intel Corp. under its intellectual property
18 * rights.  You may have additional license terms from the party that provided
19 * you this software, covering your right to use that party's intellectual
20 * property rights.
21 *
22 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23 * copy of the source code appearing in this file ("Covered Code") an
24 * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25 * base code distributed originally by Intel ("Original Intel Code") to copy,
26 * make derivatives, distribute, use and display any portion of the Covered
27 * Code in any form, with the right to sublicense such rights; and
28 *
29 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30 * license (with the right to sublicense), under only those claims of Intel
31 * patents that are infringed by the Original Intel Code, to make, use, sell,
32 * offer to sell, and import the Covered Code and derivative works thereof
33 * solely to the minimum extent necessary to exercise the above copyright
34 * license, and in no event shall the patent license extend to any additions
35 * to or modifications of the Original Intel Code.  No other license or right
36 * is granted directly or by implication, estoppel or otherwise;
37 *
38 * The above copyright and patent license is granted only if the following
39 * conditions are met:
40 *
41 * 3. Conditions
42 *
43 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44 * Redistribution of source code of any substantial portion of the Covered
45 * Code or modification with rights to further distribute source must include
46 * the above Copyright Notice, the above License, this list of Conditions,
47 * and the following Disclaimer and Export Compliance provision.  In addition,
48 * Licensee must cause all Covered Code to which Licensee contributes to
49 * contain a file documenting the changes Licensee made to create that Covered
50 * Code and the date of any change.  Licensee must include in that file the
51 * documentation of any changes made by any predecessor Licensee.  Licensee
52 * must include a prominent statement that the modification is derived,
53 * directly or indirectly, from Original Intel Code.
54 *
55 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56 * Redistribution of source code of any substantial portion of the Covered
57 * Code or modification without rights to further distribute source must
58 * include the following Disclaimer and Export Compliance provision in the
59 * documentation and/or other materials provided with distribution.  In
60 * addition, Licensee may not authorize further sublicense of source of any
61 * portion of the Covered Code, and must include terms to the effect that the
62 * license from Licensee to its licensee is limited to the intellectual
63 * property embodied in the software Licensee provides to its licensee, and
64 * not to intellectual property embodied in modifications its licensee may
65 * make.
66 *
67 * 3.3. Redistribution of Executable. Redistribution in executable form of any
68 * substantial portion of the Covered Code or modification must reproduce the
69 * above Copyright Notice, and the following Disclaimer and Export Compliance
70 * provision in the documentation and/or other materials provided with the
71 * distribution.
72 *
73 * 3.4. Intel retains all right, title, and interest in and to the Original
74 * Intel Code.
75 *
76 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77 * Intel shall be used in advertising or otherwise to promote the sale, use or
78 * other dealings in products derived from or relating to the Covered Code
79 * without prior written authorization from Intel.
80 *
81 * 4. Disclaimer and Export Compliance
82 *
83 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84 * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
86 * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
87 * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
88 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89 * PARTICULAR PURPOSE.
90 *
91 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
97 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98 * LIMITED REMEDY.
99 *
100 * 4.3. Licensee shall not export, either directly or indirectly, any of this
101 * software or system incorporating such software without first obtaining any
102 * required license or other approval from the U. S. Department of Commerce or
103 * any other agency or department of the United States Government.  In the
104 * event Licensee exports any such software from the United States or
105 * re-exports any such software from a foreign destination, Licensee shall
106 * ensure that the distribution and export/re-export of the software is in
107 * compliance with all laws, regulations, orders, or other restrictions of the
108 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109 * any of its subsidiaries will export/re-export any technical data, process,
110 * software, or service, directly or indirectly, to any country for which the
111 * United States government or any agency thereof requires an export license,
112 * other governmental approval, or letter of assurance, without first obtaining
113 * such license, approval or letter.
114 *
115 *****************************************************************************/
116
117
118#include <contrib/dev/acpica/compiler/aslcompiler.h>
119#include "aslcompiler.y.h"
120#include <contrib/dev/acpica/include/amlcode.h>
121#include <contrib/dev/acpica/include/acparser.h>
122#include <contrib/dev/acpica/include/acnamesp.h>
123
124#define _COMPONENT          ACPI_COMPILER
125        ACPI_MODULE_NAME    ("aslisting")
126
127/* Local prototypes */
128
129static void
130LsDumpAscii (
131    UINT32                  FileId,
132    UINT32                  Count,
133    UINT8                   *Buffer);
134
135static void
136LsDumpAsciiInComment (
137    UINT32                  FileId,
138    UINT32                  Count,
139    UINT8                   *Buffer);
140
141static ACPI_STATUS
142LsAmlListingWalk (
143    ACPI_PARSE_OBJECT       *Op,
144    UINT32                  Level,
145    void                    *Context);
146
147static void
148LsGenerateListing (
149    UINT32                  FileId);
150
151static void
152LsPushNode (
153    char                    *Filename);
154
155static ASL_LISTING_NODE *
156LsPopNode (
157    void);
158
159static void
160LsCheckException (
161    UINT32                  LineNumber,
162    UINT32                  FileId);
163
164static void
165LsFlushListingBuffer (
166    UINT32                  FileId);
167
168static void
169LsWriteListingHexBytes (
170    UINT8                   *Buffer,
171    UINT32                  Length,
172    UINT32                  FileId);
173
174static UINT32
175LsWriteOneSourceLine (
176    UINT32                  FileId);
177
178static void
179LsFinishSourceListing (
180    UINT32                  FileId);
181
182static void
183LsWriteSourceLines (
184    UINT32                  ToLineNumber,
185    UINT32                  ToLogicalLineNumber,
186    UINT32                  FileId);
187
188static void
189LsWriteNodeToListing (
190    ACPI_PARSE_OBJECT       *Op,
191    UINT32                  FileId);
192
193static void
194LsDoHexOutputC (
195    void);
196
197static void
198LsDoHexOutputAsm (
199    void);
200
201ACPI_STATUS
202LsTreeWriteWalk (
203    ACPI_PARSE_OBJECT       *Op,
204    UINT32                  Level,
205    void                    *Context);
206
207
208/*******************************************************************************
209 *
210 * FUNCTION:    LsTreeWriteWalk
211 *
212 * PARAMETERS:  ASL_WALK_CALLBACK
213 *
214 *
215 * RETURN:      None.
216 *
217 * DESCRIPTION: Dump entire parse tree, for compiler debug only
218 *
219 ******************************************************************************/
220
221ACPI_STATUS
222LsTreeWriteWalk (
223    ACPI_PARSE_OBJECT       *Op,
224    UINT32                  Level,
225    void                    *Context)
226{
227
228    /* Debug output */
229
230    DbgPrint (ASL_TREE_OUTPUT,
231        "%5.5d [%2d]", Op->Asl.LogicalLineNumber, Level);
232    UtPrintFormattedName (Op->Asl.ParseOpcode, Level);
233
234
235    DbgPrint (ASL_TREE_OUTPUT, "\n");
236    return (AE_OK);
237}
238
239
240void
241LsDumpParseTree (
242    void)
243{
244
245    if (!Gbl_DebugFlag)
246    {
247        return;
248    }
249
250    DbgPrint (ASL_TREE_OUTPUT, "\nOriginal parse tree from parser:\n\n");
251    TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD,
252        LsTreeWriteWalk, NULL, NULL);
253}
254
255
256/*******************************************************************************
257 *
258 * FUNCTION:    LsDumpAscii
259 *
260 * PARAMETERS:  FileId          - ID of current listing file
261 *              Count           - Number of bytes to convert
262 *              Buffer          - Buffer of bytes to convert
263 *
264 * RETURN:      None.
265 *
266 * DESCRIPTION: Convert hex bytes to ascii
267 *
268 ******************************************************************************/
269
270static void
271LsDumpAscii (
272    UINT32                  FileId,
273    UINT32                  Count,
274    UINT8                   *Buffer)
275{
276    UINT8                   BufChar;
277    UINT32                  i;
278
279
280    FlPrintFile (FileId, "    \"");
281    for (i = 0; i < Count; i++)
282    {
283        BufChar = Buffer[i];
284        if (isprint (BufChar))
285        {
286            FlPrintFile (FileId, "%c", BufChar);
287        }
288        else
289        {
290            /* Not a printable character, just put out a dot */
291
292            FlPrintFile (FileId, ".");
293        }
294    }
295    FlPrintFile (FileId, "\"");
296}
297
298
299/*******************************************************************************
300 *
301 * FUNCTION:    LsDumpAsciiInComment
302 *
303 * PARAMETERS:  FileId          - ID of current listing file
304 *              Count           - Number of bytes to convert
305 *              Buffer          - Buffer of bytes to convert
306 *
307 * RETURN:      None.
308 *
309 * DESCRIPTION: Convert hex bytes to ascii
310 *
311 ******************************************************************************/
312
313static void
314LsDumpAsciiInComment (
315    UINT32                  FileId,
316    UINT32                  Count,
317    UINT8                   *Buffer)
318{
319    UINT8                   BufChar = 0;
320    UINT8                   LastChar;
321    UINT32                  i;
322
323
324    FlPrintFile (FileId, "    \"");
325    for (i = 0; i < Count; i++)
326    {
327        LastChar = BufChar;
328        BufChar = Buffer[i];
329
330        if (isprint (BufChar))
331        {
332            /* Handle embedded C comment sequences */
333
334            if (((LastChar == '*') && (BufChar == '/')) ||
335                ((LastChar == '/') && (BufChar == '*')))
336            {
337                /* Insert a space to break the sequence */
338
339                FlPrintFile (FileId, ".", BufChar);
340            }
341
342            FlPrintFile (FileId, "%c", BufChar);
343        }
344        else
345        {
346            /* Not a printable character, just put out a dot */
347
348            FlPrintFile (FileId, ".");
349        }
350    }
351    FlPrintFile (FileId, "\"");
352}
353
354
355/*******************************************************************************
356 *
357 * FUNCTION:    LsAmlListingWalk
358 *
359 * PARAMETERS:  ASL_WALK_CALLBACK
360 *
361 * RETURN:      Status
362 *
363 * DESCRIPTION: Process one node during a listing file generation.
364 *
365 ******************************************************************************/
366
367static ACPI_STATUS
368LsAmlListingWalk (
369    ACPI_PARSE_OBJECT       *Op,
370    UINT32                  Level,
371    void                    *Context)
372{
373    UINT8                   FileByte;
374    UINT32                  i;
375    UINT32                  FileId = (UINT32) ACPI_TO_INTEGER (Context);
376
377
378    LsWriteNodeToListing (Op, FileId);
379
380    if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DATA)
381    {
382        /* Buffer is a resource template, don't dump the data all at once */
383
384        return (AE_OK);
385    }
386
387    /* Write the hex bytes to the listing file(s) (if requested) */
388
389    for (i = 0; i < Op->Asl.FinalAmlLength; i++)
390    {
391        if (ACPI_FAILURE (FlReadFile (ASL_FILE_AML_OUTPUT, &FileByte, 1)))
392        {
393            FlFileError (ASL_FILE_AML_OUTPUT, ASL_MSG_READ);
394            AslAbort ();
395        }
396        LsWriteListingHexBytes (&FileByte, 1, FileId);
397    }
398
399    return (AE_OK);
400}
401
402
403/*******************************************************************************
404 *
405 * FUNCTION:    LsGenerateListing
406 *
407 * PARAMETERS:  FileId      - ID of listing file
408 *
409 * RETURN:      None
410 *
411 * DESCRIPTION: Generate a listing file.  This can be one of the several types
412 *              of "listings" supported.
413 *
414 ******************************************************************************/
415
416static void
417LsGenerateListing (
418    UINT32                  FileId)
419{
420
421    /* Start at the beginning of both the source and AML files */
422
423    FlSeekFile (ASL_FILE_SOURCE_OUTPUT, 0);
424    FlSeekFile (ASL_FILE_AML_OUTPUT, 0);
425    Gbl_SourceLine = 0;
426    Gbl_CurrentHexColumn = 0;
427    LsPushNode (Gbl_Files[ASL_FILE_INPUT].Filename);
428
429    /* Process all parse nodes */
430
431    TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD, LsAmlListingWalk,
432                        NULL, (void *) ACPI_TO_POINTER (FileId));
433
434    /* Final processing */
435
436    LsFinishSourceListing (FileId);
437}
438
439
440/*******************************************************************************
441 *
442 * FUNCTION:    LsDoListings
443 *
444 * PARAMETERS:  None.
445 *
446 * RETURN:      None
447 *
448 * DESCRIPTION: Generate all requested listing files.
449 *
450 ******************************************************************************/
451
452void
453LsDoListings (
454    void)
455{
456
457    if (Gbl_C_OutputFlag)
458    {
459        LsGenerateListing (ASL_FILE_C_SOURCE_OUTPUT);
460    }
461
462    if (Gbl_ListingFlag)
463    {
464        LsGenerateListing (ASL_FILE_LISTING_OUTPUT);
465    }
466
467    if (Gbl_AsmOutputFlag)
468    {
469        LsGenerateListing (ASL_FILE_ASM_SOURCE_OUTPUT);
470    }
471
472    if (Gbl_C_IncludeOutputFlag)
473    {
474        LsGenerateListing (ASL_FILE_C_INCLUDE_OUTPUT);
475    }
476
477    if (Gbl_AsmIncludeOutputFlag)
478    {
479        LsGenerateListing (ASL_FILE_ASM_INCLUDE_OUTPUT);
480    }
481}
482
483
484/*******************************************************************************
485 *
486 * FUNCTION:    LsPushNode
487 *
488 * PARAMETERS:  Filename        - Pointer to the include filename
489 *
490 * RETURN:      None
491 *
492 * DESCRIPTION: Push a listing node on the listing/include file stack.  This
493 *              stack enables tracking of include files (infinitely nested)
494 *              and resumption of the listing of the parent file when the
495 *              include file is finished.
496 *
497 ******************************************************************************/
498
499static void
500LsPushNode (
501    char                    *Filename)
502{
503    ASL_LISTING_NODE        *Lnode;
504
505
506    /* Create a new node */
507
508    Lnode = UtLocalCalloc (sizeof (ASL_LISTING_NODE));
509
510    /* Initialize */
511
512    Lnode->Filename = Filename;
513    Lnode->LineNumber = 0;
514
515    /* Link (push) */
516
517    Lnode->Next = Gbl_ListingNode;
518    Gbl_ListingNode = Lnode;
519}
520
521
522/*******************************************************************************
523 *
524 * FUNCTION:    LsPopNode
525 *
526 * PARAMETERS:  None
527 *
528 * RETURN:      List head after current head is popped off
529 *
530 * DESCRIPTION: Pop the current head of the list, free it, and return the
531 *              next node on the stack (the new current node).
532 *
533 ******************************************************************************/
534
535static ASL_LISTING_NODE *
536LsPopNode (
537    void)
538{
539    ASL_LISTING_NODE        *Lnode;
540
541
542    /* Just grab the node at the head of the list */
543
544    Lnode = Gbl_ListingNode;
545    if ((!Lnode) ||
546        (!Lnode->Next))
547    {
548        AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, NULL,
549            "Could not pop empty listing stack");
550        return Gbl_ListingNode;
551    }
552
553    Gbl_ListingNode = Lnode->Next;
554    ACPI_FREE (Lnode);
555
556    /* New "Current" node is the new head */
557
558    return (Gbl_ListingNode);
559}
560
561
562/*******************************************************************************
563 *
564 * FUNCTION:    LsCheckException
565 *
566 * PARAMETERS:  LineNumber          - Current logical (cumulative) line #
567 *              FileId              - ID of output listing file
568 *
569 * RETURN:      None
570 *
571 * DESCRIPTION: Check if there is an exception for this line, and if there is,
572 *              put it in the listing immediately.  Handles multiple errors
573 *              per line.  Gbl_NextError points to the next error in the
574 *              sorted (by line #) list of compile errors/warnings.
575 *
576 ******************************************************************************/
577
578static void
579LsCheckException (
580    UINT32                  LineNumber,
581    UINT32                  FileId)
582{
583
584    if ((!Gbl_NextError) ||
585        (LineNumber < Gbl_NextError->LogicalLineNumber ))
586    {
587        return;
588    }
589
590    /* Handle multiple errors per line */
591
592    if (FileId == ASL_FILE_LISTING_OUTPUT)
593    {
594        while (Gbl_NextError &&
595              (LineNumber >= Gbl_NextError->LogicalLineNumber))
596        {
597            AePrintException (FileId, Gbl_NextError, "\n[****iasl****]\n");
598
599            Gbl_NextError = Gbl_NextError->Next;
600        }
601
602        FlPrintFile (FileId, "\n");
603    }
604}
605
606
607/*******************************************************************************
608 *
609 * FUNCTION:    LsFlushListingBuffer
610 *
611 * PARAMETERS:  FileId          - ID of the listing file
612 *
613 * RETURN:      None
614 *
615 * DESCRIPTION: Flush out the current contents of the 16-byte hex AML code
616 *              buffer.  Usually called at the termination of a single line
617 *              of source code or when the buffer is full.
618 *
619 ******************************************************************************/
620
621static void
622LsFlushListingBuffer (
623    UINT32                  FileId)
624{
625    UINT32                  i;
626
627
628    if (Gbl_CurrentHexColumn == 0)
629    {
630        return;
631    }
632
633    /* Write the hex bytes */
634
635    switch (FileId)
636    {
637    case ASL_FILE_LISTING_OUTPUT:
638
639        for (i = 0; i < Gbl_CurrentHexColumn; i++)
640        {
641            FlPrintFile (FileId, "%2.2X ", Gbl_AmlBuffer[i]);
642        }
643
644        for (i = 0; i < ((HEX_LISTING_LINE_SIZE - Gbl_CurrentHexColumn) * 3); i++)
645        {
646            FlWriteFile (FileId, ".", 1);
647        }
648
649        /* Write the ASCII character associated with each of the bytes */
650
651        LsDumpAscii (FileId, Gbl_CurrentHexColumn, Gbl_AmlBuffer);
652        break;
653
654
655    case ASL_FILE_ASM_SOURCE_OUTPUT:
656
657        for (i = 0; i < Gbl_CurrentHexColumn; i++)
658        {
659            if (i > 0)
660            {
661                FlPrintFile (FileId, ",");
662            }
663            FlPrintFile (FileId, "0%2.2Xh", Gbl_AmlBuffer[i]);
664        }
665
666        for (i = 0; i < ((HEX_LISTING_LINE_SIZE - Gbl_CurrentHexColumn) * 5); i++)
667        {
668            FlWriteFile (FileId, " ", 1);
669        }
670
671        FlPrintFile (FileId, "  ;%8.8X",
672            Gbl_CurrentAmlOffset - HEX_LISTING_LINE_SIZE);
673
674        /* Write the ASCII character associated with each of the bytes */
675
676        LsDumpAscii (FileId, Gbl_CurrentHexColumn, Gbl_AmlBuffer);
677        break;
678
679
680    case ASL_FILE_C_SOURCE_OUTPUT:
681
682        for (i = 0; i < Gbl_CurrentHexColumn; i++)
683        {
684            FlPrintFile (FileId, "0x%2.2X,", Gbl_AmlBuffer[i]);
685        }
686
687        for (i = 0; i < ((HEX_LISTING_LINE_SIZE - Gbl_CurrentHexColumn) * 5); i++)
688        {
689            FlWriteFile (FileId, " ", 1);
690        }
691
692        FlPrintFile (FileId, "    /* %8.8X",
693            Gbl_CurrentAmlOffset - HEX_LISTING_LINE_SIZE);
694
695        /* Write the ASCII character associated with each of the bytes */
696
697        LsDumpAsciiInComment (FileId, Gbl_CurrentHexColumn, Gbl_AmlBuffer);
698        FlPrintFile (FileId, " */");
699        break;
700
701    default:
702        /* No other types supported */
703        return;
704    }
705
706    FlPrintFile (FileId, "\n");
707
708    Gbl_CurrentHexColumn = 0;
709    Gbl_HexBytesWereWritten = TRUE;
710}
711
712
713/*******************************************************************************
714 *
715 * FUNCTION:    LsWriteListingHexBytes
716 *
717 * PARAMETERS:  Buffer          - AML code buffer
718 *              Length          - Number of AML bytes to write
719 *              FileId          - ID of current listing file.
720 *
721 * RETURN:      None
722 *
723 * DESCRIPTION: Write the contents of the AML buffer to the listing file via
724 *              the listing buffer.  The listing buffer is flushed every 16
725 *              AML bytes.
726 *
727 ******************************************************************************/
728
729static void
730LsWriteListingHexBytes (
731    UINT8                   *Buffer,
732    UINT32                  Length,
733    UINT32                  FileId)
734{
735    UINT32                  i;
736
737
738    /* Transfer all requested bytes */
739
740    for (i = 0; i < Length; i++)
741    {
742        /* Print line header when buffer is empty */
743
744        if (Gbl_CurrentHexColumn == 0)
745        {
746            if (Gbl_HasIncludeFiles)
747            {
748                FlPrintFile (FileId, "%*s", 10, " ");
749            }
750
751            switch (FileId)
752            {
753            case ASL_FILE_LISTING_OUTPUT:
754
755                FlPrintFile (FileId, "%8.8X....", Gbl_CurrentAmlOffset);
756                break;
757
758            case ASL_FILE_ASM_SOURCE_OUTPUT:
759
760                FlPrintFile (FileId, "    db ");
761                break;
762
763            case ASL_FILE_C_SOURCE_OUTPUT:
764
765                FlPrintFile (FileId, "        ");
766                break;
767
768            default:
769                /* No other types supported */
770                return;
771            }
772        }
773
774        /* Transfer AML byte and update counts */
775
776        Gbl_AmlBuffer[Gbl_CurrentHexColumn] = Buffer[i];
777
778        Gbl_CurrentHexColumn++;
779        Gbl_CurrentAmlOffset++;
780
781        /* Flush buffer when it is full */
782
783        if (Gbl_CurrentHexColumn >= HEX_LISTING_LINE_SIZE)
784        {
785            LsFlushListingBuffer (FileId);
786        }
787    }
788}
789
790
791/*******************************************************************************
792 *
793 * FUNCTION:    LsWriteOneSourceLine
794 *
795 * PARAMETERS:  FileID          - ID of current listing file
796 *
797 * RETURN:      FALSE on EOF (input source file), TRUE otherwise
798 *
799 * DESCRIPTION: Read one line from the input source file and echo it to the
800 *              listing file, prefixed with the line number, and if the source
801 *              file contains include files, prefixed with the current filename
802 *
803 ******************************************************************************/
804
805static UINT32
806LsWriteOneSourceLine (
807    UINT32                  FileId)
808{
809    UINT8                   FileByte;
810
811
812    Gbl_SourceLine++;
813    Gbl_ListingNode->LineNumber++;
814
815    if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
816    {
817        FlPrintFile (FileId, "     *");
818    }
819    if (FileId == ASL_FILE_ASM_SOURCE_OUTPUT)
820    {
821        FlPrintFile (FileId, "; ");
822    }
823
824    if (Gbl_HasIncludeFiles)
825    {
826        /*
827         * This file contains "include" statements, print the current
828         * filename and line number within the current file
829         */
830        FlPrintFile (FileId, "%12s %5d....",
831                    Gbl_ListingNode->Filename, Gbl_ListingNode->LineNumber);
832    }
833    else
834    {
835        /* No include files, just print the line number */
836
837        FlPrintFile (FileId, "%8d....", Gbl_SourceLine);
838    }
839
840    /* Read one line (up to a newline or EOF) */
841
842    while (FlReadFile (ASL_FILE_SOURCE_OUTPUT, &FileByte, 1) == AE_OK)
843    {
844        if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
845        {
846            if (FileByte == '/')
847            {
848                FileByte = '*';
849            }
850        }
851
852        FlWriteFile (FileId, &FileByte, 1);
853        if (FileByte == '\n')
854        {
855            /*
856             * Check if an error occurred on this source line during the compile.
857             * If so, we print the error message after the source line.
858             */
859            LsCheckException (Gbl_SourceLine, FileId);
860            return (1);
861        }
862    }
863
864    /* EOF on the input file was reached */
865
866    return (0);
867}
868
869
870/*******************************************************************************
871 *
872 * FUNCTION:    LsFinishSourceListing
873 *
874 * PARAMETERS:  FileId          - ID of current listing file.
875 *
876 * RETURN:      None
877 *
878 * DESCRIPTION: Cleanup routine for the listing file.  Flush the hex AML
879 *              listing buffer, and flush out any remaining lines in the
880 *              source input file.
881 *
882 ******************************************************************************/
883
884static void
885LsFinishSourceListing (
886    UINT32                  FileId)
887{
888
889    if ((FileId == ASL_FILE_ASM_INCLUDE_OUTPUT) ||
890        (FileId == ASL_FILE_C_INCLUDE_OUTPUT))
891    {
892        return;
893    }
894
895    LsFlushListingBuffer (FileId);
896    Gbl_CurrentAmlOffset = 0;
897
898    /* Flush any remaining text in the source file */
899
900    if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
901    {
902        FlPrintFile (FileId, "    /*\n");
903    }
904
905    while (LsWriteOneSourceLine (FileId))
906    { ; }
907
908    if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
909    {
910        FlPrintFile (FileId, "\n     */\n    };\n");
911    }
912
913    FlPrintFile (FileId, "\n");
914
915    if (FileId == ASL_FILE_LISTING_OUTPUT)
916    {
917        /* Print a summary of the compile exceptions */
918
919        FlPrintFile (FileId, "\n\nSummary of errors and warnings\n\n");
920        AePrintErrorLog (FileId);
921        FlPrintFile (FileId, "\n\n");
922        UtDisplaySummary (FileId);
923        FlPrintFile (FileId, "\n\n");
924    }
925}
926
927
928/*******************************************************************************
929 *
930 * FUNCTION:    LsWriteSourceLines
931 *
932 * PARAMETERS:  ToLineNumber            -
933 *              ToLogicalLineNumber     - Write up to this source line number
934 *              FileId                  - ID of current listing file
935 *
936 * RETURN:      None
937 *
938 * DESCRIPTION: Read then write source lines to the listing file until we have
939 *              reached the specified logical (cumulative) line number.  This
940 *              automatically echos out comment blocks and other non-AML
941 *              generating text until we get to the actual AML-generating line
942 *              of ASL code specified by the logical line number.
943 *
944 ******************************************************************************/
945
946static void
947LsWriteSourceLines (
948    UINT32                  ToLineNumber,
949    UINT32                  ToLogicalLineNumber,
950    UINT32                  FileId)
951{
952
953    if ((FileId == ASL_FILE_ASM_INCLUDE_OUTPUT) ||
954        (FileId == ASL_FILE_C_INCLUDE_OUTPUT))
955    {
956        return;
957    }
958
959    Gbl_CurrentLine = ToLogicalLineNumber;
960
961    /* Flush any hex bytes remaining from the last opcode */
962
963    LsFlushListingBuffer (FileId);
964
965    /* Read lines and write them as long as we are not caught up */
966
967    if (Gbl_SourceLine < Gbl_CurrentLine)
968    {
969        /*
970         * If we just completed writing some AML hex bytes, output a linefeed
971         * to add some whitespace for readability.
972         */
973        if (Gbl_HexBytesWereWritten)
974        {
975            FlPrintFile (FileId, "\n");
976            Gbl_HexBytesWereWritten = FALSE;
977        }
978
979        if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
980        {
981            FlPrintFile (FileId, "    /*\n");
982        }
983
984        /* Write one line at a time until we have reached the target line # */
985
986        while ((Gbl_SourceLine < Gbl_CurrentLine) &&
987                LsWriteOneSourceLine (FileId))
988        { ; }
989
990        if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
991        {
992            FlPrintFile (FileId, "     */");
993        }
994        FlPrintFile (FileId, "\n");
995    }
996}
997
998
999/*******************************************************************************
1000 *
1001 * FUNCTION:    LsWriteNodeToListing
1002 *
1003 * PARAMETERS:  Op            - Parse node to write to the listing file.
1004 *              FileId          - ID of current listing file
1005 *
1006 * RETURN:      None.
1007 *
1008 * DESCRIPTION: Write "a node" to the listing file.  This means to
1009 *              1) Write out all of the source text associated with the node
1010 *              2) Write out all of the AML bytes associated with the node
1011 *              3) Write any compiler exceptions associated with the node
1012 *
1013 ******************************************************************************/
1014
1015static void
1016LsWriteNodeToListing (
1017    ACPI_PARSE_OBJECT       *Op,
1018    UINT32                  FileId)
1019{
1020    const ACPI_OPCODE_INFO  *OpInfo;
1021    UINT32                  OpClass;
1022    char                    *Pathname;
1023    UINT32                  Length;
1024    UINT32                  i;
1025
1026
1027    OpInfo  = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
1028    OpClass = OpInfo->Class;
1029
1030    /* TBD: clean this up with a single flag that says:
1031     * I start a named output block
1032     */
1033    if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
1034    {
1035        switch (Op->Asl.ParseOpcode)
1036        {
1037        case PARSEOP_DEFINITIONBLOCK:
1038        case PARSEOP_METHODCALL:
1039        case PARSEOP_INCLUDE:
1040        case PARSEOP_INCLUDE_END:
1041        case PARSEOP_DEFAULT_ARG:
1042
1043            break;
1044
1045        default:
1046            switch (OpClass)
1047            {
1048            case AML_CLASS_NAMED_OBJECT:
1049                switch (Op->Asl.AmlOpcode)
1050                {
1051                case AML_SCOPE_OP:
1052                case AML_ALIAS_OP:
1053                    break;
1054
1055                default:
1056                    if (Op->Asl.ExternalName)
1057                    {
1058                        LsFlushListingBuffer (FileId);
1059                        FlPrintFile (FileId, "    };\n");
1060                    }
1061                    break;
1062                }
1063                break;
1064
1065            default:
1066                /* Don't care about other objects */
1067                break;
1068            }
1069            break;
1070        }
1071    }
1072
1073    /* These cases do not have a corresponding AML opcode */
1074
1075    switch (Op->Asl.ParseOpcode)
1076    {
1077    case PARSEOP_DEFINITIONBLOCK:
1078
1079        LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine, FileId);
1080
1081        /* Use the table Signature and TableId to build a unique name */
1082
1083        if (FileId == ASL_FILE_ASM_SOURCE_OUTPUT)
1084        {
1085            FlPrintFile (FileId,
1086                "%s_%s_Header \\\n",
1087                Gbl_TableSignature, Gbl_TableId);
1088        }
1089        if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
1090        {
1091            FlPrintFile (FileId,
1092                "    unsigned char    %s_%s_Header [] =\n    {\n",
1093                Gbl_TableSignature, Gbl_TableId);
1094        }
1095        if (FileId == ASL_FILE_ASM_INCLUDE_OUTPUT)
1096        {
1097            FlPrintFile (FileId,
1098                "extrn %s_%s_Header : byte\n",
1099                Gbl_TableSignature, Gbl_TableId);
1100        }
1101        if (FileId == ASL_FILE_C_INCLUDE_OUTPUT)
1102        {
1103            FlPrintFile (FileId,
1104                "extern unsigned char    %s_%s_Header [];\n",
1105                Gbl_TableSignature, Gbl_TableId);
1106        }
1107        return;
1108
1109
1110    case PARSEOP_METHODCALL:
1111
1112        LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
1113            FileId);
1114        return;
1115
1116
1117    case PARSEOP_INCLUDE:
1118
1119        /* Flush everything up to and including the include source line */
1120
1121        LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
1122            FileId);
1123
1124        /* Create a new listing node and push it */
1125
1126        LsPushNode (Op->Asl.Child->Asl.Value.String);
1127        return;
1128
1129
1130    case PARSEOP_INCLUDE_END:
1131
1132        /* Flush out the rest of the include file */
1133
1134        LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
1135            FileId);
1136
1137        /* Pop off this listing node and go back to the parent file */
1138
1139        (void) LsPopNode ();
1140        return;
1141
1142
1143    case PARSEOP_DEFAULT_ARG:
1144
1145        if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC)
1146        {
1147            LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.EndLogicalLine,
1148                FileId);
1149        }
1150        return;
1151
1152
1153    default:
1154        /* All other opcodes have an AML opcode */
1155        break;
1156    }
1157
1158    /*
1159     * Otherwise, we look at the AML opcode because we can
1160     * switch on the opcode type, getting an entire class
1161     * at once
1162     */
1163    switch (OpClass)
1164    {
1165    case AML_CLASS_ARGUMENT:       /* argument type only */
1166    case AML_CLASS_INTERNAL:
1167
1168        break;
1169
1170
1171    case AML_CLASS_NAMED_OBJECT:
1172
1173        switch (Op->Asl.AmlOpcode)
1174        {
1175        case AML_FIELD_OP:
1176        case AML_INDEX_FIELD_OP:
1177        case AML_BANK_FIELD_OP:
1178
1179            /*
1180             * For fields, we want to dump all the AML after the
1181             * entire definition
1182             */
1183            LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine,
1184                FileId);
1185            break;
1186
1187        case AML_NAME_OP:
1188
1189            if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC)
1190            {
1191                LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
1192                    FileId);
1193            }
1194            else
1195            {
1196                /*
1197                 * For fields, we want to dump all the AML after the
1198                 * entire definition
1199                 */
1200                LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine,
1201                    FileId);
1202            }
1203            break;
1204
1205        default:
1206            LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
1207                FileId);
1208            break;
1209        }
1210
1211        switch (Op->Asl.AmlOpcode)
1212        {
1213        case AML_SCOPE_OP:
1214        case AML_ALIAS_OP:
1215
1216            /* These opcodes do not declare a new object, ignore them */
1217
1218            break;
1219
1220        default:
1221
1222            /* All other named object opcodes come here */
1223
1224            switch (FileId)
1225            {
1226            case ASL_FILE_ASM_SOURCE_OUTPUT:
1227            case ASL_FILE_C_SOURCE_OUTPUT:
1228            case ASL_FILE_ASM_INCLUDE_OUTPUT:
1229            case ASL_FILE_C_INCLUDE_OUTPUT:
1230
1231                /*
1232                 * For named objects, we will create a valid symbol so that the
1233                 * AML code can be referenced from C or ASM
1234                 */
1235                if (Op->Asl.ExternalName)
1236                {
1237                    /* Get the full pathname associated with this node */
1238
1239                    Pathname = AcpiNsGetExternalPathname (Op->Asl.Node);
1240                    Length = strlen (Pathname);
1241                    if (Length >= 4)
1242                    {
1243                        /* Convert all dots in the path to underscores */
1244
1245                        for (i = 0; i < Length; i++)
1246                        {
1247                            if (Pathname[i] == '.')
1248                            {
1249                                Pathname[i] = '_';
1250                            }
1251                        }
1252
1253                        /* Create the appropriate symbol in the output file */
1254
1255                        if (FileId == ASL_FILE_ASM_SOURCE_OUTPUT)
1256                        {
1257                            FlPrintFile (FileId,
1258                                "%s_%s_%s  \\\n",
1259                                Gbl_TableSignature, Gbl_TableId, &Pathname[1]);
1260                        }
1261                        if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
1262                        {
1263                            FlPrintFile (FileId,
1264                                "    unsigned char    %s_%s_%s [] =\n    {\n",
1265                                Gbl_TableSignature, Gbl_TableId, &Pathname[1]);
1266                        }
1267                        if (FileId == ASL_FILE_ASM_INCLUDE_OUTPUT)
1268                        {
1269                            FlPrintFile (FileId,
1270                                "extrn %s_%s_%s : byte\n",
1271                                Gbl_TableSignature, Gbl_TableId, &Pathname[1]);
1272                        }
1273                        if (FileId == ASL_FILE_C_INCLUDE_OUTPUT)
1274                        {
1275                            FlPrintFile (FileId,
1276                                "extern unsigned char    %s_%s_%s [];\n",
1277                                Gbl_TableSignature, Gbl_TableId, &Pathname[1]);
1278                        }
1279                    }
1280                    ACPI_FREE (Pathname);
1281                }
1282                break;
1283
1284            default:
1285                /* Nothing to do for listing file */
1286                break;
1287            }
1288        }
1289        break;
1290
1291    case AML_CLASS_EXECUTE:
1292    case AML_CLASS_CREATE:
1293    default:
1294
1295        if ((Op->Asl.ParseOpcode == PARSEOP_BUFFER) &&
1296            (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC))
1297        {
1298            return;
1299        }
1300
1301        LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
1302            FileId);
1303        break;
1304
1305    case AML_CLASS_UNKNOWN:
1306        break;
1307    }
1308}
1309
1310
1311/*******************************************************************************
1312 *
1313 * FUNCTION:    LsDoHexOutput
1314 *
1315 * PARAMETERS:  None
1316 *
1317 * RETURN:      None.
1318 *
1319 * DESCRIPTION: Create the hex output file.
1320 *
1321 ******************************************************************************/
1322
1323void
1324LsDoHexOutput (
1325    void)
1326{
1327
1328    switch (Gbl_HexOutputFlag)
1329    {
1330    case HEX_OUTPUT_C:
1331
1332        LsDoHexOutputC ();
1333        break;
1334
1335    case HEX_OUTPUT_ASM:
1336
1337        LsDoHexOutputAsm ();
1338        break;
1339
1340    default:
1341        /* No other output types supported */
1342        break;
1343    }
1344}
1345
1346
1347/*******************************************************************************
1348 *
1349 * FUNCTION:    LsDoHexOutputC
1350 *
1351 * PARAMETERS:  None
1352 *
1353 * RETURN:      None.
1354 *
1355 * DESCRIPTION: Create the hex output file.  This is the same data as the AML
1356 *              output file, but formatted into hex/ascii bytes suitable for
1357 *              inclusion into a C source file.
1358 *
1359 ******************************************************************************/
1360
1361static void
1362LsDoHexOutputC (
1363    void)
1364{
1365    UINT32                  j;
1366    UINT8                   FileByte[HEX_TABLE_LINE_SIZE];
1367    UINT8                   Buffer[4];
1368    UINT32                  Offset = 0;
1369
1370
1371    FlPrintFile (ASL_FILE_HEX_OUTPUT, " * C source code output\n *\n */\n");
1372    FlPrintFile (ASL_FILE_HEX_OUTPUT, "unsigned char AmlCode[] =\n{\n");
1373
1374    /* Start at the beginning of the AML file */
1375
1376    FlSeekFile (ASL_FILE_AML_OUTPUT, 0);
1377
1378    /* Process all AML bytes in the AML file */
1379
1380    j = 0;
1381    while (FlReadFile (ASL_FILE_AML_OUTPUT, &FileByte[j], 1) == AE_OK)
1382    {
1383        if (j == 0)
1384        {
1385            FlPrintFile (ASL_FILE_HEX_OUTPUT, "    ");
1386        }
1387
1388        /* Convert each AML byte to hex */
1389
1390        UtConvertByteToHex (FileByte[j], Buffer);
1391        FlWriteFile (ASL_FILE_HEX_OUTPUT, Buffer, 4);
1392        FlPrintFile (ASL_FILE_HEX_OUTPUT, ",");
1393
1394        /* An occasional linefeed improves readability */
1395
1396        Offset++;
1397        j++;
1398
1399        if (j >= HEX_TABLE_LINE_SIZE)
1400        {
1401            /* End of line, emit the ascii dump of the entire line */
1402
1403            FlPrintFile (ASL_FILE_HEX_OUTPUT,
1404                "  /* %8.8X", Offset - HEX_TABLE_LINE_SIZE);
1405
1406            /* Write the ASCII character associated with each of the bytes */
1407
1408            LsDumpAsciiInComment (ASL_FILE_HEX_OUTPUT,
1409                HEX_TABLE_LINE_SIZE, FileByte);
1410            FlPrintFile (ASL_FILE_HEX_OUTPUT, " */\n");
1411
1412            /* Start new line */
1413
1414            j = 0;
1415        }
1416    }
1417
1418    FlPrintFile (ASL_FILE_HEX_OUTPUT, "\n};\n");
1419    FlCloseFile (ASL_FILE_HEX_OUTPUT);
1420}
1421
1422
1423/*******************************************************************************
1424 *
1425 * FUNCTION:    LsDoHexOutputAsm
1426 *
1427 * PARAMETERS:  None
1428 *
1429 * RETURN:      None.
1430 *
1431 * DESCRIPTION: Create the hex output file.  This is the same data as the AML
1432 *              output file, but formatted into hex/ascii bytes suitable for
1433 *              inclusion into a ASM source file.
1434 *
1435 ******************************************************************************/
1436
1437static void
1438LsDoHexOutputAsm (
1439    void)
1440{
1441    UINT32                  j;
1442    UINT8                   FileByte[HEX_TABLE_LINE_SIZE];
1443    UINT8                   Buffer[4];
1444    UINT32                  Offset = 0;
1445    BOOLEAN                 DoComma = FALSE;
1446
1447
1448    FlPrintFile (ASL_FILE_HEX_OUTPUT, "; Assembly code source output\n;\n");
1449
1450    /* Start at the beginning of the AML file */
1451
1452    FlSeekFile (ASL_FILE_AML_OUTPUT, 0);
1453
1454    /* Process all AML bytes in the AML file */
1455
1456    j = 0;
1457    while (FlReadFile (ASL_FILE_AML_OUTPUT, &FileByte[j], 1) == AE_OK)
1458    {
1459        if (j == 0)
1460        {
1461            FlPrintFile (ASL_FILE_HEX_OUTPUT, "  db  ");
1462        }
1463        else if (DoComma)
1464        {
1465            FlPrintFile (ASL_FILE_HEX_OUTPUT, ",");
1466            DoComma = FALSE;
1467        }
1468
1469        /* Convert each AML byte to hex */
1470
1471        UtConvertByteToAsmHex (FileByte[j], Buffer);
1472        FlWriteFile (ASL_FILE_HEX_OUTPUT, Buffer, 4);
1473
1474        /* An occasional linefeed improves readability */
1475
1476        Offset++;
1477        j++;
1478        if (j >= HEX_TABLE_LINE_SIZE)
1479        {
1480            FlPrintFile (ASL_FILE_HEX_OUTPUT,
1481                "  ;%8.8X", Offset - HEX_TABLE_LINE_SIZE);
1482
1483            /* Write the ASCII character associated with each of the bytes */
1484
1485            LsDumpAscii (ASL_FILE_HEX_OUTPUT, HEX_TABLE_LINE_SIZE, FileByte);
1486            FlPrintFile (ASL_FILE_HEX_OUTPUT, "\n");
1487            j = 0;
1488        }
1489        else
1490        {
1491            DoComma = TRUE;
1492        }
1493    }
1494
1495    FlPrintFile (ASL_FILE_HEX_OUTPUT, "\n");
1496    FlCloseFile (ASL_FILE_HEX_OUTPUT);
1497}
1498
1499
1500