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