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