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