xref: /freebsd/sys/contrib/dev/acpica/compiler/asllisting.c (revision 11c5cac53f6cc9a2d94cb6f58728b2655e92d3a5)
1 /******************************************************************************
2  *
3  * Module Name: asllisting - Listing file generation
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2013, 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 ACPI_STATUS
63 LsAmlListingWalk (
64     ACPI_PARSE_OBJECT       *Op,
65     UINT32                  Level,
66     void                    *Context);
67 
68 static void
69 LsGenerateListing (
70     UINT32                  FileId);
71 
72 static void
73 LsPushNode (
74     char                    *Filename);
75 
76 static ASL_LISTING_NODE *
77 LsPopNode (
78     void);
79 
80 static void
81 LsCheckException (
82     UINT32                  LineNumber,
83     UINT32                  FileId);
84 
85 static void
86 LsFlushListingBuffer (
87     UINT32                  FileId);
88 
89 static void
90 LsWriteListingHexBytes (
91     UINT8                   *Buffer,
92     UINT32                  Length,
93     UINT32                  FileId);
94 
95 static UINT32
96 LsWriteOneSourceLine (
97     UINT32                  FileId);
98 
99 static void
100 LsFinishSourceListing (
101     UINT32                  FileId);
102 
103 static void
104 LsWriteSourceLines (
105     UINT32                  ToLineNumber,
106     UINT32                  ToLogicalLineNumber,
107     UINT32                  FileId);
108 
109 static void
110 LsWriteNodeToListing (
111     ACPI_PARSE_OBJECT       *Op,
112     UINT32                  FileId);
113 
114 static ACPI_STATUS
115 LsTreeWriteWalk (
116     ACPI_PARSE_OBJECT       *Op,
117     UINT32                  Level,
118     void                    *Context);
119 
120 #define ASL_LISTING_LINE_PREFIX         ":  "
121 
122 
123 /*******************************************************************************
124  *
125  * FUNCTION:    LsDoListings
126  *
127  * PARAMETERS:  None
128  *
129  * RETURN:      None
130  *
131  * DESCRIPTION: Generate all requested listing files.
132  *
133  ******************************************************************************/
134 
135 void
136 LsDoListings (
137     void)
138 {
139 
140     if (Gbl_C_OutputFlag)
141     {
142         LsGenerateListing (ASL_FILE_C_SOURCE_OUTPUT);
143     }
144 
145     if (Gbl_ListingFlag)
146     {
147         LsGenerateListing (ASL_FILE_LISTING_OUTPUT);
148     }
149 
150     if (Gbl_AsmOutputFlag)
151     {
152         LsGenerateListing (ASL_FILE_ASM_SOURCE_OUTPUT);
153     }
154 
155     if (Gbl_C_IncludeOutputFlag)
156     {
157         LsGenerateListing (ASL_FILE_C_INCLUDE_OUTPUT);
158     }
159 
160     if (Gbl_AsmIncludeOutputFlag)
161     {
162         LsGenerateListing (ASL_FILE_ASM_INCLUDE_OUTPUT);
163     }
164 }
165 
166 
167 /*******************************************************************************
168  *
169  * FUNCTION:    LsTreeWriteWalk
170  *
171  * PARAMETERS:  ASL_WALK_CALLBACK
172  *
173  *
174  * RETURN:      None
175  *
176  * DESCRIPTION: Dump entire parse tree, for compiler debug only
177  *
178  ******************************************************************************/
179 
180 static ACPI_STATUS
181 LsTreeWriteWalk (
182     ACPI_PARSE_OBJECT       *Op,
183     UINT32                  Level,
184     void                    *Context)
185 {
186 
187     /* Debug output */
188 
189     DbgPrint (ASL_TREE_OUTPUT,
190         "%5.5d [%2d]", Op->Asl.LogicalLineNumber, Level);
191     UtPrintFormattedName (Op->Asl.ParseOpcode, Level);
192 
193 
194     DbgPrint (ASL_TREE_OUTPUT, "\n");
195     return (AE_OK);
196 }
197 
198 
199 void
200 LsDumpParseTree (
201     void)
202 {
203 
204     if (!Gbl_DebugFlag)
205     {
206         return;
207     }
208 
209     DbgPrint (ASL_TREE_OUTPUT, "\nOriginal parse tree from parser:\n\n");
210     TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD,
211         LsTreeWriteWalk, NULL, NULL);
212 }
213 
214 
215 /*******************************************************************************
216  *
217  * FUNCTION:    LsDumpAscii
218  *
219  * PARAMETERS:  FileId          - ID of current listing file
220  *              Count           - Number of bytes to convert
221  *              Buffer          - Buffer of bytes to convert
222  *
223  * RETURN:      None
224  *
225  * DESCRIPTION: Convert hex bytes to ascii
226  *
227  ******************************************************************************/
228 
229 static void
230 LsDumpAscii (
231     UINT32                  FileId,
232     UINT32                  Count,
233     UINT8                   *Buffer)
234 {
235     UINT8                   BufChar;
236     UINT32                  i;
237 
238 
239     FlPrintFile (FileId, "    \"");
240     for (i = 0; i < Count; i++)
241     {
242         BufChar = Buffer[i];
243         if (isprint (BufChar))
244         {
245             FlPrintFile (FileId, "%c", BufChar);
246         }
247         else
248         {
249             /* Not a printable character, just put out a dot */
250 
251             FlPrintFile (FileId, ".");
252         }
253     }
254     FlPrintFile (FileId, "\"");
255 }
256 
257 
258 /*******************************************************************************
259  *
260  * FUNCTION:    LsDumpAsciiInComment
261  *
262  * PARAMETERS:  FileId          - ID of current listing file
263  *              Count           - Number of bytes to convert
264  *              Buffer          - Buffer of bytes to convert
265  *
266  * RETURN:      None
267  *
268  * DESCRIPTION: Convert hex bytes to ascii
269  *
270  ******************************************************************************/
271 
272 void
273 LsDumpAsciiInComment (
274     UINT32                  FileId,
275     UINT32                  Count,
276     UINT8                   *Buffer)
277 {
278     UINT8                   BufChar = 0;
279     UINT8                   LastChar;
280     UINT32                  i;
281 
282 
283     FlPrintFile (FileId, "    \"");
284     for (i = 0; i < Count; i++)
285     {
286         LastChar = BufChar;
287         BufChar = Buffer[i];
288 
289         if (isprint (BufChar))
290         {
291             /* Handle embedded C comment sequences */
292 
293             if (((LastChar == '*') && (BufChar == '/')) ||
294                 ((LastChar == '/') && (BufChar == '*')))
295             {
296                 /* Insert a space to break the sequence */
297 
298                 FlPrintFile (FileId, ".", BufChar);
299             }
300 
301             FlPrintFile (FileId, "%c", BufChar);
302         }
303         else
304         {
305             /* Not a printable character, just put out a dot */
306 
307             FlPrintFile (FileId, ".");
308         }
309     }
310     FlPrintFile (FileId, "\"");
311 }
312 
313 
314 /*******************************************************************************
315  *
316  * FUNCTION:    LsAmlListingWalk
317  *
318  * PARAMETERS:  ASL_WALK_CALLBACK
319  *
320  * RETURN:      Status
321  *
322  * DESCRIPTION: Process one node during a listing file generation.
323  *
324  ******************************************************************************/
325 
326 static ACPI_STATUS
327 LsAmlListingWalk (
328     ACPI_PARSE_OBJECT       *Op,
329     UINT32                  Level,
330     void                    *Context)
331 {
332     UINT8                   FileByte;
333     UINT32                  i;
334     UINT32                  FileId = (UINT32) ACPI_TO_INTEGER (Context);
335 
336 
337     LsWriteNodeToListing (Op, FileId);
338 
339     if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DATA)
340     {
341         /* Buffer is a resource template, don't dump the data all at once */
342 
343         return (AE_OK);
344     }
345 
346     /* Write the hex bytes to the listing file(s) (if requested) */
347 
348     for (i = 0; i < Op->Asl.FinalAmlLength; i++)
349     {
350         if (ACPI_FAILURE (FlReadFile (ASL_FILE_AML_OUTPUT, &FileByte, 1)))
351         {
352             FlFileError (ASL_FILE_AML_OUTPUT, ASL_MSG_READ);
353             AslAbort ();
354         }
355         LsWriteListingHexBytes (&FileByte, 1, FileId);
356     }
357 
358     return (AE_OK);
359 }
360 
361 
362 /*******************************************************************************
363  *
364  * FUNCTION:    LsGenerateListing
365  *
366  * PARAMETERS:  FileId      - ID of listing file
367  *
368  * RETURN:      None
369  *
370  * DESCRIPTION: Generate a listing file. This can be one of the several types
371  *              of "listings" supported.
372  *
373  ******************************************************************************/
374 
375 static void
376 LsGenerateListing (
377     UINT32                  FileId)
378 {
379 
380     /* Start at the beginning of both the source and AML files */
381 
382     FlSeekFile (ASL_FILE_SOURCE_OUTPUT, 0);
383     FlSeekFile (ASL_FILE_AML_OUTPUT, 0);
384     Gbl_SourceLine = 0;
385     Gbl_CurrentHexColumn = 0;
386     LsPushNode (Gbl_Files[ASL_FILE_INPUT].Filename);
387 
388     /* Process all parse nodes */
389 
390     TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD, LsAmlListingWalk,
391                         NULL, (void *) ACPI_TO_POINTER (FileId));
392 
393     /* Final processing */
394 
395     LsFinishSourceListing (FileId);
396 }
397 
398 
399 /*******************************************************************************
400  *
401  * FUNCTION:    LsPushNode
402  *
403  * PARAMETERS:  Filename        - Pointer to the include filename
404  *
405  * RETURN:      None
406  *
407  * DESCRIPTION: Push a listing node on the listing/include file stack. This
408  *              stack enables tracking of include files (infinitely nested)
409  *              and resumption of the listing of the parent file when the
410  *              include file is finished.
411  *
412  ******************************************************************************/
413 
414 static void
415 LsPushNode (
416     char                    *Filename)
417 {
418     ASL_LISTING_NODE        *Lnode;
419 
420 
421     /* Create a new node */
422 
423     Lnode = UtLocalCalloc (sizeof (ASL_LISTING_NODE));
424 
425     /* Initialize */
426 
427     Lnode->Filename = Filename;
428     Lnode->LineNumber = 0;
429 
430     /* Link (push) */
431 
432     Lnode->Next = Gbl_ListingNode;
433     Gbl_ListingNode = Lnode;
434 }
435 
436 
437 /*******************************************************************************
438  *
439  * FUNCTION:    LsPopNode
440  *
441  * PARAMETERS:  None
442  *
443  * RETURN:      List head after current head is popped off
444  *
445  * DESCRIPTION: Pop the current head of the list, free it, and return the
446  *              next node on the stack (the new current node).
447  *
448  ******************************************************************************/
449 
450 static ASL_LISTING_NODE *
451 LsPopNode (
452     void)
453 {
454     ASL_LISTING_NODE        *Lnode;
455 
456 
457     /* Just grab the node at the head of the list */
458 
459     Lnode = Gbl_ListingNode;
460     if ((!Lnode) ||
461         (!Lnode->Next))
462     {
463         AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, NULL,
464             "Could not pop empty listing stack");
465         return (Gbl_ListingNode);
466     }
467 
468     Gbl_ListingNode = Lnode->Next;
469     ACPI_FREE (Lnode);
470 
471     /* New "Current" node is the new head */
472 
473     return (Gbl_ListingNode);
474 }
475 
476 
477 /*******************************************************************************
478  *
479  * FUNCTION:    LsCheckException
480  *
481  * PARAMETERS:  LineNumber          - Current logical (cumulative) line #
482  *              FileId              - ID of output listing file
483  *
484  * RETURN:      None
485  *
486  * DESCRIPTION: Check if there is an exception for this line, and if there is,
487  *              put it in the listing immediately. Handles multiple errors
488  *              per line. Gbl_NextError points to the next error in the
489  *              sorted (by line #) list of compile errors/warnings.
490  *
491  ******************************************************************************/
492 
493 static void
494 LsCheckException (
495     UINT32                  LineNumber,
496     UINT32                  FileId)
497 {
498 
499     if ((!Gbl_NextError) ||
500         (LineNumber < Gbl_NextError->LogicalLineNumber ))
501     {
502         return;
503     }
504 
505     /* Handle multiple errors per line */
506 
507     if (FileId == ASL_FILE_LISTING_OUTPUT)
508     {
509         while (Gbl_NextError &&
510               (LineNumber >= Gbl_NextError->LogicalLineNumber))
511         {
512             AePrintException (FileId, Gbl_NextError, "\n[****iasl****]\n");
513 
514             Gbl_NextError = Gbl_NextError->Next;
515         }
516 
517         FlPrintFile (FileId, "\n");
518     }
519 }
520 
521 
522 /*******************************************************************************
523  *
524  * FUNCTION:    LsFlushListingBuffer
525  *
526  * PARAMETERS:  FileId          - ID of the listing file
527  *
528  * RETURN:      None
529  *
530  * DESCRIPTION: Flush out the current contents of the 16-byte hex AML code
531  *              buffer. Usually called at the termination of a single line
532  *              of source code or when the buffer is full.
533  *
534  ******************************************************************************/
535 
536 static void
537 LsFlushListingBuffer (
538     UINT32                  FileId)
539 {
540     UINT32                  i;
541 
542 
543     if (Gbl_CurrentHexColumn == 0)
544     {
545         return;
546     }
547 
548     /* Write the hex bytes */
549 
550     switch (FileId)
551     {
552     case ASL_FILE_LISTING_OUTPUT:
553 
554         for (i = 0; i < Gbl_CurrentHexColumn; i++)
555         {
556             FlPrintFile (FileId, "%2.2X ", Gbl_AmlBuffer[i]);
557         }
558 
559         for (i = 0; i < ((HEX_LISTING_LINE_SIZE - Gbl_CurrentHexColumn) * 3); i++)
560         {
561             FlWriteFile (FileId, ".", 1);
562         }
563 
564         /* Write the ASCII character associated with each of the bytes */
565 
566         LsDumpAscii (FileId, Gbl_CurrentHexColumn, Gbl_AmlBuffer);
567         break;
568 
569 
570     case ASL_FILE_ASM_SOURCE_OUTPUT:
571 
572         for (i = 0; i < Gbl_CurrentHexColumn; i++)
573         {
574             if (i > 0)
575             {
576                 FlPrintFile (FileId, ",");
577             }
578             FlPrintFile (FileId, "0%2.2Xh", Gbl_AmlBuffer[i]);
579         }
580 
581         for (i = 0; i < ((HEX_LISTING_LINE_SIZE - Gbl_CurrentHexColumn) * 5); i++)
582         {
583             FlWriteFile (FileId, " ", 1);
584         }
585 
586         FlPrintFile (FileId, "  ;%8.8X",
587             Gbl_CurrentAmlOffset - HEX_LISTING_LINE_SIZE);
588 
589         /* Write the ASCII character associated with each of the bytes */
590 
591         LsDumpAscii (FileId, Gbl_CurrentHexColumn, Gbl_AmlBuffer);
592         break;
593 
594 
595     case ASL_FILE_C_SOURCE_OUTPUT:
596 
597         for (i = 0; i < Gbl_CurrentHexColumn; i++)
598         {
599             FlPrintFile (FileId, "0x%2.2X,", Gbl_AmlBuffer[i]);
600         }
601 
602         for (i = 0; i < ((HEX_LISTING_LINE_SIZE - Gbl_CurrentHexColumn) * 5); i++)
603         {
604             FlWriteFile (FileId, " ", 1);
605         }
606 
607         FlPrintFile (FileId, "    /* %8.8X",
608             Gbl_CurrentAmlOffset - HEX_LISTING_LINE_SIZE);
609 
610         /* Write the ASCII character associated with each of the bytes */
611 
612         LsDumpAsciiInComment (FileId, Gbl_CurrentHexColumn, Gbl_AmlBuffer);
613         FlPrintFile (FileId, " */");
614         break;
615 
616     default:
617         /* No other types supported */
618         return;
619     }
620 
621     FlPrintFile (FileId, "\n");
622 
623     Gbl_CurrentHexColumn = 0;
624     Gbl_HexBytesWereWritten = TRUE;
625 }
626 
627 
628 /*******************************************************************************
629  *
630  * FUNCTION:    LsWriteListingHexBytes
631  *
632  * PARAMETERS:  Buffer          - AML code buffer
633  *              Length          - Number of AML bytes to write
634  *              FileId          - ID of current listing file.
635  *
636  * RETURN:      None
637  *
638  * DESCRIPTION: Write the contents of the AML buffer to the listing file via
639  *              the listing buffer. The listing buffer is flushed every 16
640  *              AML bytes.
641  *
642  ******************************************************************************/
643 
644 static void
645 LsWriteListingHexBytes (
646     UINT8                   *Buffer,
647     UINT32                  Length,
648     UINT32                  FileId)
649 {
650     UINT32                  i;
651 
652 
653     /* Transfer all requested bytes */
654 
655     for (i = 0; i < Length; i++)
656     {
657         /* Print line header when buffer is empty */
658 
659         if (Gbl_CurrentHexColumn == 0)
660         {
661             if (Gbl_HasIncludeFiles)
662             {
663                 FlPrintFile (FileId, "%*s", 10, " ");
664             }
665 
666             switch (FileId)
667             {
668             case ASL_FILE_LISTING_OUTPUT:
669 
670                 FlPrintFile (FileId, "%8.8X%s", Gbl_CurrentAmlOffset,
671                     ASL_LISTING_LINE_PREFIX);
672                 break;
673 
674             case ASL_FILE_ASM_SOURCE_OUTPUT:
675 
676                 FlPrintFile (FileId, "    db ");
677                 break;
678 
679             case ASL_FILE_C_SOURCE_OUTPUT:
680 
681                 FlPrintFile (FileId, "        ");
682                 break;
683 
684             default:
685                 /* No other types supported */
686                 return;
687             }
688         }
689 
690         /* Transfer AML byte and update counts */
691 
692         Gbl_AmlBuffer[Gbl_CurrentHexColumn] = Buffer[i];
693 
694         Gbl_CurrentHexColumn++;
695         Gbl_CurrentAmlOffset++;
696 
697         /* Flush buffer when it is full */
698 
699         if (Gbl_CurrentHexColumn >= HEX_LISTING_LINE_SIZE)
700         {
701             LsFlushListingBuffer (FileId);
702         }
703     }
704 }
705 
706 
707 /*******************************************************************************
708  *
709  * FUNCTION:    LsWriteOneSourceLine
710  *
711  * PARAMETERS:  FileID          - ID of current listing file
712  *
713  * RETURN:      FALSE on EOF (input source file), TRUE otherwise
714  *
715  * DESCRIPTION: Read one line from the input source file and echo it to the
716  *              listing file, prefixed with the line number, and if the source
717  *              file contains include files, prefixed with the current filename
718  *
719  ******************************************************************************/
720 
721 static UINT32
722 LsWriteOneSourceLine (
723     UINT32                  FileId)
724 {
725     UINT8                   FileByte;
726 
727 
728     Gbl_SourceLine++;
729     Gbl_ListingNode->LineNumber++;
730 
731     /* Ignore lines that are completely blank (but count the line above) */
732 
733     if (FlReadFile (ASL_FILE_SOURCE_OUTPUT, &FileByte, 1) != AE_OK)
734     {
735         return (0);
736     }
737     if (FileByte == '\n')
738     {
739         return (1);
740     }
741 
742     /*
743      * This is a non-empty line, we will print the entire line with
744      * the line number and possibly other prefixes and transforms.
745      */
746 
747     /* Line prefixes for special files, C and ASM output */
748 
749     if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
750     {
751         FlPrintFile (FileId, "     *");
752     }
753     if (FileId == ASL_FILE_ASM_SOURCE_OUTPUT)
754     {
755         FlPrintFile (FileId, "; ");
756     }
757 
758     if (Gbl_HasIncludeFiles)
759     {
760         /*
761          * This file contains "include" statements, print the current
762          * filename and line number within the current file
763          */
764         FlPrintFile (FileId, "%12s %5d%s",
765             Gbl_ListingNode->Filename, Gbl_ListingNode->LineNumber,
766             ASL_LISTING_LINE_PREFIX);
767     }
768     else
769     {
770         /* No include files, just print the line number */
771 
772         FlPrintFile (FileId, "%8u%s", Gbl_SourceLine,
773             ASL_LISTING_LINE_PREFIX);
774     }
775 
776     /* Read the rest of this line (up to a newline or EOF) */
777 
778     do
779     {
780         if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
781         {
782             if (FileByte == '/')
783             {
784                 FileByte = '*';
785             }
786         }
787 
788         FlWriteFile (FileId, &FileByte, 1);
789         if (FileByte == '\n')
790         {
791             /*
792              * This line has been completed.
793              * Check if an error occurred on this source line during the compile.
794              * If so, we print the error message after the source line.
795              */
796             LsCheckException (Gbl_SourceLine, FileId);
797             return (1);
798         }
799 
800     } while (FlReadFile (ASL_FILE_SOURCE_OUTPUT, &FileByte, 1) == AE_OK);
801 
802     /* EOF on the input file was reached */
803 
804     return (0);
805 }
806 
807 
808 /*******************************************************************************
809  *
810  * FUNCTION:    LsFinishSourceListing
811  *
812  * PARAMETERS:  FileId          - ID of current listing file.
813  *
814  * RETURN:      None
815  *
816  * DESCRIPTION: Cleanup routine for the listing file. Flush the hex AML
817  *              listing buffer, and flush out any remaining lines in the
818  *              source input file.
819  *
820  ******************************************************************************/
821 
822 static void
823 LsFinishSourceListing (
824     UINT32                  FileId)
825 {
826 
827     if ((FileId == ASL_FILE_ASM_INCLUDE_OUTPUT) ||
828         (FileId == ASL_FILE_C_INCLUDE_OUTPUT))
829     {
830         return;
831     }
832 
833     LsFlushListingBuffer (FileId);
834     Gbl_CurrentAmlOffset = 0;
835 
836     /* Flush any remaining text in the source file */
837 
838     if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
839     {
840         FlPrintFile (FileId, "    /*\n");
841     }
842 
843     while (LsWriteOneSourceLine (FileId))
844     { ; }
845 
846     if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
847     {
848         FlPrintFile (FileId, "\n     */\n    };\n");
849     }
850 
851     FlPrintFile (FileId, "\n");
852 
853     if (FileId == ASL_FILE_LISTING_OUTPUT)
854     {
855         /* Print a summary of the compile exceptions */
856 
857         FlPrintFile (FileId, "\n\nSummary of errors and warnings\n\n");
858         AePrintErrorLog (FileId);
859         FlPrintFile (FileId, "\n");
860         UtDisplaySummary (FileId);
861         FlPrintFile (FileId, "\n");
862     }
863 }
864 
865 
866 /*******************************************************************************
867  *
868  * FUNCTION:    LsWriteSourceLines
869  *
870  * PARAMETERS:  ToLineNumber            -
871  *              ToLogicalLineNumber     - Write up to this source line number
872  *              FileId                  - ID of current listing file
873  *
874  * RETURN:      None
875  *
876  * DESCRIPTION: Read then write source lines to the listing file until we have
877  *              reached the specified logical (cumulative) line number. This
878  *              automatically echos out comment blocks and other non-AML
879  *              generating text until we get to the actual AML-generating line
880  *              of ASL code specified by the logical line number.
881  *
882  ******************************************************************************/
883 
884 static void
885 LsWriteSourceLines (
886     UINT32                  ToLineNumber,
887     UINT32                  ToLogicalLineNumber,
888     UINT32                  FileId)
889 {
890 
891     if ((FileId == ASL_FILE_ASM_INCLUDE_OUTPUT) ||
892         (FileId == ASL_FILE_C_INCLUDE_OUTPUT))
893     {
894         return;
895     }
896 
897     Gbl_CurrentLine = ToLogicalLineNumber;
898 
899     /* Flush any hex bytes remaining from the last opcode */
900 
901     LsFlushListingBuffer (FileId);
902 
903     /* Read lines and write them as long as we are not caught up */
904 
905     if (Gbl_SourceLine < Gbl_CurrentLine)
906     {
907         /*
908          * If we just completed writing some AML hex bytes, output a linefeed
909          * to add some whitespace for readability.
910          */
911         if (Gbl_HexBytesWereWritten)
912         {
913             FlPrintFile (FileId, "\n");
914             Gbl_HexBytesWereWritten = FALSE;
915         }
916 
917         if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
918         {
919             FlPrintFile (FileId, "    /*\n");
920         }
921 
922         /* Write one line at a time until we have reached the target line # */
923 
924         while ((Gbl_SourceLine < Gbl_CurrentLine) &&
925                 LsWriteOneSourceLine (FileId))
926         { ; }
927 
928         if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
929         {
930             FlPrintFile (FileId, "     */");
931         }
932         FlPrintFile (FileId, "\n");
933     }
934 }
935 
936 
937 /*******************************************************************************
938  *
939  * FUNCTION:    LsWriteNodeToListing
940  *
941  * PARAMETERS:  Op            - Parse node to write to the listing file.
942  *              FileId          - ID of current listing file
943  *
944  * RETURN:      None.
945  *
946  * DESCRIPTION: Write "a node" to the listing file. This means to
947  *              1) Write out all of the source text associated with the node
948  *              2) Write out all of the AML bytes associated with the node
949  *              3) Write any compiler exceptions associated with the node
950  *
951  ******************************************************************************/
952 
953 static void
954 LsWriteNodeToListing (
955     ACPI_PARSE_OBJECT       *Op,
956     UINT32                  FileId)
957 {
958     const ACPI_OPCODE_INFO  *OpInfo;
959     UINT32                  OpClass;
960     char                    *Pathname;
961     UINT32                  Length;
962     UINT32                  i;
963 
964 
965     OpInfo  = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
966     OpClass = OpInfo->Class;
967 
968     /* TBD: clean this up with a single flag that says:
969      * I start a named output block
970      */
971     if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
972     {
973         switch (Op->Asl.ParseOpcode)
974         {
975         case PARSEOP_DEFINITIONBLOCK:
976         case PARSEOP_METHODCALL:
977         case PARSEOP_INCLUDE:
978         case PARSEOP_INCLUDE_END:
979         case PARSEOP_DEFAULT_ARG:
980 
981             break;
982 
983         default:
984             switch (OpClass)
985             {
986             case AML_CLASS_NAMED_OBJECT:
987                 switch (Op->Asl.AmlOpcode)
988                 {
989                 case AML_SCOPE_OP:
990                 case AML_ALIAS_OP:
991                     break;
992 
993                 default:
994                     if (Op->Asl.ExternalName)
995                     {
996                         LsFlushListingBuffer (FileId);
997                         FlPrintFile (FileId, "    };\n");
998                     }
999                     break;
1000                 }
1001                 break;
1002 
1003             default:
1004                 /* Don't care about other objects */
1005                 break;
1006             }
1007             break;
1008         }
1009     }
1010 
1011     /* These cases do not have a corresponding AML opcode */
1012 
1013     switch (Op->Asl.ParseOpcode)
1014     {
1015     case PARSEOP_DEFINITIONBLOCK:
1016 
1017         LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine, FileId);
1018 
1019         /* Use the table Signature and TableId to build a unique name */
1020 
1021         if (FileId == ASL_FILE_ASM_SOURCE_OUTPUT)
1022         {
1023             FlPrintFile (FileId,
1024                 "%s_%s_Header \\\n",
1025                 Gbl_TableSignature, Gbl_TableId);
1026         }
1027         if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
1028         {
1029             FlPrintFile (FileId,
1030                 "    unsigned char    %s_%s_Header [] =\n    {\n",
1031                 Gbl_TableSignature, Gbl_TableId);
1032         }
1033         if (FileId == ASL_FILE_ASM_INCLUDE_OUTPUT)
1034         {
1035             FlPrintFile (FileId,
1036                 "extrn %s_%s_Header : byte\n",
1037                 Gbl_TableSignature, Gbl_TableId);
1038         }
1039         if (FileId == ASL_FILE_C_INCLUDE_OUTPUT)
1040         {
1041             FlPrintFile (FileId,
1042                 "extern unsigned char    %s_%s_Header [];\n",
1043                 Gbl_TableSignature, Gbl_TableId);
1044         }
1045         return;
1046 
1047 
1048     case PARSEOP_METHODCALL:
1049 
1050         LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
1051             FileId);
1052         return;
1053 
1054 
1055     case PARSEOP_INCLUDE:
1056 
1057         /* Flush everything up to and including the include source line */
1058 
1059         LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
1060             FileId);
1061 
1062         /* Create a new listing node and push it */
1063 
1064         LsPushNode (Op->Asl.Child->Asl.Value.String);
1065         return;
1066 
1067 
1068     case PARSEOP_INCLUDE_END:
1069 
1070         /* Flush out the rest of the include file */
1071 
1072         LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
1073             FileId);
1074 
1075         /* Pop off this listing node and go back to the parent file */
1076 
1077         (void) LsPopNode ();
1078         return;
1079 
1080 
1081     case PARSEOP_DEFAULT_ARG:
1082 
1083         if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC)
1084         {
1085             LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.EndLogicalLine,
1086                 FileId);
1087         }
1088         return;
1089 
1090 
1091     default:
1092         /* All other opcodes have an AML opcode */
1093         break;
1094     }
1095 
1096     /*
1097      * Otherwise, we look at the AML opcode because we can
1098      * switch on the opcode type, getting an entire class
1099      * at once
1100      */
1101     switch (OpClass)
1102     {
1103     case AML_CLASS_ARGUMENT:       /* argument type only */
1104     case AML_CLASS_INTERNAL:
1105 
1106         break;
1107 
1108 
1109     case AML_CLASS_NAMED_OBJECT:
1110 
1111         switch (Op->Asl.AmlOpcode)
1112         {
1113         case AML_FIELD_OP:
1114         case AML_INDEX_FIELD_OP:
1115         case AML_BANK_FIELD_OP:
1116 
1117             /*
1118              * For fields, we want to dump all the AML after the
1119              * entire definition
1120              */
1121             LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine,
1122                 FileId);
1123             break;
1124 
1125         case AML_NAME_OP:
1126 
1127             if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC)
1128             {
1129                 LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
1130                     FileId);
1131             }
1132             else
1133             {
1134                 /*
1135                  * For fields, we want to dump all the AML after the
1136                  * entire definition
1137                  */
1138                 LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine,
1139                     FileId);
1140             }
1141             break;
1142 
1143         default:
1144             LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
1145                 FileId);
1146             break;
1147         }
1148 
1149         switch (Op->Asl.AmlOpcode)
1150         {
1151         case AML_SCOPE_OP:
1152         case AML_ALIAS_OP:
1153 
1154             /* These opcodes do not declare a new object, ignore them */
1155 
1156             break;
1157 
1158         default:
1159 
1160             /* All other named object opcodes come here */
1161 
1162             switch (FileId)
1163             {
1164             case ASL_FILE_ASM_SOURCE_OUTPUT:
1165             case ASL_FILE_C_SOURCE_OUTPUT:
1166             case ASL_FILE_ASM_INCLUDE_OUTPUT:
1167             case ASL_FILE_C_INCLUDE_OUTPUT:
1168 
1169                 /*
1170                  * For named objects, we will create a valid symbol so that the
1171                  * AML code can be referenced from C or ASM
1172                  */
1173                 if (Op->Asl.ExternalName)
1174                 {
1175                     /* Get the full pathname associated with this node */
1176 
1177                     Pathname = AcpiNsGetExternalPathname (Op->Asl.Node);
1178                     Length = strlen (Pathname);
1179                     if (Length >= 4)
1180                     {
1181                         /* Convert all dots in the path to underscores */
1182 
1183                         for (i = 0; i < Length; i++)
1184                         {
1185                             if (Pathname[i] == '.')
1186                             {
1187                                 Pathname[i] = '_';
1188                             }
1189                         }
1190 
1191                         /* Create the appropriate symbol in the output file */
1192 
1193                         if (FileId == ASL_FILE_ASM_SOURCE_OUTPUT)
1194                         {
1195                             FlPrintFile (FileId,
1196                                 "%s_%s_%s  \\\n",
1197                                 Gbl_TableSignature, Gbl_TableId, &Pathname[1]);
1198                         }
1199                         if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
1200                         {
1201                             FlPrintFile (FileId,
1202                                 "    unsigned char    %s_%s_%s [] =\n    {\n",
1203                                 Gbl_TableSignature, Gbl_TableId, &Pathname[1]);
1204                         }
1205                         if (FileId == ASL_FILE_ASM_INCLUDE_OUTPUT)
1206                         {
1207                             FlPrintFile (FileId,
1208                                 "extrn %s_%s_%s : byte\n",
1209                                 Gbl_TableSignature, Gbl_TableId, &Pathname[1]);
1210                         }
1211                         if (FileId == ASL_FILE_C_INCLUDE_OUTPUT)
1212                         {
1213                             FlPrintFile (FileId,
1214                                 "extern unsigned char    %s_%s_%s [];\n",
1215                                 Gbl_TableSignature, Gbl_TableId, &Pathname[1]);
1216                         }
1217                     }
1218                     ACPI_FREE (Pathname);
1219                 }
1220                 break;
1221 
1222             default:
1223                 /* Nothing to do for listing file */
1224                 break;
1225             }
1226         }
1227         break;
1228 
1229     case AML_CLASS_EXECUTE:
1230     case AML_CLASS_CREATE:
1231     default:
1232 
1233         if ((Op->Asl.ParseOpcode == PARSEOP_BUFFER) &&
1234             (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC))
1235         {
1236             return;
1237         }
1238 
1239         LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
1240             FileId);
1241         break;
1242 
1243     case AML_CLASS_UNKNOWN:
1244         break;
1245     }
1246 }
1247