1 2 /****************************************************************************** 3 * 4 * Module Name: aslerror - Error handling and statistics 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 #define ASL_EXCEPTIONS 46 #include <contrib/dev/acpica/compiler/aslcompiler.h> 47 48 #define _COMPONENT ACPI_COMPILER 49 ACPI_MODULE_NAME ("aslerror") 50 51 /* Local prototypes */ 52 53 static void 54 AeAddToErrorLog ( 55 ASL_ERROR_MSG *Enode); 56 57 58 /******************************************************************************* 59 * 60 * FUNCTION: AeClearErrorLog 61 * 62 * PARAMETERS: None 63 * 64 * RETURN: None 65 * 66 * DESCRIPTION: Empty the error list 67 * 68 ******************************************************************************/ 69 70 void 71 AeClearErrorLog ( 72 void) 73 { 74 ASL_ERROR_MSG *Enode = Gbl_ErrorLog; 75 ASL_ERROR_MSG *Next; 76 77 /* Walk the error node list */ 78 79 while (Enode) 80 { 81 Next = Enode->Next; 82 ACPI_FREE (Enode); 83 Enode = Next; 84 } 85 86 Gbl_ErrorLog = NULL; 87 } 88 89 90 /******************************************************************************* 91 * 92 * FUNCTION: AeAddToErrorLog 93 * 94 * PARAMETERS: Enode - An error node to add to the log 95 * 96 * RETURN: None 97 * 98 * DESCRIPTION: Add a new error node to the error log. The error log is 99 * ordered by the "logical" line number (cumulative line number 100 * including all include files.) 101 * 102 ******************************************************************************/ 103 104 static void 105 AeAddToErrorLog ( 106 ASL_ERROR_MSG *Enode) 107 { 108 ASL_ERROR_MSG *Next; 109 ASL_ERROR_MSG *Prev; 110 111 112 /* If Gbl_ErrorLog is null, this is the first error node */ 113 114 if (!Gbl_ErrorLog) 115 { 116 Gbl_ErrorLog = Enode; 117 return; 118 } 119 120 /* 121 * Walk error list until we find a line number greater than ours. 122 * List is sorted according to line number. 123 */ 124 Prev = NULL; 125 Next = Gbl_ErrorLog; 126 127 while ((Next) && 128 (Next->LogicalLineNumber <= Enode->LogicalLineNumber)) 129 { 130 Prev = Next; 131 Next = Next->Next; 132 } 133 134 /* Found our place in the list */ 135 136 Enode->Next = Next; 137 138 if (Prev) 139 { 140 Prev->Next = Enode; 141 } 142 else 143 { 144 Gbl_ErrorLog = Enode; 145 } 146 } 147 148 149 /******************************************************************************* 150 * 151 * FUNCTION: AePrintException 152 * 153 * PARAMETERS: FileId - ID of output file 154 * Enode - Error node to print 155 * Header - Additional text before each message 156 * 157 * RETURN: None 158 * 159 * DESCRIPTION: Print the contents of an error node. 160 * 161 * NOTE: We don't use the FlxxxFile I/O functions here because on error 162 * they abort the compiler and call this function! Since we 163 * are reporting errors here, we ignore most output errors and 164 * just try to get out as much as we can. 165 * 166 ******************************************************************************/ 167 168 void 169 AePrintException ( 170 UINT32 FileId, 171 ASL_ERROR_MSG *Enode, 172 char *Header) 173 { 174 UINT8 SourceByte; 175 int Actual; 176 size_t RActual; 177 UINT32 MsgLength; 178 char *MainMessage; 179 char *ExtraMessage; 180 UINT32 SourceColumn; 181 UINT32 ErrorColumn; 182 FILE *OutputFile; 183 FILE *SourceFile = NULL; 184 long FileSize; 185 BOOLEAN PrematureEOF = FALSE; 186 UINT32 Total = 0; 187 188 189 if (Gbl_NoErrors) 190 { 191 return; 192 } 193 194 /* 195 * Only listing files have a header, and remarks/optimizations 196 * are always output 197 */ 198 if (!Header) 199 { 200 /* Ignore remarks if requested */ 201 202 switch (Enode->Level) 203 { 204 case ASL_REMARK: 205 if (!Gbl_DisplayRemarks) 206 { 207 return; 208 } 209 break; 210 211 case ASL_OPTIMIZATION: 212 if (!Gbl_DisplayOptimizations) 213 { 214 return; 215 } 216 break; 217 218 default: 219 break; 220 } 221 } 222 223 /* Get the file handles */ 224 225 OutputFile = Gbl_Files[FileId].Handle; 226 227 228 if (!Enode->SourceLine) 229 { 230 /* Use the merged header/source file if present, otherwise use input file */ 231 232 SourceFile = Gbl_Files[ASL_FILE_SOURCE_OUTPUT].Handle; 233 if (!SourceFile) 234 { 235 SourceFile = Gbl_Files[ASL_FILE_INPUT].Handle; 236 } 237 238 if (SourceFile) 239 { 240 /* Determine if the error occurred at source file EOF */ 241 242 fseek (SourceFile, 0, SEEK_END); 243 FileSize = ftell (SourceFile); 244 245 if ((long) Enode->LogicalByteOffset >= FileSize) 246 { 247 PrematureEOF = TRUE; 248 } 249 } 250 } 251 252 if (Header) 253 { 254 fprintf (OutputFile, "%s", Header); 255 } 256 257 /* Print filename and line number if present and valid */ 258 259 if (Enode->Filename) 260 { 261 if (Gbl_VerboseErrors) 262 { 263 fprintf (OutputFile, "%-8s", Enode->Filename); 264 265 if (Enode->LineNumber) 266 { 267 if (Enode->SourceLine) 268 { 269 fprintf (OutputFile, " %6u: %s", 270 Enode->LineNumber, Enode->SourceLine); 271 } 272 else 273 { 274 fprintf (OutputFile, " %6u: ", Enode->LineNumber); 275 276 /* 277 * If not at EOF, get the corresponding source code line and 278 * display it. Don't attempt this if we have a premature EOF 279 * condition. 280 */ 281 if (!PrematureEOF) 282 { 283 /* 284 * Seek to the offset in the combined source file, read 285 * the source line, and write it to the output. 286 */ 287 Actual = fseek (SourceFile, (long) Enode->LogicalByteOffset, 288 (int) SEEK_SET); 289 if (Actual) 290 { 291 fprintf (OutputFile, 292 "[*** iASL: Seek error on source code temp file %s ***]", 293 Gbl_Files[ASL_FILE_SOURCE_OUTPUT].Filename); 294 } 295 else 296 { 297 RActual = fread (&SourceByte, 1, 1, SourceFile); 298 if (!RActual) 299 { 300 fprintf (OutputFile, 301 "[*** iASL: Read error on source code temp file %s ***]", 302 Gbl_Files[ASL_FILE_SOURCE_OUTPUT].Filename); 303 } 304 else 305 { 306 while (RActual && SourceByte && (SourceByte != '\n') && (Total < 256)) 307 { 308 fwrite (&SourceByte, 1, 1, OutputFile); 309 RActual = fread (&SourceByte, 1, 1, SourceFile); 310 Total++; 311 } 312 313 if (Total >= 256) 314 { 315 fprintf (OutputFile, 316 "\n[*** iASL: Long input line, an error occurred at column %u ***]", 317 Enode->Column); 318 } 319 } 320 } 321 } 322 323 fprintf (OutputFile, "\n"); 324 } 325 } 326 } 327 else 328 { 329 /* 330 * Less verbose version of the error message, enabled via the 331 * -vi switch. The format is compatible with MS Visual Studio. 332 */ 333 fprintf (OutputFile, "%s", Enode->Filename); 334 335 if (Enode->LineNumber) 336 { 337 fprintf (OutputFile, "(%u) : ", 338 Enode->LineNumber); 339 } 340 } 341 } 342 343 /* NULL message ID, just print the raw message */ 344 345 if (Enode->MessageId == 0) 346 { 347 fprintf (OutputFile, "%s\n", Enode->Message); 348 } 349 else 350 { 351 /* Decode the message ID */ 352 353 if (Gbl_VerboseErrors) 354 { 355 fprintf (OutputFile, "%s %4.4d -", 356 AslErrorLevel[Enode->Level], 357 Enode->MessageId + ((Enode->Level+1) * 1000)); 358 } 359 else /* IDE case */ 360 { 361 fprintf (OutputFile, "%s %4.4d:", 362 AslErrorLevelIde[Enode->Level], 363 Enode->MessageId + ((Enode->Level+1) * 1000)); 364 } 365 366 MainMessage = AslMessages[Enode->MessageId]; 367 ExtraMessage = Enode->Message; 368 369 if (Enode->LineNumber) 370 { 371 /* Main message: try to use string from AslMessages first */ 372 373 if (!MainMessage) 374 { 375 MainMessage = ""; 376 } 377 378 MsgLength = strlen (MainMessage); 379 if (MsgLength == 0) 380 { 381 /* Use the secondary/extra message as main message */ 382 383 MainMessage = Enode->Message; 384 if (!MainMessage) 385 { 386 MainMessage = ""; 387 } 388 389 MsgLength = strlen (MainMessage); 390 ExtraMessage = NULL; 391 } 392 393 if (Gbl_VerboseErrors && !PrematureEOF) 394 { 395 if (Total >= 256) 396 { 397 fprintf (OutputFile, " %s", 398 MainMessage); 399 } 400 else 401 { 402 SourceColumn = Enode->Column + Enode->FilenameLength + 6 + 2; 403 ErrorColumn = ASL_ERROR_LEVEL_LENGTH + 5 + 2 + 1; 404 405 if ((MsgLength + ErrorColumn) < (SourceColumn - 1)) 406 { 407 fprintf (OutputFile, "%*s%s", 408 (int) ((SourceColumn - 1) - ErrorColumn), 409 MainMessage, " ^ "); 410 } 411 else 412 { 413 fprintf (OutputFile, "%*s %s", 414 (int) ((SourceColumn - ErrorColumn) + 1), "^", 415 MainMessage); 416 } 417 } 418 } 419 else 420 { 421 fprintf (OutputFile, " %s", MainMessage); 422 } 423 424 /* Print the extra info message if present */ 425 426 if (ExtraMessage) 427 { 428 fprintf (OutputFile, " (%s)", ExtraMessage); 429 } 430 431 if (PrematureEOF) 432 { 433 fprintf (OutputFile, " and premature End-Of-File"); 434 } 435 436 fprintf (OutputFile, "\n"); 437 if (Gbl_VerboseErrors) 438 { 439 fprintf (OutputFile, "\n"); 440 } 441 } 442 else 443 { 444 fprintf (OutputFile, " %s %s\n\n", MainMessage, ExtraMessage); 445 } 446 } 447 } 448 449 450 /******************************************************************************* 451 * 452 * FUNCTION: AePrintErrorLog 453 * 454 * PARAMETERS: FileId - Where to output the error log 455 * 456 * RETURN: None 457 * 458 * DESCRIPTION: Print the entire contents of the error log 459 * 460 ******************************************************************************/ 461 462 void 463 AePrintErrorLog ( 464 UINT32 FileId) 465 { 466 ASL_ERROR_MSG *Enode = Gbl_ErrorLog; 467 468 469 /* Walk the error node list */ 470 471 while (Enode) 472 { 473 AePrintException (FileId, Enode, NULL); 474 Enode = Enode->Next; 475 } 476 } 477 478 479 /******************************************************************************* 480 * 481 * FUNCTION: AslCommonError2 482 * 483 * PARAMETERS: Level - Seriousness (Warning/error, etc.) 484 * MessageId - Index into global message buffer 485 * LineNumber - Actual file line number 486 * Column - Column in current line 487 * SourceLine - Actual source code line 488 * Filename - source filename 489 * ExtraMessage - additional error message 490 * 491 * RETURN: None 492 * 493 * DESCRIPTION: Create a new error node and add it to the error log 494 * 495 ******************************************************************************/ 496 497 void 498 AslCommonError2 ( 499 UINT8 Level, 500 UINT8 MessageId, 501 UINT32 LineNumber, 502 UINT32 Column, 503 char *SourceLine, 504 char *Filename, 505 char *ExtraMessage) 506 { 507 char *MessageBuffer = NULL; 508 char *LineBuffer; 509 ASL_ERROR_MSG *Enode; 510 511 512 Enode = UtLocalCalloc (sizeof (ASL_ERROR_MSG)); 513 514 if (ExtraMessage) 515 { 516 /* Allocate a buffer for the message and a new error node */ 517 518 MessageBuffer = UtLocalCalloc (strlen (ExtraMessage) + 1); 519 520 /* Keep a copy of the extra message */ 521 522 ACPI_STRCPY (MessageBuffer, ExtraMessage); 523 } 524 525 LineBuffer = UtLocalCalloc (strlen (SourceLine) + 1); 526 ACPI_STRCPY (LineBuffer, SourceLine); 527 528 /* Initialize the error node */ 529 530 if (Filename) 531 { 532 Enode->Filename = Filename; 533 Enode->FilenameLength = strlen (Filename); 534 if (Enode->FilenameLength < 6) 535 { 536 Enode->FilenameLength = 6; 537 } 538 } 539 540 Enode->MessageId = MessageId; 541 Enode->Level = Level; 542 Enode->LineNumber = LineNumber; 543 Enode->LogicalLineNumber = LineNumber; 544 Enode->LogicalByteOffset = 0; 545 Enode->Column = Column; 546 Enode->Message = MessageBuffer; 547 Enode->SourceLine = LineBuffer; 548 549 /* Add the new node to the error node list */ 550 551 AeAddToErrorLog (Enode); 552 553 if (Gbl_DebugFlag) 554 { 555 /* stderr is a file, send error to it immediately */ 556 557 AePrintException (ASL_FILE_STDERR, Enode, NULL); 558 } 559 560 Gbl_ExceptionCount[Level]++; 561 } 562 563 564 /******************************************************************************* 565 * 566 * FUNCTION: AslCommonError 567 * 568 * PARAMETERS: Level - Seriousness (Warning/error, etc.) 569 * MessageId - Index into global message buffer 570 * CurrentLineNumber - Actual file line number 571 * LogicalLineNumber - Cumulative line number 572 * LogicalByteOffset - Byte offset in source file 573 * Column - Column in current line 574 * Filename - source filename 575 * ExtraMessage - additional error message 576 * 577 * RETURN: None 578 * 579 * DESCRIPTION: Create a new error node and add it to the error log 580 * 581 ******************************************************************************/ 582 583 void 584 AslCommonError ( 585 UINT8 Level, 586 UINT8 MessageId, 587 UINT32 CurrentLineNumber, 588 UINT32 LogicalLineNumber, 589 UINT32 LogicalByteOffset, 590 UINT32 Column, 591 char *Filename, 592 char *ExtraMessage) 593 { 594 UINT32 MessageSize; 595 char *MessageBuffer = NULL; 596 ASL_ERROR_MSG *Enode; 597 598 599 Enode = UtLocalCalloc (sizeof (ASL_ERROR_MSG)); 600 601 if (ExtraMessage) 602 { 603 /* Allocate a buffer for the message and a new error node */ 604 605 MessageSize = strlen (ExtraMessage) + 1; 606 MessageBuffer = UtLocalCalloc (MessageSize); 607 608 /* Keep a copy of the extra message */ 609 610 ACPI_STRCPY (MessageBuffer, ExtraMessage); 611 } 612 613 /* Initialize the error node */ 614 615 if (Filename) 616 { 617 Enode->Filename = Filename; 618 Enode->FilenameLength = strlen (Filename); 619 if (Enode->FilenameLength < 6) 620 { 621 Enode->FilenameLength = 6; 622 } 623 } 624 625 Enode->MessageId = MessageId; 626 Enode->Level = Level; 627 Enode->LineNumber = CurrentLineNumber; 628 Enode->LogicalLineNumber = LogicalLineNumber; 629 Enode->LogicalByteOffset = LogicalByteOffset; 630 Enode->Column = Column; 631 Enode->Message = MessageBuffer; 632 Enode->SourceLine = NULL; 633 634 /* Add the new node to the error node list */ 635 636 AeAddToErrorLog (Enode); 637 638 if (Gbl_DebugFlag) 639 { 640 /* stderr is a file, send error to it immediately */ 641 642 AePrintException (ASL_FILE_STDERR, Enode, NULL); 643 } 644 645 Gbl_ExceptionCount[Level]++; 646 if (Gbl_ExceptionCount[ASL_ERROR] > ASL_MAX_ERROR_COUNT) 647 { 648 printf ("\nMaximum error count (%u) exceeded\n", ASL_MAX_ERROR_COUNT); 649 650 Gbl_SourceLine = 0; 651 Gbl_NextError = Gbl_ErrorLog; 652 CmDoOutputFiles (); 653 CmCleanupAndExit (); 654 exit(1); 655 } 656 657 return; 658 } 659 660 661 /******************************************************************************* 662 * 663 * FUNCTION: AslError 664 * 665 * PARAMETERS: Level - Seriousness (Warning/error, etc.) 666 * MessageId - Index into global message buffer 667 * Op - Parse node where error happened 668 * ExtraMessage - additional error message 669 * 670 * RETURN: None 671 * 672 * DESCRIPTION: Main error reporting routine for the ASL compiler (all code 673 * except the parser.) 674 * 675 ******************************************************************************/ 676 677 void 678 AslError ( 679 UINT8 Level, 680 UINT8 MessageId, 681 ACPI_PARSE_OBJECT *Op, 682 char *ExtraMessage) 683 { 684 685 switch (Level) 686 { 687 case ASL_WARNING2: 688 case ASL_WARNING3: 689 if (Gbl_WarningLevel < Level) 690 { 691 return; 692 } 693 break; 694 695 default: 696 break; 697 } 698 699 if (Op) 700 { 701 AslCommonError (Level, MessageId, Op->Asl.LineNumber, 702 Op->Asl.LogicalLineNumber, 703 Op->Asl.LogicalByteOffset, 704 Op->Asl.Column, 705 Op->Asl.Filename, ExtraMessage); 706 } 707 else 708 { 709 AslCommonError (Level, MessageId, 0, 710 0, 0, 0, NULL, ExtraMessage); 711 } 712 } 713 714 715 /******************************************************************************* 716 * 717 * FUNCTION: AslCoreSubsystemError 718 * 719 * PARAMETERS: Op - Parse node where error happened 720 * Status - The ACPI CA Exception 721 * ExtraMessage - additional error message 722 * Abort - TRUE -> Abort compilation 723 * 724 * RETURN: None 725 * 726 * DESCRIPTION: Error reporting routine for exceptions returned by the ACPI 727 * CA core subsystem. 728 * 729 ******************************************************************************/ 730 731 void 732 AslCoreSubsystemError ( 733 ACPI_PARSE_OBJECT *Op, 734 ACPI_STATUS Status, 735 char *ExtraMessage, 736 BOOLEAN Abort) 737 { 738 739 sprintf (MsgBuffer, "%s %s", AcpiFormatException (Status), ExtraMessage); 740 741 if (Op) 742 { 743 AslCommonError (ASL_ERROR, ASL_MSG_CORE_EXCEPTION, Op->Asl.LineNumber, 744 Op->Asl.LogicalLineNumber, 745 Op->Asl.LogicalByteOffset, 746 Op->Asl.Column, 747 Op->Asl.Filename, MsgBuffer); 748 } 749 else 750 { 751 AslCommonError (ASL_ERROR, ASL_MSG_CORE_EXCEPTION, 0, 752 0, 0, 0, NULL, MsgBuffer); 753 } 754 755 if (Abort) 756 { 757 AslAbort (); 758 } 759 } 760 761 762 /******************************************************************************* 763 * 764 * FUNCTION: AslCompilererror 765 * 766 * PARAMETERS: CompilerMessage - Error message from the parser 767 * 768 * RETURN: Status (0 for now) 769 * 770 * DESCRIPTION: Report an error situation discovered in a production 771 * NOTE: don't change the name of this function, it is called 772 * from the auto-generated parser. 773 * 774 ******************************************************************************/ 775 776 int 777 AslCompilererror ( 778 const char *CompilerMessage) 779 { 780 781 AslCommonError (ASL_ERROR, ASL_MSG_SYNTAX, Gbl_CurrentLineNumber, 782 Gbl_LogicalLineNumber, Gbl_CurrentLineOffset, 783 Gbl_CurrentColumn, Gbl_Files[ASL_FILE_INPUT].Filename, 784 ACPI_CAST_PTR (char, CompilerMessage)); 785 786 return 0; 787 } 788