asllisting.c revision 245582
1/******************************************************************************
2 *
3 * Module Name: asllisting - Listing file generation
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
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 ACPI_STATUS
63LsAmlListingWalk (
64    ACPI_PARSE_OBJECT       *Op,
65    UINT32                  Level,
66    void                    *Context);
67
68static void
69LsGenerateListing (
70    UINT32                  FileId);
71
72static void
73LsPushNode (
74    char                    *Filename);
75
76static ASL_LISTING_NODE *
77LsPopNode (
78    void);
79
80static void
81LsCheckException (
82    UINT32                  LineNumber,
83    UINT32                  FileId);
84
85static void
86LsFlushListingBuffer (
87    UINT32                  FileId);
88
89static void
90LsWriteListingHexBytes (
91    UINT8                   *Buffer,
92    UINT32                  Length,
93    UINT32                  FileId);
94
95static UINT32
96LsWriteOneSourceLine (
97    UINT32                  FileId);
98
99static void
100LsFinishSourceListing (
101    UINT32                  FileId);
102
103static void
104LsWriteSourceLines (
105    UINT32                  ToLineNumber,
106    UINT32                  ToLogicalLineNumber,
107    UINT32                  FileId);
108
109static void
110LsWriteNodeToListing (
111    ACPI_PARSE_OBJECT       *Op,
112    UINT32                  FileId);
113
114static ACPI_STATUS
115LsTreeWriteWalk (
116    ACPI_PARSE_OBJECT       *Op,
117    UINT32                  Level,
118    void                    *Context);
119
120#define ASL_LISTING_LINE_PREFIX         ":  "
121
122
123/*******************************************************************************
124 *
125 * FUNCTION:    LsDoListings
126 *
127 * PARAMETERS:  None
128 *
129 * RETURN:      None
130 *
131 * DESCRIPTION: Generate all requested listing files.
132 *
133 ******************************************************************************/
134
135void
136LsDoListings (
137    void)
138{
139
140    if (Gbl_C_OutputFlag)
141    {
142        LsGenerateListing (ASL_FILE_C_SOURCE_OUTPUT);
143    }
144
145    if (Gbl_ListingFlag)
146    {
147        LsGenerateListing (ASL_FILE_LISTING_OUTPUT);
148    }
149
150    if (Gbl_AsmOutputFlag)
151    {
152        LsGenerateListing (ASL_FILE_ASM_SOURCE_OUTPUT);
153    }
154
155    if (Gbl_C_IncludeOutputFlag)
156    {
157        LsGenerateListing (ASL_FILE_C_INCLUDE_OUTPUT);
158    }
159
160    if (Gbl_AsmIncludeOutputFlag)
161    {
162        LsGenerateListing (ASL_FILE_ASM_INCLUDE_OUTPUT);
163    }
164}
165
166
167/*******************************************************************************
168 *
169 * FUNCTION:    LsTreeWriteWalk
170 *
171 * PARAMETERS:  ASL_WALK_CALLBACK
172 *
173 *
174 * RETURN:      None
175 *
176 * DESCRIPTION: Dump entire parse tree, for compiler debug only
177 *
178 ******************************************************************************/
179
180static ACPI_STATUS
181LsTreeWriteWalk (
182    ACPI_PARSE_OBJECT       *Op,
183    UINT32                  Level,
184    void                    *Context)
185{
186
187    /* Debug output */
188
189    DbgPrint (ASL_TREE_OUTPUT,
190        "%5.5d [%2d]", Op->Asl.LogicalLineNumber, Level);
191    UtPrintFormattedName (Op->Asl.ParseOpcode, Level);
192
193
194    DbgPrint (ASL_TREE_OUTPUT, "\n");
195    return (AE_OK);
196}
197
198
199void
200LsDumpParseTree (
201    void)
202{
203
204    if (!Gbl_DebugFlag)
205    {
206        return;
207    }
208
209    DbgPrint (ASL_TREE_OUTPUT, "\nOriginal parse tree from parser:\n\n");
210    TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD,
211        LsTreeWriteWalk, NULL, NULL);
212}
213
214
215/*******************************************************************************
216 *
217 * FUNCTION:    LsDumpAscii
218 *
219 * PARAMETERS:  FileId          - ID of current listing file
220 *              Count           - Number of bytes to convert
221 *              Buffer          - Buffer of bytes to convert
222 *
223 * RETURN:      None
224 *
225 * DESCRIPTION: Convert hex bytes to ascii
226 *
227 ******************************************************************************/
228
229static void
230LsDumpAscii (
231    UINT32                  FileId,
232    UINT32                  Count,
233    UINT8                   *Buffer)
234{
235    UINT8                   BufChar;
236    UINT32                  i;
237
238
239    FlPrintFile (FileId, "    \"");
240    for (i = 0; i < Count; i++)
241    {
242        BufChar = Buffer[i];
243        if (isprint (BufChar))
244        {
245            FlPrintFile (FileId, "%c", BufChar);
246        }
247        else
248        {
249            /* Not a printable character, just put out a dot */
250
251            FlPrintFile (FileId, ".");
252        }
253    }
254    FlPrintFile (FileId, "\"");
255}
256
257
258/*******************************************************************************
259 *
260 * FUNCTION:    LsDumpAsciiInComment
261 *
262 * PARAMETERS:  FileId          - ID of current listing file
263 *              Count           - Number of bytes to convert
264 *              Buffer          - Buffer of bytes to convert
265 *
266 * RETURN:      None
267 *
268 * DESCRIPTION: Convert hex bytes to ascii
269 *
270 ******************************************************************************/
271
272void
273LsDumpAsciiInComment (
274    UINT32                  FileId,
275    UINT32                  Count,
276    UINT8                   *Buffer)
277{
278    UINT8                   BufChar = 0;
279    UINT8                   LastChar;
280    UINT32                  i;
281
282
283    FlPrintFile (FileId, "    \"");
284    for (i = 0; i < Count; i++)
285    {
286        LastChar = BufChar;
287        BufChar = Buffer[i];
288
289        if (isprint (BufChar))
290        {
291            /* Handle embedded C comment sequences */
292
293            if (((LastChar == '*') && (BufChar == '/')) ||
294                ((LastChar == '/') && (BufChar == '*')))
295            {
296                /* Insert a space to break the sequence */
297
298                FlPrintFile (FileId, ".", BufChar);
299            }
300
301            FlPrintFile (FileId, "%c", BufChar);
302        }
303        else
304        {
305            /* Not a printable character, just put out a dot */
306
307            FlPrintFile (FileId, ".");
308        }
309    }
310    FlPrintFile (FileId, "\"");
311}
312
313
314/*******************************************************************************
315 *
316 * FUNCTION:    LsAmlListingWalk
317 *
318 * PARAMETERS:  ASL_WALK_CALLBACK
319 *
320 * RETURN:      Status
321 *
322 * DESCRIPTION: Process one node during a listing file generation.
323 *
324 ******************************************************************************/
325
326static ACPI_STATUS
327LsAmlListingWalk (
328    ACPI_PARSE_OBJECT       *Op,
329    UINT32                  Level,
330    void                    *Context)
331{
332    UINT8                   FileByte;
333    UINT32                  i;
334    UINT32                  FileId = (UINT32) ACPI_TO_INTEGER (Context);
335
336
337    LsWriteNodeToListing (Op, FileId);
338
339    if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DATA)
340    {
341        /* Buffer is a resource template, don't dump the data all at once */
342
343        return (AE_OK);
344    }
345
346    /* Write the hex bytes to the listing file(s) (if requested) */
347
348    for (i = 0; i < Op->Asl.FinalAmlLength; i++)
349    {
350        if (ACPI_FAILURE (FlReadFile (ASL_FILE_AML_OUTPUT, &FileByte, 1)))
351        {
352            FlFileError (ASL_FILE_AML_OUTPUT, ASL_MSG_READ);
353            AslAbort ();
354        }
355        LsWriteListingHexBytes (&FileByte, 1, FileId);
356    }
357
358    return (AE_OK);
359}
360
361
362/*******************************************************************************
363 *
364 * FUNCTION:    LsGenerateListing
365 *
366 * PARAMETERS:  FileId      - ID of listing file
367 *
368 * RETURN:      None
369 *
370 * DESCRIPTION: Generate a listing file. This can be one of the several types
371 *              of "listings" supported.
372 *
373 ******************************************************************************/
374
375static void
376LsGenerateListing (
377    UINT32                  FileId)
378{
379
380    /* Start at the beginning of both the source and AML files */
381
382    FlSeekFile (ASL_FILE_SOURCE_OUTPUT, 0);
383    FlSeekFile (ASL_FILE_AML_OUTPUT, 0);
384    Gbl_SourceLine = 0;
385    Gbl_CurrentHexColumn = 0;
386    LsPushNode (Gbl_Files[ASL_FILE_INPUT].Filename);
387
388    /* Process all parse nodes */
389
390    TrWalkParseTree (RootNode, ASL_WALK_VISIT_DOWNWARD, LsAmlListingWalk,
391                        NULL, (void *) ACPI_TO_POINTER (FileId));
392
393    /* Final processing */
394
395    LsFinishSourceListing (FileId);
396}
397
398
399/*******************************************************************************
400 *
401 * FUNCTION:    LsPushNode
402 *
403 * PARAMETERS:  Filename        - Pointer to the include filename
404 *
405 * RETURN:      None
406 *
407 * DESCRIPTION: Push a listing node on the listing/include file stack. This
408 *              stack enables tracking of include files (infinitely nested)
409 *              and resumption of the listing of the parent file when the
410 *              include file is finished.
411 *
412 ******************************************************************************/
413
414static void
415LsPushNode (
416    char                    *Filename)
417{
418    ASL_LISTING_NODE        *Lnode;
419
420
421    /* Create a new node */
422
423    Lnode = UtLocalCalloc (sizeof (ASL_LISTING_NODE));
424
425    /* Initialize */
426
427    Lnode->Filename = Filename;
428    Lnode->LineNumber = 0;
429
430    /* Link (push) */
431
432    Lnode->Next = Gbl_ListingNode;
433    Gbl_ListingNode = Lnode;
434}
435
436
437/*******************************************************************************
438 *
439 * FUNCTION:    LsPopNode
440 *
441 * PARAMETERS:  None
442 *
443 * RETURN:      List head after current head is popped off
444 *
445 * DESCRIPTION: Pop the current head of the list, free it, and return the
446 *              next node on the stack (the new current node).
447 *
448 ******************************************************************************/
449
450static ASL_LISTING_NODE *
451LsPopNode (
452    void)
453{
454    ASL_LISTING_NODE        *Lnode;
455
456
457    /* Just grab the node at the head of the list */
458
459    Lnode = Gbl_ListingNode;
460    if ((!Lnode) ||
461        (!Lnode->Next))
462    {
463        AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, NULL,
464            "Could not pop empty listing stack");
465        return (Gbl_ListingNode);
466    }
467
468    Gbl_ListingNode = Lnode->Next;
469    ACPI_FREE (Lnode);
470
471    /* New "Current" node is the new head */
472
473    return (Gbl_ListingNode);
474}
475
476
477/*******************************************************************************
478 *
479 * FUNCTION:    LsCheckException
480 *
481 * PARAMETERS:  LineNumber          - Current logical (cumulative) line #
482 *              FileId              - ID of output listing file
483 *
484 * RETURN:      None
485 *
486 * DESCRIPTION: Check if there is an exception for this line, and if there is,
487 *              put it in the listing immediately. Handles multiple errors
488 *              per line. Gbl_NextError points to the next error in the
489 *              sorted (by line #) list of compile errors/warnings.
490 *
491 ******************************************************************************/
492
493static void
494LsCheckException (
495    UINT32                  LineNumber,
496    UINT32                  FileId)
497{
498
499    if ((!Gbl_NextError) ||
500        (LineNumber < Gbl_NextError->LogicalLineNumber ))
501    {
502        return;
503    }
504
505    /* Handle multiple errors per line */
506
507    if (FileId == ASL_FILE_LISTING_OUTPUT)
508    {
509        while (Gbl_NextError &&
510              (LineNumber >= Gbl_NextError->LogicalLineNumber))
511        {
512            AePrintException (FileId, Gbl_NextError, "\n[****iasl****]\n");
513
514            Gbl_NextError = Gbl_NextError->Next;
515        }
516
517        FlPrintFile (FileId, "\n");
518    }
519}
520
521
522/*******************************************************************************
523 *
524 * FUNCTION:    LsFlushListingBuffer
525 *
526 * PARAMETERS:  FileId          - ID of the listing file
527 *
528 * RETURN:      None
529 *
530 * DESCRIPTION: Flush out the current contents of the 16-byte hex AML code
531 *              buffer. Usually called at the termination of a single line
532 *              of source code or when the buffer is full.
533 *
534 ******************************************************************************/
535
536static void
537LsFlushListingBuffer (
538    UINT32                  FileId)
539{
540    UINT32                  i;
541
542
543    if (Gbl_CurrentHexColumn == 0)
544    {
545        return;
546    }
547
548    /* Write the hex bytes */
549
550    switch (FileId)
551    {
552    case ASL_FILE_LISTING_OUTPUT:
553
554        for (i = 0; i < Gbl_CurrentHexColumn; i++)
555        {
556            FlPrintFile (FileId, "%2.2X ", Gbl_AmlBuffer[i]);
557        }
558
559        for (i = 0; i < ((HEX_LISTING_LINE_SIZE - Gbl_CurrentHexColumn) * 3); i++)
560        {
561            FlWriteFile (FileId, ".", 1);
562        }
563
564        /* Write the ASCII character associated with each of the bytes */
565
566        LsDumpAscii (FileId, Gbl_CurrentHexColumn, Gbl_AmlBuffer);
567        break;
568
569
570    case ASL_FILE_ASM_SOURCE_OUTPUT:
571
572        for (i = 0; i < Gbl_CurrentHexColumn; i++)
573        {
574            if (i > 0)
575            {
576                FlPrintFile (FileId, ",");
577            }
578            FlPrintFile (FileId, "0%2.2Xh", Gbl_AmlBuffer[i]);
579        }
580
581        for (i = 0; i < ((HEX_LISTING_LINE_SIZE - Gbl_CurrentHexColumn) * 5); i++)
582        {
583            FlWriteFile (FileId, " ", 1);
584        }
585
586        FlPrintFile (FileId, "  ;%8.8X",
587            Gbl_CurrentAmlOffset - HEX_LISTING_LINE_SIZE);
588
589        /* Write the ASCII character associated with each of the bytes */
590
591        LsDumpAscii (FileId, Gbl_CurrentHexColumn, Gbl_AmlBuffer);
592        break;
593
594
595    case ASL_FILE_C_SOURCE_OUTPUT:
596
597        for (i = 0; i < Gbl_CurrentHexColumn; i++)
598        {
599            FlPrintFile (FileId, "0x%2.2X,", Gbl_AmlBuffer[i]);
600        }
601
602        for (i = 0; i < ((HEX_LISTING_LINE_SIZE - Gbl_CurrentHexColumn) * 5); i++)
603        {
604            FlWriteFile (FileId, " ", 1);
605        }
606
607        FlPrintFile (FileId, "    /* %8.8X",
608            Gbl_CurrentAmlOffset - HEX_LISTING_LINE_SIZE);
609
610        /* Write the ASCII character associated with each of the bytes */
611
612        LsDumpAsciiInComment (FileId, Gbl_CurrentHexColumn, Gbl_AmlBuffer);
613        FlPrintFile (FileId, " */");
614        break;
615
616    default:
617        /* No other types supported */
618        return;
619    }
620
621    FlPrintFile (FileId, "\n");
622
623    Gbl_CurrentHexColumn = 0;
624    Gbl_HexBytesWereWritten = TRUE;
625}
626
627
628/*******************************************************************************
629 *
630 * FUNCTION:    LsWriteListingHexBytes
631 *
632 * PARAMETERS:  Buffer          - AML code buffer
633 *              Length          - Number of AML bytes to write
634 *              FileId          - ID of current listing file.
635 *
636 * RETURN:      None
637 *
638 * DESCRIPTION: Write the contents of the AML buffer to the listing file via
639 *              the listing buffer. The listing buffer is flushed every 16
640 *              AML bytes.
641 *
642 ******************************************************************************/
643
644static void
645LsWriteListingHexBytes (
646    UINT8                   *Buffer,
647    UINT32                  Length,
648    UINT32                  FileId)
649{
650    UINT32                  i;
651
652
653    /* Transfer all requested bytes */
654
655    for (i = 0; i < Length; i++)
656    {
657        /* Print line header when buffer is empty */
658
659        if (Gbl_CurrentHexColumn == 0)
660        {
661            if (Gbl_HasIncludeFiles)
662            {
663                FlPrintFile (FileId, "%*s", 10, " ");
664            }
665
666            switch (FileId)
667            {
668            case ASL_FILE_LISTING_OUTPUT:
669
670                FlPrintFile (FileId, "%8.8X%s", Gbl_CurrentAmlOffset,
671                    ASL_LISTING_LINE_PREFIX);
672                break;
673
674            case ASL_FILE_ASM_SOURCE_OUTPUT:
675
676                FlPrintFile (FileId, "    db ");
677                break;
678
679            case ASL_FILE_C_SOURCE_OUTPUT:
680
681                FlPrintFile (FileId, "        ");
682                break;
683
684            default:
685                /* No other types supported */
686                return;
687            }
688        }
689
690        /* Transfer AML byte and update counts */
691
692        Gbl_AmlBuffer[Gbl_CurrentHexColumn] = Buffer[i];
693
694        Gbl_CurrentHexColumn++;
695        Gbl_CurrentAmlOffset++;
696
697        /* Flush buffer when it is full */
698
699        if (Gbl_CurrentHexColumn >= HEX_LISTING_LINE_SIZE)
700        {
701            LsFlushListingBuffer (FileId);
702        }
703    }
704}
705
706
707/*******************************************************************************
708 *
709 * FUNCTION:    LsWriteOneSourceLine
710 *
711 * PARAMETERS:  FileID          - ID of current listing file
712 *
713 * RETURN:      FALSE on EOF (input source file), TRUE otherwise
714 *
715 * DESCRIPTION: Read one line from the input source file and echo it to the
716 *              listing file, prefixed with the line number, and if the source
717 *              file contains include files, prefixed with the current filename
718 *
719 ******************************************************************************/
720
721static UINT32
722LsWriteOneSourceLine (
723    UINT32                  FileId)
724{
725    UINT8                   FileByte;
726
727
728    Gbl_SourceLine++;
729    Gbl_ListingNode->LineNumber++;
730
731    /* Ignore lines that are completely blank (but count the line above) */
732
733    if (FlReadFile (ASL_FILE_SOURCE_OUTPUT, &FileByte, 1) != AE_OK)
734    {
735        return (0);
736    }
737    if (FileByte == '\n')
738    {
739        return (1);
740    }
741
742    /*
743     * This is a non-empty line, we will print the entire line with
744     * the line number and possibly other prefixes and transforms.
745     */
746
747    /* Line prefixes for special files, C and ASM output */
748
749    if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
750    {
751        FlPrintFile (FileId, "     *");
752    }
753    if (FileId == ASL_FILE_ASM_SOURCE_OUTPUT)
754    {
755        FlPrintFile (FileId, "; ");
756    }
757
758    if (Gbl_HasIncludeFiles)
759    {
760        /*
761         * This file contains "include" statements, print the current
762         * filename and line number within the current file
763         */
764        FlPrintFile (FileId, "%12s %5d%s",
765            Gbl_ListingNode->Filename, Gbl_ListingNode->LineNumber,
766            ASL_LISTING_LINE_PREFIX);
767    }
768    else
769    {
770        /* No include files, just print the line number */
771
772        FlPrintFile (FileId, "%8u%s", Gbl_SourceLine,
773            ASL_LISTING_LINE_PREFIX);
774    }
775
776    /* Read the rest of this line (up to a newline or EOF) */
777
778    do
779    {
780        if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
781        {
782            if (FileByte == '/')
783            {
784                FileByte = '*';
785            }
786        }
787
788        FlWriteFile (FileId, &FileByte, 1);
789        if (FileByte == '\n')
790        {
791            /*
792             * This line has been completed.
793             * Check if an error occurred on this source line during the compile.
794             * If so, we print the error message after the source line.
795             */
796            LsCheckException (Gbl_SourceLine, FileId);
797            return (1);
798        }
799
800    } while (FlReadFile (ASL_FILE_SOURCE_OUTPUT, &FileByte, 1) == AE_OK);
801
802    /* EOF on the input file was reached */
803
804    return (0);
805}
806
807
808/*******************************************************************************
809 *
810 * FUNCTION:    LsFinishSourceListing
811 *
812 * PARAMETERS:  FileId          - ID of current listing file.
813 *
814 * RETURN:      None
815 *
816 * DESCRIPTION: Cleanup routine for the listing file. Flush the hex AML
817 *              listing buffer, and flush out any remaining lines in the
818 *              source input file.
819 *
820 ******************************************************************************/
821
822static void
823LsFinishSourceListing (
824    UINT32                  FileId)
825{
826
827    if ((FileId == ASL_FILE_ASM_INCLUDE_OUTPUT) ||
828        (FileId == ASL_FILE_C_INCLUDE_OUTPUT))
829    {
830        return;
831    }
832
833    LsFlushListingBuffer (FileId);
834    Gbl_CurrentAmlOffset = 0;
835
836    /* Flush any remaining text in the source file */
837
838    if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
839    {
840        FlPrintFile (FileId, "    /*\n");
841    }
842
843    while (LsWriteOneSourceLine (FileId))
844    { ; }
845
846    if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
847    {
848        FlPrintFile (FileId, "\n     */\n    };\n");
849    }
850
851    FlPrintFile (FileId, "\n");
852
853    if (FileId == ASL_FILE_LISTING_OUTPUT)
854    {
855        /* Print a summary of the compile exceptions */
856
857        FlPrintFile (FileId, "\n\nSummary of errors and warnings\n\n");
858        AePrintErrorLog (FileId);
859        FlPrintFile (FileId, "\n");
860        UtDisplaySummary (FileId);
861        FlPrintFile (FileId, "\n");
862    }
863}
864
865
866/*******************************************************************************
867 *
868 * FUNCTION:    LsWriteSourceLines
869 *
870 * PARAMETERS:  ToLineNumber            -
871 *              ToLogicalLineNumber     - Write up to this source line number
872 *              FileId                  - ID of current listing file
873 *
874 * RETURN:      None
875 *
876 * DESCRIPTION: Read then write source lines to the listing file until we have
877 *              reached the specified logical (cumulative) line number. This
878 *              automatically echos out comment blocks and other non-AML
879 *              generating text until we get to the actual AML-generating line
880 *              of ASL code specified by the logical line number.
881 *
882 ******************************************************************************/
883
884static void
885LsWriteSourceLines (
886    UINT32                  ToLineNumber,
887    UINT32                  ToLogicalLineNumber,
888    UINT32                  FileId)
889{
890
891    if ((FileId == ASL_FILE_ASM_INCLUDE_OUTPUT) ||
892        (FileId == ASL_FILE_C_INCLUDE_OUTPUT))
893    {
894        return;
895    }
896
897    Gbl_CurrentLine = ToLogicalLineNumber;
898
899    /* Flush any hex bytes remaining from the last opcode */
900
901    LsFlushListingBuffer (FileId);
902
903    /* Read lines and write them as long as we are not caught up */
904
905    if (Gbl_SourceLine < Gbl_CurrentLine)
906    {
907        /*
908         * If we just completed writing some AML hex bytes, output a linefeed
909         * to add some whitespace for readability.
910         */
911        if (Gbl_HexBytesWereWritten)
912        {
913            FlPrintFile (FileId, "\n");
914            Gbl_HexBytesWereWritten = FALSE;
915        }
916
917        if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
918        {
919            FlPrintFile (FileId, "    /*\n");
920        }
921
922        /* Write one line at a time until we have reached the target line # */
923
924        while ((Gbl_SourceLine < Gbl_CurrentLine) &&
925                LsWriteOneSourceLine (FileId))
926        { ; }
927
928        if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
929        {
930            FlPrintFile (FileId, "     */");
931        }
932        FlPrintFile (FileId, "\n");
933    }
934}
935
936
937/*******************************************************************************
938 *
939 * FUNCTION:    LsWriteNodeToListing
940 *
941 * PARAMETERS:  Op            - Parse node to write to the listing file.
942 *              FileId          - ID of current listing file
943 *
944 * RETURN:      None.
945 *
946 * DESCRIPTION: Write "a node" to the listing file. This means to
947 *              1) Write out all of the source text associated with the node
948 *              2) Write out all of the AML bytes associated with the node
949 *              3) Write any compiler exceptions associated with the node
950 *
951 ******************************************************************************/
952
953static void
954LsWriteNodeToListing (
955    ACPI_PARSE_OBJECT       *Op,
956    UINT32                  FileId)
957{
958    const ACPI_OPCODE_INFO  *OpInfo;
959    UINT32                  OpClass;
960    char                    *Pathname;
961    UINT32                  Length;
962    UINT32                  i;
963
964
965    OpInfo  = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
966    OpClass = OpInfo->Class;
967
968    /* TBD: clean this up with a single flag that says:
969     * I start a named output block
970     */
971    if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
972    {
973        switch (Op->Asl.ParseOpcode)
974        {
975        case PARSEOP_DEFINITIONBLOCK:
976        case PARSEOP_METHODCALL:
977        case PARSEOP_INCLUDE:
978        case PARSEOP_INCLUDE_END:
979        case PARSEOP_DEFAULT_ARG:
980
981            break;
982
983        default:
984            switch (OpClass)
985            {
986            case AML_CLASS_NAMED_OBJECT:
987                switch (Op->Asl.AmlOpcode)
988                {
989                case AML_SCOPE_OP:
990                case AML_ALIAS_OP:
991                    break;
992
993                default:
994                    if (Op->Asl.ExternalName)
995                    {
996                        LsFlushListingBuffer (FileId);
997                        FlPrintFile (FileId, "    };\n");
998                    }
999                    break;
1000                }
1001                break;
1002
1003            default:
1004                /* Don't care about other objects */
1005                break;
1006            }
1007            break;
1008        }
1009    }
1010
1011    /* These cases do not have a corresponding AML opcode */
1012
1013    switch (Op->Asl.ParseOpcode)
1014    {
1015    case PARSEOP_DEFINITIONBLOCK:
1016
1017        LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine, FileId);
1018
1019        /* Use the table Signature and TableId to build a unique name */
1020
1021        if (FileId == ASL_FILE_ASM_SOURCE_OUTPUT)
1022        {
1023            FlPrintFile (FileId,
1024                "%s_%s_Header \\\n",
1025                Gbl_TableSignature, Gbl_TableId);
1026        }
1027        if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
1028        {
1029            FlPrintFile (FileId,
1030                "    unsigned char    %s_%s_Header [] =\n    {\n",
1031                Gbl_TableSignature, Gbl_TableId);
1032        }
1033        if (FileId == ASL_FILE_ASM_INCLUDE_OUTPUT)
1034        {
1035            FlPrintFile (FileId,
1036                "extrn %s_%s_Header : byte\n",
1037                Gbl_TableSignature, Gbl_TableId);
1038        }
1039        if (FileId == ASL_FILE_C_INCLUDE_OUTPUT)
1040        {
1041            FlPrintFile (FileId,
1042                "extern unsigned char    %s_%s_Header [];\n",
1043                Gbl_TableSignature, Gbl_TableId);
1044        }
1045        return;
1046
1047
1048    case PARSEOP_METHODCALL:
1049
1050        LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
1051            FileId);
1052        return;
1053
1054
1055    case PARSEOP_INCLUDE:
1056
1057        /* Flush everything up to and including the include source line */
1058
1059        LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
1060            FileId);
1061
1062        /* Create a new listing node and push it */
1063
1064        LsPushNode (Op->Asl.Child->Asl.Value.String);
1065        return;
1066
1067
1068    case PARSEOP_INCLUDE_END:
1069
1070        /* Flush out the rest of the include file */
1071
1072        LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
1073            FileId);
1074
1075        /* Pop off this listing node and go back to the parent file */
1076
1077        (void) LsPopNode ();
1078        return;
1079
1080
1081    case PARSEOP_DEFAULT_ARG:
1082
1083        if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC)
1084        {
1085            LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.EndLogicalLine,
1086                FileId);
1087        }
1088        return;
1089
1090
1091    default:
1092        /* All other opcodes have an AML opcode */
1093        break;
1094    }
1095
1096    /*
1097     * Otherwise, we look at the AML opcode because we can
1098     * switch on the opcode type, getting an entire class
1099     * at once
1100     */
1101    switch (OpClass)
1102    {
1103    case AML_CLASS_ARGUMENT:       /* argument type only */
1104    case AML_CLASS_INTERNAL:
1105
1106        break;
1107
1108
1109    case AML_CLASS_NAMED_OBJECT:
1110
1111        switch (Op->Asl.AmlOpcode)
1112        {
1113        case AML_FIELD_OP:
1114        case AML_INDEX_FIELD_OP:
1115        case AML_BANK_FIELD_OP:
1116
1117            /*
1118             * For fields, we want to dump all the AML after the
1119             * entire definition
1120             */
1121            LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine,
1122                FileId);
1123            break;
1124
1125        case AML_NAME_OP:
1126
1127            if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC)
1128            {
1129                LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
1130                    FileId);
1131            }
1132            else
1133            {
1134                /*
1135                 * For fields, we want to dump all the AML after the
1136                 * entire definition
1137                 */
1138                LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine,
1139                    FileId);
1140            }
1141            break;
1142
1143        default:
1144            LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
1145                FileId);
1146            break;
1147        }
1148
1149        switch (Op->Asl.AmlOpcode)
1150        {
1151        case AML_SCOPE_OP:
1152        case AML_ALIAS_OP:
1153
1154            /* These opcodes do not declare a new object, ignore them */
1155
1156            break;
1157
1158        default:
1159
1160            /* All other named object opcodes come here */
1161
1162            switch (FileId)
1163            {
1164            case ASL_FILE_ASM_SOURCE_OUTPUT:
1165            case ASL_FILE_C_SOURCE_OUTPUT:
1166            case ASL_FILE_ASM_INCLUDE_OUTPUT:
1167            case ASL_FILE_C_INCLUDE_OUTPUT:
1168
1169                /*
1170                 * For named objects, we will create a valid symbol so that the
1171                 * AML code can be referenced from C or ASM
1172                 */
1173                if (Op->Asl.ExternalName)
1174                {
1175                    /* Get the full pathname associated with this node */
1176
1177                    Pathname = AcpiNsGetExternalPathname (Op->Asl.Node);
1178                    Length = strlen (Pathname);
1179                    if (Length >= 4)
1180                    {
1181                        /* Convert all dots in the path to underscores */
1182
1183                        for (i = 0; i < Length; i++)
1184                        {
1185                            if (Pathname[i] == '.')
1186                            {
1187                                Pathname[i] = '_';
1188                            }
1189                        }
1190
1191                        /* Create the appropriate symbol in the output file */
1192
1193                        if (FileId == ASL_FILE_ASM_SOURCE_OUTPUT)
1194                        {
1195                            FlPrintFile (FileId,
1196                                "%s_%s_%s  \\\n",
1197                                Gbl_TableSignature, Gbl_TableId, &Pathname[1]);
1198                        }
1199                        if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
1200                        {
1201                            FlPrintFile (FileId,
1202                                "    unsigned char    %s_%s_%s [] =\n    {\n",
1203                                Gbl_TableSignature, Gbl_TableId, &Pathname[1]);
1204                        }
1205                        if (FileId == ASL_FILE_ASM_INCLUDE_OUTPUT)
1206                        {
1207                            FlPrintFile (FileId,
1208                                "extrn %s_%s_%s : byte\n",
1209                                Gbl_TableSignature, Gbl_TableId, &Pathname[1]);
1210                        }
1211                        if (FileId == ASL_FILE_C_INCLUDE_OUTPUT)
1212                        {
1213                            FlPrintFile (FileId,
1214                                "extern unsigned char    %s_%s_%s [];\n",
1215                                Gbl_TableSignature, Gbl_TableId, &Pathname[1]);
1216                        }
1217                    }
1218                    ACPI_FREE (Pathname);
1219                }
1220                break;
1221
1222            default:
1223                /* Nothing to do for listing file */
1224                break;
1225            }
1226        }
1227        break;
1228
1229    case AML_CLASS_EXECUTE:
1230    case AML_CLASS_CREATE:
1231    default:
1232
1233        if ((Op->Asl.ParseOpcode == PARSEOP_BUFFER) &&
1234            (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC))
1235        {
1236            return;
1237        }
1238
1239        LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
1240            FileId);
1241        break;
1242
1243    case AML_CLASS_UNKNOWN:
1244        break;
1245    }
1246}
1247