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, 68252279Sjkim char **Next); 69233237Sjkim 70233237Sjkimstatic int 71233237SjkimPrMatchDirective ( 72233237Sjkim char *Directive); 73233237Sjkim 74252279Sjkimstatic void 75252279SjkimPrPushDirective ( 76252279Sjkim int Directive, 77252279Sjkim char *Argument); 78252279Sjkim 79252279Sjkimstatic ACPI_STATUS 80252279SjkimPrPopDirective ( 81252279Sjkim void); 82252279Sjkim 83252279Sjkimstatic void 84252279SjkimPrDbgPrint ( 85252279Sjkim char *Action, 86252279Sjkim char *DirectiveName); 87252279Sjkim 88252279Sjkim 89233237Sjkim/* 90233237Sjkim * Supported preprocessor directives 91233237Sjkim */ 92233237Sjkimstatic const PR_DIRECTIVE_INFO Gbl_DirectiveInfo[] = 93233237Sjkim{ 94233237Sjkim {"define", 1}, 95233237Sjkim {"elif", 0}, /* Converted to #else..#if internally */ 96233237Sjkim {"else", 0}, 97233237Sjkim {"endif", 0}, 98233237Sjkim {"error", 1}, 99233237Sjkim {"if", 1}, 100233237Sjkim {"ifdef", 1}, 101233237Sjkim {"ifndef", 1}, 102233237Sjkim {"include", 0}, /* Argument is not standard format, so 0 */ 103233237Sjkim {"line", 1}, 104233237Sjkim {"pragma", 1}, 105233237Sjkim {"undef", 1}, 106233237Sjkim {"warning", 1}, 107233237Sjkim {NULL, 0} 108233237Sjkim}; 109233237Sjkim 110233237Sjkimenum Gbl_DirectiveIndexes 111233237Sjkim{ 112233237Sjkim PR_DIRECTIVE_DEFINE = 0, 113233237Sjkim PR_DIRECTIVE_ELIF, 114233237Sjkim PR_DIRECTIVE_ELSE, 115233237Sjkim PR_DIRECTIVE_ENDIF, 116233237Sjkim PR_DIRECTIVE_ERROR, 117233237Sjkim PR_DIRECTIVE_IF, 118233237Sjkim PR_DIRECTIVE_IFDEF, 119233237Sjkim PR_DIRECTIVE_IFNDEF, 120233237Sjkim PR_DIRECTIVE_INCLUDE, 121233237Sjkim PR_DIRECTIVE_LINE, 122233237Sjkim PR_DIRECTIVE_PRAGMA, 123233237Sjkim PR_DIRECTIVE_UNDEF, 124233237Sjkim PR_DIRECTIVE_WARNING, 125233237Sjkim}; 126233237Sjkim 127233237Sjkim#define ASL_DIRECTIVE_NOT_FOUND -1 128233237Sjkim 129233237Sjkim 130233237Sjkim/******************************************************************************* 131233237Sjkim * 132233237Sjkim * FUNCTION: PrInitializePreprocessor 133233237Sjkim * 134233237Sjkim * PARAMETERS: None 135233237Sjkim * 136233237Sjkim * RETURN: None 137233237Sjkim * 138233237Sjkim * DESCRIPTION: Startup initialization for the Preprocessor. 139233237Sjkim * 140233237Sjkim ******************************************************************************/ 141233237Sjkim 142233237Sjkimvoid 143233237SjkimPrInitializePreprocessor ( 144233237Sjkim void) 145233237Sjkim{ 146233237Sjkim /* Init globals and the list of #defines */ 147233237Sjkim 148233237Sjkim PrInitializeGlobals (); 149233237Sjkim Gbl_DefineList = NULL; 150233237Sjkim} 151233237Sjkim 152233237Sjkim 153233237Sjkim/******************************************************************************* 154233237Sjkim * 155233237Sjkim * FUNCTION: PrInitializeGlobals 156233237Sjkim * 157233237Sjkim * PARAMETERS: None 158233237Sjkim * 159233237Sjkim * RETURN: None 160233237Sjkim * 161233237Sjkim * DESCRIPTION: Initialize globals for the Preprocessor. Used for startuup 162233237Sjkim * initialization and re-initialization between compiles during 163233237Sjkim * a multiple source file compile. 164233237Sjkim * 165233237Sjkim ******************************************************************************/ 166233237Sjkim 167233237Sjkimvoid 168233237SjkimPrInitializeGlobals ( 169233237Sjkim void) 170233237Sjkim{ 171233237Sjkim /* Init globals */ 172233237Sjkim 173233237Sjkim Gbl_InputFileList = NULL; 174233237Sjkim Gbl_CurrentLineNumber = 0; 175233237Sjkim Gbl_PreprocessorLineNumber = 1; 176233237Sjkim Gbl_PreprocessorError = FALSE; 177252279Sjkim 178252279Sjkim /* These are used to track #if/#else blocks (possibly nested) */ 179252279Sjkim 180252279Sjkim Gbl_IfDepth = 0; 181252279Sjkim Gbl_IgnoringThisCodeBlock = FALSE; 182252279Sjkim Gbl_DirectiveStack = NULL; 183233237Sjkim} 184233237Sjkim 185233237Sjkim 186233237Sjkim/******************************************************************************* 187233237Sjkim * 188233237Sjkim * FUNCTION: PrTerminatePreprocessor 189233237Sjkim * 190233237Sjkim * PARAMETERS: None 191233237Sjkim * 192233237Sjkim * RETURN: None 193233237Sjkim * 194233237Sjkim * DESCRIPTION: Termination of the preprocessor. Delete lists. Keep any 195233237Sjkim * defines that were specified on the command line, in order to 196233237Sjkim * support multiple compiles with a single compiler invocation. 197233237Sjkim * 198233237Sjkim ******************************************************************************/ 199233237Sjkim 200233237Sjkimvoid 201233237SjkimPrTerminatePreprocessor ( 202233237Sjkim void) 203233237Sjkim{ 204233237Sjkim PR_DEFINE_INFO *DefineInfo; 205233237Sjkim 206233237Sjkim 207233237Sjkim /* 208233237Sjkim * The persistent defines (created on the command line) are always at the 209233237Sjkim * end of the list. We save them. 210233237Sjkim */ 211233237Sjkim while ((Gbl_DefineList) && (!Gbl_DefineList->Persist)) 212233237Sjkim { 213233237Sjkim DefineInfo = Gbl_DefineList; 214233237Sjkim Gbl_DefineList = DefineInfo->Next; 215233237Sjkim 216233237Sjkim ACPI_FREE (DefineInfo->Replacement); 217233237Sjkim ACPI_FREE (DefineInfo->Identifier); 218233237Sjkim ACPI_FREE (DefineInfo); 219233237Sjkim } 220233237Sjkim} 221233237Sjkim 222233237Sjkim 223233237Sjkim/******************************************************************************* 224233237Sjkim * 225233237Sjkim * FUNCTION: PrDoPreprocess 226233237Sjkim * 227233237Sjkim * PARAMETERS: None 228233237Sjkim * 229252279Sjkim * RETURN: None 230233237Sjkim * 231233237Sjkim * DESCRIPTION: Main entry point for the iASL Preprocessor. Input file must 232233237Sjkim * be already open. Handles multiple input files via the 233233237Sjkim * #include directive. 234233237Sjkim * 235233237Sjkim ******************************************************************************/ 236233237Sjkim 237252279Sjkimvoid 238233237SjkimPrDoPreprocess ( 239233237Sjkim void) 240233237Sjkim{ 241233237Sjkim BOOLEAN MoreInputFiles; 242233237Sjkim 243233237Sjkim 244233237Sjkim DbgPrint (ASL_DEBUG_OUTPUT, "Starting preprocessing phase\n\n"); 245233237Sjkim 246233237Sjkim 247233237Sjkim FlSeekFile (ASL_FILE_INPUT, 0); 248233237Sjkim PrDumpPredefinedNames (); 249233237Sjkim 250233237Sjkim /* Main preprocessor loop, handles include files */ 251233237Sjkim 252233237Sjkim do 253233237Sjkim { 254233237Sjkim PrPreprocessInputFile (); 255233237Sjkim MoreInputFiles = PrPopInputFileStack (); 256233237Sjkim 257233237Sjkim } while (MoreInputFiles); 258233237Sjkim 259252279Sjkim /* Point compiler input to the new preprocessor output file (.i) */ 260233237Sjkim 261233237Sjkim FlCloseFile (ASL_FILE_INPUT); 262233237Sjkim Gbl_Files[ASL_FILE_INPUT].Handle = Gbl_Files[ASL_FILE_PREPROCESSOR].Handle; 263233237Sjkim AslCompilerin = Gbl_Files[ASL_FILE_INPUT].Handle; 264233237Sjkim 265233237Sjkim /* Reset globals to allow compiler to run */ 266233237Sjkim 267233237Sjkim FlSeekFile (ASL_FILE_INPUT, 0); 268233237Sjkim Gbl_CurrentLineNumber = 1; 269233237Sjkim 270233237Sjkim DbgPrint (ASL_DEBUG_OUTPUT, "Preprocessing phase complete \n\n"); 271233237Sjkim} 272233237Sjkim 273233237Sjkim 274233237Sjkim/******************************************************************************* 275233237Sjkim * 276233237Sjkim * FUNCTION: PrPreprocessInputFile 277233237Sjkim * 278233237Sjkim * PARAMETERS: None 279233237Sjkim * 280233237Sjkim * RETURN: None 281233237Sjkim * 282233237Sjkim * DESCRIPTION: Preprocess one entire file, line-by-line. 283233237Sjkim * 284233237Sjkim * Input: Raw user ASL from ASL_FILE_INPUT 285233237Sjkim * Output: Preprocessed file written to ASL_FILE_PREPROCESSOR 286233237Sjkim * 287233237Sjkim ******************************************************************************/ 288233237Sjkim 289233237Sjkimstatic void 290233237SjkimPrPreprocessInputFile ( 291233237Sjkim void) 292233237Sjkim{ 293233237Sjkim UINT32 Offset; 294233237Sjkim char *Token; 295233237Sjkim char *ReplaceString; 296233237Sjkim PR_DEFINE_INFO *DefineInfo; 297233237Sjkim ACPI_SIZE TokenOffset; 298233237Sjkim char *Next; 299233237Sjkim int OffsetAdjust; 300233237Sjkim 301233237Sjkim 302233237Sjkim /* Scan line-by-line. Comments and blank lines are skipped by this function */ 303233237Sjkim 304233237Sjkim while ((Offset = DtGetNextLine (Gbl_Files[ASL_FILE_INPUT].Handle)) != ASL_EOF) 305233237Sjkim { 306233237Sjkim /* Need a copy of the input line for strok() */ 307233237Sjkim 308233237Sjkim strcpy (Gbl_MainTokenBuffer, Gbl_CurrentLineBuffer); 309233237Sjkim Token = PrGetNextToken (Gbl_MainTokenBuffer, PR_TOKEN_SEPARATORS, &Next); 310233237Sjkim OffsetAdjust = 0; 311233237Sjkim 312233237Sjkim /* All preprocessor directives must begin with '#' */ 313233237Sjkim 314233237Sjkim if (Token && (*Token == '#')) 315233237Sjkim { 316233237Sjkim if (strlen (Token) == 1) 317233237Sjkim { 318233237Sjkim Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, &Next); 319233237Sjkim } 320233237Sjkim else 321233237Sjkim { 322233237Sjkim Token++; /* Skip leading # */ 323233237Sjkim } 324233237Sjkim 325233237Sjkim /* Execute the directive, do not write line to output file */ 326233237Sjkim 327252279Sjkim PrDoDirective (Token, &Next); 328233237Sjkim continue; 329233237Sjkim } 330233237Sjkim 331233237Sjkim /* 332233237Sjkim * If we are currently within the part of an IF/ELSE block that is 333233237Sjkim * FALSE, ignore the line and do not write it to the output file. 334233237Sjkim * This continues until an #else or #endif is encountered. 335233237Sjkim */ 336252279Sjkim if (Gbl_IgnoringThisCodeBlock) 337233237Sjkim { 338233237Sjkim continue; 339233237Sjkim } 340233237Sjkim 341233237Sjkim /* Match and replace all #defined names within this source line */ 342233237Sjkim 343233237Sjkim while (Token) 344233237Sjkim { 345233237Sjkim DefineInfo = PrMatchDefine (Token); 346233237Sjkim if (DefineInfo) 347233237Sjkim { 348233237Sjkim if (DefineInfo->Body) 349233237Sjkim { 350233237Sjkim /* This is a macro */ 351233237Sjkim 352233237Sjkim DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID 353233237Sjkim "Matched Macro: %s->%s\n", 354233237Sjkim Gbl_CurrentLineNumber, DefineInfo->Identifier, 355233237Sjkim DefineInfo->Replacement); 356233237Sjkim 357233237Sjkim PrDoMacroInvocation (Gbl_MainTokenBuffer, Token, 358233237Sjkim DefineInfo, &Next); 359233237Sjkim } 360233237Sjkim else 361233237Sjkim { 362233237Sjkim ReplaceString = DefineInfo->Replacement; 363233237Sjkim 364233237Sjkim /* Replace the name in the original line buffer */ 365233237Sjkim 366233237Sjkim TokenOffset = Token - Gbl_MainTokenBuffer + OffsetAdjust; 367233237Sjkim PrReplaceData ( 368233237Sjkim &Gbl_CurrentLineBuffer[TokenOffset], strlen (Token), 369233237Sjkim ReplaceString, strlen (ReplaceString)); 370233237Sjkim 371233237Sjkim /* Adjust for length difference between old and new name length */ 372233237Sjkim 373233237Sjkim OffsetAdjust += strlen (ReplaceString) - strlen (Token); 374233237Sjkim 375233237Sjkim DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID 376233237Sjkim "Matched #define: %s->%s\n", 377233237Sjkim Gbl_CurrentLineNumber, Token, 378233237Sjkim *ReplaceString ? ReplaceString : "(NULL STRING)"); 379233237Sjkim } 380233237Sjkim } 381233237Sjkim 382233237Sjkim Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, &Next); 383233237Sjkim } 384233237Sjkim 385233237Sjkim#if 0 386233237Sjkim/* Line prefix */ 387233237Sjkim FlPrintFile (ASL_FILE_PREPROCESSOR, "/* %14s %.5u i:%.5u */ ", 388233237Sjkim Gbl_Files[ASL_FILE_INPUT].Filename, 389233237Sjkim Gbl_CurrentLineNumber, Gbl_PreprocessorLineNumber); 390233237Sjkim#endif 391233237Sjkim 392234623Sjkim /* 393234623Sjkim * Emit a #line directive if necessary, to keep the line numbers in 394234623Sjkim * the (.i) file synchronized with the original source code file, so 395234623Sjkim * that the correct line number appears in any error messages 396234623Sjkim * generated by the actual compiler. 397234623Sjkim */ 398234623Sjkim if (Gbl_CurrentLineNumber > (Gbl_PreviousLineNumber + 1)) 399234623Sjkim { 400234623Sjkim FlPrintFile (ASL_FILE_PREPROCESSOR, "#line %u\n", 401234623Sjkim Gbl_CurrentLineNumber); 402234623Sjkim } 403234623Sjkim 404234623Sjkim Gbl_PreviousLineNumber = Gbl_CurrentLineNumber; 405234623Sjkim Gbl_PreprocessorLineNumber++; 406234623Sjkim 407234623Sjkim /* 408234623Sjkim * Now we can write the possibly modified source line to the 409234623Sjkim * preprocessor (.i) file 410234623Sjkim */ 411233237Sjkim FlWriteFile (ASL_FILE_PREPROCESSOR, Gbl_CurrentLineBuffer, 412233237Sjkim strlen (Gbl_CurrentLineBuffer)); 413233237Sjkim } 414233237Sjkim} 415233237Sjkim 416233237Sjkim 417233237Sjkim/******************************************************************************* 418233237Sjkim * 419233237Sjkim * FUNCTION: PrDoDirective 420233237Sjkim * 421233237Sjkim * PARAMETERS: Directive - Pointer to directive name token 422233237Sjkim * Next - "Next" buffer from GetNextToken 423233237Sjkim * 424252279Sjkim * RETURN: None. 425233237Sjkim * 426233237Sjkim * DESCRIPTION: Main processing for all preprocessor directives 427233237Sjkim * 428233237Sjkim ******************************************************************************/ 429233237Sjkim 430233237Sjkimstatic void 431233237SjkimPrDoDirective ( 432233237Sjkim char *DirectiveToken, 433252279Sjkim char **Next) 434233237Sjkim{ 435233237Sjkim char *Token = Gbl_MainTokenBuffer; 436233237Sjkim char *Token2; 437233237Sjkim char *End; 438233237Sjkim UINT64 Value; 439233237Sjkim ACPI_SIZE TokenOffset; 440233237Sjkim int Directive; 441233237Sjkim ACPI_STATUS Status; 442233237Sjkim 443233237Sjkim 444233237Sjkim if (!DirectiveToken) 445233237Sjkim { 446233237Sjkim goto SyntaxError; 447233237Sjkim } 448233237Sjkim 449233237Sjkim Directive = PrMatchDirective (DirectiveToken); 450233237Sjkim if (Directive == ASL_DIRECTIVE_NOT_FOUND) 451233237Sjkim { 452233237Sjkim PrError (ASL_ERROR, ASL_MSG_UNKNOWN_DIRECTIVE, 453233237Sjkim THIS_TOKEN_OFFSET (DirectiveToken)); 454233237Sjkim 455233237Sjkim DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID 456233237Sjkim "#%s: Unknown directive\n", 457233237Sjkim Gbl_CurrentLineNumber, DirectiveToken); 458233237Sjkim return; 459233237Sjkim } 460233237Sjkim 461252279Sjkim /* 462252279Sjkim * If we are currently ignoring this block and we encounter a #else or 463252279Sjkim * #elif, we must ignore their blocks also if the parent block is also 464252279Sjkim * being ignored. 465252279Sjkim */ 466252279Sjkim if (Gbl_IgnoringThisCodeBlock) 467252279Sjkim { 468252279Sjkim switch (Directive) 469252279Sjkim { 470252279Sjkim case PR_DIRECTIVE_ELSE: 471252279Sjkim case PR_DIRECTIVE_ELIF: 472233237Sjkim 473252279Sjkim if (Gbl_DirectiveStack && Gbl_DirectiveStack->IgnoringThisCodeBlock) 474252279Sjkim { 475252279Sjkim PrDbgPrint ("Ignoring", Gbl_DirectiveInfo[Directive].Name); 476252279Sjkim return; 477252279Sjkim } 478252279Sjkim break; 479252279Sjkim 480252279Sjkim default: 481252279Sjkim break; 482252279Sjkim } 483233237Sjkim } 484233237Sjkim 485233237Sjkim /* 486233237Sjkim * Need to always check for #else, #elif, #endif regardless of 487233237Sjkim * whether we are ignoring the current code block, since these 488233237Sjkim * are conditional code block terminators. 489233237Sjkim */ 490233237Sjkim switch (Directive) 491233237Sjkim { 492252279Sjkim case PR_DIRECTIVE_ELSE: 493252279Sjkim 494252279Sjkim Gbl_IgnoringThisCodeBlock = !(Gbl_IgnoringThisCodeBlock); 495252279Sjkim PrDbgPrint ("Executing", "else block"); 496252279Sjkim return; 497252279Sjkim 498233237Sjkim case PR_DIRECTIVE_ELIF: 499250838Sjkim 500252279Sjkim Gbl_IgnoringThisCodeBlock = !(Gbl_IgnoringThisCodeBlock); 501252279Sjkim Directive = PR_DIRECTIVE_IF; 502252279Sjkim 503252279Sjkim if (Gbl_IgnoringThisCodeBlock == TRUE) 504233237Sjkim { 505233237Sjkim /* Not executing the ELSE part -- all done here */ 506252279Sjkim PrDbgPrint ("Ignoring", "elif block"); 507233237Sjkim return; 508233237Sjkim } 509233237Sjkim 510252279Sjkim /* 511252279Sjkim * After this, we will execute the IF part further below. 512252279Sjkim * First, however, pop off the original #if directive. 513252279Sjkim */ 514252279Sjkim if (ACPI_FAILURE (PrPopDirective ())) 515252279Sjkim { 516252279Sjkim PrError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, 517252279Sjkim THIS_TOKEN_OFFSET (DirectiveToken)); 518252279Sjkim } 519233237Sjkim 520252279Sjkim PrDbgPrint ("Executing", "elif block"); 521233237Sjkim break; 522233237Sjkim 523252279Sjkim case PR_DIRECTIVE_ENDIF: 524250838Sjkim 525252279Sjkim PrDbgPrint ("Executing", "endif"); 526233237Sjkim 527252279Sjkim /* Pop the owning #if/#ifdef/#ifndef */ 528250838Sjkim 529252279Sjkim if (ACPI_FAILURE (PrPopDirective ())) 530233237Sjkim { 531233237Sjkim PrError (ASL_ERROR, ASL_MSG_ENDIF_MISMATCH, 532233237Sjkim THIS_TOKEN_OFFSET (DirectiveToken)); 533233237Sjkim } 534233237Sjkim return; 535233237Sjkim 536233237Sjkim default: 537233237Sjkim break; 538233237Sjkim } 539233237Sjkim 540252279Sjkim /* Most directives have at least one argument */ 541252279Sjkim 542252279Sjkim if (Gbl_DirectiveInfo[Directive].ArgCount == 1) 543252279Sjkim { 544252279Sjkim Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next); 545252279Sjkim if (!Token) 546252279Sjkim { 547252279Sjkim goto SyntaxError; 548252279Sjkim } 549252279Sjkim } 550252279Sjkim 551233237Sjkim /* 552233237Sjkim * At this point, if we are ignoring the current code block, 553233237Sjkim * do not process any more directives (i.e., ignore them also.) 554252279Sjkim * For "if" style directives, open/push a new block anyway. We 555252279Sjkim * must do this to keep track of #endif directives 556233237Sjkim */ 557252279Sjkim if (Gbl_IgnoringThisCodeBlock) 558233237Sjkim { 559252279Sjkim switch (Directive) 560252279Sjkim { 561252279Sjkim case PR_DIRECTIVE_IF: 562252279Sjkim case PR_DIRECTIVE_IFDEF: 563252279Sjkim case PR_DIRECTIVE_IFNDEF: 564252279Sjkim 565252279Sjkim PrPushDirective (Directive, Token); 566252279Sjkim PrDbgPrint ("Ignoring", Gbl_DirectiveInfo[Directive].Name); 567252279Sjkim break; 568252279Sjkim 569252279Sjkim default: 570252279Sjkim break; 571252279Sjkim } 572252279Sjkim 573233237Sjkim return; 574233237Sjkim } 575233237Sjkim 576252279Sjkim /* 577252279Sjkim * Execute the directive 578252279Sjkim */ 579252279Sjkim PrDbgPrint ("Begin execution", Gbl_DirectiveInfo[Directive].Name); 580233237Sjkim 581252279Sjkim switch (Directive) 582252279Sjkim { 583252279Sjkim case PR_DIRECTIVE_IF: 584233237Sjkim 585252279Sjkim TokenOffset = Token - Gbl_MainTokenBuffer; 586252279Sjkim 587252279Sjkim /* Need to expand #define macros in the expression string first */ 588252279Sjkim 589252279Sjkim Status = PrResolveIntegerExpression ( 590252279Sjkim &Gbl_CurrentLineBuffer[TokenOffset-1], &Value); 591252279Sjkim if (ACPI_FAILURE (Status)) 592233237Sjkim { 593252279Sjkim return; 594233237Sjkim } 595233237Sjkim 596252279Sjkim PrPushDirective (Directive, Token); 597252279Sjkim if (!Value) 598252279Sjkim { 599252279Sjkim Gbl_IgnoringThisCodeBlock = TRUE; 600252279Sjkim } 601252279Sjkim 602252279Sjkim DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID 603252279Sjkim "Resolved #if: %8.8X%8.8X %s\n", 604252279Sjkim Gbl_CurrentLineNumber, ACPI_FORMAT_UINT64 (Value), 605252279Sjkim Gbl_IgnoringThisCodeBlock ? "<Skipping Block>" : "<Executing Block>"); 606252279Sjkim break; 607252279Sjkim 608252279Sjkim case PR_DIRECTIVE_IFDEF: 609252279Sjkim 610252279Sjkim PrPushDirective (Directive, Token); 611252279Sjkim if (!PrMatchDefine (Token)) 612252279Sjkim { 613252279Sjkim Gbl_IgnoringThisCodeBlock = TRUE; 614252279Sjkim } 615252279Sjkim 616252279Sjkim PrDbgPrint ("Evaluated", "ifdef"); 617252279Sjkim break; 618252279Sjkim 619252279Sjkim case PR_DIRECTIVE_IFNDEF: 620252279Sjkim 621252279Sjkim PrPushDirective (Directive, Token); 622252279Sjkim if (PrMatchDefine (Token)) 623252279Sjkim { 624252279Sjkim Gbl_IgnoringThisCodeBlock = TRUE; 625252279Sjkim } 626252279Sjkim 627252279Sjkim PrDbgPrint ("Evaluated", "ifndef"); 628252279Sjkim break; 629252279Sjkim 630233237Sjkim case PR_DIRECTIVE_DEFINE: 631233237Sjkim /* 632233237Sjkim * By definition, if first char after the name is a paren, 633233237Sjkim * this is a function macro. 634233237Sjkim */ 635233237Sjkim TokenOffset = Token - Gbl_MainTokenBuffer + strlen (Token); 636233237Sjkim if (*(&Gbl_CurrentLineBuffer[TokenOffset]) == '(') 637233237Sjkim { 638233237Sjkim#ifndef MACROS_SUPPORTED 639234623Sjkim AcpiOsPrintf ("%s ERROR - line %u: #define macros are not supported yet\n", 640234623Sjkim Gbl_CurrentLineBuffer, Gbl_CurrentLineNumber); 641234623Sjkim exit(1); 642233237Sjkim#else 643233237Sjkim PrAddMacro (Token, Next); 644233237Sjkim#endif 645233237Sjkim } 646233237Sjkim else 647233237Sjkim { 648233237Sjkim /* Use the remainder of the line for the #define */ 649233237Sjkim 650233237Sjkim Token2 = *Next; 651233237Sjkim if (Token2) 652233237Sjkim { 653233237Sjkim while ((*Token2 == ' ') || (*Token2 == '\t')) 654233237Sjkim { 655233237Sjkim Token2++; 656233237Sjkim } 657233237Sjkim End = Token2; 658233237Sjkim while (*End != '\n') 659233237Sjkim { 660233237Sjkim End++; 661233237Sjkim } 662233237Sjkim *End = 0; 663233237Sjkim } 664233237Sjkim else 665233237Sjkim { 666233237Sjkim Token2 = ""; 667233237Sjkim } 668233237Sjkim#if 0 669233237Sjkim Token2 = PrGetNextToken (NULL, "\n", /*PR_TOKEN_SEPARATORS,*/ Next); 670233237Sjkim if (!Token2) 671233237Sjkim { 672233237Sjkim Token2 = ""; 673233237Sjkim } 674233237Sjkim#endif 675233237Sjkim DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID 676233237Sjkim "New #define: %s->%s\n", 677233237Sjkim Gbl_CurrentLineNumber, Token, Token2); 678233237Sjkim 679233237Sjkim PrAddDefine (Token, Token2, FALSE); 680233237Sjkim } 681233237Sjkim break; 682233237Sjkim 683233237Sjkim case PR_DIRECTIVE_ERROR: 684250838Sjkim 685233237Sjkim /* Note: No macro expansion */ 686233237Sjkim 687233237Sjkim PrError (ASL_ERROR, ASL_MSG_ERROR_DIRECTIVE, 688233237Sjkim THIS_TOKEN_OFFSET (Token)); 689233237Sjkim 690252279Sjkim Gbl_SourceLine = 0; 691252279Sjkim Gbl_NextError = Gbl_ErrorLog; 692252279Sjkim CmCleanupAndExit (); 693252279Sjkim exit(1); 694250838Sjkim 695233237Sjkim case PR_DIRECTIVE_INCLUDE: 696250838Sjkim 697233237Sjkim Token = PrGetNextToken (NULL, " \"<>", Next); 698233237Sjkim if (!Token) 699233237Sjkim { 700233237Sjkim goto SyntaxError; 701233237Sjkim } 702233237Sjkim 703233237Sjkim DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID 704235945Sjkim "Start #include file \"%s\"\n", Gbl_CurrentLineNumber, 705233237Sjkim Token, Gbl_CurrentLineNumber); 706233237Sjkim 707233237Sjkim PrOpenIncludeFile (Token); 708233237Sjkim break; 709233237Sjkim 710234623Sjkim case PR_DIRECTIVE_LINE: 711250838Sjkim 712234623Sjkim TokenOffset = Token - Gbl_MainTokenBuffer; 713234623Sjkim 714234623Sjkim Status = PrResolveIntegerExpression ( 715234623Sjkim &Gbl_CurrentLineBuffer[TokenOffset-1], &Value); 716234623Sjkim if (ACPI_FAILURE (Status)) 717234623Sjkim { 718234623Sjkim return; 719234623Sjkim } 720234623Sjkim 721234623Sjkim DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID 722234623Sjkim "User #line invocation %s\n", Gbl_CurrentLineNumber, 723234623Sjkim Token); 724234623Sjkim 725234623Sjkim /* Update local line numbers */ 726234623Sjkim 727234623Sjkim Gbl_CurrentLineNumber = (UINT32) Value; 728234623Sjkim Gbl_PreviousLineNumber = 0; 729234623Sjkim 730234623Sjkim /* Emit #line into the preprocessor file */ 731234623Sjkim 732234623Sjkim FlPrintFile (ASL_FILE_PREPROCESSOR, "#line %u \"%s\"\n", 733234623Sjkim Gbl_CurrentLineNumber, Gbl_Files[ASL_FILE_INPUT].Filename); 734234623Sjkim break; 735234623Sjkim 736233237Sjkim case PR_DIRECTIVE_PRAGMA: 737233237Sjkim 738250838Sjkim if (!strcmp (Token, "disable")) 739233237Sjkim { 740250838Sjkim Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next); 741250838Sjkim if (!Token) 742250838Sjkim { 743250838Sjkim goto SyntaxError; 744250838Sjkim } 745250838Sjkim 746250838Sjkim TokenOffset = Token - Gbl_MainTokenBuffer; 747250838Sjkim AslDisableException (&Gbl_CurrentLineBuffer[TokenOffset]); 748250838Sjkim } 749250838Sjkim else if (!strcmp (Token, "message")) 750250838Sjkim { 751250838Sjkim Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next); 752250838Sjkim if (!Token) 753250838Sjkim { 754250838Sjkim goto SyntaxError; 755250838Sjkim } 756250838Sjkim 757250838Sjkim TokenOffset = Token - Gbl_MainTokenBuffer; 758250838Sjkim AcpiOsPrintf ("%s\n", &Gbl_CurrentLineBuffer[TokenOffset]); 759250838Sjkim } 760250838Sjkim else 761250838Sjkim { 762233237Sjkim PrError (ASL_ERROR, ASL_MSG_UNKNOWN_PRAGMA, 763233237Sjkim THIS_TOKEN_OFFSET (Token)); 764233237Sjkim return; 765233237Sjkim } 766233237Sjkim 767233237Sjkim break; 768233237Sjkim 769233237Sjkim case PR_DIRECTIVE_UNDEF: 770250838Sjkim 771233237Sjkim DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID 772233237Sjkim "#undef: %s\n", Gbl_CurrentLineNumber, Token); 773233237Sjkim 774233237Sjkim PrRemoveDefine (Token); 775233237Sjkim break; 776233237Sjkim 777233237Sjkim case PR_DIRECTIVE_WARNING: 778250838Sjkim 779252279Sjkim PrError (ASL_WARNING, ASL_MSG_WARNING_DIRECTIVE, 780233237Sjkim THIS_TOKEN_OFFSET (Token)); 781233237Sjkim break; 782233237Sjkim 783233237Sjkim default: 784250838Sjkim 785233237Sjkim /* Should never get here */ 786233237Sjkim DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID 787233237Sjkim "Unrecognized directive: %u\n", 788233237Sjkim Gbl_CurrentLineNumber, Directive); 789233237Sjkim break; 790233237Sjkim } 791233237Sjkim 792233237Sjkim return; 793233237Sjkim 794233237SjkimSyntaxError: 795233237Sjkim 796233237Sjkim PrError (ASL_ERROR, ASL_MSG_DIRECTIVE_SYNTAX, 797233237Sjkim THIS_TOKEN_OFFSET (DirectiveToken)); 798233237Sjkim return; 799233237Sjkim} 800233237Sjkim 801233237Sjkim 802233237Sjkim/******************************************************************************* 803233237Sjkim * 804233237Sjkim * FUNCTION: PrMatchDirective 805233237Sjkim * 806233237Sjkim * PARAMETERS: Directive - Pointer to directive name token 807233237Sjkim * 808233237Sjkim * RETURN: Index into command array, -1 if not found 809233237Sjkim * 810233237Sjkim * DESCRIPTION: Lookup the incoming directive in the known directives table. 811233237Sjkim * 812233237Sjkim ******************************************************************************/ 813233237Sjkim 814233237Sjkimstatic int 815233237SjkimPrMatchDirective ( 816233237Sjkim char *Directive) 817233237Sjkim{ 818233237Sjkim int i; 819233237Sjkim 820233237Sjkim 821233237Sjkim if (!Directive || Directive[0] == 0) 822233237Sjkim { 823233237Sjkim return (ASL_DIRECTIVE_NOT_FOUND); 824233237Sjkim } 825233237Sjkim 826233237Sjkim for (i = 0; Gbl_DirectiveInfo[i].Name; i++) 827233237Sjkim { 828233237Sjkim if (!strcmp (Gbl_DirectiveInfo[i].Name, Directive)) 829233237Sjkim { 830233237Sjkim return (i); 831233237Sjkim } 832233237Sjkim } 833233237Sjkim 834233237Sjkim return (ASL_DIRECTIVE_NOT_FOUND); /* Command not recognized */ 835233237Sjkim} 836252279Sjkim 837252279Sjkim 838252279Sjkim/******************************************************************************* 839252279Sjkim * 840252279Sjkim * FUNCTION: PrPushDirective 841252279Sjkim * 842252279Sjkim * PARAMETERS: Directive - Encoded directive ID 843252279Sjkim * Argument - String containing argument to the 844252279Sjkim * directive 845252279Sjkim * 846252279Sjkim * RETURN: None 847252279Sjkim * 848252279Sjkim * DESCRIPTION: Push an item onto the directive stack. Used for processing 849252279Sjkim * nested #if/#else type conditional compilation directives. 850252279Sjkim * Specifically: Used on detection of #if/#ifdef/#ifndef to open 851252279Sjkim * a block. 852252279Sjkim * 853252279Sjkim ******************************************************************************/ 854252279Sjkim 855252279Sjkimstatic void 856252279SjkimPrPushDirective ( 857252279Sjkim int Directive, 858252279Sjkim char *Argument) 859252279Sjkim{ 860252279Sjkim DIRECTIVE_INFO *Info; 861252279Sjkim 862252279Sjkim 863252279Sjkim /* Allocate and populate a stack info item */ 864252279Sjkim 865252279Sjkim Info = ACPI_ALLOCATE (sizeof (DIRECTIVE_INFO)); 866252279Sjkim 867252279Sjkim Info->Next = Gbl_DirectiveStack; 868252279Sjkim Info->Directive = Directive; 869252279Sjkim Info->IgnoringThisCodeBlock = Gbl_IgnoringThisCodeBlock; 870252279Sjkim strncpy (Info->Argument, Argument, MAX_ARGUMENT_LENGTH); 871252279Sjkim 872252279Sjkim DbgPrint (ASL_DEBUG_OUTPUT, 873252279Sjkim "Pr(%.4u) - [%u %s] %*s Pushed [#%s %s]: IgnoreFlag = %s\n", 874252279Sjkim Gbl_CurrentLineNumber, Gbl_IfDepth, 875252279Sjkim Gbl_IgnoringThisCodeBlock ? "I" : "E", 876252279Sjkim Gbl_IfDepth * 4, " ", 877252279Sjkim Gbl_DirectiveInfo[Directive].Name, 878252279Sjkim Argument, Gbl_IgnoringThisCodeBlock ? "TRUE" : "FALSE"); 879252279Sjkim 880252279Sjkim /* Push new item */ 881252279Sjkim 882252279Sjkim Gbl_DirectiveStack = Info; 883252279Sjkim Gbl_IfDepth++; 884252279Sjkim} 885252279Sjkim 886252279Sjkim 887252279Sjkim/******************************************************************************* 888252279Sjkim * 889252279Sjkim * FUNCTION: PrPopDirective 890252279Sjkim * 891252279Sjkim * PARAMETERS: None 892252279Sjkim * 893252279Sjkim * RETURN: Status. Error if the stack is empty. 894252279Sjkim * 895252279Sjkim * DESCRIPTION: Pop an item off the directive stack. Used for processing 896252279Sjkim * nested #if/#else type conditional compilation directives. 897252279Sjkim * Specifically: Used on detection of #elif and #endif to remove 898252279Sjkim * the original #if/#ifdef/#ifndef from the stack and close 899252279Sjkim * the block. 900252279Sjkim * 901252279Sjkim ******************************************************************************/ 902252279Sjkim 903252279Sjkimstatic ACPI_STATUS 904252279SjkimPrPopDirective ( 905252279Sjkim void) 906252279Sjkim{ 907252279Sjkim DIRECTIVE_INFO *Info; 908252279Sjkim 909252279Sjkim 910252279Sjkim /* Check for empty stack */ 911252279Sjkim 912252279Sjkim Info = Gbl_DirectiveStack; 913252279Sjkim if (!Info) 914252279Sjkim { 915252279Sjkim return (AE_ERROR); 916252279Sjkim } 917252279Sjkim 918252279Sjkim /* Pop one item, keep globals up-to-date */ 919252279Sjkim 920252279Sjkim Gbl_IfDepth--; 921252279Sjkim Gbl_IgnoringThisCodeBlock = Info->IgnoringThisCodeBlock; 922252279Sjkim Gbl_DirectiveStack = Info->Next; 923252279Sjkim 924252279Sjkim DbgPrint (ASL_DEBUG_OUTPUT, 925252279Sjkim "Pr(%.4u) - [%u %s] %*s Popped [#%s %s]: IgnoreFlag now = %s\n", 926252279Sjkim Gbl_CurrentLineNumber, Gbl_IfDepth, 927252279Sjkim Gbl_IgnoringThisCodeBlock ? "I" : "E", 928252279Sjkim Gbl_IfDepth * 4, " ", 929252279Sjkim Gbl_DirectiveInfo[Info->Directive].Name, 930252279Sjkim Info->Argument, Gbl_IgnoringThisCodeBlock ? "TRUE" : "FALSE"); 931252279Sjkim 932252279Sjkim ACPI_FREE (Info); 933252279Sjkim return (AE_OK); 934252279Sjkim} 935252279Sjkim 936252279Sjkim 937252279Sjkim/******************************************************************************* 938252279Sjkim * 939252279Sjkim * FUNCTION: PrDbgPrint 940252279Sjkim * 941252279Sjkim * PARAMETERS: Action - Action being performed 942252279Sjkim * DirectiveName - Directive being processed 943252279Sjkim * 944252279Sjkim * RETURN: None 945252279Sjkim * 946252279Sjkim * DESCRIPTION: Special debug print for directive processing. 947252279Sjkim * 948252279Sjkim ******************************************************************************/ 949252279Sjkim 950252279Sjkimstatic void 951252279SjkimPrDbgPrint ( 952252279Sjkim char *Action, 953252279Sjkim char *DirectiveName) 954252279Sjkim{ 955252279Sjkim 956252279Sjkim DbgPrint (ASL_DEBUG_OUTPUT, "Pr(%.4u) - [%u %s] " 957252279Sjkim "%*s %s #%s, Depth %u\n", 958252279Sjkim Gbl_CurrentLineNumber, Gbl_IfDepth, 959252279Sjkim Gbl_IgnoringThisCodeBlock ? "I" : "E", 960252279Sjkim Gbl_IfDepth * 4, " ", 961252279Sjkim Action, DirectiveName, Gbl_IfDepth); 962252279Sjkim} 963