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