Home | History | Annotate | Line # | Download | only in compiler
dtio.c revision 1.1.1.8
      1 /******************************************************************************
      2  *
      3  * Module Name: dtio.c - File I/O support for data table compiler
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2016, Intel Corp.
      9  * All rights reserved.
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted provided that the following conditions
     13  * are met:
     14  * 1. Redistributions of source code must retain the above copyright
     15  *    notice, this list of conditions, and the following disclaimer,
     16  *    without modification.
     17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
     18  *    substantially similar to the "NO WARRANTY" disclaimer below
     19  *    ("Disclaimer") and any redistribution must be conditioned upon
     20  *    including a substantially similar Disclaimer requirement for further
     21  *    binary redistribution.
     22  * 3. Neither the names of the above-listed copyright holders nor the names
     23  *    of any contributors may be used to endorse or promote products derived
     24  *    from this software without specific prior written permission.
     25  *
     26  * Alternatively, this software may be distributed under the terms of the
     27  * GNU General Public License ("GPL") version 2 as published by the Free
     28  * Software Foundation.
     29  *
     30  * NO WARRANTY
     31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
     34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
     40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     41  * POSSIBILITY OF SUCH DAMAGES.
     42  */
     43 
     44 #include "aslcompiler.h"
     45 #include "dtcompiler.h"
     46 #include "acapps.h"
     47 
     48 #define _COMPONENT          DT_COMPILER
     49         ACPI_MODULE_NAME    ("dtio")
     50 
     51 
     52 /* Local prototypes */
     53 
     54 static char *
     55 DtTrim (
     56     char                    *String);
     57 
     58 static void
     59 DtLinkField (
     60     DT_FIELD                *Field);
     61 
     62 static ACPI_STATUS
     63 DtParseLine (
     64     char                    *LineBuffer,
     65     UINT32                  Line,
     66     UINT32                  Offset);
     67 
     68 static void
     69 DtWriteBinary (
     70     DT_SUBTABLE             *Subtable,
     71     void                    *Context,
     72     void                    *ReturnValue);
     73 
     74 static void
     75 DtDumpBuffer (
     76     UINT32                  FileId,
     77     UINT8                   *Buffer,
     78     UINT32                  Offset,
     79     UINT32                  Length);
     80 
     81 static void
     82 DtDumpSubtableInfo (
     83     DT_SUBTABLE             *Subtable,
     84     void                    *Context,
     85     void                    *ReturnValue);
     86 
     87 static void
     88 DtDumpSubtableTree (
     89     DT_SUBTABLE             *Subtable,
     90     void                    *Context,
     91     void                    *ReturnValue);
     92 
     93 
     94 /* States for DtGetNextLine */
     95 
     96 #define DT_NORMAL_TEXT              0
     97 #define DT_START_QUOTED_STRING      1
     98 #define DT_START_COMMENT            2
     99 #define DT_SLASH_ASTERISK_COMMENT   3
    100 #define DT_SLASH_SLASH_COMMENT      4
    101 #define DT_END_COMMENT              5
    102 #define DT_MERGE_LINES              6
    103 #define DT_ESCAPE_SEQUENCE          7
    104 
    105 static UINT32               Gbl_NextLineOffset;
    106 
    107 
    108 /******************************************************************************
    109  *
    110  * FUNCTION:    DtTrim
    111  *
    112  * PARAMETERS:  String              - Current source code line to trim
    113  *
    114  * RETURN:      Trimmed line. Must be freed by caller.
    115  *
    116  * DESCRIPTION: Trim left and right spaces
    117  *
    118  *****************************************************************************/
    119 
    120 static char *
    121 DtTrim (
    122     char                    *String)
    123 {
    124     char                    *Start;
    125     char                    *End;
    126     char                    *ReturnString;
    127     ACPI_SIZE               Length;
    128 
    129 
    130     /* Skip lines that start with a space */
    131 
    132     if (!strcmp (String, " "))
    133     {
    134         ReturnString = UtStringCacheCalloc (1);
    135         return (ReturnString);
    136     }
    137 
    138     /* Setup pointers to start and end of input string */
    139 
    140     Start = String;
    141     End = String + strlen (String) - 1;
    142 
    143     /* Find first non-whitespace character */
    144 
    145     while ((Start <= End) && ((*Start == ' ') || (*Start == '\t')))
    146     {
    147         Start++;
    148     }
    149 
    150     /* Find last non-space character */
    151 
    152     while (End >= Start)
    153     {
    154         if (*End == '\r' || *End == '\n')
    155         {
    156             End--;
    157             continue;
    158         }
    159 
    160         if (*End != ' ')
    161         {
    162             break;
    163         }
    164 
    165         End--;
    166     }
    167 
    168     /* Remove any quotes around the string */
    169 
    170     if (*Start == '\"')
    171     {
    172         Start++;
    173     }
    174     if (*End == '\"')
    175     {
    176         End--;
    177     }
    178 
    179     /* Create the trimmed return string */
    180 
    181     Length = ACPI_PTR_DIFF (End, Start) + 1;
    182     ReturnString = UtStringCacheCalloc (Length + 1);
    183     if (strlen (Start))
    184     {
    185         strncpy (ReturnString, Start, Length);
    186     }
    187 
    188     ReturnString[Length] = 0;
    189     return (ReturnString);
    190 }
    191 
    192 
    193 /******************************************************************************
    194  *
    195  * FUNCTION:    DtLinkField
    196  *
    197  * PARAMETERS:  Field               - New field object to link
    198  *
    199  * RETURN:      None
    200  *
    201  * DESCRIPTION: Link one field name and value to the list
    202  *
    203  *****************************************************************************/
    204 
    205 static void
    206 DtLinkField (
    207     DT_FIELD                *Field)
    208 {
    209     DT_FIELD                *Prev;
    210     DT_FIELD                *Next;
    211 
    212 
    213     Prev = Next = Gbl_FieldList;
    214 
    215     while (Next)
    216     {
    217         Prev = Next;
    218         Next = Next->Next;
    219     }
    220 
    221     if (Prev)
    222     {
    223         Prev->Next = Field;
    224     }
    225     else
    226     {
    227         Gbl_FieldList = Field;
    228     }
    229 }
    230 
    231 
    232 /******************************************************************************
    233  *
    234  * FUNCTION:    DtParseLine
    235  *
    236  * PARAMETERS:  LineBuffer          - Current source code line
    237  *              Line                - Current line number in the source
    238  *              Offset              - Current byte offset of the line
    239  *
    240  * RETURN:      Status
    241  *
    242  * DESCRIPTION: Parse one source line
    243  *
    244  *****************************************************************************/
    245 
    246 static ACPI_STATUS
    247 DtParseLine (
    248     char                    *LineBuffer,
    249     UINT32                  Line,
    250     UINT32                  Offset)
    251 {
    252     char                    *Start;
    253     char                    *End;
    254     char                    *TmpName;
    255     char                    *TmpValue;
    256     char                    *Name;
    257     char                    *Value;
    258     char                    *Colon;
    259     UINT32                  Length;
    260     DT_FIELD                *Field;
    261     UINT32                  Column;
    262     UINT32                  NameColumn;
    263     BOOLEAN                 IsNullString = FALSE;
    264 
    265 
    266     if (!LineBuffer)
    267     {
    268         return (AE_OK);
    269     }
    270 
    271     /* All lines after "Raw Table Data" are ingored */
    272 
    273     if (strstr (LineBuffer, ACPI_RAW_TABLE_DATA_HEADER))
    274     {
    275         return (AE_NOT_FOUND);
    276     }
    277 
    278     Colon = strchr (LineBuffer, ':');
    279     if (!Colon)
    280     {
    281         return (AE_OK);
    282     }
    283 
    284     Start = LineBuffer;
    285     End = Colon;
    286 
    287     while (Start < Colon)
    288     {
    289         if (*Start == '[')
    290         {
    291             /* Found left bracket, go to the right bracket */
    292 
    293             while (Start < Colon && *Start != ']')
    294             {
    295                 Start++;
    296             }
    297         }
    298         else if (*Start != ' ')
    299         {
    300             break;
    301         }
    302 
    303         Start++;
    304     }
    305 
    306     /*
    307      * There are two column values. One for the field name,
    308      * and one for the field value.
    309      */
    310     Column = ACPI_PTR_DIFF (Colon, LineBuffer) + 3;
    311     NameColumn = ACPI_PTR_DIFF (Start, LineBuffer) + 1;
    312 
    313     Length = ACPI_PTR_DIFF (End, Start);
    314 
    315     TmpName = UtLocalCalloc (Length + 1);
    316     strncpy (TmpName, Start, Length);
    317     Name = DtTrim (TmpName);
    318     ACPI_FREE (TmpName);
    319 
    320     Start = End = (Colon + 1);
    321     while (*End)
    322     {
    323         /* Found left quotation, go to the right quotation and break */
    324 
    325         if (*End == '"')
    326         {
    327             End++;
    328 
    329             /* Check for an explicit null string */
    330 
    331             if (*End == '"')
    332             {
    333                 IsNullString = TRUE;
    334             }
    335             while (*End && (*End != '"'))
    336             {
    337                 End++;
    338             }
    339 
    340             End++;
    341             break;
    342         }
    343 
    344         /*
    345          * Special "comment" fields at line end, ignore them.
    346          * Note: normal slash-slash and slash-asterisk comments are
    347          * stripped already by the DtGetNextLine parser.
    348          *
    349          * TBD: Perhaps DtGetNextLine should parse the following type
    350          * of comments also.
    351          */
    352         if (*End == '[')
    353         {
    354             End--;
    355             break;
    356         }
    357 
    358         End++;
    359     }
    360 
    361     Length = ACPI_PTR_DIFF (End, Start);
    362     TmpValue = UtLocalCalloc (Length + 1);
    363 
    364     strncpy (TmpValue, Start, Length);
    365     Value = DtTrim (TmpValue);
    366     ACPI_FREE (TmpValue);
    367 
    368     /* Create a new field object only if we have a valid value field */
    369 
    370     if ((Value && *Value) || IsNullString)
    371     {
    372         Field = UtFieldCacheCalloc ();
    373         Field->Name = Name;
    374         Field->Value = Value;
    375         Field->Line = Line;
    376         Field->ByteOffset = Offset;
    377         Field->NameColumn = NameColumn;
    378         Field->Column = Column;
    379         Field->StringLength = Length;
    380 
    381         DtLinkField (Field);
    382     }
    383     /* Else -- Ignore this field, it has no valid data */
    384 
    385     return (AE_OK);
    386 }
    387 
    388 
    389 /******************************************************************************
    390  *
    391  * FUNCTION:    DtGetNextLine
    392  *
    393  * PARAMETERS:  Handle              - Open file handle for the source file
    394  *
    395  * RETURN:      Filled line buffer and offset of start-of-line (ASL_EOF on EOF)
    396  *
    397  * DESCRIPTION: Get the next valid source line. Removes all comments.
    398  *              Ignores empty lines.
    399  *
    400  * Handles both slash-asterisk and slash-slash comments.
    401  * Also, quoted strings, but no escapes within.
    402  *
    403  * Line is returned in Gbl_CurrentLineBuffer.
    404  * Line number in original file is returned in Gbl_CurrentLineNumber.
    405  *
    406  *****************************************************************************/
    407 
    408 UINT32
    409 DtGetNextLine (
    410     FILE                    *Handle,
    411     UINT32                  Flags)
    412 {
    413     BOOLEAN                 LineNotAllBlanks = FALSE;
    414     UINT32                  State = DT_NORMAL_TEXT;
    415     UINT32                  CurrentLineOffset;
    416     UINT32                  i;
    417     int                     c;
    418 
    419 
    420     memset (Gbl_CurrentLineBuffer, 0, Gbl_LineBufferSize);
    421     for (i = 0; ;)
    422     {
    423         /*
    424          * If line is too long, expand the line buffers. Also increases
    425          * Gbl_LineBufferSize.
    426          */
    427         if (i >= Gbl_LineBufferSize)
    428         {
    429             UtExpandLineBuffers ();
    430         }
    431 
    432         c = getc (Handle);
    433         if (c == EOF)
    434         {
    435             switch (State)
    436             {
    437             case DT_START_QUOTED_STRING:
    438             case DT_SLASH_ASTERISK_COMMENT:
    439 
    440                 AcpiOsPrintf ("**** EOF within comment/string %u\n", State);
    441                 break;
    442 
    443             default:
    444 
    445                 break;
    446             }
    447 
    448             /* Standalone EOF is OK */
    449 
    450             if (i == 0)
    451             {
    452                 return (ASL_EOF);
    453             }
    454 
    455             /*
    456              * Received an EOF in the middle of a line. Terminate the
    457              * line with a newline. The next call to this function will
    458              * return a standalone EOF. Thus, the upper parsing software
    459              * never has to deal with an EOF within a valid line (or
    460              * the last line does not get tossed on the floor.)
    461              */
    462             c = '\n';
    463             State = DT_NORMAL_TEXT;
    464         }
    465 
    466         switch (State)
    467         {
    468         case DT_NORMAL_TEXT:
    469 
    470             /* Normal text, insert char into line buffer */
    471 
    472             Gbl_CurrentLineBuffer[i] = (char) c;
    473             switch (c)
    474             {
    475             case '/':
    476 
    477                 State = DT_START_COMMENT;
    478                 break;
    479 
    480             case '"':
    481 
    482                 State = DT_START_QUOTED_STRING;
    483                 LineNotAllBlanks = TRUE;
    484                 i++;
    485                 break;
    486 
    487             case '\\':
    488                 /*
    489                  * The continuation char MUST be last char on this line.
    490                  * Otherwise, it will be assumed to be a valid ASL char.
    491                  */
    492                 State = DT_MERGE_LINES;
    493                 break;
    494 
    495             case '\n':
    496 
    497                 CurrentLineOffset = Gbl_NextLineOffset;
    498                 Gbl_NextLineOffset = (UINT32) ftell (Handle);
    499                 Gbl_CurrentLineNumber++;
    500 
    501                 /*
    502                  * Exit if line is complete. Ignore empty lines (only \n)
    503                  * or lines that contain nothing but blanks.
    504                  */
    505                 if ((i != 0) && LineNotAllBlanks)
    506                 {
    507                     if ((i + 1) >= Gbl_LineBufferSize)
    508                     {
    509                         UtExpandLineBuffers ();
    510                     }
    511 
    512                     Gbl_CurrentLineBuffer[i+1] = 0; /* Terminate string */
    513                     return (CurrentLineOffset);
    514                 }
    515 
    516                 /* Toss this line and start a new one */
    517 
    518                 i = 0;
    519                 LineNotAllBlanks = FALSE;
    520                 break;
    521 
    522             default:
    523 
    524                 if (c != ' ')
    525                 {
    526                     LineNotAllBlanks = TRUE;
    527                 }
    528 
    529                 i++;
    530                 break;
    531             }
    532             break;
    533 
    534         case DT_START_QUOTED_STRING:
    535 
    536             /* Insert raw chars until end of quoted string */
    537 
    538             Gbl_CurrentLineBuffer[i] = (char) c;
    539             i++;
    540 
    541             switch (c)
    542             {
    543             case '"':
    544 
    545                 State = DT_NORMAL_TEXT;
    546                 break;
    547 
    548             case '\\':
    549 
    550                 State = DT_ESCAPE_SEQUENCE;
    551                 break;
    552 
    553             case '\n':
    554 
    555                 if (!(Flags & DT_ALLOW_MULTILINE_QUOTES))
    556                 {
    557                     AcpiOsPrintf (
    558                         "ERROR at line %u: Unterminated quoted string\n",
    559                         Gbl_CurrentLineNumber++);
    560                     State = DT_NORMAL_TEXT;
    561                 }
    562                 break;
    563 
    564             default:    /* Get next character */
    565 
    566                 break;
    567             }
    568             break;
    569 
    570         case DT_ESCAPE_SEQUENCE:
    571 
    572             /* Just copy the escaped character. TBD: sufficient for table compiler? */
    573 
    574             Gbl_CurrentLineBuffer[i] = (char) c;
    575             i++;
    576             State = DT_START_QUOTED_STRING;
    577             break;
    578 
    579         case DT_START_COMMENT:
    580 
    581             /* Open comment if this character is an asterisk or slash */
    582 
    583             switch (c)
    584             {
    585             case '*':
    586 
    587                 State = DT_SLASH_ASTERISK_COMMENT;
    588                 break;
    589 
    590             case '/':
    591 
    592                 State = DT_SLASH_SLASH_COMMENT;
    593                 break;
    594 
    595             default:    /* Not a comment */
    596 
    597                 i++;    /* Save the preceding slash */
    598                 if (i >= Gbl_LineBufferSize)
    599                 {
    600                     UtExpandLineBuffers ();
    601                 }
    602 
    603                 Gbl_CurrentLineBuffer[i] = (char) c;
    604                 i++;
    605                 State = DT_NORMAL_TEXT;
    606                 break;
    607             }
    608             break;
    609 
    610         case DT_SLASH_ASTERISK_COMMENT:
    611 
    612             /* Ignore chars until an asterisk-slash is found */
    613 
    614             switch (c)
    615             {
    616             case '\n':
    617 
    618                 Gbl_NextLineOffset = (UINT32) ftell (Handle);
    619                 Gbl_CurrentLineNumber++;
    620                 break;
    621 
    622             case '*':
    623 
    624                 State = DT_END_COMMENT;
    625                 break;
    626 
    627             default:
    628 
    629                 break;
    630             }
    631             break;
    632 
    633         case DT_SLASH_SLASH_COMMENT:
    634 
    635             /* Ignore chars until end-of-line */
    636 
    637             if (c == '\n')
    638             {
    639                 /* We will exit via the NORMAL_TEXT path */
    640 
    641                 ungetc (c, Handle);
    642                 State = DT_NORMAL_TEXT;
    643             }
    644             break;
    645 
    646         case DT_END_COMMENT:
    647 
    648             /* End comment if this char is a slash */
    649 
    650             switch (c)
    651             {
    652             case '/':
    653 
    654                 State = DT_NORMAL_TEXT;
    655                 break;
    656 
    657             case '\n':
    658 
    659                 CurrentLineOffset = Gbl_NextLineOffset;
    660                 Gbl_NextLineOffset = (UINT32) ftell (Handle);
    661                 Gbl_CurrentLineNumber++;
    662                 break;
    663 
    664             case '*':
    665 
    666                 /* Consume all adjacent asterisks */
    667                 break;
    668 
    669             default:
    670 
    671                 State = DT_SLASH_ASTERISK_COMMENT;
    672                 break;
    673             }
    674             break;
    675 
    676         case DT_MERGE_LINES:
    677 
    678             if (c != '\n')
    679             {
    680                 /*
    681                  * This is not a continuation backslash, it is a normal
    682                  * normal ASL backslash - for example: Scope(\_SB_)
    683                  */
    684                 i++; /* Keep the backslash that is already in the buffer */
    685 
    686                 ungetc (c, Handle);
    687                 State = DT_NORMAL_TEXT;
    688             }
    689             else
    690             {
    691                 /*
    692                  * This is a continuation line -- a backlash followed
    693                  * immediately by a newline. Insert a space between the
    694                  * lines (overwrite the backslash)
    695                  */
    696                 Gbl_CurrentLineBuffer[i] = ' ';
    697                 i++;
    698 
    699                 /* Ignore newline, this will merge the lines */
    700 
    701                 CurrentLineOffset = Gbl_NextLineOffset;
    702                 Gbl_NextLineOffset = (UINT32) ftell (Handle);
    703                 Gbl_CurrentLineNumber++;
    704                 State = DT_NORMAL_TEXT;
    705             }
    706             break;
    707 
    708         default:
    709 
    710             DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, "Unknown input state");
    711             return (ASL_EOF);
    712         }
    713     }
    714 }
    715 
    716 
    717 /******************************************************************************
    718  *
    719  * FUNCTION:    DtScanFile
    720  *
    721  * PARAMETERS:  Handle              - Open file handle for the source file
    722  *
    723  * RETURN:      Pointer to start of the constructed parse tree.
    724  *
    725  * DESCRIPTION: Scan source file, link all field names and values
    726  *              to the global parse tree: Gbl_FieldList
    727  *
    728  *****************************************************************************/
    729 
    730 DT_FIELD *
    731 DtScanFile (
    732     FILE                    *Handle)
    733 {
    734     ACPI_STATUS             Status;
    735     UINT32                  Offset;
    736 
    737 
    738     ACPI_FUNCTION_NAME (DtScanFile);
    739 
    740 
    741     /* Get the file size */
    742 
    743     Gbl_InputByteCount = CmGetFileSize (Handle);
    744     if (Gbl_InputByteCount == ACPI_UINT32_MAX)
    745     {
    746         AslAbort ();
    747     }
    748 
    749     Gbl_CurrentLineNumber = 0;
    750     Gbl_CurrentLineOffset = 0;
    751     Gbl_NextLineOffset = 0;
    752 
    753     /* Scan line-by-line */
    754 
    755     while ((Offset = DtGetNextLine (Handle, 0)) != ASL_EOF)
    756     {
    757         ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Line %2.2u/%4.4X - %s",
    758             Gbl_CurrentLineNumber, Offset, Gbl_CurrentLineBuffer));
    759 
    760         Status = DtParseLine (Gbl_CurrentLineBuffer,
    761             Gbl_CurrentLineNumber, Offset);
    762         if (Status == AE_NOT_FOUND)
    763         {
    764             break;
    765         }
    766     }
    767 
    768     /* Dump the parse tree if debug enabled */
    769 
    770     DtDumpFieldList (Gbl_FieldList);
    771     return (Gbl_FieldList);
    772 }
    773 
    774 
    775 /*
    776  * Output functions
    777  */
    778 
    779 /******************************************************************************
    780  *
    781  * FUNCTION:    DtWriteBinary
    782  *
    783  * PARAMETERS:  DT_WALK_CALLBACK
    784  *
    785  * RETURN:      Status
    786  *
    787  * DESCRIPTION: Write one subtable of a binary ACPI table
    788  *
    789  *****************************************************************************/
    790 
    791 static void
    792 DtWriteBinary (
    793     DT_SUBTABLE             *Subtable,
    794     void                    *Context,
    795     void                    *ReturnValue)
    796 {
    797 
    798     FlWriteFile (ASL_FILE_AML_OUTPUT, Subtable->Buffer, Subtable->Length);
    799 }
    800 
    801 
    802 /******************************************************************************
    803  *
    804  * FUNCTION:    DtOutputBinary
    805  *
    806  * PARAMETERS:
    807  *
    808  * RETURN:      Status
    809  *
    810  * DESCRIPTION: Write entire binary ACPI table (result of compilation)
    811  *
    812  *****************************************************************************/
    813 
    814 void
    815 DtOutputBinary (
    816     DT_SUBTABLE             *RootTable)
    817 {
    818 
    819     if (!RootTable)
    820     {
    821         return;
    822     }
    823 
    824     /* Walk the entire parse tree, emitting the binary data */
    825 
    826     DtWalkTableTree (RootTable, DtWriteBinary, NULL, NULL);
    827 
    828     Gbl_TableLength = CmGetFileSize (Gbl_Files[ASL_FILE_AML_OUTPUT].Handle);
    829     if (Gbl_TableLength == ACPI_UINT32_MAX)
    830     {
    831         AslAbort ();
    832     }
    833 }
    834 
    835 
    836 /*
    837  * Listing support
    838  */
    839 
    840 /******************************************************************************
    841  *
    842  * FUNCTION:    DtDumpBuffer
    843  *
    844  * PARAMETERS:  FileID              - Where to write buffer data
    845  *              Buffer              - Buffer to dump
    846  *              Offset              - Offset in current table
    847  *              Length              - Buffer Length
    848  *
    849  * RETURN:      None
    850  *
    851  * DESCRIPTION: Another copy of DumpBuffer routine (unfortunately).
    852  *
    853  * TBD: merge dump buffer routines
    854  *
    855  *****************************************************************************/
    856 
    857 static void
    858 DtDumpBuffer (
    859     UINT32                  FileId,
    860     UINT8                   *Buffer,
    861     UINT32                  Offset,
    862     UINT32                  Length)
    863 {
    864     UINT32                  i;
    865     UINT32                  j;
    866     UINT8                   BufChar;
    867 
    868 
    869     FlPrintFile (FileId, "Output: [%3.3Xh %4.4d %3d] ",
    870         Offset, Offset, Length);
    871 
    872     i = 0;
    873     while (i < Length)
    874     {
    875         if (i >= 16)
    876         {
    877             FlPrintFile (FileId, "%24s", "");
    878         }
    879 
    880         /* Print 16 hex chars */
    881 
    882         for (j = 0; j < 16;)
    883         {
    884             if (i + j >= Length)
    885             {
    886                 /* Dump fill spaces */
    887 
    888                 FlPrintFile (FileId, "   ");
    889                 j++;
    890                 continue;
    891             }
    892 
    893             FlPrintFile (FileId, "%02X ", Buffer[i+j]);
    894             j++;
    895         }
    896 
    897         FlPrintFile (FileId, " ");
    898         for (j = 0; j < 16; j++)
    899         {
    900             if (i + j >= Length)
    901             {
    902                 FlPrintFile (FileId, "\n\n");
    903                 return;
    904             }
    905 
    906             BufChar = Buffer[(ACPI_SIZE) i + j];
    907             if (isprint (BufChar))
    908             {
    909                 FlPrintFile (FileId, "%c", BufChar);
    910             }
    911             else
    912             {
    913                 FlPrintFile (FileId, ".");
    914             }
    915         }
    916 
    917         /* Done with that line. */
    918 
    919         FlPrintFile (FileId, "\n");
    920         i += 16;
    921     }
    922 
    923     FlPrintFile (FileId, "\n\n");
    924 }
    925 
    926 
    927 /******************************************************************************
    928  *
    929  * FUNCTION:    DtDumpFieldList
    930  *
    931  * PARAMETERS:  Field               - Root field
    932  *
    933  * RETURN:      None
    934  *
    935  * DESCRIPTION: Dump the entire field list
    936  *
    937  *****************************************************************************/
    938 
    939 void
    940 DtDumpFieldList (
    941     DT_FIELD                *Field)
    942 {
    943 
    944     if (!Gbl_DebugFlag || !Field)
    945     {
    946         return;
    947     }
    948 
    949     DbgPrint (ASL_DEBUG_OUTPUT,  "\nField List:\n"
    950         "LineNo   ByteOff  NameCol  Column   TableOff "
    951         "Flags %32s : %s\n\n", "Name", "Value");
    952 
    953     while (Field)
    954     {
    955         DbgPrint (ASL_DEBUG_OUTPUT,
    956             "%.08X %.08X %.08X %.08X %.08X %2.2X    %32s : %s\n",
    957             Field->Line, Field->ByteOffset, Field->NameColumn,
    958             Field->Column, Field->TableOffset, Field->Flags,
    959             Field->Name, Field->Value);
    960 
    961         Field = Field->Next;
    962     }
    963 
    964     DbgPrint (ASL_DEBUG_OUTPUT,  "\n\n");
    965 }
    966 
    967 
    968 /******************************************************************************
    969  *
    970  * FUNCTION:    DtDumpSubtableInfo, DtDumpSubtableTree
    971  *
    972  * PARAMETERS:  DT_WALK_CALLBACK
    973  *
    974  * RETURN:      None
    975  *
    976  * DESCRIPTION: Info - dump a subtable tree entry with extra information.
    977  *              Tree - dump a subtable tree formatted by depth indentation.
    978  *
    979  *****************************************************************************/
    980 
    981 static void
    982 DtDumpSubtableInfo (
    983     DT_SUBTABLE             *Subtable,
    984     void                    *Context,
    985     void                    *ReturnValue)
    986 {
    987 
    988     DbgPrint (ASL_DEBUG_OUTPUT,
    989         "[%.04X] %24s %.08X %.08X %.08X %.08X %.08X %p %p %p\n",
    990         Subtable->Depth, Subtable->Name, Subtable->Length, Subtable->TotalLength,
    991         Subtable->SizeOfLengthField, Subtable->Flags, Subtable,
    992         Subtable->Parent, Subtable->Child, Subtable->Peer);
    993 }
    994 
    995 static void
    996 DtDumpSubtableTree (
    997     DT_SUBTABLE             *Subtable,
    998     void                    *Context,
    999     void                    *ReturnValue)
   1000 {
   1001 
   1002     DbgPrint (ASL_DEBUG_OUTPUT,
   1003         "[%.04X] %24s %*s%08X (%.02X) - (%.02X)\n",
   1004         Subtable->Depth, Subtable->Name, (4 * Subtable->Depth), " ",
   1005         Subtable, Subtable->Length, Subtable->TotalLength);
   1006 }
   1007 
   1008 
   1009 /******************************************************************************
   1010  *
   1011  * FUNCTION:    DtDumpSubtableList
   1012  *
   1013  * PARAMETERS:  None
   1014  *
   1015  * RETURN:      None
   1016  *
   1017  * DESCRIPTION: Dump the raw list of subtables with information, and also
   1018  *              dump the subtable list in formatted tree format. Assists with
   1019  *              the development of new table code.
   1020  *
   1021  *****************************************************************************/
   1022 
   1023 void
   1024 DtDumpSubtableList (
   1025     void)
   1026 {
   1027 
   1028     if (!Gbl_DebugFlag || !Gbl_RootTable)
   1029     {
   1030         return;
   1031     }
   1032 
   1033     DbgPrint (ASL_DEBUG_OUTPUT,
   1034         "Subtable Info:\n"
   1035         "Depth                      Name Length   TotalLen LenSize  Flags    "
   1036         "This     Parent   Child    Peer\n\n");
   1037     DtWalkTableTree (Gbl_RootTable, DtDumpSubtableInfo, NULL, NULL);
   1038 
   1039     DbgPrint (ASL_DEBUG_OUTPUT,
   1040         "\nSubtable Tree: (Depth, Name, Subtable, Length, TotalLength)\n\n");
   1041     DtWalkTableTree (Gbl_RootTable, DtDumpSubtableTree, NULL, NULL);
   1042 
   1043     DbgPrint (ASL_DEBUG_OUTPUT, "\n");
   1044 }
   1045 
   1046 
   1047 /******************************************************************************
   1048  *
   1049  * FUNCTION:    DtWriteFieldToListing
   1050  *
   1051  * PARAMETERS:  Buffer              - Contains the compiled data
   1052  *              Field               - Field node for the input line
   1053  *              Length              - Length of the output data
   1054  *
   1055  * RETURN:      None
   1056  *
   1057  * DESCRIPTION: Write one field to the listing file (if listing is enabled).
   1058  *
   1059  *****************************************************************************/
   1060 
   1061 void
   1062 DtWriteFieldToListing (
   1063     UINT8                   *Buffer,
   1064     DT_FIELD                *Field,
   1065     UINT32                  Length)
   1066 {
   1067     UINT8                   FileByte;
   1068 
   1069 
   1070     if (!Gbl_ListingFlag || !Field)
   1071     {
   1072         return;
   1073     }
   1074 
   1075     /* Dump the original source line */
   1076 
   1077     FlPrintFile (ASL_FILE_LISTING_OUTPUT, "Input:  ");
   1078     FlSeekFile (ASL_FILE_INPUT, Field->ByteOffset);
   1079 
   1080     while (FlReadFile (ASL_FILE_INPUT, &FileByte, 1) == AE_OK)
   1081     {
   1082         FlWriteFile (ASL_FILE_LISTING_OUTPUT, &FileByte, 1);
   1083         if (FileByte == '\n')
   1084         {
   1085             break;
   1086         }
   1087     }
   1088 
   1089     /* Dump the line as parsed and represented internally */
   1090 
   1091     FlPrintFile (ASL_FILE_LISTING_OUTPUT, "Parsed: %*s : %.64s",
   1092         Field->Column-4, Field->Name, Field->Value);
   1093 
   1094     if (strlen (Field->Value) > 64)
   1095     {
   1096         FlPrintFile (ASL_FILE_LISTING_OUTPUT, "...Additional data, length 0x%X\n",
   1097             strlen (Field->Value));
   1098     }
   1099 
   1100     FlPrintFile (ASL_FILE_LISTING_OUTPUT, "\n");
   1101 
   1102     /* Dump the hex data that will be output for this field */
   1103 
   1104     DtDumpBuffer (ASL_FILE_LISTING_OUTPUT, Buffer, Field->TableOffset, Length);
   1105 }
   1106 
   1107 
   1108 /******************************************************************************
   1109  *
   1110  * FUNCTION:    DtWriteTableToListing
   1111  *
   1112  * PARAMETERS:  None
   1113  *
   1114  * RETURN:      None
   1115  *
   1116  * DESCRIPTION: Write the entire compiled table to the listing file
   1117  *              in hex format
   1118  *
   1119  *****************************************************************************/
   1120 
   1121 void
   1122 DtWriteTableToListing (
   1123     void)
   1124 {
   1125     UINT8                   *Buffer;
   1126 
   1127 
   1128     if (!Gbl_ListingFlag)
   1129     {
   1130         return;
   1131     }
   1132 
   1133     /* Read the entire table from the output file */
   1134 
   1135     Buffer = UtLocalCalloc (Gbl_TableLength);
   1136     FlSeekFile (ASL_FILE_AML_OUTPUT, 0);
   1137     FlReadFile (ASL_FILE_AML_OUTPUT, Buffer, Gbl_TableLength);
   1138 
   1139     /* Dump the raw table data */
   1140 
   1141     AcpiOsRedirectOutput (Gbl_Files[ASL_FILE_LISTING_OUTPUT].Handle);
   1142 
   1143     AcpiOsPrintf ("\n%s: Length %d (0x%X)\n\n",
   1144         ACPI_RAW_TABLE_DATA_HEADER, Gbl_TableLength, Gbl_TableLength);
   1145     AcpiUtDumpBuffer (Buffer, Gbl_TableLength, DB_BYTE_DISPLAY, 0);
   1146 
   1147     AcpiOsRedirectOutput (stdout);
   1148     ACPI_FREE (Buffer);
   1149 }
   1150