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