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