prscan.c revision 256281
1266987Smarkj/******************************************************************************
2266987Smarkj *
3266987Smarkj * Module Name: prscan - Preprocessor start-up and file scan module
4266987Smarkj *
5266987Smarkj *****************************************************************************/
6266987Smarkj
7266987Smarkj/*
8266987Smarkj * Copyright (C) 2000 - 2013, Intel Corp.
9266987Smarkj * All rights reserved.
10266987Smarkj *
11266987Smarkj * Redistribution and use in source and binary forms, with or without
12266987Smarkj * modification, are permitted provided that the following conditions
13266987Smarkj * are met:
14266987Smarkj * 1. Redistributions of source code must retain the above copyright
15266987Smarkj *    notice, this list of conditions, and the following disclaimer,
16266987Smarkj *    without modification.
17266987Smarkj * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18266987Smarkj *    substantially similar to the "NO WARRANTY" disclaimer below
19266987Smarkj *    ("Disclaimer") and any redistribution must be conditioned upon
20266987Smarkj *    including a substantially similar Disclaimer requirement for further
21266987Smarkj *    binary redistribution.
22266987Smarkj * 3. Neither the names of the above-listed copyright holders nor the names
23266987Smarkj *    of any contributors may be used to endorse or promote products derived
24266987Smarkj *    from this software without specific prior written permission.
25266987Smarkj *
26266987Smarkj * Alternatively, this software may be distributed under the terms of the
27266987Smarkj * GNU General Public License ("GPL") version 2 as published by the Free
28266987Smarkj * Software Foundation.
29266987Smarkj *
30266987Smarkj * NO WARRANTY
31266987Smarkj * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32266987Smarkj * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33266987Smarkj * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34266987Smarkj * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35266987Smarkj * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36266987Smarkj * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37266987Smarkj * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38266987Smarkj * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39266987Smarkj * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40266987Smarkj * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41266987Smarkj * POSSIBILITY OF SUCH DAMAGES.
42266987Smarkj */
43266987Smarkj
44266987Smarkj#define _DECLARE_PR_GLOBALS
45266987Smarkj
46266987Smarkj#include <contrib/dev/acpica/compiler/aslcompiler.h>
47266987Smarkj#include <contrib/dev/acpica/compiler/dtcompiler.h>
48266987Smarkj
49266987Smarkj/*
50266987Smarkj * TBDs:
51266987Smarkj *
52266987Smarkj * No nested macros, maybe never
53266987Smarkj * Implement ASL "Include" as well as "#include" here?
54266987Smarkj */
55266987Smarkj#define _COMPONENT          ASL_PREPROCESSOR
56266987Smarkj        ACPI_MODULE_NAME    ("prscan")
57266987Smarkj
58266987Smarkj
59266987Smarkj/* Local prototypes */
60266987Smarkj
61266987Smarkjstatic void
62PrPreprocessInputFile (
63    void);
64
65static void
66PrDoDirective (
67    char                    *DirectiveToken,
68    char                    **Next);
69
70static int
71PrMatchDirective (
72    char                    *Directive);
73
74static void
75PrPushDirective (
76    int                     Directive,
77    char                    *Argument);
78
79static ACPI_STATUS
80PrPopDirective (
81    void);
82
83static void
84PrDbgPrint (
85    char                    *Action,
86    char                    *DirectiveName);
87
88
89/*
90 * Supported preprocessor directives
91 */
92static const PR_DIRECTIVE_INFO      Gbl_DirectiveInfo[] =
93{
94    {"define",  1},
95    {"elif",    0}, /* Converted to #else..#if internally */
96    {"else",    0},
97    {"endif",   0},
98    {"error",   1},
99    {"if",      1},
100    {"ifdef",   1},
101    {"ifndef",  1},
102    {"include", 0}, /* Argument is not standard format, so 0 */
103    {"line",    1},
104    {"pragma",  1},
105    {"undef",   1},
106    {"warning", 1},
107    {NULL,      0}
108};
109
110enum Gbl_DirectiveIndexes
111{
112    PR_DIRECTIVE_DEFINE = 0,
113    PR_DIRECTIVE_ELIF,
114    PR_DIRECTIVE_ELSE,
115    PR_DIRECTIVE_ENDIF,
116    PR_DIRECTIVE_ERROR,
117    PR_DIRECTIVE_IF,
118    PR_DIRECTIVE_IFDEF,
119    PR_DIRECTIVE_IFNDEF,
120    PR_DIRECTIVE_INCLUDE,
121    PR_DIRECTIVE_LINE,
122    PR_DIRECTIVE_PRAGMA,
123    PR_DIRECTIVE_UNDEF,
124    PR_DIRECTIVE_WARNING,
125};
126
127#define ASL_DIRECTIVE_NOT_FOUND     -1
128
129
130/*******************************************************************************
131 *
132 * FUNCTION:    PrInitializePreprocessor
133 *
134 * PARAMETERS:  None
135 *
136 * RETURN:      None
137 *
138 * DESCRIPTION: Startup initialization for the Preprocessor.
139 *
140 ******************************************************************************/
141
142void
143PrInitializePreprocessor (
144    void)
145{
146    /* Init globals and the list of #defines */
147
148    PrInitializeGlobals ();
149    Gbl_DefineList = NULL;
150}
151
152
153/*******************************************************************************
154 *
155 * FUNCTION:    PrInitializeGlobals
156 *
157 * PARAMETERS:  None
158 *
159 * RETURN:      None
160 *
161 * DESCRIPTION: Initialize globals for the Preprocessor. Used for startuup
162 *              initialization and re-initialization between compiles during
163 *              a multiple source file compile.
164 *
165 ******************************************************************************/
166
167void
168PrInitializeGlobals (
169    void)
170{
171    /* Init globals */
172
173    Gbl_InputFileList = NULL;
174    Gbl_CurrentLineNumber = 0;
175    Gbl_PreprocessorLineNumber = 1;
176    Gbl_PreprocessorError = FALSE;
177
178    /* These are used to track #if/#else blocks (possibly nested) */
179
180    Gbl_IfDepth = 0;
181    Gbl_IgnoringThisCodeBlock = FALSE;
182    Gbl_DirectiveStack = NULL;
183}
184
185
186/*******************************************************************************
187 *
188 * FUNCTION:    PrTerminatePreprocessor
189 *
190 * PARAMETERS:  None
191 *
192 * RETURN:      None
193 *
194 * DESCRIPTION: Termination of the preprocessor. Delete lists. Keep any
195 *              defines that were specified on the command line, in order to
196 *              support multiple compiles with a single compiler invocation.
197 *
198 ******************************************************************************/
199
200void
201PrTerminatePreprocessor (
202    void)
203{
204    PR_DEFINE_INFO          *DefineInfo;
205
206
207    /*
208     * The persistent defines (created on the command line) are always at the
209     * end of the list. We save them.
210     */
211    while ((Gbl_DefineList) && (!Gbl_DefineList->Persist))
212    {
213        DefineInfo = Gbl_DefineList;
214        Gbl_DefineList = DefineInfo->Next;
215
216        ACPI_FREE (DefineInfo->Replacement);
217        ACPI_FREE (DefineInfo->Identifier);
218        ACPI_FREE (DefineInfo);
219    }
220}
221
222
223/*******************************************************************************
224 *
225 * FUNCTION:    PrDoPreprocess
226 *
227 * PARAMETERS:  None
228 *
229 * RETURN:      None
230 *
231 * DESCRIPTION: Main entry point for the iASL Preprocessor. Input file must
232 *              be already open. Handles multiple input files via the
233 *              #include directive.
234 *
235 ******************************************************************************/
236
237void
238PrDoPreprocess (
239    void)
240{
241    BOOLEAN                 MoreInputFiles;
242
243
244    DbgPrint (ASL_DEBUG_OUTPUT, "Starting preprocessing phase\n\n");
245
246
247    FlSeekFile (ASL_FILE_INPUT, 0);
248    PrDumpPredefinedNames ();
249
250    /* Main preprocessor loop, handles include files */
251
252    do
253    {
254        PrPreprocessInputFile ();
255        MoreInputFiles = PrPopInputFileStack ();
256
257    } while (MoreInputFiles);
258
259    /* Point compiler input to the new preprocessor output file (.i) */
260
261    FlCloseFile (ASL_FILE_INPUT);
262    Gbl_Files[ASL_FILE_INPUT].Handle = Gbl_Files[ASL_FILE_PREPROCESSOR].Handle;
263    AslCompilerin = Gbl_Files[ASL_FILE_INPUT].Handle;
264
265    /* Reset globals to allow compiler to run */
266
267    FlSeekFile (ASL_FILE_INPUT, 0);
268    Gbl_CurrentLineNumber = 1;
269
270    DbgPrint (ASL_DEBUG_OUTPUT, "Preprocessing phase complete \n\n");
271}
272
273
274/*******************************************************************************
275 *
276 * FUNCTION:    PrPreprocessInputFile
277 *
278 * PARAMETERS:  None
279 *
280 * RETURN:      None
281 *
282 * DESCRIPTION: Preprocess one entire file, line-by-line.
283 *
284 * Input:  Raw user ASL from ASL_FILE_INPUT
285 * Output: Preprocessed file written to ASL_FILE_PREPROCESSOR
286 *
287 ******************************************************************************/
288
289static void
290PrPreprocessInputFile (
291    void)
292{
293    UINT32                  Offset;
294    char                    *Token;
295    char                    *ReplaceString;
296    PR_DEFINE_INFO          *DefineInfo;
297    ACPI_SIZE               TokenOffset;
298    char                    *Next;
299    int                     OffsetAdjust;
300
301
302    /* Scan line-by-line. Comments and blank lines are skipped by this function */
303
304    while ((Offset = DtGetNextLine (Gbl_Files[ASL_FILE_INPUT].Handle)) != ASL_EOF)
305    {
306        /* Need a copy of the input line for strok() */
307
308        strcpy (Gbl_MainTokenBuffer, Gbl_CurrentLineBuffer);
309        Token = PrGetNextToken (Gbl_MainTokenBuffer, PR_TOKEN_SEPARATORS, &Next);
310        OffsetAdjust = 0;
311
312        /* All preprocessor directives must begin with '#' */
313
314        if (Token && (*Token == '#'))
315        {
316            if (strlen (Token) == 1)
317            {
318                Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, &Next);
319            }
320            else
321            {
322                Token++;    /* Skip leading # */
323            }
324
325            /* Execute the directive, do not write line to output file */
326
327            PrDoDirective (Token, &Next);
328            continue;
329        }
330
331        /*
332         * If we are currently within the part of an IF/ELSE block that is
333         * FALSE, ignore the line and do not write it to the output file.
334         * This continues until an #else or #endif is encountered.
335         */
336        if (Gbl_IgnoringThisCodeBlock)
337        {
338            continue;
339        }
340
341        /* Match and replace all #defined names within this source line */
342
343        while (Token)
344        {
345            DefineInfo = PrMatchDefine (Token);
346            if (DefineInfo)
347            {
348                if (DefineInfo->Body)
349                {
350                    /* This is a macro */
351
352                    DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
353                        "Matched Macro: %s->%s\n",
354                        Gbl_CurrentLineNumber, DefineInfo->Identifier,
355                        DefineInfo->Replacement);
356
357                    PrDoMacroInvocation (Gbl_MainTokenBuffer, Token,
358                        DefineInfo, &Next);
359                }
360                else
361                {
362                    ReplaceString = DefineInfo->Replacement;
363
364                    /* Replace the name in the original line buffer */
365
366                    TokenOffset = Token - Gbl_MainTokenBuffer + OffsetAdjust;
367                    PrReplaceData (
368                        &Gbl_CurrentLineBuffer[TokenOffset], strlen (Token),
369                        ReplaceString, strlen (ReplaceString));
370
371                    /* Adjust for length difference between old and new name length */
372
373                    OffsetAdjust += strlen (ReplaceString) - strlen (Token);
374
375                    DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
376                        "Matched #define: %s->%s\n",
377                        Gbl_CurrentLineNumber, Token,
378                        *ReplaceString ? ReplaceString : "(NULL STRING)");
379                }
380            }
381
382            Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, &Next);
383        }
384
385#if 0
386/* Line prefix */
387        FlPrintFile (ASL_FILE_PREPROCESSOR, "/* %14s  %.5u  i:%.5u */ ",
388            Gbl_Files[ASL_FILE_INPUT].Filename,
389            Gbl_CurrentLineNumber, Gbl_PreprocessorLineNumber);
390#endif
391
392        /*
393         * Emit a #line directive if necessary, to keep the line numbers in
394         * the (.i) file synchronized with the original source code file, so
395         * that the correct line number appears in any error messages
396         * generated by the actual compiler.
397         */
398        if (Gbl_CurrentLineNumber > (Gbl_PreviousLineNumber + 1))
399        {
400            FlPrintFile (ASL_FILE_PREPROCESSOR, "#line %u\n",
401                Gbl_CurrentLineNumber);
402        }
403
404        Gbl_PreviousLineNumber = Gbl_CurrentLineNumber;
405        Gbl_PreprocessorLineNumber++;
406
407        /*
408         * Now we can write the possibly modified source line to the
409         * preprocessor (.i) file
410         */
411        FlWriteFile (ASL_FILE_PREPROCESSOR, Gbl_CurrentLineBuffer,
412            strlen (Gbl_CurrentLineBuffer));
413    }
414}
415
416
417/*******************************************************************************
418 *
419 * FUNCTION:    PrDoDirective
420 *
421 * PARAMETERS:  Directive               - Pointer to directive name token
422 *              Next                    - "Next" buffer from GetNextToken
423 *
424 * RETURN:      None.
425 *
426 * DESCRIPTION: Main processing for all preprocessor directives
427 *
428 ******************************************************************************/
429
430static void
431PrDoDirective (
432    char                    *DirectiveToken,
433    char                    **Next)
434{
435    char                    *Token = Gbl_MainTokenBuffer;
436    char                    *Token2;
437    char                    *End;
438    UINT64                  Value;
439    ACPI_SIZE               TokenOffset;
440    int                     Directive;
441    ACPI_STATUS             Status;
442
443
444    if (!DirectiveToken)
445    {
446        goto SyntaxError;
447    }
448
449    Directive = PrMatchDirective (DirectiveToken);
450    if (Directive == ASL_DIRECTIVE_NOT_FOUND)
451    {
452        PrError (ASL_ERROR, ASL_MSG_UNKNOWN_DIRECTIVE,
453            THIS_TOKEN_OFFSET (DirectiveToken));
454
455        DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
456            "#%s: Unknown directive\n",
457            Gbl_CurrentLineNumber, DirectiveToken);
458        return;
459    }
460
461    /*
462     * If we are currently ignoring this block and we encounter a #else or
463     * #elif, we must ignore their blocks also if the parent block is also
464     * being ignored.
465     */
466    if (Gbl_IgnoringThisCodeBlock)
467    {
468        switch (Directive)
469        {
470        case PR_DIRECTIVE_ELSE:
471        case PR_DIRECTIVE_ELIF:
472
473            if (Gbl_DirectiveStack && Gbl_DirectiveStack->IgnoringThisCodeBlock)
474            {
475                PrDbgPrint ("Ignoring", Gbl_DirectiveInfo[Directive].Name);
476                return;
477            }
478            break;
479
480        default:
481            break;
482        }
483    }
484
485    /*
486     * Need to always check for #else, #elif, #endif regardless of
487     * whether we are ignoring the current code block, since these
488     * are conditional code block terminators.
489     */
490    switch (Directive)
491    {
492    case PR_DIRECTIVE_ELSE:
493
494        Gbl_IgnoringThisCodeBlock = !(Gbl_IgnoringThisCodeBlock);
495        PrDbgPrint ("Executing", "else block");
496        return;
497
498    case PR_DIRECTIVE_ELIF:
499
500        Gbl_IgnoringThisCodeBlock = !(Gbl_IgnoringThisCodeBlock);
501        Directive = PR_DIRECTIVE_IF;
502
503        if (Gbl_IgnoringThisCodeBlock == TRUE)
504        {
505            /* Not executing the ELSE part -- all done here */
506            PrDbgPrint ("Ignoring", "elif block");
507            return;
508        }
509
510        /*
511         * After this, we will execute the IF part further below.
512         * First, however, pop off the original #if directive.
513         */
514        if (ACPI_FAILURE (PrPopDirective ()))
515        {
516            PrError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL,
517                THIS_TOKEN_OFFSET (DirectiveToken));
518        }
519
520        PrDbgPrint ("Executing", "elif block");
521        break;
522
523    case PR_DIRECTIVE_ENDIF:
524
525        PrDbgPrint ("Executing", "endif");
526
527        /* Pop the owning #if/#ifdef/#ifndef */
528
529        if (ACPI_FAILURE (PrPopDirective ()))
530        {
531            PrError (ASL_ERROR, ASL_MSG_ENDIF_MISMATCH,
532                THIS_TOKEN_OFFSET (DirectiveToken));
533        }
534        return;
535
536    default:
537        break;
538    }
539
540    /* Most directives have at least one argument */
541
542    if (Gbl_DirectiveInfo[Directive].ArgCount == 1)
543    {
544        Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next);
545        if (!Token)
546        {
547            goto SyntaxError;
548        }
549    }
550
551    /*
552     * At this point, if we are ignoring the current code block,
553     * do not process any more directives (i.e., ignore them also.)
554     * For "if" style directives, open/push a new block anyway. We
555     * must do this to keep track of #endif directives
556     */
557    if (Gbl_IgnoringThisCodeBlock)
558    {
559        switch (Directive)
560        {
561        case PR_DIRECTIVE_IF:
562        case PR_DIRECTIVE_IFDEF:
563        case PR_DIRECTIVE_IFNDEF:
564
565            PrPushDirective (Directive, Token);
566            PrDbgPrint ("Ignoring", Gbl_DirectiveInfo[Directive].Name);
567            break;
568
569        default:
570            break;
571        }
572
573        return;
574    }
575
576    /*
577     * Execute the directive
578     */
579    PrDbgPrint ("Begin execution", Gbl_DirectiveInfo[Directive].Name);
580
581    switch (Directive)
582    {
583    case PR_DIRECTIVE_IF:
584
585        TokenOffset = Token - Gbl_MainTokenBuffer;
586
587        /* Need to expand #define macros in the expression string first */
588
589        Status = PrResolveIntegerExpression (
590            &Gbl_CurrentLineBuffer[TokenOffset-1], &Value);
591        if (ACPI_FAILURE (Status))
592        {
593            return;
594        }
595
596        PrPushDirective (Directive, Token);
597        if (!Value)
598        {
599            Gbl_IgnoringThisCodeBlock = TRUE;
600        }
601
602        DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
603            "Resolved #if: %8.8X%8.8X %s\n",
604            Gbl_CurrentLineNumber, ACPI_FORMAT_UINT64 (Value),
605            Gbl_IgnoringThisCodeBlock ? "<Skipping Block>" : "<Executing Block>");
606        break;
607
608    case PR_DIRECTIVE_IFDEF:
609
610        PrPushDirective (Directive, Token);
611        if (!PrMatchDefine (Token))
612        {
613            Gbl_IgnoringThisCodeBlock = TRUE;
614        }
615
616        PrDbgPrint ("Evaluated", "ifdef");
617        break;
618
619    case PR_DIRECTIVE_IFNDEF:
620
621        PrPushDirective (Directive, Token);
622        if (PrMatchDefine (Token))
623        {
624            Gbl_IgnoringThisCodeBlock = TRUE;
625        }
626
627        PrDbgPrint ("Evaluated", "ifndef");
628        break;
629
630    case PR_DIRECTIVE_DEFINE:
631        /*
632         * By definition, if first char after the name is a paren,
633         * this is a function macro.
634         */
635        TokenOffset = Token - Gbl_MainTokenBuffer + strlen (Token);
636        if (*(&Gbl_CurrentLineBuffer[TokenOffset]) == '(')
637        {
638#ifndef MACROS_SUPPORTED
639            AcpiOsPrintf ("%s ERROR - line %u: #define macros are not supported yet\n",
640                Gbl_CurrentLineBuffer, Gbl_CurrentLineNumber);
641            exit(1);
642#else
643            PrAddMacro (Token, Next);
644#endif
645        }
646        else
647        {
648            /* Use the remainder of the line for the #define */
649
650            Token2 = *Next;
651            if (Token2)
652            {
653                while ((*Token2 == ' ') || (*Token2 == '\t'))
654                {
655                    Token2++;
656                }
657                End = Token2;
658                while (*End != '\n')
659                {
660                    End++;
661                }
662                *End = 0;
663            }
664            else
665            {
666                Token2 = "";
667            }
668#if 0
669            Token2 = PrGetNextToken (NULL, "\n", /*PR_TOKEN_SEPARATORS,*/ Next);
670            if (!Token2)
671            {
672                Token2 = "";
673            }
674#endif
675            DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
676                "New #define: %s->%s\n",
677                Gbl_CurrentLineNumber, Token, Token2);
678
679            PrAddDefine (Token, Token2, FALSE);
680        }
681        break;
682
683    case PR_DIRECTIVE_ERROR:
684
685        /* Note: No macro expansion */
686
687        PrError (ASL_ERROR, ASL_MSG_ERROR_DIRECTIVE,
688            THIS_TOKEN_OFFSET (Token));
689
690        Gbl_SourceLine = 0;
691        Gbl_NextError = Gbl_ErrorLog;
692        CmCleanupAndExit ();
693        exit(1);
694
695    case PR_DIRECTIVE_INCLUDE:
696
697        Token = PrGetNextToken (NULL, " \"<>", Next);
698        if (!Token)
699        {
700            goto SyntaxError;
701        }
702
703        DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
704            "Start #include file \"%s\"\n", Gbl_CurrentLineNumber,
705            Token, Gbl_CurrentLineNumber);
706
707        PrOpenIncludeFile (Token);
708        break;
709
710    case PR_DIRECTIVE_LINE:
711
712        TokenOffset = Token - Gbl_MainTokenBuffer;
713
714        Status = PrResolveIntegerExpression (
715            &Gbl_CurrentLineBuffer[TokenOffset-1], &Value);
716        if (ACPI_FAILURE (Status))
717        {
718            return;
719        }
720
721        DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
722            "User #line invocation %s\n", Gbl_CurrentLineNumber,
723            Token);
724
725        /* Update local line numbers */
726
727        Gbl_CurrentLineNumber = (UINT32) Value;
728        Gbl_PreviousLineNumber = 0;
729
730        /* Emit #line into the preprocessor file */
731
732        FlPrintFile (ASL_FILE_PREPROCESSOR, "#line %u \"%s\"\n",
733            Gbl_CurrentLineNumber, Gbl_Files[ASL_FILE_INPUT].Filename);
734        break;
735
736    case PR_DIRECTIVE_PRAGMA:
737
738        if (!strcmp (Token, "disable"))
739        {
740            Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next);
741            if (!Token)
742            {
743                goto SyntaxError;
744            }
745
746            TokenOffset = Token - Gbl_MainTokenBuffer;
747            AslDisableException (&Gbl_CurrentLineBuffer[TokenOffset]);
748        }
749        else if (!strcmp (Token, "message"))
750        {
751            Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next);
752            if (!Token)
753            {
754                goto SyntaxError;
755            }
756
757            TokenOffset = Token - Gbl_MainTokenBuffer;
758            AcpiOsPrintf ("%s\n", &Gbl_CurrentLineBuffer[TokenOffset]);
759        }
760        else
761        {
762            PrError (ASL_ERROR, ASL_MSG_UNKNOWN_PRAGMA,
763                THIS_TOKEN_OFFSET (Token));
764            return;
765        }
766
767        break;
768
769    case PR_DIRECTIVE_UNDEF:
770
771        DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
772            "#undef: %s\n", Gbl_CurrentLineNumber, Token);
773
774        PrRemoveDefine (Token);
775        break;
776
777    case PR_DIRECTIVE_WARNING:
778
779        PrError (ASL_WARNING, ASL_MSG_WARNING_DIRECTIVE,
780            THIS_TOKEN_OFFSET (Token));
781        break;
782
783    default:
784
785        /* Should never get here */
786        DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
787            "Unrecognized directive: %u\n",
788            Gbl_CurrentLineNumber, Directive);
789        break;
790    }
791
792    return;
793
794SyntaxError:
795
796    PrError (ASL_ERROR, ASL_MSG_DIRECTIVE_SYNTAX,
797        THIS_TOKEN_OFFSET (DirectiveToken));
798    return;
799}
800
801
802/*******************************************************************************
803 *
804 * FUNCTION:    PrMatchDirective
805 *
806 * PARAMETERS:  Directive           - Pointer to directive name token
807 *
808 * RETURN:      Index into command array, -1 if not found
809 *
810 * DESCRIPTION: Lookup the incoming directive in the known directives table.
811 *
812 ******************************************************************************/
813
814static int
815PrMatchDirective (
816    char                    *Directive)
817{
818    int                     i;
819
820
821    if (!Directive || Directive[0] == 0)
822    {
823        return (ASL_DIRECTIVE_NOT_FOUND);
824    }
825
826    for (i = 0; Gbl_DirectiveInfo[i].Name; i++)
827    {
828        if (!strcmp (Gbl_DirectiveInfo[i].Name, Directive))
829        {
830            return (i);
831        }
832    }
833
834    return (ASL_DIRECTIVE_NOT_FOUND);    /* Command not recognized */
835}
836
837
838/*******************************************************************************
839 *
840 * FUNCTION:    PrPushDirective
841 *
842 * PARAMETERS:  Directive           - Encoded directive ID
843 *              Argument            - String containing argument to the
844 *                                    directive
845 *
846 * RETURN:      None
847 *
848 * DESCRIPTION: Push an item onto the directive stack. Used for processing
849 *              nested #if/#else type conditional compilation directives.
850 *              Specifically: Used on detection of #if/#ifdef/#ifndef to open
851 *              a block.
852 *
853 ******************************************************************************/
854
855static void
856PrPushDirective (
857    int                     Directive,
858    char                    *Argument)
859{
860    DIRECTIVE_INFO          *Info;
861
862
863    /* Allocate and populate a stack info item */
864
865    Info = ACPI_ALLOCATE (sizeof (DIRECTIVE_INFO));
866
867    Info->Next = Gbl_DirectiveStack;
868    Info->Directive = Directive;
869    Info->IgnoringThisCodeBlock = Gbl_IgnoringThisCodeBlock;
870    strncpy (Info->Argument, Argument, MAX_ARGUMENT_LENGTH);
871
872    DbgPrint (ASL_DEBUG_OUTPUT,
873        "Pr(%.4u) - [%u %s] %*s Pushed [#%s %s]: IgnoreFlag = %s\n",
874        Gbl_CurrentLineNumber, Gbl_IfDepth,
875        Gbl_IgnoringThisCodeBlock ? "I" : "E",
876        Gbl_IfDepth * 4, " ",
877        Gbl_DirectiveInfo[Directive].Name,
878        Argument, Gbl_IgnoringThisCodeBlock ? "TRUE" : "FALSE");
879
880    /* Push new item */
881
882    Gbl_DirectiveStack = Info;
883    Gbl_IfDepth++;
884}
885
886
887/*******************************************************************************
888 *
889 * FUNCTION:    PrPopDirective
890 *
891 * PARAMETERS:  None
892 *
893 * RETURN:      Status. Error if the stack is empty.
894 *
895 * DESCRIPTION: Pop an item off the directive stack. Used for processing
896 *              nested #if/#else type conditional compilation directives.
897 *              Specifically: Used on detection of #elif and #endif to remove
898 *              the original #if/#ifdef/#ifndef from the stack and close
899 *              the block.
900 *
901 ******************************************************************************/
902
903static ACPI_STATUS
904PrPopDirective (
905    void)
906{
907    DIRECTIVE_INFO          *Info;
908
909
910    /* Check for empty stack */
911
912    Info = Gbl_DirectiveStack;
913    if (!Info)
914    {
915        return (AE_ERROR);
916    }
917
918    /* Pop one item, keep globals up-to-date */
919
920    Gbl_IfDepth--;
921    Gbl_IgnoringThisCodeBlock = Info->IgnoringThisCodeBlock;
922    Gbl_DirectiveStack = Info->Next;
923
924    DbgPrint (ASL_DEBUG_OUTPUT,
925        "Pr(%.4u) - [%u %s] %*s Popped [#%s %s]: IgnoreFlag now = %s\n",
926        Gbl_CurrentLineNumber, Gbl_IfDepth,
927        Gbl_IgnoringThisCodeBlock ? "I" : "E",
928        Gbl_IfDepth * 4, " ",
929        Gbl_DirectiveInfo[Info->Directive].Name,
930        Info->Argument, Gbl_IgnoringThisCodeBlock ? "TRUE" : "FALSE");
931
932    ACPI_FREE (Info);
933    return (AE_OK);
934}
935
936
937/*******************************************************************************
938 *
939 * FUNCTION:    PrDbgPrint
940 *
941 * PARAMETERS:  Action              - Action being performed
942 *              DirectiveName       - Directive being processed
943 *
944 * RETURN:      None
945 *
946 * DESCRIPTION: Special debug print for directive processing.
947 *
948 ******************************************************************************/
949
950static void
951PrDbgPrint (
952    char                    *Action,
953    char                    *DirectiveName)
954{
955
956    DbgPrint (ASL_DEBUG_OUTPUT, "Pr(%.4u) - [%u %s] "
957        "%*s %s #%s, Depth %u\n",
958        Gbl_CurrentLineNumber, Gbl_IfDepth,
959        Gbl_IgnoringThisCodeBlock ? "I" : "E",
960        Gbl_IfDepth * 4, " ",
961        Action, DirectiveName, Gbl_IfDepth);
962}
963