aslerror.c revision 217365
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
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            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
392void
393AePrintErrorLog (
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
428void
429AslCommonError (
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
521void
522AslError (
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
576void
577AslCoreSubsystemError (
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
621int
622AslCompilererror (
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
635