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