]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/contrib/dev/acpica/compiler/aslerror.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sys / contrib / dev / acpica / compiler / aslerror.c
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