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