Home | History | Annotate | Line # | Download | only in compiler
prutils.c revision 1.1.1.15
      1 /******************************************************************************
      2  *
      3  * Module Name: prutils - Preprocessor utilities
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2023, 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:    PrReplaceResizeSubstring
    180  *
    181  * PARAMETERS:  Args                - Struct containing name, offset & usecount
    182  *              Diff1               - Difference in lengths when new < old
    183  *              Diff2               - Difference in lengths when new > old
    184 *               i                   - The curr. no. of iteration of replacement
    185  *              Token               - Substring that replaces Args->Name
    186  *
    187  * RETURN:      None
    188  *
    189  * DESCRIPTION: Advanced substring replacement in a string using resized buffer.
    190  *
    191  ******************************************************************************/
    192 
    193 void
    194 PrReplaceResizeSubstring(
    195     PR_MACRO_ARG            *Args,
    196     UINT32                  Diff1,
    197     UINT32                  Diff2,
    198     UINT32                  i,
    199     char                    *Token)
    200 {
    201     UINT32                  b, PrevOffset;
    202     char                    *temp;
    203     char                    macro_sep[64];
    204 
    205 
    206     AslGbl_MacroTokenReplaceBuffer = (char *) realloc (AslGbl_MacroTokenReplaceBuffer,
    207         (2 * (strlen (AslGbl_MacroTokenBuffer))));
    208 
    209     strcpy (macro_sep, "~,() {}!*/%+-<>=&^|\"\t\n");
    210 
    211     /*
    212      * When the replacement argument (during invocation) length
    213      * < replaced parameter (in the macro function definition
    214      * and its expansion) length
    215      */
    216     if (Diff1 != 0)
    217     {
    218         /*
    219          * We save the offset value to reset it after replacing each
    220          * instance of each arg and setting the offset value to
    221          * the start of the arg to be replaced since it changes
    222          * with each iteration when arg length != token length
    223          */
    224         PrevOffset = Args->Offset[i];
    225         temp = strstr (AslGbl_MacroTokenBuffer, Args->Name);
    226         if (temp == NULL)
    227         {
    228             return;
    229         }
    230 
    231 ResetHere1:
    232         temp = strstr (temp, Args->Name);
    233         if (temp == NULL)
    234         {
    235             return;
    236         }
    237         Args->Offset[i] = strlen (AslGbl_MacroTokenBuffer) -
    238             strlen (temp);
    239         if (Args->Offset[i] == 0)
    240         {
    241             goto JumpHere1;
    242         }
    243         if ((strchr (macro_sep, AslGbl_MacroTokenBuffer[(Args->Offset[i] - 1)])) &&
    244             (strchr (macro_sep, AslGbl_MacroTokenBuffer[(Args->Offset[i] + strlen (Args->Name))])))
    245         {
    246             Args->Offset[i] += 0;
    247         }
    248         else
    249         {
    250             temp += strlen (Args->Name);
    251             goto ResetHere1;
    252         }
    253 
    254         /*
    255          * For now, we simply set the extra char positions (generated
    256          * due to longer name replaced by shorter name) to whitespace
    257          * chars so it will be ignored during compilation
    258          */
    259 JumpHere1:
    260         b = strlen (Token) + Args->Offset[i];
    261         memset (&AslGbl_MacroTokenBuffer[b], ' ', Diff1);
    262 
    263 # if 0
    264 
    265     /* Work in progress as of 03/08/2023 - experimental 'if' block
    266      * to test code for removing extra whitespaces from the macro
    267      * replacement when replacement arg < replaced param
    268      */
    269         char Buff[8192];
    270         /* char* Replace; */
    271         /* Replace = Buff; */
    272 
    273         for (j = 0; j < strlen (AslGbl_MacroTokenBuffer); j++)
    274         {
    275             Buff[j] = AslGbl_MacroTokenBuffer[j];
    276         }
    277         Buff[strlen (AslGbl_MacroTokenBuffer)] = '\0';
    278         /* fprintf(stderr, "Buff: %s\n", Buff); */
    279 
    280         UINT32 len = strlen (Buff);
    281 
    282         for (j = 0; j < len; j++)
    283         {
    284             if (Buff[0] == ' ')
    285             {
    286                 for (j = 0; j < (len - 1); j++)
    287                 {
    288                     Buff[j] = Buff[j + 1];
    289                 }
    290                 Buff[j] = '\0';
    291                 len--;
    292                 j = -1;
    293                 continue;
    294             }
    295 
    296             if (Buff[j] == ' ' && Buff[j + 1] == ' ')
    297             {
    298                 for (k = 0; k < (len - 1); k++)
    299                 {
    300                     Buff[j] = Buff[j + 1];
    301                 }
    302                 Buff[j] = '\0';
    303                 len--;
    304                 j--;
    305             }
    306         }
    307         /* fprintf(stderr, "Buff: %s\n", Buff); */
    308 
    309         for (k = 0; k < strlen (Buff); k++)
    310         {
    311             AslGbl_MacroTokenBuffer[k] = Buff[k];
    312         }
    313 #endif
    314 
    315         PrReplaceData (
    316             &AslGbl_MacroTokenBuffer[Args->Offset[i]],
    317             strlen (Token), Token, strlen (Token));
    318 
    319         temp = NULL;
    320         Args->Offset[i] = PrevOffset;
    321     }
    322 
    323     /*
    324      * When the replacement argument (during invocation) length
    325      * > replaced parameter (in the macro function definition
    326      * and its expansion) length
    327      */
    328     else if (Diff2 != 0)
    329     {
    330         /* Doing the same thing with offset value as for prev case */
    331 
    332         PrevOffset = Args->Offset[i];
    333         temp = strstr (AslGbl_MacroTokenBuffer, Args->Name);
    334         if (temp == NULL)
    335         {
    336             return;
    337         }
    338 
    339 ResetHere2:
    340         temp = strstr (temp, Args->Name);
    341         if (temp == NULL)
    342         {
    343             return;
    344         }
    345         Args->Offset[i] = strlen (AslGbl_MacroTokenBuffer) -
    346             strlen (temp);
    347         if (Args->Offset[i] == 0)
    348         {
    349             goto JumpHere2;
    350         }
    351         if ((strchr (macro_sep, AslGbl_MacroTokenBuffer[(Args->Offset[i] - 1)])) &&
    352             (strchr (macro_sep, AslGbl_MacroTokenBuffer[(Args->Offset[i] + strlen (Args->Name))])))
    353         {
    354             Args->Offset[i] += 0;
    355         }
    356         else
    357         {
    358             temp+= strlen (Args->Name);
    359             goto ResetHere2;
    360         }
    361 
    362         /*
    363          * We will need to allocate some extra space in our buffer to
    364          * accommodate the increase in the replacement string length
    365          * over the shorter outgoing arg string and do the replacement
    366          * at the correct offset value which is resetted every iteration
    367          */
    368 JumpHere2:
    369         strncpy (AslGbl_MacroTokenReplaceBuffer, AslGbl_MacroTokenBuffer, Args->Offset[i]);
    370         strcat (AslGbl_MacroTokenReplaceBuffer, Token);
    371         strcat (AslGbl_MacroTokenReplaceBuffer, (AslGbl_MacroTokenBuffer +
    372             (Args->Offset[i] + strlen (Args->Name))));
    373 
    374         strcpy (AslGbl_MacroTokenBuffer, AslGbl_MacroTokenReplaceBuffer);
    375 
    376         temp = NULL;
    377         Args->Offset[i] = PrevOffset;
    378     }
    379 
    380     /*
    381      * When the replacement argument (during invocation) length =
    382      * replaced parameter (in the macro function definition and
    383      * its expansion) length
    384      */
    385     else
    386     {
    387 
    388         /*
    389          * We still need to reset the offset for each iteration even when
    390          * arg and param lengths are same since any macro func invocation
    391          * could use various cases for each separate arg-param pair
    392          */
    393         PrevOffset = Args->Offset[i];
    394         temp = strstr (AslGbl_MacroTokenBuffer, Args->Name);
    395         if (temp == NULL)
    396         {
    397             return;
    398         }
    399 
    400 ResetHere3:
    401         temp = strstr (temp, Args->Name);
    402         if (temp == NULL)
    403         {
    404             return;
    405         }
    406         Args->Offset[i] = strlen (AslGbl_MacroTokenBuffer) -
    407             strlen (temp);
    408         if (Args->Offset[i] == 0)
    409         {
    410             goto JumpHere3;
    411         }
    412         if ((strchr (macro_sep, AslGbl_MacroTokenBuffer[(Args->Offset[i] - 1)])) &&
    413             (strchr (macro_sep, AslGbl_MacroTokenBuffer[(Args->Offset[i] + strlen (Args->Name))])))
    414         {
    415             Args->Offset[i] += 0;
    416         }
    417         else
    418         {
    419             temp += strlen (Args->Name);
    420             goto ResetHere3;
    421         }
    422 
    423 JumpHere3:
    424         PrReplaceData (
    425             &AslGbl_MacroTokenBuffer[Args->Offset[i]],
    426             strlen (Args->Name), Token, strlen (Token));
    427         temp = NULL;
    428         Args->Offset[i] = PrevOffset;
    429     }
    430 }
    431 
    432 
    433 /*******************************************************************************
    434  *
    435  * FUNCTION:    PrReplaceData
    436  *
    437  * PARAMETERS:  Buffer              - Original(target) buffer pointer
    438  *              LengthToRemove      - Length to be removed from target buffer
    439  *              BufferToAdd         - Data to be inserted into target buffer
    440  *              LengthToAdd         - Length of BufferToAdd
    441  *
    442  * RETURN:      Pointer to where the buffer is replaced with data
    443  *
    444  * DESCRIPTION: Generic buffer data replacement.
    445  *
    446  ******************************************************************************/
    447 
    448 char *
    449 PrReplaceData (
    450     char                    *Buffer,
    451     UINT32                  LengthToRemove,
    452     char                    *BufferToAdd,
    453     UINT32                  LengthToAdd)
    454 {
    455     UINT32                  BufferLength;
    456 
    457 
    458     /* Buffer is a string, so the length must include the terminating zero */
    459 
    460     BufferLength = strlen (Buffer) + 1;
    461 
    462     if (LengthToRemove != LengthToAdd)
    463     {
    464         /*
    465          * Move some of the existing data
    466          * 1) If adding more bytes than removing, make room for the new data
    467          * 2) if removing more bytes than adding, delete the extra space
    468          */
    469         if (LengthToRemove > 0)
    470         {
    471             memmove ((Buffer + LengthToAdd), (Buffer + LengthToRemove),
    472                 (BufferLength - LengthToRemove));
    473         }
    474     }
    475 
    476 
    477     /* Now we can move in the new data */
    478 
    479     if (LengthToAdd > 0)
    480     {
    481         memmove (Buffer, BufferToAdd, LengthToAdd);
    482     }
    483     return (Buffer + LengthToAdd);
    484 }
    485 
    486 
    487 /*******************************************************************************
    488  *
    489  * FUNCTION:    PrOpenIncludeFile
    490  *
    491  * PARAMETERS:  Filename            - Filename or pathname for include file
    492  *
    493  * RETURN:      None.
    494  *
    495  * DESCRIPTION: Open an include file and push it on the input file stack.
    496  *
    497  ******************************************************************************/
    498 
    499 FILE *
    500 PrOpenIncludeFile (
    501     char                    *Filename,
    502     char                    *OpenMode,
    503     char                    **FullPathname)
    504 {
    505     FILE                    *IncludeFile;
    506     ASL_INCLUDE_DIR         *NextDir;
    507 
    508 
    509     /* Start the actual include file on the next line */
    510 
    511     AslGbl_CurrentLineOffset++;
    512 
    513     /* Attempt to open the include file */
    514     /* If the file specifies an absolute path, just open it */
    515 
    516     if ((Filename[0] == '/')  ||
    517         (Filename[0] == '\\') ||
    518         (Filename[1] == ':'))
    519     {
    520         IncludeFile = PrOpenIncludeWithPrefix (
    521             "", Filename, OpenMode, FullPathname);
    522         if (!IncludeFile)
    523         {
    524             goto ErrorExit;
    525         }
    526         return (IncludeFile);
    527     }
    528 
    529     /*
    530      * The include filename is not an absolute path.
    531      *
    532      * First, search for the file within the "local" directory -- meaning
    533      * the same directory that contains the source file.
    534      *
    535      * Construct the file pathname from the global directory name.
    536      */
    537     IncludeFile = PrOpenIncludeWithPrefix (
    538         AslGbl_DirectoryPath, Filename, OpenMode, FullPathname);
    539     if (IncludeFile)
    540     {
    541         return (IncludeFile);
    542     }
    543 
    544     /*
    545      * Second, search for the file within the (possibly multiple)
    546      * directories specified by the -I option on the command line.
    547      */
    548     NextDir = AslGbl_IncludeDirList;
    549     while (NextDir)
    550     {
    551         IncludeFile = PrOpenIncludeWithPrefix (
    552             NextDir->Dir, Filename, OpenMode, FullPathname);
    553         if (IncludeFile)
    554         {
    555             return (IncludeFile);
    556         }
    557 
    558         NextDir = NextDir->Next;
    559     }
    560 
    561     /* We could not open the include file after trying very hard */
    562 
    563 ErrorExit:
    564     sprintf (AslGbl_MainTokenBuffer, "%s, %s", Filename, strerror (errno));
    565     PrError (ASL_ERROR, ASL_MSG_INCLUDE_FILE_OPEN, 0);
    566     return (NULL);
    567 }
    568 
    569 
    570 /*******************************************************************************
    571  *
    572  * FUNCTION:    FlOpenIncludeWithPrefix
    573  *
    574  * PARAMETERS:  PrefixDir       - Prefix directory pathname. Can be a zero
    575  *                                length string.
    576  *              Filename        - The include filename from the source ASL.
    577  *
    578  * RETURN:      Valid file descriptor if successful. Null otherwise.
    579  *
    580  * DESCRIPTION: Open an include file and push it on the input file stack.
    581  *
    582  ******************************************************************************/
    583 
    584 FILE *
    585 PrOpenIncludeWithPrefix (
    586     char                    *PrefixDir,
    587     char                    *Filename,
    588     char                    *OpenMode,
    589     char                    **FullPathname)
    590 {
    591     FILE                    *IncludeFile;
    592     char                    *Pathname;
    593 
    594 
    595     /* Build the full pathname to the file */
    596 
    597     Pathname = FlMergePathnames (PrefixDir, Filename);
    598 
    599     DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
    600         "Include: Opening file - \"%s\"\n",
    601         AslGbl_CurrentLineNumber, Pathname);
    602 
    603     /* Attempt to open the file, push if successful */
    604 
    605     IncludeFile = fopen (Pathname, OpenMode);
    606     if (!IncludeFile)
    607     {
    608         return (NULL);
    609     }
    610 
    611     /* Push the include file on the open input file stack */
    612 
    613     PrPushInputFileStack (IncludeFile, Pathname);
    614     *FullPathname = Pathname;
    615     return (IncludeFile);
    616 }
    617 
    618 
    619 /*******************************************************************************
    620  *
    621  * FUNCTION:    AslPushInputFileStack
    622  *
    623  * PARAMETERS:  InputFile           - Open file pointer
    624  *              Filename            - Name of the file
    625  *
    626  * RETURN:      None
    627  *
    628  * DESCRIPTION: Push the InputFile onto the file stack, and point the parser
    629  *              to this file. Called when an include file is successfully
    630  *              opened.
    631  *
    632  ******************************************************************************/
    633 
    634 void
    635 PrPushInputFileStack (
    636     FILE                    *InputFile,
    637     char                    *Filename)
    638 {
    639     PR_FILE_NODE            *Fnode;
    640 
    641 
    642     AslGbl_HasIncludeFiles = TRUE;
    643 
    644     /* Save the current state in an Fnode */
    645 
    646     Fnode = UtLocalCalloc (sizeof (PR_FILE_NODE));
    647 
    648     Fnode->File = AslGbl_Files[ASL_FILE_INPUT].Handle;
    649     Fnode->Next = AslGbl_InputFileList;
    650     Fnode->Filename = AslGbl_Files[ASL_FILE_INPUT].Filename;
    651     Fnode->CurrentLineNumber = AslGbl_CurrentLineNumber;
    652 
    653     /* Push it on the stack */
    654 
    655     AslGbl_InputFileList = Fnode;
    656 
    657     DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
    658         "Push InputFile Stack: handle %p\n\n",
    659         AslGbl_CurrentLineNumber, InputFile);
    660 
    661     /* Reset the global line count and filename */
    662 
    663     AslGbl_Files[ASL_FILE_INPUT].Filename =
    664         UtLocalCacheCalloc (strlen (Filename) + 1);
    665     strcpy (AslGbl_Files[ASL_FILE_INPUT].Filename, Filename);
    666 
    667     AslGbl_Files[ASL_FILE_INPUT].Handle = InputFile;
    668     AslGbl_CurrentLineNumber = 1;
    669 
    670     /* Emit a new #line directive for the include file */
    671 
    672     FlPrintFile (ASL_FILE_PREPROCESSOR, "#line %u \"%s\"\n", 1, Filename);
    673 }
    674 
    675 
    676 /*******************************************************************************
    677  *
    678  * FUNCTION:    AslPopInputFileStack
    679  *
    680  * PARAMETERS:  None
    681  *
    682  * RETURN:      0 if a node was popped, -1 otherwise
    683  *
    684  * DESCRIPTION: Pop the top of the input file stack and point the parser to
    685  *              the saved parse buffer contained in the fnode. Also, set the
    686  *              global line counters to the saved values. This function is
    687  *              called when an include file reaches EOF.
    688  *
    689  ******************************************************************************/
    690 
    691 BOOLEAN
    692 PrPopInputFileStack (
    693     void)
    694 {
    695     PR_FILE_NODE            *Fnode;
    696 
    697 
    698     Fnode = AslGbl_InputFileList;
    699     DbgPrint (ASL_PARSE_OUTPUT, "\n" PR_PREFIX_ID
    700         "Pop InputFile Stack, Fnode %p\n\n",
    701         AslGbl_CurrentLineNumber, Fnode);
    702 
    703     if (!Fnode)
    704     {
    705         return (FALSE);
    706     }
    707 
    708     /* Close the current include file */
    709 
    710     fclose (AslGbl_Files[ASL_FILE_INPUT].Handle);
    711 
    712     /* Update the top-of-stack */
    713 
    714     AslGbl_InputFileList = Fnode->Next;
    715 
    716     /* Reset global line counter and filename */
    717 
    718     AslGbl_Files[ASL_FILE_INPUT].Filename = Fnode->Filename;
    719     AslGbl_Files[ASL_FILE_INPUT].Handle = Fnode->File;
    720     AslGbl_CurrentLineNumber = Fnode->CurrentLineNumber;
    721 
    722     /* Emit a new #line directive after the include file */
    723 
    724     FlPrintFile (ASL_FILE_PREPROCESSOR, "#line %u \"%s\"\n",
    725         AslGbl_CurrentLineNumber, Fnode->Filename);
    726 
    727     /* All done with this node */
    728 
    729     ACPI_FREE (Fnode);
    730     return (TRUE);
    731 }
    732