Home | History | Annotate | Line # | Download | only in compiler
prscan.c revision 1.1
      1 /******************************************************************************
      2  *
      3  * Module Name: prscan - Preprocessor start-up and file scan module
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2013, 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 #define _DECLARE_PR_GLOBALS
     45 
     46 #include "aslcompiler.h"
     47 #include "dtcompiler.h"
     48 
     49 /*
     50  * TBDs:
     51  *
     52  * No nested macros, maybe never
     53  * Implement ASL "Include" as well as "#include" here?
     54  */
     55 #define _COMPONENT          ASL_PREPROCESSOR
     56         ACPI_MODULE_NAME    ("prscan")
     57 
     58 
     59 /* Local prototypes */
     60 
     61 static void
     62 PrPreprocessInputFile (
     63     void);
     64 
     65 static void
     66 PrDoDirective (
     67     char                    *DirectiveToken,
     68     char                    **Next);
     69 
     70 static int
     71 PrMatchDirective (
     72     char                    *Directive);
     73 
     74 static void
     75 PrPushDirective (
     76     int                     Directive,
     77     char                    *Argument);
     78 
     79 static ACPI_STATUS
     80 PrPopDirective (
     81     void);
     82 
     83 static void
     84 PrDbgPrint (
     85     char                    *Action,
     86     char                    *DirectiveName);
     87 
     88 
     89 /*
     90  * Supported preprocessor directives
     91  */
     92 static const PR_DIRECTIVE_INFO      Gbl_DirectiveInfo[] =
     93 {
     94     {"define",  1},
     95     {"elif",    0}, /* Converted to #else..#if internally */
     96     {"else",    0},
     97     {"endif",   0},
     98     {"error",   1},
     99     {"if",      1},
    100     {"ifdef",   1},
    101     {"ifndef",  1},
    102     {"include", 0}, /* Argument is not standard format, so 0 */
    103     {"line",    1},
    104     {"pragma",  1},
    105     {"undef",   1},
    106     {"warning", 1},
    107     {NULL,      0}
    108 };
    109 
    110 enum Gbl_DirectiveIndexes
    111 {
    112     PR_DIRECTIVE_DEFINE = 0,
    113     PR_DIRECTIVE_ELIF,
    114     PR_DIRECTIVE_ELSE,
    115     PR_DIRECTIVE_ENDIF,
    116     PR_DIRECTIVE_ERROR,
    117     PR_DIRECTIVE_IF,
    118     PR_DIRECTIVE_IFDEF,
    119     PR_DIRECTIVE_IFNDEF,
    120     PR_DIRECTIVE_INCLUDE,
    121     PR_DIRECTIVE_LINE,
    122     PR_DIRECTIVE_PRAGMA,
    123     PR_DIRECTIVE_UNDEF,
    124     PR_DIRECTIVE_WARNING,
    125 };
    126 
    127 #define ASL_DIRECTIVE_NOT_FOUND     -1
    128 
    129 
    130 /*******************************************************************************
    131  *
    132  * FUNCTION:    PrInitializePreprocessor
    133  *
    134  * PARAMETERS:  None
    135  *
    136  * RETURN:      None
    137  *
    138  * DESCRIPTION: Startup initialization for the Preprocessor.
    139  *
    140  ******************************************************************************/
    141 
    142 void
    143 PrInitializePreprocessor (
    144     void)
    145 {
    146     /* Init globals and the list of #defines */
    147 
    148     PrInitializeGlobals ();
    149     Gbl_DefineList = NULL;
    150 }
    151 
    152 
    153 /*******************************************************************************
    154  *
    155  * FUNCTION:    PrInitializeGlobals
    156  *
    157  * PARAMETERS:  None
    158  *
    159  * RETURN:      None
    160  *
    161  * DESCRIPTION: Initialize globals for the Preprocessor. Used for startuup
    162  *              initialization and re-initialization between compiles during
    163  *              a multiple source file compile.
    164  *
    165  ******************************************************************************/
    166 
    167 void
    168 PrInitializeGlobals (
    169     void)
    170 {
    171     /* Init globals */
    172 
    173     Gbl_InputFileList = NULL;
    174     Gbl_CurrentLineNumber = 0;
    175     Gbl_PreprocessorLineNumber = 1;
    176     Gbl_PreprocessorError = FALSE;
    177 
    178     /* These are used to track #if/#else blocks (possibly nested) */
    179 
    180     Gbl_IfDepth = 0;
    181     Gbl_IgnoringThisCodeBlock = FALSE;
    182     Gbl_DirectiveStack = NULL;
    183 }
    184 
    185 
    186 /*******************************************************************************
    187  *
    188  * FUNCTION:    PrTerminatePreprocessor
    189  *
    190  * PARAMETERS:  None
    191  *
    192  * RETURN:      None
    193  *
    194  * DESCRIPTION: Termination of the preprocessor. Delete lists. Keep any
    195  *              defines that were specified on the command line, in order to
    196  *              support multiple compiles with a single compiler invocation.
    197  *
    198  ******************************************************************************/
    199 
    200 void
    201 PrTerminatePreprocessor (
    202     void)
    203 {
    204     PR_DEFINE_INFO          *DefineInfo;
    205 
    206 
    207     /*
    208      * The persistent defines (created on the command line) are always at the
    209      * end of the list. We save them.
    210      */
    211     while ((Gbl_DefineList) && (!Gbl_DefineList->Persist))
    212     {
    213         DefineInfo = Gbl_DefineList;
    214         Gbl_DefineList = DefineInfo->Next;
    215 
    216         ACPI_FREE (DefineInfo->Replacement);
    217         ACPI_FREE (DefineInfo->Identifier);
    218         ACPI_FREE (DefineInfo);
    219     }
    220 }
    221 
    222 
    223 /*******************************************************************************
    224  *
    225  * FUNCTION:    PrDoPreprocess
    226  *
    227  * PARAMETERS:  None
    228  *
    229  * RETURN:      None
    230  *
    231  * DESCRIPTION: Main entry point for the iASL Preprocessor. Input file must
    232  *              be already open. Handles multiple input files via the
    233  *              #include directive.
    234  *
    235  ******************************************************************************/
    236 
    237 void
    238 PrDoPreprocess (
    239     void)
    240 {
    241     BOOLEAN                 MoreInputFiles;
    242 
    243 
    244     DbgPrint (ASL_DEBUG_OUTPUT, "Starting preprocessing phase\n\n");
    245 
    246 
    247     FlSeekFile (ASL_FILE_INPUT, 0);
    248     PrDumpPredefinedNames ();
    249 
    250     /* Main preprocessor loop, handles include files */
    251 
    252     do
    253     {
    254         PrPreprocessInputFile ();
    255         MoreInputFiles = PrPopInputFileStack ();
    256 
    257     } while (MoreInputFiles);
    258 
    259     /* Point compiler input to the new preprocessor output file (.i) */
    260 
    261     FlCloseFile (ASL_FILE_INPUT);
    262     Gbl_Files[ASL_FILE_INPUT].Handle = Gbl_Files[ASL_FILE_PREPROCESSOR].Handle;
    263     AslCompilerin = Gbl_Files[ASL_FILE_INPUT].Handle;
    264 
    265     /* Reset globals to allow compiler to run */
    266 
    267     FlSeekFile (ASL_FILE_INPUT, 0);
    268     Gbl_CurrentLineNumber = 1;
    269 
    270     DbgPrint (ASL_DEBUG_OUTPUT, "Preprocessing phase complete \n\n");
    271 }
    272 
    273 
    274 /*******************************************************************************
    275  *
    276  * FUNCTION:    PrPreprocessInputFile
    277  *
    278  * PARAMETERS:  None
    279  *
    280  * RETURN:      None
    281  *
    282  * DESCRIPTION: Preprocess one entire file, line-by-line.
    283  *
    284  * Input:  Raw user ASL from ASL_FILE_INPUT
    285  * Output: Preprocessed file written to ASL_FILE_PREPROCESSOR
    286  *
    287  ******************************************************************************/
    288 
    289 static void
    290 PrPreprocessInputFile (
    291     void)
    292 {
    293     UINT32                  Offset;
    294     char                    *Token;
    295     char                    *ReplaceString;
    296     PR_DEFINE_INFO          *DefineInfo;
    297     ACPI_SIZE               TokenOffset;
    298     char                    *Next;
    299     int                     OffsetAdjust;
    300 
    301 
    302     /* Scan line-by-line. Comments and blank lines are skipped by this function */
    303 
    304     while ((Offset = DtGetNextLine (Gbl_Files[ASL_FILE_INPUT].Handle)) != ASL_EOF)
    305     {
    306         /* Need a copy of the input line for strok() */
    307 
    308         strcpy (Gbl_MainTokenBuffer, Gbl_CurrentLineBuffer);
    309         Token = PrGetNextToken (Gbl_MainTokenBuffer, PR_TOKEN_SEPARATORS, &Next);
    310         OffsetAdjust = 0;
    311 
    312         /* All preprocessor directives must begin with '#' */
    313 
    314         if (Token && (*Token == '#'))
    315         {
    316             if (strlen (Token) == 1)
    317             {
    318                 Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, &Next);
    319             }
    320             else
    321             {
    322                 Token++;    /* Skip leading # */
    323             }
    324 
    325             /* Execute the directive, do not write line to output file */
    326 
    327             PrDoDirective (Token, &Next);
    328             continue;
    329         }
    330 
    331         /*
    332          * If we are currently within the part of an IF/ELSE block that is
    333          * FALSE, ignore the line and do not write it to the output file.
    334          * This continues until an #else or #endif is encountered.
    335          */
    336         if (Gbl_IgnoringThisCodeBlock)
    337         {
    338             continue;
    339         }
    340 
    341         /* Match and replace all #defined names within this source line */
    342 
    343         while (Token)
    344         {
    345             DefineInfo = PrMatchDefine (Token);
    346             if (DefineInfo)
    347             {
    348                 if (DefineInfo->Body)
    349                 {
    350                     /* This is a macro */
    351 
    352                     DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
    353                         "Matched Macro: %s->%s\n",
    354                         Gbl_CurrentLineNumber, DefineInfo->Identifier,
    355                         DefineInfo->Replacement);
    356 
    357                     PrDoMacroInvocation (Gbl_MainTokenBuffer, Token,
    358                         DefineInfo, &Next);
    359                 }
    360                 else
    361                 {
    362                     ReplaceString = DefineInfo->Replacement;
    363 
    364                     /* Replace the name in the original line buffer */
    365 
    366                     TokenOffset = Token - Gbl_MainTokenBuffer + OffsetAdjust;
    367                     PrReplaceData (
    368                         &Gbl_CurrentLineBuffer[TokenOffset], strlen (Token),
    369                         ReplaceString, strlen (ReplaceString));
    370 
    371                     /* Adjust for length difference between old and new name length */
    372 
    373                     OffsetAdjust += strlen (ReplaceString) - strlen (Token);
    374 
    375                     DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
    376                         "Matched #define: %s->%s\n",
    377                         Gbl_CurrentLineNumber, Token,
    378                         *ReplaceString ? ReplaceString : "(NULL STRING)");
    379                 }
    380             }
    381 
    382             Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, &Next);
    383         }
    384 
    385 #if 0
    386 /* Line prefix */
    387         FlPrintFile (ASL_FILE_PREPROCESSOR, "/* %14s  %.5u  i:%.5u */ ",
    388             Gbl_Files[ASL_FILE_INPUT].Filename,
    389             Gbl_CurrentLineNumber, Gbl_PreprocessorLineNumber);
    390 #endif
    391 
    392         /*
    393          * Emit a #line directive if necessary, to keep the line numbers in
    394          * the (.i) file synchronized with the original source code file, so
    395          * that the correct line number appears in any error messages
    396          * generated by the actual compiler.
    397          */
    398         if (Gbl_CurrentLineNumber > (Gbl_PreviousLineNumber + 1))
    399         {
    400             FlPrintFile (ASL_FILE_PREPROCESSOR, "#line %u\n",
    401                 Gbl_CurrentLineNumber);
    402         }
    403 
    404         Gbl_PreviousLineNumber = Gbl_CurrentLineNumber;
    405         Gbl_PreprocessorLineNumber++;
    406 
    407         /*
    408          * Now we can write the possibly modified source line to the
    409          * preprocessor (.i) file
    410          */
    411         FlWriteFile (ASL_FILE_PREPROCESSOR, Gbl_CurrentLineBuffer,
    412             strlen (Gbl_CurrentLineBuffer));
    413     }
    414 }
    415 
    416 
    417 /*******************************************************************************
    418  *
    419  * FUNCTION:    PrDoDirective
    420  *
    421  * PARAMETERS:  Directive               - Pointer to directive name token
    422  *              Next                    - "Next" buffer from GetNextToken
    423  *
    424  * RETURN:      None.
    425  *
    426  * DESCRIPTION: Main processing for all preprocessor directives
    427  *
    428  ******************************************************************************/
    429 
    430 static void
    431 PrDoDirective (
    432     char                    *DirectiveToken,
    433     char                    **Next)
    434 {
    435     char                    *Token = Gbl_MainTokenBuffer;
    436     char                    *Token2;
    437     char                    *End;
    438     UINT64                  Value;
    439     ACPI_SIZE               TokenOffset;
    440     int                     Directive;
    441     ACPI_STATUS             Status;
    442 
    443 
    444     if (!DirectiveToken)
    445     {
    446         goto SyntaxError;
    447     }
    448 
    449     Directive = PrMatchDirective (DirectiveToken);
    450     if (Directive == ASL_DIRECTIVE_NOT_FOUND)
    451     {
    452         PrError (ASL_ERROR, ASL_MSG_UNKNOWN_DIRECTIVE,
    453             THIS_TOKEN_OFFSET (DirectiveToken));
    454 
    455         DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
    456             "#%s: Unknown directive\n",
    457             Gbl_CurrentLineNumber, DirectiveToken);
    458         return;
    459     }
    460 
    461     /*
    462      * If we are currently ignoring this block and we encounter a #else or
    463      * #elif, we must ignore their blocks also if the parent block is also
    464      * being ignored.
    465      */
    466     if (Gbl_IgnoringThisCodeBlock)
    467     {
    468         switch (Directive)
    469         {
    470         case PR_DIRECTIVE_ELSE:
    471         case PR_DIRECTIVE_ELIF:
    472 
    473             if (Gbl_DirectiveStack && Gbl_DirectiveStack->IgnoringThisCodeBlock)
    474             {
    475                 PrDbgPrint ("Ignoring", Gbl_DirectiveInfo[Directive].Name);
    476                 return;
    477             }
    478             break;
    479 
    480         default:
    481             break;
    482         }
    483     }
    484 
    485     /*
    486      * Need to always check for #else, #elif, #endif regardless of
    487      * whether we are ignoring the current code block, since these
    488      * are conditional code block terminators.
    489      */
    490     switch (Directive)
    491     {
    492     case PR_DIRECTIVE_ELSE:
    493 
    494         Gbl_IgnoringThisCodeBlock = !(Gbl_IgnoringThisCodeBlock);
    495         PrDbgPrint ("Executing", "else block");
    496         return;
    497 
    498     case PR_DIRECTIVE_ELIF:
    499 
    500         Gbl_IgnoringThisCodeBlock = !(Gbl_IgnoringThisCodeBlock);
    501         Directive = PR_DIRECTIVE_IF;
    502 
    503         if (Gbl_IgnoringThisCodeBlock == TRUE)
    504         {
    505             /* Not executing the ELSE part -- all done here */
    506             PrDbgPrint ("Ignoring", "elif block");
    507             return;
    508         }
    509 
    510         /*
    511          * After this, we will execute the IF part further below.
    512          * First, however, pop off the original #if directive.
    513          */
    514         if (ACPI_FAILURE (PrPopDirective ()))
    515         {
    516             PrError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL,
    517                 THIS_TOKEN_OFFSET (DirectiveToken));
    518         }
    519 
    520         PrDbgPrint ("Executing", "elif block");
    521         break;
    522 
    523     case PR_DIRECTIVE_ENDIF:
    524 
    525         PrDbgPrint ("Executing", "endif");
    526 
    527         /* Pop the owning #if/#ifdef/#ifndef */
    528 
    529         if (ACPI_FAILURE (PrPopDirective ()))
    530         {
    531             PrError (ASL_ERROR, ASL_MSG_ENDIF_MISMATCH,
    532                 THIS_TOKEN_OFFSET (DirectiveToken));
    533         }
    534         return;
    535 
    536     default:
    537         break;
    538     }
    539 
    540     /* Most directives have at least one argument */
    541 
    542     if (Gbl_DirectiveInfo[Directive].ArgCount == 1)
    543     {
    544         Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next);
    545         if (!Token)
    546         {
    547             goto SyntaxError;
    548         }
    549     }
    550 
    551     /*
    552      * At this point, if we are ignoring the current code block,
    553      * do not process any more directives (i.e., ignore them also.)
    554      * For "if" style directives, open/push a new block anyway. We
    555      * must do this to keep track of #endif directives
    556      */
    557     if (Gbl_IgnoringThisCodeBlock)
    558     {
    559         switch (Directive)
    560         {
    561         case PR_DIRECTIVE_IF:
    562         case PR_DIRECTIVE_IFDEF:
    563         case PR_DIRECTIVE_IFNDEF:
    564 
    565             PrPushDirective (Directive, Token);
    566             PrDbgPrint ("Ignoring", Gbl_DirectiveInfo[Directive].Name);
    567             break;
    568 
    569         default:
    570             break;
    571         }
    572 
    573         return;
    574     }
    575 
    576     /*
    577      * Execute the directive
    578      */
    579     PrDbgPrint ("Begin execution", Gbl_DirectiveInfo[Directive].Name);
    580 
    581     switch (Directive)
    582     {
    583     case PR_DIRECTIVE_IF:
    584 
    585         TokenOffset = Token - Gbl_MainTokenBuffer;
    586 
    587         /* Need to expand #define macros in the expression string first */
    588 
    589         Status = PrResolveIntegerExpression (
    590             &Gbl_CurrentLineBuffer[TokenOffset-1], &Value);
    591         if (ACPI_FAILURE (Status))
    592         {
    593             return;
    594         }
    595 
    596         PrPushDirective (Directive, Token);
    597         if (!Value)
    598         {
    599             Gbl_IgnoringThisCodeBlock = TRUE;
    600         }
    601 
    602         DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
    603             "Resolved #if: %8.8X%8.8X %s\n",
    604             Gbl_CurrentLineNumber, ACPI_FORMAT_UINT64 (Value),
    605             Gbl_IgnoringThisCodeBlock ? "<Skipping Block>" : "<Executing Block>");
    606         break;
    607 
    608     case PR_DIRECTIVE_IFDEF:
    609 
    610         PrPushDirective (Directive, Token);
    611         if (!PrMatchDefine (Token))
    612         {
    613             Gbl_IgnoringThisCodeBlock = TRUE;
    614         }
    615 
    616         PrDbgPrint ("Evaluated", "ifdef");
    617         break;
    618 
    619     case PR_DIRECTIVE_IFNDEF:
    620 
    621         PrPushDirective (Directive, Token);
    622         if (PrMatchDefine (Token))
    623         {
    624             Gbl_IgnoringThisCodeBlock = TRUE;
    625         }
    626 
    627         PrDbgPrint ("Evaluated", "ifndef");
    628         break;
    629 
    630     case PR_DIRECTIVE_DEFINE:
    631         /*
    632          * By definition, if first char after the name is a paren,
    633          * this is a function macro.
    634          */
    635         TokenOffset = Token - Gbl_MainTokenBuffer + strlen (Token);
    636         if (*(&Gbl_CurrentLineBuffer[TokenOffset]) == '(')
    637         {
    638 #ifndef MACROS_SUPPORTED
    639             AcpiOsPrintf ("%s ERROR - line %u: #define macros are not supported yet\n",
    640                 Gbl_CurrentLineBuffer, Gbl_CurrentLineNumber);
    641             exit(1);
    642 #else
    643             PrAddMacro (Token, Next);
    644 #endif
    645         }
    646         else
    647         {
    648             /* Use the remainder of the line for the #define */
    649 
    650             Token2 = *Next;
    651             if (Token2)
    652             {
    653                 while ((*Token2 == ' ') || (*Token2 == '\t'))
    654                 {
    655                     Token2++;
    656                 }
    657                 End = Token2;
    658                 while (*End != '\n')
    659                 {
    660                     End++;
    661                 }
    662                 *End = 0;
    663             }
    664             else
    665             {
    666                 Token2 = "";
    667             }
    668 #if 0
    669             Token2 = PrGetNextToken (NULL, "\n", /*PR_TOKEN_SEPARATORS,*/ Next);
    670             if (!Token2)
    671             {
    672                 Token2 = "";
    673             }
    674 #endif
    675             DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
    676                 "New #define: %s->%s\n",
    677                 Gbl_CurrentLineNumber, Token, Token2);
    678 
    679             PrAddDefine (Token, Token2, FALSE);
    680         }
    681         break;
    682 
    683     case PR_DIRECTIVE_ERROR:
    684 
    685         /* Note: No macro expansion */
    686 
    687         PrError (ASL_ERROR, ASL_MSG_ERROR_DIRECTIVE,
    688             THIS_TOKEN_OFFSET (Token));
    689 
    690         Gbl_SourceLine = 0;
    691         Gbl_NextError = Gbl_ErrorLog;
    692         CmCleanupAndExit ();
    693         exit(1);
    694 
    695     case PR_DIRECTIVE_INCLUDE:
    696 
    697         Token = PrGetNextToken (NULL, " \"<>", Next);
    698         if (!Token)
    699         {
    700             goto SyntaxError;
    701         }
    702 
    703         DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
    704             "Start #include file \"%s\"\n", Gbl_CurrentLineNumber,
    705             Token, Gbl_CurrentLineNumber);
    706 
    707         PrOpenIncludeFile (Token);
    708         break;
    709 
    710     case PR_DIRECTIVE_LINE:
    711 
    712         TokenOffset = Token - Gbl_MainTokenBuffer;
    713 
    714         Status = PrResolveIntegerExpression (
    715             &Gbl_CurrentLineBuffer[TokenOffset-1], &Value);
    716         if (ACPI_FAILURE (Status))
    717         {
    718             return;
    719         }
    720 
    721         DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
    722             "User #line invocation %s\n", Gbl_CurrentLineNumber,
    723             Token);
    724 
    725         /* Update local line numbers */
    726 
    727         Gbl_CurrentLineNumber = (UINT32) Value;
    728         Gbl_PreviousLineNumber = 0;
    729 
    730         /* Emit #line into the preprocessor file */
    731 
    732         FlPrintFile (ASL_FILE_PREPROCESSOR, "#line %u \"%s\"\n",
    733             Gbl_CurrentLineNumber, Gbl_Files[ASL_FILE_INPUT].Filename);
    734         break;
    735 
    736     case PR_DIRECTIVE_PRAGMA:
    737 
    738         if (!strcmp (Token, "disable"))
    739         {
    740             Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next);
    741             if (!Token)
    742             {
    743                 goto SyntaxError;
    744             }
    745 
    746             TokenOffset = Token - Gbl_MainTokenBuffer;
    747             AslDisableException (&Gbl_CurrentLineBuffer[TokenOffset]);
    748         }
    749         else if (!strcmp (Token, "message"))
    750         {
    751             Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next);
    752             if (!Token)
    753             {
    754                 goto SyntaxError;
    755             }
    756 
    757             TokenOffset = Token - Gbl_MainTokenBuffer;
    758             AcpiOsPrintf ("%s\n", &Gbl_CurrentLineBuffer[TokenOffset]);
    759         }
    760         else
    761         {
    762             PrError (ASL_ERROR, ASL_MSG_UNKNOWN_PRAGMA,
    763                 THIS_TOKEN_OFFSET (Token));
    764             return;
    765         }
    766 
    767         break;
    768 
    769     case PR_DIRECTIVE_UNDEF:
    770 
    771         DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
    772             "#undef: %s\n", Gbl_CurrentLineNumber, Token);
    773 
    774         PrRemoveDefine (Token);
    775         break;
    776 
    777     case PR_DIRECTIVE_WARNING:
    778 
    779         PrError (ASL_WARNING, ASL_MSG_WARNING_DIRECTIVE,
    780             THIS_TOKEN_OFFSET (Token));
    781         break;
    782 
    783     default:
    784 
    785         /* Should never get here */
    786         DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
    787             "Unrecognized directive: %u\n",
    788             Gbl_CurrentLineNumber, Directive);
    789         break;
    790     }
    791 
    792     return;
    793 
    794 SyntaxError:
    795 
    796     PrError (ASL_ERROR, ASL_MSG_DIRECTIVE_SYNTAX,
    797         THIS_TOKEN_OFFSET (DirectiveToken));
    798     return;
    799 }
    800 
    801 
    802 /*******************************************************************************
    803  *
    804  * FUNCTION:    PrMatchDirective
    805  *
    806  * PARAMETERS:  Directive           - Pointer to directive name token
    807  *
    808  * RETURN:      Index into command array, -1 if not found
    809  *
    810  * DESCRIPTION: Lookup the incoming directive in the known directives table.
    811  *
    812  ******************************************************************************/
    813 
    814 static int
    815 PrMatchDirective (
    816     char                    *Directive)
    817 {
    818     int                     i;
    819 
    820 
    821     if (!Directive || Directive[0] == 0)
    822     {
    823         return (ASL_DIRECTIVE_NOT_FOUND);
    824     }
    825 
    826     for (i = 0; Gbl_DirectiveInfo[i].Name; i++)
    827     {
    828         if (!strcmp (Gbl_DirectiveInfo[i].Name, Directive))
    829         {
    830             return (i);
    831         }
    832     }
    833 
    834     return (ASL_DIRECTIVE_NOT_FOUND);    /* Command not recognized */
    835 }
    836 
    837 
    838 /*******************************************************************************
    839  *
    840  * FUNCTION:    PrPushDirective
    841  *
    842  * PARAMETERS:  Directive           - Encoded directive ID
    843  *              Argument            - String containing argument to the
    844  *                                    directive
    845  *
    846  * RETURN:      None
    847  *
    848  * DESCRIPTION: Push an item onto the directive stack. Used for processing
    849  *              nested #if/#else type conditional compilation directives.
    850  *              Specifically: Used on detection of #if/#ifdef/#ifndef to open
    851  *              a block.
    852  *
    853  ******************************************************************************/
    854 
    855 static void
    856 PrPushDirective (
    857     int                     Directive,
    858     char                    *Argument)
    859 {
    860     DIRECTIVE_INFO          *Info;
    861 
    862 
    863     /* Allocate and populate a stack info item */
    864 
    865     Info = ACPI_ALLOCATE (sizeof (DIRECTIVE_INFO));
    866 
    867     Info->Next = Gbl_DirectiveStack;
    868     Info->Directive = Directive;
    869     Info->IgnoringThisCodeBlock = Gbl_IgnoringThisCodeBlock;
    870     strncpy (Info->Argument, Argument, MAX_ARGUMENT_LENGTH);
    871 
    872     DbgPrint (ASL_DEBUG_OUTPUT,
    873         "Pr(%.4u) - [%u %s] %*s Pushed [#%s %s]: IgnoreFlag = %s\n",
    874         Gbl_CurrentLineNumber, Gbl_IfDepth,
    875         Gbl_IgnoringThisCodeBlock ? "I" : "E",
    876         Gbl_IfDepth * 4, " ",
    877         Gbl_DirectiveInfo[Directive].Name,
    878         Argument, Gbl_IgnoringThisCodeBlock ? "TRUE" : "FALSE");
    879 
    880     /* Push new item */
    881 
    882     Gbl_DirectiveStack = Info;
    883     Gbl_IfDepth++;
    884 }
    885 
    886 
    887 /*******************************************************************************
    888  *
    889  * FUNCTION:    PrPopDirective
    890  *
    891  * PARAMETERS:  None
    892  *
    893  * RETURN:      Status. Error if the stack is empty.
    894  *
    895  * DESCRIPTION: Pop an item off the directive stack. Used for processing
    896  *              nested #if/#else type conditional compilation directives.
    897  *              Specifically: Used on detection of #elif and #endif to remove
    898  *              the original #if/#ifdef/#ifndef from the stack and close
    899  *              the block.
    900  *
    901  ******************************************************************************/
    902 
    903 static ACPI_STATUS
    904 PrPopDirective (
    905     void)
    906 {
    907     DIRECTIVE_INFO          *Info;
    908 
    909 
    910     /* Check for empty stack */
    911 
    912     Info = Gbl_DirectiveStack;
    913     if (!Info)
    914     {
    915         return (AE_ERROR);
    916     }
    917 
    918     /* Pop one item, keep globals up-to-date */
    919 
    920     Gbl_IfDepth--;
    921     Gbl_IgnoringThisCodeBlock = Info->IgnoringThisCodeBlock;
    922     Gbl_DirectiveStack = Info->Next;
    923 
    924     DbgPrint (ASL_DEBUG_OUTPUT,
    925         "Pr(%.4u) - [%u %s] %*s Popped [#%s %s]: IgnoreFlag now = %s\n",
    926         Gbl_CurrentLineNumber, Gbl_IfDepth,
    927         Gbl_IgnoringThisCodeBlock ? "I" : "E",
    928         Gbl_IfDepth * 4, " ",
    929         Gbl_DirectiveInfo[Info->Directive].Name,
    930         Info->Argument, Gbl_IgnoringThisCodeBlock ? "TRUE" : "FALSE");
    931 
    932     ACPI_FREE (Info);
    933     return (AE_OK);
    934 }
    935 
    936 
    937 /*******************************************************************************
    938  *
    939  * FUNCTION:    PrDbgPrint
    940  *
    941  * PARAMETERS:  Action              - Action being performed
    942  *              DirectiveName       - Directive being processed
    943  *
    944  * RETURN:      None
    945  *
    946  * DESCRIPTION: Special debug print for directive processing.
    947  *
    948  ******************************************************************************/
    949 
    950 static void
    951 PrDbgPrint (
    952     char                    *Action,
    953     char                    *DirectiveName)
    954 {
    955 
    956     DbgPrint (ASL_DEBUG_OUTPUT, "Pr(%.4u) - [%u %s] "
    957         "%*s %s #%s, Depth %u\n",
    958         Gbl_CurrentLineNumber, Gbl_IfDepth,
    959         Gbl_IgnoringThisCodeBlock ? "I" : "E",
    960         Gbl_IfDepth * 4, " ",
    961         Action, DirectiveName, Gbl_IfDepth);
    962 }
    963