1 /****************************************************************************** 2 * 3 * Module Name: prscan - Preprocessor start-up and file scan module 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2015, 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 void 71 PrGetNextLineInit ( 72 void); 73 74 static UINT32 75 PrGetNextLine ( 76 FILE *Handle); 77 78 static int 79 PrMatchDirective ( 80 char *Directive); 81 82 static void 83 PrPushDirective ( 84 int Directive, 85 char *Argument); 86 87 static ACPI_STATUS 88 PrPopDirective ( 89 void); 90 91 static void 92 PrDbgPrint ( 93 char *Action, 94 char *DirectiveName); 95 96 static void 97 PrDoIncludeBuffer ( 98 char *Pathname, 99 char *BufferName); 100 101 static void 102 PrDoIncludeFile ( 103 char *Pathname); 104 105 106 /* 107 * Supported preprocessor directives 108 * Each entry is of the form "Name, ArgumentCount" 109 */ 110 static const PR_DIRECTIVE_INFO Gbl_DirectiveInfo[] = 111 { 112 {"define", 1}, 113 {"elif", 0}, /* Converted to #else..#if internally */ 114 {"else", 0}, 115 {"endif", 0}, 116 {"error", 1}, 117 {"if", 1}, 118 {"ifdef", 1}, 119 {"ifndef", 1}, 120 {"include", 0}, /* Argument is not standard format, so just use 0 here */ 121 {"includebuffer", 0}, /* Argument is not standard format, so just use 0 here */ 122 {"line", 1}, 123 {"loadbuffer", 0}, 124 {"pragma", 1}, 125 {"undef", 1}, 126 {"warning", 1}, 127 {NULL, 0} 128 }; 129 130 /* This table must match ordering of above table exactly */ 131 132 enum Gbl_DirectiveIndexes 133 { 134 PR_DIRECTIVE_DEFINE = 0, 135 PR_DIRECTIVE_ELIF, 136 PR_DIRECTIVE_ELSE, 137 PR_DIRECTIVE_ENDIF, 138 PR_DIRECTIVE_ERROR, 139 PR_DIRECTIVE_IF, 140 PR_DIRECTIVE_IFDEF, 141 PR_DIRECTIVE_IFNDEF, 142 PR_DIRECTIVE_INCLUDE, 143 PR_DIRECTIVE_INCLUDEBUFFER, 144 PR_DIRECTIVE_LINE, 145 PR_DIRECTIVE_PRAGMA, 146 PR_DIRECTIVE_UNDEF, 147 PR_DIRECTIVE_WARNING, 148 }; 149 150 #define ASL_DIRECTIVE_NOT_FOUND -1 151 152 153 /******************************************************************************* 154 * 155 * FUNCTION: PrInitializePreprocessor 156 * 157 * PARAMETERS: None 158 * 159 * RETURN: None 160 * 161 * DESCRIPTION: Startup initialization for the Preprocessor. 162 * 163 ******************************************************************************/ 164 165 void 166 PrInitializePreprocessor ( 167 void) 168 { 169 /* Init globals and the list of #defines */ 170 171 PrInitializeGlobals (); 172 Gbl_DefineList = NULL; 173 } 174 175 176 /******************************************************************************* 177 * 178 * FUNCTION: PrInitializeGlobals 179 * 180 * PARAMETERS: None 181 * 182 * RETURN: None 183 * 184 * DESCRIPTION: Initialize globals for the Preprocessor. Used for startuup 185 * initialization and re-initialization between compiles during 186 * a multiple source file compile. 187 * 188 ******************************************************************************/ 189 190 void 191 PrInitializeGlobals ( 192 void) 193 { 194 /* Init globals */ 195 196 Gbl_InputFileList = NULL; 197 Gbl_CurrentLineNumber = 1; 198 Gbl_PreprocessorLineNumber = 1; 199 Gbl_PreprocessorError = FALSE; 200 201 /* These are used to track #if/#else blocks (possibly nested) */ 202 203 Gbl_IfDepth = 0; 204 Gbl_IgnoringThisCodeBlock = FALSE; 205 Gbl_DirectiveStack = NULL; 206 } 207 208 209 /******************************************************************************* 210 * 211 * FUNCTION: PrTerminatePreprocessor 212 * 213 * PARAMETERS: None 214 * 215 * RETURN: None 216 * 217 * DESCRIPTION: Termination of the preprocessor. Delete lists. Keep any 218 * defines that were specified on the command line, in order to 219 * support multiple compiles with a single compiler invocation. 220 * 221 ******************************************************************************/ 222 223 void 224 PrTerminatePreprocessor ( 225 void) 226 { 227 PR_DEFINE_INFO *DefineInfo; 228 229 230 /* 231 * The persistent defines (created on the command line) are always at the 232 * end of the list. We save them. 233 */ 234 while ((Gbl_DefineList) && (!Gbl_DefineList->Persist)) 235 { 236 DefineInfo = Gbl_DefineList; 237 Gbl_DefineList = DefineInfo->Next; 238 239 ACPI_FREE (DefineInfo->Replacement); 240 ACPI_FREE (DefineInfo->Identifier); 241 ACPI_FREE (DefineInfo); 242 } 243 } 244 245 246 /******************************************************************************* 247 * 248 * FUNCTION: PrDoPreprocess 249 * 250 * PARAMETERS: None 251 * 252 * RETURN: None 253 * 254 * DESCRIPTION: Main entry point for the iASL Preprocessor. Input file must 255 * be already open. Handles multiple input files via the 256 * #include directive. 257 * 258 ******************************************************************************/ 259 260 void 261 PrDoPreprocess ( 262 void) 263 { 264 BOOLEAN MoreInputFiles; 265 266 267 DbgPrint (ASL_DEBUG_OUTPUT, "Starting preprocessing phase\n\n"); 268 269 270 FlSeekFile (ASL_FILE_INPUT, 0); 271 PrDumpPredefinedNames (); 272 273 /* Main preprocessor loop, handles include files */ 274 275 do 276 { 277 PrPreprocessInputFile (); 278 MoreInputFiles = PrPopInputFileStack (); 279 280 } while (MoreInputFiles); 281 282 /* Point compiler input to the new preprocessor output file (.pre) */ 283 284 FlCloseFile (ASL_FILE_INPUT); 285 Gbl_Files[ASL_FILE_INPUT].Handle = Gbl_Files[ASL_FILE_PREPROCESSOR].Handle; 286 AslCompilerin = Gbl_Files[ASL_FILE_INPUT].Handle; 287 288 /* Reset globals to allow compiler to run */ 289 290 FlSeekFile (ASL_FILE_INPUT, 0); 291 if (!Gbl_PreprocessOnly) 292 { 293 Gbl_CurrentLineNumber = 0; 294 } 295 296 DbgPrint (ASL_DEBUG_OUTPUT, "Preprocessing phase complete \n\n"); 297 } 298 299 300 /******************************************************************************* 301 * 302 * FUNCTION: PrPreprocessInputFile 303 * 304 * PARAMETERS: None 305 * 306 * RETURN: None 307 * 308 * DESCRIPTION: Preprocess one entire file, line-by-line. 309 * 310 * Input: Raw user ASL from ASL_FILE_INPUT 311 * Output: Preprocessed file written to ASL_FILE_PREPROCESSOR and 312 * (optionally) ASL_FILE_PREPROCESSOR_USER 313 * 314 ******************************************************************************/ 315 316 static void 317 PrPreprocessInputFile ( 318 void) 319 { 320 UINT32 Status; 321 char *Token; 322 char *ReplaceString; 323 PR_DEFINE_INFO *DefineInfo; 324 ACPI_SIZE TokenOffset; 325 char *Next; 326 int OffsetAdjust; 327 328 329 PrGetNextLineInit (); 330 331 /* Scan line-by-line. Comments and blank lines are skipped by this function */ 332 333 while ((Status = PrGetNextLine (Gbl_Files[ASL_FILE_INPUT].Handle)) != ASL_EOF) 334 { 335 Gbl_CurrentLineNumber++; 336 Gbl_LogicalLineNumber++; 337 338 if ((Status == ASL_WITHIN_COMMENT) || 339 (Status == ASL_BLANK_LINE)) 340 { 341 goto WriteEntireLine; 342 } 343 344 /* Need a copy of the input line for strok() */ 345 346 strcpy (Gbl_MainTokenBuffer, Gbl_CurrentLineBuffer); 347 Token = PrGetNextToken (Gbl_MainTokenBuffer, PR_TOKEN_SEPARATORS, &Next); 348 OffsetAdjust = 0; 349 350 /* All preprocessor directives must begin with '#' */ 351 352 if (Token && (*Token == '#')) 353 { 354 if (strlen (Token) == 1) 355 { 356 Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, &Next); 357 } 358 else 359 { 360 Token++; /* Skip leading # */ 361 } 362 363 /* Execute the directive, do not write line to output file */ 364 365 PrDoDirective (Token, &Next); 366 continue; 367 } 368 369 /* 370 * If we are currently within the part of an IF/ELSE block that is 371 * FALSE, ignore the line and do not write it to the output file. 372 * This continues until an #else or #endif is encountered. 373 */ 374 if (Gbl_IgnoringThisCodeBlock) 375 { 376 continue; 377 } 378 379 /* Match and replace all #defined names within this source line */ 380 381 while (Token) 382 { 383 DefineInfo = PrMatchDefine (Token); 384 if (DefineInfo) 385 { 386 if (DefineInfo->Body) 387 { 388 /* This is a macro */ 389 390 DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID 391 "Matched Macro: %s->%s\n", 392 Gbl_CurrentLineNumber, DefineInfo->Identifier, 393 DefineInfo->Replacement); 394 395 PrDoMacroInvocation (Gbl_MainTokenBuffer, Token, 396 DefineInfo, &Next); 397 } 398 else 399 { 400 ReplaceString = DefineInfo->Replacement; 401 402 /* Replace the name in the original line buffer */ 403 404 TokenOffset = Token - Gbl_MainTokenBuffer + OffsetAdjust; 405 PrReplaceData ( 406 &Gbl_CurrentLineBuffer[TokenOffset], strlen (Token), 407 ReplaceString, strlen (ReplaceString)); 408 409 /* Adjust for length difference between old and new name length */ 410 411 OffsetAdjust += strlen (ReplaceString) - strlen (Token); 412 413 DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID 414 "Matched #define: %s->%s\n", 415 Gbl_CurrentLineNumber, Token, 416 *ReplaceString ? ReplaceString : "(NULL STRING)"); 417 } 418 } 419 420 Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, &Next); 421 } 422 423 Gbl_PreprocessorLineNumber++; 424 425 426 WriteEntireLine: 427 /* 428 * Now we can write the possibly modified source line to the 429 * preprocessor file(s). 430 */ 431 FlWriteFile (ASL_FILE_PREPROCESSOR, Gbl_CurrentLineBuffer, 432 strlen (Gbl_CurrentLineBuffer)); 433 } 434 } 435 436 437 /******************************************************************************* 438 * 439 * FUNCTION: PrDoDirective 440 * 441 * PARAMETERS: Directive - Pointer to directive name token 442 * Next - "Next" buffer from GetNextToken 443 * 444 * RETURN: None. 445 * 446 * DESCRIPTION: Main processing for all preprocessor directives 447 * 448 ******************************************************************************/ 449 450 static void 451 PrDoDirective ( 452 char *DirectiveToken, 453 char **Next) 454 { 455 char *Token = Gbl_MainTokenBuffer; 456 char *Token2 = NULL; 457 char *End; 458 UINT64 Value; 459 ACPI_SIZE TokenOffset; 460 int Directive; 461 ACPI_STATUS Status; 462 463 464 if (!DirectiveToken) 465 { 466 goto SyntaxError; 467 } 468 469 Directive = PrMatchDirective (DirectiveToken); 470 if (Directive == ASL_DIRECTIVE_NOT_FOUND) 471 { 472 PrError (ASL_ERROR, ASL_MSG_UNKNOWN_DIRECTIVE, 473 THIS_TOKEN_OFFSET (DirectiveToken)); 474 475 DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID 476 "#%s: Unknown directive\n", 477 Gbl_CurrentLineNumber, DirectiveToken); 478 return; 479 } 480 481 /* 482 * If we are currently ignoring this block and we encounter a #else or 483 * #elif, we must ignore their blocks also if the parent block is also 484 * being ignored. 485 */ 486 if (Gbl_IgnoringThisCodeBlock) 487 { 488 switch (Directive) 489 { 490 case PR_DIRECTIVE_ELSE: 491 case PR_DIRECTIVE_ELIF: 492 493 if (Gbl_DirectiveStack && Gbl_DirectiveStack->IgnoringThisCodeBlock) 494 { 495 PrDbgPrint ("Ignoring", Gbl_DirectiveInfo[Directive].Name); 496 return; 497 } 498 break; 499 500 default: 501 break; 502 } 503 } 504 505 /* 506 * Need to always check for #else, #elif, #endif regardless of 507 * whether we are ignoring the current code block, since these 508 * are conditional code block terminators. 509 */ 510 switch (Directive) 511 { 512 case PR_DIRECTIVE_ELSE: 513 514 Gbl_IgnoringThisCodeBlock = !(Gbl_IgnoringThisCodeBlock); 515 PrDbgPrint ("Executing", "else block"); 516 return; 517 518 case PR_DIRECTIVE_ELIF: 519 520 Gbl_IgnoringThisCodeBlock = !(Gbl_IgnoringThisCodeBlock); 521 Directive = PR_DIRECTIVE_IF; 522 523 if (Gbl_IgnoringThisCodeBlock == TRUE) 524 { 525 /* Not executing the ELSE part -- all done here */ 526 PrDbgPrint ("Ignoring", "elif block"); 527 return; 528 } 529 530 /* 531 * After this, we will execute the IF part further below. 532 * First, however, pop off the original #if directive. 533 */ 534 if (ACPI_FAILURE (PrPopDirective ())) 535 { 536 PrError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, 537 THIS_TOKEN_OFFSET (DirectiveToken)); 538 } 539 540 PrDbgPrint ("Executing", "elif block"); 541 break; 542 543 case PR_DIRECTIVE_ENDIF: 544 545 PrDbgPrint ("Executing", "endif"); 546 547 /* Pop the owning #if/#ifdef/#ifndef */ 548 549 if (ACPI_FAILURE (PrPopDirective ())) 550 { 551 PrError (ASL_ERROR, ASL_MSG_ENDIF_MISMATCH, 552 THIS_TOKEN_OFFSET (DirectiveToken)); 553 } 554 return; 555 556 default: 557 break; 558 } 559 560 /* Most directives have at least one argument */ 561 562 if (Gbl_DirectiveInfo[Directive].ArgCount >= 1) 563 { 564 Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next); 565 if (!Token) 566 { 567 goto SyntaxError; 568 } 569 } 570 571 if (Gbl_DirectiveInfo[Directive].ArgCount >= 2) 572 { 573 Token2 = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next); 574 if (!Token2) 575 { 576 goto SyntaxError; 577 } 578 } 579 580 /* 581 * At this point, if we are ignoring the current code block, 582 * do not process any more directives (i.e., ignore them also.) 583 * For "if" style directives, open/push a new block anyway. We 584 * must do this to keep track of #endif directives 585 */ 586 if (Gbl_IgnoringThisCodeBlock) 587 { 588 switch (Directive) 589 { 590 case PR_DIRECTIVE_IF: 591 case PR_DIRECTIVE_IFDEF: 592 case PR_DIRECTIVE_IFNDEF: 593 594 PrPushDirective (Directive, Token); 595 PrDbgPrint ("Ignoring", Gbl_DirectiveInfo[Directive].Name); 596 break; 597 598 default: 599 break; 600 } 601 602 return; 603 } 604 605 /* 606 * Execute the directive 607 */ 608 PrDbgPrint ("Begin execution", Gbl_DirectiveInfo[Directive].Name); 609 610 switch (Directive) 611 { 612 case PR_DIRECTIVE_IF: 613 614 TokenOffset = Token - Gbl_MainTokenBuffer; 615 616 /* Need to expand #define macros in the expression string first */ 617 618 Status = PrResolveIntegerExpression ( 619 &Gbl_CurrentLineBuffer[TokenOffset-1], &Value); 620 if (ACPI_FAILURE (Status)) 621 { 622 return; 623 } 624 625 PrPushDirective (Directive, Token); 626 if (!Value) 627 { 628 Gbl_IgnoringThisCodeBlock = TRUE; 629 } 630 631 DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID 632 "Resolved #if: %8.8X%8.8X %s\n", 633 Gbl_CurrentLineNumber, ACPI_FORMAT_UINT64 (Value), 634 Gbl_IgnoringThisCodeBlock ? "<Skipping Block>" : "<Executing Block>"); 635 break; 636 637 case PR_DIRECTIVE_IFDEF: 638 639 PrPushDirective (Directive, Token); 640 if (!PrMatchDefine (Token)) 641 { 642 Gbl_IgnoringThisCodeBlock = TRUE; 643 } 644 645 PrDbgPrint ("Evaluated", "ifdef"); 646 break; 647 648 case PR_DIRECTIVE_IFNDEF: 649 650 PrPushDirective (Directive, Token); 651 if (PrMatchDefine (Token)) 652 { 653 Gbl_IgnoringThisCodeBlock = TRUE; 654 } 655 656 PrDbgPrint ("Evaluated", "ifndef"); 657 break; 658 659 case PR_DIRECTIVE_DEFINE: 660 /* 661 * By definition, if first char after the name is a paren, 662 * this is a function macro. 663 */ 664 TokenOffset = Token - Gbl_MainTokenBuffer + strlen (Token); 665 if (*(&Gbl_CurrentLineBuffer[TokenOffset]) == '(') 666 { 667 #ifndef MACROS_SUPPORTED 668 AcpiOsPrintf ("%s ERROR - line %u: #define macros are not supported yet\n", 669 Gbl_CurrentLineBuffer, Gbl_LogicalLineNumber); 670 exit(1); 671 #else 672 PrAddMacro (Token, Next); 673 #endif 674 } 675 else 676 { 677 /* Use the remainder of the line for the #define */ 678 679 Token2 = *Next; 680 if (Token2) 681 { 682 while ((*Token2 == ' ') || (*Token2 == '\t')) 683 { 684 Token2++; 685 } 686 End = Token2; 687 while (*End != '\n') 688 { 689 End++; 690 } 691 *End = 0; 692 } 693 else 694 { 695 Token2 = ""; 696 } 697 #if 0 698 Token2 = PrGetNextToken (NULL, "\n", /*PR_TOKEN_SEPARATORS,*/ Next); 699 if (!Token2) 700 { 701 Token2 = ""; 702 } 703 #endif 704 DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID 705 "New #define: %s->%s\n", 706 Gbl_LogicalLineNumber, Token, Token2); 707 708 PrAddDefine (Token, Token2, FALSE); 709 } 710 break; 711 712 case PR_DIRECTIVE_ERROR: 713 714 /* Note: No macro expansion */ 715 716 PrError (ASL_ERROR, ASL_MSG_ERROR_DIRECTIVE, 717 THIS_TOKEN_OFFSET (Token)); 718 719 Gbl_SourceLine = 0; 720 Gbl_NextError = Gbl_ErrorLog; 721 CmCleanupAndExit (); 722 exit(1); 723 724 case PR_DIRECTIVE_INCLUDE: 725 726 Token = PrGetNextToken (NULL, " \"<>", Next); 727 if (!Token) 728 { 729 goto SyntaxError; 730 } 731 732 DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID 733 "Start #include file \"%s\"\n", Gbl_CurrentLineNumber, 734 Token, Gbl_CurrentLineNumber); 735 736 PrDoIncludeFile (Token); 737 break; 738 739 case PR_DIRECTIVE_INCLUDEBUFFER: 740 741 Token = PrGetNextToken (NULL, " \"<>", Next); 742 if (!Token) 743 { 744 goto SyntaxError; 745 } 746 747 Token2 = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next); 748 if (!Token2) 749 { 750 goto SyntaxError; 751 } 752 753 DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID 754 "Start #includebuffer input from file \"%s\", buffer name %s\n", 755 Gbl_CurrentLineNumber, Token, Token2); 756 757 PrDoIncludeBuffer (Token, Token2); 758 break; 759 760 case PR_DIRECTIVE_LINE: 761 762 TokenOffset = Token - Gbl_MainTokenBuffer; 763 764 Status = PrResolveIntegerExpression ( 765 &Gbl_CurrentLineBuffer[TokenOffset-1], &Value); 766 if (ACPI_FAILURE (Status)) 767 { 768 return; 769 } 770 771 DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID 772 "User #line invocation %s\n", Gbl_CurrentLineNumber, 773 Token); 774 775 Gbl_CurrentLineNumber = (UINT32) Value; 776 777 /* Emit #line into the preprocessor file */ 778 779 FlPrintFile (ASL_FILE_PREPROCESSOR, "#line %u \"%s\"\n", 780 Gbl_CurrentLineNumber, Gbl_Files[ASL_FILE_INPUT].Filename); 781 break; 782 783 case PR_DIRECTIVE_PRAGMA: 784 785 if (!strcmp (Token, "disable")) 786 { 787 Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next); 788 if (!Token) 789 { 790 goto SyntaxError; 791 } 792 793 TokenOffset = Token - Gbl_MainTokenBuffer; 794 AslDisableException (&Gbl_CurrentLineBuffer[TokenOffset]); 795 } 796 else if (!strcmp (Token, "message")) 797 { 798 Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next); 799 if (!Token) 800 { 801 goto SyntaxError; 802 } 803 804 TokenOffset = Token - Gbl_MainTokenBuffer; 805 AcpiOsPrintf ("%s\n", &Gbl_CurrentLineBuffer[TokenOffset]); 806 } 807 else 808 { 809 PrError (ASL_ERROR, ASL_MSG_UNKNOWN_PRAGMA, 810 THIS_TOKEN_OFFSET (Token)); 811 return; 812 } 813 814 break; 815 816 case PR_DIRECTIVE_UNDEF: 817 818 DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID 819 "#undef: %s\n", Gbl_CurrentLineNumber, Token); 820 821 PrRemoveDefine (Token); 822 break; 823 824 case PR_DIRECTIVE_WARNING: 825 826 PrError (ASL_WARNING, ASL_MSG_WARNING_DIRECTIVE, 827 THIS_TOKEN_OFFSET (Token)); 828 break; 829 830 default: 831 832 /* Should never get here */ 833 DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID 834 "Unrecognized directive: %u\n", 835 Gbl_CurrentLineNumber, Directive); 836 break; 837 } 838 839 return; 840 841 SyntaxError: 842 843 PrError (ASL_ERROR, ASL_MSG_DIRECTIVE_SYNTAX, 844 THIS_TOKEN_OFFSET (DirectiveToken)); 845 return; 846 } 847 848 849 /******************************************************************************* 850 * 851 * FUNCTION: PrGetNextLine, PrGetNextLineInit 852 * 853 * PARAMETERS: Handle - Open file handle for the source file 854 * 855 * RETURN: Status of the GetLine operation: 856 * AE_OK - Normal line, OK status 857 * ASL_WITHIN_COMMENT - Line is part of a multi-line comment 858 * ASL_EOF - End-of-file reached 859 * 860 * DESCRIPTION: Get the next text line from the input file. Does not strip 861 * comments. 862 * 863 ******************************************************************************/ 864 865 #define PR_NORMAL_TEXT 0 866 #define PR_WITHIN_COMMENT 1 867 868 static UINT8 AcpiGbl_LineScanState = PR_NORMAL_TEXT; 869 870 static void 871 PrGetNextLineInit ( 872 void) 873 { 874 AcpiGbl_LineScanState = 0; 875 } 876 877 static UINT32 878 PrGetNextLine ( 879 FILE *Handle) 880 { 881 UINT32 i; 882 int c = 0; 883 int PreviousChar; 884 885 886 /* Always clear the global line buffer */ 887 888 memset (Gbl_CurrentLineBuffer, 0, Gbl_LineBufferSize); 889 for (i = 0; ;) 890 { 891 /* 892 * If line is too long, expand the line buffers. Also increases 893 * Gbl_LineBufferSize. 894 */ 895 if (i >= Gbl_LineBufferSize) 896 { 897 UtExpandLineBuffers (); 898 } 899 900 PreviousChar = c; 901 c = getc (Handle); 902 if (c == EOF) 903 { 904 return (ASL_EOF); 905 } 906 907 /* We need to worry about multi-line slash-asterisk comments */ 908 909 /* Check for comment open */ 910 911 if ((AcpiGbl_LineScanState == PR_NORMAL_TEXT) && 912 (PreviousChar == '/') && (c == '*')) 913 { 914 AcpiGbl_LineScanState = PR_WITHIN_COMMENT; 915 } 916 917 /* Check for comment close */ 918 919 if ((AcpiGbl_LineScanState == PR_WITHIN_COMMENT) && 920 (PreviousChar == '*') && (c == '/')) 921 { 922 AcpiGbl_LineScanState = PR_NORMAL_TEXT; 923 } 924 925 /* Always copy the character into line buffer */ 926 927 Gbl_CurrentLineBuffer[i] = (char) c; 928 i++; 929 930 /* Always exit on end-of-line */ 931 932 if (c == '\n') 933 { 934 /* Handle multi-line comments */ 935 936 if (AcpiGbl_LineScanState == PR_WITHIN_COMMENT) 937 { 938 return (ASL_WITHIN_COMMENT); 939 } 940 if (i == 1) 941 { 942 return (ASL_BLANK_LINE); 943 } 944 return (AE_OK); 945 } 946 } 947 } 948 949 950 /******************************************************************************* 951 * 952 * FUNCTION: PrMatchDirective 953 * 954 * PARAMETERS: Directive - Pointer to directive name token 955 * 956 * RETURN: Index into command array, -1 if not found 957 * 958 * DESCRIPTION: Lookup the incoming directive in the known directives table. 959 * 960 ******************************************************************************/ 961 962 static int 963 PrMatchDirective ( 964 char *Directive) 965 { 966 int i; 967 968 969 if (!Directive || Directive[0] == 0) 970 { 971 return (ASL_DIRECTIVE_NOT_FOUND); 972 } 973 974 for (i = 0; Gbl_DirectiveInfo[i].Name; i++) 975 { 976 if (!strcmp (Gbl_DirectiveInfo[i].Name, Directive)) 977 { 978 return (i); 979 } 980 } 981 982 return (ASL_DIRECTIVE_NOT_FOUND); /* Command not recognized */ 983 } 984 985 986 /******************************************************************************* 987 * 988 * FUNCTION: PrPushDirective 989 * 990 * PARAMETERS: Directive - Encoded directive ID 991 * Argument - String containing argument to the 992 * directive 993 * 994 * RETURN: None 995 * 996 * DESCRIPTION: Push an item onto the directive stack. Used for processing 997 * nested #if/#else type conditional compilation directives. 998 * Specifically: Used on detection of #if/#ifdef/#ifndef to open 999 * a block. 1000 * 1001 ******************************************************************************/ 1002 1003 static void 1004 PrPushDirective ( 1005 int Directive, 1006 char *Argument) 1007 { 1008 DIRECTIVE_INFO *Info; 1009 1010 1011 /* Allocate and populate a stack info item */ 1012 1013 Info = ACPI_ALLOCATE (sizeof (DIRECTIVE_INFO)); 1014 1015 Info->Next = Gbl_DirectiveStack; 1016 Info->Directive = Directive; 1017 Info->IgnoringThisCodeBlock = Gbl_IgnoringThisCodeBlock; 1018 strncpy (Info->Argument, Argument, MAX_ARGUMENT_LENGTH); 1019 1020 DbgPrint (ASL_DEBUG_OUTPUT, 1021 "Pr(%.4u) - [%u %s] %*s Pushed [#%s %s]: IgnoreFlag = %s\n", 1022 Gbl_CurrentLineNumber, Gbl_IfDepth, 1023 Gbl_IgnoringThisCodeBlock ? "I" : "E", 1024 Gbl_IfDepth * 4, " ", 1025 Gbl_DirectiveInfo[Directive].Name, 1026 Argument, Gbl_IgnoringThisCodeBlock ? "TRUE" : "FALSE"); 1027 1028 /* Push new item */ 1029 1030 Gbl_DirectiveStack = Info; 1031 Gbl_IfDepth++; 1032 } 1033 1034 1035 /******************************************************************************* 1036 * 1037 * FUNCTION: PrPopDirective 1038 * 1039 * PARAMETERS: None 1040 * 1041 * RETURN: Status. Error if the stack is empty. 1042 * 1043 * DESCRIPTION: Pop an item off the directive stack. Used for processing 1044 * nested #if/#else type conditional compilation directives. 1045 * Specifically: Used on detection of #elif and #endif to remove 1046 * the original #if/#ifdef/#ifndef from the stack and close 1047 * the block. 1048 * 1049 ******************************************************************************/ 1050 1051 static ACPI_STATUS 1052 PrPopDirective ( 1053 void) 1054 { 1055 DIRECTIVE_INFO *Info; 1056 1057 1058 /* Check for empty stack */ 1059 1060 Info = Gbl_DirectiveStack; 1061 if (!Info) 1062 { 1063 return (AE_ERROR); 1064 } 1065 1066 /* Pop one item, keep globals up-to-date */ 1067 1068 Gbl_IfDepth--; 1069 Gbl_IgnoringThisCodeBlock = Info->IgnoringThisCodeBlock; 1070 Gbl_DirectiveStack = Info->Next; 1071 1072 DbgPrint (ASL_DEBUG_OUTPUT, 1073 "Pr(%.4u) - [%u %s] %*s Popped [#%s %s]: IgnoreFlag now = %s\n", 1074 Gbl_CurrentLineNumber, Gbl_IfDepth, 1075 Gbl_IgnoringThisCodeBlock ? "I" : "E", 1076 Gbl_IfDepth * 4, " ", 1077 Gbl_DirectiveInfo[Info->Directive].Name, 1078 Info->Argument, Gbl_IgnoringThisCodeBlock ? "TRUE" : "FALSE"); 1079 1080 ACPI_FREE (Info); 1081 return (AE_OK); 1082 } 1083 1084 1085 /******************************************************************************* 1086 * 1087 * FUNCTION: PrDbgPrint 1088 * 1089 * PARAMETERS: Action - Action being performed 1090 * DirectiveName - Directive being processed 1091 * 1092 * RETURN: None 1093 * 1094 * DESCRIPTION: Special debug print for directive processing. 1095 * 1096 ******************************************************************************/ 1097 1098 static void 1099 PrDbgPrint ( 1100 char *Action, 1101 char *DirectiveName) 1102 { 1103 1104 DbgPrint (ASL_DEBUG_OUTPUT, "Pr(%.4u) - [%u %s] " 1105 "%*s %s #%s, IfDepth %u\n", 1106 Gbl_CurrentLineNumber, Gbl_IfDepth, 1107 Gbl_IgnoringThisCodeBlock ? "I" : "E", 1108 Gbl_IfDepth * 4, " ", 1109 Action, DirectiveName, Gbl_IfDepth); 1110 } 1111 1112 1113 /******************************************************************************* 1114 * 1115 * FUNCTION: PrDoIncludeFile 1116 * 1117 * PARAMETERS: Pathname - Name of the input file 1118 * 1119 * RETURN: None. 1120 * 1121 * DESCRIPTION: Open an include file, from #include. 1122 * 1123 ******************************************************************************/ 1124 1125 static void 1126 PrDoIncludeFile ( 1127 char *Pathname) 1128 { 1129 char *FullPathname; 1130 1131 1132 (void) PrOpenIncludeFile (Pathname, "r", &FullPathname); 1133 } 1134 1135 1136 /******************************************************************************* 1137 * 1138 * FUNCTION: PrDoIncludeBuffer 1139 * 1140 * PARAMETERS: Pathname - Name of the input binary file 1141 * BufferName - ACPI namepath of the buffer 1142 * 1143 * RETURN: None. 1144 * 1145 * DESCRIPTION: Create an ACPI buffer object from a binary file. The contents 1146 * of the file are emitted into the buffer object as ascii 1147 * hex data. From #includebuffer. 1148 * 1149 ******************************************************************************/ 1150 1151 static void 1152 PrDoIncludeBuffer ( 1153 char *Pathname, 1154 char *BufferName) 1155 { 1156 char *FullPathname; 1157 FILE *BinaryBufferFile; 1158 UINT32 i = 0; 1159 UINT8 c; 1160 1161 1162 BinaryBufferFile = PrOpenIncludeFile (Pathname, "rb", &FullPathname); 1163 if (!BinaryBufferFile) 1164 { 1165 return; 1166 } 1167 1168 /* Emit "Name (XXXX, Buffer() {" header */ 1169 1170 FlPrintFile (ASL_FILE_PREPROCESSOR, "Name (%s, Buffer()\n{", BufferName); 1171 1172 /* Dump the entire file in ascii hex format */ 1173 1174 while (fread (&c, 1, 1, BinaryBufferFile)) 1175 { 1176 if (!(i % 8)) 1177 { 1178 FlPrintFile (ASL_FILE_PREPROCESSOR, "\n ", c); 1179 } 1180 1181 FlPrintFile (ASL_FILE_PREPROCESSOR, " 0x%2.2X,", c); 1182 i++; 1183 } 1184 1185 DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID 1186 "#includebuffer: read %u bytes from %s\n", 1187 Gbl_CurrentLineNumber, i, FullPathname); 1188 1189 /* Close the Name() operator */ 1190 1191 FlPrintFile (ASL_FILE_PREPROCESSOR, "\n})\n", BufferName); 1192 fclose (BinaryBufferFile); 1193 } 1194