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