prscan.c revision 233250
1233237Sjkim/****************************************************************************** 2233237Sjkim * 3233237Sjkim * Module Name: prscan - Preprocessor start-up and file scan module 4233237Sjkim * 5233237Sjkim *****************************************************************************/ 6233237Sjkim 7233237Sjkim/* 8233237Sjkim * Copyright (C) 2000 - 2012, 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 Gbl_MapBlockHead = UtLocalCalloc (sizeof (PR_LINE_MAPPING)); 166233237Sjkim Gbl_MapBlockHead->Map = UtLocalCalloc (PR_LINES_PER_BLOCK * sizeof (UINT32)); 167233237Sjkim} 168233237Sjkim 169233237Sjkim 170233237Sjkim/******************************************************************************* 171233237Sjkim * 172233237Sjkim * FUNCTION: PrTerminatePreprocessor 173233237Sjkim * 174233237Sjkim * PARAMETERS: None 175233237Sjkim * 176233237Sjkim * RETURN: None 177233237Sjkim * 178233237Sjkim * DESCRIPTION: Termination of the preprocessor. Delete lists. Keep any 179233237Sjkim * defines that were specified on the command line, in order to 180233237Sjkim * support multiple compiles with a single compiler invocation. 181233237Sjkim * 182233237Sjkim ******************************************************************************/ 183233237Sjkim 184233237Sjkimvoid 185233237SjkimPrTerminatePreprocessor ( 186233237Sjkim void) 187233237Sjkim{ 188233237Sjkim PR_DEFINE_INFO *DefineInfo; 189233237Sjkim PR_LINE_MAPPING *MapInfo; 190233237Sjkim 191233237Sjkim 192233237Sjkim /* 193233237Sjkim * The persistent defines (created on the command line) are always at the 194233237Sjkim * end of the list. We save them. 195233237Sjkim */ 196233237Sjkim while ((Gbl_DefineList) && (!Gbl_DefineList->Persist)) 197233237Sjkim { 198233237Sjkim DefineInfo = Gbl_DefineList; 199233237Sjkim Gbl_DefineList = DefineInfo->Next; 200233237Sjkim 201233237Sjkim ACPI_FREE (DefineInfo->Replacement); 202233237Sjkim ACPI_FREE (DefineInfo->Identifier); 203233237Sjkim ACPI_FREE (DefineInfo); 204233237Sjkim } 205233237Sjkim 206233237Sjkim /* Clear the line number mappings */ 207233237Sjkim 208233237Sjkim while (Gbl_MapBlockHead) 209233237Sjkim { 210233237Sjkim MapInfo = Gbl_MapBlockHead; 211233237Sjkim Gbl_MapBlockHead = MapInfo->Next; 212233237Sjkim 213233237Sjkim ACPI_FREE (MapInfo->Map); 214233237Sjkim ACPI_FREE (MapInfo); 215233237Sjkim } 216233237Sjkim} 217233237Sjkim 218233237Sjkim 219233237Sjkim/******************************************************************************* 220233237Sjkim * 221233237Sjkim * FUNCTION: PrDoPreprocess 222233237Sjkim * 223233237Sjkim * PARAMETERS: None 224233237Sjkim * 225233237Sjkim * RETURN: Error Status. TRUE if error, FALSE if OK. 226233237Sjkim * 227233237Sjkim * DESCRIPTION: Main entry point for the iASL Preprocessor. Input file must 228233237Sjkim * be already open. Handles multiple input files via the 229233237Sjkim * #include directive. 230233237Sjkim * 231233237Sjkim ******************************************************************************/ 232233237Sjkim 233233237SjkimBOOLEAN 234233237SjkimPrDoPreprocess ( 235233237Sjkim void) 236233237Sjkim{ 237233237Sjkim BOOLEAN MoreInputFiles; 238233237Sjkim 239233237Sjkim 240233237Sjkim DbgPrint (ASL_DEBUG_OUTPUT, "Starting preprocessing phase\n\n"); 241233237Sjkim 242233237Sjkim 243233237Sjkim FlSeekFile (ASL_FILE_INPUT, 0); 244233237Sjkim PrDumpPredefinedNames (); 245233237Sjkim 246233237Sjkim /* Main preprocessor loop, handles include files */ 247233237Sjkim 248233237Sjkim do 249233237Sjkim { 250233237Sjkim PrPreprocessInputFile (); 251233237Sjkim MoreInputFiles = PrPopInputFileStack (); 252233237Sjkim 253233237Sjkim } while (MoreInputFiles); 254233237Sjkim 255233237Sjkim 256233237Sjkim /* 257233237Sjkim * TBD: is this necessary? (Do we abort on any preprocessing errors?) 258233237Sjkim */ 259233237Sjkim if (Gbl_PreprocessorError) 260233237Sjkim { 261233237Sjkim /* TBD: can't use source_output file for preprocessor error reporting */ 262233237Sjkim 263233237Sjkim Gbl_Files[ASL_FILE_SOURCE_OUTPUT].Handle = NULL; 264233237Sjkim PrTerminatePreprocessor (); 265233237Sjkim return (TRUE); 266233237Sjkim } 267233237Sjkim 268233237Sjkim /* Point compiler input to the new preprocessor file (.i) */ 269233237Sjkim 270233237Sjkim FlCloseFile (ASL_FILE_INPUT); 271233237Sjkim Gbl_Files[ASL_FILE_INPUT].Handle = Gbl_Files[ASL_FILE_PREPROCESSOR].Handle; 272233237Sjkim AslCompilerin = Gbl_Files[ASL_FILE_INPUT].Handle; 273233237Sjkim 274233237Sjkim /* Reset globals to allow compiler to run */ 275233237Sjkim 276233237Sjkim FlSeekFile (ASL_FILE_INPUT, 0); 277233237Sjkim Gbl_CurrentLineNumber = 1; 278233237Sjkim 279233237Sjkim DbgPrint (ASL_DEBUG_OUTPUT, "Preprocessing phase complete \n\n"); 280233237Sjkim return (FALSE); 281233237Sjkim} 282233237Sjkim 283233237Sjkim 284233237Sjkim/******************************************************************************* 285233237Sjkim * 286233237Sjkim * FUNCTION: PrPreprocessInputFile 287233237Sjkim * 288233237Sjkim * PARAMETERS: None 289233237Sjkim * 290233237Sjkim * RETURN: None 291233237Sjkim * 292233237Sjkim * DESCRIPTION: Preprocess one entire file, line-by-line. 293233237Sjkim * 294233237Sjkim * Input: Raw user ASL from ASL_FILE_INPUT 295233237Sjkim * Output: Preprocessed file written to ASL_FILE_PREPROCESSOR 296233237Sjkim * 297233237Sjkim ******************************************************************************/ 298233237Sjkim 299233237Sjkimstatic void 300233237SjkimPrPreprocessInputFile ( 301233237Sjkim void) 302233237Sjkim{ 303233237Sjkim UINT32 Offset; 304233237Sjkim char *Token; 305233237Sjkim char *ReplaceString; 306233237Sjkim PR_DEFINE_INFO *DefineInfo; 307233237Sjkim ACPI_SIZE TokenOffset; 308233237Sjkim BOOLEAN IgnoringThisCodeBlock = FALSE; 309233237Sjkim char *Next; 310233237Sjkim int OffsetAdjust; 311233237Sjkim 312233237Sjkim 313233237Sjkim /* Scan line-by-line. Comments and blank lines are skipped by this function */ 314233237Sjkim 315233237Sjkim while ((Offset = DtGetNextLine (Gbl_Files[ASL_FILE_INPUT].Handle)) != ASL_EOF) 316233237Sjkim { 317233237Sjkim /* Need a copy of the input line for strok() */ 318233237Sjkim 319233237Sjkim strcpy (Gbl_MainTokenBuffer, Gbl_CurrentLineBuffer); 320233237Sjkim Token = PrGetNextToken (Gbl_MainTokenBuffer, PR_TOKEN_SEPARATORS, &Next); 321233237Sjkim OffsetAdjust = 0; 322233237Sjkim 323233237Sjkim /* All preprocessor directives must begin with '#' */ 324233237Sjkim 325233237Sjkim if (Token && (*Token == '#')) 326233237Sjkim { 327233237Sjkim if (strlen (Token) == 1) 328233237Sjkim { 329233237Sjkim Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, &Next); 330233237Sjkim } 331233237Sjkim else 332233237Sjkim { 333233237Sjkim Token++; /* Skip leading # */ 334233237Sjkim } 335233237Sjkim 336233237Sjkim /* Execute the directive, do not write line to output file */ 337233237Sjkim 338233237Sjkim PrDoDirective (Token, &Next, &IgnoringThisCodeBlock); 339233237Sjkim continue; 340233237Sjkim } 341233237Sjkim 342233237Sjkim /* 343233237Sjkim * If we are currently within the part of an IF/ELSE block that is 344233237Sjkim * FALSE, ignore the line and do not write it to the output file. 345233237Sjkim * This continues until an #else or #endif is encountered. 346233237Sjkim */ 347233237Sjkim if (IgnoringThisCodeBlock == TRUE) 348233237Sjkim { 349233237Sjkim continue; 350233237Sjkim } 351233237Sjkim 352233237Sjkim /* Match and replace all #defined names within this source line */ 353233237Sjkim 354233237Sjkim while (Token) 355233237Sjkim { 356233237Sjkim DefineInfo = PrMatchDefine (Token); 357233237Sjkim if (DefineInfo) 358233237Sjkim { 359233237Sjkim if (DefineInfo->Body) 360233237Sjkim { 361233237Sjkim /* This is a macro */ 362233237Sjkim 363233237Sjkim DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID 364233237Sjkim "Matched Macro: %s->%s\n", 365233237Sjkim Gbl_CurrentLineNumber, DefineInfo->Identifier, 366233237Sjkim DefineInfo->Replacement); 367233237Sjkim 368233237Sjkim PrDoMacroInvocation (Gbl_MainTokenBuffer, Token, 369233237Sjkim DefineInfo, &Next); 370233237Sjkim } 371233237Sjkim else 372233237Sjkim { 373233237Sjkim ReplaceString = DefineInfo->Replacement; 374233237Sjkim 375233237Sjkim /* Replace the name in the original line buffer */ 376233237Sjkim 377233237Sjkim TokenOffset = Token - Gbl_MainTokenBuffer + OffsetAdjust; 378233237Sjkim PrReplaceData ( 379233237Sjkim &Gbl_CurrentLineBuffer[TokenOffset], strlen (Token), 380233237Sjkim ReplaceString, strlen (ReplaceString)); 381233237Sjkim 382233237Sjkim /* Adjust for length difference between old and new name length */ 383233237Sjkim 384233237Sjkim OffsetAdjust += strlen (ReplaceString) - strlen (Token); 385233237Sjkim 386233237Sjkim DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID 387233237Sjkim "Matched #define: %s->%s\n", 388233237Sjkim Gbl_CurrentLineNumber, Token, 389233237Sjkim *ReplaceString ? ReplaceString : "(NULL STRING)"); 390233237Sjkim } 391233237Sjkim } 392233237Sjkim 393233237Sjkim Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, &Next); 394233237Sjkim } 395233237Sjkim 396233237Sjkim /* Write the possibly modified line to the .i file*/ 397233237Sjkim 398233237Sjkim#if 0 399233237Sjkim/* Line prefix */ 400233237Sjkim FlPrintFile (ASL_FILE_PREPROCESSOR, "/* %14s %.5u i:%.5u */ ", 401233237Sjkim Gbl_Files[ASL_FILE_INPUT].Filename, 402233237Sjkim Gbl_CurrentLineNumber, Gbl_PreprocessorLineNumber); 403233237Sjkim#endif 404233237Sjkim 405233237Sjkim FlWriteFile (ASL_FILE_PREPROCESSOR, Gbl_CurrentLineBuffer, 406233237Sjkim strlen (Gbl_CurrentLineBuffer)); 407233237Sjkim 408233237Sjkim PrSetLineNumber (Gbl_CurrentLineNumber, Gbl_PreprocessorLineNumber); 409233237Sjkim Gbl_PreprocessorLineNumber++; 410233237Sjkim } 411233237Sjkim} 412233237Sjkim 413233237Sjkim 414233237Sjkim/******************************************************************************* 415233237Sjkim * 416233237Sjkim * FUNCTION: PrDoDirective 417233237Sjkim * 418233237Sjkim * PARAMETERS: Directive - Pointer to directive name token 419233237Sjkim * Next - "Next" buffer from GetNextToken 420233237Sjkim * IgnoringThisCodeBlock - Where the "ignore code" flag is 421233237Sjkim * returned. 422233237Sjkim * 423233237Sjkim * RETURN: IgnoringThisCodeBlock: Set to TRUE if we are skipping the FALSE 424233237Sjkim * part of an #if or #else block. Set to FALSE when the 425233237Sjkim * corresponding #else or #endif is encountered. 426233237Sjkim * 427233237Sjkim * DESCRIPTION: Main processing for all preprocessor directives 428233237Sjkim * 429233237Sjkim ******************************************************************************/ 430233237Sjkim 431233237Sjkimstatic void 432233237SjkimPrDoDirective ( 433233237Sjkim char *DirectiveToken, 434233237Sjkim char **Next, 435233237Sjkim BOOLEAN *IgnoringThisCodeBlock) 436233237Sjkim{ 437233237Sjkim char *Token = Gbl_MainTokenBuffer; 438233237Sjkim char *Token2; 439233237Sjkim char *End; 440233237Sjkim UINT64 Value; 441233237Sjkim ACPI_SIZE TokenOffset; 442233237Sjkim int Directive; 443233237Sjkim ACPI_STATUS Status; 444233237Sjkim 445233237Sjkim 446233237Sjkim if (!DirectiveToken) 447233237Sjkim { 448233237Sjkim goto SyntaxError; 449233237Sjkim } 450233237Sjkim 451233237Sjkim Directive = PrMatchDirective (DirectiveToken); 452233237Sjkim if (Directive == ASL_DIRECTIVE_NOT_FOUND) 453233237Sjkim { 454233237Sjkim PrError (ASL_ERROR, ASL_MSG_UNKNOWN_DIRECTIVE, 455233237Sjkim THIS_TOKEN_OFFSET (DirectiveToken)); 456233237Sjkim 457233237Sjkim DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID 458233237Sjkim "#%s: Unknown directive\n", 459233237Sjkim Gbl_CurrentLineNumber, DirectiveToken); 460233237Sjkim return; 461233237Sjkim } 462233237Sjkim 463233237Sjkim /* TBD: Need a faster way to do this: */ 464233237Sjkim 465233237Sjkim if ((Directive == PR_DIRECTIVE_ELIF) || 466233237Sjkim (Directive == PR_DIRECTIVE_ELSE) || 467233237Sjkim (Directive == PR_DIRECTIVE_ENDIF)) 468233237Sjkim { 469233237Sjkim DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID "Begin #%s\n", 470233237Sjkim Gbl_CurrentLineNumber, Gbl_DirectiveInfo[Directive].Name); 471233237Sjkim } 472233237Sjkim 473233237Sjkim /* 474233237Sjkim * Need to always check for #else, #elif, #endif regardless of 475233237Sjkim * whether we are ignoring the current code block, since these 476233237Sjkim * are conditional code block terminators. 477233237Sjkim */ 478233237Sjkim switch (Directive) 479233237Sjkim { 480233237Sjkim case PR_DIRECTIVE_ELIF: 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: 497233237Sjkim *IgnoringThisCodeBlock = !(*IgnoringThisCodeBlock); 498233237Sjkim return; 499233237Sjkim 500233237Sjkim case PR_DIRECTIVE_ENDIF: 501233237Sjkim *IgnoringThisCodeBlock = FALSE; 502233237Sjkim Gbl_IfDepth--; 503233237Sjkim if (Gbl_IfDepth < 0) 504233237Sjkim { 505233237Sjkim PrError (ASL_ERROR, ASL_MSG_ENDIF_MISMATCH, 506233237Sjkim THIS_TOKEN_OFFSET (DirectiveToken)); 507233237Sjkim Gbl_IfDepth = 0; 508233237Sjkim } 509233237Sjkim return; 510233237Sjkim 511233237Sjkim default: 512233237Sjkim break; 513233237Sjkim } 514233237Sjkim 515233237Sjkim /* 516233237Sjkim * At this point, if we are ignoring the current code block, 517233237Sjkim * do not process any more directives (i.e., ignore them also.) 518233237Sjkim */ 519233237Sjkim if (*IgnoringThisCodeBlock == TRUE) 520233237Sjkim { 521233237Sjkim return; 522233237Sjkim } 523233237Sjkim 524233237Sjkim DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID "Begin #%s\n", 525233237Sjkim Gbl_CurrentLineNumber, Gbl_DirectiveInfo[Directive].Name); 526233237Sjkim 527233237Sjkim /* Most directives have at least one argument */ 528233237Sjkim 529233237Sjkim if (Gbl_DirectiveInfo[Directive].ArgCount == 1) 530233237Sjkim { 531233237Sjkim Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next); 532233237Sjkim if (!Token) 533233237Sjkim { 534233237Sjkim goto SyntaxError; 535233237Sjkim } 536233237Sjkim } 537233237Sjkim 538233237Sjkim switch (Directive) 539233237Sjkim { 540233237Sjkim case PR_DIRECTIVE_DEFINE: 541233237Sjkim /* 542233237Sjkim * By definition, if first char after the name is a paren, 543233237Sjkim * this is a function macro. 544233237Sjkim */ 545233237Sjkim TokenOffset = Token - Gbl_MainTokenBuffer + strlen (Token); 546233237Sjkim if (*(&Gbl_CurrentLineBuffer[TokenOffset]) == '(') 547233237Sjkim { 548233237Sjkim#ifndef MACROS_SUPPORTED 549233237Sjkim AcpiOsPrintf ("#define macros not supported\n"); 550233237Sjkim goto SyntaxError; 551233237Sjkim#else 552233237Sjkim PrAddMacro (Token, Next); 553233237Sjkim#endif 554233237Sjkim } 555233237Sjkim else 556233237Sjkim { 557233237Sjkim /* Use the remainder of the line for the #define */ 558233237Sjkim 559233237Sjkim Token2 = *Next; 560233237Sjkim if (Token2) 561233237Sjkim { 562233237Sjkim while ((*Token2 == ' ') || (*Token2 == '\t')) 563233237Sjkim { 564233237Sjkim Token2++; 565233237Sjkim } 566233237Sjkim End = Token2; 567233237Sjkim while (*End != '\n') 568233237Sjkim { 569233237Sjkim End++; 570233237Sjkim } 571233237Sjkim *End = 0; 572233237Sjkim } 573233237Sjkim else 574233237Sjkim { 575233237Sjkim Token2 = ""; 576233237Sjkim } 577233237Sjkim#if 0 578233237Sjkim Token2 = PrGetNextToken (NULL, "\n", /*PR_TOKEN_SEPARATORS,*/ Next); 579233237Sjkim if (!Token2) 580233237Sjkim { 581233237Sjkim Token2 = ""; 582233237Sjkim } 583233237Sjkim#endif 584233237Sjkim DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID 585233237Sjkim "New #define: %s->%s\n", 586233237Sjkim Gbl_CurrentLineNumber, Token, Token2); 587233237Sjkim 588233237Sjkim PrAddDefine (Token, Token2, FALSE); 589233237Sjkim } 590233237Sjkim break; 591233237Sjkim 592233237Sjkim case PR_DIRECTIVE_ERROR: 593233237Sjkim /* TBD compiler should abort */ 594233237Sjkim /* Note: No macro expansion */ 595233237Sjkim 596233237Sjkim PrError (ASL_ERROR, ASL_MSG_ERROR_DIRECTIVE, 597233237Sjkim THIS_TOKEN_OFFSET (Token)); 598233237Sjkim break; 599233237Sjkim 600233237Sjkim case PR_DIRECTIVE_IF: 601233237Sjkim TokenOffset = Token - Gbl_MainTokenBuffer; 602233237Sjkim 603233237Sjkim /* Need to expand #define macros in the expression string first */ 604233237Sjkim 605233237Sjkim Status = PrResolveIntegerExpression ( 606233237Sjkim &Gbl_CurrentLineBuffer[TokenOffset-1], &Value); 607233237Sjkim if (ACPI_FAILURE (Status)) 608233237Sjkim { 609233237Sjkim return; 610233237Sjkim } 611233237Sjkim 612233237Sjkim if (!Value) 613233237Sjkim { 614233237Sjkim *IgnoringThisCodeBlock = TRUE; 615233237Sjkim } 616233237Sjkim 617233237Sjkim DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID 618233237Sjkim "Resolved #if: %8.8X%8.8X %s\n", 619233237Sjkim Gbl_CurrentLineNumber, ACPI_FORMAT_UINT64 (Value), 620233237Sjkim *IgnoringThisCodeBlock ? "<Skipping Block>" : "<Executing Block>"); 621233237Sjkim 622233237Sjkim Gbl_IfDepth++; 623233237Sjkim break; 624233237Sjkim 625233237Sjkim case PR_DIRECTIVE_IFDEF: 626233237Sjkim if (!PrMatchDefine (Token)) 627233237Sjkim { 628233237Sjkim *IgnoringThisCodeBlock = TRUE; 629233237Sjkim } 630233237Sjkim 631233237Sjkim Gbl_IfDepth++; 632233237Sjkim DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID 633233237Sjkim "Start #ifdef %s\n", Gbl_CurrentLineNumber, 634233237Sjkim *IgnoringThisCodeBlock ? "<Skipping Block>" : "<Executing Block>"); 635233237Sjkim break; 636233237Sjkim 637233237Sjkim case PR_DIRECTIVE_IFNDEF: 638233237Sjkim if (PrMatchDefine (Token)) 639233237Sjkim { 640233237Sjkim *IgnoringThisCodeBlock = TRUE; 641233237Sjkim } 642233237Sjkim 643233237Sjkim Gbl_IfDepth++; 644233237Sjkim DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID 645233237Sjkim "Start #ifndef %2.2X\n", Gbl_CurrentLineNumber, 646233237Sjkim *IgnoringThisCodeBlock, Gbl_CurrentLineNumber); 647233237Sjkim break; 648233237Sjkim 649233237Sjkim case PR_DIRECTIVE_INCLUDE: 650233237Sjkim Token = PrGetNextToken (NULL, " \"<>", Next); 651233237Sjkim if (!Token) 652233237Sjkim { 653233237Sjkim goto SyntaxError; 654233237Sjkim } 655233237Sjkim 656233237Sjkim DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID 657233237Sjkim "Start #include file %s\n", Gbl_CurrentLineNumber, 658233237Sjkim Token, Gbl_CurrentLineNumber); 659233237Sjkim 660233237Sjkim PrOpenIncludeFile (Token); 661233237Sjkim break; 662233237Sjkim 663233237Sjkim case PR_DIRECTIVE_PRAGMA: 664233237Sjkim /* Only "#pragma message" supported at this time */ 665233237Sjkim 666233237Sjkim if (strcmp (Token, "message")) 667233237Sjkim { 668233237Sjkim PrError (ASL_ERROR, ASL_MSG_UNKNOWN_PRAGMA, 669233237Sjkim THIS_TOKEN_OFFSET (Token)); 670233237Sjkim return; 671233237Sjkim } 672233237Sjkim 673233237Sjkim Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next); 674233237Sjkim if (!Token) 675233237Sjkim { 676233237Sjkim goto SyntaxError; 677233237Sjkim } 678233237Sjkim 679233237Sjkim TokenOffset = Token - Gbl_MainTokenBuffer; 680233237Sjkim AcpiOsPrintf ("%s\n", &Gbl_CurrentLineBuffer[TokenOffset]); 681233237Sjkim break; 682233237Sjkim 683233237Sjkim case PR_DIRECTIVE_UNDEF: 684233237Sjkim DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID 685233237Sjkim "#undef: %s\n", Gbl_CurrentLineNumber, Token); 686233237Sjkim 687233237Sjkim PrRemoveDefine (Token); 688233237Sjkim break; 689233237Sjkim 690233237Sjkim case PR_DIRECTIVE_WARNING: 691233237Sjkim PrError (ASL_WARNING, ASL_MSG_ERROR_DIRECTIVE, 692233237Sjkim THIS_TOKEN_OFFSET (Token)); 693233237Sjkim break; 694233237Sjkim 695233237Sjkim case PR_DIRECTIVE_LINE: 696233237Sjkim /* TBD: set line number -- or, do this in main compiler */ 697233237Sjkim default: 698233237Sjkim /* Should never get here */ 699233237Sjkim DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID 700233237Sjkim "Unrecognized directive: %u\n", 701233237Sjkim Gbl_CurrentLineNumber, Directive); 702233237Sjkim break; 703233237Sjkim } 704233237Sjkim 705233237Sjkim return; 706233237Sjkim 707233237Sjkim 708233237SjkimSyntaxError: 709233237Sjkim 710233237Sjkim PrError (ASL_ERROR, ASL_MSG_DIRECTIVE_SYNTAX, 711233237Sjkim THIS_TOKEN_OFFSET (DirectiveToken)); 712233237Sjkim return; 713233237Sjkim} 714233237Sjkim 715233237Sjkim 716233237Sjkim/******************************************************************************* 717233237Sjkim * 718233237Sjkim * FUNCTION: PrMatchDirective 719233237Sjkim * 720233237Sjkim * PARAMETERS: Directive - Pointer to directive name token 721233237Sjkim * 722233237Sjkim * RETURN: Index into command array, -1 if not found 723233237Sjkim * 724233237Sjkim * DESCRIPTION: Lookup the incoming directive in the known directives table. 725233237Sjkim * 726233237Sjkim ******************************************************************************/ 727233237Sjkim 728233237Sjkimstatic int 729233237SjkimPrMatchDirective ( 730233237Sjkim char *Directive) 731233237Sjkim{ 732233237Sjkim int i; 733233237Sjkim 734233237Sjkim 735233237Sjkim if (!Directive || Directive[0] == 0) 736233237Sjkim { 737233237Sjkim return (ASL_DIRECTIVE_NOT_FOUND); 738233237Sjkim } 739233237Sjkim 740233237Sjkim for (i = 0; Gbl_DirectiveInfo[i].Name; i++) 741233237Sjkim { 742233237Sjkim if (!strcmp (Gbl_DirectiveInfo[i].Name, Directive)) 743233237Sjkim { 744233237Sjkim return (i); 745233237Sjkim } 746233237Sjkim } 747233237Sjkim 748233237Sjkim return (ASL_DIRECTIVE_NOT_FOUND); /* Command not recognized */ 749233237Sjkim} 750