prscan.c revision 250838
1233237Sjkim/******************************************************************************
2233237Sjkim *
3233237Sjkim * Module Name: prscan - Preprocessor start-up and file scan module
4233237Sjkim *
5233237Sjkim *****************************************************************************/
6233237Sjkim
7233237Sjkim/*
8245582Sjkim * Copyright (C) 2000 - 2013, Intel Corp.
9233237Sjkim * All rights reserved.
10233237Sjkim *
11233237Sjkim * Redistribution and use in source and binary forms, with or without
12233237Sjkim * modification, are permitted provided that the following conditions
13233237Sjkim * are met:
14233237Sjkim * 1. Redistributions of source code must retain the above copyright
15233237Sjkim *    notice, this list of conditions, and the following disclaimer,
16233237Sjkim *    without modification.
17233237Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18233237Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
19233237Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
20233237Sjkim *    including a substantially similar Disclaimer requirement for further
21233237Sjkim *    binary redistribution.
22233237Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
23233237Sjkim *    of any contributors may be used to endorse or promote products derived
24233237Sjkim *    from this software without specific prior written permission.
25233237Sjkim *
26233237Sjkim * Alternatively, this software may be distributed under the terms of the
27233237Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
28233237Sjkim * Software Foundation.
29233237Sjkim *
30233237Sjkim * NO WARRANTY
31233237Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32233237Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33233237Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34233237Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35233237Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36233237Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37233237Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38233237Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39233237Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40233237Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41233237Sjkim * POSSIBILITY OF SUCH DAMAGES.
42233237Sjkim */
43233237Sjkim
44233237Sjkim#define _DECLARE_PR_GLOBALS
45233237Sjkim
46233250Sjkim#include <contrib/dev/acpica/compiler/aslcompiler.h>
47233250Sjkim#include <contrib/dev/acpica/compiler/dtcompiler.h>
48233237Sjkim
49233237Sjkim/*
50233237Sjkim * TBDs:
51233237Sjkim *
52233237Sjkim * No nested macros, maybe never
53233237Sjkim * Implement ASL "Include" as well as "#include" here?
54233237Sjkim */
55233237Sjkim#define _COMPONENT          ASL_PREPROCESSOR
56233237Sjkim        ACPI_MODULE_NAME    ("prscan")
57233237Sjkim
58233237Sjkim
59233237Sjkim/* Local prototypes */
60233237Sjkim
61233237Sjkimstatic void
62233237SjkimPrPreprocessInputFile (
63233237Sjkim    void);
64233237Sjkim
65233237Sjkimstatic void
66233237SjkimPrDoDirective (
67233237Sjkim    char                    *DirectiveToken,
68233237Sjkim    char                    **Next,
69233237Sjkim    BOOLEAN                 *IgnoringThisCodeBlock);
70233237Sjkim
71233237Sjkimstatic int
72233237SjkimPrMatchDirective (
73233237Sjkim    char                    *Directive);
74233237Sjkim
75233237Sjkim/*
76233237Sjkim * Supported preprocessor directives
77233237Sjkim */
78233237Sjkimstatic const PR_DIRECTIVE_INFO      Gbl_DirectiveInfo[] =
79233237Sjkim{
80233237Sjkim    {"define",  1},
81233237Sjkim    {"elif",    0}, /* Converted to #else..#if internally */
82233237Sjkim    {"else",    0},
83233237Sjkim    {"endif",   0},
84233237Sjkim    {"error",   1},
85233237Sjkim    {"if",      1},
86233237Sjkim    {"ifdef",   1},
87233237Sjkim    {"ifndef",  1},
88233237Sjkim    {"include", 0}, /* Argument is not standard format, so 0 */
89233237Sjkim    {"line",    1},
90233237Sjkim    {"pragma",  1},
91233237Sjkim    {"undef",   1},
92233237Sjkim    {"warning", 1},
93233237Sjkim    {NULL,      0}
94233237Sjkim};
95233237Sjkim
96233237Sjkimenum Gbl_DirectiveIndexes
97233237Sjkim{
98233237Sjkim    PR_DIRECTIVE_DEFINE = 0,
99233237Sjkim    PR_DIRECTIVE_ELIF,
100233237Sjkim    PR_DIRECTIVE_ELSE,
101233237Sjkim    PR_DIRECTIVE_ENDIF,
102233237Sjkim    PR_DIRECTIVE_ERROR,
103233237Sjkim    PR_DIRECTIVE_IF,
104233237Sjkim    PR_DIRECTIVE_IFDEF,
105233237Sjkim    PR_DIRECTIVE_IFNDEF,
106233237Sjkim    PR_DIRECTIVE_INCLUDE,
107233237Sjkim    PR_DIRECTIVE_LINE,
108233237Sjkim    PR_DIRECTIVE_PRAGMA,
109233237Sjkim    PR_DIRECTIVE_UNDEF,
110233237Sjkim    PR_DIRECTIVE_WARNING,
111233237Sjkim};
112233237Sjkim
113233237Sjkim#define ASL_DIRECTIVE_NOT_FOUND     -1
114233237Sjkim
115233237Sjkim
116233237Sjkim/*******************************************************************************
117233237Sjkim *
118233237Sjkim * FUNCTION:    PrInitializePreprocessor
119233237Sjkim *
120233237Sjkim * PARAMETERS:  None
121233237Sjkim *
122233237Sjkim * RETURN:      None
123233237Sjkim *
124233237Sjkim * DESCRIPTION: Startup initialization for the Preprocessor.
125233237Sjkim *
126233237Sjkim ******************************************************************************/
127233237Sjkim
128233237Sjkimvoid
129233237SjkimPrInitializePreprocessor (
130233237Sjkim    void)
131233237Sjkim{
132233237Sjkim    /* Init globals and the list of #defines */
133233237Sjkim
134233237Sjkim    PrInitializeGlobals ();
135233237Sjkim    Gbl_DefineList = NULL;
136233237Sjkim}
137233237Sjkim
138233237Sjkim
139233237Sjkim/*******************************************************************************
140233237Sjkim *
141233237Sjkim * FUNCTION:    PrInitializeGlobals
142233237Sjkim *
143233237Sjkim * PARAMETERS:  None
144233237Sjkim *
145233237Sjkim * RETURN:      None
146233237Sjkim *
147233237Sjkim * DESCRIPTION: Initialize globals for the Preprocessor. Used for startuup
148233237Sjkim *              initialization and re-initialization between compiles during
149233237Sjkim *              a multiple source file compile.
150233237Sjkim *
151233237Sjkim ******************************************************************************/
152233237Sjkim
153233237Sjkimvoid
154233237SjkimPrInitializeGlobals (
155233237Sjkim    void)
156233237Sjkim{
157233237Sjkim    /* Init globals */
158233237Sjkim
159233237Sjkim    Gbl_IfDepth = 0;
160233237Sjkim    Gbl_InputFileList = NULL;
161233237Sjkim    Gbl_CurrentLineNumber = 0;
162233237Sjkim    Gbl_PreprocessorLineNumber = 1;
163233237Sjkim    Gbl_PreprocessorError = FALSE;
164233237Sjkim}
165233237Sjkim
166233237Sjkim
167233237Sjkim/*******************************************************************************
168233237Sjkim *
169233237Sjkim * FUNCTION:    PrTerminatePreprocessor
170233237Sjkim *
171233237Sjkim * PARAMETERS:  None
172233237Sjkim *
173233237Sjkim * RETURN:      None
174233237Sjkim *
175233237Sjkim * DESCRIPTION: Termination of the preprocessor. Delete lists. Keep any
176233237Sjkim *              defines that were specified on the command line, in order to
177233237Sjkim *              support multiple compiles with a single compiler invocation.
178233237Sjkim *
179233237Sjkim ******************************************************************************/
180233237Sjkim
181233237Sjkimvoid
182233237SjkimPrTerminatePreprocessor (
183233237Sjkim    void)
184233237Sjkim{
185233237Sjkim    PR_DEFINE_INFO          *DefineInfo;
186233237Sjkim
187233237Sjkim
188233237Sjkim    /*
189233237Sjkim     * The persistent defines (created on the command line) are always at the
190233237Sjkim     * end of the list. We save them.
191233237Sjkim     */
192233237Sjkim    while ((Gbl_DefineList) && (!Gbl_DefineList->Persist))
193233237Sjkim    {
194233237Sjkim        DefineInfo = Gbl_DefineList;
195233237Sjkim        Gbl_DefineList = DefineInfo->Next;
196233237Sjkim
197233237Sjkim        ACPI_FREE (DefineInfo->Replacement);
198233237Sjkim        ACPI_FREE (DefineInfo->Identifier);
199233237Sjkim        ACPI_FREE (DefineInfo);
200233237Sjkim    }
201233237Sjkim}
202233237Sjkim
203233237Sjkim
204233237Sjkim/*******************************************************************************
205233237Sjkim *
206233237Sjkim * FUNCTION:    PrDoPreprocess
207233237Sjkim *
208233237Sjkim * PARAMETERS:  None
209233237Sjkim *
210233237Sjkim * RETURN:      Error Status. TRUE if error, FALSE if OK.
211233237Sjkim *
212233237Sjkim * DESCRIPTION: Main entry point for the iASL Preprocessor. Input file must
213233237Sjkim *              be already open. Handles multiple input files via the
214233237Sjkim *              #include directive.
215233237Sjkim *
216233237Sjkim ******************************************************************************/
217233237Sjkim
218233237SjkimBOOLEAN
219233237SjkimPrDoPreprocess (
220233237Sjkim    void)
221233237Sjkim{
222233237Sjkim    BOOLEAN                 MoreInputFiles;
223233237Sjkim
224233237Sjkim
225233237Sjkim    DbgPrint (ASL_DEBUG_OUTPUT, "Starting preprocessing phase\n\n");
226233237Sjkim
227233237Sjkim
228233237Sjkim    FlSeekFile (ASL_FILE_INPUT, 0);
229233237Sjkim    PrDumpPredefinedNames ();
230233237Sjkim
231233237Sjkim    /* Main preprocessor loop, handles include files */
232233237Sjkim
233233237Sjkim    do
234233237Sjkim    {
235233237Sjkim        PrPreprocessInputFile ();
236233237Sjkim        MoreInputFiles = PrPopInputFileStack ();
237233237Sjkim
238233237Sjkim    } while (MoreInputFiles);
239233237Sjkim
240233237Sjkim
241233237Sjkim    /*
242233237Sjkim     * TBD: is this necessary? (Do we abort on any preprocessing errors?)
243233237Sjkim     */
244233237Sjkim    if (Gbl_PreprocessorError)
245233237Sjkim    {
246233237Sjkim        /* TBD: can't use source_output file for preprocessor error reporting */
247233237Sjkim
248233237Sjkim        Gbl_Files[ASL_FILE_SOURCE_OUTPUT].Handle = NULL;
249233237Sjkim        PrTerminatePreprocessor ();
250233237Sjkim        return (TRUE);
251233237Sjkim    }
252233237Sjkim
253233237Sjkim    /* Point compiler input to the new preprocessor file (.i) */
254233237Sjkim
255233237Sjkim    FlCloseFile (ASL_FILE_INPUT);
256233237Sjkim    Gbl_Files[ASL_FILE_INPUT].Handle = Gbl_Files[ASL_FILE_PREPROCESSOR].Handle;
257233237Sjkim    AslCompilerin = Gbl_Files[ASL_FILE_INPUT].Handle;
258233237Sjkim
259233237Sjkim    /* Reset globals to allow compiler to run */
260233237Sjkim
261233237Sjkim    FlSeekFile (ASL_FILE_INPUT, 0);
262233237Sjkim    Gbl_CurrentLineNumber = 1;
263233237Sjkim
264233237Sjkim    DbgPrint (ASL_DEBUG_OUTPUT, "Preprocessing phase complete \n\n");
265233237Sjkim    return (FALSE);
266233237Sjkim}
267233237Sjkim
268233237Sjkim
269233237Sjkim/*******************************************************************************
270233237Sjkim *
271233237Sjkim * FUNCTION:    PrPreprocessInputFile
272233237Sjkim *
273233237Sjkim * PARAMETERS:  None
274233237Sjkim *
275233237Sjkim * RETURN:      None
276233237Sjkim *
277233237Sjkim * DESCRIPTION: Preprocess one entire file, line-by-line.
278233237Sjkim *
279233237Sjkim * Input:  Raw user ASL from ASL_FILE_INPUT
280233237Sjkim * Output: Preprocessed file written to ASL_FILE_PREPROCESSOR
281233237Sjkim *
282233237Sjkim ******************************************************************************/
283233237Sjkim
284233237Sjkimstatic void
285233237SjkimPrPreprocessInputFile (
286233237Sjkim    void)
287233237Sjkim{
288233237Sjkim    UINT32                  Offset;
289233237Sjkim    char                    *Token;
290233237Sjkim    char                    *ReplaceString;
291233237Sjkim    PR_DEFINE_INFO          *DefineInfo;
292233237Sjkim    ACPI_SIZE               TokenOffset;
293233237Sjkim    BOOLEAN                 IgnoringThisCodeBlock = FALSE;
294233237Sjkim    char                    *Next;
295233237Sjkim    int                     OffsetAdjust;
296233237Sjkim
297233237Sjkim
298233237Sjkim    /* Scan line-by-line. Comments and blank lines are skipped by this function */
299233237Sjkim
300233237Sjkim    while ((Offset = DtGetNextLine (Gbl_Files[ASL_FILE_INPUT].Handle)) != ASL_EOF)
301233237Sjkim    {
302233237Sjkim        /* Need a copy of the input line for strok() */
303233237Sjkim
304233237Sjkim        strcpy (Gbl_MainTokenBuffer, Gbl_CurrentLineBuffer);
305233237Sjkim        Token = PrGetNextToken (Gbl_MainTokenBuffer, PR_TOKEN_SEPARATORS, &Next);
306233237Sjkim        OffsetAdjust = 0;
307233237Sjkim
308233237Sjkim        /* All preprocessor directives must begin with '#' */
309233237Sjkim
310233237Sjkim        if (Token && (*Token == '#'))
311233237Sjkim        {
312233237Sjkim            if (strlen (Token) == 1)
313233237Sjkim            {
314233237Sjkim                Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, &Next);
315233237Sjkim            }
316233237Sjkim            else
317233237Sjkim            {
318233237Sjkim                Token++;    /* Skip leading # */
319233237Sjkim            }
320233237Sjkim
321233237Sjkim            /* Execute the directive, do not write line to output file */
322233237Sjkim
323233237Sjkim            PrDoDirective (Token, &Next, &IgnoringThisCodeBlock);
324233237Sjkim            continue;
325233237Sjkim        }
326233237Sjkim
327233237Sjkim        /*
328233237Sjkim         * If we are currently within the part of an IF/ELSE block that is
329233237Sjkim         * FALSE, ignore the line and do not write it to the output file.
330233237Sjkim         * This continues until an #else or #endif is encountered.
331233237Sjkim         */
332233237Sjkim        if (IgnoringThisCodeBlock == TRUE)
333233237Sjkim        {
334233237Sjkim            continue;
335233237Sjkim        }
336233237Sjkim
337233237Sjkim        /* Match and replace all #defined names within this source line */
338233237Sjkim
339233237Sjkim        while (Token)
340233237Sjkim        {
341233237Sjkim            DefineInfo = PrMatchDefine (Token);
342233237Sjkim            if (DefineInfo)
343233237Sjkim            {
344233237Sjkim                if (DefineInfo->Body)
345233237Sjkim                {
346233237Sjkim                    /* This is a macro */
347233237Sjkim
348233237Sjkim                    DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
349233237Sjkim                        "Matched Macro: %s->%s\n",
350233237Sjkim                        Gbl_CurrentLineNumber, DefineInfo->Identifier,
351233237Sjkim                        DefineInfo->Replacement);
352233237Sjkim
353233237Sjkim                    PrDoMacroInvocation (Gbl_MainTokenBuffer, Token,
354233237Sjkim                        DefineInfo, &Next);
355233237Sjkim                }
356233237Sjkim                else
357233237Sjkim                {
358233237Sjkim                    ReplaceString = DefineInfo->Replacement;
359233237Sjkim
360233237Sjkim                    /* Replace the name in the original line buffer */
361233237Sjkim
362233237Sjkim                    TokenOffset = Token - Gbl_MainTokenBuffer + OffsetAdjust;
363233237Sjkim                    PrReplaceData (
364233237Sjkim                        &Gbl_CurrentLineBuffer[TokenOffset], strlen (Token),
365233237Sjkim                        ReplaceString, strlen (ReplaceString));
366233237Sjkim
367233237Sjkim                    /* Adjust for length difference between old and new name length */
368233237Sjkim
369233237Sjkim                    OffsetAdjust += strlen (ReplaceString) - strlen (Token);
370233237Sjkim
371233237Sjkim                    DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
372233237Sjkim                        "Matched #define: %s->%s\n",
373233237Sjkim                        Gbl_CurrentLineNumber, Token,
374233237Sjkim                        *ReplaceString ? ReplaceString : "(NULL STRING)");
375233237Sjkim                }
376233237Sjkim            }
377233237Sjkim
378233237Sjkim            Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, &Next);
379233237Sjkim        }
380233237Sjkim
381233237Sjkim#if 0
382233237Sjkim/* Line prefix */
383233237Sjkim        FlPrintFile (ASL_FILE_PREPROCESSOR, "/* %14s  %.5u  i:%.5u */ ",
384233237Sjkim            Gbl_Files[ASL_FILE_INPUT].Filename,
385233237Sjkim            Gbl_CurrentLineNumber, Gbl_PreprocessorLineNumber);
386233237Sjkim#endif
387233237Sjkim
388234623Sjkim        /*
389234623Sjkim         * Emit a #line directive if necessary, to keep the line numbers in
390234623Sjkim         * the (.i) file synchronized with the original source code file, so
391234623Sjkim         * that the correct line number appears in any error messages
392234623Sjkim         * generated by the actual compiler.
393234623Sjkim         */
394234623Sjkim        if (Gbl_CurrentLineNumber > (Gbl_PreviousLineNumber + 1))
395234623Sjkim        {
396234623Sjkim            FlPrintFile (ASL_FILE_PREPROCESSOR, "#line %u\n",
397234623Sjkim                Gbl_CurrentLineNumber);
398234623Sjkim        }
399234623Sjkim
400234623Sjkim        Gbl_PreviousLineNumber = Gbl_CurrentLineNumber;
401234623Sjkim        Gbl_PreprocessorLineNumber++;
402234623Sjkim
403234623Sjkim        /*
404234623Sjkim         * Now we can write the possibly modified source line to the
405234623Sjkim         * preprocessor (.i) file
406234623Sjkim         */
407233237Sjkim        FlWriteFile (ASL_FILE_PREPROCESSOR, Gbl_CurrentLineBuffer,
408233237Sjkim            strlen (Gbl_CurrentLineBuffer));
409233237Sjkim    }
410233237Sjkim}
411233237Sjkim
412233237Sjkim
413233237Sjkim/*******************************************************************************
414233237Sjkim *
415233237Sjkim * FUNCTION:    PrDoDirective
416233237Sjkim *
417233237Sjkim * PARAMETERS:  Directive               - Pointer to directive name token
418233237Sjkim *              Next                    - "Next" buffer from GetNextToken
419233237Sjkim *              IgnoringThisCodeBlock   - Where the "ignore code" flag is
420233237Sjkim *                                        returned.
421233237Sjkim *
422233237Sjkim * RETURN:      IgnoringThisCodeBlock: Set to TRUE if we are skipping the FALSE
423233237Sjkim *              part of an #if or #else block. Set to FALSE when the
424233237Sjkim *              corresponding #else or #endif is encountered.
425233237Sjkim *
426233237Sjkim * DESCRIPTION: Main processing for all preprocessor directives
427233237Sjkim *
428233237Sjkim ******************************************************************************/
429233237Sjkim
430233237Sjkimstatic void
431233237SjkimPrDoDirective (
432233237Sjkim    char                    *DirectiveToken,
433233237Sjkim    char                    **Next,
434233237Sjkim    BOOLEAN                 *IgnoringThisCodeBlock)
435233237Sjkim{
436233237Sjkim    char                    *Token = Gbl_MainTokenBuffer;
437233237Sjkim    char                    *Token2;
438233237Sjkim    char                    *End;
439233237Sjkim    UINT64                  Value;
440233237Sjkim    ACPI_SIZE               TokenOffset;
441233237Sjkim    int                     Directive;
442233237Sjkim    ACPI_STATUS             Status;
443233237Sjkim
444233237Sjkim
445233237Sjkim    if (!DirectiveToken)
446233237Sjkim    {
447233237Sjkim        goto SyntaxError;
448233237Sjkim    }
449233237Sjkim
450233237Sjkim    Directive = PrMatchDirective (DirectiveToken);
451233237Sjkim    if (Directive == ASL_DIRECTIVE_NOT_FOUND)
452233237Sjkim    {
453233237Sjkim        PrError (ASL_ERROR, ASL_MSG_UNKNOWN_DIRECTIVE,
454233237Sjkim            THIS_TOKEN_OFFSET (DirectiveToken));
455233237Sjkim
456233237Sjkim        DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
457233237Sjkim            "#%s: Unknown directive\n",
458233237Sjkim            Gbl_CurrentLineNumber, DirectiveToken);
459233237Sjkim        return;
460233237Sjkim    }
461233237Sjkim
462233237Sjkim    /* TBD: Need a faster way to do this: */
463233237Sjkim
464233237Sjkim    if ((Directive == PR_DIRECTIVE_ELIF) ||
465233237Sjkim        (Directive == PR_DIRECTIVE_ELSE) ||
466233237Sjkim        (Directive == PR_DIRECTIVE_ENDIF))
467233237Sjkim    {
468233237Sjkim        DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID "Begin #%s\n",
469233237Sjkim            Gbl_CurrentLineNumber, Gbl_DirectiveInfo[Directive].Name);
470233237Sjkim    }
471233237Sjkim
472233237Sjkim    /*
473233237Sjkim     * Need to always check for #else, #elif, #endif regardless of
474233237Sjkim     * whether we are ignoring the current code block, since these
475233237Sjkim     * are conditional code block terminators.
476233237Sjkim     */
477233237Sjkim    switch (Directive)
478233237Sjkim    {
479233237Sjkim    case PR_DIRECTIVE_ELIF:
480250838Sjkim
481233237Sjkim        *IgnoringThisCodeBlock = !(*IgnoringThisCodeBlock);
482233237Sjkim        if (*IgnoringThisCodeBlock == TRUE)
483233237Sjkim        {
484233237Sjkim            /* Not executing the ELSE part -- all done here */
485233237Sjkim            return;
486233237Sjkim        }
487233237Sjkim
488233237Sjkim        /* Will execute the ELSE..IF part */
489233237Sjkim
490233237Sjkim        DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
491233237Sjkim            "#elif - Executing else block\n",
492233237Sjkim            Gbl_CurrentLineNumber);
493233237Sjkim        Directive = PR_DIRECTIVE_IF;
494233237Sjkim        break;
495233237Sjkim
496233237Sjkim    case PR_DIRECTIVE_ELSE:
497250838Sjkim
498233237Sjkim        *IgnoringThisCodeBlock = !(*IgnoringThisCodeBlock);
499233237Sjkim        return;
500233237Sjkim
501233237Sjkim    case PR_DIRECTIVE_ENDIF:
502250838Sjkim
503233237Sjkim        *IgnoringThisCodeBlock = FALSE;
504233237Sjkim        Gbl_IfDepth--;
505233237Sjkim        if (Gbl_IfDepth < 0)
506233237Sjkim        {
507233237Sjkim            PrError (ASL_ERROR, ASL_MSG_ENDIF_MISMATCH,
508233237Sjkim                THIS_TOKEN_OFFSET (DirectiveToken));
509233237Sjkim            Gbl_IfDepth = 0;
510233237Sjkim        }
511233237Sjkim        return;
512233237Sjkim
513233237Sjkim    default:
514250838Sjkim
515233237Sjkim        break;
516233237Sjkim    }
517233237Sjkim
518233237Sjkim    /*
519233237Sjkim     * At this point, if we are ignoring the current code block,
520233237Sjkim     * do not process any more directives (i.e., ignore them also.)
521233237Sjkim     */
522233237Sjkim    if (*IgnoringThisCodeBlock == TRUE)
523233237Sjkim    {
524233237Sjkim        return;
525233237Sjkim    }
526233237Sjkim
527233237Sjkim    DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID "Begin #%s\n",
528233237Sjkim        Gbl_CurrentLineNumber, Gbl_DirectiveInfo[Directive].Name);
529233237Sjkim
530233237Sjkim    /* Most directives have at least one argument */
531233237Sjkim
532233237Sjkim    if (Gbl_DirectiveInfo[Directive].ArgCount == 1)
533233237Sjkim    {
534233237Sjkim        Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next);
535233237Sjkim        if (!Token)
536233237Sjkim        {
537233237Sjkim            goto SyntaxError;
538233237Sjkim        }
539233237Sjkim    }
540233237Sjkim
541233237Sjkim    switch (Directive)
542233237Sjkim    {
543233237Sjkim    case PR_DIRECTIVE_DEFINE:
544233237Sjkim        /*
545233237Sjkim         * By definition, if first char after the name is a paren,
546233237Sjkim         * this is a function macro.
547233237Sjkim         */
548233237Sjkim        TokenOffset = Token - Gbl_MainTokenBuffer + strlen (Token);
549233237Sjkim        if (*(&Gbl_CurrentLineBuffer[TokenOffset]) == '(')
550233237Sjkim        {
551233237Sjkim#ifndef MACROS_SUPPORTED
552234623Sjkim            AcpiOsPrintf ("%s ERROR - line %u: #define macros are not supported yet\n",
553234623Sjkim                Gbl_CurrentLineBuffer, Gbl_CurrentLineNumber);
554234623Sjkim            exit(1);
555233237Sjkim#else
556233237Sjkim            PrAddMacro (Token, Next);
557233237Sjkim#endif
558233237Sjkim        }
559233237Sjkim        else
560233237Sjkim        {
561233237Sjkim            /* Use the remainder of the line for the #define */
562233237Sjkim
563233237Sjkim            Token2 = *Next;
564233237Sjkim            if (Token2)
565233237Sjkim            {
566233237Sjkim                while ((*Token2 == ' ') || (*Token2 == '\t'))
567233237Sjkim                {
568233237Sjkim                    Token2++;
569233237Sjkim                }
570233237Sjkim                End = Token2;
571233237Sjkim                while (*End != '\n')
572233237Sjkim                {
573233237Sjkim                    End++;
574233237Sjkim                }
575233237Sjkim                *End = 0;
576233237Sjkim            }
577233237Sjkim            else
578233237Sjkim            {
579233237Sjkim                Token2 = "";
580233237Sjkim            }
581233237Sjkim#if 0
582233237Sjkim            Token2 = PrGetNextToken (NULL, "\n", /*PR_TOKEN_SEPARATORS,*/ Next);
583233237Sjkim            if (!Token2)
584233237Sjkim            {
585233237Sjkim                Token2 = "";
586233237Sjkim            }
587233237Sjkim#endif
588233237Sjkim            DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
589233237Sjkim                "New #define: %s->%s\n",
590233237Sjkim                Gbl_CurrentLineNumber, Token, Token2);
591233237Sjkim
592233237Sjkim            PrAddDefine (Token, Token2, FALSE);
593233237Sjkim        }
594233237Sjkim        break;
595233237Sjkim
596233237Sjkim    case PR_DIRECTIVE_ERROR:
597250838Sjkim
598233237Sjkim        /* TBD compiler should abort */
599233237Sjkim        /* Note: No macro expansion */
600233237Sjkim
601233237Sjkim        PrError (ASL_ERROR, ASL_MSG_ERROR_DIRECTIVE,
602233237Sjkim            THIS_TOKEN_OFFSET (Token));
603233237Sjkim        break;
604233237Sjkim
605233237Sjkim    case PR_DIRECTIVE_IF:
606250838Sjkim
607233237Sjkim        TokenOffset = Token - Gbl_MainTokenBuffer;
608233237Sjkim
609233237Sjkim        /* Need to expand #define macros in the expression string first */
610233237Sjkim
611233237Sjkim        Status = PrResolveIntegerExpression (
612233237Sjkim            &Gbl_CurrentLineBuffer[TokenOffset-1], &Value);
613233237Sjkim        if (ACPI_FAILURE (Status))
614233237Sjkim        {
615233237Sjkim            return;
616233237Sjkim        }
617233237Sjkim
618233237Sjkim        if (!Value)
619233237Sjkim        {
620233237Sjkim            *IgnoringThisCodeBlock = TRUE;
621233237Sjkim        }
622233237Sjkim
623233237Sjkim        DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
624233237Sjkim            "Resolved #if: %8.8X%8.8X %s\n",
625233237Sjkim            Gbl_CurrentLineNumber, ACPI_FORMAT_UINT64 (Value),
626233237Sjkim            *IgnoringThisCodeBlock ? "<Skipping Block>" : "<Executing Block>");
627233237Sjkim
628233237Sjkim        Gbl_IfDepth++;
629233237Sjkim        break;
630233237Sjkim
631233237Sjkim    case PR_DIRECTIVE_IFDEF:
632250838Sjkim
633233237Sjkim        if (!PrMatchDefine (Token))
634233237Sjkim        {
635233237Sjkim            *IgnoringThisCodeBlock = TRUE;
636233237Sjkim        }
637233237Sjkim
638233237Sjkim        Gbl_IfDepth++;
639233237Sjkim        DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
640233237Sjkim            "Start #ifdef %s\n", Gbl_CurrentLineNumber,
641233237Sjkim            *IgnoringThisCodeBlock ? "<Skipping Block>" : "<Executing Block>");
642233237Sjkim        break;
643233237Sjkim
644233237Sjkim    case PR_DIRECTIVE_IFNDEF:
645250838Sjkim
646233237Sjkim        if (PrMatchDefine (Token))
647233237Sjkim        {
648233237Sjkim            *IgnoringThisCodeBlock = TRUE;
649233237Sjkim        }
650233237Sjkim
651233237Sjkim        Gbl_IfDepth++;
652233237Sjkim        DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
653233237Sjkim            "Start #ifndef %2.2X\n", Gbl_CurrentLineNumber,
654233237Sjkim            *IgnoringThisCodeBlock, Gbl_CurrentLineNumber);
655233237Sjkim        break;
656233237Sjkim
657233237Sjkim    case PR_DIRECTIVE_INCLUDE:
658250838Sjkim
659233237Sjkim        Token = PrGetNextToken (NULL, " \"<>", Next);
660233237Sjkim        if (!Token)
661233237Sjkim        {
662233237Sjkim            goto SyntaxError;
663233237Sjkim        }
664233237Sjkim
665233237Sjkim        DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
666235945Sjkim            "Start #include file \"%s\"\n", Gbl_CurrentLineNumber,
667233237Sjkim            Token, Gbl_CurrentLineNumber);
668233237Sjkim
669233237Sjkim        PrOpenIncludeFile (Token);
670233237Sjkim        break;
671233237Sjkim
672234623Sjkim    case PR_DIRECTIVE_LINE:
673250838Sjkim
674234623Sjkim        TokenOffset = Token - Gbl_MainTokenBuffer;
675234623Sjkim
676234623Sjkim        Status = PrResolveIntegerExpression (
677234623Sjkim            &Gbl_CurrentLineBuffer[TokenOffset-1], &Value);
678234623Sjkim        if (ACPI_FAILURE (Status))
679234623Sjkim        {
680234623Sjkim            return;
681234623Sjkim        }
682234623Sjkim
683234623Sjkim        DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
684234623Sjkim            "User #line invocation %s\n", Gbl_CurrentLineNumber,
685234623Sjkim            Token);
686234623Sjkim
687234623Sjkim        /* Update local line numbers */
688234623Sjkim
689234623Sjkim        Gbl_CurrentLineNumber = (UINT32) Value;
690234623Sjkim        Gbl_PreviousLineNumber = 0;
691234623Sjkim
692234623Sjkim        /* Emit #line into the preprocessor file */
693234623Sjkim
694234623Sjkim        FlPrintFile (ASL_FILE_PREPROCESSOR, "#line %u \"%s\"\n",
695234623Sjkim            Gbl_CurrentLineNumber, Gbl_Files[ASL_FILE_INPUT].Filename);
696234623Sjkim        break;
697234623Sjkim
698233237Sjkim    case PR_DIRECTIVE_PRAGMA:
699233237Sjkim
700250838Sjkim        if (!strcmp (Token, "disable"))
701233237Sjkim        {
702250838Sjkim            Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next);
703250838Sjkim            if (!Token)
704250838Sjkim            {
705250838Sjkim                goto SyntaxError;
706250838Sjkim            }
707250838Sjkim
708250838Sjkim            TokenOffset = Token - Gbl_MainTokenBuffer;
709250838Sjkim            AslDisableException (&Gbl_CurrentLineBuffer[TokenOffset]);
710250838Sjkim        }
711250838Sjkim        else if (!strcmp (Token, "message"))
712250838Sjkim        {
713250838Sjkim            Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next);
714250838Sjkim            if (!Token)
715250838Sjkim            {
716250838Sjkim                goto SyntaxError;
717250838Sjkim            }
718250838Sjkim
719250838Sjkim            TokenOffset = Token - Gbl_MainTokenBuffer;
720250838Sjkim            AcpiOsPrintf ("%s\n", &Gbl_CurrentLineBuffer[TokenOffset]);
721250838Sjkim        }
722250838Sjkim        else
723250838Sjkim        {
724233237Sjkim            PrError (ASL_ERROR, ASL_MSG_UNKNOWN_PRAGMA,
725233237Sjkim                THIS_TOKEN_OFFSET (Token));
726233237Sjkim            return;
727233237Sjkim        }
728233237Sjkim
729233237Sjkim        break;
730233237Sjkim
731233237Sjkim    case PR_DIRECTIVE_UNDEF:
732250838Sjkim
733233237Sjkim        DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
734233237Sjkim            "#undef: %s\n", Gbl_CurrentLineNumber, Token);
735233237Sjkim
736233237Sjkim        PrRemoveDefine (Token);
737233237Sjkim        break;
738233237Sjkim
739233237Sjkim    case PR_DIRECTIVE_WARNING:
740250838Sjkim
741233237Sjkim        PrError (ASL_WARNING, ASL_MSG_ERROR_DIRECTIVE,
742233237Sjkim            THIS_TOKEN_OFFSET (Token));
743233237Sjkim        break;
744233237Sjkim
745233237Sjkim    default:
746250838Sjkim
747233237Sjkim        /* Should never get here */
748233237Sjkim        DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
749233237Sjkim            "Unrecognized directive: %u\n",
750233237Sjkim            Gbl_CurrentLineNumber, Directive);
751233237Sjkim        break;
752233237Sjkim    }
753233237Sjkim
754233237Sjkim    return;
755233237Sjkim
756233237Sjkim
757233237SjkimSyntaxError:
758233237Sjkim
759233237Sjkim    PrError (ASL_ERROR, ASL_MSG_DIRECTIVE_SYNTAX,
760233237Sjkim        THIS_TOKEN_OFFSET (DirectiveToken));
761233237Sjkim    return;
762233237Sjkim}
763233237Sjkim
764233237Sjkim
765233237Sjkim/*******************************************************************************
766233237Sjkim *
767233237Sjkim * FUNCTION:    PrMatchDirective
768233237Sjkim *
769233237Sjkim * PARAMETERS:  Directive           - Pointer to directive name token
770233237Sjkim *
771233237Sjkim * RETURN:      Index into command array, -1 if not found
772233237Sjkim *
773233237Sjkim * DESCRIPTION: Lookup the incoming directive in the known directives table.
774233237Sjkim *
775233237Sjkim ******************************************************************************/
776233237Sjkim
777233237Sjkimstatic int
778233237SjkimPrMatchDirective (
779233237Sjkim    char                    *Directive)
780233237Sjkim{
781233237Sjkim    int                     i;
782233237Sjkim
783233237Sjkim
784233237Sjkim    if (!Directive || Directive[0] == 0)
785233237Sjkim    {
786233237Sjkim        return (ASL_DIRECTIVE_NOT_FOUND);
787233237Sjkim    }
788233237Sjkim
789233237Sjkim    for (i = 0; Gbl_DirectiveInfo[i].Name; i++)
790233237Sjkim    {
791233237Sjkim        if (!strcmp (Gbl_DirectiveInfo[i].Name, Directive))
792233237Sjkim        {
793233237Sjkim            return (i);
794233237Sjkim        }
795233237Sjkim    }
796233237Sjkim
797233237Sjkim    return (ASL_DIRECTIVE_NOT_FOUND);    /* Command not recognized */
798233237Sjkim}
799