Home | History | Annotate | Line # | Download | only in compiler
prutils.c revision 1.7
      1 /******************************************************************************
      2  *
      3  * Module Name: prutils - Preprocessor utilities
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2016, Intel Corp.
      9  * All rights reserved.
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted provided that the following conditions
     13  * are met:
     14  * 1. Redistributions of source code must retain the above copyright
     15  *    notice, this list of conditions, and the following disclaimer,
     16  *    without modification.
     17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
     18  *    substantially similar to the "NO WARRANTY" disclaimer below
     19  *    ("Disclaimer") and any redistribution must be conditioned upon
     20  *    including a substantially similar Disclaimer requirement for further
     21  *    binary redistribution.
     22  * 3. Neither the names of the above-listed copyright holders nor the names
     23  *    of any contributors may be used to endorse or promote products derived
     24  *    from this software without specific prior written permission.
     25  *
     26  * Alternatively, this software may be distributed under the terms of the
     27  * GNU General Public License ("GPL") version 2 as published by the Free
     28  * Software Foundation.
     29  *
     30  * NO WARRANTY
     31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
     34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
     40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     41  * POSSIBILITY OF SUCH DAMAGES.
     42  */
     43 
     44 #include "aslcompiler.h"
     45 #include "dtcompiler.h"
     46 
     47 
     48 #define _COMPONENT          ASL_PREPROCESSOR
     49         ACPI_MODULE_NAME    ("prutils")
     50 
     51 
     52 /******************************************************************************
     53  *
     54  * FUNCTION:    PrGetNextToken
     55  *
     56  * PARAMETERS:  Buffer              - Current line buffer
     57  *              MatchString         - String with valid token delimiters
     58  *              Next                - Set to next possible token in buffer
     59  *
     60  * RETURN:      Next token (null-terminated). Modifies the input line.
     61  *              Remainder of line is stored in *Next.
     62  *
     63  * DESCRIPTION: Local implementation of strtok() with local storage for the
     64  *              next pointer. Not only thread-safe, but allows multiple
     65  *              parsing of substrings such as expressions.
     66  *
     67  *****************************************************************************/
     68 
     69 char *
     70 PrGetNextToken (
     71     char                    *Buffer,
     72     char                    *MatchString,
     73     char                    **Next)
     74 {
     75     char                    *TokenStart;
     76 
     77 
     78     if (!Buffer)
     79     {
     80         /* Use Next if it is valid */
     81 
     82         Buffer = *Next;
     83         if (!(*Next))
     84         {
     85             return (NULL);
     86         }
     87     }
     88 
     89     /* Skip any leading delimiters */
     90 
     91     while (*Buffer)
     92     {
     93         if (strchr (MatchString, *Buffer))
     94         {
     95             Buffer++;
     96         }
     97         else
     98         {
     99             break;
    100         }
    101     }
    102 
    103     /* Anything left on the line? */
    104 
    105     if (!(*Buffer))
    106     {
    107         *Next = NULL;
    108         return (NULL);
    109     }
    110 
    111     TokenStart = Buffer;
    112 
    113     /* Find the end of this token */
    114 
    115     while (*Buffer)
    116     {
    117         if (strchr (MatchString, *Buffer))
    118         {
    119             *Buffer = 0;
    120             *Next = Buffer+1;
    121             if (!**Next)
    122             {
    123                 *Next = NULL;
    124             }
    125 
    126             return (TokenStart);
    127         }
    128 
    129         Buffer++;
    130     }
    131 
    132     *Next = NULL;
    133     return (TokenStart);
    134 }
    135 
    136 
    137 /*******************************************************************************
    138  *
    139  * FUNCTION:    PrError
    140  *
    141  * PARAMETERS:  Level               - Seriousness (Warning/error, etc.)
    142  *              MessageId           - Index into global message buffer
    143  *              Column              - Column in current line
    144  *
    145  * RETURN:      None
    146  *
    147  * DESCRIPTION: Preprocessor error reporting. Front end to AslCommonError2
    148  *
    149  ******************************************************************************/
    150 
    151 void
    152 PrError (
    153     UINT8                   Level,
    154     UINT16                  MessageId,
    155     UINT32                  Column)
    156 {
    157 #if 0
    158     AcpiOsPrintf ("%s (%u) : %s", Gbl_Files[ASL_FILE_INPUT].Filename,
    159         Gbl_CurrentLineNumber, Gbl_CurrentLineBuffer);
    160 #endif
    161 
    162 
    163     if (Column > 120)
    164     {
    165         Column = 0;
    166     }
    167 
    168     /* TBD: Need Logical line number? */
    169 
    170     AslCommonError2 (Level, MessageId,
    171         Gbl_CurrentLineNumber, Column,
    172         Gbl_CurrentLineBuffer,
    173         Gbl_Files[ASL_FILE_INPUT].Filename, "Preprocessor");
    174 
    175     Gbl_PreprocessorError = TRUE;
    176 }
    177 
    178 
    179 /*******************************************************************************
    180  *
    181  * FUNCTION:    PrReplaceData
    182  *
    183  * PARAMETERS:  Buffer              - Original(target) buffer pointer
    184  *              LengthToRemove      - Length to be removed from target buffer
    185  *              BufferToAdd         - Data to be inserted into target buffer
    186  *              LengthToAdd         - Length of BufferToAdd
    187  *
    188  * RETURN:      None
    189  *
    190  * DESCRIPTION: Generic buffer data replacement.
    191  *
    192  ******************************************************************************/
    193 
    194 void
    195 PrReplaceData (
    196     char                    *Buffer,
    197     UINT32                  LengthToRemove,
    198     char                    *BufferToAdd,
    199     UINT32                  LengthToAdd)
    200 {
    201     UINT32                  BufferLength;
    202 
    203 
    204     /* Buffer is a string, so the length must include the terminating zero */
    205 
    206     BufferLength = strlen (Buffer) + 1;
    207 
    208     if (LengthToRemove != LengthToAdd)
    209     {
    210         /*
    211          * Move some of the existing data
    212          * 1) If adding more bytes than removing, make room for the new data
    213          * 2) if removing more bytes than adding, delete the extra space
    214          */
    215         if (LengthToRemove > 0)
    216         {
    217             memmove ((Buffer + LengthToAdd), (Buffer + LengthToRemove),
    218                 (BufferLength - LengthToRemove));
    219         }
    220     }
    221 
    222     /* Now we can move in the new data */
    223 
    224     if (LengthToAdd > 0)
    225     {
    226         memmove (Buffer, BufferToAdd, LengthToAdd);
    227     }
    228 }
    229 
    230 
    231 /*******************************************************************************
    232  *
    233  * FUNCTION:    PrOpenIncludeFile
    234  *
    235  * PARAMETERS:  Filename            - Filename or pathname for include file
    236  *
    237  * RETURN:      None.
    238  *
    239  * DESCRIPTION: Open an include file and push it on the input file stack.
    240  *
    241  ******************************************************************************/
    242 
    243 FILE *
    244 PrOpenIncludeFile (
    245     char                    *Filename,
    246     char                    *OpenMode,
    247     char                    **FullPathname)
    248 {
    249     FILE                    *IncludeFile;
    250     ASL_INCLUDE_DIR         *NextDir;
    251 
    252 
    253     /* Start the actual include file on the next line */
    254 
    255     Gbl_CurrentLineOffset++;
    256 
    257     /* Attempt to open the include file */
    258     /* If the file specifies an absolute path, just open it */
    259 
    260     if ((Filename[0] == '/')  ||
    261         (Filename[0] == '\\') ||
    262         (Filename[1] == ':'))
    263     {
    264         IncludeFile = PrOpenIncludeWithPrefix (
    265             "", Filename, OpenMode, FullPathname);
    266         if (!IncludeFile)
    267         {
    268             goto ErrorExit;
    269         }
    270         return (IncludeFile);
    271     }
    272 
    273     /*
    274      * The include filename is not an absolute path.
    275      *
    276      * First, search for the file within the "local" directory -- meaning
    277      * the same directory that contains the source file.
    278      *
    279      * Construct the file pathname from the global directory name.
    280      */
    281     IncludeFile = PrOpenIncludeWithPrefix (
    282         Gbl_DirectoryPath, Filename, OpenMode, FullPathname);
    283     if (IncludeFile)
    284     {
    285         return (IncludeFile);
    286     }
    287 
    288     /*
    289      * Second, search for the file within the (possibly multiple)
    290      * directories specified by the -I option on the command line.
    291      */
    292     NextDir = Gbl_IncludeDirList;
    293     while (NextDir)
    294     {
    295         IncludeFile = PrOpenIncludeWithPrefix (
    296             NextDir->Dir, Filename, OpenMode, FullPathname);
    297         if (IncludeFile)
    298         {
    299             return (IncludeFile);
    300         }
    301 
    302         NextDir = NextDir->Next;
    303     }
    304 
    305     /* We could not open the include file after trying very hard */
    306 
    307 ErrorExit:
    308     snprintf (Gbl_MainTokenBuffer, ASL_DEFAULT_LINE_BUFFER_SIZE, "%s, %s",
    309 	Filename, strerror (errno));
    310     PrError (ASL_ERROR, ASL_MSG_INCLUDE_FILE_OPEN, 0);
    311     return (NULL);
    312 }
    313 
    314 
    315 /*******************************************************************************
    316  *
    317  * FUNCTION:    FlOpenIncludeWithPrefix
    318  *
    319  * PARAMETERS:  PrefixDir       - Prefix directory pathname. Can be a zero
    320  *                                length string.
    321  *              Filename        - The include filename from the source ASL.
    322  *
    323  * RETURN:      Valid file descriptor if successful. Null otherwise.
    324  *
    325  * DESCRIPTION: Open an include file and push it on the input file stack.
    326  *
    327  ******************************************************************************/
    328 
    329 FILE *
    330 PrOpenIncludeWithPrefix (
    331     char                    *PrefixDir,
    332     char                    *Filename,
    333     char                    *OpenMode,
    334     char                    **FullPathname)
    335 {
    336     FILE                    *IncludeFile;
    337     char                    *Pathname;
    338 
    339 
    340     /* Build the full pathname to the file */
    341 
    342     Pathname = FlMergePathnames (PrefixDir, Filename);
    343 
    344     DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
    345         "Include: Opening file - \"%s\"\n",
    346         Gbl_CurrentLineNumber, Pathname);
    347 
    348     /* Attempt to open the file, push if successful */
    349 
    350     IncludeFile = fopen (Pathname, OpenMode);
    351     if (!IncludeFile)
    352     {
    353         fprintf (stderr, "Could not open include file %s\n", Pathname);
    354         return (NULL);
    355     }
    356 
    357     /* Push the include file on the open input file stack */
    358 
    359     PrPushInputFileStack (IncludeFile, Pathname);
    360     *FullPathname = Pathname;
    361     return (IncludeFile);
    362 }
    363 
    364 
    365 /*******************************************************************************
    366  *
    367  * FUNCTION:    AslPushInputFileStack
    368  *
    369  * PARAMETERS:  InputFile           - Open file pointer
    370  *              Filename            - Name of the file
    371  *
    372  * RETURN:      None
    373  *
    374  * DESCRIPTION: Push the InputFile onto the file stack, and point the parser
    375  *              to this file. Called when an include file is successfully
    376  *              opened.
    377  *
    378  ******************************************************************************/
    379 
    380 void
    381 PrPushInputFileStack (
    382     FILE                    *InputFile,
    383     char                    *Filename)
    384 {
    385     PR_FILE_NODE            *Fnode;
    386 
    387 
    388     Gbl_HasIncludeFiles = TRUE;
    389 
    390     /* Save the current state in an Fnode */
    391 
    392     Fnode = UtLocalCalloc (sizeof (PR_FILE_NODE));
    393 
    394     Fnode->File = Gbl_Files[ASL_FILE_INPUT].Handle;
    395     Fnode->Next = Gbl_InputFileList;
    396     Fnode->Filename = Gbl_Files[ASL_FILE_INPUT].Filename;
    397     Fnode->CurrentLineNumber = Gbl_CurrentLineNumber;
    398 
    399     /* Push it on the stack */
    400 
    401     Gbl_InputFileList = Fnode;
    402 
    403     DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
    404         "Push InputFile Stack: handle %p\n\n",
    405         Gbl_CurrentLineNumber, InputFile);
    406 
    407     /* Reset the global line count and filename */
    408 
    409     Gbl_Files[ASL_FILE_INPUT].Filename =
    410         UtStringCacheCalloc (strlen (Filename) + 1);
    411     strcpy (Gbl_Files[ASL_FILE_INPUT].Filename, Filename);
    412 
    413     Gbl_Files[ASL_FILE_INPUT].Handle = InputFile;
    414     Gbl_CurrentLineNumber = 1;
    415 
    416     /* Emit a new #line directive for the include file */
    417 
    418     FlPrintFile (ASL_FILE_PREPROCESSOR, "#line %u \"%s\"\n", 1, Filename);
    419 }
    420 
    421 
    422 /*******************************************************************************
    423  *
    424  * FUNCTION:    AslPopInputFileStack
    425  *
    426  * PARAMETERS:  None
    427  *
    428  * RETURN:      0 if a node was popped, -1 otherwise
    429  *
    430  * DESCRIPTION: Pop the top of the input file stack and point the parser to
    431  *              the saved parse buffer contained in the fnode. Also, set the
    432  *              global line counters to the saved values. This function is
    433  *              called when an include file reaches EOF.
    434  *
    435  ******************************************************************************/
    436 
    437 BOOLEAN
    438 PrPopInputFileStack (
    439     void)
    440 {
    441     PR_FILE_NODE            *Fnode;
    442 
    443 
    444     Fnode = Gbl_InputFileList;
    445     DbgPrint (ASL_PARSE_OUTPUT, "\n" PR_PREFIX_ID
    446         "Pop InputFile Stack, Fnode %p\n\n",
    447         Gbl_CurrentLineNumber, Fnode);
    448 
    449     if (!Fnode)
    450     {
    451         return (FALSE);
    452     }
    453 
    454     /* Close the current include file */
    455 
    456     fclose (Gbl_Files[ASL_FILE_INPUT].Handle);
    457 
    458     /* Update the top-of-stack */
    459 
    460     Gbl_InputFileList = Fnode->Next;
    461 
    462     /* Reset global line counter and filename */
    463 
    464     Gbl_Files[ASL_FILE_INPUT].Filename = Fnode->Filename;
    465     Gbl_Files[ASL_FILE_INPUT].Handle = Fnode->File;
    466     Gbl_CurrentLineNumber = Fnode->CurrentLineNumber;
    467 
    468     /* Emit a new #line directive after the include file */
    469 
    470     FlPrintFile (ASL_FILE_PREPROCESSOR, "#line %u \"%s\"\n",
    471         Gbl_CurrentLineNumber, Fnode->Filename);
    472 
    473     /* All done with this node */
    474 
    475     ACPI_FREE (Fnode);
    476     return (TRUE);
    477 }
    478