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