1 /******************************************************************************
2  *
3  * Module Name: aslcompile - top level compile module
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2013, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43 
44 #include <contrib/dev/acpica/compiler/aslcompiler.h>
45 #include <contrib/dev/acpica/compiler/dtcompiler.h>
46 
47 #include <stdio.h>
48 #include <time.h>
49 #include <contrib/dev/acpica/include/acapps.h>
50 
51 #define _COMPONENT          ACPI_COMPILER
52         ACPI_MODULE_NAME    ("aslcompile")
53 
54 /*
55  * Main parser entry
56  * External is here in case the parser emits the same external in the
57  * generated header. (Newer versions of Bison)
58  */
59 int
60 AslCompilerparse(
61     void);
62 
63 /* Local prototypes */
64 
65 static void
66 CmFlushSourceCode (
67     void);
68 
69 static void
70 FlConsumeAnsiComment (
71     FILE                    *Handle,
72     ASL_FILE_STATUS         *Status);
73 
74 static void
75 FlConsumeNewComment (
76     FILE                    *Handle,
77     ASL_FILE_STATUS         *Status);
78 
79 static void
80 CmDumpAllEvents (
81     void);
82 
83 
84 /*******************************************************************************
85  *
86  * FUNCTION:    AslCompilerSignon
87  *
88  * PARAMETERS:  FileId      - ID of the output file
89  *
90  * RETURN:      None
91  *
92  * DESCRIPTION: Display compiler signon
93  *
94  ******************************************************************************/
95 
96 void
97 AslCompilerSignon (
98     UINT32                  FileId)
99 {
100     char                    *Prefix = "";
101     char                    *UtilityName;
102 
103 
104     /* Set line prefix depending on the destination file type */
105 
106     switch (FileId)
107     {
108     case ASL_FILE_ASM_SOURCE_OUTPUT:
109     case ASL_FILE_ASM_INCLUDE_OUTPUT:
110 
111         Prefix = "; ";
112         break;
113 
114     case ASL_FILE_HEX_OUTPUT:
115 
116         if (Gbl_HexOutputFlag == HEX_OUTPUT_ASM)
117         {
118             Prefix = "; ";
119         }
120         else if ((Gbl_HexOutputFlag == HEX_OUTPUT_C) ||
121                  (Gbl_HexOutputFlag == HEX_OUTPUT_ASL))
122         {
123             FlPrintFile (ASL_FILE_HEX_OUTPUT, "/*\n");
124             Prefix = " * ";
125         }
126         break;
127 
128     case ASL_FILE_C_SOURCE_OUTPUT:
129     case ASL_FILE_C_OFFSET_OUTPUT:
130     case ASL_FILE_C_INCLUDE_OUTPUT:
131 
132         Prefix = " * ";
133         break;
134 
135     default:
136 
137         /* No other output types supported */
138 
139         break;
140     }
141 
142     /* Running compiler or disassembler? */
143 
144     if (Gbl_DisasmFlag)
145     {
146         UtilityName = AML_DISASSEMBLER_NAME;
147     }
148     else
149     {
150         UtilityName = ASL_COMPILER_NAME;
151     }
152 
153     /* Compiler signon with copyright */
154 
155     FlPrintFile (FileId, "%s\n", Prefix);
156     FlPrintFile (FileId, ACPI_COMMON_HEADER (UtilityName, Prefix));
157 }
158 
159 
160 /*******************************************************************************
161  *
162  * FUNCTION:    AslCompilerFileHeader
163  *
164  * PARAMETERS:  FileId      - ID of the output file
165  *
166  * RETURN:      None
167  *
168  * DESCRIPTION: Header used at the beginning of output files
169  *
170  ******************************************************************************/
171 
172 void
173 AslCompilerFileHeader (
174     UINT32                  FileId)
175 {
176     struct tm               *NewTime;
177     time_t                  Aclock;
178     char                    *Prefix = "";
179 
180 
181     /* Set line prefix depending on the destination file type */
182 
183     switch (FileId)
184     {
185     case ASL_FILE_ASM_SOURCE_OUTPUT:
186     case ASL_FILE_ASM_INCLUDE_OUTPUT:
187 
188         Prefix = "; ";
189         break;
190 
191     case ASL_FILE_HEX_OUTPUT:
192 
193         if (Gbl_HexOutputFlag == HEX_OUTPUT_ASM)
194         {
195             Prefix = "; ";
196         }
197         else if ((Gbl_HexOutputFlag == HEX_OUTPUT_C) ||
198                  (Gbl_HexOutputFlag == HEX_OUTPUT_ASL))
199         {
200             Prefix = " * ";
201         }
202         break;
203 
204     case ASL_FILE_C_SOURCE_OUTPUT:
205     case ASL_FILE_C_OFFSET_OUTPUT:
206     case ASL_FILE_C_INCLUDE_OUTPUT:
207 
208         Prefix = " * ";
209         break;
210 
211     default:
212 
213         /* No other output types supported */
214 
215         break;
216     }
217 
218     /* Compilation header with timestamp */
219 
220     (void) time (&Aclock);
221     NewTime = localtime (&Aclock);
222 
223     FlPrintFile (FileId,
224         "%sCompilation of \"%s\" - %s%s\n",
225         Prefix, Gbl_Files[ASL_FILE_INPUT].Filename, asctime (NewTime),
226         Prefix);
227 
228     switch (FileId)
229     {
230     case ASL_FILE_C_SOURCE_OUTPUT:
231     case ASL_FILE_C_OFFSET_OUTPUT:
232     case ASL_FILE_C_INCLUDE_OUTPUT:
233 
234         FlPrintFile (FileId, " */\n");
235         break;
236 
237     default:
238 
239         /* Nothing to do for other output types */
240 
241         break;
242     }
243 }
244 
245 
246 /*******************************************************************************
247  *
248  * FUNCTION:    CmFlushSourceCode
249  *
250  * PARAMETERS:  None
251  *
252  * RETURN:      None
253  *
254  * DESCRIPTION: Read in any remaining source code after the parse tree
255  *              has been constructed.
256  *
257  ******************************************************************************/
258 
259 static void
260 CmFlushSourceCode (
261     void)
262 {
263     char                    Buffer;
264 
265 
266     while (FlReadFile (ASL_FILE_INPUT, &Buffer, 1) != AE_ERROR)
267     {
268         AslInsertLineBuffer ((int) Buffer);
269     }
270 
271     AslResetCurrentLineBuffer ();
272 }
273 
274 
275 /*******************************************************************************
276  *
277  * FUNCTION:    FlConsume*
278  *
279  * PARAMETERS:  Handle              - Open input file
280  *              Status              - File current status struct
281  *
282  * RETURN:      Number of lines consumed
283  *
284  * DESCRIPTION: Step over both types of comment during check for ascii chars
285  *
286  ******************************************************************************/
287 
288 static void
289 FlConsumeAnsiComment (
290     FILE                    *Handle,
291     ASL_FILE_STATUS         *Status)
292 {
293     UINT8                   Byte;
294     BOOLEAN                 ClosingComment = FALSE;
295 
296 
297     while (fread (&Byte, 1, 1, Handle) == 1)
298     {
299         /* Scan until comment close is found */
300 
301         if (ClosingComment)
302         {
303             if (Byte == '/')
304             {
305                 return;
306             }
307 
308             if (Byte != '*')
309             {
310                 /* Reset */
311 
312                 ClosingComment = FALSE;
313             }
314         }
315         else if (Byte == '*')
316         {
317             ClosingComment = TRUE;
318         }
319 
320         /* Maintain line count */
321 
322         if (Byte == 0x0A)
323         {
324             Status->Line++;
325         }
326 
327         Status->Offset++;
328     }
329 }
330 
331 
332 static void
333 FlConsumeNewComment (
334     FILE                    *Handle,
335     ASL_FILE_STATUS         *Status)
336 {
337     UINT8                   Byte;
338 
339 
340     while (fread (&Byte, 1, 1, Handle) == 1)
341     {
342         Status->Offset++;
343 
344         /* Comment ends at newline */
345 
346         if (Byte == 0x0A)
347         {
348             Status->Line++;
349             return;
350         }
351     }
352 }
353 
354 
355 /*******************************************************************************
356  *
357  * FUNCTION:    FlCheckForAcpiTable
358  *
359  * PARAMETERS:  Handle              - Open input file
360  *
361  * RETURN:      Status
362  *
363  * DESCRIPTION: Determine if a file seems to be a binary ACPI table, via the
364  *              following checks on what would be the table header:
365  *              0) File must be at least as long as an ACPI_TABLE_HEADER
366  *              1) The header length field must match the file size
367  *              2) Signature, OemId, OemTableId, AslCompilerId must be ASCII
368  *
369  ******************************************************************************/
370 
371 ACPI_STATUS
372 FlCheckForAcpiTable (
373     FILE                    *Handle)
374 {
375     ACPI_TABLE_HEADER       Table;
376     UINT32                  FileSize;
377     size_t                  Actual;
378     UINT32                  i;
379 
380 
381     /* Read a potential table header */
382 
383     Actual = fread (&Table, 1, sizeof (ACPI_TABLE_HEADER), Handle);
384     fseek (Handle, 0, SEEK_SET);
385 
386     if (Actual < sizeof (ACPI_TABLE_HEADER))
387     {
388         return (AE_ERROR);
389     }
390 
391     /* Header length field must match the file size */
392 
393     FileSize = DtGetFileSize (Handle);
394     if (Table.Length != FileSize)
395     {
396         return (AE_ERROR);
397     }
398 
399     /*
400      * These fields must be ASCII:
401      * Signature, OemId, OemTableId, AslCompilerId.
402      * We allow a NULL terminator in OemId and OemTableId.
403      */
404     for (i = 0; i < ACPI_NAME_SIZE; i++)
405     {
406         if (!ACPI_IS_ASCII ((UINT8) Table.Signature[i]))
407         {
408             return (AE_ERROR);
409         }
410 
411         if (!ACPI_IS_ASCII ((UINT8) Table.AslCompilerId[i]))
412         {
413             return (AE_ERROR);
414         }
415     }
416 
417     for (i = 0; (i < ACPI_OEM_ID_SIZE) && (Table.OemId[i]); i++)
418     {
419         if (!ACPI_IS_ASCII ((UINT8) Table.OemId[i]))
420         {
421             return (AE_ERROR);
422         }
423     }
424 
425     for (i = 0; (i < ACPI_OEM_TABLE_ID_SIZE) && (Table.OemTableId[i]); i++)
426     {
427         if (!ACPI_IS_ASCII ((UINT8) Table.OemTableId[i]))
428         {
429             return (AE_ERROR);
430         }
431     }
432 
433     printf ("Binary file appears to be a valid ACPI table, disassembling\n");
434     return (AE_OK);
435 }
436 
437 
438 /*******************************************************************************
439  *
440  * FUNCTION:    FlCheckForAscii
441  *
442  * PARAMETERS:  Handle              - Open input file
443  *              Filename            - Input filename
444  *              DisplayErrors       - TRUE if error messages desired
445  *
446  * RETURN:      Status
447  *
448  * DESCRIPTION: Verify that the input file is entirely ASCII. Ignores characters
449  *              within comments. Note: does not handle nested comments and does
450  *              not handle comment delimiters within string literals. However,
451  *              on the rare chance this happens and an invalid character is
452  *              missed, the parser will catch the error by failing in some
453  *              spectactular manner.
454  *
455  ******************************************************************************/
456 
457 ACPI_STATUS
458 FlCheckForAscii (
459     FILE                    *Handle,
460     char                    *Filename,
461     BOOLEAN                 DisplayErrors)
462 {
463     UINT8                   Byte;
464     ACPI_SIZE               BadBytes = 0;
465     BOOLEAN                 OpeningComment = FALSE;
466     ASL_FILE_STATUS         Status;
467 
468 
469     Status.Line = 1;
470     Status.Offset = 0;
471 
472     /* Read the entire file */
473 
474     while (fread (&Byte, 1, 1, Handle) == 1)
475     {
476         /* Ignore comment fields (allow non-ascii within) */
477 
478         if (OpeningComment)
479         {
480             /* Check for second comment open delimiter */
481 
482             if (Byte == '*')
483             {
484                 FlConsumeAnsiComment (Handle, &Status);
485             }
486 
487             if (Byte == '/')
488             {
489                 FlConsumeNewComment (Handle, &Status);
490             }
491 
492             /* Reset */
493 
494             OpeningComment = FALSE;
495         }
496         else if (Byte == '/')
497         {
498             OpeningComment = TRUE;
499         }
500 
501         /* Check for an ASCII character */
502 
503         if (!ACPI_IS_ASCII (Byte))
504         {
505             if ((BadBytes < 10) && (DisplayErrors))
506             {
507                 AcpiOsPrintf (
508                     "Non-ASCII character [0x%2.2X] found in line %u, file offset 0x%.2X\n",
509                     Byte, Status.Line, Status.Offset);
510             }
511 
512             BadBytes++;
513         }
514 
515         /* Update line counter */
516 
517         else if (Byte == 0x0A)
518         {
519             Status.Line++;
520         }
521 
522         Status.Offset++;
523     }
524 
525     /* Seek back to the beginning of the source file */
526 
527     fseek (Handle, 0, SEEK_SET);
528 
529     /* Were there any non-ASCII characters in the file? */
530 
531     if (BadBytes)
532     {
533         if (DisplayErrors)
534         {
535             AcpiOsPrintf (
536                 "%u non-ASCII characters found in input source text, could be a binary file\n",
537                 BadBytes);
538             AslError (ASL_ERROR, ASL_MSG_NON_ASCII, NULL, Filename);
539         }
540 
541         return (AE_BAD_CHARACTER);
542     }
543 
544     /* File is OK (100% ASCII) */
545 
546     return (AE_OK);
547 }
548 
549 
550 /*******************************************************************************
551  *
552  * FUNCTION:    CmDoCompile
553  *
554  * PARAMETERS:  None
555  *
556  * RETURN:      Status (0 = OK)
557  *
558  * DESCRIPTION: This procedure performs the entire compile
559  *
560  ******************************************************************************/
561 
562 int
563 CmDoCompile (
564     void)
565 {
566     ACPI_STATUS             Status;
567     UINT8                   FullCompile;
568     UINT8                   Event;
569 
570 
571     FullCompile = UtBeginEvent ("*** Total Compile time ***");
572     Event = UtBeginEvent ("Open input and output files");
573     UtEndEvent (Event);
574 
575     Event = UtBeginEvent ("Preprocess input file");
576     if (Gbl_PreprocessFlag)
577     {
578         /* Preprocessor */
579 
580         PrDoPreprocess ();
581         if (Gbl_PreprocessOnly)
582         {
583             UtEndEvent (Event);
584             CmCleanupAndExit ();
585             return (0);
586         }
587     }
588     UtEndEvent (Event);
589 
590     /* Build the parse tree */
591 
592     Event = UtBeginEvent ("Parse source code and build parse tree");
593     AslCompilerparse();
594     UtEndEvent (Event);
595 
596     /* Flush out any remaining source after parse tree is complete */
597 
598     Event = UtBeginEvent ("Flush source input");
599     CmFlushSourceCode ();
600 
601     /* Did the parse tree get successfully constructed? */
602 
603     if (!RootNode)
604     {
605         /*
606          * If there are no errors, then we have some sort of
607          * internal problem.
608          */
609         Status = AslCheckForErrorExit ();
610         if (Status == AE_OK)
611         {
612             AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL,
613                 NULL, "- Could not resolve parse tree root node");
614         }
615 
616         goto ErrorExit;
617     }
618 
619     /* Optional parse tree dump, compiler debug output only */
620 
621     LsDumpParseTree ();
622 
623     OpcGetIntegerWidth (RootNode);
624     UtEndEvent (Event);
625 
626     /* Pre-process parse tree for any operator transforms */
627 
628     Event = UtBeginEvent ("Parse tree transforms");
629     DbgPrint (ASL_DEBUG_OUTPUT, "\nParse tree transforms\n\n");
630     TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD,
631         TrAmlTransformWalk, NULL, NULL);
632     UtEndEvent (Event);
633 
634     /* Generate AML opcodes corresponding to the parse tokens */
635 
636     Event = UtBeginEvent ("Generate AML opcodes");
637     DbgPrint (ASL_DEBUG_OUTPUT, "\nGenerating AML opcodes\n\n");
638     TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD, NULL,
639         OpcAmlOpcodeWalk, NULL);
640     UtEndEvent (Event);
641 
642     /*
643      * Now that the input is parsed, we can open the AML output file.
644      * Note: by default, the name of this file comes from the table descriptor
645      * within the input file.
646      */
647     Event = UtBeginEvent ("Open AML output file");
648     Status = FlOpenAmlOutputFile (Gbl_OutputFilenamePrefix);
649     UtEndEvent (Event);
650     if (ACPI_FAILURE (Status))
651     {
652         AePrintErrorLog (ASL_FILE_STDERR);
653         return (-1);
654     }
655 
656     /* Interpret and generate all compile-time constants */
657 
658     Event = UtBeginEvent ("Constant folding via AML interpreter");
659     DbgPrint (ASL_DEBUG_OUTPUT,
660         "\nInterpreting compile-time constant expressions\n\n");
661     TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD,
662         OpcAmlConstantWalk, NULL, NULL);
663     UtEndEvent (Event);
664 
665     /* Update AML opcodes if necessary, after constant folding */
666 
667     Event = UtBeginEvent ("Updating AML opcodes after constant folding");
668     DbgPrint (ASL_DEBUG_OUTPUT,
669         "\nUpdating AML opcodes after constant folding\n\n");
670     TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD,
671         NULL, OpcAmlOpcodeUpdateWalk, NULL);
672     UtEndEvent (Event);
673 
674     /* Calculate all AML package lengths */
675 
676     Event = UtBeginEvent ("Generate AML package lengths");
677     DbgPrint (ASL_DEBUG_OUTPUT, "\nGenerating Package lengths\n\n");
678     TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD, NULL,
679         LnPackageLengthWalk, NULL);
680     UtEndEvent (Event);
681 
682     if (Gbl_ParseOnlyFlag)
683     {
684         AePrintErrorLog (ASL_FILE_STDERR);
685         UtDisplaySummary (ASL_FILE_STDERR);
686         if (Gbl_DebugFlag)
687         {
688             /* Print error summary to the stdout also */
689 
690             AePrintErrorLog (ASL_FILE_STDOUT);
691             UtDisplaySummary (ASL_FILE_STDOUT);
692         }
693         UtEndEvent (FullCompile);
694         return (0);
695     }
696 
697     /*
698      * Create an internal namespace and use it as a symbol table
699      */
700 
701     /* Namespace loading */
702 
703     Event = UtBeginEvent ("Create ACPI Namespace");
704     Status = LdLoadNamespace (RootNode);
705     UtEndEvent (Event);
706     if (ACPI_FAILURE (Status))
707     {
708         goto ErrorExit;
709     }
710 
711     /* Namespace cross-reference */
712 
713     AslGbl_NamespaceEvent = UtBeginEvent ("Cross reference parse tree and Namespace");
714     Status = XfCrossReferenceNamespace ();
715     if (ACPI_FAILURE (Status))
716     {
717         goto ErrorExit;
718     }
719 
720     /* Namespace - Check for non-referenced objects */
721 
722     LkFindUnreferencedObjects ();
723     UtEndEvent (AslGbl_NamespaceEvent);
724 
725     /*
726      * Semantic analysis. This can happen only after the
727      * namespace has been loaded and cross-referenced.
728      *
729      * part one - check control methods
730      */
731     Event = UtBeginEvent ("Analyze control method return types");
732     AnalysisWalkInfo.MethodStack = NULL;
733 
734     DbgPrint (ASL_DEBUG_OUTPUT, "\nSemantic analysis - Method analysis\n\n");
735     TrWalkParseTree (RootNode, ASL_WALK_VISIT_TWICE,
736         MtMethodAnalysisWalkBegin,
737         MtMethodAnalysisWalkEnd, &AnalysisWalkInfo);
738     UtEndEvent (Event);
739 
740     /* Semantic error checking part two - typing of method returns */
741 
742     Event = UtBeginEvent ("Determine object types returned by methods");
743     DbgPrint (ASL_DEBUG_OUTPUT, "\nSemantic analysis - Method typing\n\n");
744     TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD,
745         NULL, AnMethodTypingWalkEnd, NULL);
746     UtEndEvent (Event);
747 
748     /* Semantic error checking part three - operand type checking */
749 
750     Event = UtBeginEvent ("Analyze AML operand types");
751     DbgPrint (ASL_DEBUG_OUTPUT, "\nSemantic analysis - Operand type checking\n\n");
752     TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD,
753         NULL, AnOperandTypecheckWalkEnd, &AnalysisWalkInfo);
754     UtEndEvent (Event);
755 
756     /* Semantic error checking part four - other miscellaneous checks */
757 
758     Event = UtBeginEvent ("Miscellaneous analysis");
759     DbgPrint (ASL_DEBUG_OUTPUT, "\nSemantic analysis - miscellaneous\n\n");
760     TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD,
761         AnOtherSemanticAnalysisWalkBegin,
762         NULL, &AnalysisWalkInfo);
763     UtEndEvent (Event);
764 
765     /* Calculate all AML package lengths */
766 
767     Event = UtBeginEvent ("Finish AML package length generation");
768     DbgPrint (ASL_DEBUG_OUTPUT, "\nGenerating Package lengths\n\n");
769     TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD, NULL,
770         LnInitLengthsWalk, NULL);
771     TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD, NULL,
772         LnPackageLengthWalk, NULL);
773     UtEndEvent (Event);
774 
775     /* Code generation - emit the AML */
776 
777     Event = UtBeginEvent ("Generate AML code and write output files");
778     CgGenerateAmlOutput ();
779     UtEndEvent (Event);
780 
781     Event = UtBeginEvent ("Write optional output files");
782     CmDoOutputFiles ();
783     UtEndEvent (Event);
784 
785     UtEndEvent (FullCompile);
786     CmCleanupAndExit ();
787     return (0);
788 
789 ErrorExit:
790     UtEndEvent (FullCompile);
791     CmCleanupAndExit ();
792     return (-1);
793 }
794 
795 
796 /*******************************************************************************
797  *
798  * FUNCTION:    CmDoOutputFiles
799  *
800  * PARAMETERS:  None
801  *
802  * RETURN:      None.
803  *
804  * DESCRIPTION: Create all "listing" type files
805  *
806  ******************************************************************************/
807 
808 void
809 CmDoOutputFiles (
810     void)
811 {
812 
813     /* Create listings and hex files */
814 
815     LsDoListings ();
816     HxDoHexOutput ();
817 
818     /* Dump the namespace to the .nsp file if requested */
819 
820     (void) NsDisplayNamespace ();
821 }
822 
823 
824 /*******************************************************************************
825  *
826  * FUNCTION:    CmDumpAllEvents
827  *
828  * PARAMETERS:  None
829  *
830  * RETURN:      None.
831  *
832  * DESCRIPTION: Dump all compiler events
833  *
834  ******************************************************************************/
835 
836 static void
837 CmDumpAllEvents (
838     void)
839 {
840     ASL_EVENT_INFO          *Event;
841     UINT32                  Delta;
842     UINT32                  USec;
843     UINT32                  MSec;
844     UINT32                  i;
845 
846 
847     Event = AslGbl_Events;
848 
849     DbgPrint (ASL_DEBUG_OUTPUT, "\n\nElapsed time for major events\n\n");
850     if (Gbl_CompileTimesFlag)
851     {
852         printf ("\nElapsed time for major events\n\n");
853     }
854 
855     for (i = 0; i < AslGbl_NextEvent; i++)
856     {
857         if (Event->Valid)
858         {
859             /* Delta will be in 100-nanosecond units */
860 
861             Delta = (UINT32) (Event->EndTime - Event->StartTime);
862 
863             USec = Delta / ACPI_100NSEC_PER_USEC;
864             MSec = Delta / ACPI_100NSEC_PER_MSEC;
865 
866             /* Round milliseconds up */
867 
868             if ((USec - (MSec * ACPI_USEC_PER_MSEC)) >= 500)
869             {
870                 MSec++;
871             }
872 
873             DbgPrint (ASL_DEBUG_OUTPUT, "%8u usec %8u msec - %s\n",
874                 USec, MSec, Event->EventName);
875 
876             if (Gbl_CompileTimesFlag)
877             {
878                 printf ("%8u usec %8u msec - %s\n",
879                     USec, MSec, Event->EventName);
880             }
881         }
882 
883         Event++;
884     }
885 }
886 
887 
888 /*******************************************************************************
889  *
890  * FUNCTION:    CmCleanupAndExit
891  *
892  * PARAMETERS:  None
893  *
894  * RETURN:      None.
895  *
896  * DESCRIPTION: Close all open files and exit the compiler
897  *
898  ******************************************************************************/
899 
900 void
901 CmCleanupAndExit (
902     void)
903 {
904     UINT32                  i;
905     BOOLEAN                 DeleteAmlFile = FALSE;
906 
907 
908     AePrintErrorLog (ASL_FILE_STDERR);
909     if (Gbl_DebugFlag)
910     {
911         /* Print error summary to stdout also */
912 
913         AePrintErrorLog (ASL_FILE_STDOUT);
914     }
915 
916     /* Emit compile times if enabled */
917 
918     CmDumpAllEvents ();
919 
920     if (Gbl_CompileTimesFlag)
921     {
922         printf ("\nMiscellaneous compile statistics\n\n");
923         printf ("%11u : %s\n", TotalParseNodes, "Parse nodes");
924         printf ("%11u : %s\n", Gbl_NsLookupCount, "Namespace searches");
925         printf ("%11u : %s\n", TotalNamedObjects, "Named objects");
926         printf ("%11u : %s\n", TotalMethods, "Control methods");
927         printf ("%11u : %s\n", TotalAllocations, "Memory Allocations");
928         printf ("%11u : %s\n", TotalAllocated, "Total allocated memory");
929         printf ("%11u : %s\n", TotalFolds, "Constant subtrees folded");
930         printf ("\n");
931     }
932 
933     if (Gbl_NsLookupCount)
934     {
935         DbgPrint (ASL_DEBUG_OUTPUT,
936             "\n\nMiscellaneous compile statistics\n\n");
937 
938         DbgPrint (ASL_DEBUG_OUTPUT,
939             "%32s : %u\n", "Total Namespace searches",
940             Gbl_NsLookupCount);
941 
942         DbgPrint (ASL_DEBUG_OUTPUT,
943             "%32s : %u usec\n", "Time per search", ((UINT32)
944             (AslGbl_Events[AslGbl_NamespaceEvent].EndTime -
945                 AslGbl_Events[AslGbl_NamespaceEvent].StartTime) / 10) /
946                 Gbl_NsLookupCount);
947     }
948 
949     if (Gbl_ExceptionCount[ASL_ERROR] > ASL_MAX_ERROR_COUNT)
950     {
951         printf ("\nMaximum error count (%u) exceeded\n",
952             ASL_MAX_ERROR_COUNT);
953     }
954 
955     UtDisplaySummary (ASL_FILE_STDOUT);
956 
957     /*
958      * We will delete the AML file if there are errors and the
959      * force AML output option has not been used.
960      */
961     if ((Gbl_ExceptionCount[ASL_ERROR] > 0) && (!Gbl_IgnoreErrors) &&
962         Gbl_Files[ASL_FILE_AML_OUTPUT].Handle)
963     {
964         DeleteAmlFile = TRUE;
965     }
966 
967     /* Close all open files */
968 
969     /*
970      * Take care with the preprocessor file (.i), it might be the same
971      * as the "input" file, depending on where the compiler has terminated
972      * or aborted. Prevent attempt to close the same file twice in
973      * loop below.
974      */
975     if (Gbl_Files[ASL_FILE_PREPROCESSOR].Handle ==
976         Gbl_Files[ASL_FILE_INPUT].Handle)
977     {
978         Gbl_Files[ASL_FILE_PREPROCESSOR].Handle = NULL;
979     }
980 
981     /* Close the standard I/O files */
982 
983     for (i = ASL_FILE_INPUT; i < ASL_MAX_FILE_TYPE; i++)
984     {
985         FlCloseFile (i);
986     }
987 
988     /* Delete AML file if there are errors */
989 
990     if (DeleteAmlFile)
991     {
992         FlDeleteFile (ASL_FILE_AML_OUTPUT);
993     }
994 
995     /* Delete the preprocessor output file (.i) unless -li flag is set */
996 
997     if (!Gbl_PreprocessorOutputFlag &&
998         Gbl_PreprocessFlag)
999     {
1000         FlDeleteFile (ASL_FILE_PREPROCESSOR);
1001     }
1002 
1003     /*
1004      * Delete intermediate ("combined") source file (if -ls flag not set)
1005      * This file is created during normal ASL/AML compiles. It is not
1006      * created by the data table compiler.
1007      *
1008      * If the -ls flag is set, then the .SRC file should not be deleted.
1009      * In this case, Gbl_SourceOutputFlag is set to TRUE.
1010      *
1011      * Note: Handles are cleared by FlCloseFile above, so we look at the
1012      * filename instead, to determine if the .SRC file was actually
1013      * created.
1014      *
1015      * TBD: SourceOutput should be .TMP, then rename if we want to keep it?
1016      */
1017     if (!Gbl_SourceOutputFlag)
1018     {
1019         FlDeleteFile (ASL_FILE_SOURCE_OUTPUT);
1020     }
1021 }
1022