1 2 /****************************************************************************** 3 * 4 * Module Name: aslerror - Error handling and statistics 5 * 6 *****************************************************************************/ 7 8 /* 9 * Copyright (C) 2000 - 2011, 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 void 59 AeClearErrorLog ( 60 void) 61 { 62 ASL_ERROR_MSG *Enode = Gbl_ErrorLog; 63 ASL_ERROR_MSG *Next; 64 65 /* Walk the error node list */ 66 67 while (Enode) 68 { 69 Next = Enode->Next; 70 ACPI_FREE (Enode); 71 Enode = Next; 72 } 73 74 Gbl_ErrorLog = NULL; 75 } 76 77 78 /******************************************************************************* 79 * 80 * FUNCTION: AeAddToErrorLog 81 * 82 * PARAMETERS: Enode - An error node to add to the log 83 * 84 * RETURN: None 85 * 86 * DESCRIPTION: Add a new error node to the error log. The error log is 87 * ordered by the "logical" line number (cumulative line number 88 * including all include files.) 89 * 90 ******************************************************************************/ 91 92 static void 93 AeAddToErrorLog ( 94 ASL_ERROR_MSG *Enode) 95 { 96 ASL_ERROR_MSG *Next; 97 ASL_ERROR_MSG *Prev; 98 99 100 /* If Gbl_ErrorLog is null, this is the first error node */ 101 102 if (!Gbl_ErrorLog) 103 { 104 Gbl_ErrorLog = Enode; 105 return; 106 } 107 108 /* 109 * Walk error list until we find a line number greater than ours. 110 * List is sorted according to line number. 111 */ 112 Prev = NULL; 113 Next = Gbl_ErrorLog; 114 115 while ((Next) && 116 (Next->LogicalLineNumber <= Enode->LogicalLineNumber)) 117 { 118 Prev = Next; 119 Next = Next->Next; 120 } 121 122 /* Found our place in the list */ 123 124 Enode->Next = Next; 125 126 if (Prev) 127 { 128 Prev->Next = Enode; 129 } 130 else 131 { 132 Gbl_ErrorLog = Enode; 133 } 134 } 135 136 137 /******************************************************************************* 138 * 139 * FUNCTION: AePrintException 140 * 141 * PARAMETERS: FileId - ID of output file 142 * Enode - Error node to print 143 * Header - Additional text before each message 144 * 145 * RETURN: None 146 * 147 * DESCRIPTION: Print the contents of an error node. 148 * 149 * NOTE: We don't use the FlxxxFile I/O functions here because on error 150 * they abort the compiler and call this function! Since we 151 * are reporting errors here, we ignore most output errors and 152 * just try to get out as much as we can. 153 * 154 ******************************************************************************/ 155 156 void 157 AePrintException ( 158 UINT32 FileId, 159 ASL_ERROR_MSG *Enode, 160 char *Header) 161 { 162 UINT8 SourceByte; 163 int Actual; 164 size_t RActual; 165 UINT32 MsgLength; 166 char *MainMessage; 167 char *ExtraMessage; 168 UINT32 SourceColumn; 169 UINT32 ErrorColumn; 170 FILE *OutputFile; 171 FILE *SourceFile; 172 long FileSize; 173 BOOLEAN PrematureEOF = FALSE; 174 175 176 if (Gbl_NoErrors) 177 { 178 return; 179 } 180 181 /* 182 * Only listing files have a header, and remarks/optimizations 183 * are always output 184 */ 185 if (!Header) 186 { 187 /* Ignore remarks if requested */ 188 189 switch (Enode->Level) 190 { 191 case ASL_REMARK: 192 if (!Gbl_DisplayRemarks) 193 { 194 return; 195 } 196 break; 197 198 case ASL_OPTIMIZATION: 199 if (!Gbl_DisplayOptimizations) 200 { 201 return; 202 } 203 break; 204 205 default: 206 break; 207 } 208 } 209 210 /* Get the file handles */ 211 212 OutputFile = Gbl_Files[FileId].Handle; 213 214 /* Use the merged header/source file if present, otherwise use input file */ 215 216 SourceFile = Gbl_Files[ASL_FILE_SOURCE_OUTPUT].Handle; 217 if (!SourceFile) 218 { 219 SourceFile = Gbl_Files[ASL_FILE_INPUT].Handle; 220 } 221 222 if (SourceFile) 223 { 224 /* Determine if the error occurred at source file EOF */ 225 226 fseek (SourceFile, 0, SEEK_END); 227 FileSize = ftell (SourceFile); 228 229 if ((long) Enode->LogicalByteOffset >= FileSize) 230 { 231 PrematureEOF = TRUE; 232 } 233 } 234 235 if (Header) 236 { 237 fprintf (OutputFile, "%s", Header); 238 } 239 240 /* Print filename and line number if present and valid */ 241 242 if (Enode->Filename) 243 { 244 if (Gbl_VerboseErrors) 245 { 246 fprintf (OutputFile, "%6s", Enode->Filename); 247 248 if (Enode->LineNumber) 249 { 250 fprintf (OutputFile, " %6u: ", Enode->LineNumber); 251 252 /* 253 * If not at EOF, get the corresponding source code line and 254 * display it. Don't attempt this if we have a premature EOF 255 * condition. 256 */ 257 if (!PrematureEOF) 258 { 259 /* 260 * Seek to the offset in the combined source file, read 261 * the source line, and write it to the output. 262 */ 263 Actual = fseek (SourceFile, (long) Enode->LogicalByteOffset, 264 (int) SEEK_SET); 265 if (Actual) 266 { 267 fprintf (OutputFile, 268 "[*** iASL: Seek error on source code temp file %s ***]", 269 Gbl_Files[ASL_FILE_SOURCE_OUTPUT].Filename); 270 } 271 else 272 { 273 RActual = fread (&SourceByte, 1, 1, SourceFile); 274 if (!RActual) 275 { 276 fprintf (OutputFile, 277 "[*** iASL: Read error on source code temp file %s ***]", 278 Gbl_Files[ASL_FILE_SOURCE_OUTPUT].Filename); 279 } 280 281 else while (RActual && SourceByte && (SourceByte != '\n')) 282 { 283 fwrite (&SourceByte, 1, 1, OutputFile); 284 RActual = fread (&SourceByte, 1, 1, SourceFile); 285 } 286 } 287 } 288 289 fprintf (OutputFile, "\n"); 290 } 291 } 292 else 293 { 294 fprintf (OutputFile, "%s", Enode->Filename); 295 296 if (Enode->LineNumber) 297 { 298 fprintf (OutputFile, "(%u) : ", Enode->LineNumber); 299 } 300 } 301 } 302 303 /* NULL message ID, just print the raw message */ 304 305 if (Enode->MessageId == 0) 306 { 307 fprintf (OutputFile, "%s\n", Enode->Message); 308 } 309 else 310 { 311 /* Decode the message ID */ 312 313 fprintf (OutputFile, "%s %4.4d - ", 314 AslErrorLevel[Enode->Level], 315 Enode->MessageId + ((Enode->Level+1) * 1000)); 316 317 MainMessage = AslMessages[Enode->MessageId]; 318 ExtraMessage = Enode->Message; 319 320 if (Enode->LineNumber) 321 { 322 /* Main message: try to use string from AslMessages first */ 323 324 if (!MainMessage) 325 { 326 MainMessage = ""; 327 } 328 329 MsgLength = strlen (MainMessage); 330 if (MsgLength == 0) 331 { 332 /* Use the secondary/extra message as main message */ 333 334 MainMessage = Enode->Message; 335 if (!MainMessage) 336 { 337 MainMessage = ""; 338 } 339 340 MsgLength = strlen (MainMessage); 341 ExtraMessage = NULL; 342 } 343 344 if (Gbl_VerboseErrors && !PrematureEOF) 345 { 346 SourceColumn = Enode->Column + Enode->FilenameLength + 6 + 2; 347 ErrorColumn = ASL_ERROR_LEVEL_LENGTH + 5 + 2 + 1; 348 349 if ((MsgLength + ErrorColumn) < (SourceColumn - 1)) 350 { 351 fprintf (OutputFile, "%*s%s", 352 (int) ((SourceColumn - 1) - ErrorColumn), 353 MainMessage, " ^ "); 354 } 355 else 356 { 357 fprintf (OutputFile, "%*s %s", 358 (int) ((SourceColumn - ErrorColumn) + 1), "^", 359 MainMessage); 360 } 361 } 362 else 363 { 364 fprintf (OutputFile, " %s", MainMessage); 365 } 366 367 /* Print the extra info message if present */ 368 369 if (ExtraMessage) 370 { 371 fprintf (OutputFile, " (%s)", ExtraMessage); 372 } 373 374 if (PrematureEOF) 375 { 376 fprintf (OutputFile, " and premature End-Of-File"); 377 } 378 379 fprintf (OutputFile, "\n"); 380 if (Gbl_VerboseErrors) 381 { 382 fprintf (OutputFile, "\n"); 383 } 384 } 385 else 386 { 387 fprintf (OutputFile, " %s %s\n\n", MainMessage, ExtraMessage); 388 } 389 } 390 } 391 392 393 /******************************************************************************* 394 * 395 * FUNCTION: AePrintErrorLog 396 * 397 * PARAMETERS: FileId - Where to output the error log 398 * 399 * RETURN: None 400 * 401 * DESCRIPTION: Print the entire contents of the error log 402 * 403 ******************************************************************************/ 404 405 void 406 AePrintErrorLog ( 407 UINT32 FileId) 408 { 409 ASL_ERROR_MSG *Enode = Gbl_ErrorLog; 410 411 412 /* Walk the error node list */ 413 414 while (Enode) 415 { 416 AePrintException (FileId, Enode, NULL); 417 Enode = Enode->Next; 418 } 419 } 420 421 422 /******************************************************************************* 423 * 424 * FUNCTION: AslCommonError 425 * 426 * PARAMETERS: Level - Seriousness (Warning/error, etc.) 427 * MessageId - Index into global message buffer 428 * CurrentLineNumber - Actual file line number 429 * LogicalLineNumber - Cumulative line number 430 * LogicalByteOffset - Byte offset in source file 431 * Column - Column in current line 432 * Filename - source filename 433 * ExtraMessage - additional error message 434 * 435 * RETURN: None 436 * 437 * DESCRIPTION: Create a new error node and add it to the error log 438 * 439 ******************************************************************************/ 440 441 void 442 AslCommonError ( 443 UINT8 Level, 444 UINT8 MessageId, 445 UINT32 CurrentLineNumber, 446 UINT32 LogicalLineNumber, 447 UINT32 LogicalByteOffset, 448 UINT32 Column, 449 char *Filename, 450 char *ExtraMessage) 451 { 452 UINT32 MessageSize; 453 char *MessageBuffer = NULL; 454 ASL_ERROR_MSG *Enode; 455 456 457 Enode = UtLocalCalloc (sizeof (ASL_ERROR_MSG)); 458 459 if (ExtraMessage) 460 { 461 /* Allocate a buffer for the message and a new error node */ 462 463 MessageSize = strlen (ExtraMessage) + 1; 464 MessageBuffer = UtLocalCalloc (MessageSize); 465 466 /* Keep a copy of the extra message */ 467 468 ACPI_STRCPY (MessageBuffer, ExtraMessage); 469 } 470 471 /* Initialize the error node */ 472 473 if (Filename) 474 { 475 Enode->Filename = Filename; 476 Enode->FilenameLength = strlen (Filename); 477 if (Enode->FilenameLength < 6) 478 { 479 Enode->FilenameLength = 6; 480 } 481 } 482 483 Enode->MessageId = MessageId; 484 Enode->Level = Level; 485 Enode->LineNumber = CurrentLineNumber; 486 Enode->LogicalLineNumber = LogicalLineNumber; 487 Enode->LogicalByteOffset = LogicalByteOffset; 488 Enode->Column = Column; 489 Enode->Message = MessageBuffer; 490 491 /* Add the new node to the error node list */ 492 493 AeAddToErrorLog (Enode); 494 495 if (Gbl_DebugFlag) 496 { 497 /* stderr is a file, send error to it immediately */ 498 499 AePrintException (ASL_FILE_STDERR, Enode, NULL); 500 } 501 502 Gbl_ExceptionCount[Level]++; 503 if (Gbl_ExceptionCount[ASL_ERROR] > ASL_MAX_ERROR_COUNT) 504 { 505 printf ("\nMaximum error count (%u) exceeded\n", ASL_MAX_ERROR_COUNT); 506 507 Gbl_SourceLine = 0; 508 Gbl_NextError = Gbl_ErrorLog; 509 CmDoOutputFiles (); 510 CmCleanupAndExit (); 511 exit(1); 512 } 513 514 return; 515 } 516 517 518 /******************************************************************************* 519 * 520 * FUNCTION: AslError 521 * 522 * PARAMETERS: Level - Seriousness (Warning/error, etc.) 523 * MessageId - Index into global message buffer 524 * Op - Parse node where error happened 525 * ExtraMessage - additional error message 526 * 527 * RETURN: None 528 * 529 * DESCRIPTION: Main error reporting routine for the ASL compiler (all code 530 * except the parser.) 531 * 532 ******************************************************************************/ 533 534 void 535 AslError ( 536 UINT8 Level, 537 UINT8 MessageId, 538 ACPI_PARSE_OBJECT *Op, 539 char *ExtraMessage) 540 { 541 542 switch (Level) 543 { 544 case ASL_WARNING2: 545 case ASL_WARNING3: 546 if (Gbl_WarningLevel < Level) 547 { 548 return; 549 } 550 break; 551 552 default: 553 break; 554 } 555 556 557 if (Op) 558 { 559 AslCommonError (Level, MessageId, Op->Asl.LineNumber, 560 Op->Asl.LogicalLineNumber, 561 Op->Asl.LogicalByteOffset, 562 Op->Asl.Column, 563 Op->Asl.Filename, ExtraMessage); 564 } 565 else 566 { 567 AslCommonError (Level, MessageId, 0, 568 0, 0, 0, NULL, ExtraMessage); 569 } 570 } 571 572 573 /******************************************************************************* 574 * 575 * FUNCTION: AslCoreSubsystemError 576 * 577 * PARAMETERS: Op - Parse node where error happened 578 * Status - The ACPI CA Exception 579 * ExtraMessage - additional error message 580 * Abort - TRUE -> Abort compilation 581 * 582 * RETURN: None 583 * 584 * DESCRIPTION: Error reporting routine for exceptions returned by the ACPI 585 * CA core subsystem. 586 * 587 ******************************************************************************/ 588 589 void 590 AslCoreSubsystemError ( 591 ACPI_PARSE_OBJECT *Op, 592 ACPI_STATUS Status, 593 char *ExtraMessage, 594 BOOLEAN Abort) 595 { 596 597 sprintf (MsgBuffer, "%s %s", AcpiFormatException (Status), ExtraMessage); 598 599 if (Op) 600 { 601 AslCommonError (ASL_ERROR, ASL_MSG_CORE_EXCEPTION, Op->Asl.LineNumber, 602 Op->Asl.LogicalLineNumber, 603 Op->Asl.LogicalByteOffset, 604 Op->Asl.Column, 605 Op->Asl.Filename, MsgBuffer); 606 } 607 else 608 { 609 AslCommonError (ASL_ERROR, ASL_MSG_CORE_EXCEPTION, 0, 610 0, 0, 0, NULL, MsgBuffer); 611 } 612 613 if (Abort) 614 { 615 AslAbort (); 616 } 617 } 618 619 620 /******************************************************************************* 621 * 622 * FUNCTION: AslCompilererror 623 * 624 * PARAMETERS: CompilerMessage - Error message from the parser 625 * 626 * RETURN: Status (0 for now) 627 * 628 * DESCRIPTION: Report an error situation discovered in a production 629 * NOTE: don't change the name of this function, it is called 630 * from the auto-generated parser. 631 * 632 ******************************************************************************/ 633 634 int 635 AslCompilererror ( 636 const char *CompilerMessage) 637 { 638 639 AslCommonError (ASL_ERROR, ASL_MSG_SYNTAX, Gbl_CurrentLineNumber, 640 Gbl_LogicalLineNumber, Gbl_CurrentLineOffset, 641 Gbl_CurrentColumn, Gbl_Files[ASL_FILE_INPUT].Filename, 642 ACPI_CAST_PTR (char, CompilerMessage)); 643 644 return 0; 645 } 646 647 648