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