Home | History | Annotate | Line # | Download | only in compiler
asllistsup.c revision 1.1.1.3
      1 /******************************************************************************
      2  *
      3  * Module Name: asllistsup - Listing file support utilities
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2015, 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     FlPrintFile (FileId, "\"");
     92 }
     93 
     94 
     95 /*******************************************************************************
     96  *
     97  * FUNCTION:    LsDumpAsciiInComment
     98  *
     99  * PARAMETERS:  FileId          - ID of current listing file
    100  *              Count           - Number of bytes to convert
    101  *              Buffer          - Buffer of bytes to convert
    102  *
    103  * RETURN:      None
    104  *
    105  * DESCRIPTION: Convert hex bytes to ascii
    106  *
    107  ******************************************************************************/
    108 
    109 void
    110 LsDumpAsciiInComment (
    111     UINT32                  FileId,
    112     UINT32                  Count,
    113     UINT8                   *Buffer)
    114 {
    115     UINT8                   BufChar = 0;
    116     UINT8                   LastChar;
    117     UINT32                  i;
    118 
    119 
    120     FlPrintFile (FileId, "    \"");
    121     for (i = 0; i < Count; i++)
    122     {
    123         LastChar = BufChar;
    124         BufChar = Buffer[i];
    125 
    126         if (isprint (BufChar))
    127         {
    128             /* Handle embedded C comment sequences */
    129 
    130             if (((LastChar == '*') && (BufChar == '/')) ||
    131                 ((LastChar == '/') && (BufChar == '*')))
    132             {
    133                 /* Insert a space to break the sequence */
    134 
    135                 FlPrintFile (FileId, ".", BufChar);
    136             }
    137 
    138             FlPrintFile (FileId, "%c", BufChar);
    139         }
    140         else
    141         {
    142             /* Not a printable character, just put out a dot */
    143 
    144             FlPrintFile (FileId, ".");
    145         }
    146     }
    147 
    148     FlPrintFile (FileId, "\"");
    149 }
    150 
    151 
    152 /*******************************************************************************
    153  *
    154  * FUNCTION:    LsCheckException
    155  *
    156  * PARAMETERS:  LineNumber          - Current logical (cumulative) line #
    157  *              FileId              - ID of output listing file
    158  *
    159  * RETURN:      None
    160  *
    161  * DESCRIPTION: Check if there is an exception for this line, and if there is,
    162  *              put it in the listing immediately. Handles multiple errors
    163  *              per line. Gbl_NextError points to the next error in the
    164  *              sorted (by line #) list of compile errors/warnings.
    165  *
    166  ******************************************************************************/
    167 
    168 void
    169 LsCheckException (
    170     UINT32                  LineNumber,
    171     UINT32                  FileId)
    172 {
    173 
    174     if ((!Gbl_NextError) ||
    175         (LineNumber < Gbl_NextError->LogicalLineNumber ))
    176     {
    177         return;
    178     }
    179 
    180     /* Handle multiple errors per line */
    181 
    182     if (FileId == ASL_FILE_LISTING_OUTPUT)
    183     {
    184         while (Gbl_NextError &&
    185               (LineNumber >= Gbl_NextError->LogicalLineNumber))
    186         {
    187             AePrintException (FileId, Gbl_NextError, "\n[****iasl****]\n");
    188 
    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             FlPrintFile (FileId, "0%2.2Xh", Gbl_AmlBuffer[i]);
    580         }
    581 
    582         for (i = 0; i < ((HEX_LISTING_LINE_SIZE - Gbl_CurrentHexColumn) * 5); i++)
    583         {
    584             FlWriteFile (FileId, " ", 1);
    585         }
    586 
    587         FlPrintFile (FileId, "  ;%8.8X",
    588             Gbl_CurrentAmlOffset - HEX_LISTING_LINE_SIZE);
    589 
    590         /* Write the ASCII character associated with each of the bytes */
    591 
    592         LsDumpAscii (FileId, Gbl_CurrentHexColumn, Gbl_AmlBuffer);
    593         break;
    594 
    595 
    596     case ASL_FILE_C_SOURCE_OUTPUT:
    597 
    598         for (i = 0; i < Gbl_CurrentHexColumn; i++)
    599         {
    600             FlPrintFile (FileId, "0x%2.2X,", Gbl_AmlBuffer[i]);
    601         }
    602 
    603         /* Pad hex output with spaces if line is shorter than max line size */
    604 
    605         for (i = 0; i < ((HEX_LISTING_LINE_SIZE - Gbl_CurrentHexColumn) * 5); i++)
    606         {
    607             FlWriteFile (FileId, " ", 1);
    608         }
    609 
    610         /* AML offset for the start of the line */
    611 
    612         FlPrintFile (FileId, "    /* %8.8X",
    613             Gbl_CurrentAmlOffset - Gbl_CurrentHexColumn);
    614 
    615         /* Write the ASCII character associated with each of the bytes */
    616 
    617         LsDumpAsciiInComment (FileId, Gbl_CurrentHexColumn, Gbl_AmlBuffer);
    618         FlPrintFile (FileId, " */");
    619         break;
    620 
    621     default:
    622 
    623         /* No other types supported */
    624 
    625         return;
    626     }
    627 
    628     FlPrintFile (FileId, "\n");
    629 
    630     Gbl_CurrentHexColumn = 0;
    631     Gbl_HexBytesWereWritten = TRUE;
    632 }
    633 
    634 
    635 /*******************************************************************************
    636  *
    637  * FUNCTION:    LsPushNode
    638  *
    639  * PARAMETERS:  Filename        - Pointer to the include filename
    640  *
    641  * RETURN:      None
    642  *
    643  * DESCRIPTION: Push a listing node on the listing/include file stack. This
    644  *              stack enables tracking of include files (infinitely nested)
    645  *              and resumption of the listing of the parent file when the
    646  *              include file is finished.
    647  *
    648  ******************************************************************************/
    649 
    650 void
    651 LsPushNode (
    652     char                    *Filename)
    653 {
    654     ASL_LISTING_NODE        *Lnode;
    655 
    656 
    657     /* Create a new node */
    658 
    659     Lnode = UtLocalCalloc (sizeof (ASL_LISTING_NODE));
    660 
    661     /* Initialize */
    662 
    663     Lnode->Filename = Filename;
    664     Lnode->LineNumber = 0;
    665 
    666     /* Link (push) */
    667 
    668     Lnode->Next = Gbl_ListingNode;
    669     Gbl_ListingNode = Lnode;
    670 }
    671 
    672 
    673 /*******************************************************************************
    674  *
    675  * FUNCTION:    LsPopNode
    676  *
    677  * PARAMETERS:  None
    678  *
    679  * RETURN:      List head after current head is popped off
    680  *
    681  * DESCRIPTION: Pop the current head of the list, free it, and return the
    682  *              next node on the stack (the new current node).
    683  *
    684  ******************************************************************************/
    685 
    686 ASL_LISTING_NODE *
    687 LsPopNode (
    688     void)
    689 {
    690     ASL_LISTING_NODE        *Lnode;
    691 
    692 
    693     /* Just grab the node at the head of the list */
    694 
    695     Lnode = Gbl_ListingNode;
    696     if ((!Lnode) ||
    697         (!Lnode->Next))
    698     {
    699         AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, NULL,
    700             "Could not pop empty listing stack");
    701         return (Gbl_ListingNode);
    702     }
    703 
    704     Gbl_ListingNode = Lnode->Next;
    705     ACPI_FREE (Lnode);
    706 
    707     /* New "Current" node is the new head */
    708 
    709     return (Gbl_ListingNode);
    710 }
    711