1/****************************************************************************** 2 * 3 * Module Name: aslsupport.l - Flex/lex scanner C support routines. 4 * NOTE: Included into aslcompile.l, not compiled by itself. 5 * 6 *****************************************************************************/ 7 8/* 9 * Copyright (C) 2000 - 2015, Intel Corp. 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions, and the following disclaimer, 17 * without modification. 18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 19 * substantially similar to the "NO WARRANTY" disclaimer below 20 * ("Disclaimer") and any redistribution must be conditioned upon 21 * including a substantially similar Disclaimer requirement for further 22 * binary redistribution. 23 * 3. Neither the names of the above-listed copyright holders nor the names 24 * of any contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * Alternatively, this software may be distributed under the terms of the 28 * GNU General Public License ("GPL") version 2 as published by the Free 29 * Software Foundation. 30 * 31 * NO WARRANTY 32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 42 * POSSIBILITY OF SUCH DAMAGES. 43 */ 44 45/* Configuration */ 46 47#define ASL_SPACES_PER_TAB 4 48 49#define ASL_NORMAL_CHAR 0 50#define ASL_ESCAPE_SEQUENCE 1 51#define ASL_OCTAL_CONSTANT 2 52#define ASL_HEX_CONSTANT 3 53 54 55/* File node - used for "Include" operator file stack */ 56 57typedef struct asl_file_node 58{ 59 FILE *File; 60 UINT32 CurrentLineNumber; 61 YY_BUFFER_STATE State; 62 char *Filename; 63 struct asl_file_node *Next; 64 65} ASL_FILE_NODE; 66 67/* File stack for the "Include" operator (NOT #include operator) */ 68 69ASL_FILE_NODE *Gbl_IncludeFileStack = NULL; 70 71 72/******************************************************************************* 73 * 74 * FUNCTION: AslParserCleanup 75 * 76 * Used to delete the current buffer 77 * 78 ******************************************************************************/ 79 80void 81AslParserCleanup ( 82 void) 83{ 84 85 yy_delete_buffer (YY_CURRENT_BUFFER); 86} 87 88 89/******************************************************************************* 90 * 91 * FUNCTION: AslDoLineDirective 92 * 93 * PARAMETERS: None. Uses input() to access current source code line 94 * 95 * RETURN: Updates global line number and filename 96 * 97 * DESCRIPTION: Handle #line directives emitted by the preprocessor. 98 * 99 * The #line directive is emitted by the preprocesser, and is used to 100 * pass through line numbers from the original source code file to the 101 * preprocessor output file (.i). This allows any compiler-generated 102 * error messages to be displayed with the correct line number. 103 * 104 ******************************************************************************/ 105 106static void 107AslDoLineDirective ( 108 void) 109{ 110 int c; 111 char *Token; 112 UINT32 LineNumber; 113 char *Filename; 114 UINT32 i; 115 116 117 /* Eat the entire line that contains the #line directive */ 118 119 Gbl_LineBufPtr = Gbl_CurrentLineBuffer; 120 121 while ((c = input()) != '\n' && c != EOF) 122 { 123 *Gbl_LineBufPtr = c; 124 Gbl_LineBufPtr++; 125 } 126 *Gbl_LineBufPtr = 0; 127 128 /* First argument is the actual line number */ 129 130 Token = strtok (Gbl_CurrentLineBuffer, " "); 131 if (!Token) 132 { 133 goto ResetAndExit; 134 } 135 136 /* First argument is the line number */ 137 138 LineNumber = (UINT32) UtDoConstant (Token); 139 140 /* Emit the appropriate number of newlines */ 141 142 Gbl_CurrentColumn = 0; 143 if (LineNumber > Gbl_CurrentLineNumber) 144 { 145 for (i = 0; i < (LineNumber - Gbl_CurrentLineNumber); i++) 146 { 147 FlWriteFile (ASL_FILE_SOURCE_OUTPUT, "\n", 1); 148 Gbl_CurrentColumn++; 149 } 150 } 151 152 FlSetLineNumber (LineNumber); 153 154 /* Second argument is the optional filename (in double quotes) */ 155 156 Token = strtok (NULL, " \""); 157 if (Token) 158 { 159 Filename = ACPI_ALLOCATE_ZEROED (strlen (Token) + 1); 160 strcpy (Filename, Token); 161 FlSetFilename (Filename); 162 } 163 164 /* Third argument is not supported at this time */ 165 166ResetAndExit: 167 168 /* Reset globals for a new line */ 169 170 Gbl_CurrentLineOffset += Gbl_CurrentColumn; 171 Gbl_CurrentColumn = 0; 172 Gbl_LineBufPtr = Gbl_CurrentLineBuffer; 173} 174 175 176/******************************************************************************* 177 * 178 * FUNCTION: AslPopInputFileStack 179 * 180 * PARAMETERS: None 181 * 182 * RETURN: 0 if a node was popped, -1 otherwise 183 * 184 * DESCRIPTION: Pop the top of the input file stack and point the parser to 185 * the saved parse buffer contained in the fnode. Also, set the 186 * global line counters to the saved values. This function is 187 * called when an include file reaches EOF. 188 * 189 ******************************************************************************/ 190 191int 192AslPopInputFileStack ( 193 void) 194{ 195 ASL_FILE_NODE *Fnode; 196 197 198 Fnode = Gbl_IncludeFileStack; 199 DbgPrint (ASL_PARSE_OUTPUT, 200 "\nPop InputFile Stack, Fnode %p\n\n", Fnode); 201 202 if (!Fnode) 203 { 204 return (-1); 205 } 206 207 /* Close the current include file */ 208 209 fclose (yyin); 210 211 /* Update the top-of-stack */ 212 213 Gbl_IncludeFileStack = Fnode->Next; 214 215 /* Reset global line counter and filename */ 216 217 Gbl_Files[ASL_FILE_INPUT].Filename = Fnode->Filename; 218 Gbl_CurrentLineNumber = Fnode->CurrentLineNumber; 219 220 /* Point the parser to the popped file */ 221 222 yy_delete_buffer (YY_CURRENT_BUFFER); 223 yy_switch_to_buffer (Fnode->State); 224 225 /* All done with this node */ 226 227 ACPI_FREE (Fnode); 228 return (0); 229} 230 231 232/******************************************************************************* 233 * 234 * FUNCTION: AslPushInputFileStack 235 * 236 * PARAMETERS: InputFile - Open file pointer 237 * Filename - Name of the file 238 * 239 * RETURN: None 240 * 241 * DESCRIPTION: Push the InputFile onto the file stack, and point the parser 242 * to this file. Called when an include file is successfully 243 * opened. 244 * 245 ******************************************************************************/ 246 247void 248AslPushInputFileStack ( 249 FILE *InputFile, 250 char *Filename) 251{ 252 ASL_FILE_NODE *Fnode; 253 YY_BUFFER_STATE State; 254 255 256 /* Save the current state in an Fnode */ 257 258 Fnode = UtLocalCalloc (sizeof (ASL_FILE_NODE)); 259 260 Fnode->File = yyin; 261 Fnode->Next = Gbl_IncludeFileStack; 262 Fnode->State = YY_CURRENT_BUFFER; 263 Fnode->Filename = Gbl_Files[ASL_FILE_INPUT].Filename; 264 Fnode->CurrentLineNumber = Gbl_CurrentLineNumber; 265 266 /* Push it on the stack */ 267 268 Gbl_IncludeFileStack = Fnode; 269 270 /* Point the parser to this file */ 271 272 State = yy_create_buffer (InputFile, YY_BUF_SIZE); 273 yy_switch_to_buffer (State); 274 275 DbgPrint (ASL_PARSE_OUTPUT, 276 "\nPush InputFile Stack, returning %p\n\n", InputFile); 277 278 /* Reset the global line count and filename */ 279 280 Gbl_Files[ASL_FILE_INPUT].Filename = 281 UtStringCacheCalloc (strlen (Filename) + 1); 282 283 strcpy (Gbl_Files[ASL_FILE_INPUT].Filename, Filename); 284 285 Gbl_CurrentLineNumber = 1; 286 yyin = InputFile; 287} 288 289 290/******************************************************************************* 291 * 292 * FUNCTION: AslResetCurrentLineBuffer 293 * 294 * PARAMETERS: None 295 * 296 * RETURN: None 297 * 298 * DESCRIPTION: Reset the Line Buffer to zero, increment global line numbers. 299 * 300 ******************************************************************************/ 301 302void 303AslResetCurrentLineBuffer ( 304 void) 305{ 306 307 if (Gbl_Files[ASL_FILE_SOURCE_OUTPUT].Handle) 308 { 309 FlWriteFile (ASL_FILE_SOURCE_OUTPUT, Gbl_CurrentLineBuffer, 310 Gbl_LineBufPtr - Gbl_CurrentLineBuffer); 311 } 312 313 Gbl_CurrentLineOffset += Gbl_CurrentColumn; 314 Gbl_CurrentColumn = 0; 315 316 Gbl_CurrentLineNumber++; 317 Gbl_LogicalLineNumber++; 318 Gbl_LineBufPtr = Gbl_CurrentLineBuffer; 319} 320 321 322/******************************************************************************* 323 * 324 * FUNCTION: AslInsertLineBuffer 325 * 326 * PARAMETERS: SourceChar - One char from the input ASL source file 327 * 328 * RETURN: None 329 * 330 * DESCRIPTION: Put one character of the source file into the temp line buffer 331 * 332 ******************************************************************************/ 333 334void 335AslInsertLineBuffer ( 336 int SourceChar) 337{ 338 UINT32 i; 339 UINT32 Count = 1; 340 341 342 if (SourceChar == EOF) 343 { 344 return; 345 } 346 347 Gbl_InputByteCount++; 348 349 /* Handle tabs. Convert to spaces */ 350 351 if (SourceChar == '\t') 352 { 353 SourceChar = ' '; 354 Count = ASL_SPACES_PER_TAB - 355 (Gbl_CurrentColumn & (ASL_SPACES_PER_TAB-1)); 356 } 357 358 for (i = 0; i < Count; i++) 359 { 360 Gbl_CurrentColumn++; 361 362 /* Insert the character into the line buffer */ 363 364 *Gbl_LineBufPtr = (UINT8) SourceChar; 365 Gbl_LineBufPtr++; 366 367 if (Gbl_LineBufPtr > 368 (Gbl_CurrentLineBuffer + (Gbl_LineBufferSize - 1))) 369 { 370#if 0 371 /* 372 * Warning if we have split a long source line. 373 * <Probably overkill> 374 */ 375 sprintf (MsgBuffer, "Max %u", Gbl_LineBufferSize); 376 AslCommonError (ASL_WARNING, ASL_MSG_LONG_LINE, 377 Gbl_CurrentLineNumber, Gbl_LogicalLineNumber, 378 Gbl_CurrentLineOffset, Gbl_CurrentColumn, 379 Gbl_Files[ASL_FILE_INPUT].Filename, MsgBuffer); 380#endif 381 382 AslResetCurrentLineBuffer (); 383 } 384 else if (SourceChar == '\n') 385 { 386 /* End of line */ 387 388 AslResetCurrentLineBuffer (); 389 } 390 } 391} 392 393 394/******************************************************************************* 395 * 396 * FUNCTION: count 397 * 398 * PARAMETERS: yytext - Contains the matched keyword. 399 * Type - Keyword/Character type: 400 * 0 = anything except a keyword 401 * 1 = pseudo-keywords 402 * 2 = non-executable ASL keywords 403 * 3 = executable ASL keywords 404 * 405 * RETURN: None 406 * 407 * DESCRIPTION: Count keywords and put them into the line buffer 408 * 409 ******************************************************************************/ 410 411static void 412count ( 413 int Type) 414{ 415 int i; 416 417 418 switch (Type) 419 { 420 case 2: 421 422 TotalKeywords++; 423 TotalNamedObjects++; 424 break; 425 426 case 3: 427 428 TotalKeywords++; 429 TotalExecutableOpcodes++; 430 break; 431 432 default: 433 434 break; 435 } 436 437 for (i = 0; (yytext[i] != 0) && (yytext[i] != EOF); i++) 438 { 439 AslInsertLineBuffer (yytext[i]); 440 *Gbl_LineBufPtr = 0; 441 } 442} 443 444 445/******************************************************************************* 446 * 447 * FUNCTION: AslDoComment 448 * 449 * PARAMETERS: none 450 * 451 * RETURN: none 452 * 453 * DESCRIPTION: Process a standard comment. 454 * 455 ******************************************************************************/ 456 457static char 458AslDoComment ( 459 void) 460{ 461 int c; 462 int c1 = 0; 463 464 465 AslInsertLineBuffer ('/'); 466 AslInsertLineBuffer ('*'); 467 468loop: 469 470 /* Eat chars until end-of-comment */ 471 472 while (((c = input ()) != '*') && (c != EOF)) 473 { 474 AslInsertLineBuffer (c); 475 c1 = c; 476 } 477 478 if (c == EOF) 479 { 480 goto EarlyEOF; 481 } 482 483 /* 484 * Check for nested comment -- can help catch cases where a previous 485 * comment was accidently left unterminated 486 */ 487 if ((c1 == '/') && (c == '*')) 488 { 489 AslCommonError (ASL_WARNING, ASL_MSG_NESTED_COMMENT, 490 Gbl_CurrentLineNumber, Gbl_LogicalLineNumber, 491 Gbl_InputByteCount, Gbl_CurrentColumn, 492 Gbl_Files[ASL_FILE_INPUT].Filename, NULL); 493 } 494 495 /* Comment is closed only if the NEXT character is a slash */ 496 497 AslInsertLineBuffer (c); 498 499 if (((c1 = input ()) != '/') && (c1 != EOF)) 500 { 501 unput(c1); 502 goto loop; 503 } 504 505 if (c1 == EOF) 506 { 507 goto EarlyEOF; 508 } 509 510 AslInsertLineBuffer (c1); 511 return (TRUE); 512 513 514EarlyEOF: 515 /* 516 * Premature End-Of-File 517 */ 518 AslCommonError (ASL_ERROR, ASL_MSG_EARLY_EOF, 519 Gbl_CurrentLineNumber, Gbl_LogicalLineNumber, 520 Gbl_CurrentLineOffset, Gbl_CurrentColumn, 521 Gbl_Files[ASL_FILE_INPUT].Filename, NULL); 522 return (FALSE); 523} 524 525 526/******************************************************************************* 527 * 528 * FUNCTION: AslDoCommentType2 529 * 530 * PARAMETERS: none 531 * 532 * RETURN: none 533 * 534 * DESCRIPTION: Process a new "//" comment. 535 * 536 ******************************************************************************/ 537 538static char 539AslDoCommentType2 ( 540 void) 541{ 542 int c; 543 544 545 AslInsertLineBuffer ('/'); 546 AslInsertLineBuffer ('/'); 547 548 while (((c = input ()) != '\n') && (c != EOF)) 549 { 550 AslInsertLineBuffer (c); 551 } 552 553 if (c == EOF) 554 { 555 /* End of file is OK, change to newline. Let parser detect EOF later */ 556 557 c = '\n'; 558 } 559 560 AslInsertLineBuffer (c); 561 return (TRUE); 562} 563 564 565/******************************************************************************* 566 * 567 * FUNCTION: AslDoStringLiteral 568 * 569 * PARAMETERS: none 570 * 571 * RETURN: none 572 * 573 * DESCRIPTION: Process a string literal (surrounded by quotes) 574 * 575 ******************************************************************************/ 576 577static char 578AslDoStringLiteral ( 579 void) 580{ 581 char *StringBuffer = MsgBuffer; 582 char *EndBuffer = MsgBuffer + ASL_MSG_BUFFER_SIZE; 583 char *CleanString; 584 int StringChar; 585 UINT32 State = ASL_NORMAL_CHAR; 586 UINT32 i = 0; 587 UINT8 Digit; 588 char ConvertBuffer[4]; 589 590 591 /* 592 * Eat chars until end-of-literal. 593 * NOTE: Put back the original surrounding quotes into the 594 * source line buffer. 595 */ 596 AslInsertLineBuffer ('\"'); 597 while ((StringChar = input()) != EOF) 598 { 599 AslInsertLineBuffer (StringChar); 600 601DoCharacter: 602 switch (State) 603 { 604 case ASL_NORMAL_CHAR: 605 606 switch (StringChar) 607 { 608 case '\\': 609 /* 610 * Special handling for backslash-escape sequence. We will 611 * toss the backslash and translate the escape char(s). 612 */ 613 State = ASL_ESCAPE_SEQUENCE; 614 continue; 615 616 case '\"': 617 618 /* String terminator */ 619 620 goto CompletedString; 621 622 default: 623 624 break; 625 } 626 break; 627 628 629 case ASL_ESCAPE_SEQUENCE: 630 631 State = ASL_NORMAL_CHAR; 632 switch (StringChar) 633 { 634 case 'a': 635 636 StringChar = 0x07; /* BELL */ 637 break; 638 639 case 'b': 640 641 StringChar = 0x08; /* BACKSPACE */ 642 break; 643 644 case 'f': 645 646 StringChar = 0x0C; /* FORMFEED */ 647 break; 648 649 case 'n': 650 651 StringChar = 0x0A; /* LINEFEED */ 652 break; 653 654 case 'r': 655 656 StringChar = 0x0D; /* CARRIAGE RETURN*/ 657 break; 658 659 case 't': 660 661 StringChar = 0x09; /* HORIZONTAL TAB */ 662 break; 663 664 case 'v': 665 666 StringChar = 0x0B; /* VERTICAL TAB */ 667 break; 668 669 case 'x': 670 671 State = ASL_HEX_CONSTANT; 672 i = 0; 673 continue; 674 675 case '\'': /* Single Quote */ 676 case '\"': /* Double Quote */ 677 case '\\': /* Backslash */ 678 679 break; 680 681 default: 682 683 /* Check for an octal digit (0-7) */ 684 685 if (ACPI_IS_OCTAL_DIGIT (StringChar)) 686 { 687 State = ASL_OCTAL_CONSTANT; 688 ConvertBuffer[0] = StringChar; 689 i = 1; 690 continue; 691 } 692 693 /* Unknown escape sequence issue warning, but use the character */ 694 695 AslCommonError (ASL_WARNING, ASL_MSG_INVALID_ESCAPE, 696 Gbl_CurrentLineNumber, Gbl_LogicalLineNumber, 697 Gbl_CurrentLineOffset, Gbl_CurrentColumn, 698 Gbl_Files[ASL_FILE_INPUT].Filename, NULL); 699 break; 700 } 701 break; 702 703 704 case ASL_OCTAL_CONSTANT: 705 706 /* Up to three octal digits allowed */ 707 708 if (!ACPI_IS_OCTAL_DIGIT (StringChar) || 709 (i > 2)) 710 { 711 /* 712 * Reached end of the constant. Convert the assembled ASCII 713 * string and resume processing of the next character 714 */ 715 ConvertBuffer[i] = 0; 716 Digit = (UINT8) ACPI_STRTOUL (ConvertBuffer, NULL, 8); 717 718 /* Check for NULL or non-ascii character (ignore if so) */ 719 720 if ((Digit == 0) || (Digit > ACPI_ASCII_MAX)) 721 { 722 AslCommonError (ASL_WARNING, ASL_MSG_INVALID_STRING, 723 Gbl_CurrentLineNumber, Gbl_LogicalLineNumber, 724 Gbl_CurrentLineOffset, Gbl_CurrentColumn, 725 Gbl_Files[ASL_FILE_INPUT].Filename, NULL); 726 } 727 else 728 { 729 *StringBuffer = (char) Digit; 730 StringBuffer++; 731 if (StringBuffer >= EndBuffer) 732 { 733 goto BufferOverflow; 734 } 735 } 736 737 State = ASL_NORMAL_CHAR; 738 goto DoCharacter; 739 break; 740 } 741 742 /* Append another digit of the constant */ 743 744 ConvertBuffer[i] = StringChar; 745 i++; 746 continue; 747 748 case ASL_HEX_CONSTANT: 749 750 /* Up to two hex digits allowed */ 751 752 if (!ACPI_IS_XDIGIT (StringChar) || 753 (i > 1)) 754 { 755 /* 756 * Reached end of the constant. Convert the assembled ASCII 757 * string and resume processing of the next character 758 */ 759 ConvertBuffer[i] = 0; 760 Digit = (UINT8) ACPI_STRTOUL (ConvertBuffer, NULL, 16); 761 762 /* Check for NULL or non-ascii character (ignore if so) */ 763 764 if ((Digit == 0) || (Digit > ACPI_ASCII_MAX)) 765 { 766 AslCommonError (ASL_WARNING, ASL_MSG_INVALID_STRING, 767 Gbl_CurrentLineNumber, Gbl_LogicalLineNumber, 768 Gbl_CurrentLineOffset, Gbl_CurrentColumn, 769 Gbl_Files[ASL_FILE_INPUT].Filename, NULL); 770 } 771 else 772 { 773 *StringBuffer = (char) Digit; 774 StringBuffer++; 775 if (StringBuffer >= EndBuffer) 776 { 777 goto BufferOverflow; 778 } 779 } 780 781 State = ASL_NORMAL_CHAR; 782 goto DoCharacter; 783 break; 784 } 785 786 /* Append another digit of the constant */ 787 788 ConvertBuffer[i] = StringChar; 789 i++; 790 continue; 791 792 default: 793 794 break; 795 } 796 797 /* Save the finished character */ 798 799 *StringBuffer = StringChar; 800 StringBuffer++; 801 if (StringBuffer >= EndBuffer) 802 { 803 goto BufferOverflow; 804 } 805 } 806 807 /* 808 * Premature End-Of-File 809 */ 810 AslCommonError (ASL_ERROR, ASL_MSG_EARLY_EOF, 811 Gbl_CurrentLineNumber, Gbl_LogicalLineNumber, 812 Gbl_CurrentLineOffset, Gbl_CurrentColumn, 813 Gbl_Files[ASL_FILE_INPUT].Filename, NULL); 814 return (FALSE); 815 816 817CompletedString: 818 /* 819 * Null terminate the input string and copy string to a new buffer 820 */ 821 *StringBuffer = 0; 822 823 CleanString = UtStringCacheCalloc (strlen (MsgBuffer) + 1); 824 if (!CleanString) 825 { 826 AslCommonError (ASL_ERROR, ASL_MSG_MEMORY_ALLOCATION, 827 Gbl_CurrentLineNumber, Gbl_LogicalLineNumber, 828 Gbl_CurrentLineOffset, Gbl_CurrentColumn, 829 Gbl_Files[ASL_FILE_INPUT].Filename, NULL); 830 return (FALSE); 831 } 832 833 ACPI_STRCPY (CleanString, MsgBuffer); 834 AslCompilerlval.s = CleanString; 835 return (TRUE); 836 837 838BufferOverflow: 839 840 /* Literal was too long */ 841 842 AslCommonError (ASL_ERROR, ASL_MSG_STRING_LENGTH, 843 Gbl_CurrentLineNumber, Gbl_LogicalLineNumber, 844 Gbl_CurrentLineOffset, Gbl_CurrentColumn, 845 Gbl_Files[ASL_FILE_INPUT].Filename, "Max length 4096"); 846 return (FALSE); 847} 848