prscan.c revision 250838
1233237Sjkim/****************************************************************************** 2233237Sjkim * 3233237Sjkim * Module Name: prscan - Preprocessor start-up and file scan module 4233237Sjkim * 5233237Sjkim *****************************************************************************/ 6233237Sjkim 7233237Sjkim/* 8245582Sjkim * Copyright (C) 2000 - 2013, Intel Corp. 9233237Sjkim * All rights reserved. 10233237Sjkim * 11233237Sjkim * Redistribution and use in source and binary forms, with or without 12233237Sjkim * modification, are permitted provided that the following conditions 13233237Sjkim * are met: 14233237Sjkim * 1. Redistributions of source code must retain the above copyright 15233237Sjkim * notice, this list of conditions, and the following disclaimer, 16233237Sjkim * without modification. 17233237Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18233237Sjkim * substantially similar to the "NO WARRANTY" disclaimer below 19233237Sjkim * ("Disclaimer") and any redistribution must be conditioned upon 20233237Sjkim * including a substantially similar Disclaimer requirement for further 21233237Sjkim * binary redistribution. 22233237Sjkim * 3. Neither the names of the above-listed copyright holders nor the names 23233237Sjkim * of any contributors may be used to endorse or promote products derived 24233237Sjkim * from this software without specific prior written permission. 25233237Sjkim * 26233237Sjkim * Alternatively, this software may be distributed under the terms of the 27233237Sjkim * GNU General Public License ("GPL") version 2 as published by the Free 28233237Sjkim * Software Foundation. 29233237Sjkim * 30233237Sjkim * NO WARRANTY 31233237Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32233237Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33233237Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34233237Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35233237Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36233237Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37233237Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38233237Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39233237Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40233237Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41233237Sjkim * POSSIBILITY OF SUCH DAMAGES. 42233237Sjkim */ 43233237Sjkim 44233237Sjkim#define _DECLARE_PR_GLOBALS 45233237Sjkim 46233250Sjkim#include <contrib/dev/acpica/compiler/aslcompiler.h> 47233250Sjkim#include <contrib/dev/acpica/compiler/dtcompiler.h> 48233237Sjkim 49233237Sjkim/* 50233237Sjkim * TBDs: 51233237Sjkim * 52233237Sjkim * No nested macros, maybe never 53233237Sjkim * Implement ASL "Include" as well as "#include" here? 54233237Sjkim */ 55233237Sjkim#define _COMPONENT ASL_PREPROCESSOR 56233237Sjkim ACPI_MODULE_NAME ("prscan") 57233237Sjkim 58233237Sjkim 59233237Sjkim/* Local prototypes */ 60233237Sjkim 61233237Sjkimstatic void 62233237SjkimPrPreprocessInputFile ( 63233237Sjkim void); 64233237Sjkim 65233237Sjkimstatic void 66233237SjkimPrDoDirective ( 67233237Sjkim char *DirectiveToken, 68233237Sjkim char **Next, 69233237Sjkim BOOLEAN *IgnoringThisCodeBlock); 70233237Sjkim 71233237Sjkimstatic int 72233237SjkimPrMatchDirective ( 73233237Sjkim char *Directive); 74233237Sjkim 75233237Sjkim/* 76233237Sjkim * Supported preprocessor directives 77233237Sjkim */ 78233237Sjkimstatic const PR_DIRECTIVE_INFO Gbl_DirectiveInfo[] = 79233237Sjkim{ 80233237Sjkim {"define", 1}, 81233237Sjkim {"elif", 0}, /* Converted to #else..#if internally */ 82233237Sjkim {"else", 0}, 83233237Sjkim {"endif", 0}, 84233237Sjkim {"error", 1}, 85233237Sjkim {"if", 1}, 86233237Sjkim {"ifdef", 1}, 87233237Sjkim {"ifndef", 1}, 88233237Sjkim {"include", 0}, /* Argument is not standard format, so 0 */ 89233237Sjkim {"line", 1}, 90233237Sjkim {"pragma", 1}, 91233237Sjkim {"undef", 1}, 92233237Sjkim {"warning", 1}, 93233237Sjkim {NULL, 0} 94233237Sjkim}; 95233237Sjkim 96233237Sjkimenum Gbl_DirectiveIndexes 97233237Sjkim{ 98233237Sjkim PR_DIRECTIVE_DEFINE = 0, 99233237Sjkim PR_DIRECTIVE_ELIF, 100233237Sjkim PR_DIRECTIVE_ELSE, 101233237Sjkim PR_DIRECTIVE_ENDIF, 102233237Sjkim PR_DIRECTIVE_ERROR, 103233237Sjkim PR_DIRECTIVE_IF, 104233237Sjkim PR_DIRECTIVE_IFDEF, 105233237Sjkim PR_DIRECTIVE_IFNDEF, 106233237Sjkim PR_DIRECTIVE_INCLUDE, 107233237Sjkim PR_DIRECTIVE_LINE, 108233237Sjkim PR_DIRECTIVE_PRAGMA, 109233237Sjkim PR_DIRECTIVE_UNDEF, 110233237Sjkim PR_DIRECTIVE_WARNING, 111233237Sjkim}; 112233237Sjkim 113233237Sjkim#define ASL_DIRECTIVE_NOT_FOUND -1 114233237Sjkim 115233237Sjkim 116233237Sjkim/******************************************************************************* 117233237Sjkim * 118233237Sjkim * FUNCTION: PrInitializePreprocessor 119233237Sjkim * 120233237Sjkim * PARAMETERS: None 121233237Sjkim * 122233237Sjkim * RETURN: None 123233237Sjkim * 124233237Sjkim * DESCRIPTION: Startup initialization for the Preprocessor. 125233237Sjkim * 126233237Sjkim ******************************************************************************/ 127233237Sjkim 128233237Sjkimvoid 129233237SjkimPrInitializePreprocessor ( 130233237Sjkim void) 131233237Sjkim{ 132233237Sjkim /* Init globals and the list of #defines */ 133233237Sjkim 134233237Sjkim PrInitializeGlobals (); 135233237Sjkim Gbl_DefineList = NULL; 136233237Sjkim} 137233237Sjkim 138233237Sjkim 139233237Sjkim/******************************************************************************* 140233237Sjkim * 141233237Sjkim * FUNCTION: PrInitializeGlobals 142233237Sjkim * 143233237Sjkim * PARAMETERS: None 144233237Sjkim * 145233237Sjkim * RETURN: None 146233237Sjkim * 147233237Sjkim * DESCRIPTION: Initialize globals for the Preprocessor. Used for startuup 148233237Sjkim * initialization and re-initialization between compiles during 149233237Sjkim * a multiple source file compile. 150233237Sjkim * 151233237Sjkim ******************************************************************************/ 152233237Sjkim 153233237Sjkimvoid 154233237SjkimPrInitializeGlobals ( 155233237Sjkim void) 156233237Sjkim{ 157233237Sjkim /* Init globals */ 158233237Sjkim 159233237Sjkim Gbl_IfDepth = 0; 160233237Sjkim Gbl_InputFileList = NULL; 161233237Sjkim Gbl_CurrentLineNumber = 0; 162233237Sjkim Gbl_PreprocessorLineNumber = 1; 163233237Sjkim Gbl_PreprocessorError = FALSE; 164233237Sjkim} 165233237Sjkim 166233237Sjkim 167233237Sjkim/******************************************************************************* 168233237Sjkim * 169233237Sjkim * FUNCTION: PrTerminatePreprocessor 170233237Sjkim * 171233237Sjkim * PARAMETERS: None 172233237Sjkim * 173233237Sjkim * RETURN: None 174233237Sjkim * 175233237Sjkim * DESCRIPTION: Termination of the preprocessor. Delete lists. Keep any 176233237Sjkim * defines that were specified on the command line, in order to 177233237Sjkim * support multiple compiles with a single compiler invocation. 178233237Sjkim * 179233237Sjkim ******************************************************************************/ 180233237Sjkim 181233237Sjkimvoid 182233237SjkimPrTerminatePreprocessor ( 183233237Sjkim void) 184233237Sjkim{ 185233237Sjkim PR_DEFINE_INFO *DefineInfo; 186233237Sjkim 187233237Sjkim 188233237Sjkim /* 189233237Sjkim * The persistent defines (created on the command line) are always at the 190233237Sjkim * end of the list. We save them. 191233237Sjkim */ 192233237Sjkim while ((Gbl_DefineList) && (!Gbl_DefineList->Persist)) 193233237Sjkim { 194233237Sjkim DefineInfo = Gbl_DefineList; 195233237Sjkim Gbl_DefineList = DefineInfo->Next; 196233237Sjkim 197233237Sjkim ACPI_FREE (DefineInfo->Replacement); 198233237Sjkim ACPI_FREE (DefineInfo->Identifier); 199233237Sjkim ACPI_FREE (DefineInfo); 200233237Sjkim } 201233237Sjkim} 202233237Sjkim 203233237Sjkim 204233237Sjkim/******************************************************************************* 205233237Sjkim * 206233237Sjkim * FUNCTION: PrDoPreprocess 207233237Sjkim * 208233237Sjkim * PARAMETERS: None 209233237Sjkim * 210233237Sjkim * RETURN: Error Status. TRUE if error, FALSE if OK. 211233237Sjkim * 212233237Sjkim * DESCRIPTION: Main entry point for the iASL Preprocessor. Input file must 213233237Sjkim * be already open. Handles multiple input files via the 214233237Sjkim * #include directive. 215233237Sjkim * 216233237Sjkim ******************************************************************************/ 217233237Sjkim 218233237SjkimBOOLEAN 219233237SjkimPrDoPreprocess ( 220233237Sjkim void) 221233237Sjkim{ 222233237Sjkim BOOLEAN MoreInputFiles; 223233237Sjkim 224233237Sjkim 225233237Sjkim DbgPrint (ASL_DEBUG_OUTPUT, "Starting preprocessing phase\n\n"); 226233237Sjkim 227233237Sjkim 228233237Sjkim FlSeekFile (ASL_FILE_INPUT, 0); 229233237Sjkim PrDumpPredefinedNames (); 230233237Sjkim 231233237Sjkim /* Main preprocessor loop, handles include files */ 232233237Sjkim 233233237Sjkim do 234233237Sjkim { 235233237Sjkim PrPreprocessInputFile (); 236233237Sjkim MoreInputFiles = PrPopInputFileStack (); 237233237Sjkim 238233237Sjkim } while (MoreInputFiles); 239233237Sjkim 240233237Sjkim 241233237Sjkim /* 242233237Sjkim * TBD: is this necessary? (Do we abort on any preprocessing errors?) 243233237Sjkim */ 244233237Sjkim if (Gbl_PreprocessorError) 245233237Sjkim { 246233237Sjkim /* TBD: can't use source_output file for preprocessor error reporting */ 247233237Sjkim 248233237Sjkim Gbl_Files[ASL_FILE_SOURCE_OUTPUT].Handle = NULL; 249233237Sjkim PrTerminatePreprocessor (); 250233237Sjkim return (TRUE); 251233237Sjkim } 252233237Sjkim 253233237Sjkim /* Point compiler input to the new preprocessor file (.i) */ 254233237Sjkim 255233237Sjkim FlCloseFile (ASL_FILE_INPUT); 256233237Sjkim Gbl_Files[ASL_FILE_INPUT].Handle = Gbl_Files[ASL_FILE_PREPROCESSOR].Handle; 257233237Sjkim AslCompilerin = Gbl_Files[ASL_FILE_INPUT].Handle; 258233237Sjkim 259233237Sjkim /* Reset globals to allow compiler to run */ 260233237Sjkim 261233237Sjkim FlSeekFile (ASL_FILE_INPUT, 0); 262233237Sjkim Gbl_CurrentLineNumber = 1; 263233237Sjkim 264233237Sjkim DbgPrint (ASL_DEBUG_OUTPUT, "Preprocessing phase complete \n\n"); 265233237Sjkim return (FALSE); 266233237Sjkim} 267233237Sjkim 268233237Sjkim 269233237Sjkim/******************************************************************************* 270233237Sjkim * 271233237Sjkim * FUNCTION: PrPreprocessInputFile 272233237Sjkim * 273233237Sjkim * PARAMETERS: None 274233237Sjkim * 275233237Sjkim * RETURN: None 276233237Sjkim * 277233237Sjkim * DESCRIPTION: Preprocess one entire file, line-by-line. 278233237Sjkim * 279233237Sjkim * Input: Raw user ASL from ASL_FILE_INPUT 280233237Sjkim * Output: Preprocessed file written to ASL_FILE_PREPROCESSOR 281233237Sjkim * 282233237Sjkim ******************************************************************************/ 283233237Sjkim 284233237Sjkimstatic void 285233237SjkimPrPreprocessInputFile ( 286233237Sjkim void) 287233237Sjkim{ 288233237Sjkim UINT32 Offset; 289233237Sjkim char *Token; 290233237Sjkim char *ReplaceString; 291233237Sjkim PR_DEFINE_INFO *DefineInfo; 292233237Sjkim ACPI_SIZE TokenOffset; 293233237Sjkim BOOLEAN IgnoringThisCodeBlock = FALSE; 294233237Sjkim char *Next; 295233237Sjkim int OffsetAdjust; 296233237Sjkim 297233237Sjkim 298233237Sjkim /* Scan line-by-line. Comments and blank lines are skipped by this function */ 299233237Sjkim 300233237Sjkim while ((Offset = DtGetNextLine (Gbl_Files[ASL_FILE_INPUT].Handle)) != ASL_EOF) 301233237Sjkim { 302233237Sjkim /* Need a copy of the input line for strok() */ 303233237Sjkim 304233237Sjkim strcpy (Gbl_MainTokenBuffer, Gbl_CurrentLineBuffer); 305233237Sjkim Token = PrGetNextToken (Gbl_MainTokenBuffer, PR_TOKEN_SEPARATORS, &Next); 306233237Sjkim OffsetAdjust = 0; 307233237Sjkim 308233237Sjkim /* All preprocessor directives must begin with '#' */ 309233237Sjkim 310233237Sjkim if (Token && (*Token == '#')) 311233237Sjkim { 312233237Sjkim if (strlen (Token) == 1) 313233237Sjkim { 314233237Sjkim Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, &Next); 315233237Sjkim } 316233237Sjkim else 317233237Sjkim { 318233237Sjkim Token++; /* Skip leading # */ 319233237Sjkim } 320233237Sjkim 321233237Sjkim /* Execute the directive, do not write line to output file */ 322233237Sjkim 323233237Sjkim PrDoDirective (Token, &Next, &IgnoringThisCodeBlock); 324233237Sjkim continue; 325233237Sjkim } 326233237Sjkim 327233237Sjkim /* 328233237Sjkim * If we are currently within the part of an IF/ELSE block that is 329233237Sjkim * FALSE, ignore the line and do not write it to the output file. 330233237Sjkim * This continues until an #else or #endif is encountered. 331233237Sjkim */ 332233237Sjkim if (IgnoringThisCodeBlock == TRUE) 333233237Sjkim { 334233237Sjkim continue; 335233237Sjkim } 336233237Sjkim 337233237Sjkim /* Match and replace all #defined names within this source line */ 338233237Sjkim 339233237Sjkim while (Token) 340233237Sjkim { 341233237Sjkim DefineInfo = PrMatchDefine (Token); 342233237Sjkim if (DefineInfo) 343233237Sjkim { 344233237Sjkim if (DefineInfo->Body) 345233237Sjkim { 346233237Sjkim /* This is a macro */ 347233237Sjkim 348233237Sjkim DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID 349233237Sjkim "Matched Macro: %s->%s\n", 350233237Sjkim Gbl_CurrentLineNumber, DefineInfo->Identifier, 351233237Sjkim DefineInfo->Replacement); 352233237Sjkim 353233237Sjkim PrDoMacroInvocation (Gbl_MainTokenBuffer, Token, 354233237Sjkim DefineInfo, &Next); 355233237Sjkim } 356233237Sjkim else 357233237Sjkim { 358233237Sjkim ReplaceString = DefineInfo->Replacement; 359233237Sjkim 360233237Sjkim /* Replace the name in the original line buffer */ 361233237Sjkim 362233237Sjkim TokenOffset = Token - Gbl_MainTokenBuffer + OffsetAdjust; 363233237Sjkim PrReplaceData ( 364233237Sjkim &Gbl_CurrentLineBuffer[TokenOffset], strlen (Token), 365233237Sjkim ReplaceString, strlen (ReplaceString)); 366233237Sjkim 367233237Sjkim /* Adjust for length difference between old and new name length */ 368233237Sjkim 369233237Sjkim OffsetAdjust += strlen (ReplaceString) - strlen (Token); 370233237Sjkim 371233237Sjkim DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID 372233237Sjkim "Matched #define: %s->%s\n", 373233237Sjkim Gbl_CurrentLineNumber, Token, 374233237Sjkim *ReplaceString ? ReplaceString : "(NULL STRING)"); 375233237Sjkim } 376233237Sjkim } 377233237Sjkim 378233237Sjkim Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, &Next); 379233237Sjkim } 380233237Sjkim 381233237Sjkim#if 0 382233237Sjkim/* Line prefix */ 383233237Sjkim FlPrintFile (ASL_FILE_PREPROCESSOR, "/* %14s %.5u i:%.5u */ ", 384233237Sjkim Gbl_Files[ASL_FILE_INPUT].Filename, 385233237Sjkim Gbl_CurrentLineNumber, Gbl_PreprocessorLineNumber); 386233237Sjkim#endif 387233237Sjkim 388234623Sjkim /* 389234623Sjkim * Emit a #line directive if necessary, to keep the line numbers in 390234623Sjkim * the (.i) file synchronized with the original source code file, so 391234623Sjkim * that the correct line number appears in any error messages 392234623Sjkim * generated by the actual compiler. 393234623Sjkim */ 394234623Sjkim if (Gbl_CurrentLineNumber > (Gbl_PreviousLineNumber + 1)) 395234623Sjkim { 396234623Sjkim FlPrintFile (ASL_FILE_PREPROCESSOR, "#line %u\n", 397234623Sjkim Gbl_CurrentLineNumber); 398234623Sjkim } 399234623Sjkim 400234623Sjkim Gbl_PreviousLineNumber = Gbl_CurrentLineNumber; 401234623Sjkim Gbl_PreprocessorLineNumber++; 402234623Sjkim 403234623Sjkim /* 404234623Sjkim * Now we can write the possibly modified source line to the 405234623Sjkim * preprocessor (.i) file 406234623Sjkim */ 407233237Sjkim FlWriteFile (ASL_FILE_PREPROCESSOR, Gbl_CurrentLineBuffer, 408233237Sjkim strlen (Gbl_CurrentLineBuffer)); 409233237Sjkim } 410233237Sjkim} 411233237Sjkim 412233237Sjkim 413233237Sjkim/******************************************************************************* 414233237Sjkim * 415233237Sjkim * FUNCTION: PrDoDirective 416233237Sjkim * 417233237Sjkim * PARAMETERS: Directive - Pointer to directive name token 418233237Sjkim * Next - "Next" buffer from GetNextToken 419233237Sjkim * IgnoringThisCodeBlock - Where the "ignore code" flag is 420233237Sjkim * returned. 421233237Sjkim * 422233237Sjkim * RETURN: IgnoringThisCodeBlock: Set to TRUE if we are skipping the FALSE 423233237Sjkim * part of an #if or #else block. Set to FALSE when the 424233237Sjkim * corresponding #else or #endif is encountered. 425233237Sjkim * 426233237Sjkim * DESCRIPTION: Main processing for all preprocessor directives 427233237Sjkim * 428233237Sjkim ******************************************************************************/ 429233237Sjkim 430233237Sjkimstatic void 431233237SjkimPrDoDirective ( 432233237Sjkim char *DirectiveToken, 433233237Sjkim char **Next, 434233237Sjkim BOOLEAN *IgnoringThisCodeBlock) 435233237Sjkim{ 436233237Sjkim char *Token = Gbl_MainTokenBuffer; 437233237Sjkim char *Token2; 438233237Sjkim char *End; 439233237Sjkim UINT64 Value; 440233237Sjkim ACPI_SIZE TokenOffset; 441233237Sjkim int Directive; 442233237Sjkim ACPI_STATUS Status; 443233237Sjkim 444233237Sjkim 445233237Sjkim if (!DirectiveToken) 446233237Sjkim { 447233237Sjkim goto SyntaxError; 448233237Sjkim } 449233237Sjkim 450233237Sjkim Directive = PrMatchDirective (DirectiveToken); 451233237Sjkim if (Directive == ASL_DIRECTIVE_NOT_FOUND) 452233237Sjkim { 453233237Sjkim PrError (ASL_ERROR, ASL_MSG_UNKNOWN_DIRECTIVE, 454233237Sjkim THIS_TOKEN_OFFSET (DirectiveToken)); 455233237Sjkim 456233237Sjkim DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID 457233237Sjkim "#%s: Unknown directive\n", 458233237Sjkim Gbl_CurrentLineNumber, DirectiveToken); 459233237Sjkim return; 460233237Sjkim } 461233237Sjkim 462233237Sjkim /* TBD: Need a faster way to do this: */ 463233237Sjkim 464233237Sjkim if ((Directive == PR_DIRECTIVE_ELIF) || 465233237Sjkim (Directive == PR_DIRECTIVE_ELSE) || 466233237Sjkim (Directive == PR_DIRECTIVE_ENDIF)) 467233237Sjkim { 468233237Sjkim DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID "Begin #%s\n", 469233237Sjkim Gbl_CurrentLineNumber, Gbl_DirectiveInfo[Directive].Name); 470233237Sjkim } 471233237Sjkim 472233237Sjkim /* 473233237Sjkim * Need to always check for #else, #elif, #endif regardless of 474233237Sjkim * whether we are ignoring the current code block, since these 475233237Sjkim * are conditional code block terminators. 476233237Sjkim */ 477233237Sjkim switch (Directive) 478233237Sjkim { 479233237Sjkim case PR_DIRECTIVE_ELIF: 480250838Sjkim 481233237Sjkim *IgnoringThisCodeBlock = !(*IgnoringThisCodeBlock); 482233237Sjkim if (*IgnoringThisCodeBlock == TRUE) 483233237Sjkim { 484233237Sjkim /* Not executing the ELSE part -- all done here */ 485233237Sjkim return; 486233237Sjkim } 487233237Sjkim 488233237Sjkim /* Will execute the ELSE..IF part */ 489233237Sjkim 490233237Sjkim DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID 491233237Sjkim "#elif - Executing else block\n", 492233237Sjkim Gbl_CurrentLineNumber); 493233237Sjkim Directive = PR_DIRECTIVE_IF; 494233237Sjkim break; 495233237Sjkim 496233237Sjkim case PR_DIRECTIVE_ELSE: 497250838Sjkim 498233237Sjkim *IgnoringThisCodeBlock = !(*IgnoringThisCodeBlock); 499233237Sjkim return; 500233237Sjkim 501233237Sjkim case PR_DIRECTIVE_ENDIF: 502250838Sjkim 503233237Sjkim *IgnoringThisCodeBlock = FALSE; 504233237Sjkim Gbl_IfDepth--; 505233237Sjkim if (Gbl_IfDepth < 0) 506233237Sjkim { 507233237Sjkim PrError (ASL_ERROR, ASL_MSG_ENDIF_MISMATCH, 508233237Sjkim THIS_TOKEN_OFFSET (DirectiveToken)); 509233237Sjkim Gbl_IfDepth = 0; 510233237Sjkim } 511233237Sjkim return; 512233237Sjkim 513233237Sjkim default: 514250838Sjkim 515233237Sjkim break; 516233237Sjkim } 517233237Sjkim 518233237Sjkim /* 519233237Sjkim * At this point, if we are ignoring the current code block, 520233237Sjkim * do not process any more directives (i.e., ignore them also.) 521233237Sjkim */ 522233237Sjkim if (*IgnoringThisCodeBlock == TRUE) 523233237Sjkim { 524233237Sjkim return; 525233237Sjkim } 526233237Sjkim 527233237Sjkim DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID "Begin #%s\n", 528233237Sjkim Gbl_CurrentLineNumber, Gbl_DirectiveInfo[Directive].Name); 529233237Sjkim 530233237Sjkim /* Most directives have at least one argument */ 531233237Sjkim 532233237Sjkim if (Gbl_DirectiveInfo[Directive].ArgCount == 1) 533233237Sjkim { 534233237Sjkim Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next); 535233237Sjkim if (!Token) 536233237Sjkim { 537233237Sjkim goto SyntaxError; 538233237Sjkim } 539233237Sjkim } 540233237Sjkim 541233237Sjkim switch (Directive) 542233237Sjkim { 543233237Sjkim case PR_DIRECTIVE_DEFINE: 544233237Sjkim /* 545233237Sjkim * By definition, if first char after the name is a paren, 546233237Sjkim * this is a function macro. 547233237Sjkim */ 548233237Sjkim TokenOffset = Token - Gbl_MainTokenBuffer + strlen (Token); 549233237Sjkim if (*(&Gbl_CurrentLineBuffer[TokenOffset]) == '(') 550233237Sjkim { 551233237Sjkim#ifndef MACROS_SUPPORTED 552234623Sjkim AcpiOsPrintf ("%s ERROR - line %u: #define macros are not supported yet\n", 553234623Sjkim Gbl_CurrentLineBuffer, Gbl_CurrentLineNumber); 554234623Sjkim exit(1); 555233237Sjkim#else 556233237Sjkim PrAddMacro (Token, Next); 557233237Sjkim#endif 558233237Sjkim } 559233237Sjkim else 560233237Sjkim { 561233237Sjkim /* Use the remainder of the line for the #define */ 562233237Sjkim 563233237Sjkim Token2 = *Next; 564233237Sjkim if (Token2) 565233237Sjkim { 566233237Sjkim while ((*Token2 == ' ') || (*Token2 == '\t')) 567233237Sjkim { 568233237Sjkim Token2++; 569233237Sjkim } 570233237Sjkim End = Token2; 571233237Sjkim while (*End != '\n') 572233237Sjkim { 573233237Sjkim End++; 574233237Sjkim } 575233237Sjkim *End = 0; 576233237Sjkim } 577233237Sjkim else 578233237Sjkim { 579233237Sjkim Token2 = ""; 580233237Sjkim } 581233237Sjkim#if 0 582233237Sjkim Token2 = PrGetNextToken (NULL, "\n", /*PR_TOKEN_SEPARATORS,*/ Next); 583233237Sjkim if (!Token2) 584233237Sjkim { 585233237Sjkim Token2 = ""; 586233237Sjkim } 587233237Sjkim#endif 588233237Sjkim DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID 589233237Sjkim "New #define: %s->%s\n", 590233237Sjkim Gbl_CurrentLineNumber, Token, Token2); 591233237Sjkim 592233237Sjkim PrAddDefine (Token, Token2, FALSE); 593233237Sjkim } 594233237Sjkim break; 595233237Sjkim 596233237Sjkim case PR_DIRECTIVE_ERROR: 597250838Sjkim 598233237Sjkim /* TBD compiler should abort */ 599233237Sjkim /* Note: No macro expansion */ 600233237Sjkim 601233237Sjkim PrError (ASL_ERROR, ASL_MSG_ERROR_DIRECTIVE, 602233237Sjkim THIS_TOKEN_OFFSET (Token)); 603233237Sjkim break; 604233237Sjkim 605233237Sjkim case PR_DIRECTIVE_IF: 606250838Sjkim 607233237Sjkim TokenOffset = Token - Gbl_MainTokenBuffer; 608233237Sjkim 609233237Sjkim /* Need to expand #define macros in the expression string first */ 610233237Sjkim 611233237Sjkim Status = PrResolveIntegerExpression ( 612233237Sjkim &Gbl_CurrentLineBuffer[TokenOffset-1], &Value); 613233237Sjkim if (ACPI_FAILURE (Status)) 614233237Sjkim { 615233237Sjkim return; 616233237Sjkim } 617233237Sjkim 618233237Sjkim if (!Value) 619233237Sjkim { 620233237Sjkim *IgnoringThisCodeBlock = TRUE; 621233237Sjkim } 622233237Sjkim 623233237Sjkim DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID 624233237Sjkim "Resolved #if: %8.8X%8.8X %s\n", 625233237Sjkim Gbl_CurrentLineNumber, ACPI_FORMAT_UINT64 (Value), 626233237Sjkim *IgnoringThisCodeBlock ? "<Skipping Block>" : "<Executing Block>"); 627233237Sjkim 628233237Sjkim Gbl_IfDepth++; 629233237Sjkim break; 630233237Sjkim 631233237Sjkim case PR_DIRECTIVE_IFDEF: 632250838Sjkim 633233237Sjkim if (!PrMatchDefine (Token)) 634233237Sjkim { 635233237Sjkim *IgnoringThisCodeBlock = TRUE; 636233237Sjkim } 637233237Sjkim 638233237Sjkim Gbl_IfDepth++; 639233237Sjkim DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID 640233237Sjkim "Start #ifdef %s\n", Gbl_CurrentLineNumber, 641233237Sjkim *IgnoringThisCodeBlock ? "<Skipping Block>" : "<Executing Block>"); 642233237Sjkim break; 643233237Sjkim 644233237Sjkim case PR_DIRECTIVE_IFNDEF: 645250838Sjkim 646233237Sjkim if (PrMatchDefine (Token)) 647233237Sjkim { 648233237Sjkim *IgnoringThisCodeBlock = TRUE; 649233237Sjkim } 650233237Sjkim 651233237Sjkim Gbl_IfDepth++; 652233237Sjkim DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID 653233237Sjkim "Start #ifndef %2.2X\n", Gbl_CurrentLineNumber, 654233237Sjkim *IgnoringThisCodeBlock, Gbl_CurrentLineNumber); 655233237Sjkim break; 656233237Sjkim 657233237Sjkim case PR_DIRECTIVE_INCLUDE: 658250838Sjkim 659233237Sjkim Token = PrGetNextToken (NULL, " \"<>", Next); 660233237Sjkim if (!Token) 661233237Sjkim { 662233237Sjkim goto SyntaxError; 663233237Sjkim } 664233237Sjkim 665233237Sjkim DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID 666235945Sjkim "Start #include file \"%s\"\n", Gbl_CurrentLineNumber, 667233237Sjkim Token, Gbl_CurrentLineNumber); 668233237Sjkim 669233237Sjkim PrOpenIncludeFile (Token); 670233237Sjkim break; 671233237Sjkim 672234623Sjkim case PR_DIRECTIVE_LINE: 673250838Sjkim 674234623Sjkim TokenOffset = Token - Gbl_MainTokenBuffer; 675234623Sjkim 676234623Sjkim Status = PrResolveIntegerExpression ( 677234623Sjkim &Gbl_CurrentLineBuffer[TokenOffset-1], &Value); 678234623Sjkim if (ACPI_FAILURE (Status)) 679234623Sjkim { 680234623Sjkim return; 681234623Sjkim } 682234623Sjkim 683234623Sjkim DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID 684234623Sjkim "User #line invocation %s\n", Gbl_CurrentLineNumber, 685234623Sjkim Token); 686234623Sjkim 687234623Sjkim /* Update local line numbers */ 688234623Sjkim 689234623Sjkim Gbl_CurrentLineNumber = (UINT32) Value; 690234623Sjkim Gbl_PreviousLineNumber = 0; 691234623Sjkim 692234623Sjkim /* Emit #line into the preprocessor file */ 693234623Sjkim 694234623Sjkim FlPrintFile (ASL_FILE_PREPROCESSOR, "#line %u \"%s\"\n", 695234623Sjkim Gbl_CurrentLineNumber, Gbl_Files[ASL_FILE_INPUT].Filename); 696234623Sjkim break; 697234623Sjkim 698233237Sjkim case PR_DIRECTIVE_PRAGMA: 699233237Sjkim 700250838Sjkim if (!strcmp (Token, "disable")) 701233237Sjkim { 702250838Sjkim Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next); 703250838Sjkim if (!Token) 704250838Sjkim { 705250838Sjkim goto SyntaxError; 706250838Sjkim } 707250838Sjkim 708250838Sjkim TokenOffset = Token - Gbl_MainTokenBuffer; 709250838Sjkim AslDisableException (&Gbl_CurrentLineBuffer[TokenOffset]); 710250838Sjkim } 711250838Sjkim else if (!strcmp (Token, "message")) 712250838Sjkim { 713250838Sjkim Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next); 714250838Sjkim if (!Token) 715250838Sjkim { 716250838Sjkim goto SyntaxError; 717250838Sjkim } 718250838Sjkim 719250838Sjkim TokenOffset = Token - Gbl_MainTokenBuffer; 720250838Sjkim AcpiOsPrintf ("%s\n", &Gbl_CurrentLineBuffer[TokenOffset]); 721250838Sjkim } 722250838Sjkim else 723250838Sjkim { 724233237Sjkim PrError (ASL_ERROR, ASL_MSG_UNKNOWN_PRAGMA, 725233237Sjkim THIS_TOKEN_OFFSET (Token)); 726233237Sjkim return; 727233237Sjkim } 728233237Sjkim 729233237Sjkim break; 730233237Sjkim 731233237Sjkim case PR_DIRECTIVE_UNDEF: 732250838Sjkim 733233237Sjkim DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID 734233237Sjkim "#undef: %s\n", Gbl_CurrentLineNumber, Token); 735233237Sjkim 736233237Sjkim PrRemoveDefine (Token); 737233237Sjkim break; 738233237Sjkim 739233237Sjkim case PR_DIRECTIVE_WARNING: 740250838Sjkim 741233237Sjkim PrError (ASL_WARNING, ASL_MSG_ERROR_DIRECTIVE, 742233237Sjkim THIS_TOKEN_OFFSET (Token)); 743233237Sjkim break; 744233237Sjkim 745233237Sjkim default: 746250838Sjkim 747233237Sjkim /* Should never get here */ 748233237Sjkim DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID 749233237Sjkim "Unrecognized directive: %u\n", 750233237Sjkim Gbl_CurrentLineNumber, Directive); 751233237Sjkim break; 752233237Sjkim } 753233237Sjkim 754233237Sjkim return; 755233237Sjkim 756233237Sjkim 757233237SjkimSyntaxError: 758233237Sjkim 759233237Sjkim PrError (ASL_ERROR, ASL_MSG_DIRECTIVE_SYNTAX, 760233237Sjkim THIS_TOKEN_OFFSET (DirectiveToken)); 761233237Sjkim return; 762233237Sjkim} 763233237Sjkim 764233237Sjkim 765233237Sjkim/******************************************************************************* 766233237Sjkim * 767233237Sjkim * FUNCTION: PrMatchDirective 768233237Sjkim * 769233237Sjkim * PARAMETERS: Directive - Pointer to directive name token 770233237Sjkim * 771233237Sjkim * RETURN: Index into command array, -1 if not found 772233237Sjkim * 773233237Sjkim * DESCRIPTION: Lookup the incoming directive in the known directives table. 774233237Sjkim * 775233237Sjkim ******************************************************************************/ 776233237Sjkim 777233237Sjkimstatic int 778233237SjkimPrMatchDirective ( 779233237Sjkim char *Directive) 780233237Sjkim{ 781233237Sjkim int i; 782233237Sjkim 783233237Sjkim 784233237Sjkim if (!Directive || Directive[0] == 0) 785233237Sjkim { 786233237Sjkim return (ASL_DIRECTIVE_NOT_FOUND); 787233237Sjkim } 788233237Sjkim 789233237Sjkim for (i = 0; Gbl_DirectiveInfo[i].Name; i++) 790233237Sjkim { 791233237Sjkim if (!strcmp (Gbl_DirectiveInfo[i].Name, Directive)) 792233237Sjkim { 793233237Sjkim return (i); 794233237Sjkim } 795233237Sjkim } 796233237Sjkim 797233237Sjkim return (ASL_DIRECTIVE_NOT_FOUND); /* Command not recognized */ 798233237Sjkim} 799