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 - 2013, 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 TotalKeywords++; 399 TotalNamedObjects++; 400 break; 401 402 case 3: 403 TotalKeywords++; 404 TotalExecutableOpcodes++; 405 break; 406 407 default: 408 break; 409 } 410 411 for (i = 0; (yytext[i] != 0) && (yytext[i] != EOF); i++) 412 { 413 AslInsertLineBuffer (yytext[i]); 414 *Gbl_LineBufPtr = 0; 415 } 416 } 417 418 419 /******************************************************************************* 420 * 421 * FUNCTION: AslDoComment 422 * 423 * PARAMETERS: none 424 * 425 * RETURN: none 426 * 427 * DESCRIPTION: Process a standard comment. 428 * 429 ******************************************************************************/ 430 431 static char 432 AslDoComment ( 433 void) 434 { 435 int c; 436 int c1 = 0; 437 438 439 AslInsertLineBuffer ('/'); 440 AslInsertLineBuffer ('*'); 441 442 loop: 443 444 /* Eat chars until end-of-comment */ 445 446 while ((c = input()) != '*' && c != EOF) 447 { 448 AslInsertLineBuffer (c); 449 c1 = c; 450 } 451 452 if (c == EOF) 453 { 454 goto EarlyEOF; 455 } 456 457 /* 458 * Check for nested comment -- can help catch cases where a previous 459 * comment was accidently left unterminated 460 */ 461 if ((c1 == '/') && (c == '*')) 462 { 463 AslCommonError (ASL_WARNING, ASL_MSG_NESTED_COMMENT, 464 Gbl_CurrentLineNumber, Gbl_LogicalLineNumber, 465 Gbl_InputByteCount, Gbl_CurrentColumn, 466 Gbl_Files[ASL_FILE_INPUT].Filename, NULL); 467 } 468 469 /* Comment is closed only if the NEXT character is a slash */ 470 471 AslInsertLineBuffer (c); 472 473 if ((c1 = input()) != '/' && c1 != EOF) 474 { 475 unput(c1); 476 goto loop; 477 } 478 479 if (c1 == EOF) 480 { 481 goto EarlyEOF; 482 } 483 484 AslInsertLineBuffer (c1); 485 return (TRUE); 486 487 488 EarlyEOF: 489 /* 490 * Premature End-Of-File 491 */ 492 AslCommonError (ASL_ERROR, ASL_MSG_EARLY_EOF, 493 Gbl_CurrentLineNumber, Gbl_LogicalLineNumber, 494 Gbl_CurrentLineOffset, Gbl_CurrentColumn, 495 Gbl_Files[ASL_FILE_INPUT].Filename, NULL); 496 return (FALSE); 497 } 498 499 500 /******************************************************************************* 501 * 502 * FUNCTION: AslDoCommentType2 503 * 504 * PARAMETERS: none 505 * 506 * RETURN: none 507 * 508 * DESCRIPTION: Process a new "//" comment. 509 * 510 ******************************************************************************/ 511 512 static char 513 AslDoCommentType2 ( 514 void) 515 { 516 int c; 517 518 519 AslInsertLineBuffer ('/'); 520 AslInsertLineBuffer ('/'); 521 522 while ((c = input()) != '\n' && c != EOF) 523 { 524 AslInsertLineBuffer (c); 525 } 526 527 if (c == EOF) 528 { 529 /* End of file is OK, change to newline. Let parser detect EOF later */ 530 531 c = '\n'; 532 } 533 534 AslInsertLineBuffer (c); 535 return (TRUE); 536 } 537 538 539 /******************************************************************************* 540 * 541 * FUNCTION: AslDoStringLiteral 542 * 543 * PARAMETERS: none 544 * 545 * RETURN: none 546 * 547 * DESCRIPTION: Process a string literal (surrounded by quotes) 548 * 549 ******************************************************************************/ 550 551 static char 552 AslDoStringLiteral ( 553 void) 554 { 555 char *StringBuffer = MsgBuffer; 556 char *EndBuffer = MsgBuffer + ASL_MSG_BUFFER_SIZE; 557 char *CleanString; 558 int StringChar; 559 UINT32 State = ASL_NORMAL_CHAR; 560 UINT32 i = 0; 561 UINT8 Digit; 562 char ConvertBuffer[4]; 563 564 565 /* 566 * Eat chars until end-of-literal. 567 * NOTE: Put back the original surrounding quotes into the 568 * source line buffer. 569 */ 570 AslInsertLineBuffer ('\"'); 571 while ((StringChar = input()) != EOF) 572 { 573 AslInsertLineBuffer (StringChar); 574 575 DoCharacter: 576 switch (State) 577 { 578 case ASL_NORMAL_CHAR: 579 580 switch (StringChar) 581 { 582 case '\\': 583 /* 584 * Special handling for backslash-escape sequence. We will 585 * toss the backslash and translate the escape char(s). 586 */ 587 State = ASL_ESCAPE_SEQUENCE; 588 continue; 589 590 case '\"': 591 592 /* String terminator */ 593 594 goto CompletedString; 595 596 default: 597 break; 598 } 599 break; 600 601 602 case ASL_ESCAPE_SEQUENCE: 603 604 State = ASL_NORMAL_CHAR; 605 switch (StringChar) 606 { 607 case 'a': 608 StringChar = 0x07; /* BELL */ 609 break; 610 611 case 'b': 612 StringChar = 0x08; /* BACKSPACE */ 613 break; 614 615 case 'f': 616 StringChar = 0x0C; /* FORMFEED */ 617 break; 618 619 case 'n': 620 StringChar = 0x0A; /* LINEFEED */ 621 break; 622 623 case 'r': 624 StringChar = 0x0D; /* CARRIAGE RETURN*/ 625 break; 626 627 case 't': 628 StringChar = 0x09; /* HORIZONTAL TAB */ 629 break; 630 631 case 'v': 632 StringChar = 0x0B; /* VERTICAL TAB */ 633 break; 634 635 case 'x': 636 State = ASL_HEX_CONSTANT; 637 i = 0; 638 continue; 639 640 case '\'': /* Single Quote */ 641 case '\"': /* Double Quote */ 642 case '\\': /* Backslash */ 643 break; 644 645 default: 646 647 /* Check for an octal digit (0-7) */ 648 649 if (ACPI_IS_OCTAL_DIGIT (StringChar)) 650 { 651 State = ASL_OCTAL_CONSTANT; 652 ConvertBuffer[0] = StringChar; 653 i = 1; 654 continue; 655 } 656 657 /* Unknown escape sequence issue warning, but use the character */ 658 659 AslCommonError (ASL_WARNING, ASL_MSG_INVALID_ESCAPE, 660 Gbl_CurrentLineNumber, Gbl_LogicalLineNumber, 661 Gbl_CurrentLineOffset, Gbl_CurrentColumn, 662 Gbl_Files[ASL_FILE_INPUT].Filename, NULL); 663 break; 664 } 665 break; 666 667 668 case ASL_OCTAL_CONSTANT: 669 670 /* Up to three octal digits allowed */ 671 672 if (!ACPI_IS_OCTAL_DIGIT (StringChar) || 673 (i > 2)) 674 { 675 /* 676 * Reached end of the constant. Convert the assembled ASCII 677 * string and resume processing of the next character 678 */ 679 ConvertBuffer[i] = 0; 680 Digit = (UINT8) ACPI_STRTOUL (ConvertBuffer, NULL, 8); 681 682 /* Check for NULL or non-ascii character (ignore if so) */ 683 684 if ((Digit == 0) || (Digit > ACPI_ASCII_MAX)) 685 { 686 AslCommonError (ASL_WARNING, ASL_MSG_INVALID_STRING, 687 Gbl_CurrentLineNumber, Gbl_LogicalLineNumber, 688 Gbl_CurrentLineOffset, Gbl_CurrentColumn, 689 Gbl_Files[ASL_FILE_INPUT].Filename, NULL); 690 } 691 else 692 { 693 *StringBuffer = (char) Digit; 694 StringBuffer++; 695 if (StringBuffer >= EndBuffer) 696 { 697 goto BufferOverflow; 698 } 699 } 700 701 State = ASL_NORMAL_CHAR; 702 goto DoCharacter; 703 break; 704 } 705 706 /* Append another digit of the constant */ 707 708 ConvertBuffer[i] = StringChar; 709 i++; 710 continue; 711 712 713 case ASL_HEX_CONSTANT: 714 715 /* Up to two hex digits allowed */ 716 717 if (!ACPI_IS_XDIGIT (StringChar) || 718 (i > 1)) 719 { 720 /* 721 * Reached end of the constant. Convert the assembled ASCII 722 * string and resume processing of the next character 723 */ 724 ConvertBuffer[i] = 0; 725 Digit = (UINT8) ACPI_STRTOUL (ConvertBuffer, NULL, 16); 726 727 /* Check for NULL or non-ascii character (ignore if so) */ 728 729 if ((Digit == 0) || (Digit > ACPI_ASCII_MAX)) 730 { 731 AslCommonError (ASL_WARNING, ASL_MSG_INVALID_STRING, 732 Gbl_CurrentLineNumber, Gbl_LogicalLineNumber, 733 Gbl_CurrentLineOffset, Gbl_CurrentColumn, 734 Gbl_Files[ASL_FILE_INPUT].Filename, NULL); 735 } 736 else 737 { 738 *StringBuffer = (char) Digit; 739 StringBuffer++; 740 if (StringBuffer >= EndBuffer) 741 { 742 goto BufferOverflow; 743 } 744 } 745 746 State = ASL_NORMAL_CHAR; 747 goto DoCharacter; 748 break; 749 } 750 751 /* Append another digit of the constant */ 752 753 ConvertBuffer[i] = StringChar; 754 i++; 755 continue; 756 757 default: 758 break; 759 } 760 761 /* Save the finished character */ 762 763 *StringBuffer = StringChar; 764 StringBuffer++; 765 if (StringBuffer >= EndBuffer) 766 { 767 goto BufferOverflow; 768 } 769 } 770 771 /* 772 * Premature End-Of-File 773 */ 774 AslCommonError (ASL_ERROR, ASL_MSG_EARLY_EOF, 775 Gbl_CurrentLineNumber, Gbl_LogicalLineNumber, 776 Gbl_CurrentLineOffset, Gbl_CurrentColumn, 777 Gbl_Files[ASL_FILE_INPUT].Filename, NULL); 778 return (FALSE); 779 780 781 CompletedString: 782 /* 783 * Null terminate the input string and copy string to a new buffer 784 */ 785 *StringBuffer = 0; 786 787 CleanString = UtGetStringBuffer (strlen (MsgBuffer) + 1); 788 if (!CleanString) 789 { 790 AslCommonError (ASL_ERROR, ASL_MSG_MEMORY_ALLOCATION, 791 Gbl_CurrentLineNumber, Gbl_LogicalLineNumber, 792 Gbl_CurrentLineOffset, Gbl_CurrentColumn, 793 Gbl_Files[ASL_FILE_INPUT].Filename, NULL); 794 return (FALSE); 795 } 796 797 ACPI_STRCPY (CleanString, MsgBuffer); 798 AslCompilerlval.s = CleanString; 799 return (TRUE); 800 801 802 BufferOverflow: 803 804 /* Literal was too long */ 805 806 AslCommonError (ASL_ERROR, ASL_MSG_STRING_LENGTH, 807 Gbl_CurrentLineNumber, Gbl_LogicalLineNumber, 808 Gbl_CurrentLineOffset, Gbl_CurrentColumn, 809 Gbl_Files[ASL_FILE_INPUT].Filename, "Max length 4096"); 810 return (FALSE); 811 } 812