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