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