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 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) 298 { 299 fprintf (OutputFile, 300 "[*** iASL: Read error on source code temp file %s ***]", 301 Gbl_Files[ASL_FILE_SOURCE_OUTPUT].Filename); 302 } 303 304 else while (RActual && SourceByte && (SourceByte != '\n')) 305 { 306 fwrite (&SourceByte, 1, 1, OutputFile); 307 RActual = fread (&SourceByte, 1, 1, SourceFile); 308 } 309 } 310 } 311 312 fprintf (OutputFile, "\n"); 313 } 314 } 315 } 316 else 317 { 318 /* 319 * Less verbose version of the error message, enabled via the 320 * -vi switch. The format is compatible with MS Visual Studio. 321 */ 322 fprintf (OutputFile, "%s", Enode->Filename); 323 324 if (Enode->LineNumber) 325 { 326 fprintf (OutputFile, "(%u) : ", 327 Enode->LineNumber); 328 } 329 } 330 } 331 332 /* NULL message ID, just print the raw message */ 333 334 if (Enode->MessageId == 0) 335 { 336 fprintf (OutputFile, "%s\n", Enode->Message); 337 } 338 else 339 { 340 /* Decode the message ID */ 341 342 if (Gbl_VerboseErrors) 343 { 344 fprintf (OutputFile, "%s %4.4d - ", 345 AslErrorLevel[Enode->Level], 346 Enode->MessageId + ((Enode->Level+1) * 1000)); 347 } 348 else /* IDE case */ 349 { 350 fprintf (OutputFile, "%s %4.4d:", 351 AslErrorLevelIde[Enode->Level], 352 Enode->MessageId + ((Enode->Level+1) * 1000)); 353 } 354 355 MainMessage = AslMessages[Enode->MessageId]; 356 ExtraMessage = Enode->Message; 357 358 if (Enode->LineNumber) 359 { 360 /* Main message: try to use string from AslMessages first */ 361 362 if (!MainMessage) 363 { 364 MainMessage = ""; 365 } 366 367 MsgLength = strlen (MainMessage); 368 if (MsgLength == 0) 369 { 370 /* Use the secondary/extra message as main message */ 371 372 MainMessage = Enode->Message; 373 if (!MainMessage) 374 { 375 MainMessage = ""; 376 } 377 378 MsgLength = strlen (MainMessage); 379 ExtraMessage = NULL; 380 } 381 382 if (Gbl_VerboseErrors && !PrematureEOF) 383 { 384 SourceColumn = Enode->Column + Enode->FilenameLength + 6 + 2; 385 ErrorColumn = ASL_ERROR_LEVEL_LENGTH + 5 + 2 + 1; 386 387 if ((MsgLength + ErrorColumn) < (SourceColumn - 1)) 388 { 389 fprintf (OutputFile, "%*s%s", 390 (int) ((SourceColumn - 1) - ErrorColumn), 391 MainMessage, " ^ "); 392 } 393 else 394 { 395 fprintf (OutputFile, "%*s %s", 396 (int) ((SourceColumn - ErrorColumn) + 1), "^", 397 MainMessage); 398 } 399 } 400 else 401 { 402 fprintf (OutputFile, " %s", MainMessage); 403 } 404 405 /* Print the extra info message if present */ 406 407 if (ExtraMessage) 408 { 409 fprintf (OutputFile, " (%s)", ExtraMessage); 410 } 411 412 if (PrematureEOF) 413 { 414 fprintf (OutputFile, " and premature End-Of-File"); 415 } 416 417 fprintf (OutputFile, "\n"); 418 if (Gbl_VerboseErrors) 419 { 420 fprintf (OutputFile, "\n"); 421 } 422 } 423 else 424 { 425 fprintf (OutputFile, " %s %s\n\n", MainMessage, ExtraMessage); 426 } 427 } 428 } 429 430 431 /******************************************************************************* 432 * 433 * FUNCTION: AePrintErrorLog 434 * 435 * PARAMETERS: FileId - Where to output the error log 436 * 437 * RETURN: None 438 * 439 * DESCRIPTION: Print the entire contents of the error log 440 * 441 ******************************************************************************/ 442 443 void 444 AePrintErrorLog ( 445 UINT32 FileId) 446 { 447 ASL_ERROR_MSG *Enode = Gbl_ErrorLog; 448 449 450 /* Walk the error node list */ 451 452 while (Enode) 453 { 454 AePrintException (FileId, Enode, NULL); 455 Enode = Enode->Next; 456 } 457 } 458 459 460 /******************************************************************************* 461 * 462 * FUNCTION: AslCommonError2 463 * 464 * PARAMETERS: Level - Seriousness (Warning/error, etc.) 465 * MessageId - Index into global message buffer 466 * LineNumber - Actual file line number 467 * Column - Column in current line 468 * SourceLine - Actual source code line 469 * Filename - source filename 470 * ExtraMessage - additional error message 471 * 472 * RETURN: None 473 * 474 * DESCRIPTION: Create a new error node and add it to the error log 475 * 476 ******************************************************************************/ 477 478 void 479 AslCommonError2 ( 480 UINT8 Level, 481 UINT8 MessageId, 482 UINT32 LineNumber, 483 UINT32 Column, 484 char *SourceLine, 485 char *Filename, 486 char *ExtraMessage) 487 { 488 char *MessageBuffer = NULL; 489 char *LineBuffer; 490 ASL_ERROR_MSG *Enode; 491 492 493 Enode = UtLocalCalloc (sizeof (ASL_ERROR_MSG)); 494 495 if (ExtraMessage) 496 { 497 /* Allocate a buffer for the message and a new error node */ 498 499 MessageBuffer = UtLocalCalloc (strlen (ExtraMessage) + 1); 500 501 /* Keep a copy of the extra message */ 502 503 ACPI_STRCPY (MessageBuffer, ExtraMessage); 504 } 505 506 LineBuffer = UtLocalCalloc (strlen (SourceLine) + 1); 507 ACPI_STRCPY (LineBuffer, SourceLine); 508 509 /* Initialize the error node */ 510 511 if (Filename) 512 { 513 Enode->Filename = Filename; 514 Enode->FilenameLength = strlen (Filename); 515 if (Enode->FilenameLength < 6) 516 { 517 Enode->FilenameLength = 6; 518 } 519 } 520 521 Enode->MessageId = MessageId; 522 Enode->Level = Level; 523 Enode->LineNumber = LineNumber; 524 Enode->LogicalLineNumber = LineNumber; 525 Enode->LogicalByteOffset = 0; 526 Enode->Column = Column; 527 Enode->Message = MessageBuffer; 528 Enode->SourceLine = LineBuffer; 529 530 /* Add the new node to the error node list */ 531 532 AeAddToErrorLog (Enode); 533 534 if (Gbl_DebugFlag) 535 { 536 /* stderr is a file, send error to it immediately */ 537 538 AePrintException (ASL_FILE_STDERR, Enode, NULL); 539 } 540 541 Gbl_ExceptionCount[Level]++; 542 } 543 544 545 /******************************************************************************* 546 * 547 * FUNCTION: AslCommonError 548 * 549 * PARAMETERS: Level - Seriousness (Warning/error, etc.) 550 * MessageId - Index into global message buffer 551 * CurrentLineNumber - Actual file line number 552 * LogicalLineNumber - Cumulative line number 553 * LogicalByteOffset - Byte offset in source file 554 * Column - Column in current line 555 * Filename - source filename 556 * ExtraMessage - additional error message 557 * 558 * RETURN: None 559 * 560 * DESCRIPTION: Create a new error node and add it to the error log 561 * 562 ******************************************************************************/ 563 564 void 565 AslCommonError ( 566 UINT8 Level, 567 UINT8 MessageId, 568 UINT32 CurrentLineNumber, 569 UINT32 LogicalLineNumber, 570 UINT32 LogicalByteOffset, 571 UINT32 Column, 572 char *Filename, 573 char *ExtraMessage) 574 { 575 UINT32 MessageSize; 576 char *MessageBuffer = NULL; 577 ASL_ERROR_MSG *Enode; 578 579 580 Enode = UtLocalCalloc (sizeof (ASL_ERROR_MSG)); 581 582 if (ExtraMessage) 583 { 584 /* Allocate a buffer for the message and a new error node */ 585 586 MessageSize = strlen (ExtraMessage) + 1; 587 MessageBuffer = UtLocalCalloc (MessageSize); 588 589 /* Keep a copy of the extra message */ 590 591 ACPI_STRCPY (MessageBuffer, ExtraMessage); 592 } 593 594 /* Initialize the error node */ 595 596 if (Filename) 597 { 598 Enode->Filename = Filename; 599 Enode->FilenameLength = strlen (Filename); 600 if (Enode->FilenameLength < 6) 601 { 602 Enode->FilenameLength = 6; 603 } 604 } 605 606 Enode->MessageId = MessageId; 607 Enode->Level = Level; 608 Enode->LineNumber = CurrentLineNumber; 609 Enode->LogicalLineNumber = LogicalLineNumber; 610 Enode->LogicalByteOffset = LogicalByteOffset; 611 Enode->Column = Column; 612 Enode->Message = MessageBuffer; 613 Enode->SourceLine = NULL; 614 615 /* Add the new node to the error node list */ 616 617 AeAddToErrorLog (Enode); 618 619 if (Gbl_DebugFlag) 620 { 621 /* stderr is a file, send error to it immediately */ 622 623 AePrintException (ASL_FILE_STDERR, Enode, NULL); 624 } 625 626 Gbl_ExceptionCount[Level]++; 627 if (Gbl_ExceptionCount[ASL_ERROR] > ASL_MAX_ERROR_COUNT) 628 { 629 printf ("\nMaximum error count (%u) exceeded\n", ASL_MAX_ERROR_COUNT); 630 631 Gbl_SourceLine = 0; 632 Gbl_NextError = Gbl_ErrorLog; 633 CmDoOutputFiles (); 634 CmCleanupAndExit (); 635 exit(1); 636 } 637 638 return; 639 } 640 641 642 /******************************************************************************* 643 * 644 * FUNCTION: AslError 645 * 646 * PARAMETERS: Level - Seriousness (Warning/error, etc.) 647 * MessageId - Index into global message buffer 648 * Op - Parse node where error happened 649 * ExtraMessage - additional error message 650 * 651 * RETURN: None 652 * 653 * DESCRIPTION: Main error reporting routine for the ASL compiler (all code 654 * except the parser.) 655 * 656 ******************************************************************************/ 657 658 void 659 AslError ( 660 UINT8 Level, 661 UINT8 MessageId, 662 ACPI_PARSE_OBJECT *Op, 663 char *ExtraMessage) 664 { 665 666 switch (Level) 667 { 668 case ASL_WARNING2: 669 case ASL_WARNING3: 670 if (Gbl_WarningLevel < Level) 671 { 672 return; 673 } 674 break; 675 676 default: 677 break; 678 } 679 680 if (Op) 681 { 682 AslCommonError (Level, MessageId, Op->Asl.LineNumber, 683 Op->Asl.LogicalLineNumber, 684 Op->Asl.LogicalByteOffset, 685 Op->Asl.Column, 686 Op->Asl.Filename, ExtraMessage); 687 } 688 else 689 { 690 AslCommonError (Level, MessageId, 0, 691 0, 0, 0, NULL, ExtraMessage); 692 } 693 } 694 695 696 /******************************************************************************* 697 * 698 * FUNCTION: AslCoreSubsystemError 699 * 700 * PARAMETERS: Op - Parse node where error happened 701 * Status - The ACPI CA Exception 702 * ExtraMessage - additional error message 703 * Abort - TRUE -> Abort compilation 704 * 705 * RETURN: None 706 * 707 * DESCRIPTION: Error reporting routine for exceptions returned by the ACPI 708 * CA core subsystem. 709 * 710 ******************************************************************************/ 711 712 void 713 AslCoreSubsystemError ( 714 ACPI_PARSE_OBJECT *Op, 715 ACPI_STATUS Status, 716 char *ExtraMessage, 717 BOOLEAN Abort) 718 { 719 720 sprintf (MsgBuffer, "%s %s", AcpiFormatException (Status), ExtraMessage); 721 722 if (Op) 723 { 724 AslCommonError (ASL_ERROR, ASL_MSG_CORE_EXCEPTION, Op->Asl.LineNumber, 725 Op->Asl.LogicalLineNumber, 726 Op->Asl.LogicalByteOffset, 727 Op->Asl.Column, 728 Op->Asl.Filename, MsgBuffer); 729 } 730 else 731 { 732 AslCommonError (ASL_ERROR, ASL_MSG_CORE_EXCEPTION, 0, 733 0, 0, 0, NULL, MsgBuffer); 734 } 735 736 if (Abort) 737 { 738 AslAbort (); 739 } 740 } 741 742 743 /******************************************************************************* 744 * 745 * FUNCTION: AslCompilererror 746 * 747 * PARAMETERS: CompilerMessage - Error message from the parser 748 * 749 * RETURN: Status (0 for now) 750 * 751 * DESCRIPTION: Report an error situation discovered in a production 752 * NOTE: don't change the name of this function, it is called 753 * from the auto-generated parser. 754 * 755 ******************************************************************************/ 756 757 int 758 AslCompilererror ( 759 const char *CompilerMessage) 760 { 761 762 AslCommonError (ASL_ERROR, ASL_MSG_SYNTAX, Gbl_CurrentLineNumber, 763 Gbl_LogicalLineNumber, Gbl_CurrentLineOffset, 764 Gbl_CurrentColumn, Gbl_Files[ASL_FILE_INPUT].Filename, 765 ACPI_CAST_PTR (char, CompilerMessage)); 766 767 return 0; 768 } 769