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 */
59int
60AslCompilerparse(
61    void);
62
63/* Local prototypes */
64
65static void
66CmFlushSourceCode (
67    void);
68
69static void
70FlConsumeAnsiComment (
71    FILE                    *Handle,
72    ASL_FILE_STATUS         *Status);
73
74static void
75FlConsumeNewComment (
76    FILE                    *Handle,
77    ASL_FILE_STATUS         *Status);
78
79static void
80CmDumpAllEvents (
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
96void
97AslCompilerSignon (
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
172void
173AslCompilerFileHeader (
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
259static void
260CmFlushSourceCode (
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
288static void
289FlConsumeAnsiComment (
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
332static void
333FlConsumeNewComment (
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
371ACPI_STATUS
372FlCheckForAcpiTable (
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
457ACPI_STATUS
458FlCheckForAscii (
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
562int
563CmDoCompile (
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    /* Check for parse errors */
597
598    Status = AslCheckForErrorExit ();
599    if (ACPI_FAILURE (Status))
600    {
601        fprintf (stderr, "Compiler aborting due to parser-detected syntax error(s)\n");
602        LsDumpParseTree ();
603        goto ErrorExit;
604    }
605
606    /* Did the parse tree get successfully constructed? */
607
608    if (!RootNode)
609    {
610        /*
611         * If there are no errors, then we have some sort of
612         * internal problem.
613         */
614        AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL,
615            NULL, "- Could not resolve parse tree root node");
616
617        goto ErrorExit;
618    }
619
620
621    /* Flush out any remaining source after parse tree is complete */
622
623    Event = UtBeginEvent ("Flush source input");
624    CmFlushSourceCode ();
625
626    /* Optional parse tree dump, compiler debug output only */
627
628    LsDumpParseTree ();
629
630    OpcGetIntegerWidth (RootNode);
631    UtEndEvent (Event);
632
633    /* Pre-process parse tree for any operator transforms */
634
635    Event = UtBeginEvent ("Parse tree transforms");
636    DbgPrint (ASL_DEBUG_OUTPUT, "\nParse tree transforms\n\n");
637    TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD,
638        TrAmlTransformWalk, NULL, NULL);
639    UtEndEvent (Event);
640
641    /* Generate AML opcodes corresponding to the parse tokens */
642
643    Event = UtBeginEvent ("Generate AML opcodes");
644    DbgPrint (ASL_DEBUG_OUTPUT, "\nGenerating AML opcodes\n\n");
645    TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD, NULL,
646        OpcAmlOpcodeWalk, NULL);
647    UtEndEvent (Event);
648
649    /*
650     * Now that the input is parsed, we can open the AML output file.
651     * Note: by default, the name of this file comes from the table descriptor
652     * within the input file.
653     */
654    Event = UtBeginEvent ("Open AML output file");
655    Status = FlOpenAmlOutputFile (Gbl_OutputFilenamePrefix);
656    UtEndEvent (Event);
657    if (ACPI_FAILURE (Status))
658    {
659        AePrintErrorLog (ASL_FILE_STDERR);
660        return (-1);
661    }
662
663    /* Interpret and generate all compile-time constants */
664
665    Event = UtBeginEvent ("Constant folding via AML interpreter");
666    DbgPrint (ASL_DEBUG_OUTPUT,
667        "\nInterpreting compile-time constant expressions\n\n");
668    TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD,
669        OpcAmlConstantWalk, NULL, NULL);
670    UtEndEvent (Event);
671
672    /* Update AML opcodes if necessary, after constant folding */
673
674    Event = UtBeginEvent ("Updating AML opcodes after constant folding");
675    DbgPrint (ASL_DEBUG_OUTPUT,
676        "\nUpdating AML opcodes after constant folding\n\n");
677    TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD,
678        NULL, OpcAmlOpcodeUpdateWalk, NULL);
679    UtEndEvent (Event);
680
681    /* Calculate all AML package lengths */
682
683    Event = UtBeginEvent ("Generate AML package lengths");
684    DbgPrint (ASL_DEBUG_OUTPUT, "\nGenerating Package lengths\n\n");
685    TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD, NULL,
686        LnPackageLengthWalk, NULL);
687    UtEndEvent (Event);
688
689    if (Gbl_ParseOnlyFlag)
690    {
691        AePrintErrorLog (ASL_FILE_STDERR);
692        UtDisplaySummary (ASL_FILE_STDERR);
693        if (Gbl_DebugFlag)
694        {
695            /* Print error summary to the stdout also */
696
697            AePrintErrorLog (ASL_FILE_STDOUT);
698            UtDisplaySummary (ASL_FILE_STDOUT);
699        }
700        UtEndEvent (FullCompile);
701        return (0);
702    }
703
704    /*
705     * Create an internal namespace and use it as a symbol table
706     */
707
708    /* Namespace loading */
709
710    Event = UtBeginEvent ("Create ACPI Namespace");
711    Status = LdLoadNamespace (RootNode);
712    UtEndEvent (Event);
713    if (ACPI_FAILURE (Status))
714    {
715        goto ErrorExit;
716    }
717
718    /* Namespace cross-reference */
719
720    AslGbl_NamespaceEvent = UtBeginEvent ("Cross reference parse tree and Namespace");
721    Status = XfCrossReferenceNamespace ();
722    if (ACPI_FAILURE (Status))
723    {
724        goto ErrorExit;
725    }
726
727    /* Namespace - Check for non-referenced objects */
728
729    LkFindUnreferencedObjects ();
730    UtEndEvent (AslGbl_NamespaceEvent);
731
732    /*
733     * Semantic analysis. This can happen only after the
734     * namespace has been loaded and cross-referenced.
735     *
736     * part one - check control methods
737     */
738    Event = UtBeginEvent ("Analyze control method return types");
739    AnalysisWalkInfo.MethodStack = NULL;
740
741    DbgPrint (ASL_DEBUG_OUTPUT, "\nSemantic analysis - Method analysis\n\n");
742    TrWalkParseTree (RootNode, ASL_WALK_VISIT_TWICE,
743        MtMethodAnalysisWalkBegin,
744        MtMethodAnalysisWalkEnd, &AnalysisWalkInfo);
745    UtEndEvent (Event);
746
747    /* Semantic error checking part two - typing of method returns */
748
749    Event = UtBeginEvent ("Determine object types returned by methods");
750    DbgPrint (ASL_DEBUG_OUTPUT, "\nSemantic analysis - Method typing\n\n");
751    TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD,
752        NULL, AnMethodTypingWalkEnd, NULL);
753    UtEndEvent (Event);
754
755    /* Semantic error checking part three - operand type checking */
756
757    Event = UtBeginEvent ("Analyze AML operand types");
758    DbgPrint (ASL_DEBUG_OUTPUT, "\nSemantic analysis - Operand type checking\n\n");
759    TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD,
760        NULL, AnOperandTypecheckWalkEnd, &AnalysisWalkInfo);
761    UtEndEvent (Event);
762
763    /* Semantic error checking part four - other miscellaneous checks */
764
765    Event = UtBeginEvent ("Miscellaneous analysis");
766    DbgPrint (ASL_DEBUG_OUTPUT, "\nSemantic analysis - miscellaneous\n\n");
767    TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD,
768        AnOtherSemanticAnalysisWalkBegin,
769        NULL, &AnalysisWalkInfo);
770    UtEndEvent (Event);
771
772    /* Calculate all AML package lengths */
773
774    Event = UtBeginEvent ("Finish AML package length generation");
775    DbgPrint (ASL_DEBUG_OUTPUT, "\nGenerating Package lengths\n\n");
776    TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD, NULL,
777        LnInitLengthsWalk, NULL);
778    TrWalkParseTree (RootNode, ASL_WALK_VISIT_UPWARD, NULL,
779        LnPackageLengthWalk, NULL);
780    UtEndEvent (Event);
781
782    /* Code generation - emit the AML */
783
784    Event = UtBeginEvent ("Generate AML code and write output files");
785    CgGenerateAmlOutput ();
786    UtEndEvent (Event);
787
788    Event = UtBeginEvent ("Write optional output files");
789    CmDoOutputFiles ();
790    UtEndEvent (Event);
791
792    UtEndEvent (FullCompile);
793    CmCleanupAndExit ();
794    return (0);
795
796ErrorExit:
797    UtEndEvent (FullCompile);
798    CmCleanupAndExit ();
799    return (-1);
800}
801
802
803/*******************************************************************************
804 *
805 * FUNCTION:    CmDoOutputFiles
806 *
807 * PARAMETERS:  None
808 *
809 * RETURN:      None.
810 *
811 * DESCRIPTION: Create all "listing" type files
812 *
813 ******************************************************************************/
814
815void
816CmDoOutputFiles (
817    void)
818{
819
820    /* Create listings and hex files */
821
822    LsDoListings ();
823    HxDoHexOutput ();
824
825    /* Dump the namespace to the .nsp file if requested */
826
827    (void) NsDisplayNamespace ();
828}
829
830
831/*******************************************************************************
832 *
833 * FUNCTION:    CmDumpAllEvents
834 *
835 * PARAMETERS:  None
836 *
837 * RETURN:      None.
838 *
839 * DESCRIPTION: Dump all compiler events
840 *
841 ******************************************************************************/
842
843static void
844CmDumpAllEvents (
845    void)
846{
847    ASL_EVENT_INFO          *Event;
848    UINT32                  Delta;
849    UINT32                  USec;
850    UINT32                  MSec;
851    UINT32                  i;
852
853
854    Event = AslGbl_Events;
855
856    DbgPrint (ASL_DEBUG_OUTPUT, "\n\nElapsed time for major events\n\n");
857    if (Gbl_CompileTimesFlag)
858    {
859        printf ("\nElapsed time for major events\n\n");
860    }
861
862    for (i = 0; i < AslGbl_NextEvent; i++)
863    {
864        if (Event->Valid)
865        {
866            /* Delta will be in 100-nanosecond units */
867
868            Delta = (UINT32) (Event->EndTime - Event->StartTime);
869
870            USec = Delta / ACPI_100NSEC_PER_USEC;
871            MSec = Delta / ACPI_100NSEC_PER_MSEC;
872
873            /* Round milliseconds up */
874
875            if ((USec - (MSec * ACPI_USEC_PER_MSEC)) >= 500)
876            {
877                MSec++;
878            }
879
880            DbgPrint (ASL_DEBUG_OUTPUT, "%8u usec %8u msec - %s\n",
881                USec, MSec, Event->EventName);
882
883            if (Gbl_CompileTimesFlag)
884            {
885                printf ("%8u usec %8u msec - %s\n",
886                    USec, MSec, Event->EventName);
887            }
888        }
889
890        Event++;
891    }
892}
893
894
895/*******************************************************************************
896 *
897 * FUNCTION:    CmCleanupAndExit
898 *
899 * PARAMETERS:  None
900 *
901 * RETURN:      None.
902 *
903 * DESCRIPTION: Close all open files and exit the compiler
904 *
905 ******************************************************************************/
906
907void
908CmCleanupAndExit (
909    void)
910{
911    UINT32                  i;
912    BOOLEAN                 DeleteAmlFile = FALSE;
913
914
915    AePrintErrorLog (ASL_FILE_STDERR);
916    if (Gbl_DebugFlag)
917    {
918        /* Print error summary to stdout also */
919
920        AePrintErrorLog (ASL_FILE_STDOUT);
921    }
922
923    /* Emit compile times if enabled */
924
925    CmDumpAllEvents ();
926
927    if (Gbl_CompileTimesFlag)
928    {
929        printf ("\nMiscellaneous compile statistics\n\n");
930        printf ("%11u : %s\n", TotalParseNodes, "Parse nodes");
931        printf ("%11u : %s\n", Gbl_NsLookupCount, "Namespace searches");
932        printf ("%11u : %s\n", TotalNamedObjects, "Named objects");
933        printf ("%11u : %s\n", TotalMethods, "Control methods");
934        printf ("%11u : %s\n", TotalAllocations, "Memory Allocations");
935        printf ("%11u : %s\n", TotalAllocated, "Total allocated memory");
936        printf ("%11u : %s\n", TotalFolds, "Constant subtrees folded");
937        printf ("\n");
938    }
939
940    if (Gbl_NsLookupCount)
941    {
942        DbgPrint (ASL_DEBUG_OUTPUT,
943            "\n\nMiscellaneous compile statistics\n\n");
944
945        DbgPrint (ASL_DEBUG_OUTPUT,
946            "%32s : %u\n", "Total Namespace searches",
947            Gbl_NsLookupCount);
948
949        DbgPrint (ASL_DEBUG_OUTPUT,
950            "%32s : %u usec\n", "Time per search", ((UINT32)
951            (AslGbl_Events[AslGbl_NamespaceEvent].EndTime -
952                AslGbl_Events[AslGbl_NamespaceEvent].StartTime) / 10) /
953                Gbl_NsLookupCount);
954    }
955
956    if (Gbl_ExceptionCount[ASL_ERROR] > ASL_MAX_ERROR_COUNT)
957    {
958        printf ("\nMaximum error count (%u) exceeded\n",
959            ASL_MAX_ERROR_COUNT);
960    }
961
962    UtDisplaySummary (ASL_FILE_STDOUT);
963
964    /*
965     * We will delete the AML file if there are errors and the
966     * force AML output option has not been used.
967     */
968    if ((Gbl_ExceptionCount[ASL_ERROR] > 0) && (!Gbl_IgnoreErrors) &&
969        Gbl_Files[ASL_FILE_AML_OUTPUT].Handle)
970    {
971        DeleteAmlFile = TRUE;
972    }
973
974    /* Close all open files */
975
976    /*
977     * Take care with the preprocessor file (.i), it might be the same
978     * as the "input" file, depending on where the compiler has terminated
979     * or aborted. Prevent attempt to close the same file twice in
980     * loop below.
981     */
982    if (Gbl_Files[ASL_FILE_PREPROCESSOR].Handle ==
983        Gbl_Files[ASL_FILE_INPUT].Handle)
984    {
985        Gbl_Files[ASL_FILE_PREPROCESSOR].Handle = NULL;
986    }
987
988    /* Close the standard I/O files */
989
990    for (i = ASL_FILE_INPUT; i < ASL_MAX_FILE_TYPE; i++)
991    {
992        FlCloseFile (i);
993    }
994
995    /* Delete AML file if there are errors */
996
997    if (DeleteAmlFile)
998    {
999        FlDeleteFile (ASL_FILE_AML_OUTPUT);
1000    }
1001
1002    /* Delete the preprocessor output file (.i) unless -li flag is set */
1003
1004    if (!Gbl_PreprocessorOutputFlag &&
1005        Gbl_PreprocessFlag)
1006    {
1007        FlDeleteFile (ASL_FILE_PREPROCESSOR);
1008    }
1009
1010    /*
1011     * Delete intermediate ("combined") source file (if -ls flag not set)
1012     * This file is created during normal ASL/AML compiles. It is not
1013     * created by the data table compiler.
1014     *
1015     * If the -ls flag is set, then the .SRC file should not be deleted.
1016     * In this case, Gbl_SourceOutputFlag is set to TRUE.
1017     *
1018     * Note: Handles are cleared by FlCloseFile above, so we look at the
1019     * filename instead, to determine if the .SRC file was actually
1020     * created.
1021     *
1022     * TBD: SourceOutput should be .TMP, then rename if we want to keep it?
1023     */
1024    if (!Gbl_SourceOutputFlag)
1025    {
1026        FlDeleteFile (ASL_FILE_SOURCE_OUTPUT);
1027    }
1028}
1029