prscan.c revision 233250
1233237Sjkim/******************************************************************************
2233237Sjkim *
3233237Sjkim * Module Name: prscan - Preprocessor start-up and file scan module
4233237Sjkim *
5233237Sjkim *****************************************************************************/
6233237Sjkim
7233237Sjkim/*
8233237Sjkim * Copyright (C) 2000 - 2012, 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    Gbl_MapBlockHead = UtLocalCalloc (sizeof (PR_LINE_MAPPING));
166233237Sjkim    Gbl_MapBlockHead->Map = UtLocalCalloc (PR_LINES_PER_BLOCK * sizeof (UINT32));
167233237Sjkim}
168233237Sjkim
169233237Sjkim
170233237Sjkim/*******************************************************************************
171233237Sjkim *
172233237Sjkim * FUNCTION:    PrTerminatePreprocessor
173233237Sjkim *
174233237Sjkim * PARAMETERS:  None
175233237Sjkim *
176233237Sjkim * RETURN:      None
177233237Sjkim *
178233237Sjkim * DESCRIPTION: Termination of the preprocessor. Delete lists. Keep any
179233237Sjkim *              defines that were specified on the command line, in order to
180233237Sjkim *              support multiple compiles with a single compiler invocation.
181233237Sjkim *
182233237Sjkim ******************************************************************************/
183233237Sjkim
184233237Sjkimvoid
185233237SjkimPrTerminatePreprocessor (
186233237Sjkim    void)
187233237Sjkim{
188233237Sjkim    PR_DEFINE_INFO          *DefineInfo;
189233237Sjkim    PR_LINE_MAPPING         *MapInfo;
190233237Sjkim
191233237Sjkim
192233237Sjkim    /*
193233237Sjkim     * The persistent defines (created on the command line) are always at the
194233237Sjkim     * end of the list. We save them.
195233237Sjkim     */
196233237Sjkim    while ((Gbl_DefineList) && (!Gbl_DefineList->Persist))
197233237Sjkim    {
198233237Sjkim        DefineInfo = Gbl_DefineList;
199233237Sjkim        Gbl_DefineList = DefineInfo->Next;
200233237Sjkim
201233237Sjkim        ACPI_FREE (DefineInfo->Replacement);
202233237Sjkim        ACPI_FREE (DefineInfo->Identifier);
203233237Sjkim        ACPI_FREE (DefineInfo);
204233237Sjkim    }
205233237Sjkim
206233237Sjkim    /* Clear the line number mappings */
207233237Sjkim
208233237Sjkim    while (Gbl_MapBlockHead)
209233237Sjkim    {
210233237Sjkim        MapInfo = Gbl_MapBlockHead;
211233237Sjkim        Gbl_MapBlockHead = MapInfo->Next;
212233237Sjkim
213233237Sjkim        ACPI_FREE (MapInfo->Map);
214233237Sjkim        ACPI_FREE (MapInfo);
215233237Sjkim    }
216233237Sjkim}
217233237Sjkim
218233237Sjkim
219233237Sjkim/*******************************************************************************
220233237Sjkim *
221233237Sjkim * FUNCTION:    PrDoPreprocess
222233237Sjkim *
223233237Sjkim * PARAMETERS:  None
224233237Sjkim *
225233237Sjkim * RETURN:      Error Status. TRUE if error, FALSE if OK.
226233237Sjkim *
227233237Sjkim * DESCRIPTION: Main entry point for the iASL Preprocessor. Input file must
228233237Sjkim *              be already open. Handles multiple input files via the
229233237Sjkim *              #include directive.
230233237Sjkim *
231233237Sjkim ******************************************************************************/
232233237Sjkim
233233237SjkimBOOLEAN
234233237SjkimPrDoPreprocess (
235233237Sjkim    void)
236233237Sjkim{
237233237Sjkim    BOOLEAN                 MoreInputFiles;
238233237Sjkim
239233237Sjkim
240233237Sjkim    DbgPrint (ASL_DEBUG_OUTPUT, "Starting preprocessing phase\n\n");
241233237Sjkim
242233237Sjkim
243233237Sjkim    FlSeekFile (ASL_FILE_INPUT, 0);
244233237Sjkim    PrDumpPredefinedNames ();
245233237Sjkim
246233237Sjkim    /* Main preprocessor loop, handles include files */
247233237Sjkim
248233237Sjkim    do
249233237Sjkim    {
250233237Sjkim        PrPreprocessInputFile ();
251233237Sjkim        MoreInputFiles = PrPopInputFileStack ();
252233237Sjkim
253233237Sjkim    } while (MoreInputFiles);
254233237Sjkim
255233237Sjkim
256233237Sjkim    /*
257233237Sjkim     * TBD: is this necessary? (Do we abort on any preprocessing errors?)
258233237Sjkim     */
259233237Sjkim    if (Gbl_PreprocessorError)
260233237Sjkim    {
261233237Sjkim        /* TBD: can't use source_output file for preprocessor error reporting */
262233237Sjkim
263233237Sjkim        Gbl_Files[ASL_FILE_SOURCE_OUTPUT].Handle = NULL;
264233237Sjkim        PrTerminatePreprocessor ();
265233237Sjkim        return (TRUE);
266233237Sjkim    }
267233237Sjkim
268233237Sjkim    /* Point compiler input to the new preprocessor file (.i) */
269233237Sjkim
270233237Sjkim    FlCloseFile (ASL_FILE_INPUT);
271233237Sjkim    Gbl_Files[ASL_FILE_INPUT].Handle = Gbl_Files[ASL_FILE_PREPROCESSOR].Handle;
272233237Sjkim    AslCompilerin = Gbl_Files[ASL_FILE_INPUT].Handle;
273233237Sjkim
274233237Sjkim    /* Reset globals to allow compiler to run */
275233237Sjkim
276233237Sjkim    FlSeekFile (ASL_FILE_INPUT, 0);
277233237Sjkim    Gbl_CurrentLineNumber = 1;
278233237Sjkim
279233237Sjkim    DbgPrint (ASL_DEBUG_OUTPUT, "Preprocessing phase complete \n\n");
280233237Sjkim    return (FALSE);
281233237Sjkim}
282233237Sjkim
283233237Sjkim
284233237Sjkim/*******************************************************************************
285233237Sjkim *
286233237Sjkim * FUNCTION:    PrPreprocessInputFile
287233237Sjkim *
288233237Sjkim * PARAMETERS:  None
289233237Sjkim *
290233237Sjkim * RETURN:      None
291233237Sjkim *
292233237Sjkim * DESCRIPTION: Preprocess one entire file, line-by-line.
293233237Sjkim *
294233237Sjkim * Input:  Raw user ASL from ASL_FILE_INPUT
295233237Sjkim * Output: Preprocessed file written to ASL_FILE_PREPROCESSOR
296233237Sjkim *
297233237Sjkim ******************************************************************************/
298233237Sjkim
299233237Sjkimstatic void
300233237SjkimPrPreprocessInputFile (
301233237Sjkim    void)
302233237Sjkim{
303233237Sjkim    UINT32                  Offset;
304233237Sjkim    char                    *Token;
305233237Sjkim    char                    *ReplaceString;
306233237Sjkim    PR_DEFINE_INFO          *DefineInfo;
307233237Sjkim    ACPI_SIZE               TokenOffset;
308233237Sjkim    BOOLEAN                 IgnoringThisCodeBlock = FALSE;
309233237Sjkim    char                    *Next;
310233237Sjkim    int                     OffsetAdjust;
311233237Sjkim
312233237Sjkim
313233237Sjkim    /* Scan line-by-line. Comments and blank lines are skipped by this function */
314233237Sjkim
315233237Sjkim    while ((Offset = DtGetNextLine (Gbl_Files[ASL_FILE_INPUT].Handle)) != ASL_EOF)
316233237Sjkim    {
317233237Sjkim        /* Need a copy of the input line for strok() */
318233237Sjkim
319233237Sjkim        strcpy (Gbl_MainTokenBuffer, Gbl_CurrentLineBuffer);
320233237Sjkim        Token = PrGetNextToken (Gbl_MainTokenBuffer, PR_TOKEN_SEPARATORS, &Next);
321233237Sjkim        OffsetAdjust = 0;
322233237Sjkim
323233237Sjkim        /* All preprocessor directives must begin with '#' */
324233237Sjkim
325233237Sjkim        if (Token && (*Token == '#'))
326233237Sjkim        {
327233237Sjkim            if (strlen (Token) == 1)
328233237Sjkim            {
329233237Sjkim                Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, &Next);
330233237Sjkim            }
331233237Sjkim            else
332233237Sjkim            {
333233237Sjkim                Token++;    /* Skip leading # */
334233237Sjkim            }
335233237Sjkim
336233237Sjkim            /* Execute the directive, do not write line to output file */
337233237Sjkim
338233237Sjkim            PrDoDirective (Token, &Next, &IgnoringThisCodeBlock);
339233237Sjkim            continue;
340233237Sjkim        }
341233237Sjkim
342233237Sjkim        /*
343233237Sjkim         * If we are currently within the part of an IF/ELSE block that is
344233237Sjkim         * FALSE, ignore the line and do not write it to the output file.
345233237Sjkim         * This continues until an #else or #endif is encountered.
346233237Sjkim         */
347233237Sjkim        if (IgnoringThisCodeBlock == TRUE)
348233237Sjkim        {
349233237Sjkim            continue;
350233237Sjkim        }
351233237Sjkim
352233237Sjkim        /* Match and replace all #defined names within this source line */
353233237Sjkim
354233237Sjkim        while (Token)
355233237Sjkim        {
356233237Sjkim            DefineInfo = PrMatchDefine (Token);
357233237Sjkim            if (DefineInfo)
358233237Sjkim            {
359233237Sjkim                if (DefineInfo->Body)
360233237Sjkim                {
361233237Sjkim                    /* This is a macro */
362233237Sjkim
363233237Sjkim                    DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
364233237Sjkim                        "Matched Macro: %s->%s\n",
365233237Sjkim                        Gbl_CurrentLineNumber, DefineInfo->Identifier,
366233237Sjkim                        DefineInfo->Replacement);
367233237Sjkim
368233237Sjkim                    PrDoMacroInvocation (Gbl_MainTokenBuffer, Token,
369233237Sjkim                        DefineInfo, &Next);
370233237Sjkim                }
371233237Sjkim                else
372233237Sjkim                {
373233237Sjkim                    ReplaceString = DefineInfo->Replacement;
374233237Sjkim
375233237Sjkim                    /* Replace the name in the original line buffer */
376233237Sjkim
377233237Sjkim                    TokenOffset = Token - Gbl_MainTokenBuffer + OffsetAdjust;
378233237Sjkim                    PrReplaceData (
379233237Sjkim                        &Gbl_CurrentLineBuffer[TokenOffset], strlen (Token),
380233237Sjkim                        ReplaceString, strlen (ReplaceString));
381233237Sjkim
382233237Sjkim                    /* Adjust for length difference between old and new name length */
383233237Sjkim
384233237Sjkim                    OffsetAdjust += strlen (ReplaceString) - strlen (Token);
385233237Sjkim
386233237Sjkim                    DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
387233237Sjkim                        "Matched #define: %s->%s\n",
388233237Sjkim                        Gbl_CurrentLineNumber, Token,
389233237Sjkim                        *ReplaceString ? ReplaceString : "(NULL STRING)");
390233237Sjkim                }
391233237Sjkim            }
392233237Sjkim
393233237Sjkim            Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, &Next);
394233237Sjkim        }
395233237Sjkim
396233237Sjkim        /* Write the possibly modified line to the .i file*/
397233237Sjkim
398233237Sjkim#if 0
399233237Sjkim/* Line prefix */
400233237Sjkim        FlPrintFile (ASL_FILE_PREPROCESSOR, "/* %14s  %.5u  i:%.5u */ ",
401233237Sjkim            Gbl_Files[ASL_FILE_INPUT].Filename,
402233237Sjkim            Gbl_CurrentLineNumber, Gbl_PreprocessorLineNumber);
403233237Sjkim#endif
404233237Sjkim
405233237Sjkim        FlWriteFile (ASL_FILE_PREPROCESSOR, Gbl_CurrentLineBuffer,
406233237Sjkim            strlen (Gbl_CurrentLineBuffer));
407233237Sjkim
408233237Sjkim        PrSetLineNumber (Gbl_CurrentLineNumber, Gbl_PreprocessorLineNumber);
409233237Sjkim        Gbl_PreprocessorLineNumber++;
410233237Sjkim    }
411233237Sjkim}
412233237Sjkim
413233237Sjkim
414233237Sjkim/*******************************************************************************
415233237Sjkim *
416233237Sjkim * FUNCTION:    PrDoDirective
417233237Sjkim *
418233237Sjkim * PARAMETERS:  Directive               - Pointer to directive name token
419233237Sjkim *              Next                    - "Next" buffer from GetNextToken
420233237Sjkim *              IgnoringThisCodeBlock   - Where the "ignore code" flag is
421233237Sjkim *                                        returned.
422233237Sjkim *
423233237Sjkim * RETURN:      IgnoringThisCodeBlock: Set to TRUE if we are skipping the FALSE
424233237Sjkim *              part of an #if or #else block. Set to FALSE when the
425233237Sjkim *              corresponding #else or #endif is encountered.
426233237Sjkim *
427233237Sjkim * DESCRIPTION: Main processing for all preprocessor directives
428233237Sjkim *
429233237Sjkim ******************************************************************************/
430233237Sjkim
431233237Sjkimstatic void
432233237SjkimPrDoDirective (
433233237Sjkim    char                    *DirectiveToken,
434233237Sjkim    char                    **Next,
435233237Sjkim    BOOLEAN                 *IgnoringThisCodeBlock)
436233237Sjkim{
437233237Sjkim    char                    *Token = Gbl_MainTokenBuffer;
438233237Sjkim    char                    *Token2;
439233237Sjkim    char                    *End;
440233237Sjkim    UINT64                  Value;
441233237Sjkim    ACPI_SIZE               TokenOffset;
442233237Sjkim    int                     Directive;
443233237Sjkim    ACPI_STATUS             Status;
444233237Sjkim
445233237Sjkim
446233237Sjkim    if (!DirectiveToken)
447233237Sjkim    {
448233237Sjkim        goto SyntaxError;
449233237Sjkim    }
450233237Sjkim
451233237Sjkim    Directive = PrMatchDirective (DirectiveToken);
452233237Sjkim    if (Directive == ASL_DIRECTIVE_NOT_FOUND)
453233237Sjkim    {
454233237Sjkim        PrError (ASL_ERROR, ASL_MSG_UNKNOWN_DIRECTIVE,
455233237Sjkim            THIS_TOKEN_OFFSET (DirectiveToken));
456233237Sjkim
457233237Sjkim        DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
458233237Sjkim            "#%s: Unknown directive\n",
459233237Sjkim            Gbl_CurrentLineNumber, DirectiveToken);
460233237Sjkim        return;
461233237Sjkim    }
462233237Sjkim
463233237Sjkim    /* TBD: Need a faster way to do this: */
464233237Sjkim
465233237Sjkim    if ((Directive == PR_DIRECTIVE_ELIF) ||
466233237Sjkim        (Directive == PR_DIRECTIVE_ELSE) ||
467233237Sjkim        (Directive == PR_DIRECTIVE_ENDIF))
468233237Sjkim    {
469233237Sjkim        DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID "Begin #%s\n",
470233237Sjkim            Gbl_CurrentLineNumber, Gbl_DirectiveInfo[Directive].Name);
471233237Sjkim    }
472233237Sjkim
473233237Sjkim    /*
474233237Sjkim     * Need to always check for #else, #elif, #endif regardless of
475233237Sjkim     * whether we are ignoring the current code block, since these
476233237Sjkim     * are conditional code block terminators.
477233237Sjkim     */
478233237Sjkim    switch (Directive)
479233237Sjkim    {
480233237Sjkim    case PR_DIRECTIVE_ELIF:
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:
497233237Sjkim        *IgnoringThisCodeBlock = !(*IgnoringThisCodeBlock);
498233237Sjkim        return;
499233237Sjkim
500233237Sjkim    case PR_DIRECTIVE_ENDIF:
501233237Sjkim        *IgnoringThisCodeBlock = FALSE;
502233237Sjkim        Gbl_IfDepth--;
503233237Sjkim        if (Gbl_IfDepth < 0)
504233237Sjkim        {
505233237Sjkim            PrError (ASL_ERROR, ASL_MSG_ENDIF_MISMATCH,
506233237Sjkim                THIS_TOKEN_OFFSET (DirectiveToken));
507233237Sjkim            Gbl_IfDepth = 0;
508233237Sjkim        }
509233237Sjkim        return;
510233237Sjkim
511233237Sjkim    default:
512233237Sjkim        break;
513233237Sjkim    }
514233237Sjkim
515233237Sjkim    /*
516233237Sjkim     * At this point, if we are ignoring the current code block,
517233237Sjkim     * do not process any more directives (i.e., ignore them also.)
518233237Sjkim     */
519233237Sjkim    if (*IgnoringThisCodeBlock == TRUE)
520233237Sjkim    {
521233237Sjkim        return;
522233237Sjkim    }
523233237Sjkim
524233237Sjkim    DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID "Begin #%s\n",
525233237Sjkim        Gbl_CurrentLineNumber, Gbl_DirectiveInfo[Directive].Name);
526233237Sjkim
527233237Sjkim    /* Most directives have at least one argument */
528233237Sjkim
529233237Sjkim    if (Gbl_DirectiveInfo[Directive].ArgCount == 1)
530233237Sjkim    {
531233237Sjkim        Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next);
532233237Sjkim        if (!Token)
533233237Sjkim        {
534233237Sjkim            goto SyntaxError;
535233237Sjkim        }
536233237Sjkim    }
537233237Sjkim
538233237Sjkim    switch (Directive)
539233237Sjkim    {
540233237Sjkim    case PR_DIRECTIVE_DEFINE:
541233237Sjkim        /*
542233237Sjkim         * By definition, if first char after the name is a paren,
543233237Sjkim         * this is a function macro.
544233237Sjkim         */
545233237Sjkim        TokenOffset = Token - Gbl_MainTokenBuffer + strlen (Token);
546233237Sjkim        if (*(&Gbl_CurrentLineBuffer[TokenOffset]) == '(')
547233237Sjkim        {
548233237Sjkim#ifndef MACROS_SUPPORTED
549233237Sjkim            AcpiOsPrintf ("#define macros not supported\n");
550233237Sjkim            goto SyntaxError;
551233237Sjkim#else
552233237Sjkim            PrAddMacro (Token, Next);
553233237Sjkim#endif
554233237Sjkim        }
555233237Sjkim        else
556233237Sjkim        {
557233237Sjkim            /* Use the remainder of the line for the #define */
558233237Sjkim
559233237Sjkim            Token2 = *Next;
560233237Sjkim            if (Token2)
561233237Sjkim            {
562233237Sjkim                while ((*Token2 == ' ') || (*Token2 == '\t'))
563233237Sjkim                {
564233237Sjkim                    Token2++;
565233237Sjkim                }
566233237Sjkim                End = Token2;
567233237Sjkim                while (*End != '\n')
568233237Sjkim                {
569233237Sjkim                    End++;
570233237Sjkim                }
571233237Sjkim                *End = 0;
572233237Sjkim            }
573233237Sjkim            else
574233237Sjkim            {
575233237Sjkim                Token2 = "";
576233237Sjkim            }
577233237Sjkim#if 0
578233237Sjkim            Token2 = PrGetNextToken (NULL, "\n", /*PR_TOKEN_SEPARATORS,*/ Next);
579233237Sjkim            if (!Token2)
580233237Sjkim            {
581233237Sjkim                Token2 = "";
582233237Sjkim            }
583233237Sjkim#endif
584233237Sjkim            DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
585233237Sjkim                "New #define: %s->%s\n",
586233237Sjkim                Gbl_CurrentLineNumber, Token, Token2);
587233237Sjkim
588233237Sjkim            PrAddDefine (Token, Token2, FALSE);
589233237Sjkim        }
590233237Sjkim        break;
591233237Sjkim
592233237Sjkim    case PR_DIRECTIVE_ERROR:
593233237Sjkim        /* TBD compiler should abort */
594233237Sjkim        /* Note: No macro expansion */
595233237Sjkim
596233237Sjkim        PrError (ASL_ERROR, ASL_MSG_ERROR_DIRECTIVE,
597233237Sjkim            THIS_TOKEN_OFFSET (Token));
598233237Sjkim        break;
599233237Sjkim
600233237Sjkim    case PR_DIRECTIVE_IF:
601233237Sjkim        TokenOffset = Token - Gbl_MainTokenBuffer;
602233237Sjkim
603233237Sjkim        /* Need to expand #define macros in the expression string first */
604233237Sjkim
605233237Sjkim        Status = PrResolveIntegerExpression (
606233237Sjkim            &Gbl_CurrentLineBuffer[TokenOffset-1], &Value);
607233237Sjkim        if (ACPI_FAILURE (Status))
608233237Sjkim        {
609233237Sjkim            return;
610233237Sjkim        }
611233237Sjkim
612233237Sjkim        if (!Value)
613233237Sjkim        {
614233237Sjkim            *IgnoringThisCodeBlock = TRUE;
615233237Sjkim        }
616233237Sjkim
617233237Sjkim        DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
618233237Sjkim            "Resolved #if: %8.8X%8.8X %s\n",
619233237Sjkim            Gbl_CurrentLineNumber, ACPI_FORMAT_UINT64 (Value),
620233237Sjkim            *IgnoringThisCodeBlock ? "<Skipping Block>" : "<Executing Block>");
621233237Sjkim
622233237Sjkim        Gbl_IfDepth++;
623233237Sjkim        break;
624233237Sjkim
625233237Sjkim    case PR_DIRECTIVE_IFDEF:
626233237Sjkim        if (!PrMatchDefine (Token))
627233237Sjkim        {
628233237Sjkim            *IgnoringThisCodeBlock = TRUE;
629233237Sjkim        }
630233237Sjkim
631233237Sjkim        Gbl_IfDepth++;
632233237Sjkim        DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
633233237Sjkim            "Start #ifdef %s\n", Gbl_CurrentLineNumber,
634233237Sjkim            *IgnoringThisCodeBlock ? "<Skipping Block>" : "<Executing Block>");
635233237Sjkim        break;
636233237Sjkim
637233237Sjkim    case PR_DIRECTIVE_IFNDEF:
638233237Sjkim        if (PrMatchDefine (Token))
639233237Sjkim        {
640233237Sjkim            *IgnoringThisCodeBlock = TRUE;
641233237Sjkim        }
642233237Sjkim
643233237Sjkim        Gbl_IfDepth++;
644233237Sjkim        DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
645233237Sjkim            "Start #ifndef %2.2X\n", Gbl_CurrentLineNumber,
646233237Sjkim            *IgnoringThisCodeBlock, Gbl_CurrentLineNumber);
647233237Sjkim        break;
648233237Sjkim
649233237Sjkim    case PR_DIRECTIVE_INCLUDE:
650233237Sjkim        Token = PrGetNextToken (NULL, " \"<>", Next);
651233237Sjkim        if (!Token)
652233237Sjkim        {
653233237Sjkim            goto SyntaxError;
654233237Sjkim        }
655233237Sjkim
656233237Sjkim        DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
657233237Sjkim            "Start #include file %s\n", Gbl_CurrentLineNumber,
658233237Sjkim            Token, Gbl_CurrentLineNumber);
659233237Sjkim
660233237Sjkim        PrOpenIncludeFile (Token);
661233237Sjkim        break;
662233237Sjkim
663233237Sjkim    case PR_DIRECTIVE_PRAGMA:
664233237Sjkim        /* Only "#pragma message" supported at this time */
665233237Sjkim
666233237Sjkim        if (strcmp (Token, "message"))
667233237Sjkim        {
668233237Sjkim            PrError (ASL_ERROR, ASL_MSG_UNKNOWN_PRAGMA,
669233237Sjkim                THIS_TOKEN_OFFSET (Token));
670233237Sjkim            return;
671233237Sjkim        }
672233237Sjkim
673233237Sjkim        Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next);
674233237Sjkim        if (!Token)
675233237Sjkim        {
676233237Sjkim            goto SyntaxError;
677233237Sjkim        }
678233237Sjkim
679233237Sjkim        TokenOffset = Token - Gbl_MainTokenBuffer;
680233237Sjkim        AcpiOsPrintf ("%s\n", &Gbl_CurrentLineBuffer[TokenOffset]);
681233237Sjkim        break;
682233237Sjkim
683233237Sjkim    case PR_DIRECTIVE_UNDEF:
684233237Sjkim        DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
685233237Sjkim            "#undef: %s\n", Gbl_CurrentLineNumber, Token);
686233237Sjkim
687233237Sjkim        PrRemoveDefine (Token);
688233237Sjkim        break;
689233237Sjkim
690233237Sjkim    case PR_DIRECTIVE_WARNING:
691233237Sjkim        PrError (ASL_WARNING, ASL_MSG_ERROR_DIRECTIVE,
692233237Sjkim            THIS_TOKEN_OFFSET (Token));
693233237Sjkim        break;
694233237Sjkim
695233237Sjkim    case PR_DIRECTIVE_LINE:
696233237Sjkim        /* TBD: set line number -- or, do this in main compiler */
697233237Sjkim    default:
698233237Sjkim        /* Should never get here */
699233237Sjkim        DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
700233237Sjkim            "Unrecognized directive: %u\n",
701233237Sjkim            Gbl_CurrentLineNumber, Directive);
702233237Sjkim        break;
703233237Sjkim    }
704233237Sjkim
705233237Sjkim    return;
706233237Sjkim
707233237Sjkim
708233237SjkimSyntaxError:
709233237Sjkim
710233237Sjkim    PrError (ASL_ERROR, ASL_MSG_DIRECTIVE_SYNTAX,
711233237Sjkim        THIS_TOKEN_OFFSET (DirectiveToken));
712233237Sjkim    return;
713233237Sjkim}
714233237Sjkim
715233237Sjkim
716233237Sjkim/*******************************************************************************
717233237Sjkim *
718233237Sjkim * FUNCTION:    PrMatchDirective
719233237Sjkim *
720233237Sjkim * PARAMETERS:  Directive           - Pointer to directive name token
721233237Sjkim *
722233237Sjkim * RETURN:      Index into command array, -1 if not found
723233237Sjkim *
724233237Sjkim * DESCRIPTION: Lookup the incoming directive in the known directives table.
725233237Sjkim *
726233237Sjkim ******************************************************************************/
727233237Sjkim
728233237Sjkimstatic int
729233237SjkimPrMatchDirective (
730233237Sjkim    char                    *Directive)
731233237Sjkim{
732233237Sjkim    int                     i;
733233237Sjkim
734233237Sjkim
735233237Sjkim    if (!Directive || Directive[0] == 0)
736233237Sjkim    {
737233237Sjkim        return (ASL_DIRECTIVE_NOT_FOUND);
738233237Sjkim    }
739233237Sjkim
740233237Sjkim    for (i = 0; Gbl_DirectiveInfo[i].Name; i++)
741233237Sjkim    {
742233237Sjkim        if (!strcmp (Gbl_DirectiveInfo[i].Name, Directive))
743233237Sjkim        {
744233237Sjkim            return (i);
745233237Sjkim        }
746233237Sjkim    }
747233237Sjkim
748233237Sjkim    return (ASL_DIRECTIVE_NOT_FOUND);    /* Command not recognized */
749233237Sjkim}
750