asllisting.c revision 243347
1/******************************************************************************
2 *
3 * Module Name: asllisting - Listing file generation
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2012, 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
45#include <contrib/dev/acpica/compiler/aslcompiler.h>
46#include "aslcompiler.y.h"
47#include <contrib/dev/acpica/include/amlcode.h>
48#include <contrib/dev/acpica/include/acparser.h>
49#include <contrib/dev/acpica/include/acnamesp.h>
50
51#define _COMPONENT          ACPI_COMPILER
52        ACPI_MODULE_NAME    ("aslisting")
53
54/* Local prototypes */
55
56static void
57LsDumpAscii (
58    UINT32                  FileId,
59    UINT32                  Count,
60    UINT8                   *Buffer);
61
62static void
63LsDumpAsciiInComment (
64    UINT32                  FileId,
65    UINT32                  Count,
66    UINT8                   *Buffer);
67
68static ACPI_STATUS
69LsAmlListingWalk (
70    ACPI_PARSE_OBJECT       *Op,
71    UINT32                  Level,
72    void                    *Context);
73
74static void
75LsGenerateListing (
76    UINT32                  FileId);
77
78static void
79LsPushNode (
80    char                    *Filename);
81
82static ASL_LISTING_NODE *
83LsPopNode (
84    void);
85
86static void
87LsCheckException (
88    UINT32                  LineNumber,
89    UINT32                  FileId);
90
91static void
92LsFlushListingBuffer (
93    UINT32                  FileId);
94
95static void
96LsWriteListingHexBytes (
97    UINT8                   *Buffer,
98    UINT32                  Length,
99    UINT32                  FileId);
100
101static UINT32
102LsWriteOneSourceLine (
103    UINT32                  FileId);
104
105static void
106LsFinishSourceListing (
107    UINT32                  FileId);
108
109static void
110LsWriteSourceLines (
111    UINT32                  ToLineNumber,
112    UINT32                  ToLogicalLineNumber,
113    UINT32                  FileId);
114
115static void
116LsWriteNodeToListing (
117    ACPI_PARSE_OBJECT       *Op,
118    UINT32                  FileId);
119
120static void
121LsDoHexOutputC (
122    void);
123
124static void
125LsDoHexOutputAsm (
126    void);
127
128static void
129LsDoHexOutputAsl (
130    void);
131
132static ACPI_STATUS
133LsTreeWriteWalk (
134    ACPI_PARSE_OBJECT       *Op,
135    UINT32                  Level,
136    void                    *Context);
137
138static UINT32
139LsReadAmlOutputFile (
140    UINT8                   *Buffer);
141
142
143/*******************************************************************************
144 *
145 * FUNCTION:    LsTreeWriteWalk
146 *
147 * PARAMETERS:  ASL_WALK_CALLBACK
148 *
149 *
150 * RETURN:      None.
151 *
152 * DESCRIPTION: Dump entire parse tree, for compiler debug only
153 *
154 ******************************************************************************/
155
156static ACPI_STATUS
157LsTreeWriteWalk (
158    ACPI_PARSE_OBJECT       *Op,
159    UINT32                  Level,
160    void                    *Context)
161{
162
163    /* Debug output */
164
165    DbgPrint (ASL_TREE_OUTPUT,
166        "%5.5d [%2d]", Op->Asl.LogicalLineNumber, Level);
167    UtPrintFormattedName (Op->Asl.ParseOpcode, Level);
168
169
170    DbgPrint (ASL_TREE_OUTPUT, "\n");
171    return (AE_OK);
172}
173
174
175void
176LsDumpParseTree (
177    void)
178{
179
180    if (!Gbl_DebugFlag)
181    {
182        return;
183    }
184
185    DbgPrint (ASL_TREE_OUTPUT, "\nOriginal parse tree from parser:\n\n");
186    TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD,
187        LsTreeWriteWalk, NULL, NULL);
188}
189
190
191/*******************************************************************************
192 *
193 * FUNCTION:    LsDumpAscii
194 *
195 * PARAMETERS:  FileId          - ID of current listing file
196 *              Count           - Number of bytes to convert
197 *              Buffer          - Buffer of bytes to convert
198 *
199 * RETURN:      None.
200 *
201 * DESCRIPTION: Convert hex bytes to ascii
202 *
203 ******************************************************************************/
204
205static void
206LsDumpAscii (
207    UINT32                  FileId,
208    UINT32                  Count,
209    UINT8                   *Buffer)
210{
211    UINT8                   BufChar;
212    UINT32                  i;
213
214
215    FlPrintFile (FileId, "    \"");
216    for (i = 0; i < Count; i++)
217    {
218        BufChar = Buffer[i];
219        if (isprint (BufChar))
220        {
221            FlPrintFile (FileId, "%c", BufChar);
222        }
223        else
224        {
225            /* Not a printable character, just put out a dot */
226
227            FlPrintFile (FileId, ".");
228        }
229    }
230    FlPrintFile (FileId, "\"");
231}
232
233
234/*******************************************************************************
235 *
236 * FUNCTION:    LsDumpAsciiInComment
237 *
238 * PARAMETERS:  FileId          - ID of current listing file
239 *              Count           - Number of bytes to convert
240 *              Buffer          - Buffer of bytes to convert
241 *
242 * RETURN:      None.
243 *
244 * DESCRIPTION: Convert hex bytes to ascii
245 *
246 ******************************************************************************/
247
248static void
249LsDumpAsciiInComment (
250    UINT32                  FileId,
251    UINT32                  Count,
252    UINT8                   *Buffer)
253{
254    UINT8                   BufChar = 0;
255    UINT8                   LastChar;
256    UINT32                  i;
257
258
259    FlPrintFile (FileId, "    \"");
260    for (i = 0; i < Count; i++)
261    {
262        LastChar = BufChar;
263        BufChar = Buffer[i];
264
265        if (isprint (BufChar))
266        {
267            /* Handle embedded C comment sequences */
268
269            if (((LastChar == '*') && (BufChar == '/')) ||
270                ((LastChar == '/') && (BufChar == '*')))
271            {
272                /* Insert a space to break the sequence */
273
274                FlPrintFile (FileId, ".", BufChar);
275            }
276
277            FlPrintFile (FileId, "%c", BufChar);
278        }
279        else
280        {
281            /* Not a printable character, just put out a dot */
282
283            FlPrintFile (FileId, ".");
284        }
285    }
286    FlPrintFile (FileId, "\"");
287}
288
289
290/*******************************************************************************
291 *
292 * FUNCTION:    LsAmlListingWalk
293 *
294 * PARAMETERS:  ASL_WALK_CALLBACK
295 *
296 * RETURN:      Status
297 *
298 * DESCRIPTION: Process one node during a listing file generation.
299 *
300 ******************************************************************************/
301
302static ACPI_STATUS
303LsAmlListingWalk (
304    ACPI_PARSE_OBJECT       *Op,
305    UINT32                  Level,
306    void                    *Context)
307{
308    UINT8                   FileByte;
309    UINT32                  i;
310    UINT32                  FileId = (UINT32) ACPI_TO_INTEGER (Context);
311
312
313    LsWriteNodeToListing (Op, FileId);
314
315    if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DATA)
316    {
317        /* Buffer is a resource template, don't dump the data all at once */
318
319        return (AE_OK);
320    }
321
322    /* Write the hex bytes to the listing file(s) (if requested) */
323
324    for (i = 0; i < Op->Asl.FinalAmlLength; i++)
325    {
326        if (ACPI_FAILURE (FlReadFile (ASL_FILE_AML_OUTPUT, &FileByte, 1)))
327        {
328            FlFileError (ASL_FILE_AML_OUTPUT, ASL_MSG_READ);
329            AslAbort ();
330        }
331        LsWriteListingHexBytes (&FileByte, 1, FileId);
332    }
333
334    return (AE_OK);
335}
336
337
338/*******************************************************************************
339 *
340 * FUNCTION:    LsGenerateListing
341 *
342 * PARAMETERS:  FileId      - ID of listing file
343 *
344 * RETURN:      None
345 *
346 * DESCRIPTION: Generate a listing file. This can be one of the several types
347 *              of "listings" supported.
348 *
349 ******************************************************************************/
350
351static void
352LsGenerateListing (
353    UINT32                  FileId)
354{
355
356    /* Start at the beginning of both the source and AML files */
357
358    FlSeekFile (ASL_FILE_SOURCE_OUTPUT, 0);
359    FlSeekFile (ASL_FILE_AML_OUTPUT, 0);
360    Gbl_SourceLine = 0;
361    Gbl_CurrentHexColumn = 0;
362    LsPushNode (Gbl_Files[ASL_FILE_INPUT].Filename);
363
364    /* Process all parse nodes */
365
366    TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD, LsAmlListingWalk,
367                        NULL, (void *) ACPI_TO_POINTER (FileId));
368
369    /* Final processing */
370
371    LsFinishSourceListing (FileId);
372}
373
374
375/*******************************************************************************
376 *
377 * FUNCTION:    LsDoListings
378 *
379 * PARAMETERS:  None.
380 *
381 * RETURN:      None
382 *
383 * DESCRIPTION: Generate all requested listing files.
384 *
385 ******************************************************************************/
386
387void
388LsDoListings (
389    void)
390{
391
392    if (Gbl_C_OutputFlag)
393    {
394        LsGenerateListing (ASL_FILE_C_SOURCE_OUTPUT);
395    }
396
397    if (Gbl_ListingFlag)
398    {
399        LsGenerateListing (ASL_FILE_LISTING_OUTPUT);
400    }
401
402    if (Gbl_AsmOutputFlag)
403    {
404        LsGenerateListing (ASL_FILE_ASM_SOURCE_OUTPUT);
405    }
406
407    if (Gbl_C_IncludeOutputFlag)
408    {
409        LsGenerateListing (ASL_FILE_C_INCLUDE_OUTPUT);
410    }
411
412    if (Gbl_AsmIncludeOutputFlag)
413    {
414        LsGenerateListing (ASL_FILE_ASM_INCLUDE_OUTPUT);
415    }
416}
417
418
419/*******************************************************************************
420 *
421 * FUNCTION:    LsPushNode
422 *
423 * PARAMETERS:  Filename        - Pointer to the include filename
424 *
425 * RETURN:      None
426 *
427 * DESCRIPTION: Push a listing node on the listing/include file stack. This
428 *              stack enables tracking of include files (infinitely nested)
429 *              and resumption of the listing of the parent file when the
430 *              include file is finished.
431 *
432 ******************************************************************************/
433
434static void
435LsPushNode (
436    char                    *Filename)
437{
438    ASL_LISTING_NODE        *Lnode;
439
440
441    /* Create a new node */
442
443    Lnode = UtLocalCalloc (sizeof (ASL_LISTING_NODE));
444
445    /* Initialize */
446
447    Lnode->Filename = Filename;
448    Lnode->LineNumber = 0;
449
450    /* Link (push) */
451
452    Lnode->Next = Gbl_ListingNode;
453    Gbl_ListingNode = Lnode;
454}
455
456
457/*******************************************************************************
458 *
459 * FUNCTION:    LsPopNode
460 *
461 * PARAMETERS:  None
462 *
463 * RETURN:      List head after current head is popped off
464 *
465 * DESCRIPTION: Pop the current head of the list, free it, and return the
466 *              next node on the stack (the new current node).
467 *
468 ******************************************************************************/
469
470static ASL_LISTING_NODE *
471LsPopNode (
472    void)
473{
474    ASL_LISTING_NODE        *Lnode;
475
476
477    /* Just grab the node at the head of the list */
478
479    Lnode = Gbl_ListingNode;
480    if ((!Lnode) ||
481        (!Lnode->Next))
482    {
483        AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, NULL,
484            "Could not pop empty listing stack");
485        return (Gbl_ListingNode);
486    }
487
488    Gbl_ListingNode = Lnode->Next;
489    ACPI_FREE (Lnode);
490
491    /* New "Current" node is the new head */
492
493    return (Gbl_ListingNode);
494}
495
496
497/*******************************************************************************
498 *
499 * FUNCTION:    LsCheckException
500 *
501 * PARAMETERS:  LineNumber          - Current logical (cumulative) line #
502 *              FileId              - ID of output listing file
503 *
504 * RETURN:      None
505 *
506 * DESCRIPTION: Check if there is an exception for this line, and if there is,
507 *              put it in the listing immediately. Handles multiple errors
508 *              per line. Gbl_NextError points to the next error in the
509 *              sorted (by line #) list of compile errors/warnings.
510 *
511 ******************************************************************************/
512
513static void
514LsCheckException (
515    UINT32                  LineNumber,
516    UINT32                  FileId)
517{
518
519    if ((!Gbl_NextError) ||
520        (LineNumber < Gbl_NextError->LogicalLineNumber ))
521    {
522        return;
523    }
524
525    /* Handle multiple errors per line */
526
527    if (FileId == ASL_FILE_LISTING_OUTPUT)
528    {
529        while (Gbl_NextError &&
530              (LineNumber >= Gbl_NextError->LogicalLineNumber))
531        {
532            AePrintException (FileId, Gbl_NextError, "\n[****iasl****]\n");
533
534            Gbl_NextError = Gbl_NextError->Next;
535        }
536
537        FlPrintFile (FileId, "\n");
538    }
539}
540
541
542/*******************************************************************************
543 *
544 * FUNCTION:    LsFlushListingBuffer
545 *
546 * PARAMETERS:  FileId          - ID of the listing file
547 *
548 * RETURN:      None
549 *
550 * DESCRIPTION: Flush out the current contents of the 16-byte hex AML code
551 *              buffer. Usually called at the termination of a single line
552 *              of source code or when the buffer is full.
553 *
554 ******************************************************************************/
555
556static void
557LsFlushListingBuffer (
558    UINT32                  FileId)
559{
560    UINT32                  i;
561
562
563    if (Gbl_CurrentHexColumn == 0)
564    {
565        return;
566    }
567
568    /* Write the hex bytes */
569
570    switch (FileId)
571    {
572    case ASL_FILE_LISTING_OUTPUT:
573
574        for (i = 0; i < Gbl_CurrentHexColumn; i++)
575        {
576            FlPrintFile (FileId, "%2.2X ", Gbl_AmlBuffer[i]);
577        }
578
579        for (i = 0; i < ((HEX_LISTING_LINE_SIZE - Gbl_CurrentHexColumn) * 3); i++)
580        {
581            FlWriteFile (FileId, ".", 1);
582        }
583
584        /* Write the ASCII character associated with each of the bytes */
585
586        LsDumpAscii (FileId, Gbl_CurrentHexColumn, Gbl_AmlBuffer);
587        break;
588
589
590    case ASL_FILE_ASM_SOURCE_OUTPUT:
591
592        for (i = 0; i < Gbl_CurrentHexColumn; i++)
593        {
594            if (i > 0)
595            {
596                FlPrintFile (FileId, ",");
597            }
598            FlPrintFile (FileId, "0%2.2Xh", Gbl_AmlBuffer[i]);
599        }
600
601        for (i = 0; i < ((HEX_LISTING_LINE_SIZE - Gbl_CurrentHexColumn) * 5); i++)
602        {
603            FlWriteFile (FileId, " ", 1);
604        }
605
606        FlPrintFile (FileId, "  ;%8.8X",
607            Gbl_CurrentAmlOffset - HEX_LISTING_LINE_SIZE);
608
609        /* Write the ASCII character associated with each of the bytes */
610
611        LsDumpAscii (FileId, Gbl_CurrentHexColumn, Gbl_AmlBuffer);
612        break;
613
614
615    case ASL_FILE_C_SOURCE_OUTPUT:
616
617        for (i = 0; i < Gbl_CurrentHexColumn; i++)
618        {
619            FlPrintFile (FileId, "0x%2.2X,", Gbl_AmlBuffer[i]);
620        }
621
622        for (i = 0; i < ((HEX_LISTING_LINE_SIZE - Gbl_CurrentHexColumn) * 5); i++)
623        {
624            FlWriteFile (FileId, " ", 1);
625        }
626
627        FlPrintFile (FileId, "    /* %8.8X",
628            Gbl_CurrentAmlOffset - HEX_LISTING_LINE_SIZE);
629
630        /* Write the ASCII character associated with each of the bytes */
631
632        LsDumpAsciiInComment (FileId, Gbl_CurrentHexColumn, Gbl_AmlBuffer);
633        FlPrintFile (FileId, " */");
634        break;
635
636    default:
637        /* No other types supported */
638        return;
639    }
640
641    FlPrintFile (FileId, "\n");
642
643    Gbl_CurrentHexColumn = 0;
644    Gbl_HexBytesWereWritten = TRUE;
645}
646
647
648/*******************************************************************************
649 *
650 * FUNCTION:    LsWriteListingHexBytes
651 *
652 * PARAMETERS:  Buffer          - AML code buffer
653 *              Length          - Number of AML bytes to write
654 *              FileId          - ID of current listing file.
655 *
656 * RETURN:      None
657 *
658 * DESCRIPTION: Write the contents of the AML buffer to the listing file via
659 *              the listing buffer. The listing buffer is flushed every 16
660 *              AML bytes.
661 *
662 ******************************************************************************/
663
664static void
665LsWriteListingHexBytes (
666    UINT8                   *Buffer,
667    UINT32                  Length,
668    UINT32                  FileId)
669{
670    UINT32                  i;
671
672
673    /* Transfer all requested bytes */
674
675    for (i = 0; i < Length; i++)
676    {
677        /* Print line header when buffer is empty */
678
679        if (Gbl_CurrentHexColumn == 0)
680        {
681            if (Gbl_HasIncludeFiles)
682            {
683                FlPrintFile (FileId, "%*s", 10, " ");
684            }
685
686            switch (FileId)
687            {
688            case ASL_FILE_LISTING_OUTPUT:
689
690                FlPrintFile (FileId, "%8.8X....", Gbl_CurrentAmlOffset);
691                break;
692
693            case ASL_FILE_ASM_SOURCE_OUTPUT:
694
695                FlPrintFile (FileId, "    db ");
696                break;
697
698            case ASL_FILE_C_SOURCE_OUTPUT:
699
700                FlPrintFile (FileId, "        ");
701                break;
702
703            default:
704                /* No other types supported */
705                return;
706            }
707        }
708
709        /* Transfer AML byte and update counts */
710
711        Gbl_AmlBuffer[Gbl_CurrentHexColumn] = Buffer[i];
712
713        Gbl_CurrentHexColumn++;
714        Gbl_CurrentAmlOffset++;
715
716        /* Flush buffer when it is full */
717
718        if (Gbl_CurrentHexColumn >= HEX_LISTING_LINE_SIZE)
719        {
720            LsFlushListingBuffer (FileId);
721        }
722    }
723}
724
725
726/*******************************************************************************
727 *
728 * FUNCTION:    LsWriteOneSourceLine
729 *
730 * PARAMETERS:  FileID          - ID of current listing file
731 *
732 * RETURN:      FALSE on EOF (input source file), TRUE otherwise
733 *
734 * DESCRIPTION: Read one line from the input source file and echo it to the
735 *              listing file, prefixed with the line number, and if the source
736 *              file contains include files, prefixed with the current filename
737 *
738 ******************************************************************************/
739
740static UINT32
741LsWriteOneSourceLine (
742    UINT32                  FileId)
743{
744    UINT8                   FileByte;
745
746
747    Gbl_SourceLine++;
748    Gbl_ListingNode->LineNumber++;
749
750    if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
751    {
752        FlPrintFile (FileId, "     *");
753    }
754    if (FileId == ASL_FILE_ASM_SOURCE_OUTPUT)
755    {
756        FlPrintFile (FileId, "; ");
757    }
758
759    if (Gbl_HasIncludeFiles)
760    {
761        /*
762         * This file contains "include" statements, print the current
763         * filename and line number within the current file
764         */
765        FlPrintFile (FileId, "%12s %5d....",
766                    Gbl_ListingNode->Filename, Gbl_ListingNode->LineNumber);
767    }
768    else
769    {
770        /* No include files, just print the line number */
771
772        FlPrintFile (FileId, "%8d....", Gbl_SourceLine);
773    }
774
775    /* Read one line (up to a newline or EOF) */
776
777    while (FlReadFile (ASL_FILE_SOURCE_OUTPUT, &FileByte, 1) == AE_OK)
778    {
779        if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
780        {
781            if (FileByte == '/')
782            {
783                FileByte = '*';
784            }
785        }
786
787        FlWriteFile (FileId, &FileByte, 1);
788        if (FileByte == '\n')
789        {
790            /*
791             * Check if an error occurred on this source line during the compile.
792             * If so, we print the error message after the source line.
793             */
794            LsCheckException (Gbl_SourceLine, FileId);
795            return (1);
796        }
797    }
798
799    /* EOF on the input file was reached */
800
801    return (0);
802}
803
804
805/*******************************************************************************
806 *
807 * FUNCTION:    LsFinishSourceListing
808 *
809 * PARAMETERS:  FileId          - ID of current listing file.
810 *
811 * RETURN:      None
812 *
813 * DESCRIPTION: Cleanup routine for the listing file. Flush the hex AML
814 *              listing buffer, and flush out any remaining lines in the
815 *              source input file.
816 *
817 ******************************************************************************/
818
819static void
820LsFinishSourceListing (
821    UINT32                  FileId)
822{
823
824    if ((FileId == ASL_FILE_ASM_INCLUDE_OUTPUT) ||
825        (FileId == ASL_FILE_C_INCLUDE_OUTPUT))
826    {
827        return;
828    }
829
830    LsFlushListingBuffer (FileId);
831    Gbl_CurrentAmlOffset = 0;
832
833    /* Flush any remaining text in the source file */
834
835    if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
836    {
837        FlPrintFile (FileId, "    /*\n");
838    }
839
840    while (LsWriteOneSourceLine (FileId))
841    { ; }
842
843    if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
844    {
845        FlPrintFile (FileId, "\n     */\n    };\n");
846    }
847
848    FlPrintFile (FileId, "\n");
849
850    if (FileId == ASL_FILE_LISTING_OUTPUT)
851    {
852        /* Print a summary of the compile exceptions */
853
854        FlPrintFile (FileId, "\n\nSummary of errors and warnings\n\n");
855        AePrintErrorLog (FileId);
856        FlPrintFile (FileId, "\n");
857        UtDisplaySummary (FileId);
858        FlPrintFile (FileId, "\n");
859    }
860}
861
862
863/*******************************************************************************
864 *
865 * FUNCTION:    LsWriteSourceLines
866 *
867 * PARAMETERS:  ToLineNumber            -
868 *              ToLogicalLineNumber     - Write up to this source line number
869 *              FileId                  - ID of current listing file
870 *
871 * RETURN:      None
872 *
873 * DESCRIPTION: Read then write source lines to the listing file until we have
874 *              reached the specified logical (cumulative) line number. This
875 *              automatically echos out comment blocks and other non-AML
876 *              generating text until we get to the actual AML-generating line
877 *              of ASL code specified by the logical line number.
878 *
879 ******************************************************************************/
880
881static void
882LsWriteSourceLines (
883    UINT32                  ToLineNumber,
884    UINT32                  ToLogicalLineNumber,
885    UINT32                  FileId)
886{
887
888    if ((FileId == ASL_FILE_ASM_INCLUDE_OUTPUT) ||
889        (FileId == ASL_FILE_C_INCLUDE_OUTPUT))
890    {
891        return;
892    }
893
894    Gbl_CurrentLine = ToLogicalLineNumber;
895
896    /* Flush any hex bytes remaining from the last opcode */
897
898    LsFlushListingBuffer (FileId);
899
900    /* Read lines and write them as long as we are not caught up */
901
902    if (Gbl_SourceLine < Gbl_CurrentLine)
903    {
904        /*
905         * If we just completed writing some AML hex bytes, output a linefeed
906         * to add some whitespace for readability.
907         */
908        if (Gbl_HexBytesWereWritten)
909        {
910            FlPrintFile (FileId, "\n");
911            Gbl_HexBytesWereWritten = FALSE;
912        }
913
914        if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
915        {
916            FlPrintFile (FileId, "    /*\n");
917        }
918
919        /* Write one line at a time until we have reached the target line # */
920
921        while ((Gbl_SourceLine < Gbl_CurrentLine) &&
922                LsWriteOneSourceLine (FileId))
923        { ; }
924
925        if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
926        {
927            FlPrintFile (FileId, "     */");
928        }
929        FlPrintFile (FileId, "\n");
930    }
931}
932
933
934/*******************************************************************************
935 *
936 * FUNCTION:    LsWriteNodeToListing
937 *
938 * PARAMETERS:  Op            - Parse node to write to the listing file.
939 *              FileId          - ID of current listing file
940 *
941 * RETURN:      None.
942 *
943 * DESCRIPTION: Write "a node" to the listing file. This means to
944 *              1) Write out all of the source text associated with the node
945 *              2) Write out all of the AML bytes associated with the node
946 *              3) Write any compiler exceptions associated with the node
947 *
948 ******************************************************************************/
949
950static void
951LsWriteNodeToListing (
952    ACPI_PARSE_OBJECT       *Op,
953    UINT32                  FileId)
954{
955    const ACPI_OPCODE_INFO  *OpInfo;
956    UINT32                  OpClass;
957    char                    *Pathname;
958    UINT32                  Length;
959    UINT32                  i;
960
961
962    OpInfo  = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
963    OpClass = OpInfo->Class;
964
965    /* TBD: clean this up with a single flag that says:
966     * I start a named output block
967     */
968    if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
969    {
970        switch (Op->Asl.ParseOpcode)
971        {
972        case PARSEOP_DEFINITIONBLOCK:
973        case PARSEOP_METHODCALL:
974        case PARSEOP_INCLUDE:
975        case PARSEOP_INCLUDE_END:
976        case PARSEOP_DEFAULT_ARG:
977
978            break;
979
980        default:
981            switch (OpClass)
982            {
983            case AML_CLASS_NAMED_OBJECT:
984                switch (Op->Asl.AmlOpcode)
985                {
986                case AML_SCOPE_OP:
987                case AML_ALIAS_OP:
988                    break;
989
990                default:
991                    if (Op->Asl.ExternalName)
992                    {
993                        LsFlushListingBuffer (FileId);
994                        FlPrintFile (FileId, "    };\n");
995                    }
996                    break;
997                }
998                break;
999
1000            default:
1001                /* Don't care about other objects */
1002                break;
1003            }
1004            break;
1005        }
1006    }
1007
1008    /* These cases do not have a corresponding AML opcode */
1009
1010    switch (Op->Asl.ParseOpcode)
1011    {
1012    case PARSEOP_DEFINITIONBLOCK:
1013
1014        LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine, FileId);
1015
1016        /* Use the table Signature and TableId to build a unique name */
1017
1018        if (FileId == ASL_FILE_ASM_SOURCE_OUTPUT)
1019        {
1020            FlPrintFile (FileId,
1021                "%s_%s_Header \\\n",
1022                Gbl_TableSignature, Gbl_TableId);
1023        }
1024        if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
1025        {
1026            FlPrintFile (FileId,
1027                "    unsigned char    %s_%s_Header [] =\n    {\n",
1028                Gbl_TableSignature, Gbl_TableId);
1029        }
1030        if (FileId == ASL_FILE_ASM_INCLUDE_OUTPUT)
1031        {
1032            FlPrintFile (FileId,
1033                "extrn %s_%s_Header : byte\n",
1034                Gbl_TableSignature, Gbl_TableId);
1035        }
1036        if (FileId == ASL_FILE_C_INCLUDE_OUTPUT)
1037        {
1038            FlPrintFile (FileId,
1039                "extern unsigned char    %s_%s_Header [];\n",
1040                Gbl_TableSignature, Gbl_TableId);
1041        }
1042        return;
1043
1044
1045    case PARSEOP_METHODCALL:
1046
1047        LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
1048            FileId);
1049        return;
1050
1051
1052    case PARSEOP_INCLUDE:
1053
1054        /* Flush everything up to and including the include source line */
1055
1056        LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
1057            FileId);
1058
1059        /* Create a new listing node and push it */
1060
1061        LsPushNode (Op->Asl.Child->Asl.Value.String);
1062        return;
1063
1064
1065    case PARSEOP_INCLUDE_END:
1066
1067        /* Flush out the rest of the include file */
1068
1069        LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
1070            FileId);
1071
1072        /* Pop off this listing node and go back to the parent file */
1073
1074        (void) LsPopNode ();
1075        return;
1076
1077
1078    case PARSEOP_DEFAULT_ARG:
1079
1080        if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC)
1081        {
1082            LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.EndLogicalLine,
1083                FileId);
1084        }
1085        return;
1086
1087
1088    default:
1089        /* All other opcodes have an AML opcode */
1090        break;
1091    }
1092
1093    /*
1094     * Otherwise, we look at the AML opcode because we can
1095     * switch on the opcode type, getting an entire class
1096     * at once
1097     */
1098    switch (OpClass)
1099    {
1100    case AML_CLASS_ARGUMENT:       /* argument type only */
1101    case AML_CLASS_INTERNAL:
1102
1103        break;
1104
1105
1106    case AML_CLASS_NAMED_OBJECT:
1107
1108        switch (Op->Asl.AmlOpcode)
1109        {
1110        case AML_FIELD_OP:
1111        case AML_INDEX_FIELD_OP:
1112        case AML_BANK_FIELD_OP:
1113
1114            /*
1115             * For fields, we want to dump all the AML after the
1116             * entire definition
1117             */
1118            LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine,
1119                FileId);
1120            break;
1121
1122        case AML_NAME_OP:
1123
1124            if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC)
1125            {
1126                LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
1127                    FileId);
1128            }
1129            else
1130            {
1131                /*
1132                 * For fields, we want to dump all the AML after the
1133                 * entire definition
1134                 */
1135                LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine,
1136                    FileId);
1137            }
1138            break;
1139
1140        default:
1141            LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
1142                FileId);
1143            break;
1144        }
1145
1146        switch (Op->Asl.AmlOpcode)
1147        {
1148        case AML_SCOPE_OP:
1149        case AML_ALIAS_OP:
1150
1151            /* These opcodes do not declare a new object, ignore them */
1152
1153            break;
1154
1155        default:
1156
1157            /* All other named object opcodes come here */
1158
1159            switch (FileId)
1160            {
1161            case ASL_FILE_ASM_SOURCE_OUTPUT:
1162            case ASL_FILE_C_SOURCE_OUTPUT:
1163            case ASL_FILE_ASM_INCLUDE_OUTPUT:
1164            case ASL_FILE_C_INCLUDE_OUTPUT:
1165
1166                /*
1167                 * For named objects, we will create a valid symbol so that the
1168                 * AML code can be referenced from C or ASM
1169                 */
1170                if (Op->Asl.ExternalName)
1171                {
1172                    /* Get the full pathname associated with this node */
1173
1174                    Pathname = AcpiNsGetExternalPathname (Op->Asl.Node);
1175                    Length = strlen (Pathname);
1176                    if (Length >= 4)
1177                    {
1178                        /* Convert all dots in the path to underscores */
1179
1180                        for (i = 0; i < Length; i++)
1181                        {
1182                            if (Pathname[i] == '.')
1183                            {
1184                                Pathname[i] = '_';
1185                            }
1186                        }
1187
1188                        /* Create the appropriate symbol in the output file */
1189
1190                        if (FileId == ASL_FILE_ASM_SOURCE_OUTPUT)
1191                        {
1192                            FlPrintFile (FileId,
1193                                "%s_%s_%s  \\\n",
1194                                Gbl_TableSignature, Gbl_TableId, &Pathname[1]);
1195                        }
1196                        if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
1197                        {
1198                            FlPrintFile (FileId,
1199                                "    unsigned char    %s_%s_%s [] =\n    {\n",
1200                                Gbl_TableSignature, Gbl_TableId, &Pathname[1]);
1201                        }
1202                        if (FileId == ASL_FILE_ASM_INCLUDE_OUTPUT)
1203                        {
1204                            FlPrintFile (FileId,
1205                                "extrn %s_%s_%s : byte\n",
1206                                Gbl_TableSignature, Gbl_TableId, &Pathname[1]);
1207                        }
1208                        if (FileId == ASL_FILE_C_INCLUDE_OUTPUT)
1209                        {
1210                            FlPrintFile (FileId,
1211                                "extern unsigned char    %s_%s_%s [];\n",
1212                                Gbl_TableSignature, Gbl_TableId, &Pathname[1]);
1213                        }
1214                    }
1215                    ACPI_FREE (Pathname);
1216                }
1217                break;
1218
1219            default:
1220                /* Nothing to do for listing file */
1221                break;
1222            }
1223        }
1224        break;
1225
1226    case AML_CLASS_EXECUTE:
1227    case AML_CLASS_CREATE:
1228    default:
1229
1230        if ((Op->Asl.ParseOpcode == PARSEOP_BUFFER) &&
1231            (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC))
1232        {
1233            return;
1234        }
1235
1236        LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
1237            FileId);
1238        break;
1239
1240    case AML_CLASS_UNKNOWN:
1241        break;
1242    }
1243}
1244
1245
1246/*******************************************************************************
1247 *
1248 * FUNCTION:    LsDoHexOutput
1249 *
1250 * PARAMETERS:  None
1251 *
1252 * RETURN:      None.
1253 *
1254 * DESCRIPTION: Create the hex output file.
1255 *
1256 ******************************************************************************/
1257
1258void
1259LsDoHexOutput (
1260    void)
1261{
1262
1263    switch (Gbl_HexOutputFlag)
1264    {
1265    case HEX_OUTPUT_C:
1266
1267        LsDoHexOutputC ();
1268        break;
1269
1270    case HEX_OUTPUT_ASM:
1271
1272        LsDoHexOutputAsm ();
1273        break;
1274
1275    case HEX_OUTPUT_ASL:
1276
1277        LsDoHexOutputAsl ();
1278        break;
1279
1280    default:
1281        /* No other output types supported */
1282        break;
1283    }
1284}
1285
1286
1287/*******************************************************************************
1288 *
1289 * FUNCTION:    LsReadAmlOutputFile
1290 *
1291 * PARAMETERS:  Buffer              - Where to return data
1292 *
1293 * RETURN:      None.
1294 *
1295 * DESCRIPTION: Read a line of the AML output prior to formatting the data
1296 *
1297 ******************************************************************************/
1298
1299static UINT32
1300LsReadAmlOutputFile (
1301    UINT8                   *Buffer)
1302{
1303    UINT32                  Actual;
1304
1305
1306    Actual = fread (Buffer, 1, HEX_TABLE_LINE_SIZE,
1307        Gbl_Files[ASL_FILE_AML_OUTPUT].Handle);
1308
1309    if (ferror (Gbl_Files[ASL_FILE_AML_OUTPUT].Handle))
1310    {
1311        FlFileError (ASL_FILE_AML_OUTPUT, ASL_MSG_READ);
1312        AslAbort ();
1313    }
1314
1315    return (Actual);
1316}
1317
1318
1319/*******************************************************************************
1320 *
1321 * FUNCTION:    LsDoHexOutputC
1322 *
1323 * PARAMETERS:  None
1324 *
1325 * RETURN:      None.
1326 *
1327 * DESCRIPTION: Create the hex output file. This is the same data as the AML
1328 *              output file, but formatted into hex/ascii bytes suitable for
1329 *              inclusion into a C source file.
1330 *
1331 ******************************************************************************/
1332
1333static void
1334LsDoHexOutputC (
1335    void)
1336{
1337    UINT8                   FileData[HEX_TABLE_LINE_SIZE];
1338    UINT32                  LineLength;
1339    UINT32                  Offset = 0;
1340    UINT32                  AmlFileSize;
1341    UINT32                  i;
1342
1343
1344    /* Get AML size, seek back to start */
1345
1346    AmlFileSize = FlGetFileSize (ASL_FILE_AML_OUTPUT);
1347    FlSeekFile (ASL_FILE_AML_OUTPUT, 0);
1348
1349    FlPrintFile (ASL_FILE_HEX_OUTPUT, " * C source code output\n");
1350    FlPrintFile (ASL_FILE_HEX_OUTPUT, " * AML code block contains 0x%X bytes\n *\n */\n",
1351        AmlFileSize);
1352    FlPrintFile (ASL_FILE_HEX_OUTPUT, "unsigned char AmlCode[] =\n{\n");
1353
1354    while (Offset < AmlFileSize)
1355    {
1356        /* Read enough bytes needed for one output line */
1357
1358        LineLength = LsReadAmlOutputFile (FileData);
1359        if (!LineLength)
1360        {
1361            break;
1362        }
1363
1364        FlPrintFile (ASL_FILE_HEX_OUTPUT, "    ");
1365
1366        for (i = 0; i < LineLength; i++)
1367        {
1368            /*
1369             * Print each hex byte.
1370             * Add a comma until the very last byte of the AML file
1371             * (Some C compilers complain about a trailing comma)
1372             */
1373            FlPrintFile (ASL_FILE_HEX_OUTPUT, "0x%2.2X", FileData[i]);
1374            if ((Offset + i + 1) < AmlFileSize)
1375            {
1376                FlPrintFile (ASL_FILE_HEX_OUTPUT, ",");
1377            }
1378            else
1379            {
1380                FlPrintFile (ASL_FILE_HEX_OUTPUT, " ");
1381            }
1382        }
1383
1384        /* Add fill spaces if needed for last line */
1385
1386        if (LineLength < HEX_TABLE_LINE_SIZE)
1387        {
1388            FlPrintFile (ASL_FILE_HEX_OUTPUT, "%*s",
1389                5 * (HEX_TABLE_LINE_SIZE - LineLength), " ");
1390        }
1391
1392        /* Emit the offset and ascii dump for the entire line */
1393
1394        FlPrintFile (ASL_FILE_HEX_OUTPUT, "  /* %8.8X", Offset);
1395        LsDumpAsciiInComment (ASL_FILE_HEX_OUTPUT, LineLength, FileData);
1396        FlPrintFile (ASL_FILE_HEX_OUTPUT, "%*s*/\n",
1397            HEX_TABLE_LINE_SIZE - LineLength + 1, " ");
1398
1399        Offset += LineLength;
1400    }
1401
1402    FlPrintFile (ASL_FILE_HEX_OUTPUT, "};\n");
1403}
1404
1405
1406/*******************************************************************************
1407 *
1408 * FUNCTION:    LsDoHexOutputAsl
1409 *
1410 * PARAMETERS:  None
1411 *
1412 * RETURN:      None.
1413 *
1414 * DESCRIPTION: Create the hex output file. This is the same data as the AML
1415 *              output file, but formatted into hex/ascii bytes suitable for
1416 *              inclusion into a C source file.
1417 *
1418 ******************************************************************************/
1419
1420static void
1421LsDoHexOutputAsl (
1422    void)
1423{
1424    UINT8                   FileData[HEX_TABLE_LINE_SIZE];
1425    UINT32                  LineLength;
1426    UINT32                  Offset = 0;
1427    UINT32                  AmlFileSize;
1428    UINT32                  i;
1429
1430
1431    /* Get AML size, seek back to start */
1432
1433    AmlFileSize = FlGetFileSize (ASL_FILE_AML_OUTPUT);
1434    FlSeekFile (ASL_FILE_AML_OUTPUT, 0);
1435
1436    FlPrintFile (ASL_FILE_HEX_OUTPUT, " * ASL source code output\n");
1437    FlPrintFile (ASL_FILE_HEX_OUTPUT, " * AML code block contains 0x%X bytes\n *\n */\n",
1438        AmlFileSize);
1439    FlPrintFile (ASL_FILE_HEX_OUTPUT, "    Name (BUF1, Buffer()\n    {\n");
1440
1441    while (Offset < AmlFileSize)
1442    {
1443        /* Read enough bytes needed for one output line */
1444
1445        LineLength = LsReadAmlOutputFile (FileData);
1446        if (!LineLength)
1447        {
1448            break;
1449        }
1450
1451        FlPrintFile (ASL_FILE_HEX_OUTPUT, "        ");
1452
1453        for (i = 0; i < LineLength; i++)
1454        {
1455            /*
1456             * Print each hex byte.
1457             * Add a comma until the very last byte of the AML file
1458             * (Some C compilers complain about a trailing comma)
1459             */
1460            FlPrintFile (ASL_FILE_HEX_OUTPUT, "0x%2.2X", FileData[i]);
1461            if ((Offset + i + 1) < AmlFileSize)
1462            {
1463                FlPrintFile (ASL_FILE_HEX_OUTPUT, ",");
1464            }
1465            else
1466            {
1467                FlPrintFile (ASL_FILE_HEX_OUTPUT, " ");
1468            }
1469        }
1470
1471        /* Add fill spaces if needed for last line */
1472
1473        if (LineLength < HEX_TABLE_LINE_SIZE)
1474        {
1475            FlPrintFile (ASL_FILE_HEX_OUTPUT, "%*s",
1476                5 * (HEX_TABLE_LINE_SIZE - LineLength), " ");
1477        }
1478
1479        /* Emit the offset and ascii dump for the entire line */
1480
1481        FlPrintFile (ASL_FILE_HEX_OUTPUT, "  /* %8.8X", Offset);
1482        LsDumpAsciiInComment (ASL_FILE_HEX_OUTPUT, LineLength, FileData);
1483        FlPrintFile (ASL_FILE_HEX_OUTPUT, "%*s*/\n",
1484            HEX_TABLE_LINE_SIZE - LineLength + 1, " ");
1485
1486        Offset += LineLength;
1487    }
1488
1489    FlPrintFile (ASL_FILE_HEX_OUTPUT, "    })\n");
1490}
1491
1492
1493/*******************************************************************************
1494 *
1495 * FUNCTION:    LsDoHexOutputAsm
1496 *
1497 * PARAMETERS:  None
1498 *
1499 * RETURN:      None.
1500 *
1501 * DESCRIPTION: Create the hex output file. This is the same data as the AML
1502 *              output file, but formatted into hex/ascii bytes suitable for
1503 *              inclusion into a ASM source file.
1504 *
1505 ******************************************************************************/
1506
1507static void
1508LsDoHexOutputAsm (
1509    void)
1510{
1511    UINT8                   FileData[HEX_TABLE_LINE_SIZE];
1512    UINT32                  LineLength;
1513    UINT32                  Offset = 0;
1514    UINT32                  AmlFileSize;
1515    UINT32                  i;
1516
1517
1518    /* Get AML size, seek back to start */
1519
1520    AmlFileSize = FlGetFileSize (ASL_FILE_AML_OUTPUT);
1521    FlSeekFile (ASL_FILE_AML_OUTPUT, 0);
1522
1523    FlPrintFile (ASL_FILE_HEX_OUTPUT, "; Assembly code source output\n");
1524    FlPrintFile (ASL_FILE_HEX_OUTPUT, "; AML code block contains 0x%X bytes\n;\n",
1525        AmlFileSize);
1526
1527    while (Offset < AmlFileSize)
1528    {
1529        /* Read enough bytes needed for one output line */
1530
1531        LineLength = LsReadAmlOutputFile (FileData);
1532        if (!LineLength)
1533        {
1534            break;
1535        }
1536
1537        FlPrintFile (ASL_FILE_HEX_OUTPUT, "  db  ");
1538
1539        for (i = 0; i < LineLength; i++)
1540        {
1541            /*
1542             * Print each hex byte.
1543             * Add a comma until the last byte of the line
1544             */
1545            FlPrintFile (ASL_FILE_HEX_OUTPUT, "0%2.2Xh", FileData[i]);
1546            if ((i + 1) < LineLength)
1547            {
1548                FlPrintFile (ASL_FILE_HEX_OUTPUT, ",");
1549            }
1550        }
1551
1552        FlPrintFile (ASL_FILE_HEX_OUTPUT, " ");
1553
1554        /* Add fill spaces if needed for last line */
1555
1556        if (LineLength < HEX_TABLE_LINE_SIZE)
1557        {
1558            FlPrintFile (ASL_FILE_HEX_OUTPUT, "%*s",
1559                5 * (HEX_TABLE_LINE_SIZE - LineLength), " ");
1560        }
1561
1562        /* Emit the offset and ascii dump for the entire line */
1563
1564        FlPrintFile (ASL_FILE_HEX_OUTPUT, "  ; %8.8X", Offset);
1565        LsDumpAsciiInComment (ASL_FILE_HEX_OUTPUT, LineLength, FileData);
1566        FlPrintFile (ASL_FILE_HEX_OUTPUT, "\n");
1567
1568        Offset += LineLength;
1569    }
1570
1571    FlPrintFile (ASL_FILE_HEX_OUTPUT, "\n");
1572}
1573