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