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