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