Home | History | Annotate | Line # | Download | only in compiler
asllistsup.c revision 1.1.1.1.10.3
      1 /******************************************************************************
      2  *
      3  * Module Name: asllistsup - Listing file support utilities
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2017, 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 "aslcompiler.y.h"
     46 
     47 
     48 #define _COMPONENT          ACPI_COMPILER
     49         ACPI_MODULE_NAME    ("aslistsup")
     50 
     51 
     52 /*******************************************************************************
     53  *
     54  * FUNCTION:    LsDumpAscii
     55  *
     56  * PARAMETERS:  FileId          - ID of current listing file
     57  *              Count           - Number of bytes to convert
     58  *              Buffer          - Buffer of bytes to convert
     59  *
     60  * RETURN:      None
     61  *
     62  * DESCRIPTION: Convert hex bytes to ascii
     63  *
     64  ******************************************************************************/
     65 
     66 void
     67 LsDumpAscii (
     68     UINT32                  FileId,
     69     UINT32                  Count,
     70     UINT8                   *Buffer)
     71 {
     72     UINT8                   BufChar;
     73     UINT32                  i;
     74 
     75 
     76     FlPrintFile (FileId, "    \"");
     77     for (i = 0; i < Count; i++)
     78     {
     79         BufChar = Buffer[i];
     80         if (isprint (BufChar))
     81         {
     82             FlPrintFile (FileId, "%c", BufChar);
     83         }
     84         else
     85         {
     86             /* Not a printable character, just put out a dot */
     87 
     88             FlPrintFile (FileId, ".");
     89         }
     90     }
     91 
     92     FlPrintFile (FileId, "\"");
     93 }
     94 
     95 
     96 /*******************************************************************************
     97  *
     98  * FUNCTION:    LsDumpAsciiInComment
     99  *
    100  * PARAMETERS:  FileId          - ID of current listing file
    101  *              Count           - Number of bytes to convert
    102  *              Buffer          - Buffer of bytes to convert
    103  *
    104  * RETURN:      None
    105  *
    106  * DESCRIPTION: Convert hex bytes to ascii
    107  *
    108  ******************************************************************************/
    109 
    110 void
    111 LsDumpAsciiInComment (
    112     UINT32                  FileId,
    113     UINT32                  Count,
    114     UINT8                   *Buffer)
    115 {
    116     UINT8                   BufChar = 0;
    117     UINT8                   LastChar;
    118     UINT32                  i;
    119 
    120 
    121     FlPrintFile (FileId, "    \"");
    122     for (i = 0; i < Count; i++)
    123     {
    124         LastChar = BufChar;
    125         BufChar = Buffer[i];
    126 
    127         if (isprint (BufChar))
    128         {
    129             /* Handle embedded C comment sequences */
    130 
    131             if (((LastChar == '*') && (BufChar == '/')) ||
    132                 ((LastChar == '/') && (BufChar == '*')))
    133             {
    134                 /* Insert a space to break the sequence */
    135 
    136                 FlPrintFile (FileId, ".", BufChar);
    137             }
    138 
    139             FlPrintFile (FileId, "%c", BufChar);
    140         }
    141         else
    142         {
    143             /* Not a printable character, just put out a dot */
    144 
    145             FlPrintFile (FileId, ".");
    146         }
    147     }
    148 
    149     FlPrintFile (FileId, "\"");
    150 }
    151 
    152 
    153 /*******************************************************************************
    154  *
    155  * FUNCTION:    LsCheckException
    156  *
    157  * PARAMETERS:  LineNumber          - Current logical (cumulative) line #
    158  *              FileId              - ID of output listing file
    159  *
    160  * RETURN:      None
    161  *
    162  * DESCRIPTION: Check if there is an exception for this line, and if there is,
    163  *              put it in the listing immediately. Handles multiple errors
    164  *              per line. Gbl_NextError points to the next error in the
    165  *              sorted (by line #) list of compile errors/warnings.
    166  *
    167  ******************************************************************************/
    168 
    169 void
    170 LsCheckException (
    171     UINT32                  LineNumber,
    172     UINT32                  FileId)
    173 {
    174 
    175     if ((!Gbl_NextError) ||
    176         (LineNumber < Gbl_NextError->LogicalLineNumber ))
    177     {
    178         return;
    179     }
    180 
    181     /* Handle multiple errors per line */
    182 
    183     if (FileId == ASL_FILE_LISTING_OUTPUT)
    184     {
    185         while (Gbl_NextError &&
    186               (LineNumber >= Gbl_NextError->LogicalLineNumber))
    187         {
    188             AePrintException (FileId, Gbl_NextError, "\n[****iasl****]\n");
    189             Gbl_NextError = Gbl_NextError->Next;
    190         }
    191 
    192         FlPrintFile (FileId, "\n");
    193     }
    194 }
    195 
    196 
    197 /*******************************************************************************
    198  *
    199  * FUNCTION:    LsWriteListingHexBytes
    200  *
    201  * PARAMETERS:  Buffer          - AML code buffer
    202  *              Length          - Number of AML bytes to write
    203  *              FileId          - ID of current listing file.
    204  *
    205  * RETURN:      None
    206  *
    207  * DESCRIPTION: Write the contents of the AML buffer to the listing file via
    208  *              the listing buffer. The listing buffer is flushed every 16
    209  *              AML bytes.
    210  *
    211  ******************************************************************************/
    212 
    213 void
    214 LsWriteListingHexBytes (
    215     UINT8                   *Buffer,
    216     UINT32                  Length,
    217     UINT32                  FileId)
    218 {
    219     UINT32                  i;
    220 
    221 
    222     /* Transfer all requested bytes */
    223 
    224     for (i = 0; i < Length; i++)
    225     {
    226         /* Print line header when buffer is empty */
    227 
    228         if (Gbl_CurrentHexColumn == 0)
    229         {
    230             if (Gbl_HasIncludeFiles)
    231             {
    232                 FlPrintFile (FileId, "%*s", 10, " ");
    233             }
    234 
    235             switch (FileId)
    236             {
    237             case ASL_FILE_LISTING_OUTPUT:
    238 
    239                 FlPrintFile (FileId, "%8.8X%s", Gbl_CurrentAmlOffset,
    240                     ASL_LISTING_LINE_PREFIX);
    241                 break;
    242 
    243             case ASL_FILE_ASM_SOURCE_OUTPUT:
    244 
    245                 FlPrintFile (FileId, "    db ");
    246                 break;
    247 
    248             case ASL_FILE_C_SOURCE_OUTPUT:
    249 
    250                 FlPrintFile (FileId, "        ");
    251                 break;
    252 
    253             default:
    254 
    255                 /* No other types supported */
    256 
    257                 return;
    258             }
    259         }
    260 
    261         /* Transfer AML byte and update counts */
    262 
    263         Gbl_AmlBuffer[Gbl_CurrentHexColumn] = Buffer[i];
    264 
    265         Gbl_CurrentHexColumn++;
    266         Gbl_CurrentAmlOffset++;
    267 
    268         /* Flush buffer when it is full */
    269 
    270         if (Gbl_CurrentHexColumn >= HEX_LISTING_LINE_SIZE)
    271         {
    272             LsFlushListingBuffer (FileId);
    273         }
    274     }
    275 }
    276 
    277 
    278 /*******************************************************************************
    279  *
    280  * FUNCTION:    LsWriteSourceLines
    281  *
    282  * PARAMETERS:  ToLineNumber            -
    283  *              ToLogicalLineNumber     - Write up to this source line number
    284  *              FileId                  - ID of current listing file
    285  *
    286  * RETURN:      None
    287  *
    288  * DESCRIPTION: Read then write source lines to the listing file until we have
    289  *              reached the specified logical (cumulative) line number. This
    290  *              automatically echos out comment blocks and other non-AML
    291  *              generating text until we get to the actual AML-generating line
    292  *              of ASL code specified by the logical line number.
    293  *
    294  ******************************************************************************/
    295 
    296 void
    297 LsWriteSourceLines (
    298     UINT32                  ToLineNumber,
    299     UINT32                  ToLogicalLineNumber,
    300     UINT32                  FileId)
    301 {
    302 
    303     /* Nothing to do for these file types */
    304 
    305     if ((FileId == ASL_FILE_ASM_INCLUDE_OUTPUT) ||
    306         (FileId == ASL_FILE_C_INCLUDE_OUTPUT))
    307     {
    308         return;
    309     }
    310 
    311     Gbl_CurrentLine = ToLogicalLineNumber;
    312 
    313     /* Flush any hex bytes remaining from the last opcode */
    314 
    315     LsFlushListingBuffer (FileId);
    316 
    317     /* Read lines and write them as long as we are not caught up */
    318 
    319     if (Gbl_SourceLine < Gbl_CurrentLine)
    320     {
    321         /*
    322          * If we just completed writing some AML hex bytes, output a linefeed
    323          * to add some whitespace for readability.
    324          */
    325         if (Gbl_HexBytesWereWritten)
    326         {
    327             FlPrintFile (FileId, "\n");
    328             Gbl_HexBytesWereWritten = FALSE;
    329         }
    330 
    331         if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
    332         {
    333             FlPrintFile (FileId, "    /*\n");
    334         }
    335 
    336         /* Write one line at a time until we have reached the target line # */
    337 
    338         while ((Gbl_SourceLine < Gbl_CurrentLine) &&
    339                 LsWriteOneSourceLine (FileId))
    340         { ; }
    341 
    342         if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
    343         {
    344             FlPrintFile (FileId, "     */");
    345         }
    346 
    347         FlPrintFile (FileId, "\n");
    348     }
    349 }
    350 
    351 
    352 /*******************************************************************************
    353  *
    354  * FUNCTION:    LsWriteOneSourceLine
    355  *
    356  * PARAMETERS:  FileId          - ID of current listing file
    357  *
    358  * RETURN:      FALSE on EOF (input source file), TRUE otherwise
    359  *
    360  * DESCRIPTION: Read one line from the input source file and echo it to the
    361  *              listing file, prefixed with the line number, and if the source
    362  *              file contains include files, prefixed with the current filename
    363  *
    364  ******************************************************************************/
    365 
    366 UINT32
    367 LsWriteOneSourceLine (
    368     UINT32                  FileId)
    369 {
    370     UINT8                   FileByte;
    371     UINT32                  Column = 0;
    372     UINT32                  Index = 16;
    373     BOOLEAN                 StartOfLine = FALSE;
    374     BOOLEAN                 ProcessLongLine = FALSE;
    375 
    376 
    377     Gbl_SourceLine++;
    378     Gbl_ListingNode->LineNumber++;
    379 
    380     /* Ignore lines that are completely blank (but count the line above) */
    381 
    382     if (FlReadFile (ASL_FILE_SOURCE_OUTPUT, &FileByte, 1) != AE_OK)
    383     {
    384         return (0);
    385     }
    386     if (FileByte == '\n')
    387     {
    388         return (1);
    389     }
    390 
    391     /*
    392      * This is a non-empty line, we will print the entire line with
    393      * the line number and possibly other prefixes and transforms.
    394      */
    395 
    396     /* Line prefixes for special files, C and ASM output */
    397 
    398     if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
    399     {
    400         FlPrintFile (FileId, "     *");
    401     }
    402     if (FileId == ASL_FILE_ASM_SOURCE_OUTPUT)
    403     {
    404         FlPrintFile (FileId, "; ");
    405     }
    406 
    407     if (Gbl_HasIncludeFiles)
    408     {
    409         /*
    410          * This file contains "include" statements, print the current
    411          * filename and line number within the current file
    412          */
    413         FlPrintFile (FileId, "%12s %5d%s",
    414             Gbl_ListingNode->Filename, Gbl_ListingNode->LineNumber,
    415             ASL_LISTING_LINE_PREFIX);
    416     }
    417     else
    418     {
    419         /* No include files, just print the line number */
    420 
    421         FlPrintFile (FileId, "%8u%s", Gbl_SourceLine,
    422             ASL_LISTING_LINE_PREFIX);
    423     }
    424 
    425     /* Read the rest of this line (up to a newline or EOF) */
    426 
    427     do
    428     {
    429         if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
    430         {
    431             if (FileByte == '/')
    432             {
    433                 FileByte = '*';
    434             }
    435         }
    436 
    437         /* Split long input lines for readability in the listing */
    438 
    439         Column++;
    440         if (Column >= 128)
    441         {
    442             if (!ProcessLongLine)
    443             {
    444                 if ((FileByte != '}') &&
    445                     (FileByte != '{'))
    446                 {
    447                     goto WriteByte;
    448                 }
    449 
    450                 ProcessLongLine = TRUE;
    451             }
    452 
    453             if (FileByte == '{')
    454             {
    455                 FlPrintFile (FileId, "\n%*s{\n", Index, " ");
    456                 StartOfLine = TRUE;
    457                 Index += 4;
    458                 continue;
    459             }
    460 
    461             else if (FileByte == '}')
    462             {
    463                 if (!StartOfLine)
    464                 {
    465                     FlPrintFile (FileId, "\n");
    466                 }
    467 
    468                 StartOfLine = TRUE;
    469                 Index -= 4;
    470                 FlPrintFile (FileId, "%*s}\n", Index, " ");
    471                 continue;
    472             }
    473 
    474             /* Ignore spaces/tabs at the start of line */
    475 
    476             else if ((FileByte == ' ') && StartOfLine)
    477             {
    478                 continue;
    479             }
    480 
    481             else if (StartOfLine)
    482             {
    483                 StartOfLine = FALSE;
    484                 FlPrintFile (FileId, "%*s", Index, " ");
    485             }
    486 
    487 WriteByte:
    488             FlWriteFile (FileId, &FileByte, 1);
    489             if (FileByte == '\n')
    490             {
    491                 /*
    492                  * This line has been completed.
    493                  * Check if an error occurred on this source line during the compile.
    494                  * If so, we print the error message after the source line.
    495                  */
    496                 LsCheckException (Gbl_SourceLine, FileId);
    497                 return (1);
    498             }
    499         }
    500         else
    501         {
    502             FlWriteFile (FileId, &FileByte, 1);
    503             if (FileByte == '\n')
    504             {
    505                 /*
    506                  * This line has been completed.
    507                  * Check if an error occurred on this source line during the compile.
    508                  * If so, we print the error message after the source line.
    509                  */
    510                 LsCheckException (Gbl_SourceLine, FileId);
    511                 return (1);
    512             }
    513         }
    514 
    515     } while (FlReadFile (ASL_FILE_SOURCE_OUTPUT, &FileByte, 1) == AE_OK);
    516 
    517     /* EOF on the input file was reached */
    518 
    519     return (0);
    520 }
    521 
    522 
    523 /*******************************************************************************
    524  *
    525  * FUNCTION:    LsFlushListingBuffer
    526  *
    527  * PARAMETERS:  FileId          - ID of the listing file
    528  *
    529  * RETURN:      None
    530  *
    531  * DESCRIPTION: Flush out the current contents of the 16-byte hex AML code
    532  *              buffer. Usually called at the termination of a single line
    533  *              of source code or when the buffer is full.
    534  *
    535  ******************************************************************************/
    536 
    537 void
    538 LsFlushListingBuffer (
    539     UINT32                  FileId)
    540 {
    541     UINT32                  i;
    542 
    543 
    544     if (Gbl_CurrentHexColumn == 0)
    545     {
    546         return;
    547     }
    548 
    549     /* Write the hex bytes */
    550 
    551     switch (FileId)
    552     {
    553     case ASL_FILE_LISTING_OUTPUT:
    554 
    555         for (i = 0; i < Gbl_CurrentHexColumn; i++)
    556         {
    557             FlPrintFile (FileId, "%2.2X ", Gbl_AmlBuffer[i]);
    558         }
    559 
    560         for (i = 0; i < ((HEX_LISTING_LINE_SIZE - Gbl_CurrentHexColumn) * 3); i++)
    561         {
    562             FlWriteFile (FileId, ".", 1);
    563         }
    564 
    565         /* Write the ASCII character associated with each of the bytes */
    566 
    567         LsDumpAscii (FileId, Gbl_CurrentHexColumn, Gbl_AmlBuffer);
    568         break;
    569 
    570 
    571     case ASL_FILE_ASM_SOURCE_OUTPUT:
    572 
    573         for (i = 0; i < Gbl_CurrentHexColumn; i++)
    574         {
    575             if (i > 0)
    576             {
    577                 FlPrintFile (FileId, ",");
    578             }
    579 
    580             FlPrintFile (FileId, "0%2.2Xh", Gbl_AmlBuffer[i]);
    581         }
    582 
    583         for (i = 0; i < ((HEX_LISTING_LINE_SIZE - Gbl_CurrentHexColumn) * 5); i++)
    584         {
    585             FlWriteFile (FileId, " ", 1);
    586         }
    587 
    588         FlPrintFile (FileId, "  ;%8.8X",
    589             Gbl_CurrentAmlOffset - HEX_LISTING_LINE_SIZE);
    590 
    591         /* Write the ASCII character associated with each of the bytes */
    592 
    593         LsDumpAscii (FileId, Gbl_CurrentHexColumn, Gbl_AmlBuffer);
    594         break;
    595 
    596 
    597     case ASL_FILE_C_SOURCE_OUTPUT:
    598 
    599         for (i = 0; i < Gbl_CurrentHexColumn; i++)
    600         {
    601             FlPrintFile (FileId, "0x%2.2X,", Gbl_AmlBuffer[i]);
    602         }
    603 
    604         /* Pad hex output with spaces if line is shorter than max line size */
    605 
    606         for (i = 0; i < ((HEX_LISTING_LINE_SIZE - Gbl_CurrentHexColumn) * 5); i++)
    607         {
    608             FlWriteFile (FileId, " ", 1);
    609         }
    610 
    611         /* AML offset for the start of the line */
    612 
    613         FlPrintFile (FileId, "    /* %8.8X",
    614             Gbl_CurrentAmlOffset - Gbl_CurrentHexColumn);
    615 
    616         /* Write the ASCII character associated with each of the bytes */
    617 
    618         LsDumpAsciiInComment (FileId, Gbl_CurrentHexColumn, Gbl_AmlBuffer);
    619         FlPrintFile (FileId, " */");
    620         break;
    621 
    622     default:
    623 
    624         /* No other types supported */
    625 
    626         return;
    627     }
    628 
    629     FlPrintFile (FileId, "\n");
    630 
    631     Gbl_CurrentHexColumn = 0;
    632     Gbl_HexBytesWereWritten = TRUE;
    633 }
    634 
    635 
    636 /*******************************************************************************
    637  *
    638  * FUNCTION:    LsPushNode
    639  *
    640  * PARAMETERS:  Filename        - Pointer to the include filename
    641  *
    642  * RETURN:      None
    643  *
    644  * DESCRIPTION: Push a listing node on the listing/include file stack. This
    645  *              stack enables tracking of include files (infinitely nested)
    646  *              and resumption of the listing of the parent file when the
    647  *              include file is finished.
    648  *
    649  ******************************************************************************/
    650 
    651 void
    652 LsPushNode (
    653     char                    *Filename)
    654 {
    655     ASL_LISTING_NODE        *Lnode;
    656 
    657 
    658     /* Create a new node */
    659 
    660     Lnode = UtLocalCalloc (sizeof (ASL_LISTING_NODE));
    661 
    662     /* Initialize */
    663 
    664     Lnode->Filename = Filename;
    665     Lnode->LineNumber = 0;
    666 
    667     /* Link (push) */
    668 
    669     Lnode->Next = Gbl_ListingNode;
    670     Gbl_ListingNode = Lnode;
    671 }
    672 
    673 
    674 /*******************************************************************************
    675  *
    676  * FUNCTION:    LsPopNode
    677  *
    678  * PARAMETERS:  None
    679  *
    680  * RETURN:      List head after current head is popped off
    681  *
    682  * DESCRIPTION: Pop the current head of the list, free it, and return the
    683  *              next node on the stack (the new current node).
    684  *
    685  ******************************************************************************/
    686 
    687 ASL_LISTING_NODE *
    688 LsPopNode (
    689     void)
    690 {
    691     ASL_LISTING_NODE        *Lnode;
    692 
    693 
    694     /* Just grab the node at the head of the list */
    695 
    696     Lnode = Gbl_ListingNode;
    697     if ((!Lnode) ||
    698         (!Lnode->Next))
    699     {
    700         AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, NULL,
    701             "Could not pop empty listing stack");
    702         return (Gbl_ListingNode);
    703     }
    704 
    705     Gbl_ListingNode = Lnode->Next;
    706     ACPI_FREE (Lnode);
    707 
    708     /* New "Current" node is the new head */
    709 
    710     return (Gbl_ListingNode);
    711 }
    712