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