xref: /freebsd/sys/contrib/dev/acpica/compiler/asllisting.c (revision 271c3a9060f2ee55607ebe146523f888e1db2654)
1 
2 /******************************************************************************
3  *
4  * Module Name: asllisting - Listing file generation
5  *              $Revision: 1.63 $
6  *
7  *****************************************************************************/
8 
9 /******************************************************************************
10  *
11  * 1. Copyright Notice
12  *
13  * Some or all of this work - Copyright (c) 1999 - 2007, 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 <contrib/dev/acpica/compiler/aslcompiler.h>
120 #include "aslcompiler.y.h"
121 #include <contrib/dev/acpica/amlcode.h>
122 #include <contrib/dev/acpica/acparser.h>
123 #include <contrib/dev/acpica/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 
1495