1 /****************************************************************************** 2 * 3 * Module Name: prscan - Preprocessor start-up and file scan module 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2014, 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 <contrib/dev/acpica/compiler/aslcompiler.h> 47 #include <contrib/dev/acpica/compiler/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