aslerror.c revision 234623
1130803Smarcel
2130803Smarcel/******************************************************************************
3130803Smarcel *
4130803Smarcel * Module Name: aslerror - Error handling and statistics
598944Sobrien *
698944Sobrien *****************************************************************************/
798944Sobrien
898944Sobrien/*
998944Sobrien * Copyright (C) 2000 - 2012, Intel Corp.
1098944Sobrien * All rights reserved.
1198944Sobrien *
1298944Sobrien * Redistribution and use in source and binary forms, with or without
1398944Sobrien * modification, are permitted provided that the following conditions
1498944Sobrien * are met:
1598944Sobrien * 1. Redistributions of source code must retain the above copyright
1698944Sobrien *    notice, this list of conditions, and the following disclaimer,
1798944Sobrien *    without modification.
1898944Sobrien * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1998944Sobrien *    substantially similar to the "NO WARRANTY" disclaimer below
2098944Sobrien *    ("Disclaimer") and any redistribution must be conditioned upon
2198944Sobrien *    including a substantially similar Disclaimer requirement for further
2298944Sobrien *    binary redistribution.
2398944Sobrien * 3. Neither the names of the above-listed copyright holders nor the names
24130803Smarcel *    of any contributors may be used to endorse or promote products derived
25130803Smarcel *    from this software without specific prior written permission.
26130803Smarcel *
27130803Smarcel * Alternatively, this software may be distributed under the terms of the
28130803Smarcel * GNU General Public License ("GPL") version 2 as published by the Free
2998944Sobrien * Software Foundation.
3098944Sobrien *
3198944Sobrien * NO WARRANTY
3298944Sobrien * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3398944Sobrien * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3498944Sobrien * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
3598944Sobrien * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3698944Sobrien * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3798944Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3898944Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3998944Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
4098944Sobrien * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
4198944Sobrien * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
4298944Sobrien * POSSIBILITY OF SUCH DAMAGES.
4398944Sobrien */
4498944Sobrien
4598944Sobrien#define ASL_EXCEPTIONS
4698944Sobrien#include <contrib/dev/acpica/compiler/aslcompiler.h>
4798944Sobrien
4898944Sobrien#define _COMPONENT          ACPI_COMPILER
4998944Sobrien        ACPI_MODULE_NAME    ("aslerror")
5098944Sobrien
5198944Sobrien/* Local prototypes */
5298944Sobrien
5398944Sobrienstatic void
5498944SobrienAeAddToErrorLog (
5598944Sobrien    ASL_ERROR_MSG           *Enode);
5698944Sobrien
5798944Sobrien
5898944Sobrien/*******************************************************************************
5998944Sobrien *
6098944Sobrien * FUNCTION:    AeClearErrorLog
6198944Sobrien *
6298944Sobrien * PARAMETERS:  None
6398944Sobrien *
6498944Sobrien * RETURN:      None
6598944Sobrien *
6698944Sobrien * DESCRIPTION: Empty the error list
6798944Sobrien *
6898944Sobrien ******************************************************************************/
6998944Sobrien
7098944Sobrienvoid
7198944SobrienAeClearErrorLog (
7298944Sobrien    void)
7398944Sobrien{
7498944Sobrien    ASL_ERROR_MSG           *Enode = Gbl_ErrorLog;
7598944Sobrien    ASL_ERROR_MSG           *Next;
7698944Sobrien
7798944Sobrien    /* Walk the error node list */
7898944Sobrien
7998944Sobrien    while (Enode)
8098944Sobrien    {
81130803Smarcel        Next = Enode->Next;
82130803Smarcel        ACPI_FREE (Enode);
8398944Sobrien        Enode = Next;
8498944Sobrien    }
8598944Sobrien
8698944Sobrien    Gbl_ErrorLog = NULL;
8798944Sobrien}
8898944Sobrien
8998944Sobrien
9098944Sobrien/*******************************************************************************
9198944Sobrien *
9298944Sobrien * FUNCTION:    AeAddToErrorLog
9398944Sobrien *
9498944Sobrien * PARAMETERS:  Enode       - An error node to add to the log
9598944Sobrien *
9698944Sobrien * RETURN:      None
9798944Sobrien *
9898944Sobrien * DESCRIPTION: Add a new error node to the error log.  The error log is
9998944Sobrien *              ordered by the "logical" line number (cumulative line number
10098944Sobrien *              including all include files.)
10198944Sobrien *
10298944Sobrien ******************************************************************************/
10398944Sobrien
10498944Sobrienstatic void
10598944SobrienAeAddToErrorLog (
10698944Sobrien    ASL_ERROR_MSG           *Enode)
10798944Sobrien{
10898944Sobrien    ASL_ERROR_MSG           *Next;
10998944Sobrien    ASL_ERROR_MSG           *Prev;
11098944Sobrien
11198944Sobrien
11298944Sobrien    /* If Gbl_ErrorLog is null, this is the first error node */
11398944Sobrien
11498944Sobrien    if (!Gbl_ErrorLog)
11598944Sobrien    {
11698944Sobrien        Gbl_ErrorLog = Enode;
11798944Sobrien        return;
11898944Sobrien    }
11998944Sobrien
12098944Sobrien    /*
121130803Smarcel     * Walk error list until we find a line number greater than ours.
122130803Smarcel     * List is sorted according to line number.
123130803Smarcel     */
124130803Smarcel    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, "%-8s", 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                    fprintf (OutputFile, " %6u: ", Enode->LineNumber);
274
275                    /*
276                     * If not at EOF, get the corresponding source code line and
277                     * display it. Don't attempt this if we have a premature EOF
278                     * condition.
279                     */
280                    if (!PrematureEOF)
281                    {
282                        /*
283                         * Seek to the offset in the combined source file, read
284                         * the source line, and write it to the output.
285                         */
286                        Actual = fseek (SourceFile, (long) Enode->LogicalByteOffset,
287                                    (int) SEEK_SET);
288                        if (Actual)
289                        {
290                            fprintf (OutputFile,
291                                "[*** iASL: Seek error on source code temp file %s ***]",
292                                Gbl_Files[ASL_FILE_SOURCE_OUTPUT].Filename);
293                        }
294                        else
295                        {
296                            RActual = fread (&SourceByte, 1, 1, SourceFile);
297                            if (!RActual)
298                            {
299                                fprintf (OutputFile,
300                                    "[*** iASL: Read error on source code temp file %s ***]",
301                                    Gbl_Files[ASL_FILE_SOURCE_OUTPUT].Filename);
302                            }
303
304                            else while (RActual && SourceByte && (SourceByte != '\n'))
305                            {
306                                fwrite (&SourceByte, 1, 1, OutputFile);
307                                RActual = fread (&SourceByte, 1, 1, SourceFile);
308                            }
309                        }
310                    }
311
312                    fprintf (OutputFile, "\n");
313                }
314            }
315        }
316        else
317        {
318            fprintf (OutputFile, "%s", Enode->Filename);
319
320            if (Enode->LineNumber)
321            {
322                fprintf (OutputFile, "(%u) i:%6u : ",
323                    Enode->LineNumber, Enode->LineNumber);
324            }
325        }
326    }
327
328    /* NULL message ID, just print the raw message */
329
330    if (Enode->MessageId == 0)
331    {
332        fprintf (OutputFile, "%s\n", Enode->Message);
333    }
334    else
335    {
336        /* Decode the message ID */
337
338        fprintf (OutputFile, "%s %4.4d - ",
339                    AslErrorLevel[Enode->Level],
340                    Enode->MessageId + ((Enode->Level+1) * 1000));
341
342        MainMessage = AslMessages[Enode->MessageId];
343        ExtraMessage = Enode->Message;
344
345        if (Enode->LineNumber)
346        {
347            /* Main message: try to use string from AslMessages first */
348
349            if (!MainMessage)
350            {
351                MainMessage = "";
352            }
353
354            MsgLength = strlen (MainMessage);
355            if (MsgLength == 0)
356            {
357                /* Use the secondary/extra message as main message */
358
359                MainMessage = Enode->Message;
360                if (!MainMessage)
361                {
362                    MainMessage = "";
363                }
364
365                MsgLength = strlen (MainMessage);
366                ExtraMessage = NULL;
367            }
368
369            if (Gbl_VerboseErrors && !PrematureEOF)
370            {
371                SourceColumn = Enode->Column + Enode->FilenameLength + 6 + 2;
372                ErrorColumn = ASL_ERROR_LEVEL_LENGTH + 5 + 2 + 1;
373
374                if ((MsgLength + ErrorColumn) < (SourceColumn - 1))
375                {
376                    fprintf (OutputFile, "%*s%s",
377                        (int) ((SourceColumn - 1) - ErrorColumn),
378                        MainMessage, " ^ ");
379                }
380                else
381                {
382                    fprintf (OutputFile, "%*s %s",
383                        (int) ((SourceColumn - ErrorColumn) + 1), "^",
384                        MainMessage);
385                }
386            }
387            else
388            {
389                fprintf (OutputFile, " %s", MainMessage);
390            }
391
392            /* Print the extra info message if present */
393
394            if (ExtraMessage)
395            {
396                fprintf (OutputFile, " (%s)", ExtraMessage);
397            }
398
399            if (PrematureEOF)
400            {
401                fprintf (OutputFile, " and premature End-Of-File");
402            }
403
404            fprintf (OutputFile, "\n");
405            if (Gbl_VerboseErrors)
406            {
407                fprintf (OutputFile, "\n");
408            }
409        }
410        else
411        {
412            fprintf (OutputFile, " %s %s\n\n", MainMessage, ExtraMessage);
413        }
414    }
415}
416
417
418/*******************************************************************************
419 *
420 * FUNCTION:    AePrintErrorLog
421 *
422 * PARAMETERS:  FileId           - Where to output the error log
423 *
424 * RETURN:      None
425 *
426 * DESCRIPTION: Print the entire contents of the error log
427 *
428 ******************************************************************************/
429
430void
431AePrintErrorLog (
432    UINT32                  FileId)
433{
434    ASL_ERROR_MSG           *Enode = Gbl_ErrorLog;
435
436
437    /* Walk the error node list */
438
439    while (Enode)
440    {
441        AePrintException (FileId, Enode, NULL);
442        Enode = Enode->Next;
443    }
444}
445
446
447/*******************************************************************************
448 *
449 * FUNCTION:    AslCommonError2
450 *
451 * PARAMETERS:  Level               - Seriousness (Warning/error, etc.)
452 *              MessageId           - Index into global message buffer
453 *              LineNumber          - Actual file line number
454 *              Column              - Column in current line
455 *              SourceLine          - Actual source code line
456 *              Filename            - source filename
457 *              ExtraMessage        - additional error message
458 *
459 * RETURN:      None
460 *
461 * DESCRIPTION: Create a new error node and add it to the error log
462 *
463 ******************************************************************************/
464
465void
466AslCommonError2 (
467    UINT8                   Level,
468    UINT8                   MessageId,
469    UINT32                  LineNumber,
470    UINT32                  Column,
471    char                    *SourceLine,
472    char                    *Filename,
473    char                    *ExtraMessage)
474{
475    char                    *MessageBuffer = NULL;
476    char                    *LineBuffer;
477    ASL_ERROR_MSG           *Enode;
478
479
480    Enode = UtLocalCalloc (sizeof (ASL_ERROR_MSG));
481
482    if (ExtraMessage)
483    {
484        /* Allocate a buffer for the message and a new error node */
485
486        MessageBuffer = UtLocalCalloc (strlen (ExtraMessage) + 1);
487
488        /* Keep a copy of the extra message */
489
490        ACPI_STRCPY (MessageBuffer, ExtraMessage);
491    }
492
493    LineBuffer = UtLocalCalloc (strlen (SourceLine) + 1);
494    ACPI_STRCPY (LineBuffer, SourceLine);
495
496    /* Initialize the error node */
497
498    if (Filename)
499    {
500        Enode->Filename       = Filename;
501        Enode->FilenameLength = strlen (Filename);
502        if (Enode->FilenameLength < 6)
503        {
504            Enode->FilenameLength = 6;
505        }
506    }
507
508    Enode->MessageId            = MessageId;
509    Enode->Level                = Level;
510    Enode->LineNumber           = LineNumber;
511    Enode->LogicalLineNumber    = LineNumber;
512    Enode->LogicalByteOffset    = 0;
513    Enode->Column               = Column;
514    Enode->Message              = MessageBuffer;
515    Enode->SourceLine           = LineBuffer;
516
517    /* Add the new node to the error node list */
518
519    AeAddToErrorLog (Enode);
520
521    if (Gbl_DebugFlag)
522    {
523        /* stderr is a file, send error to it immediately */
524
525        AePrintException (ASL_FILE_STDERR, Enode, NULL);
526    }
527
528    Gbl_ExceptionCount[Level]++;
529}
530
531
532/*******************************************************************************
533 *
534 * FUNCTION:    AslCommonError
535 *
536 * PARAMETERS:  Level               - Seriousness (Warning/error, etc.)
537 *              MessageId           - Index into global message buffer
538 *              CurrentLineNumber   - Actual file line number
539 *              LogicalLineNumber   - Cumulative line number
540 *              LogicalByteOffset   - Byte offset in source file
541 *              Column              - Column in current line
542 *              Filename            - source filename
543 *              ExtraMessage        - additional error message
544 *
545 * RETURN:      None
546 *
547 * DESCRIPTION: Create a new error node and add it to the error log
548 *
549 ******************************************************************************/
550
551void
552AslCommonError (
553    UINT8                   Level,
554    UINT8                   MessageId,
555    UINT32                  CurrentLineNumber,
556    UINT32                  LogicalLineNumber,
557    UINT32                  LogicalByteOffset,
558    UINT32                  Column,
559    char                    *Filename,
560    char                    *ExtraMessage)
561{
562    UINT32                  MessageSize;
563    char                    *MessageBuffer = NULL;
564    ASL_ERROR_MSG           *Enode;
565
566
567    Enode = UtLocalCalloc (sizeof (ASL_ERROR_MSG));
568
569    if (ExtraMessage)
570    {
571        /* Allocate a buffer for the message and a new error node */
572
573        MessageSize   = strlen (ExtraMessage) + 1;
574        MessageBuffer = UtLocalCalloc (MessageSize);
575
576        /* Keep a copy of the extra message */
577
578        ACPI_STRCPY (MessageBuffer, ExtraMessage);
579    }
580
581    /* Initialize the error node */
582
583    if (Filename)
584    {
585        Enode->Filename       = Filename;
586        Enode->FilenameLength = strlen (Filename);
587        if (Enode->FilenameLength < 6)
588        {
589            Enode->FilenameLength = 6;
590        }
591    }
592
593    Enode->MessageId            = MessageId;
594    Enode->Level                = Level;
595    Enode->LineNumber           = CurrentLineNumber;
596    Enode->LogicalLineNumber    = LogicalLineNumber;
597    Enode->LogicalByteOffset    = LogicalByteOffset;
598    Enode->Column               = Column;
599    Enode->Message              = MessageBuffer;
600    Enode->SourceLine           = NULL;
601
602    /* Add the new node to the error node list */
603
604    AeAddToErrorLog (Enode);
605
606    if (Gbl_DebugFlag)
607    {
608        /* stderr is a file, send error to it immediately */
609
610        AePrintException (ASL_FILE_STDERR, Enode, NULL);
611    }
612
613    Gbl_ExceptionCount[Level]++;
614    if (Gbl_ExceptionCount[ASL_ERROR] > ASL_MAX_ERROR_COUNT)
615    {
616        printf ("\nMaximum error count (%u) exceeded\n", ASL_MAX_ERROR_COUNT);
617
618        Gbl_SourceLine = 0;
619        Gbl_NextError = Gbl_ErrorLog;
620        CmDoOutputFiles ();
621        CmCleanupAndExit ();
622        exit(1);
623    }
624
625    return;
626}
627
628
629/*******************************************************************************
630 *
631 * FUNCTION:    AslError
632 *
633 * PARAMETERS:  Level               - Seriousness (Warning/error, etc.)
634 *              MessageId           - Index into global message buffer
635 *              Op                  - Parse node where error happened
636 *              ExtraMessage        - additional error message
637 *
638 * RETURN:      None
639 *
640 * DESCRIPTION: Main error reporting routine for the ASL compiler (all code
641 *              except the parser.)
642 *
643 ******************************************************************************/
644
645void
646AslError (
647    UINT8                   Level,
648    UINT8                   MessageId,
649    ACPI_PARSE_OBJECT       *Op,
650    char                    *ExtraMessage)
651{
652
653    switch (Level)
654    {
655    case ASL_WARNING2:
656    case ASL_WARNING3:
657        if (Gbl_WarningLevel < Level)
658        {
659            return;
660        }
661        break;
662
663    default:
664        break;
665    }
666
667    if (Op)
668    {
669        AslCommonError (Level, MessageId, Op->Asl.LineNumber,
670                        Op->Asl.LogicalLineNumber,
671                        Op->Asl.LogicalByteOffset,
672                        Op->Asl.Column,
673                        Op->Asl.Filename, ExtraMessage);
674    }
675    else
676    {
677        AslCommonError (Level, MessageId, 0,
678                        0, 0, 0, NULL, ExtraMessage);
679    }
680}
681
682
683/*******************************************************************************
684 *
685 * FUNCTION:    AslCoreSubsystemError
686 *
687 * PARAMETERS:  Op                  - Parse node where error happened
688 *              Status              - The ACPI CA Exception
689 *              ExtraMessage        - additional error message
690 *              Abort               - TRUE -> Abort compilation
691 *
692 * RETURN:      None
693 *
694 * DESCRIPTION: Error reporting routine for exceptions returned by the ACPI
695 *              CA core subsystem.
696 *
697 ******************************************************************************/
698
699void
700AslCoreSubsystemError (
701    ACPI_PARSE_OBJECT       *Op,
702    ACPI_STATUS             Status,
703    char                    *ExtraMessage,
704    BOOLEAN                 Abort)
705{
706
707    sprintf (MsgBuffer, "%s %s", AcpiFormatException (Status), ExtraMessage);
708
709    if (Op)
710    {
711        AslCommonError (ASL_ERROR, ASL_MSG_CORE_EXCEPTION, Op->Asl.LineNumber,
712                        Op->Asl.LogicalLineNumber,
713                        Op->Asl.LogicalByteOffset,
714                        Op->Asl.Column,
715                        Op->Asl.Filename, MsgBuffer);
716    }
717    else
718    {
719        AslCommonError (ASL_ERROR, ASL_MSG_CORE_EXCEPTION, 0,
720                        0, 0, 0, NULL, MsgBuffer);
721    }
722
723    if (Abort)
724    {
725        AslAbort ();
726    }
727}
728
729
730/*******************************************************************************
731 *
732 * FUNCTION:    AslCompilererror
733 *
734 * PARAMETERS:  CompilerMessage         - Error message from the parser
735 *
736 * RETURN:      Status (0 for now)
737 *
738 * DESCRIPTION: Report an error situation discovered in a production
739 *              NOTE: don't change the name of this function, it is called
740 *              from the auto-generated parser.
741 *
742 ******************************************************************************/
743
744int
745AslCompilererror (
746    const char              *CompilerMessage)
747{
748
749    AslCommonError (ASL_ERROR, ASL_MSG_SYNTAX, Gbl_CurrentLineNumber,
750        Gbl_LogicalLineNumber, Gbl_CurrentLineOffset,
751        Gbl_CurrentColumn, Gbl_Files[ASL_FILE_INPUT].Filename,
752        ACPI_CAST_PTR (char, CompilerMessage));
753
754    return 0;
755}
756