dtio.c revision 240716
1/******************************************************************************
2 *
3 * Module Name: dtio.c - File I/O support for data table compiler
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#define __DTIO_C__
45
46#include <contrib/dev/acpica/compiler/aslcompiler.h>
47#include <contrib/dev/acpica/compiler/dtcompiler.h>
48
49#define _COMPONENT          DT_COMPILER
50        ACPI_MODULE_NAME    ("dtio")
51
52
53/* Local prototypes */
54
55static char *
56DtTrim (
57    char                    *String);
58
59static void
60DtLinkField (
61    DT_FIELD                *Field);
62
63static ACPI_STATUS
64DtParseLine (
65    char                    *LineBuffer,
66    UINT32                  Line,
67    UINT32                  Offset);
68
69static void
70DtWriteBinary (
71    DT_SUBTABLE             *Subtable,
72    void                    *Context,
73    void                    *ReturnValue);
74
75static void
76DtDumpBuffer (
77    UINT32                  FileId,
78    UINT8                   *Buffer,
79    UINT32                  Offset,
80    UINT32                  Length);
81
82
83/* States for DtGetNextLine */
84
85#define DT_NORMAL_TEXT              0
86#define DT_START_QUOTED_STRING      1
87#define DT_START_COMMENT            2
88#define DT_SLASH_ASTERISK_COMMENT   3
89#define DT_SLASH_SLASH_COMMENT      4
90#define DT_END_COMMENT              5
91#define DT_MERGE_LINES              6
92#define DT_ESCAPE_SEQUENCE          7
93
94static UINT32  Gbl_NextLineOffset;
95
96
97/******************************************************************************
98 *
99 * FUNCTION:    DtTrim
100 *
101 * PARAMETERS:  String              - Current source code line to trim
102 *
103 * RETURN:      Trimmed line. Must be freed by caller.
104 *
105 * DESCRIPTION: Trim left and right spaces
106 *
107 *****************************************************************************/
108
109static char *
110DtTrim (
111    char                    *String)
112{
113    char                    *Start;
114    char                    *End;
115    char                    *ReturnString;
116    ACPI_SIZE               Length;
117
118
119    /* Skip lines that start with a space */
120
121    if (!ACPI_STRCMP (String, " "))
122    {
123        ReturnString = UtLocalCalloc (1);
124        return (ReturnString);
125    }
126
127    /* Setup pointers to start and end of input string */
128
129    Start = String;
130    End = String + ACPI_STRLEN (String) - 1;
131
132    /* Find first non-whitespace character */
133
134    while ((Start <= End) && ((*Start == ' ') || (*Start == '\t')))
135    {
136        Start++;
137    }
138
139    /* Find last non-space character */
140
141    while (End >= Start)
142    {
143        if (*End == '\r' || *End == '\n')
144        {
145            End--;
146            continue;
147        }
148
149        if (*End != ' ')
150        {
151            break;
152        }
153
154        End--;
155    }
156
157    /* Remove any quotes around the string */
158
159    if (*Start == '\"')
160    {
161        Start++;
162    }
163    if (*End == '\"')
164    {
165        End--;
166    }
167
168    /* Create the trimmed return string */
169
170    Length = ACPI_PTR_DIFF (End, Start) + 1;
171    ReturnString = UtLocalCalloc (Length + 1);
172    if (ACPI_STRLEN (Start))
173    {
174        ACPI_STRNCPY (ReturnString, Start, Length);
175    }
176
177    ReturnString[Length] = 0;
178    return (ReturnString);
179}
180
181
182/******************************************************************************
183 *
184 * FUNCTION:    DtLinkField
185 *
186 * PARAMETERS:  Field               - New field object to link
187 *
188 * RETURN:      None
189 *
190 * DESCRIPTION: Link one field name and value to the list
191 *
192 *****************************************************************************/
193
194static void
195DtLinkField (
196    DT_FIELD                *Field)
197{
198    DT_FIELD                *Prev;
199    DT_FIELD                *Next;
200
201
202    Prev = Next = Gbl_FieldList;
203
204    while (Next)
205    {
206        Prev = Next;
207        Next = Next->Next;
208    }
209
210    if (Prev)
211    {
212        Prev->Next = Field;
213    }
214    else
215    {
216        Gbl_FieldList = Field;
217    }
218}
219
220
221/******************************************************************************
222 *
223 * FUNCTION:    DtParseLine
224 *
225 * PARAMETERS:  LineBuffer          - Current source code line
226 *              Line                - Current line number in the source
227 *              Offset              - Current byte offset of the line
228 *
229 * RETURN:      Status
230 *
231 * DESCRIPTION: Parse one source line
232 *
233 *****************************************************************************/
234
235static ACPI_STATUS
236DtParseLine (
237    char                    *LineBuffer,
238    UINT32                  Line,
239    UINT32                  Offset)
240{
241    char                    *Start;
242    char                    *End;
243    char                    *TmpName;
244    char                    *TmpValue;
245    char                    *Name;
246    char                    *Value;
247    char                    *Colon;
248    UINT32                  Length;
249    DT_FIELD                *Field;
250    UINT32                  Column;
251    UINT32                  NameColumn;
252    BOOLEAN                 IsNullString = FALSE;
253
254
255    if (!LineBuffer)
256    {
257        return (AE_OK);
258    }
259
260    /* All lines after "Raw Table Data" are ingored */
261
262    if (strstr (LineBuffer, ACPI_RAW_TABLE_DATA_HEADER))
263    {
264        return (AE_NOT_FOUND);
265    }
266
267    Colon = strchr (LineBuffer, ':');
268    if (!Colon)
269    {
270        return (AE_OK);
271    }
272
273    Start = LineBuffer;
274    End = Colon;
275
276    while (Start < Colon)
277    {
278        if (*Start == ' ')
279        {
280            Start++;
281            continue;
282        }
283
284        /* Found left bracket, go to the right bracket */
285
286        if (*Start == '[')
287        {
288            while (Start < Colon && *Start != ']')
289            {
290                Start++;
291            }
292
293            if (Start == Colon)
294            {
295                break;
296            }
297
298            Start++;
299            continue;
300        }
301
302        break;
303    }
304
305    /*
306     * There are two column values. One for the field name,
307     * and one for the field value.
308     */
309    Column = ACPI_PTR_DIFF (Colon, LineBuffer) + 3;
310    NameColumn = ACPI_PTR_DIFF (Start, LineBuffer) + 1;
311
312    Length = ACPI_PTR_DIFF (End, Start);
313
314    TmpName = UtLocalCalloc (Length + 1);
315    ACPI_STRNCPY (TmpName, Start, Length);
316    Name = DtTrim (TmpName);
317    ACPI_FREE (TmpName);
318
319    Start = End = (Colon + 1);
320    while (*End)
321    {
322        /* Found left quotation, go to the right quotation and break */
323
324        if (*End == '"')
325        {
326            End++;
327
328            /* Check for an explicit null string */
329
330            if (*End == '"')
331            {
332                IsNullString = TRUE;
333            }
334            while (*End && (*End != '"'))
335            {
336                End++;
337            }
338
339            End++;
340            break;
341        }
342
343        /*
344         * Special "comment" fields at line end, ignore them.
345         * Note: normal slash-slash and slash-asterisk comments are
346         * stripped already by the DtGetNextLine parser.
347         *
348         * TBD: Perhaps DtGetNextLine should parse the following type
349         * of comments also.
350         */
351        if (*End == '[')
352        {
353            End--;
354            break;
355        }
356        End++;
357    }
358
359    Length = ACPI_PTR_DIFF (End, Start);
360    TmpValue = UtLocalCalloc (Length + 1);
361
362    ACPI_STRNCPY (TmpValue, Start, Length);
363    Value = DtTrim (TmpValue);
364    ACPI_FREE (TmpValue);
365
366    /* Create a new field object only if we have a valid value field */
367
368    if ((Value && *Value) || IsNullString)
369    {
370        Field = UtLocalCalloc (sizeof (DT_FIELD));
371        Field->Name = Name;
372        Field->Value = Value;
373        Field->Line = Line;
374        Field->ByteOffset = Offset;
375        Field->NameColumn = NameColumn;
376        Field->Column = Column;
377
378        DtLinkField (Field);
379    }
380    else /* Ignore this field, it has no valid data */
381    {
382        ACPI_FREE (Name);
383        ACPI_FREE (Value);
384    }
385
386    return (AE_OK);
387}
388
389
390/******************************************************************************
391 *
392 * FUNCTION:    DtGetNextLine
393 *
394 * PARAMETERS:  Handle              - Open file handle for the source file
395 *
396 * RETURN:      Filled line buffer and offset of start-of-line (ASL_EOF on EOF)
397 *
398 * DESCRIPTION: Get the next valid source line. Removes all comments.
399 *              Ignores empty lines.
400 *
401 * Handles both slash-asterisk and slash-slash comments.
402 * Also, quoted strings, but no escapes within.
403 *
404 * Line is returned in Gbl_CurrentLineBuffer.
405 * Line number in original file is returned in Gbl_CurrentLineNumber.
406 *
407 *****************************************************************************/
408
409UINT32
410DtGetNextLine (
411    FILE                    *Handle)
412{
413    BOOLEAN                 LineNotAllBlanks = FALSE;
414    UINT32                  State = DT_NORMAL_TEXT;
415    UINT32                  CurrentLineOffset;
416    UINT32                  i;
417    char                    c;
418
419
420    for (i = 0; ;)
421    {
422        /*
423         * If line is too long, expand the line buffers. Also increases
424         * Gbl_LineBufferSize.
425         */
426        if (i >= Gbl_LineBufferSize)
427        {
428            UtExpandLineBuffers ();
429        }
430
431        c = (char) getc (Handle);
432        if (c == EOF)
433        {
434            switch (State)
435            {
436            case DT_START_QUOTED_STRING:
437            case DT_SLASH_ASTERISK_COMMENT:
438
439                AcpiOsPrintf ("**** EOF within comment/string %u\n", State);
440                break;
441
442            default:
443                break;
444            }
445
446            /* Standalone EOF is OK */
447
448            if (i == 0)
449            {
450                return (ASL_EOF);
451            }
452
453            /*
454             * Received an EOF in the middle of a line. Terminate the
455             * line with a newline. The next call to this function will
456             * return a standalone EOF. Thus, the upper parsing software
457             * never has to deal with an EOF within a valid line (or
458             * the last line does not get tossed on the floor.)
459             */
460            c = '\n';
461            State = DT_NORMAL_TEXT;
462        }
463
464        switch (State)
465        {
466        case DT_NORMAL_TEXT:
467
468            /* Normal text, insert char into line buffer */
469
470            Gbl_CurrentLineBuffer[i] = c;
471            switch (c)
472            {
473            case '/':
474                State = DT_START_COMMENT;
475                break;
476
477            case '"':
478                State = DT_START_QUOTED_STRING;
479                LineNotAllBlanks = TRUE;
480                i++;
481                break;
482
483            case '\\':
484                /*
485                 * The continuation char MUST be last char on this line.
486                 * Otherwise, it will be assumed to be a valid ASL char.
487                 */
488                State = DT_MERGE_LINES;
489                break;
490
491            case '\n':
492                CurrentLineOffset = Gbl_NextLineOffset;
493                Gbl_NextLineOffset = (UINT32) ftell (Handle);
494                Gbl_CurrentLineNumber++;
495
496                /*
497                 * Exit if line is complete. Ignore empty lines (only \n)
498                 * or lines that contain nothing but blanks.
499                 */
500                if ((i != 0) && LineNotAllBlanks)
501                {
502                    if ((i + 1) >= Gbl_LineBufferSize)
503                    {
504                        UtExpandLineBuffers ();
505                    }
506
507                    Gbl_CurrentLineBuffer[i+1] = 0; /* Terminate string */
508                    return (CurrentLineOffset);
509                }
510
511                /* Toss this line and start a new one */
512
513                i = 0;
514                LineNotAllBlanks = FALSE;
515                break;
516
517            default:
518                if (c != ' ')
519                {
520                    LineNotAllBlanks = TRUE;
521                }
522
523                i++;
524                break;
525            }
526            break;
527
528        case DT_START_QUOTED_STRING:
529
530            /* Insert raw chars until end of quoted string */
531
532            Gbl_CurrentLineBuffer[i] = c;
533            i++;
534
535            switch (c)
536            {
537            case '"':
538                State = DT_NORMAL_TEXT;
539                break;
540
541            case '\\':
542                State = DT_ESCAPE_SEQUENCE;
543                break;
544
545            case '\n':
546                AcpiOsPrintf ("ERROR at line %u: Unterminated quoted string\n",
547                    Gbl_CurrentLineNumber++);
548                State = DT_NORMAL_TEXT;
549                break;
550
551            default:    /* Get next character */
552                break;
553            }
554            break;
555
556        case DT_ESCAPE_SEQUENCE:
557
558            /* Just copy the escaped character. TBD: sufficient for table compiler? */
559
560            Gbl_CurrentLineBuffer[i] = c;
561            i++;
562            State = DT_START_QUOTED_STRING;
563            break;
564
565        case DT_START_COMMENT:
566
567            /* Open comment if this character is an asterisk or slash */
568
569            switch (c)
570            {
571            case '*':
572                State = DT_SLASH_ASTERISK_COMMENT;
573                break;
574
575            case '/':
576                State = DT_SLASH_SLASH_COMMENT;
577                break;
578
579            default:    /* Not a comment */
580                i++;    /* Save the preceeding slash */
581                if (i >= Gbl_LineBufferSize)
582                {
583                    UtExpandLineBuffers ();
584                }
585
586                Gbl_CurrentLineBuffer[i] = c;
587                i++;
588                State = DT_NORMAL_TEXT;
589                break;
590            }
591            break;
592
593        case DT_SLASH_ASTERISK_COMMENT:
594
595            /* Ignore chars until an asterisk-slash is found */
596
597            switch (c)
598            {
599            case '\n':
600                Gbl_NextLineOffset = (UINT32) ftell (Handle);
601                Gbl_CurrentLineNumber++;
602                break;
603
604            case '*':
605                State = DT_END_COMMENT;
606                break;
607
608            default:
609                break;
610            }
611            break;
612
613        case DT_SLASH_SLASH_COMMENT:
614
615            /* Ignore chars until end-of-line */
616
617            if (c == '\n')
618            {
619                /* We will exit via the NORMAL_TEXT path */
620
621                ungetc (c, Handle);
622                State = DT_NORMAL_TEXT;
623            }
624            break;
625
626        case DT_END_COMMENT:
627
628            /* End comment if this char is a slash */
629
630            switch (c)
631            {
632            case '/':
633                State = DT_NORMAL_TEXT;
634                break;
635
636            case '\n':
637                CurrentLineOffset = Gbl_NextLineOffset;
638                Gbl_NextLineOffset = (UINT32) ftell (Handle);
639                Gbl_CurrentLineNumber++;
640                break;
641
642            case '*':
643                /* Consume all adjacent asterisks */
644                break;
645
646            default:
647                State = DT_SLASH_ASTERISK_COMMENT;
648                break;
649            }
650            break;
651
652        case DT_MERGE_LINES:
653
654            if (c != '\n')
655            {
656                /*
657                 * This is not a continuation backslash, it is a normal
658                 * normal ASL backslash - for example: Scope(\_SB_)
659                 */
660                i++; /* Keep the backslash that is already in the buffer */
661
662                ungetc (c, Handle);
663                State = DT_NORMAL_TEXT;
664            }
665            else
666            {
667                /*
668                 * This is a continuation line -- a backlash followed
669                 * immediately by a newline. Insert a space between the
670                 * lines (overwrite the backslash)
671                 */
672                Gbl_CurrentLineBuffer[i] = ' ';
673                i++;
674
675                /* Ignore newline, this will merge the lines */
676
677                CurrentLineOffset = Gbl_NextLineOffset;
678                Gbl_NextLineOffset = (UINT32) ftell (Handle);
679                Gbl_CurrentLineNumber++;
680                State = DT_NORMAL_TEXT;
681            }
682            break;
683
684        default:
685            DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, "Unknown input state");
686            return (ASL_EOF);
687        }
688    }
689}
690
691
692/******************************************************************************
693 *
694 * FUNCTION:    DtScanFile
695 *
696 * PARAMETERS:  Handle              - Open file handle for the source file
697 *
698 * RETURN:      Pointer to start of the constructed parse tree.
699 *
700 * DESCRIPTION: Scan source file, link all field names and values
701 *              to the global parse tree: Gbl_FieldList
702 *
703 *****************************************************************************/
704
705DT_FIELD *
706DtScanFile (
707    FILE                    *Handle)
708{
709    ACPI_STATUS             Status;
710    UINT32                  Offset;
711    DT_FIELD                *Next;
712
713
714    ACPI_FUNCTION_NAME (DtScanFile);
715
716
717    /* Get the file size */
718
719    Gbl_InputByteCount = DtGetFileSize (Handle);
720
721    Gbl_CurrentLineNumber = 0;
722    Gbl_CurrentLineOffset = 0;
723    Gbl_NextLineOffset = 0;
724
725    /* Scan line-by-line */
726
727    while ((Offset = DtGetNextLine (Handle)) != ASL_EOF)
728    {
729        ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Line %2.2u/%4.4X - %s",
730            Gbl_CurrentLineNumber, Offset, Gbl_CurrentLineBuffer));
731
732        Status = DtParseLine (Gbl_CurrentLineBuffer, Gbl_CurrentLineNumber, Offset);
733        if (Status == AE_NOT_FOUND)
734        {
735            break;
736        }
737    }
738
739    /* Dump the parse tree if debug enabled */
740
741    if (Gbl_DebugFlag)
742    {
743        Next = Gbl_FieldList;
744        DbgPrint (ASL_DEBUG_OUTPUT, "Tree:  %32s %32s %8s %8s %8s %8s %8s %8s\n\n",
745            "Name", "Value", "Line", "ByteOff", "NameCol", "Column", "TableOff", "Flags");
746
747        while (Next)
748        {
749            DbgPrint (ASL_DEBUG_OUTPUT, "Field: %32.32s %32.32s %.8X %.8X %.8X %.8X %.8X %.8X\n",
750                Next->Name,
751                Next->Value,
752                Next->Line,
753                Next->ByteOffset,
754                Next->NameColumn,
755                Next->Column,
756                Next->TableOffset,
757                Next->Flags);
758
759            Next = Next->Next;
760        }
761    }
762
763    return (Gbl_FieldList);
764}
765
766
767/*
768 * Output functions
769 */
770
771/******************************************************************************
772 *
773 * FUNCTION:    DtWriteBinary
774 *
775 * PARAMETERS:  DT_WALK_CALLBACK
776 *
777 * RETURN:      Status
778 *
779 * DESCRIPTION: Write one subtable of a binary ACPI table
780 *
781 *****************************************************************************/
782
783static void
784DtWriteBinary (
785    DT_SUBTABLE             *Subtable,
786    void                    *Context,
787    void                    *ReturnValue)
788{
789
790    FlWriteFile (ASL_FILE_AML_OUTPUT, Subtable->Buffer, Subtable->Length);
791}
792
793
794/******************************************************************************
795 *
796 * FUNCTION:    DtOutputBinary
797 *
798 * PARAMETERS:
799 *
800 * RETURN:      Status
801 *
802 * DESCRIPTION: Write entire binary ACPI table (result of compilation)
803 *
804 *****************************************************************************/
805
806void
807DtOutputBinary (
808    DT_SUBTABLE             *RootTable)
809{
810
811    if (!RootTable)
812    {
813        return;
814    }
815
816    /* Walk the entire parse tree, emitting the binary data */
817
818    DtWalkTableTree (RootTable, DtWriteBinary, NULL, NULL);
819    Gbl_TableLength = DtGetFileSize (Gbl_Files[ASL_FILE_AML_OUTPUT].Handle);
820}
821
822
823/*
824 * Listing support
825 */
826
827/******************************************************************************
828 *
829 * FUNCTION:    DtDumpBuffer
830 *
831 * PARAMETERS:  FileID              - Where to write buffer data
832 *              Buffer              - Buffer to dump
833 *              Offset              - Offset in current table
834 *              Length              - Buffer Length
835 *
836 * RETURN:      None
837 *
838 * DESCRIPTION: Another copy of DumpBuffer routine (unfortunately).
839 *
840 * TBD: merge dump buffer routines
841 *
842 *****************************************************************************/
843
844static void
845DtDumpBuffer (
846    UINT32                  FileId,
847    UINT8                   *Buffer,
848    UINT32                  Offset,
849    UINT32                  Length)
850{
851    UINT32                  i;
852    UINT32                  j;
853    UINT8                   BufChar;
854
855
856    FlPrintFile (FileId, "Output: [%3.3Xh %4.4d %3d] ",
857        Offset, Offset, Length);
858
859    i = 0;
860    while (i < Length)
861    {
862        if (i >= 16)
863        {
864            FlPrintFile (FileId, "%24s", "");
865        }
866
867        /* Print 16 hex chars */
868
869        for (j = 0; j < 16;)
870        {
871            if (i + j >= Length)
872            {
873                /* Dump fill spaces */
874
875                FlPrintFile (FileId, "   ");
876                j++;
877                continue;
878            }
879
880            FlPrintFile (FileId, "%02X ", Buffer[i+j]);
881            j++;
882        }
883
884        FlPrintFile (FileId, " ");
885        for (j = 0; j < 16; j++)
886        {
887            if (i + j >= Length)
888            {
889                FlPrintFile (FileId, "\n\n");
890                return;
891            }
892
893            BufChar = Buffer[(ACPI_SIZE) i + j];
894            if (ACPI_IS_PRINT (BufChar))
895            {
896                FlPrintFile (FileId, "%c", BufChar);
897            }
898            else
899            {
900                FlPrintFile (FileId, ".");
901            }
902        }
903
904        /* Done with that line. */
905
906        FlPrintFile (FileId, "\n");
907        i += 16;
908    }
909
910    FlPrintFile (FileId, "\n\n");
911}
912
913
914/******************************************************************************
915 *
916 * FUNCTION:    DtWriteFieldToListing
917 *
918 * PARAMETERS:  Buffer              - Contains the compiled data
919 *              Field               - Field node for the input line
920 *              Length              - Length of the output data
921 *
922 * RETURN:      None
923 *
924 * DESCRIPTION: Write one field to the listing file (if listing is enabled).
925 *
926 *****************************************************************************/
927
928void
929DtWriteFieldToListing (
930    UINT8                   *Buffer,
931    DT_FIELD                *Field,
932    UINT32                  Length)
933{
934    UINT8                   FileByte;
935
936
937    if (!Gbl_ListingFlag || !Field)
938    {
939        return;
940    }
941
942    /* Dump the original source line */
943
944    FlPrintFile (ASL_FILE_LISTING_OUTPUT, "Input:  ");
945    FlSeekFile (ASL_FILE_INPUT, Field->ByteOffset);
946
947    while (FlReadFile (ASL_FILE_INPUT, &FileByte, 1) == AE_OK)
948    {
949        FlWriteFile (ASL_FILE_LISTING_OUTPUT, &FileByte, 1);
950        if (FileByte == '\n')
951        {
952            break;
953        }
954    }
955
956    /* Dump the line as parsed and represented internally */
957
958    FlPrintFile (ASL_FILE_LISTING_OUTPUT, "Parsed: %*s : %.64s",
959        Field->Column-4, Field->Name, Field->Value);
960
961    if (strlen (Field->Value) > 64)
962    {
963        FlPrintFile (ASL_FILE_LISTING_OUTPUT, "...Additional data, length 0x%X\n",
964            strlen (Field->Value));
965    }
966    FlPrintFile (ASL_FILE_LISTING_OUTPUT, "\n");
967
968    /* Dump the hex data that will be output for this field */
969
970    DtDumpBuffer (ASL_FILE_LISTING_OUTPUT, Buffer, Field->TableOffset, Length);
971}
972
973
974/******************************************************************************
975 *
976 * FUNCTION:    DtWriteTableToListing
977 *
978 * PARAMETERS:  None
979 *
980 * RETURN:      None
981 *
982 * DESCRIPTION: Write the entire compiled table to the listing file
983 *              in hex format
984 *
985 *****************************************************************************/
986
987void
988DtWriteTableToListing (
989    void)
990{
991    UINT8                   *Buffer;
992
993
994    if (!Gbl_ListingFlag)
995    {
996        return;
997    }
998
999    /* Read the entire table from the output file */
1000
1001    Buffer = UtLocalCalloc (Gbl_TableLength);
1002    FlSeekFile (ASL_FILE_AML_OUTPUT, 0);
1003    FlReadFile (ASL_FILE_AML_OUTPUT, Buffer, Gbl_TableLength);
1004
1005    /* Dump the raw table data */
1006
1007    AcpiOsRedirectOutput (Gbl_Files[ASL_FILE_LISTING_OUTPUT].Handle);
1008
1009    AcpiOsPrintf ("\n%s: Length %d (0x%X)\n\n",
1010        ACPI_RAW_TABLE_DATA_HEADER, Gbl_TableLength, Gbl_TableLength);
1011    AcpiUtDumpBuffer2 (Buffer, Gbl_TableLength, DB_BYTE_DISPLAY);
1012
1013    AcpiOsRedirectOutput (stdout);
1014}
1015