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