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