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