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 MsgLength = strlen (MainMessage); 323 if (MsgLength == 0) 324 { 325 MainMessage = Enode->Message; 326 327 MsgLength = strlen (MainMessage); 328 ExtraMessage = NULL; 329 } 330 331 if (Gbl_VerboseErrors && !PrematureEOF) 332 { 333 SourceColumn = Enode->Column + Enode->FilenameLength + 6 + 2; 334 ErrorColumn = ASL_ERROR_LEVEL_LENGTH + 5 + 2 + 1; 335 336 if ((MsgLength + ErrorColumn) < (SourceColumn - 1)) 337 { 338 fprintf (OutputFile, "%*s%s", 339 (int) ((SourceColumn - 1) - ErrorColumn), 340 MainMessage, " ^ "); 341 } 342 else 343 { 344 fprintf (OutputFile, "%*s %s", 345 (int) ((SourceColumn - ErrorColumn) + 1), "^", 346 MainMessage); 347 } 348 } 349 else 350 { 351 fprintf (OutputFile, " %s", MainMessage); 352 } 353 354 /* Print the extra info message if present */ 355 356 if (ExtraMessage) 357 { 358 fprintf (OutputFile, " (%s)", ExtraMessage); 359 } 360 361 if (PrematureEOF) 362 { 363 fprintf (OutputFile, " and premature End-Of-File"); 364 } 365 366 fprintf (OutputFile, "\n"); 367 if (Gbl_VerboseErrors) 368 { 369 fprintf (OutputFile, "\n"); 370 } 371 } 372 else 373 { 374 fprintf (OutputFile, " %s %s\n\n", MainMessage, ExtraMessage); 375 } 376 } 377 } 378 379 380 /******************************************************************************* 381 * 382 * FUNCTION: AePrintErrorLog 383 * 384 * PARAMETERS: FileId - Where to output the error log 385 * 386 * RETURN: None 387 * 388 * DESCRIPTION: Print the entire contents of the error log 389 * 390 ******************************************************************************/ 391 392 void 393 AePrintErrorLog ( 394 UINT32 FileId) 395 { 396 ASL_ERROR_MSG *Enode = Gbl_ErrorLog; 397 398 399 /* Walk the error node list */ 400 401 while (Enode) 402 { 403 AePrintException (FileId, Enode, NULL); 404 Enode = Enode->Next; 405 } 406 } 407 408 409 /******************************************************************************* 410 * 411 * FUNCTION: AslCommonError 412 * 413 * PARAMETERS: Level - Seriousness (Warning/error, etc.) 414 * MessageId - Index into global message buffer 415 * CurrentLineNumber - Actual file line number 416 * LogicalLineNumber - Cumulative line number 417 * LogicalByteOffset - Byte offset in source file 418 * Column - Column in current line 419 * Filename - source filename 420 * ExtraMessage - additional error message 421 * 422 * RETURN: None 423 * 424 * DESCRIPTION: Create a new error node and add it to the error log 425 * 426 ******************************************************************************/ 427 428 void 429 AslCommonError ( 430 UINT8 Level, 431 UINT8 MessageId, 432 UINT32 CurrentLineNumber, 433 UINT32 LogicalLineNumber, 434 UINT32 LogicalByteOffset, 435 UINT32 Column, 436 char *Filename, 437 char *ExtraMessage) 438 { 439 UINT32 MessageSize; 440 char *MessageBuffer = NULL; 441 ASL_ERROR_MSG *Enode; 442 443 444 Enode = UtLocalCalloc (sizeof (ASL_ERROR_MSG)); 445 446 if (ExtraMessage) 447 { 448 /* Allocate a buffer for the message and a new error node */ 449 450 MessageSize = strlen (ExtraMessage) + 1; 451 MessageBuffer = UtLocalCalloc (MessageSize); 452 453 /* Keep a copy of the extra message */ 454 455 ACPI_STRCPY (MessageBuffer, ExtraMessage); 456 } 457 458 /* Initialize the error node */ 459 460 if (Filename) 461 { 462 Enode->Filename = Filename; 463 Enode->FilenameLength = strlen (Filename); 464 if (Enode->FilenameLength < 6) 465 { 466 Enode->FilenameLength = 6; 467 } 468 } 469 470 Enode->MessageId = MessageId; 471 Enode->Level = Level; 472 Enode->LineNumber = CurrentLineNumber; 473 Enode->LogicalLineNumber = LogicalLineNumber; 474 Enode->LogicalByteOffset = LogicalByteOffset; 475 Enode->Column = Column; 476 Enode->Message = MessageBuffer; 477 478 /* Add the new node to the error node list */ 479 480 AeAddToErrorLog (Enode); 481 482 if (Gbl_DebugFlag) 483 { 484 /* stderr is a file, send error to it immediately */ 485 486 AePrintException (ASL_FILE_STDERR, Enode, NULL); 487 } 488 489 Gbl_ExceptionCount[Level]++; 490 if (Gbl_ExceptionCount[ASL_ERROR] > ASL_MAX_ERROR_COUNT) 491 { 492 printf ("\nMaximum error count (%u) exceeded\n", ASL_MAX_ERROR_COUNT); 493 494 Gbl_SourceLine = 0; 495 Gbl_NextError = Gbl_ErrorLog; 496 CmDoOutputFiles (); 497 CmCleanupAndExit (); 498 exit(1); 499 } 500 501 return; 502 } 503 504 505 /******************************************************************************* 506 * 507 * FUNCTION: AslError 508 * 509 * PARAMETERS: Level - Seriousness (Warning/error, etc.) 510 * MessageId - Index into global message buffer 511 * Op - Parse node where error happened 512 * ExtraMessage - additional error message 513 * 514 * RETURN: None 515 * 516 * DESCRIPTION: Main error reporting routine for the ASL compiler (all code 517 * except the parser.) 518 * 519 ******************************************************************************/ 520 521 void 522 AslError ( 523 UINT8 Level, 524 UINT8 MessageId, 525 ACPI_PARSE_OBJECT *Op, 526 char *ExtraMessage) 527 { 528 529 switch (Level) 530 { 531 case ASL_WARNING2: 532 case ASL_WARNING3: 533 if (Gbl_WarningLevel < Level) 534 { 535 return; 536 } 537 break; 538 539 default: 540 break; 541 } 542 543 544 if (Op) 545 { 546 AslCommonError (Level, MessageId, Op->Asl.LineNumber, 547 Op->Asl.LogicalLineNumber, 548 Op->Asl.LogicalByteOffset, 549 Op->Asl.Column, 550 Op->Asl.Filename, ExtraMessage); 551 } 552 else 553 { 554 AslCommonError (Level, MessageId, 0, 555 0, 0, 0, NULL, ExtraMessage); 556 } 557 } 558 559 560 /******************************************************************************* 561 * 562 * FUNCTION: AslCoreSubsystemError 563 * 564 * PARAMETERS: Op - Parse node where error happened 565 * Status - The ACPI CA Exception 566 * ExtraMessage - additional error message 567 * Abort - TRUE -> Abort compilation 568 * 569 * RETURN: None 570 * 571 * DESCRIPTION: Error reporting routine for exceptions returned by the ACPI 572 * CA core subsystem. 573 * 574 ******************************************************************************/ 575 576 void 577 AslCoreSubsystemError ( 578 ACPI_PARSE_OBJECT *Op, 579 ACPI_STATUS Status, 580 char *ExtraMessage, 581 BOOLEAN Abort) 582 { 583 584 sprintf (MsgBuffer, "%s %s", AcpiFormatException (Status), ExtraMessage); 585 586 if (Op) 587 { 588 AslCommonError (ASL_ERROR, ASL_MSG_CORE_EXCEPTION, Op->Asl.LineNumber, 589 Op->Asl.LogicalLineNumber, 590 Op->Asl.LogicalByteOffset, 591 Op->Asl.Column, 592 Op->Asl.Filename, MsgBuffer); 593 } 594 else 595 { 596 AslCommonError (ASL_ERROR, ASL_MSG_CORE_EXCEPTION, 0, 597 0, 0, 0, NULL, MsgBuffer); 598 } 599 600 if (Abort) 601 { 602 AslAbort (); 603 } 604 } 605 606 607 /******************************************************************************* 608 * 609 * FUNCTION: AslCompilererror 610 * 611 * PARAMETERS: CompilerMessage - Error message from the parser 612 * 613 * RETURN: Status (0 for now) 614 * 615 * DESCRIPTION: Report an error situation discovered in a production 616 * NOTE: don't change the name of this function, it is called 617 * from the auto-generated parser. 618 * 619 ******************************************************************************/ 620 621 int 622 AslCompilererror ( 623 char *CompilerMessage) 624 { 625 626 AslCommonError (ASL_ERROR, ASL_MSG_SYNTAX, Gbl_CurrentLineNumber, 627 Gbl_LogicalLineNumber, Gbl_CurrentLineOffset, 628 Gbl_CurrentColumn, Gbl_Files[ASL_FILE_INPUT].Filename, 629 CompilerMessage); 630 631 return 0; 632 } 633 634 635