1/******************************************************************************
2 *
3 * Module Name: aslcompile - top level compile module
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2023, 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 MERCHANTABILITY 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 "aslcompiler.h"
45#include "acnamesp.h"
46
47#include <stdio.h>
48#include <time.h>
49#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 */
59int
60AslCompilerparse(
61    void);
62
63/* Local prototypes */
64
65static void
66CmFlushSourceCode (
67    void);
68
69static void
70CmDumpAllEvents (
71    void);
72
73static void
74CmFinishFiles(
75    BOOLEAN                 DeleteAmlFile);
76
77
78/*******************************************************************************
79 *
80 * FUNCTION:    CmDoCompile
81 *
82 * PARAMETERS:  None
83 *
84 * RETURN:      Status (0 = OK)
85 *
86 * DESCRIPTION: This procedure performs the entire compile
87 *
88 ******************************************************************************/
89
90ACPI_STATUS
91CmDoCompile (
92    void)
93{
94    UINT8                   FullCompile;
95    UINT8                   Event;
96    ASL_GLOBAL_FILE_NODE    *FileNode;
97
98
99    FullCompile = UtBeginEvent ("*** Total Compile time ***");
100    Event = UtBeginEvent ("Open input and output files");
101    UtEndEvent (Event);
102
103    Event = UtBeginEvent ("Preprocess input file");
104    if (AslGbl_PreprocessFlag)
105    {
106        /* Enter compiler name as a #define */
107
108        PrAddDefine (ASL_DEFINE, "", FALSE);
109
110        /* Preprocessor */
111
112        PrDoPreprocess ();
113        AslGbl_CurrentLineNumber = 1;
114        AslGbl_LogicalLineNumber = 1;
115        AslGbl_CurrentLineOffset = 0;
116
117        if (AslGbl_PreprocessOnly)
118        {
119            UtEndEvent (Event);
120            return (AE_OK);
121        }
122    }
123    UtEndEvent (Event);
124
125
126    /* Build the parse tree */
127
128    Event = UtBeginEvent ("Parse source code and build parse tree");
129    AslCompilerparse();
130    UtEndEvent (Event);
131
132    /* Check for parser-detected syntax errors */
133
134    if (AslGbl_SyntaxError)
135    {
136        AslError (ASL_ERROR, ASL_MSG_SYNTAX, NULL,
137            "Compiler aborting due to parser-detected syntax error(s)\n");
138
139        /* Flag this error in the FileNode for compilation summary */
140
141        FileNode = FlGetCurrentFileNode ();
142        FileNode->ParserErrorDetected = TRUE;
143        AslGbl_ParserErrorDetected = TRUE;
144        LsDumpParseTree ();
145        AePrintErrorLog(ASL_FILE_STDERR);
146
147        goto ErrorExit;
148    }
149
150    /* Did the parse tree get successfully constructed? */
151
152    if (!AslGbl_ParseTreeRoot)
153    {
154        /*
155         * If there are no errors, then we have some sort of
156         * internal problem.
157         */
158        AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL,
159            NULL, "- Could not resolve parse tree root node");
160
161        goto ErrorExit;
162    }
163
164    AePrintErrorLog(ASL_FILE_STDERR);
165
166    /* Flush out any remaining source after parse tree is complete */
167
168    Event = UtBeginEvent ("Flush source input");
169    CmFlushSourceCode ();
170
171    /* Prune the parse tree if requested (debug purposes only) */
172
173    if (AslGbl_PruneParseTree)
174    {
175        AslPruneParseTree (AslGbl_PruneDepth, AslGbl_PruneType);
176    }
177
178    /* Optional parse tree dump, compiler debug output only */
179
180    LsDumpParseTree ();
181
182    AslGbl_ParserErrorDetected = FALSE;
183    AslGbl_SyntaxError = FALSE;
184    UtEndEvent (Event);
185    UtEndEvent (FullCompile);
186
187    AslGbl_ParserErrorDetected = FALSE;
188    AslGbl_SyntaxError = FALSE;
189ErrorExit:
190    UtEndEvent (FullCompile);
191    return (AE_ERROR);
192}
193
194
195/*******************************************************************************
196 *
197 * FUNCTION:    CmDoAslMiddleAndBackEnd
198 *
199 * PARAMETERS:  None
200 *
201 * RETURN:      Status of middle-end and back-end
202 *
203 * DESCRIPTION: Perform compiler middle-end (type checking and semantic
204 *              analysis) and back-end (code generation)
205 *
206 ******************************************************************************/
207
208int
209CmDoAslMiddleAndBackEnd (
210    void)
211{
212    UINT8                   Event;
213    ACPI_STATUS             Status;
214
215
216    OpcGetIntegerWidth (AslGbl_ParseTreeRoot->Asl.Child);
217
218    /* Pre-process parse tree for any operator transforms */
219
220    Event = UtBeginEvent ("Parse tree transforms");
221    DbgPrint (ASL_DEBUG_OUTPUT, "\nParse tree transforms\n\n");
222    TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_TWICE,
223        TrAmlTransformWalkBegin, TrAmlTransformWalkEnd, NULL);
224    UtEndEvent (Event);
225
226    /* Generate AML opcodes corresponding to the parse tokens */
227
228    Event = UtBeginEvent ("Generate AML opcodes");
229    DbgPrint (ASL_DEBUG_OUTPUT, "Generating AML opcodes\n\n");
230    TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_UPWARD,
231        NULL, OpcAmlOpcodeWalk, NULL);
232    UtEndEvent (Event);
233
234
235    /* Interpret and generate all compile-time constants */
236
237    Event = UtBeginEvent ("Constant folding via AML interpreter");
238    DbgPrint (ASL_DEBUG_OUTPUT,
239        "Interpreting compile-time constant expressions\n\n");
240
241    if (AslGbl_FoldConstants)
242    {
243        TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_UPWARD,
244            NULL, OpcAmlConstantWalk, NULL);
245    }
246    else
247    {
248        DbgPrint (ASL_PARSE_OUTPUT, "    Optional folding disabled\n");
249    }
250    UtEndEvent (Event);
251
252    /* Update AML opcodes if necessary, after constant folding */
253
254    Event = UtBeginEvent ("Updating AML opcodes after constant folding");
255    DbgPrint (ASL_DEBUG_OUTPUT,
256        "Updating AML opcodes after constant folding\n\n");
257    TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_UPWARD,
258        NULL, OpcAmlOpcodeUpdateWalk, NULL);
259    UtEndEvent (Event);
260
261    /* Calculate all AML package lengths */
262
263    Event = UtBeginEvent ("Generate AML package lengths");
264    DbgPrint (ASL_DEBUG_OUTPUT, "Generating Package lengths\n\n");
265    TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_UPWARD, NULL,
266        LnPackageLengthWalk, NULL);
267    UtEndEvent (Event);
268
269    if (AslGbl_ParseOnlyFlag)
270    {
271        AePrintErrorLog (ASL_FILE_STDERR);
272        UtDisplaySummary (ASL_FILE_STDERR);
273        if (AslGbl_DebugFlag)
274        {
275            /* Print error summary to the stdout also */
276
277            AePrintErrorLog (ASL_FILE_STDOUT);
278            UtDisplaySummary (ASL_FILE_STDOUT);
279        }
280        return (0);
281    }
282
283    /*
284     * Create an internal namespace and use it as a symbol table
285     */
286
287    /* Namespace loading */
288
289    Event = UtBeginEvent ("Create ACPI Namespace");
290    DbgPrint (ASL_DEBUG_OUTPUT, "Creating ACPI Namespace\n\n");
291    Status = LdLoadNamespace (AslGbl_ParseTreeRoot);
292    UtEndEvent (Event);
293    if (ACPI_FAILURE (Status))
294    {
295        return (-1);
296    }
297
298    /* Namespace cross-reference */
299
300    AslGbl_NamespaceEvent = UtBeginEvent (
301        "Cross reference parse tree and Namespace");
302    DbgPrint (ASL_DEBUG_OUTPUT, "Cross referencing namespace\n\n");
303    Status = XfCrossReferenceNamespace ();
304    if (ACPI_FAILURE (Status))
305    {
306        return (-1);
307    }
308
309    /* Namespace - Check for non-referenced objects */
310
311    LkFindUnreferencedObjects ();
312    UtEndEvent (AslGbl_NamespaceEvent);
313
314    /* Resolve External Declarations */
315
316    Event = UtBeginEvent ("Resolve all Externals");
317    DbgPrint (ASL_DEBUG_OUTPUT, "\nResolve Externals\n\n");
318
319    if (AslGbl_DoExternalsInPlace)
320    {
321        TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_DOWNWARD,
322            ExAmlExternalWalkBegin, NULL, NULL);
323    }
324    else
325    {
326        TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_TWICE,
327            ExAmlExternalWalkBegin, ExAmlExternalWalkEnd, NULL);
328    }
329    UtEndEvent (Event);
330
331    /*
332     * Semantic analysis. This can happen only after the
333     * namespace has been loaded and cross-referenced.
334     *
335     * part one - check control methods
336     */
337    Event = UtBeginEvent ("Analyze control method return types");
338    AslGbl_AnalysisWalkInfo.MethodStack = NULL;
339
340    DbgPrint (ASL_DEBUG_OUTPUT, "Semantic analysis - Method analysis\n\n");
341
342    if (AslGbl_CrossReferenceOutput)
343    {
344        OtPrintHeaders ("Part 1: Object Reference Map "
345            "(Object references from within each control method)");
346    }
347
348    TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_TWICE,
349        MtMethodAnalysisWalkBegin,
350        MtMethodAnalysisWalkEnd, &AslGbl_AnalysisWalkInfo);
351    UtEndEvent (Event);
352
353    /* Generate the object cross-reference file if requested */
354
355    Event = UtBeginEvent ("Generate cross-reference file");
356    OtCreateXrefFile ();
357    UtEndEvent (Event);
358
359    /* Semantic error checking part two - typing of method returns */
360
361    Event = UtBeginEvent ("Determine object types returned by methods");
362    DbgPrint (ASL_DEBUG_OUTPUT, "Semantic analysis - Method typing\n\n");
363    TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_UPWARD,
364        NULL, AnMethodTypingWalkEnd, NULL);
365    UtEndEvent (Event);
366
367    /* Semantic error checking part three - operand type checking */
368
369    Event = UtBeginEvent ("Analyze AML operand types");
370    DbgPrint (ASL_DEBUG_OUTPUT,
371        "Semantic analysis - Operand type checking\n\n");
372    if (AslGbl_DoTypechecking)
373    {
374        TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_UPWARD,
375            NULL, AnOperandTypecheckWalkEnd, &AslGbl_AnalysisWalkInfo);
376    }
377    UtEndEvent (Event);
378
379    /* Semantic error checking part four - other miscellaneous checks */
380
381    Event = UtBeginEvent ("Miscellaneous analysis");
382    DbgPrint (ASL_DEBUG_OUTPUT, "Semantic analysis - miscellaneous\n\n");
383    TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_DOWNWARD,
384        AnOtherSemanticAnalysisWalkBegin,
385        NULL, &AslGbl_AnalysisWalkInfo);
386    UtEndEvent (Event);
387
388    /*
389     * ASL-/ASL+ converter: Gbl_ParseTreeRoot->CommentList contains the
390     * very last comment of a given ASL file because it's the last constructed
391     * node during compilation. We take the very last comment and save it in a
392     * global for it to be used by the disassembler.
393     */
394    if (AcpiGbl_CaptureComments)
395    {
396        AcpiGbl_LastListHead = AslGbl_ParseTreeRoot->Asl.CommentList;
397        AslGbl_ParseTreeRoot->Asl.CommentList = NULL;
398    }
399
400    /* Calculate all AML package lengths */
401
402    Event = UtBeginEvent ("Finish AML package length generation");
403    DbgPrint (ASL_DEBUG_OUTPUT, "Generating Package lengths\n\n");
404    TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_UPWARD, NULL,
405        LnInitLengthsWalk, NULL);
406    TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_UPWARD, NULL,
407        LnPackageLengthWalk, NULL);
408    UtEndEvent (Event);
409
410    /* Code generation - emit the AML */
411
412    Event = UtBeginEvent ("Generate AML code and write output files");
413    DbgPrint (ASL_DEBUG_OUTPUT, "Writing AML byte code\n\n");
414
415    AslGbl_CurrentDB = AslGbl_ParseTreeRoot->Asl.Child;
416
417    while (AslGbl_CurrentDB)
418    {
419        switch  (FlSwitchFileSet(AslGbl_CurrentDB->Asl.Filename))
420        {
421            case SWITCH_TO_DIFFERENT_FILE:
422                /*
423                 * Reset these parameters when definition blocks belong in
424                 * different files. If they belong in the same file, there is
425                 * no need to reset these parameters
426                 */
427                FlSeekFile (ASL_FILE_SOURCE_OUTPUT, 0);
428                AslGbl_SourceLine = 0;
429                AslGbl_NextError = AslGbl_ErrorLog;
430
431                /* fall-through */
432
433            case SWITCH_TO_SAME_FILE:
434
435                CgGenerateAmlOutput ();
436                CmDoOutputFiles ();
437                AslGbl_CurrentDB = AslGbl_CurrentDB->Asl.Next;
438
439                break;
440
441            default: /* FILE_NOT_FOUND */
442
443                /* The requested file could not be found. Get out of here */
444
445                AslGbl_CurrentDB = NULL;
446                break;
447        }
448    }
449    UtEndEvent (Event);
450
451    Event = UtBeginEvent ("Write optional output files");
452    UtEndEvent (Event);
453
454    return (0);
455}
456
457
458/*******************************************************************************
459 *
460 * FUNCTION:    AslCompilerSignon
461 *
462 * PARAMETERS:  FileId      - ID of the output file
463 *
464 * RETURN:      None
465 *
466 * DESCRIPTION: Display compiler signon
467 *
468 ******************************************************************************/
469
470void
471AslCompilerSignon (
472    UINT32                  FileId)
473{
474    char                    *Prefix = "";
475    char                    *UtilityName;
476
477
478    /* Set line prefix depending on the destination file type */
479
480    switch (FileId)
481    {
482    case ASL_FILE_ASM_SOURCE_OUTPUT:
483    case ASL_FILE_ASM_INCLUDE_OUTPUT:
484
485        Prefix = "; ";
486        break;
487
488    case ASL_FILE_HEX_OUTPUT:
489
490        if (AslGbl_HexOutputFlag == HEX_OUTPUT_ASM)
491        {
492            Prefix = "; ";
493        }
494        else if ((AslGbl_HexOutputFlag == HEX_OUTPUT_C) ||
495                 (AslGbl_HexOutputFlag == HEX_OUTPUT_ASL))
496        {
497            FlPrintFile (ASL_FILE_HEX_OUTPUT, "/*\n");
498            Prefix = " * ";
499        }
500        break;
501
502    case ASL_FILE_C_SOURCE_OUTPUT:
503    case ASL_FILE_C_OFFSET_OUTPUT:
504    case ASL_FILE_C_INCLUDE_OUTPUT:
505
506        Prefix = " * ";
507        break;
508
509    default:
510
511        /* No other output types supported */
512
513        break;
514    }
515
516    /* Running compiler or disassembler? */
517
518    if (AcpiGbl_DisasmFlag)
519    {
520        UtilityName = AML_DISASSEMBLER_NAME;
521    }
522    else
523    {
524        UtilityName = ASL_COMPILER_NAME;
525    }
526
527    /* Compiler signon with copyright */
528
529    FlPrintFile (FileId, "%s\n", Prefix);
530    FlPrintFile (FileId, ACPI_COMMON_HEADER (UtilityName, Prefix));
531}
532
533
534/*******************************************************************************
535 *
536 * FUNCTION:    AslCompilerFileHeader
537 *
538 * PARAMETERS:  FileId      - ID of the output file
539 *
540 * RETURN:      None
541 *
542 * DESCRIPTION: Header used at the beginning of output files
543 *
544 ******************************************************************************/
545
546void
547AslCompilerFileHeader (
548    UINT32                  FileId)
549{
550    char                    *NewTime;
551    time_t                  Aclock;
552    char                    *Prefix = "";
553
554
555    /* Set line prefix depending on the destination file type */
556
557    switch (FileId)
558    {
559    case ASL_FILE_ASM_SOURCE_OUTPUT:
560    case ASL_FILE_ASM_INCLUDE_OUTPUT:
561
562        Prefix = "; ";
563        break;
564
565    case ASL_FILE_HEX_OUTPUT:
566
567        if (AslGbl_HexOutputFlag == HEX_OUTPUT_ASM)
568        {
569            Prefix = "; ";
570        }
571        else if ((AslGbl_HexOutputFlag == HEX_OUTPUT_C) ||
572                 (AslGbl_HexOutputFlag == HEX_OUTPUT_ASL))
573        {
574            Prefix = " * ";
575        }
576        break;
577
578    case ASL_FILE_C_SOURCE_OUTPUT:
579    case ASL_FILE_C_OFFSET_OUTPUT:
580    case ASL_FILE_C_INCLUDE_OUTPUT:
581
582        Prefix = " * ";
583        break;
584
585    default:
586
587        /* No other output types supported */
588
589        break;
590    }
591
592    /* Compilation header with timestamp */
593
594    Aclock = time (NULL);
595    NewTime = ctime (&Aclock);
596
597    FlPrintFile (FileId,
598        "%sCompilation of \"%s\" -",
599        Prefix, AslGbl_Files[ASL_FILE_INPUT].Filename);
600
601    if (NewTime)
602    {
603        FlPrintFile (FileId, " %s%s\n", NewTime, Prefix);
604    }
605
606    switch (FileId)
607    {
608    case ASL_FILE_C_SOURCE_OUTPUT:
609    case ASL_FILE_C_OFFSET_OUTPUT:
610    case ASL_FILE_C_INCLUDE_OUTPUT:
611
612        FlPrintFile (FileId, " */\n");
613        break;
614
615    default:
616
617        /* Nothing to do for other output types */
618
619        break;
620    }
621}
622
623
624/*******************************************************************************
625 *
626 * FUNCTION:    CmFlushSourceCode
627 *
628 * PARAMETERS:  None
629 *
630 * RETURN:      None
631 *
632 * DESCRIPTION: Read in any remaining source code after the parse tree
633 *              has been constructed.
634 *
635 ******************************************************************************/
636
637static void
638CmFlushSourceCode (
639    void)
640{
641    char                    Buffer;
642
643
644    while (FlReadFile (ASL_FILE_INPUT, &Buffer, 1) != AE_ERROR)
645    {
646        AslInsertLineBuffer ((int) Buffer);
647    }
648
649    AslResetCurrentLineBuffer ();
650}
651
652
653/*******************************************************************************
654 *
655 * FUNCTION:    CmDoOutputFiles
656 *
657 * PARAMETERS:  None
658 *
659 * RETURN:      None.
660 *
661 * DESCRIPTION: Create all "listing" type files
662 *
663 ******************************************************************************/
664
665void
666CmDoOutputFiles (
667    void)
668{
669
670    /* Create listings and hex files */
671
672    LsDoListings ();
673    HxDoHexOutput ();
674
675    /* Dump the namespace to the .nsp file if requested */
676
677    (void) NsDisplayNamespace ();
678
679    /* Dump the device mapping file */
680
681    MpEmitMappingInfo ();
682}
683
684
685/*******************************************************************************
686 *
687 * FUNCTION:    CmDumpAllEvents
688 *
689 * PARAMETERS:  None
690 *
691 * RETURN:      None.
692 *
693 * DESCRIPTION: Dump all compiler events
694 *
695 ******************************************************************************/
696
697static void
698CmDumpAllEvents (
699    void)
700{
701    ASL_EVENT_INFO          *Event;
702    UINT32                  Delta;
703    UINT32                  MicroSeconds;
704    UINT32                  MilliSeconds;
705    UINT32                  i;
706
707
708    Event = AslGbl_Events;
709
710    DbgPrint (ASL_DEBUG_OUTPUT, "\n\nElapsed time for major events\n\n");
711    if (AslGbl_CompileTimesFlag)
712    {
713        printf ("\nElapsed time for major events\n\n");
714    }
715
716    for (i = 0; i < AslGbl_NextEvent; i++)
717    {
718        if (Event->Valid)
719        {
720            /* Delta will be in 100-nanosecond units */
721
722            Delta = (UINT32) (Event->EndTime - Event->StartTime);
723
724            MicroSeconds = Delta / ACPI_100NSEC_PER_USEC;
725            MilliSeconds = Delta / ACPI_100NSEC_PER_MSEC;
726
727            /* Round milliseconds up */
728
729            if ((MicroSeconds - (MilliSeconds * ACPI_USEC_PER_MSEC)) >= 500)
730            {
731                MilliSeconds++;
732            }
733
734            DbgPrint (ASL_DEBUG_OUTPUT, "%8u usec %8u msec - %s\n",
735                MicroSeconds, MilliSeconds, Event->EventName);
736
737            if (AslGbl_CompileTimesFlag)
738            {
739                printf ("%8u usec %8u msec - %s\n",
740                    MicroSeconds, MilliSeconds, Event->EventName);
741            }
742        }
743
744        Event++;
745    }
746}
747
748
749/*******************************************************************************
750 *
751 * FUNCTION:    CmCleanupAndExit
752 *
753 * PARAMETERS:  None
754 *
755 * RETURN:      None.
756 *
757 * DESCRIPTION: Close all open files and exit the compiler
758 *
759 ******************************************************************************/
760
761int
762CmCleanupAndExit (
763    void)
764{
765    int                     Status = 0;
766    BOOLEAN                 DeleteAmlFile = FALSE;
767    ASL_GLOBAL_FILE_NODE    *CurrentFileNode = AslGbl_FilesList;
768
769
770    /* Check if any errors occurred during compile */
771
772    (void) AslCheckForErrorExit ();
773
774    AePrintErrorLog (ASL_FILE_STDERR);
775    if (AslGbl_DebugFlag)
776    {
777        /* Print error summary to stdout also */
778
779        AePrintErrorLog (ASL_FILE_STDOUT);
780    }
781
782    /* Emit compile times if enabled */
783
784    CmDumpAllEvents ();
785
786    if (AslGbl_CompileTimesFlag)
787    {
788        printf ("\nMiscellaneous compile statistics\n\n");
789        printf ("%11u : %s\n", AslGbl_TotalParseNodes, "Parse nodes");
790        printf ("%11u : %s\n", AslGbl_NsLookupCount, "Namespace searches");
791        printf ("%11u : %s\n", AslGbl_TotalNamedObjects, "Named objects");
792        printf ("%11u : %s\n", AslGbl_TotalMethods, "Control methods");
793        printf ("%11u : %s\n", AslGbl_TotalAllocations, "Memory Allocations");
794        printf ("%11u : %s\n", AslGbl_TotalAllocated, "Total allocated memory");
795        printf ("%11u : %s\n", AslGbl_TotalFolds, "Constant subtrees folded");
796        printf ("\n");
797    }
798
799    if (AslGbl_NsLookupCount)
800    {
801        DbgPrint (ASL_DEBUG_OUTPUT,
802            "\n\nMiscellaneous compile statistics\n\n");
803
804        DbgPrint (ASL_DEBUG_OUTPUT,
805            "%32s : %u\n", "Total Namespace searches",
806            AslGbl_NsLookupCount);
807
808        DbgPrint (ASL_DEBUG_OUTPUT,
809            "%32s : %u usec\n", "Time per search", ((UINT32)
810            (AslGbl_Events[AslGbl_NamespaceEvent].EndTime -
811                AslGbl_Events[AslGbl_NamespaceEvent].StartTime) / 10) /
812                AslGbl_NsLookupCount);
813    }
814
815    if (AslGbl_ExceptionCount[ASL_ERROR] > ASL_MAX_ERROR_COUNT)
816    {
817        printf ("\nMaximum error count (%d) exceeded (aslcompile.c)\n",
818            ASL_MAX_ERROR_COUNT);
819    }
820
821    UtDisplaySummary (ASL_FILE_STDOUT);
822
823    /*
824     * Delete the AML file if there are errors and the force AML output option
825     * (-f) has not been used.
826     *
827     * Return -1 as a status of the compiler if no AML files are generated. If
828     * the AML file is generated in the presence of errors, return 0. In the
829     * latter case, the errors were ignored by the user so the compilation is
830     * considered successful.
831     */
832    if (AslGbl_ParserErrorDetected || AslGbl_PreprocessOnly ||
833        ((AslGbl_ExceptionCount[ASL_ERROR] > 0) &&
834        (!AslGbl_IgnoreErrors) &&
835        AslGbl_Files[ASL_FILE_AML_OUTPUT].Handle))
836    {
837        DeleteAmlFile = TRUE;
838        Status = -1;
839    }
840
841    /* Close all open files */
842
843    while (CurrentFileNode)
844    {
845        /*
846         * Set the program return status based on file errors. If there are any
847         * errors and during compilation, the command is not considered
848         * successful.
849         */
850        if (Status != -1 && !AslGbl_IgnoreErrors &&
851            CurrentFileNode->ParserErrorDetected)
852        {
853            Status = -1;
854        }
855
856        switch  (FlSwitchFileSet (CurrentFileNode->Files[ASL_FILE_INPUT].Filename))
857        {
858            case SWITCH_TO_SAME_FILE:
859            case SWITCH_TO_DIFFERENT_FILE:
860
861                CmFinishFiles (DeleteAmlFile);
862                CurrentFileNode = CurrentFileNode->Next;
863                break;
864
865            case FILE_NOT_FOUND:
866            default:
867
868                CurrentFileNode = NULL;
869                break;
870        }
871    }
872
873    /* Final cleanup after compiling one file */
874
875    if (!AslGbl_DoAslConversion)
876    {
877        UtDeleteLocalCaches ();
878    }
879
880    return (Status);
881}
882
883
884/*******************************************************************************
885 *
886 * FUNCTION:    CmFinishFiles
887 *
888 * PARAMETERS:  DeleteAmlFile
889 *
890 * RETURN:      None.
891 *
892 * DESCRIPTION: Close all open files, delete AML files depending on the
893 *              function parameter is true.
894 *
895 ******************************************************************************/
896
897static void
898CmFinishFiles(
899    BOOLEAN                 DeleteAmlFile)
900{
901    UINT32                  i;
902
903
904    /*
905     * Take care with the preprocessor file (.pre), it might be the same
906     * as the "input" file, depending on where the compiler has terminated
907     * or aborted. Prevent attempt to close the same file twice in
908     * loop below.
909     */
910    if (AslGbl_Files[ASL_FILE_PREPROCESSOR].Handle ==
911        AslGbl_Files[ASL_FILE_INPUT].Handle)
912    {
913        AslGbl_Files[ASL_FILE_PREPROCESSOR].Handle = NULL;
914    }
915
916    /* Close the standard I/O files */
917
918    for (i = ASL_FILE_INPUT; i < ASL_MAX_FILE_TYPE; i++)
919    {
920        /*
921         * Some files such as debug output files could be pointing to
922         * stderr or stdout. Leave these alone.
923         */
924        if (AslGbl_Files[i].Handle != stderr &&
925            AslGbl_Files[i].Handle != stdout)
926        {
927            FlCloseFile (i);
928        }
929    }
930
931    /* Delete AML file if there are errors */
932
933    if (DeleteAmlFile)
934    {
935        FlDeleteFile (ASL_FILE_AML_OUTPUT);
936    }
937
938    /* Delete the preprocessor temp file unless full debug was specified */
939
940    if (AslGbl_PreprocessFlag && !AslGbl_KeepPreprocessorTempFile)
941    {
942        FlDeleteFile (ASL_FILE_PREPROCESSOR);
943    }
944
945    /*
946     * Delete intermediate ("combined") source file (if -ls flag not set)
947     * This file is created during normal ASL/AML compiles. It is not
948     * created by the data table compiler.
949     *
950     * If the -ls flag is set, then the .SRC file should not be deleted.
951     * In this case, Gbl_SourceOutputFlag is set to TRUE.
952     *
953     * Note: Handles are cleared by FlCloseFile above, so we look at the
954     * filename instead, to determine if the .SRC file was actually
955     * created.
956     */
957    if (!AslGbl_SourceOutputFlag)
958    {
959        FlDeleteFile (ASL_FILE_SOURCE_OUTPUT);
960    }
961}
962