Home | History | Annotate | Line # | Download | only in compiler
prutils.c revision 1.1.1.13
      1 /******************************************************************************
      2  *
      3  * Module Name: prutils - Preprocessor utilities
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2022, 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 MERCHANTABILITY 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 
     46 #define _COMPONENT          ASL_PREPROCESSOR
     47         ACPI_MODULE_NAME    ("prutils")
     48 
     49 
     50 /******************************************************************************
     51  *
     52  * FUNCTION:    PrGetNextToken
     53  *
     54  * PARAMETERS:  Buffer              - Current line buffer
     55  *              MatchString         - String with valid token delimiters
     56  *              Next                - Set to next possible token in buffer
     57  *
     58  * RETURN:      Next token (null-terminated). Modifies the input line.
     59  *              Remainder of line is stored in *Next.
     60  *
     61  * DESCRIPTION: Local implementation of strtok() with local storage for the
     62  *              next pointer. Not only thread-safe, but allows multiple
     63  *              parsing of substrings such as expressions.
     64  *
     65  *****************************************************************************/
     66 
     67 char *
     68 PrGetNextToken (
     69     char                    *Buffer,
     70     char                    *MatchString,
     71     char                    **Next)
     72 {
     73     char                    *TokenStart;
     74 
     75 
     76     if (!Buffer)
     77     {
     78         /* Use Next if it is valid */
     79 
     80         Buffer = *Next;
     81         if (!(*Next))
     82         {
     83             return (NULL);
     84         }
     85     }
     86 
     87     /* Skip any leading delimiters */
     88 
     89     while (*Buffer)
     90     {
     91         if (strchr (MatchString, *Buffer))
     92         {
     93             Buffer++;
     94         }
     95         else
     96         {
     97             break;
     98         }
     99     }
    100 
    101     /* Anything left on the line? */
    102 
    103     if (!(*Buffer))
    104     {
    105         *Next = NULL;
    106         return (NULL);
    107     }
    108 
    109     TokenStart = Buffer;
    110 
    111     /* Find the end of this token */
    112 
    113     while (*Buffer)
    114     {
    115         if (strchr (MatchString, *Buffer))
    116         {
    117             *Buffer = 0;
    118             *Next = Buffer+1;
    119             if (!**Next)
    120             {
    121                 *Next = NULL;
    122             }
    123 
    124             return (TokenStart);
    125         }
    126 
    127         Buffer++;
    128     }
    129 
    130     *Next = NULL;
    131     return (TokenStart);
    132 }
    133 
    134 
    135 /*******************************************************************************
    136  *
    137  * FUNCTION:    PrError
    138  *
    139  * PARAMETERS:  Level               - Seriousness (Warning/error, etc.)
    140  *              MessageId           - Index into global message buffer
    141  *              Column              - Column in current line
    142  *
    143  * RETURN:      None
    144  *
    145  * DESCRIPTION: Preprocessor error reporting. Front end to AslCommonError2
    146  *
    147  ******************************************************************************/
    148 
    149 void
    150 PrError (
    151     UINT8                   Level,
    152     UINT16                  MessageId,
    153     UINT32                  Column)
    154 {
    155 #if 0
    156     AcpiOsPrintf ("%s (%u) : %s", AslGbl_Files[ASL_FILE_INPUT].Filename,
    157         AslGbl_CurrentLineNumber, AslGbl_CurrentLineBuffer);
    158 #endif
    159 
    160 
    161     if (Column > 120)
    162     {
    163         Column = 0;
    164     }
    165 
    166     /* TBD: Need Logical line number? */
    167 
    168     AslCommonError2 (Level, MessageId,
    169         AslGbl_CurrentLineNumber, Column,
    170         AslGbl_CurrentLineBuffer,
    171         AslGbl_Files[ASL_FILE_INPUT].Filename, "Preprocessor");
    172 
    173     AslGbl_PreprocessorError = TRUE;
    174 }
    175 
    176 
    177 /*******************************************************************************
    178  *
    179  * FUNCTION:    PrReplaceData
    180  *
    181  * PARAMETERS:  Buffer              - Original(target) buffer pointer
    182  *              LengthToRemove      - Length to be removed from target buffer
    183  *              BufferToAdd         - Data to be inserted into target buffer
    184  *              LengthToAdd         - Length of BufferToAdd
    185  *
    186  * RETURN:      None
    187  *
    188  * DESCRIPTION: Generic buffer data replacement.
    189  *
    190  ******************************************************************************/
    191 
    192 void
    193 PrReplaceData (
    194     char                    *Buffer,
    195     UINT32                  LengthToRemove,
    196     char                    *BufferToAdd,
    197     UINT32                  LengthToAdd)
    198 {
    199     UINT32                  BufferLength;
    200 
    201 
    202     /* Buffer is a string, so the length must include the terminating zero */
    203 
    204     BufferLength = strlen (Buffer) + 1;
    205 
    206     if (LengthToRemove != LengthToAdd)
    207     {
    208         /*
    209          * Move some of the existing data
    210          * 1) If adding more bytes than removing, make room for the new data
    211          * 2) if removing more bytes than adding, delete the extra space
    212          */
    213         if (LengthToRemove > 0)
    214         {
    215             memmove ((Buffer + LengthToAdd), (Buffer + LengthToRemove),
    216                 (BufferLength - LengthToRemove));
    217         }
    218     }
    219 
    220     /* Now we can move in the new data */
    221 
    222     if (LengthToAdd > 0)
    223     {
    224         memmove (Buffer, BufferToAdd, LengthToAdd);
    225     }
    226 }
    227 
    228 
    229 /*******************************************************************************
    230  *
    231  * FUNCTION:    PrOpenIncludeFile
    232  *
    233  * PARAMETERS:  Filename            - Filename or pathname for include file
    234  *
    235  * RETURN:      None.
    236  *
    237  * DESCRIPTION: Open an include file and push it on the input file stack.
    238  *
    239  ******************************************************************************/
    240 
    241 FILE *
    242 PrOpenIncludeFile (
    243     char                    *Filename,
    244     char                    *OpenMode,
    245     char                    **FullPathname)
    246 {
    247     FILE                    *IncludeFile;
    248     ASL_INCLUDE_DIR         *NextDir;
    249 
    250 
    251     /* Start the actual include file on the next line */
    252 
    253     AslGbl_CurrentLineOffset++;
    254 
    255     /* Attempt to open the include file */
    256     /* If the file specifies an absolute path, just open it */
    257 
    258     if ((Filename[0] == '/')  ||
    259         (Filename[0] == '\\') ||
    260         (Filename[1] == ':'))
    261     {
    262         IncludeFile = PrOpenIncludeWithPrefix (
    263             "", Filename, OpenMode, FullPathname);
    264         if (!IncludeFile)
    265         {
    266             goto ErrorExit;
    267         }
    268         return (IncludeFile);
    269     }
    270 
    271     /*
    272      * The include filename is not an absolute path.
    273      *
    274      * First, search for the file within the "local" directory -- meaning
    275      * the same directory that contains the source file.
    276      *
    277      * Construct the file pathname from the global directory name.
    278      */
    279     IncludeFile = PrOpenIncludeWithPrefix (
    280         AslGbl_DirectoryPath, Filename, OpenMode, FullPathname);
    281     if (IncludeFile)
    282     {
    283         return (IncludeFile);
    284     }
    285 
    286     /*
    287      * Second, search for the file within the (possibly multiple)
    288      * directories specified by the -I option on the command line.
    289      */
    290     NextDir = AslGbl_IncludeDirList;
    291     while (NextDir)
    292     {
    293         IncludeFile = PrOpenIncludeWithPrefix (
    294             NextDir->Dir, Filename, OpenMode, FullPathname);
    295         if (IncludeFile)
    296         {
    297             return (IncludeFile);
    298         }
    299 
    300         NextDir = NextDir->Next;
    301     }
    302 
    303     /* We could not open the include file after trying very hard */
    304 
    305 ErrorExit:
    306     sprintf (AslGbl_MainTokenBuffer, "%s, %s", Filename, strerror (errno));
    307     PrError (ASL_ERROR, ASL_MSG_INCLUDE_FILE_OPEN, 0);
    308     return (NULL);
    309 }
    310 
    311 
    312 /*******************************************************************************
    313  *
    314  * FUNCTION:    FlOpenIncludeWithPrefix
    315  *
    316  * PARAMETERS:  PrefixDir       - Prefix directory pathname. Can be a zero
    317  *                                length string.
    318  *              Filename        - The include filename from the source ASL.
    319  *
    320  * RETURN:      Valid file descriptor if successful. Null otherwise.
    321  *
    322  * DESCRIPTION: Open an include file and push it on the input file stack.
    323  *
    324  ******************************************************************************/
    325 
    326 FILE *
    327 PrOpenIncludeWithPrefix (
    328     char                    *PrefixDir,
    329     char                    *Filename,
    330     char                    *OpenMode,
    331     char                    **FullPathname)
    332 {
    333     FILE                    *IncludeFile;
    334     char                    *Pathname;
    335 
    336 
    337     /* Build the full pathname to the file */
    338 
    339     Pathname = FlMergePathnames (PrefixDir, Filename);
    340 
    341     DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
    342         "Include: Opening file - \"%s\"\n",
    343         AslGbl_CurrentLineNumber, Pathname);
    344 
    345     /* Attempt to open the file, push if successful */
    346 
    347     IncludeFile = fopen (Pathname, OpenMode);
    348     if (!IncludeFile)
    349     {
    350         return (NULL);
    351     }
    352 
    353     /* Push the include file on the open input file stack */
    354 
    355     PrPushInputFileStack (IncludeFile, Pathname);
    356     *FullPathname = Pathname;
    357     return (IncludeFile);
    358 }
    359 
    360 
    361 /*******************************************************************************
    362  *
    363  * FUNCTION:    AslPushInputFileStack
    364  *
    365  * PARAMETERS:  InputFile           - Open file pointer
    366  *              Filename            - Name of the file
    367  *
    368  * RETURN:      None
    369  *
    370  * DESCRIPTION: Push the InputFile onto the file stack, and point the parser
    371  *              to this file. Called when an include file is successfully
    372  *              opened.
    373  *
    374  ******************************************************************************/
    375 
    376 void
    377 PrPushInputFileStack (
    378     FILE                    *InputFile,
    379     char                    *Filename)
    380 {
    381     PR_FILE_NODE            *Fnode;
    382 
    383 
    384     AslGbl_HasIncludeFiles = TRUE;
    385 
    386     /* Save the current state in an Fnode */
    387 
    388     Fnode = UtLocalCalloc (sizeof (PR_FILE_NODE));
    389 
    390     Fnode->File = AslGbl_Files[ASL_FILE_INPUT].Handle;
    391     Fnode->Next = AslGbl_InputFileList;
    392     Fnode->Filename = AslGbl_Files[ASL_FILE_INPUT].Filename;
    393     Fnode->CurrentLineNumber = AslGbl_CurrentLineNumber;
    394 
    395     /* Push it on the stack */
    396 
    397     AslGbl_InputFileList = Fnode;
    398 
    399     DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
    400         "Push InputFile Stack: handle %p\n\n",
    401         AslGbl_CurrentLineNumber, InputFile);
    402 
    403     /* Reset the global line count and filename */
    404 
    405     AslGbl_Files[ASL_FILE_INPUT].Filename =
    406         UtLocalCacheCalloc (strlen (Filename) + 1);
    407     strcpy (AslGbl_Files[ASL_FILE_INPUT].Filename, Filename);
    408 
    409     AslGbl_Files[ASL_FILE_INPUT].Handle = InputFile;
    410     AslGbl_CurrentLineNumber = 1;
    411 
    412     /* Emit a new #line directive for the include file */
    413 
    414     FlPrintFile (ASL_FILE_PREPROCESSOR, "#line %u \"%s\"\n", 1, Filename);
    415 }
    416 
    417 
    418 /*******************************************************************************
    419  *
    420  * FUNCTION:    AslPopInputFileStack
    421  *
    422  * PARAMETERS:  None
    423  *
    424  * RETURN:      0 if a node was popped, -1 otherwise
    425  *
    426  * DESCRIPTION: Pop the top of the input file stack and point the parser to
    427  *              the saved parse buffer contained in the fnode. Also, set the
    428  *              global line counters to the saved values. This function is
    429  *              called when an include file reaches EOF.
    430  *
    431  ******************************************************************************/
    432 
    433 BOOLEAN
    434 PrPopInputFileStack (
    435     void)
    436 {
    437     PR_FILE_NODE            *Fnode;
    438 
    439 
    440     Fnode = AslGbl_InputFileList;
    441     DbgPrint (ASL_PARSE_OUTPUT, "\n" PR_PREFIX_ID
    442         "Pop InputFile Stack, Fnode %p\n\n",
    443         AslGbl_CurrentLineNumber, Fnode);
    444 
    445     if (!Fnode)
    446     {
    447         return (FALSE);
    448     }
    449 
    450     /* Close the current include file */
    451 
    452     fclose (AslGbl_Files[ASL_FILE_INPUT].Handle);
    453 
    454     /* Update the top-of-stack */
    455 
    456     AslGbl_InputFileList = Fnode->Next;
    457 
    458     /* Reset global line counter and filename */
    459 
    460     AslGbl_Files[ASL_FILE_INPUT].Filename = Fnode->Filename;
    461     AslGbl_Files[ASL_FILE_INPUT].Handle = Fnode->File;
    462     AslGbl_CurrentLineNumber = Fnode->CurrentLineNumber;
    463 
    464     /* Emit a new #line directive after the include file */
    465 
    466     FlPrintFile (ASL_FILE_PREPROCESSOR, "#line %u \"%s\"\n",
    467         AslGbl_CurrentLineNumber, Fnode->Filename);
    468 
    469     /* All done with this node */
    470 
    471     ACPI_FREE (Fnode);
    472     return (TRUE);
    473 }
    474