1 /****************************************************************************** 2 * 3 * Module Name: prscan - Preprocessor start-up and file scan module 4 * 5 *****************************************************************************/ 6 7 /****************************************************************************** 8 * 9 * 1. Copyright Notice 10 * 11 * Some or all of this work - Copyright (c) 1999 - 2017, Intel Corp. 12 * All rights reserved. 13 * 14 * 2. License 15 * 16 * 2.1. This is your license from Intel Corp. under its intellectual property 17 * rights. You may have additional license terms from the party that provided 18 * you this software, covering your right to use that party's intellectual 19 * property rights. 20 * 21 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 22 * copy of the source code appearing in this file ("Covered Code") an 23 * irrevocable, perpetual, worldwide license under Intel's copyrights in the 24 * base code distributed originally by Intel ("Original Intel Code") to copy, 25 * make derivatives, distribute, use and display any portion of the Covered 26 * Code in any form, with the right to sublicense such rights; and 27 * 28 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 29 * license (with the right to sublicense), under only those claims of Intel 30 * patents that are infringed by the Original Intel Code, to make, use, sell, 31 * offer to sell, and import the Covered Code and derivative works thereof 32 * solely to the minimum extent necessary to exercise the above copyright 33 * license, and in no event shall the patent license extend to any additions 34 * to or modifications of the Original Intel Code. No other license or right 35 * is granted directly or by implication, estoppel or otherwise; 36 * 37 * The above copyright and patent license is granted only if the following 38 * conditions are met: 39 * 40 * 3. Conditions 41 * 42 * 3.1. Redistribution of Source with Rights to Further Distribute Source. 43 * Redistribution of source code of any substantial portion of the Covered 44 * Code or modification with rights to further distribute source must include 45 * the above Copyright Notice, the above License, this list of Conditions, 46 * and the following Disclaimer and Export Compliance provision. In addition, 47 * Licensee must cause all Covered Code to which Licensee contributes to 48 * contain a file documenting the changes Licensee made to create that Covered 49 * Code and the date of any change. Licensee must include in that file the 50 * documentation of any changes made by any predecessor Licensee. Licensee 51 * must include a prominent statement that the modification is derived, 52 * directly or indirectly, from Original Intel Code. 53 * 54 * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 55 * Redistribution of source code of any substantial portion of the Covered 56 * Code or modification without rights to further distribute source must 57 * include the following Disclaimer and Export Compliance provision in the 58 * documentation and/or other materials provided with distribution. In 59 * addition, Licensee may not authorize further sublicense of source of any 60 * portion of the Covered Code, and must include terms to the effect that the 61 * license from Licensee to its licensee is limited to the intellectual 62 * property embodied in the software Licensee provides to its licensee, and 63 * not to intellectual property embodied in modifications its licensee may 64 * make. 65 * 66 * 3.3. Redistribution of Executable. Redistribution in executable form of any 67 * substantial portion of the Covered Code or modification must reproduce the 68 * above Copyright Notice, and the following Disclaimer and Export Compliance 69 * provision in the documentation and/or other materials provided with the 70 * distribution. 71 * 72 * 3.4. Intel retains all right, title, and interest in and to the Original 73 * Intel Code. 74 * 75 * 3.5. Neither the name Intel nor any other trademark owned or controlled by 76 * Intel shall be used in advertising or otherwise to promote the sale, use or 77 * other dealings in products derived from or relating to the Covered Code 78 * without prior written authorization from Intel. 79 * 80 * 4. Disclaimer and Export Compliance 81 * 82 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 83 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 84 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 85 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 86 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 87 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 88 * PARTICULAR PURPOSE. 89 * 90 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 91 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 92 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 93 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 94 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 95 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 96 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 97 * LIMITED REMEDY. 98 * 99 * 4.3. Licensee shall not export, either directly or indirectly, any of this 100 * software or system incorporating such software without first obtaining any 101 * required license or other approval from the U. S. Department of Commerce or 102 * any other agency or department of the United States Government. In the 103 * event Licensee exports any such software from the United States or 104 * re-exports any such software from a foreign destination, Licensee shall 105 * ensure that the distribution and export/re-export of the software is in 106 * compliance with all laws, regulations, orders, or other restrictions of the 107 * U.S. Export Administration Regulations. Licensee agrees that neither it nor 108 * any of its subsidiaries will export/re-export any technical data, process, 109 * software, or service, directly or indirectly, to any country for which the 110 * United States government or any agency thereof requires an export license, 111 * other governmental approval, or letter of assurance, without first obtaining 112 * such license, approval or letter. 113 * 114 ***************************************************************************** 115 * 116 * Alternatively, you may choose to be licensed under the terms of the 117 * following license: 118 * 119 * Redistribution and use in source and binary forms, with or without 120 * modification, are permitted provided that the following conditions 121 * are met: 122 * 1. Redistributions of source code must retain the above copyright 123 * notice, this list of conditions, and the following disclaimer, 124 * without modification. 125 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 126 * substantially similar to the "NO WARRANTY" disclaimer below 127 * ("Disclaimer") and any redistribution must be conditioned upon 128 * including a substantially similar Disclaimer requirement for further 129 * binary redistribution. 130 * 3. Neither the names of the above-listed copyright holders nor the names 131 * of any contributors may be used to endorse or promote products derived 132 * from this software without specific prior written permission. 133 * 134 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 135 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 136 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 137 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 138 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 139 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 140 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 141 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 142 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 143 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 144 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 145 * 146 * Alternatively, you may choose to be licensed under the terms of the 147 * GNU General Public License ("GPL") version 2 as published by the Free 148 * Software Foundation. 149 * 150 *****************************************************************************/ 151 152 #define _DECLARE_PR_GLOBALS 153 154 #include <contrib/dev/acpica/compiler/aslcompiler.h> 155 #include <contrib/dev/acpica/compiler/dtcompiler.h> 156 157 /* 158 * TBDs: 159 * 160 * No nested macros, maybe never 161 * Implement ASL "Include" as well as "#include" here? 162 */ 163 #define _COMPONENT ASL_PREPROCESSOR 164 ACPI_MODULE_NAME ("prscan") 165 166 167 /* Local prototypes */ 168 169 static void 170 PrPreprocessInputFile ( 171 void); 172 173 static void 174 PrDoDirective ( 175 char *DirectiveToken, 176 char **Next); 177 178 static void 179 PrGetNextLineInit ( 180 void); 181 182 static UINT32 183 PrGetNextLine ( 184 FILE *Handle); 185 186 static int 187 PrMatchDirective ( 188 char *Directive); 189 190 static void 191 PrPushDirective ( 192 int Directive, 193 char *Argument); 194 195 static ACPI_STATUS 196 PrPopDirective ( 197 void); 198 199 static void 200 PrDbgPrint ( 201 char *Action, 202 char *DirectiveName); 203 204 static void 205 PrDoIncludeBuffer ( 206 char *Pathname, 207 char *BufferName); 208 209 static void 210 PrDoIncludeFile ( 211 char *Pathname); 212 213 214 /* 215 * Supported preprocessor directives 216 * Each entry is of the form "Name, ArgumentCount" 217 */ 218 static const PR_DIRECTIVE_INFO Gbl_DirectiveInfo[] = 219 { 220 {"define", 1}, 221 {"elif", 0}, /* Converted to #else..#if internally */ 222 {"else", 0}, 223 {"endif", 0}, 224 {"error", 1}, 225 {"if", 1}, 226 {"ifdef", 1}, 227 {"ifndef", 1}, 228 {"include", 0}, /* Argument is not standard format, so just use 0 here */ 229 {"includebuffer", 0}, /* Argument is not standard format, so just use 0 here */ 230 {"line", 1}, 231 {"pragma", 1}, 232 {"undef", 1}, 233 {"warning", 1}, 234 {NULL, 0} 235 }; 236 237 /* This table must match ordering of above table exactly */ 238 239 enum Gbl_DirectiveIndexes 240 { 241 PR_DIRECTIVE_DEFINE = 0, 242 PR_DIRECTIVE_ELIF, 243 PR_DIRECTIVE_ELSE, 244 PR_DIRECTIVE_ENDIF, 245 PR_DIRECTIVE_ERROR, 246 PR_DIRECTIVE_IF, 247 PR_DIRECTIVE_IFDEF, 248 PR_DIRECTIVE_IFNDEF, 249 PR_DIRECTIVE_INCLUDE, 250 PR_DIRECTIVE_INCLUDEBUFFER, 251 PR_DIRECTIVE_LINE, 252 PR_DIRECTIVE_PRAGMA, 253 PR_DIRECTIVE_UNDEF, 254 PR_DIRECTIVE_WARNING 255 }; 256 257 #define ASL_DIRECTIVE_NOT_FOUND -1 258 259 260 /******************************************************************************* 261 * 262 * FUNCTION: PrInitializePreprocessor 263 * 264 * PARAMETERS: None 265 * 266 * RETURN: None 267 * 268 * DESCRIPTION: Startup initialization for the Preprocessor. 269 * 270 ******************************************************************************/ 271 272 void 273 PrInitializePreprocessor ( 274 void) 275 { 276 /* Init globals and the list of #defines */ 277 278 PrInitializeGlobals (); 279 Gbl_DefineList = NULL; 280 } 281 282 283 /******************************************************************************* 284 * 285 * FUNCTION: PrInitializeGlobals 286 * 287 * PARAMETERS: None 288 * 289 * RETURN: None 290 * 291 * DESCRIPTION: Initialize globals for the Preprocessor. Used for startuup 292 * initialization and re-initialization between compiles during 293 * a multiple source file compile. 294 * 295 ******************************************************************************/ 296 297 void 298 PrInitializeGlobals ( 299 void) 300 { 301 /* Init globals */ 302 303 Gbl_InputFileList = NULL; 304 Gbl_CurrentLineNumber = 1; 305 Gbl_PreprocessorLineNumber = 1; 306 Gbl_PreprocessorError = FALSE; 307 308 /* These are used to track #if/#else blocks (possibly nested) */ 309 310 Gbl_IfDepth = 0; 311 Gbl_IgnoringThisCodeBlock = FALSE; 312 Gbl_DirectiveStack = NULL; 313 } 314 315 316 /******************************************************************************* 317 * 318 * FUNCTION: PrTerminatePreprocessor 319 * 320 * PARAMETERS: None 321 * 322 * RETURN: None 323 * 324 * DESCRIPTION: Termination of the preprocessor. Delete lists. Keep any 325 * defines that were specified on the command line, in order to 326 * support multiple compiles with a single compiler invocation. 327 * 328 ******************************************************************************/ 329 330 void 331 PrTerminatePreprocessor ( 332 void) 333 { 334 PR_DEFINE_INFO *DefineInfo; 335 336 337 /* 338 * The persistent defines (created on the command line) are always at the 339 * end of the list. We save them. 340 */ 341 while ((Gbl_DefineList) && (!Gbl_DefineList->Persist)) 342 { 343 DefineInfo = Gbl_DefineList; 344 Gbl_DefineList = DefineInfo->Next; 345 346 ACPI_FREE (DefineInfo->Replacement); 347 ACPI_FREE (DefineInfo->Identifier); 348 ACPI_FREE (DefineInfo); 349 } 350 } 351 352 353 /******************************************************************************* 354 * 355 * FUNCTION: PrDoPreprocess 356 * 357 * PARAMETERS: None 358 * 359 * RETURN: None 360 * 361 * DESCRIPTION: Main entry point for the iASL Preprocessor. Input file must 362 * be already open. Handles multiple input files via the 363 * #include directive. 364 * 365 ******************************************************************************/ 366 367 void 368 PrDoPreprocess ( 369 void) 370 { 371 BOOLEAN MoreInputFiles; 372 373 374 DbgPrint (ASL_DEBUG_OUTPUT, "Starting preprocessing phase\n\n"); 375 376 377 FlSeekFile (ASL_FILE_INPUT, 0); 378 PrDumpPredefinedNames (); 379 380 /* Main preprocessor loop, handles include files */ 381 382 do 383 { 384 PrPreprocessInputFile (); 385 MoreInputFiles = PrPopInputFileStack (); 386 387 } while (MoreInputFiles); 388 389 /* Point compiler input to the new preprocessor output file (.pre) */ 390 391 FlCloseFile (ASL_FILE_INPUT); 392 Gbl_Files[ASL_FILE_INPUT].Handle = Gbl_Files[ASL_FILE_PREPROCESSOR].Handle; 393 AslCompilerin = Gbl_Files[ASL_FILE_INPUT].Handle; 394 395 /* Reset globals to allow compiler to run */ 396 397 FlSeekFile (ASL_FILE_INPUT, 0); 398 if (!Gbl_PreprocessOnly) 399 { 400 Gbl_CurrentLineNumber = 0; 401 } 402 403 DbgPrint (ASL_DEBUG_OUTPUT, "Preprocessing phase complete \n\n"); 404 } 405 406 407 /******************************************************************************* 408 * 409 * FUNCTION: PrPreprocessInputFile 410 * 411 * PARAMETERS: None 412 * 413 * RETURN: None 414 * 415 * DESCRIPTION: Preprocess one entire file, line-by-line. 416 * 417 * Input: Raw user ASL from ASL_FILE_INPUT 418 * Output: Preprocessed file written to ASL_FILE_PREPROCESSOR and 419 * (optionally) ASL_FILE_PREPROCESSOR_USER 420 * 421 ******************************************************************************/ 422 423 static void 424 PrPreprocessInputFile ( 425 void) 426 { 427 UINT32 Status; 428 char *Token; 429 char *ReplaceString; 430 PR_DEFINE_INFO *DefineInfo; 431 ACPI_SIZE TokenOffset; 432 char *Next; 433 int OffsetAdjust; 434 435 436 PrGetNextLineInit (); 437 438 /* Scan source line-by-line and process directives. Then write the .i file */ 439 440 while ((Status = PrGetNextLine (Gbl_Files[ASL_FILE_INPUT].Handle)) != ASL_EOF) 441 { 442 Gbl_CurrentLineNumber++; 443 Gbl_LogicalLineNumber++; 444 445 if (Status == ASL_IGNORE_LINE) 446 { 447 goto WriteEntireLine; 448 } 449 450 /* Need a copy of the input line for strok() */ 451 452 strcpy (Gbl_MainTokenBuffer, Gbl_CurrentLineBuffer); 453 Token = PrGetNextToken (Gbl_MainTokenBuffer, PR_TOKEN_SEPARATORS, &Next); 454 OffsetAdjust = 0; 455 456 /* All preprocessor directives must begin with '#' */ 457 458 if (Token && (*Token == '#')) 459 { 460 if (strlen (Token) == 1) 461 { 462 Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, &Next); 463 } 464 else 465 { 466 Token++; /* Skip leading # */ 467 } 468 469 /* Execute the directive, do not write line to output file */ 470 471 PrDoDirective (Token, &Next); 472 continue; 473 } 474 475 /* 476 * If we are currently within the part of an IF/ELSE block that is 477 * FALSE, ignore the line and do not write it to the output file. 478 * This continues until an #else or #endif is encountered. 479 */ 480 if (Gbl_IgnoringThisCodeBlock) 481 { 482 continue; 483 } 484 485 /* Match and replace all #defined names within this source line */ 486 487 while (Token) 488 { 489 DefineInfo = PrMatchDefine (Token); 490 if (DefineInfo) 491 { 492 if (DefineInfo->Body) 493 { 494 /* This is a macro */ 495 496 DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID 497 "Matched Macro: %s->%s\n", 498 Gbl_CurrentLineNumber, DefineInfo->Identifier, 499 DefineInfo->Replacement); 500 501 PrDoMacroInvocation (Gbl_MainTokenBuffer, Token, 502 DefineInfo, &Next); 503 } 504 else 505 { 506 ReplaceString = DefineInfo->Replacement; 507 508 /* Replace the name in the original line buffer */ 509 510 TokenOffset = Token - Gbl_MainTokenBuffer + OffsetAdjust; 511 PrReplaceData ( 512 &Gbl_CurrentLineBuffer[TokenOffset], strlen (Token), 513 ReplaceString, strlen (ReplaceString)); 514 515 /* Adjust for length difference between old and new name length */ 516 517 OffsetAdjust += strlen (ReplaceString) - strlen (Token); 518 519 DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID 520 "Matched #define: %s->%s\n", 521 Gbl_CurrentLineNumber, Token, 522 *ReplaceString ? ReplaceString : "(NULL STRING)"); 523 } 524 } 525 526 Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, &Next); 527 } 528 529 Gbl_PreprocessorLineNumber++; 530 531 532 WriteEntireLine: 533 /* 534 * Now we can write the possibly modified source line to the 535 * preprocessor file(s). 536 */ 537 FlWriteFile (ASL_FILE_PREPROCESSOR, Gbl_CurrentLineBuffer, 538 strlen (Gbl_CurrentLineBuffer)); 539 } 540 } 541 542 543 /******************************************************************************* 544 * 545 * FUNCTION: PrDoDirective 546 * 547 * PARAMETERS: Directive - Pointer to directive name token 548 * Next - "Next" buffer from GetNextToken 549 * 550 * RETURN: None. 551 * 552 * DESCRIPTION: Main processing for all preprocessor directives 553 * 554 ******************************************************************************/ 555 556 static void 557 PrDoDirective ( 558 char *DirectiveToken, 559 char **Next) 560 { 561 char *Token = Gbl_MainTokenBuffer; 562 char *Token2 = NULL; 563 char *End; 564 UINT64 Value; 565 ACPI_SIZE TokenOffset; 566 int Directive; 567 ACPI_STATUS Status; 568 569 570 if (!DirectiveToken) 571 { 572 goto SyntaxError; 573 } 574 575 Directive = PrMatchDirective (DirectiveToken); 576 if (Directive == ASL_DIRECTIVE_NOT_FOUND) 577 { 578 PrError (ASL_ERROR, ASL_MSG_UNKNOWN_DIRECTIVE, 579 THIS_TOKEN_OFFSET (DirectiveToken)); 580 581 DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID 582 "#%s: Unknown directive\n", 583 Gbl_CurrentLineNumber, DirectiveToken); 584 return; 585 } 586 587 /* 588 * Emit a line directive into the preprocessor file (.pre) after 589 * every matched directive. This is passed through to the compiler 590 * so that error/warning messages are kept in sync with the 591 * original source file. 592 */ 593 FlPrintFile (ASL_FILE_PREPROCESSOR, "#line %u \"%s\" // #%s\n", 594 Gbl_CurrentLineNumber, Gbl_Files[ASL_FILE_INPUT].Filename, 595 Gbl_DirectiveInfo[Directive].Name); 596 597 /* 598 * If we are currently ignoring this block and we encounter a #else or 599 * #elif, we must ignore their blocks also if the parent block is also 600 * being ignored. 601 */ 602 if (Gbl_IgnoringThisCodeBlock) 603 { 604 switch (Directive) 605 { 606 case PR_DIRECTIVE_ELSE: 607 case PR_DIRECTIVE_ELIF: 608 609 if (Gbl_DirectiveStack && 610 Gbl_DirectiveStack->IgnoringThisCodeBlock) 611 { 612 PrDbgPrint ("Ignoring", Gbl_DirectiveInfo[Directive].Name); 613 return; 614 } 615 break; 616 617 default: 618 break; 619 } 620 } 621 622 /* 623 * Need to always check for #else, #elif, #endif regardless of 624 * whether we are ignoring the current code block, since these 625 * are conditional code block terminators. 626 */ 627 switch (Directive) 628 { 629 case PR_DIRECTIVE_ELSE: 630 631 Gbl_IgnoringThisCodeBlock = !(Gbl_IgnoringThisCodeBlock); 632 PrDbgPrint ("Executing", "else block"); 633 return; 634 635 case PR_DIRECTIVE_ELIF: 636 637 Gbl_IgnoringThisCodeBlock = !(Gbl_IgnoringThisCodeBlock); 638 Directive = PR_DIRECTIVE_IF; 639 640 if (Gbl_IgnoringThisCodeBlock == TRUE) 641 { 642 /* Not executing the ELSE part -- all done here */ 643 PrDbgPrint ("Ignoring", "elif block"); 644 return; 645 } 646 647 /* 648 * After this, we will execute the IF part further below. 649 * First, however, pop off the original #if directive. 650 */ 651 if (ACPI_FAILURE (PrPopDirective ())) 652 { 653 PrError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, 654 THIS_TOKEN_OFFSET (DirectiveToken)); 655 } 656 657 PrDbgPrint ("Executing", "elif block"); 658 break; 659 660 case PR_DIRECTIVE_ENDIF: 661 662 PrDbgPrint ("Executing", "endif"); 663 664 /* Pop the owning #if/#ifdef/#ifndef */ 665 666 if (ACPI_FAILURE (PrPopDirective ())) 667 { 668 PrError (ASL_ERROR, ASL_MSG_ENDIF_MISMATCH, 669 THIS_TOKEN_OFFSET (DirectiveToken)); 670 } 671 return; 672 673 default: 674 break; 675 } 676 677 /* Most directives have at least one argument */ 678 679 if (Gbl_DirectiveInfo[Directive].ArgCount >= 1) 680 { 681 Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next); 682 if (!Token) 683 { 684 goto SyntaxError; 685 } 686 } 687 688 if (Gbl_DirectiveInfo[Directive].ArgCount >= 2) 689 { 690 Token2 = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next); 691 if (!Token2) 692 { 693 goto SyntaxError; 694 } 695 } 696 697 /* 698 * At this point, if we are ignoring the current code block, 699 * do not process any more directives (i.e., ignore them also.) 700 * For "if" style directives, open/push a new block anyway. We 701 * must do this to keep track of #endif directives 702 */ 703 if (Gbl_IgnoringThisCodeBlock) 704 { 705 switch (Directive) 706 { 707 case PR_DIRECTIVE_IF: 708 case PR_DIRECTIVE_IFDEF: 709 case PR_DIRECTIVE_IFNDEF: 710 711 PrPushDirective (Directive, Token); 712 PrDbgPrint ("Ignoring", Gbl_DirectiveInfo[Directive].Name); 713 break; 714 715 default: 716 break; 717 } 718 719 return; 720 } 721 722 /* 723 * Execute the directive 724 */ 725 PrDbgPrint ("Begin execution", Gbl_DirectiveInfo[Directive].Name); 726 727 switch (Directive) 728 { 729 case PR_DIRECTIVE_IF: 730 731 TokenOffset = Token - Gbl_MainTokenBuffer; 732 733 /* Need to expand #define macros in the expression string first */ 734 735 Status = PrResolveIntegerExpression ( 736 &Gbl_CurrentLineBuffer[TokenOffset-1], &Value); 737 if (ACPI_FAILURE (Status)) 738 { 739 return; 740 } 741 742 PrPushDirective (Directive, Token); 743 if (!Value) 744 { 745 Gbl_IgnoringThisCodeBlock = TRUE; 746 } 747 748 DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID 749 "Resolved #if: %8.8X%8.8X %s\n", 750 Gbl_CurrentLineNumber, ACPI_FORMAT_UINT64 (Value), 751 Gbl_IgnoringThisCodeBlock ? "<Skipping Block>" : "<Executing Block>"); 752 break; 753 754 case PR_DIRECTIVE_IFDEF: 755 756 PrPushDirective (Directive, Token); 757 if (!PrMatchDefine (Token)) 758 { 759 Gbl_IgnoringThisCodeBlock = TRUE; 760 } 761 762 PrDbgPrint ("Evaluated", "ifdef"); 763 break; 764 765 case PR_DIRECTIVE_IFNDEF: 766 767 PrPushDirective (Directive, Token); 768 if (PrMatchDefine (Token)) 769 { 770 Gbl_IgnoringThisCodeBlock = TRUE; 771 } 772 773 PrDbgPrint ("Evaluated", "ifndef"); 774 break; 775 776 case PR_DIRECTIVE_DEFINE: 777 /* 778 * By definition, if first char after the name is a paren, 779 * this is a function macro. 780 */ 781 TokenOffset = Token - Gbl_MainTokenBuffer + strlen (Token); 782 if (*(&Gbl_CurrentLineBuffer[TokenOffset]) == '(') 783 { 784 #ifndef MACROS_SUPPORTED 785 AcpiOsPrintf ( 786 "%s ERROR - line %u: #define macros are not supported yet\n", 787 Gbl_CurrentLineBuffer, Gbl_LogicalLineNumber); 788 exit(1); 789 #else 790 PrAddMacro (Token, Next); 791 #endif 792 } 793 else 794 { 795 /* Use the remainder of the line for the #define */ 796 797 Token2 = *Next; 798 if (Token2) 799 { 800 while ((*Token2 == ' ') || (*Token2 == '\t')) 801 { 802 Token2++; 803 } 804 805 End = Token2; 806 while (*End != '\n') 807 { 808 End++; 809 } 810 811 *End = 0; 812 } 813 else 814 { 815 Token2 = ""; 816 } 817 #if 0 818 Token2 = PrGetNextToken (NULL, "\n", /*PR_TOKEN_SEPARATORS,*/ Next); 819 if (!Token2) 820 { 821 Token2 = ""; 822 } 823 #endif 824 DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID 825 "New #define: %s->%s\n", 826 Gbl_LogicalLineNumber, Token, Token2); 827 828 PrAddDefine (Token, Token2, FALSE); 829 } 830 break; 831 832 case PR_DIRECTIVE_ERROR: 833 834 /* Note: No macro expansion */ 835 836 PrError (ASL_ERROR, ASL_MSG_ERROR_DIRECTIVE, 837 THIS_TOKEN_OFFSET (Token)); 838 839 Gbl_SourceLine = 0; 840 Gbl_NextError = Gbl_ErrorLog; 841 CmCleanupAndExit (); 842 exit(1); 843 844 case PR_DIRECTIVE_INCLUDE: 845 846 Token = PrGetNextToken (NULL, " \"<>", Next); 847 if (!Token) 848 { 849 goto SyntaxError; 850 } 851 852 DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID 853 "Start #include file \"%s\"\n", Gbl_CurrentLineNumber, 854 Token, Gbl_CurrentLineNumber); 855 856 PrDoIncludeFile (Token); 857 break; 858 859 case PR_DIRECTIVE_INCLUDEBUFFER: 860 861 Token = PrGetNextToken (NULL, " \"<>", Next); 862 if (!Token) 863 { 864 goto SyntaxError; 865 } 866 867 Token2 = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next); 868 if (!Token2) 869 { 870 goto SyntaxError; 871 } 872 873 DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID 874 "Start #includebuffer input from file \"%s\", buffer name %s\n", 875 Gbl_CurrentLineNumber, Token, Token2); 876 877 PrDoIncludeBuffer (Token, Token2); 878 break; 879 880 case PR_DIRECTIVE_LINE: 881 882 TokenOffset = Token - Gbl_MainTokenBuffer; 883 884 Status = PrResolveIntegerExpression ( 885 &Gbl_CurrentLineBuffer[TokenOffset-1], &Value); 886 if (ACPI_FAILURE (Status)) 887 { 888 return; 889 } 890 891 DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID 892 "User #line invocation %s\n", Gbl_CurrentLineNumber, 893 Token); 894 895 Gbl_CurrentLineNumber = (UINT32) Value; 896 897 /* Emit #line into the preprocessor file */ 898 899 FlPrintFile (ASL_FILE_PREPROCESSOR, "#line %u \"%s\"\n", 900 Gbl_CurrentLineNumber, Gbl_Files[ASL_FILE_INPUT].Filename); 901 break; 902 903 case PR_DIRECTIVE_PRAGMA: 904 905 if (!strcmp (Token, "disable")) 906 { 907 Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next); 908 if (!Token) 909 { 910 goto SyntaxError; 911 } 912 913 TokenOffset = Token - Gbl_MainTokenBuffer; 914 AslDisableException (&Gbl_CurrentLineBuffer[TokenOffset]); 915 } 916 else if (!strcmp (Token, "message")) 917 { 918 Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next); 919 if (!Token) 920 { 921 goto SyntaxError; 922 } 923 924 TokenOffset = Token - Gbl_MainTokenBuffer; 925 AcpiOsPrintf ("%s\n", &Gbl_CurrentLineBuffer[TokenOffset]); 926 } 927 else 928 { 929 PrError (ASL_ERROR, ASL_MSG_UNKNOWN_PRAGMA, 930 THIS_TOKEN_OFFSET (Token)); 931 return; 932 } 933 934 break; 935 936 case PR_DIRECTIVE_UNDEF: 937 938 DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID 939 "#undef: %s\n", Gbl_CurrentLineNumber, Token); 940 941 PrRemoveDefine (Token); 942 break; 943 944 case PR_DIRECTIVE_WARNING: 945 946 PrError (ASL_WARNING, ASL_MSG_WARNING_DIRECTIVE, 947 THIS_TOKEN_OFFSET (Token)); 948 949 Gbl_SourceLine = 0; 950 Gbl_NextError = Gbl_ErrorLog; 951 break; 952 953 default: 954 955 /* Should never get here */ 956 DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID 957 "Unrecognized directive: %u\n", 958 Gbl_CurrentLineNumber, Directive); 959 break; 960 } 961 962 return; 963 964 SyntaxError: 965 966 PrError (ASL_ERROR, ASL_MSG_DIRECTIVE_SYNTAX, 967 THIS_TOKEN_OFFSET (DirectiveToken)); 968 return; 969 } 970 971 972 /******************************************************************************* 973 * 974 * FUNCTION: PrGetNextLine, PrGetNextLineInit 975 * 976 * PARAMETERS: Handle - Open file handle for the source file 977 * 978 * RETURN: Status of the GetLine operation: 979 * AE_OK - Normal line, OK status 980 * ASL_IGNORE_LINE - Line is blank or part of a multi-line 981 * comment 982 * ASL_EOF - End-of-file reached 983 * 984 * DESCRIPTION: Get the next text line from the input file. Does not strip 985 * comments. 986 * 987 ******************************************************************************/ 988 989 #define PR_NORMAL_TEXT 0 990 #define PR_MULTI_LINE_COMMENT 1 991 #define PR_SINGLE_LINE_COMMENT 2 992 #define PR_QUOTED_STRING 3 993 994 static UINT8 AcpiGbl_LineScanState = PR_NORMAL_TEXT; 995 996 static void 997 PrGetNextLineInit ( 998 void) 999 { 1000 AcpiGbl_LineScanState = 0; 1001 } 1002 1003 static UINT32 1004 PrGetNextLine ( 1005 FILE *Handle) 1006 { 1007 UINT32 i; 1008 int c = 0; 1009 int PreviousChar; 1010 1011 1012 /* Always clear the global line buffer */ 1013 1014 memset (Gbl_CurrentLineBuffer, 0, Gbl_LineBufferSize); 1015 for (i = 0; ;) 1016 { 1017 /* 1018 * If line is too long, expand the line buffers. Also increases 1019 * Gbl_LineBufferSize. 1020 */ 1021 if (i >= Gbl_LineBufferSize) 1022 { 1023 UtExpandLineBuffers (); 1024 } 1025 1026 PreviousChar = c; 1027 c = getc (Handle); 1028 if (c == EOF) 1029 { 1030 /* 1031 * On EOF: If there is anything in the line buffer, terminate 1032 * it with a newline, and catch the EOF on the next call 1033 * to this function. 1034 */ 1035 if (i > 0) 1036 { 1037 Gbl_CurrentLineBuffer[i] = '\n'; 1038 return (AE_OK); 1039 } 1040 1041 return (ASL_EOF); 1042 } 1043 1044 /* Update state machine as necessary */ 1045 1046 switch (AcpiGbl_LineScanState) 1047 { 1048 case PR_NORMAL_TEXT: 1049 1050 /* Check for multi-line comment start */ 1051 1052 if ((PreviousChar == '/') && (c == '*')) 1053 { 1054 AcpiGbl_LineScanState = PR_MULTI_LINE_COMMENT; 1055 } 1056 1057 /* Check for single-line comment start */ 1058 1059 else if ((PreviousChar == '/') && (c == '/')) 1060 { 1061 AcpiGbl_LineScanState = PR_SINGLE_LINE_COMMENT; 1062 } 1063 1064 /* Check for quoted string start */ 1065 1066 else if (PreviousChar == '"') 1067 { 1068 AcpiGbl_LineScanState = PR_QUOTED_STRING; 1069 } 1070 break; 1071 1072 case PR_QUOTED_STRING: 1073 1074 if (PreviousChar == '"') 1075 { 1076 AcpiGbl_LineScanState = PR_NORMAL_TEXT; 1077 } 1078 break; 1079 1080 case PR_MULTI_LINE_COMMENT: 1081 1082 /* Check for multi-line comment end */ 1083 1084 if ((PreviousChar == '*') && (c == '/')) 1085 { 1086 AcpiGbl_LineScanState = PR_NORMAL_TEXT; 1087 } 1088 break; 1089 1090 case PR_SINGLE_LINE_COMMENT: /* Just ignore text until EOL */ 1091 default: 1092 break; 1093 } 1094 1095 /* Always copy the character into line buffer */ 1096 1097 Gbl_CurrentLineBuffer[i] = (char) c; 1098 i++; 1099 1100 /* Always exit on end-of-line */ 1101 1102 if (c == '\n') 1103 { 1104 /* Handle multi-line comments */ 1105 1106 if (AcpiGbl_LineScanState == PR_MULTI_LINE_COMMENT) 1107 { 1108 return (ASL_IGNORE_LINE); 1109 } 1110 1111 /* End of single-line comment */ 1112 1113 if (AcpiGbl_LineScanState == PR_SINGLE_LINE_COMMENT) 1114 { 1115 AcpiGbl_LineScanState = PR_NORMAL_TEXT; 1116 return (AE_OK); 1117 } 1118 1119 /* Blank line */ 1120 1121 if (i == 1) 1122 { 1123 return (ASL_IGNORE_LINE); 1124 } 1125 1126 return (AE_OK); 1127 } 1128 } 1129 } 1130 1131 1132 /******************************************************************************* 1133 * 1134 * FUNCTION: PrMatchDirective 1135 * 1136 * PARAMETERS: Directive - Pointer to directive name token 1137 * 1138 * RETURN: Index into command array, -1 if not found 1139 * 1140 * DESCRIPTION: Lookup the incoming directive in the known directives table. 1141 * 1142 ******************************************************************************/ 1143 1144 static int 1145 PrMatchDirective ( 1146 char *Directive) 1147 { 1148 int i; 1149 1150 1151 if (!Directive || Directive[0] == 0) 1152 { 1153 return (ASL_DIRECTIVE_NOT_FOUND); 1154 } 1155 1156 for (i = 0; Gbl_DirectiveInfo[i].Name; i++) 1157 { 1158 if (!strcmp (Gbl_DirectiveInfo[i].Name, Directive)) 1159 { 1160 return (i); 1161 } 1162 } 1163 1164 return (ASL_DIRECTIVE_NOT_FOUND); /* Command not recognized */ 1165 } 1166 1167 1168 /******************************************************************************* 1169 * 1170 * FUNCTION: PrPushDirective 1171 * 1172 * PARAMETERS: Directive - Encoded directive ID 1173 * Argument - String containing argument to the 1174 * directive 1175 * 1176 * RETURN: None 1177 * 1178 * DESCRIPTION: Push an item onto the directive stack. Used for processing 1179 * nested #if/#else type conditional compilation directives. 1180 * Specifically: Used on detection of #if/#ifdef/#ifndef to open 1181 * a block. 1182 * 1183 ******************************************************************************/ 1184 1185 static void 1186 PrPushDirective ( 1187 int Directive, 1188 char *Argument) 1189 { 1190 DIRECTIVE_INFO *Info; 1191 1192 1193 /* Allocate and populate a stack info item */ 1194 1195 Info = ACPI_ALLOCATE (sizeof (DIRECTIVE_INFO)); 1196 1197 Info->Next = Gbl_DirectiveStack; 1198 Info->Directive = Directive; 1199 Info->IgnoringThisCodeBlock = Gbl_IgnoringThisCodeBlock; 1200 strncpy (Info->Argument, Argument, MAX_ARGUMENT_LENGTH); 1201 1202 DbgPrint (ASL_DEBUG_OUTPUT, 1203 "Pr(%.4u) - [%u %s] %*s Pushed [#%s %s]: IgnoreFlag = %s\n", 1204 Gbl_CurrentLineNumber, Gbl_IfDepth, 1205 Gbl_IgnoringThisCodeBlock ? "I" : "E", 1206 Gbl_IfDepth * 4, " ", 1207 Gbl_DirectiveInfo[Directive].Name, 1208 Argument, Gbl_IgnoringThisCodeBlock ? "TRUE" : "FALSE"); 1209 1210 /* Push new item */ 1211 1212 Gbl_DirectiveStack = Info; 1213 Gbl_IfDepth++; 1214 } 1215 1216 1217 /******************************************************************************* 1218 * 1219 * FUNCTION: PrPopDirective 1220 * 1221 * PARAMETERS: None 1222 * 1223 * RETURN: Status. Error if the stack is empty. 1224 * 1225 * DESCRIPTION: Pop an item off the directive stack. Used for processing 1226 * nested #if/#else type conditional compilation directives. 1227 * Specifically: Used on detection of #elif and #endif to remove 1228 * the original #if/#ifdef/#ifndef from the stack and close 1229 * the block. 1230 * 1231 ******************************************************************************/ 1232 1233 static ACPI_STATUS 1234 PrPopDirective ( 1235 void) 1236 { 1237 DIRECTIVE_INFO *Info; 1238 1239 1240 /* Check for empty stack */ 1241 1242 Info = Gbl_DirectiveStack; 1243 if (!Info) 1244 { 1245 return (AE_ERROR); 1246 } 1247 1248 /* Pop one item, keep globals up-to-date */ 1249 1250 Gbl_IfDepth--; 1251 Gbl_IgnoringThisCodeBlock = Info->IgnoringThisCodeBlock; 1252 Gbl_DirectiveStack = Info->Next; 1253 1254 DbgPrint (ASL_DEBUG_OUTPUT, 1255 "Pr(%.4u) - [%u %s] %*s Popped [#%s %s]: IgnoreFlag now = %s\n", 1256 Gbl_CurrentLineNumber, Gbl_IfDepth, 1257 Gbl_IgnoringThisCodeBlock ? "I" : "E", 1258 Gbl_IfDepth * 4, " ", 1259 Gbl_DirectiveInfo[Info->Directive].Name, 1260 Info->Argument, Gbl_IgnoringThisCodeBlock ? "TRUE" : "FALSE"); 1261 1262 ACPI_FREE (Info); 1263 return (AE_OK); 1264 } 1265 1266 1267 /******************************************************************************* 1268 * 1269 * FUNCTION: PrDbgPrint 1270 * 1271 * PARAMETERS: Action - Action being performed 1272 * DirectiveName - Directive being processed 1273 * 1274 * RETURN: None 1275 * 1276 * DESCRIPTION: Special debug print for directive processing. 1277 * 1278 ******************************************************************************/ 1279 1280 static void 1281 PrDbgPrint ( 1282 char *Action, 1283 char *DirectiveName) 1284 { 1285 1286 DbgPrint (ASL_DEBUG_OUTPUT, "Pr(%.4u) - [%u %s] " 1287 "%*s %s #%s, IfDepth %u\n", 1288 Gbl_CurrentLineNumber, Gbl_IfDepth, 1289 Gbl_IgnoringThisCodeBlock ? "I" : "E", 1290 Gbl_IfDepth * 4, " ", 1291 Action, DirectiveName, Gbl_IfDepth); 1292 } 1293 1294 1295 /******************************************************************************* 1296 * 1297 * FUNCTION: PrDoIncludeFile 1298 * 1299 * PARAMETERS: Pathname - Name of the input file 1300 * 1301 * RETURN: None. 1302 * 1303 * DESCRIPTION: Open an include file, from #include. 1304 * 1305 ******************************************************************************/ 1306 1307 static void 1308 PrDoIncludeFile ( 1309 char *Pathname) 1310 { 1311 char *FullPathname; 1312 1313 1314 (void) PrOpenIncludeFile (Pathname, "r", &FullPathname); 1315 } 1316 1317 1318 /******************************************************************************* 1319 * 1320 * FUNCTION: PrDoIncludeBuffer 1321 * 1322 * PARAMETERS: Pathname - Name of the input binary file 1323 * BufferName - ACPI namepath of the buffer 1324 * 1325 * RETURN: None. 1326 * 1327 * DESCRIPTION: Create an ACPI buffer object from a binary file. The contents 1328 * of the file are emitted into the buffer object as ascii 1329 * hex data. From #includebuffer. 1330 * 1331 ******************************************************************************/ 1332 1333 static void 1334 PrDoIncludeBuffer ( 1335 char *Pathname, 1336 char *BufferName) 1337 { 1338 char *FullPathname; 1339 FILE *BinaryBufferFile; 1340 UINT32 i = 0; 1341 UINT8 c; 1342 1343 1344 BinaryBufferFile = PrOpenIncludeFile (Pathname, "rb", &FullPathname); 1345 if (!BinaryBufferFile) 1346 { 1347 return; 1348 } 1349 1350 /* Emit "Name (XXXX, Buffer() {" header */ 1351 1352 FlPrintFile (ASL_FILE_PREPROCESSOR, "Name (%s, Buffer()\n{", BufferName); 1353 1354 /* Dump the entire file in ascii hex format */ 1355 1356 while (fread (&c, 1, 1, BinaryBufferFile)) 1357 { 1358 if (!(i % 8)) 1359 { 1360 FlPrintFile (ASL_FILE_PREPROCESSOR, "\n ", c); 1361 } 1362 1363 FlPrintFile (ASL_FILE_PREPROCESSOR, " 0x%2.2X,", c); 1364 i++; 1365 } 1366 1367 DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID 1368 "#includebuffer: read %u bytes from %s\n", 1369 Gbl_CurrentLineNumber, i, FullPathname); 1370 1371 /* Close the Name() operator */ 1372 1373 FlPrintFile (ASL_FILE_PREPROCESSOR, "\n})\n", BufferName); 1374 fclose (BinaryBufferFile); 1375 } 1376