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