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