Fixed compatibility of output.
[AROS.git] / arch / all-pc / acpica / source / compiler / aslerror.c
blobd0e8e03bc0608c3dfdb66846929f461e56650889
1 /******************************************************************************
3 * Module Name: aslerror - Error handling and statistics
5 *****************************************************************************/
7 /*
8 * Copyright (C) 2000 - 2013, Intel Corp.
9 * All rights reserved.
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.
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.
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.
44 #define ASL_EXCEPTIONS
45 #include "aslcompiler.h"
47 #define _COMPONENT ACPI_COMPILER
48 ACPI_MODULE_NAME ("aslerror")
50 /* Local prototypes */
52 static void
53 AeAddToErrorLog (
54 ASL_ERROR_MSG *Enode);
57 /*******************************************************************************
59 * FUNCTION: AeClearErrorLog
61 * PARAMETERS: None
63 * RETURN: None
65 * DESCRIPTION: Empty the error list
67 ******************************************************************************/
69 void
70 AeClearErrorLog (
71 void)
73 ASL_ERROR_MSG *Enode = Gbl_ErrorLog;
74 ASL_ERROR_MSG *Next;
76 /* Walk the error node list */
78 while (Enode)
80 Next = Enode->Next;
81 ACPI_FREE (Enode);
82 Enode = Next;
85 Gbl_ErrorLog = NULL;
89 /*******************************************************************************
91 * FUNCTION: AeAddToErrorLog
93 * PARAMETERS: Enode - An error node to add to the log
95 * RETURN: None
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.)
101 ******************************************************************************/
103 static void
104 AeAddToErrorLog (
105 ASL_ERROR_MSG *Enode)
107 ASL_ERROR_MSG *Next;
108 ASL_ERROR_MSG *Prev;
111 /* If Gbl_ErrorLog is null, this is the first error node */
113 if (!Gbl_ErrorLog)
115 Gbl_ErrorLog = Enode;
116 return;
120 * Walk error list until we find a line number greater than ours.
121 * List is sorted according to line number.
123 Prev = NULL;
124 Next = Gbl_ErrorLog;
126 while ((Next) &&
127 (Next->LogicalLineNumber <= Enode->LogicalLineNumber))
129 Prev = Next;
130 Next = Next->Next;
133 /* Found our place in the list */
135 Enode->Next = Next;
137 if (Prev)
139 Prev->Next = Enode;
141 else
143 Gbl_ErrorLog = Enode;
148 /*******************************************************************************
150 * FUNCTION: AePrintException
152 * PARAMETERS: FileId - ID of output file
153 * Enode - Error node to print
154 * Header - Additional text before each message
156 * RETURN: None
158 * DESCRIPTION: Print the contents of an error node.
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.
165 ******************************************************************************/
167 void
168 AePrintException (
169 UINT32 FileId,
170 ASL_ERROR_MSG *Enode,
171 char *Header)
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;
188 if (Gbl_NoErrors)
190 return;
194 * Only listing files have a header, and remarks/optimizations
195 * are always output
197 if (!Header)
199 /* Ignore remarks if requested */
201 switch (Enode->Level)
203 case ASL_REMARK:
205 if (!Gbl_DisplayRemarks)
207 return;
209 break;
211 case ASL_OPTIMIZATION:
213 if (!Gbl_DisplayOptimizations)
215 return;
217 break;
219 default:
221 break;
225 /* Get the file handles */
227 OutputFile = Gbl_Files[FileId].Handle;
230 if (!Enode->SourceLine)
232 /* Use the merged header/source file if present, otherwise use input file */
234 SourceFile = Gbl_Files[ASL_FILE_SOURCE_OUTPUT].Handle;
235 if (!SourceFile)
237 SourceFile = Gbl_Files[ASL_FILE_INPUT].Handle;
240 if (SourceFile)
242 /* Determine if the error occurred at source file EOF */
244 fseek (SourceFile, 0, SEEK_END);
245 FileSize = ftell (SourceFile);
247 if ((long) Enode->LogicalByteOffset >= FileSize)
249 PrematureEOF = TRUE;
254 if (Header)
256 fprintf (OutputFile, "%s", Header);
259 /* Print filename and line number if present and valid */
261 if (Enode->Filename)
263 if (Gbl_VerboseErrors)
265 fprintf (OutputFile, "%-8s", Enode->Filename);
267 if (Enode->LineNumber)
269 if (Enode->SourceLine)
271 fprintf (OutputFile, " %6u: %s",
272 Enode->LineNumber, Enode->SourceLine);
274 else
276 fprintf (OutputFile, " %6u: ", Enode->LineNumber);
279 * If not at EOF, get the corresponding source code line and
280 * display it. Don't attempt this if we have a premature EOF
281 * condition.
283 if (!PrematureEOF)
286 * Seek to the offset in the combined source file, read
287 * the source line, and write it to the output.
289 Actual = fseek (SourceFile, (long) Enode->LogicalByteOffset,
290 (int) SEEK_SET);
291 if (Actual)
293 fprintf (OutputFile,
294 "[*** iASL: Seek error on source code temp file %s ***]",
295 Gbl_Files[ASL_FILE_SOURCE_OUTPUT].Filename);
297 else
299 RActual = fread (&SourceByte, 1, 1, SourceFile);
300 if (RActual != 1)
302 fprintf (OutputFile,
303 "[*** iASL: Read error on source code temp file %s ***]",
304 Gbl_Files[ASL_FILE_SOURCE_OUTPUT].Filename);
306 else
308 /* Read/write the source line, up to the maximum line length */
310 while (RActual && SourceByte && (SourceByte != '\n'))
312 if (Total < 256)
314 /* After the max line length, we will just read the line, no write */
316 if (fwrite (&SourceByte, 1, 1, OutputFile) != 1)
318 printf ("[*** iASL: Write error on output file ***]\n");
319 return;
322 else if (Total == 256)
324 fprintf (OutputFile,
325 "\n[*** iASL: Very long input line, message below refers to column %u ***]",
326 Enode->Column);
329 RActual = fread (&SourceByte, 1, 1, SourceFile);
330 if (RActual != 1)
332 fprintf (OutputFile,
333 "[*** iASL: Read error on source code temp file %s ***]",
334 Gbl_Files[ASL_FILE_SOURCE_OUTPUT].Filename);
335 return;
337 Total++;
343 fprintf (OutputFile, "\n");
347 else
350 * Less verbose version of the error message, enabled via the
351 * -vi switch. The format is compatible with MS Visual Studio.
353 fprintf (OutputFile, "%s", Enode->Filename);
355 if (Enode->LineNumber)
357 fprintf (OutputFile, "(%u) : ",
358 Enode->LineNumber);
363 /* NULL message ID, just print the raw message */
365 if (Enode->MessageId == 0)
367 fprintf (OutputFile, "%s\n", Enode->Message);
369 else
371 /* Decode the message ID */
373 if (Gbl_VerboseErrors)
375 fprintf (OutputFile, "%s %4.4d -",
376 AslErrorLevel[Enode->Level],
377 Enode->MessageId + ((Enode->Level+1) * 1000));
379 else /* IDE case */
381 fprintf (OutputFile, "%s %4.4d:",
382 AslErrorLevelIde[Enode->Level],
383 Enode->MessageId + ((Enode->Level+1) * 1000));
386 MainMessage = AslMessages[Enode->MessageId];
387 ExtraMessage = Enode->Message;
389 if (Enode->LineNumber)
391 /* Main message: try to use string from AslMessages first */
393 if (!MainMessage)
395 MainMessage = "";
398 MsgLength = strlen (MainMessage);
399 if (MsgLength == 0)
401 /* Use the secondary/extra message as main message */
403 MainMessage = Enode->Message;
404 if (!MainMessage)
406 MainMessage = "";
409 MsgLength = strlen (MainMessage);
410 ExtraMessage = NULL;
413 if (Gbl_VerboseErrors && !PrematureEOF)
415 if (Total >= 256)
417 fprintf (OutputFile, " %s",
418 MainMessage);
420 else
422 SourceColumn = Enode->Column + Enode->FilenameLength + 6 + 2;
423 ErrorColumn = ASL_ERROR_LEVEL_LENGTH + 5 + 2 + 1;
425 if ((MsgLength + ErrorColumn) < (SourceColumn - 1))
427 fprintf (OutputFile, "%*s%s",
428 (int) ((SourceColumn - 1) - ErrorColumn),
429 MainMessage, " ^ ");
431 else
433 fprintf (OutputFile, "%*s %s",
434 (int) ((SourceColumn - ErrorColumn) + 1), "^",
435 MainMessage);
439 else
441 fprintf (OutputFile, " %s", MainMessage);
444 /* Print the extra info message if present */
446 if (ExtraMessage)
448 fprintf (OutputFile, " (%s)", ExtraMessage);
451 if (PrematureEOF)
453 fprintf (OutputFile, " and premature End-Of-File");
456 fprintf (OutputFile, "\n");
457 if (Gbl_VerboseErrors)
459 fprintf (OutputFile, "\n");
462 else
464 fprintf (OutputFile, " %s %s\n\n", MainMessage, ExtraMessage);
470 /*******************************************************************************
472 * FUNCTION: AePrintErrorLog
474 * PARAMETERS: FileId - Where to output the error log
476 * RETURN: None
478 * DESCRIPTION: Print the entire contents of the error log
480 ******************************************************************************/
482 void
483 AePrintErrorLog (
484 UINT32 FileId)
486 ASL_ERROR_MSG *Enode = Gbl_ErrorLog;
489 /* Walk the error node list */
491 while (Enode)
493 AePrintException (FileId, Enode, NULL);
494 Enode = Enode->Next;
499 /*******************************************************************************
501 * FUNCTION: AslCommonError2
503 * PARAMETERS: Level - Seriousness (Warning/error, etc.)
504 * MessageId - Index into global message buffer
505 * LineNumber - Actual file line number
506 * Column - Column in current line
507 * SourceLine - Actual source code line
508 * Filename - source filename
509 * ExtraMessage - additional error message
511 * RETURN: None
513 * DESCRIPTION: Create a new error node and add it to the error log
515 ******************************************************************************/
517 void
518 AslCommonError2 (
519 UINT8 Level,
520 UINT8 MessageId,
521 UINT32 LineNumber,
522 UINT32 Column,
523 char *SourceLine,
524 char *Filename,
525 char *ExtraMessage)
527 char *MessageBuffer = NULL;
528 char *LineBuffer;
529 ASL_ERROR_MSG *Enode;
532 Enode = UtLocalCalloc (sizeof (ASL_ERROR_MSG));
534 if (ExtraMessage)
536 /* Allocate a buffer for the message and a new error node */
538 MessageBuffer = UtLocalCalloc (strlen (ExtraMessage) + 1);
540 /* Keep a copy of the extra message */
542 ACPI_STRCPY (MessageBuffer, ExtraMessage);
545 LineBuffer = UtLocalCalloc (strlen (SourceLine) + 1);
546 ACPI_STRCPY (LineBuffer, SourceLine);
548 /* Initialize the error node */
550 if (Filename)
552 Enode->Filename = Filename;
553 Enode->FilenameLength = strlen (Filename);
554 if (Enode->FilenameLength < 6)
556 Enode->FilenameLength = 6;
560 Enode->MessageId = MessageId;
561 Enode->Level = Level;
562 Enode->LineNumber = LineNumber;
563 Enode->LogicalLineNumber = LineNumber;
564 Enode->LogicalByteOffset = 0;
565 Enode->Column = Column;
566 Enode->Message = MessageBuffer;
567 Enode->SourceLine = LineBuffer;
569 /* Add the new node to the error node list */
571 AeAddToErrorLog (Enode);
573 if (Gbl_DebugFlag)
575 /* stderr is a file, send error to it immediately */
577 AePrintException (ASL_FILE_STDERR, Enode, NULL);
580 Gbl_ExceptionCount[Level]++;
584 /*******************************************************************************
586 * FUNCTION: AslCommonError
588 * PARAMETERS: Level - Seriousness (Warning/error, etc.)
589 * MessageId - Index into global message buffer
590 * CurrentLineNumber - Actual file line number
591 * LogicalLineNumber - Cumulative line number
592 * LogicalByteOffset - Byte offset in source file
593 * Column - Column in current line
594 * Filename - source filename
595 * ExtraMessage - additional error message
597 * RETURN: None
599 * DESCRIPTION: Create a new error node and add it to the error log
601 ******************************************************************************/
603 void
604 AslCommonError (
605 UINT8 Level,
606 UINT8 MessageId,
607 UINT32 CurrentLineNumber,
608 UINT32 LogicalLineNumber,
609 UINT32 LogicalByteOffset,
610 UINT32 Column,
611 char *Filename,
612 char *ExtraMessage)
614 char *MessageBuffer = NULL;
615 ASL_ERROR_MSG *Enode;
618 Enode = UtLocalCalloc (sizeof (ASL_ERROR_MSG));
620 if (ExtraMessage)
622 /* Allocate a buffer for the message and a new error node */
624 MessageBuffer = UtLocalCalloc (strlen (ExtraMessage) + 1);
626 /* Keep a copy of the extra message */
628 ACPI_STRCPY (MessageBuffer, ExtraMessage);
631 /* Initialize the error node */
633 if (Filename)
635 Enode->Filename = Filename;
636 Enode->FilenameLength = strlen (Filename);
637 if (Enode->FilenameLength < 6)
639 Enode->FilenameLength = 6;
643 Enode->MessageId = MessageId;
644 Enode->Level = Level;
645 Enode->LineNumber = CurrentLineNumber;
646 Enode->LogicalLineNumber = LogicalLineNumber;
647 Enode->LogicalByteOffset = LogicalByteOffset;
648 Enode->Column = Column;
649 Enode->Message = MessageBuffer;
650 Enode->SourceLine = NULL;
652 /* Add the new node to the error node list */
654 AeAddToErrorLog (Enode);
656 if (Gbl_DebugFlag)
658 /* stderr is a file, send error to it immediately */
660 AePrintException (ASL_FILE_STDERR, Enode, NULL);
663 Gbl_ExceptionCount[Level]++;
664 if (Gbl_ExceptionCount[ASL_ERROR] > ASL_MAX_ERROR_COUNT)
666 printf ("\nMaximum error count (%u) exceeded\n", ASL_MAX_ERROR_COUNT);
668 Gbl_SourceLine = 0;
669 Gbl_NextError = Gbl_ErrorLog;
670 CmCleanupAndExit ();
671 exit(1);
674 return;
678 /*******************************************************************************
680 * FUNCTION: AslDisableException
682 * PARAMETERS: MessageIdString - ID to be disabled
684 * RETURN: Status
686 * DESCRIPTION: Enter a message ID into the global disabled messages table
688 ******************************************************************************/
690 ACPI_STATUS
691 AslDisableException (
692 char *MessageIdString)
694 UINT32 MessageId;
697 /* Convert argument to an integer and validate it */
699 MessageId = (UINT32) strtoul (MessageIdString, NULL, 0);
701 if ((MessageId < 2000) || (MessageId > 5999))
703 printf ("\"%s\" is not a valid warning/remark ID\n",
704 MessageIdString);
705 return (AE_BAD_PARAMETER);
708 /* Insert value into the global disabled message array */
710 if (Gbl_DisabledMessagesIndex >= ASL_MAX_DISABLED_MESSAGES)
712 printf ("Too many messages have been disabled (max %u)\n",
713 ASL_MAX_DISABLED_MESSAGES);
714 return (AE_LIMIT);
717 Gbl_DisabledMessages[Gbl_DisabledMessagesIndex] = MessageId;
718 Gbl_DisabledMessagesIndex++;
719 return (AE_OK);
723 /*******************************************************************************
725 * FUNCTION: AslIsExceptionDisabled
727 * PARAMETERS: Level - Seriousness (Warning/error, etc.)
728 * MessageId - Index into global message buffer
730 * RETURN: TRUE if exception/message should be ignored
732 * DESCRIPTION: Check if the user has specified options such that this
733 * exception should be ignored
735 ******************************************************************************/
737 BOOLEAN
738 AslIsExceptionDisabled (
739 UINT8 Level,
740 UINT8 MessageId)
742 UINT32 EncodedMessageId;
743 UINT32 i;
746 switch (Level)
748 case ASL_WARNING2:
749 case ASL_WARNING3:
751 /* Check for global disable via -w1/-w2/-w3 options */
753 if (Level > Gbl_WarningLevel)
755 return (TRUE);
757 /* Fall through */
759 case ASL_WARNING:
760 case ASL_REMARK:
762 * Ignore this warning/remark if it has been disabled by
763 * the user (-vw option)
765 EncodedMessageId = MessageId + ((Level + 1) * 1000);
766 for (i = 0; i < Gbl_DisabledMessagesIndex; i++)
768 /* Simple implementation via fixed array */
770 if (EncodedMessageId == Gbl_DisabledMessages[i])
772 return (TRUE);
775 break;
777 default:
778 break;
781 return (FALSE);
785 /*******************************************************************************
787 * FUNCTION: AslError
789 * PARAMETERS: Level - Seriousness (Warning/error, etc.)
790 * MessageId - Index into global message buffer
791 * Op - Parse node where error happened
792 * ExtraMessage - additional error message
794 * RETURN: None
796 * DESCRIPTION: Main error reporting routine for the ASL compiler (all code
797 * except the parser.)
799 ******************************************************************************/
801 void
802 AslError (
803 UINT8 Level,
804 UINT8 MessageId,
805 ACPI_PARSE_OBJECT *Op,
806 char *ExtraMessage)
809 /* Check if user wants to ignore this exception */
811 if (AslIsExceptionDisabled (Level, MessageId))
813 return;
816 if (Op)
818 AslCommonError (Level, MessageId, Op->Asl.LineNumber,
819 Op->Asl.LogicalLineNumber,
820 Op->Asl.LogicalByteOffset,
821 Op->Asl.Column,
822 Op->Asl.Filename, ExtraMessage);
824 else
826 AslCommonError (Level, MessageId, 0,
827 0, 0, 0, NULL, ExtraMessage);
832 /*******************************************************************************
834 * FUNCTION: AslCoreSubsystemError
836 * PARAMETERS: Op - Parse node where error happened
837 * Status - The ACPI CA Exception
838 * ExtraMessage - additional error message
839 * Abort - TRUE -> Abort compilation
841 * RETURN: None
843 * DESCRIPTION: Error reporting routine for exceptions returned by the ACPI
844 * CA core subsystem.
846 ******************************************************************************/
848 void
849 AslCoreSubsystemError (
850 ACPI_PARSE_OBJECT *Op,
851 ACPI_STATUS Status,
852 char *ExtraMessage,
853 BOOLEAN Abort)
856 sprintf (MsgBuffer, "%s %s", AcpiFormatException (Status), ExtraMessage);
858 if (Op)
860 AslCommonError (ASL_ERROR, ASL_MSG_CORE_EXCEPTION, Op->Asl.LineNumber,
861 Op->Asl.LogicalLineNumber,
862 Op->Asl.LogicalByteOffset,
863 Op->Asl.Column,
864 Op->Asl.Filename, MsgBuffer);
866 else
868 AslCommonError (ASL_ERROR, ASL_MSG_CORE_EXCEPTION, 0,
869 0, 0, 0, NULL, MsgBuffer);
872 if (Abort)
874 AslAbort ();
879 /*******************************************************************************
881 * FUNCTION: AslCompilererror
883 * PARAMETERS: CompilerMessage - Error message from the parser
885 * RETURN: Status (0 for now)
887 * DESCRIPTION: Report an error situation discovered in a production
888 * NOTE: don't change the name of this function, it is called
889 * from the auto-generated parser.
891 ******************************************************************************/
894 AslCompilererror (
895 const char *CompilerMessage)
898 AslCommonError (ASL_ERROR, ASL_MSG_SYNTAX, Gbl_CurrentLineNumber,
899 Gbl_LogicalLineNumber, Gbl_CurrentLineOffset,
900 Gbl_CurrentColumn, Gbl_Files[ASL_FILE_INPUT].Filename,
901 ACPI_CAST_PTR (char, CompilerMessage));
903 return (0);