1233237Sjkim/******************************************************************************
2233237Sjkim *
3233237Sjkim * Module Name: prscan - Preprocessor start-up and file scan module
4233237Sjkim *
5233237Sjkim *****************************************************************************/
6233237Sjkim
7233237Sjkim/*
8306536Sjkim * Copyright (C) 2000 - 2016, 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,
68252279Sjkim    char                    **Next);
69233237Sjkim
70306536Sjkimstatic void
71306536SjkimPrGetNextLineInit (
72306536Sjkim    void);
73306536Sjkim
74306536Sjkimstatic UINT32
75306536SjkimPrGetNextLine (
76306536Sjkim    FILE                    *Handle);
77306536Sjkim
78233237Sjkimstatic int
79233237SjkimPrMatchDirective (
80233237Sjkim    char                    *Directive);
81233237Sjkim
82252279Sjkimstatic void
83252279SjkimPrPushDirective (
84252279Sjkim    int                     Directive,
85252279Sjkim    char                    *Argument);
86252279Sjkim
87252279Sjkimstatic ACPI_STATUS
88252279SjkimPrPopDirective (
89252279Sjkim    void);
90252279Sjkim
91252279Sjkimstatic void
92252279SjkimPrDbgPrint (
93252279Sjkim    char                    *Action,
94252279Sjkim    char                    *DirectiveName);
95252279Sjkim
96284460Sjkimstatic void
97284460SjkimPrDoIncludeBuffer (
98284460Sjkim    char                    *Pathname,
99284460Sjkim    char                    *BufferName);
100252279Sjkim
101284460Sjkimstatic void
102284460SjkimPrDoIncludeFile (
103284460Sjkim    char                    *Pathname);
104284460Sjkim
105284460Sjkim
106233237Sjkim/*
107233237Sjkim * Supported preprocessor directives
108284460Sjkim * Each entry is of the form "Name, ArgumentCount"
109233237Sjkim */
110233237Sjkimstatic const PR_DIRECTIVE_INFO      Gbl_DirectiveInfo[] =
111233237Sjkim{
112284460Sjkim    {"define",          1},
113284460Sjkim    {"elif",            0}, /* Converted to #else..#if internally */
114284460Sjkim    {"else",            0},
115284460Sjkim    {"endif",           0},
116284460Sjkim    {"error",           1},
117284460Sjkim    {"if",              1},
118284460Sjkim    {"ifdef",           1},
119284460Sjkim    {"ifndef",          1},
120284460Sjkim    {"include",         0}, /* Argument is not standard format, so just use 0 here */
121284460Sjkim    {"includebuffer",   0}, /* Argument is not standard format, so just use 0 here */
122284460Sjkim    {"line",            1},
123284460Sjkim    {"pragma",          1},
124284460Sjkim    {"undef",           1},
125284460Sjkim    {"warning",         1},
126284460Sjkim    {NULL,              0}
127233237Sjkim};
128233237Sjkim
129284460Sjkim/* This table must match ordering of above table exactly */
130284460Sjkim
131233237Sjkimenum Gbl_DirectiveIndexes
132233237Sjkim{
133233237Sjkim    PR_DIRECTIVE_DEFINE = 0,
134233237Sjkim    PR_DIRECTIVE_ELIF,
135233237Sjkim    PR_DIRECTIVE_ELSE,
136233237Sjkim    PR_DIRECTIVE_ENDIF,
137233237Sjkim    PR_DIRECTIVE_ERROR,
138233237Sjkim    PR_DIRECTIVE_IF,
139233237Sjkim    PR_DIRECTIVE_IFDEF,
140233237Sjkim    PR_DIRECTIVE_IFNDEF,
141233237Sjkim    PR_DIRECTIVE_INCLUDE,
142284460Sjkim    PR_DIRECTIVE_INCLUDEBUFFER,
143233237Sjkim    PR_DIRECTIVE_LINE,
144233237Sjkim    PR_DIRECTIVE_PRAGMA,
145233237Sjkim    PR_DIRECTIVE_UNDEF,
146306536Sjkim    PR_DIRECTIVE_WARNING
147233237Sjkim};
148233237Sjkim
149233237Sjkim#define ASL_DIRECTIVE_NOT_FOUND     -1
150233237Sjkim
151233237Sjkim
152233237Sjkim/*******************************************************************************
153233237Sjkim *
154233237Sjkim * FUNCTION:    PrInitializePreprocessor
155233237Sjkim *
156233237Sjkim * PARAMETERS:  None
157233237Sjkim *
158233237Sjkim * RETURN:      None
159233237Sjkim *
160233237Sjkim * DESCRIPTION: Startup initialization for the Preprocessor.
161233237Sjkim *
162233237Sjkim ******************************************************************************/
163233237Sjkim
164233237Sjkimvoid
165233237SjkimPrInitializePreprocessor (
166233237Sjkim    void)
167233237Sjkim{
168233237Sjkim    /* Init globals and the list of #defines */
169233237Sjkim
170233237Sjkim    PrInitializeGlobals ();
171233237Sjkim    Gbl_DefineList = NULL;
172233237Sjkim}
173233237Sjkim
174233237Sjkim
175233237Sjkim/*******************************************************************************
176233237Sjkim *
177233237Sjkim * FUNCTION:    PrInitializeGlobals
178233237Sjkim *
179233237Sjkim * PARAMETERS:  None
180233237Sjkim *
181233237Sjkim * RETURN:      None
182233237Sjkim *
183233237Sjkim * DESCRIPTION: Initialize globals for the Preprocessor. Used for startuup
184233237Sjkim *              initialization and re-initialization between compiles during
185233237Sjkim *              a multiple source file compile.
186233237Sjkim *
187233237Sjkim ******************************************************************************/
188233237Sjkim
189233237Sjkimvoid
190233237SjkimPrInitializeGlobals (
191233237Sjkim    void)
192233237Sjkim{
193233237Sjkim    /* Init globals */
194233237Sjkim
195233237Sjkim    Gbl_InputFileList = NULL;
196306536Sjkim    Gbl_CurrentLineNumber = 1;
197233237Sjkim    Gbl_PreprocessorLineNumber = 1;
198233237Sjkim    Gbl_PreprocessorError = FALSE;
199252279Sjkim
200252279Sjkim    /* These are used to track #if/#else blocks (possibly nested) */
201252279Sjkim
202252279Sjkim    Gbl_IfDepth = 0;
203252279Sjkim    Gbl_IgnoringThisCodeBlock = FALSE;
204252279Sjkim    Gbl_DirectiveStack = NULL;
205233237Sjkim}
206233237Sjkim
207233237Sjkim
208233237Sjkim/*******************************************************************************
209233237Sjkim *
210233237Sjkim * FUNCTION:    PrTerminatePreprocessor
211233237Sjkim *
212233237Sjkim * PARAMETERS:  None
213233237Sjkim *
214233237Sjkim * RETURN:      None
215233237Sjkim *
216233237Sjkim * DESCRIPTION: Termination of the preprocessor. Delete lists. Keep any
217233237Sjkim *              defines that were specified on the command line, in order to
218233237Sjkim *              support multiple compiles with a single compiler invocation.
219233237Sjkim *
220233237Sjkim ******************************************************************************/
221233237Sjkim
222233237Sjkimvoid
223233237SjkimPrTerminatePreprocessor (
224233237Sjkim    void)
225233237Sjkim{
226233237Sjkim    PR_DEFINE_INFO          *DefineInfo;
227233237Sjkim
228233237Sjkim
229233237Sjkim    /*
230233237Sjkim     * The persistent defines (created on the command line) are always at the
231233237Sjkim     * end of the list. We save them.
232233237Sjkim     */
233233237Sjkim    while ((Gbl_DefineList) && (!Gbl_DefineList->Persist))
234233237Sjkim    {
235233237Sjkim        DefineInfo = Gbl_DefineList;
236233237Sjkim        Gbl_DefineList = DefineInfo->Next;
237233237Sjkim
238233237Sjkim        ACPI_FREE (DefineInfo->Replacement);
239233237Sjkim        ACPI_FREE (DefineInfo->Identifier);
240233237Sjkim        ACPI_FREE (DefineInfo);
241233237Sjkim    }
242233237Sjkim}
243233237Sjkim
244233237Sjkim
245233237Sjkim/*******************************************************************************
246233237Sjkim *
247233237Sjkim * FUNCTION:    PrDoPreprocess
248233237Sjkim *
249233237Sjkim * PARAMETERS:  None
250233237Sjkim *
251252279Sjkim * RETURN:      None
252233237Sjkim *
253233237Sjkim * DESCRIPTION: Main entry point for the iASL Preprocessor. Input file must
254233237Sjkim *              be already open. Handles multiple input files via the
255233237Sjkim *              #include directive.
256233237Sjkim *
257233237Sjkim ******************************************************************************/
258233237Sjkim
259252279Sjkimvoid
260233237SjkimPrDoPreprocess (
261233237Sjkim    void)
262233237Sjkim{
263233237Sjkim    BOOLEAN                 MoreInputFiles;
264233237Sjkim
265233237Sjkim
266233237Sjkim    DbgPrint (ASL_DEBUG_OUTPUT, "Starting preprocessing phase\n\n");
267233237Sjkim
268233237Sjkim
269233237Sjkim    FlSeekFile (ASL_FILE_INPUT, 0);
270233237Sjkim    PrDumpPredefinedNames ();
271233237Sjkim
272233237Sjkim    /* Main preprocessor loop, handles include files */
273233237Sjkim
274233237Sjkim    do
275233237Sjkim    {
276233237Sjkim        PrPreprocessInputFile ();
277233237Sjkim        MoreInputFiles = PrPopInputFileStack ();
278233237Sjkim
279233237Sjkim    } while (MoreInputFiles);
280233237Sjkim
281306536Sjkim    /* Point compiler input to the new preprocessor output file (.pre) */
282233237Sjkim
283233237Sjkim    FlCloseFile (ASL_FILE_INPUT);
284233237Sjkim    Gbl_Files[ASL_FILE_INPUT].Handle = Gbl_Files[ASL_FILE_PREPROCESSOR].Handle;
285233237Sjkim    AslCompilerin = Gbl_Files[ASL_FILE_INPUT].Handle;
286233237Sjkim
287233237Sjkim    /* Reset globals to allow compiler to run */
288233237Sjkim
289233237Sjkim    FlSeekFile (ASL_FILE_INPUT, 0);
290306536Sjkim    if (!Gbl_PreprocessOnly)
291306536Sjkim    {
292306536Sjkim        Gbl_CurrentLineNumber = 0;
293306536Sjkim    }
294233237Sjkim
295233237Sjkim    DbgPrint (ASL_DEBUG_OUTPUT, "Preprocessing phase complete \n\n");
296233237Sjkim}
297233237Sjkim
298233237Sjkim
299233237Sjkim/*******************************************************************************
300233237Sjkim *
301233237Sjkim * FUNCTION:    PrPreprocessInputFile
302233237Sjkim *
303233237Sjkim * PARAMETERS:  None
304233237Sjkim *
305233237Sjkim * RETURN:      None
306233237Sjkim *
307233237Sjkim * DESCRIPTION: Preprocess one entire file, line-by-line.
308233237Sjkim *
309233237Sjkim * Input:  Raw user ASL from ASL_FILE_INPUT
310306536Sjkim * Output: Preprocessed file written to ASL_FILE_PREPROCESSOR and
311306536Sjkim *         (optionally) ASL_FILE_PREPROCESSOR_USER
312233237Sjkim *
313233237Sjkim ******************************************************************************/
314233237Sjkim
315233237Sjkimstatic void
316233237SjkimPrPreprocessInputFile (
317233237Sjkim    void)
318233237Sjkim{
319306536Sjkim    UINT32                  Status;
320233237Sjkim    char                    *Token;
321233237Sjkim    char                    *ReplaceString;
322233237Sjkim    PR_DEFINE_INFO          *DefineInfo;
323233237Sjkim    ACPI_SIZE               TokenOffset;
324233237Sjkim    char                    *Next;
325233237Sjkim    int                     OffsetAdjust;
326233237Sjkim
327233237Sjkim
328306536Sjkim    PrGetNextLineInit ();
329233237Sjkim
330306536Sjkim    /* Scan source line-by-line and process directives. Then write the .i file */
331306536Sjkim
332306536Sjkim    while ((Status = PrGetNextLine (Gbl_Files[ASL_FILE_INPUT].Handle)) != ASL_EOF)
333233237Sjkim    {
334306536Sjkim        Gbl_CurrentLineNumber++;
335306536Sjkim        Gbl_LogicalLineNumber++;
336306536Sjkim
337306536Sjkim        if (Status == ASL_IGNORE_LINE)
338306536Sjkim        {
339306536Sjkim            goto WriteEntireLine;
340306536Sjkim        }
341306536Sjkim
342233237Sjkim        /* Need a copy of the input line for strok() */
343233237Sjkim
344233237Sjkim        strcpy (Gbl_MainTokenBuffer, Gbl_CurrentLineBuffer);
345233237Sjkim        Token = PrGetNextToken (Gbl_MainTokenBuffer, PR_TOKEN_SEPARATORS, &Next);
346233237Sjkim        OffsetAdjust = 0;
347233237Sjkim
348233237Sjkim        /* All preprocessor directives must begin with '#' */
349233237Sjkim
350233237Sjkim        if (Token && (*Token == '#'))
351233237Sjkim        {
352233237Sjkim            if (strlen (Token) == 1)
353233237Sjkim            {
354233237Sjkim                Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, &Next);
355233237Sjkim            }
356233237Sjkim            else
357233237Sjkim            {
358233237Sjkim                Token++;    /* Skip leading # */
359233237Sjkim            }
360233237Sjkim
361233237Sjkim            /* Execute the directive, do not write line to output file */
362233237Sjkim
363252279Sjkim            PrDoDirective (Token, &Next);
364233237Sjkim            continue;
365233237Sjkim        }
366233237Sjkim
367233237Sjkim        /*
368233237Sjkim         * If we are currently within the part of an IF/ELSE block that is
369233237Sjkim         * FALSE, ignore the line and do not write it to the output file.
370233237Sjkim         * This continues until an #else or #endif is encountered.
371233237Sjkim         */
372252279Sjkim        if (Gbl_IgnoringThisCodeBlock)
373233237Sjkim        {
374233237Sjkim            continue;
375233237Sjkim        }
376233237Sjkim
377233237Sjkim        /* Match and replace all #defined names within this source line */
378233237Sjkim
379233237Sjkim        while (Token)
380233237Sjkim        {
381233237Sjkim            DefineInfo = PrMatchDefine (Token);
382233237Sjkim            if (DefineInfo)
383233237Sjkim            {
384233237Sjkim                if (DefineInfo->Body)
385233237Sjkim                {
386233237Sjkim                    /* This is a macro */
387233237Sjkim
388233237Sjkim                    DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
389233237Sjkim                        "Matched Macro: %s->%s\n",
390233237Sjkim                        Gbl_CurrentLineNumber, DefineInfo->Identifier,
391233237Sjkim                        DefineInfo->Replacement);
392233237Sjkim
393233237Sjkim                    PrDoMacroInvocation (Gbl_MainTokenBuffer, Token,
394233237Sjkim                        DefineInfo, &Next);
395233237Sjkim                }
396233237Sjkim                else
397233237Sjkim                {
398233237Sjkim                    ReplaceString = DefineInfo->Replacement;
399233237Sjkim
400233237Sjkim                    /* Replace the name in the original line buffer */
401233237Sjkim
402233237Sjkim                    TokenOffset = Token - Gbl_MainTokenBuffer + OffsetAdjust;
403233237Sjkim                    PrReplaceData (
404233237Sjkim                        &Gbl_CurrentLineBuffer[TokenOffset], strlen (Token),
405233237Sjkim                        ReplaceString, strlen (ReplaceString));
406233237Sjkim
407233237Sjkim                    /* Adjust for length difference between old and new name length */
408233237Sjkim
409233237Sjkim                    OffsetAdjust += strlen (ReplaceString) - strlen (Token);
410233237Sjkim
411233237Sjkim                    DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
412233237Sjkim                        "Matched #define: %s->%s\n",
413233237Sjkim                        Gbl_CurrentLineNumber, Token,
414233237Sjkim                        *ReplaceString ? ReplaceString : "(NULL STRING)");
415233237Sjkim                }
416233237Sjkim            }
417233237Sjkim
418233237Sjkim            Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, &Next);
419233237Sjkim        }
420233237Sjkim
421234623Sjkim        Gbl_PreprocessorLineNumber++;
422234623Sjkim
423306536Sjkim
424306536SjkimWriteEntireLine:
425234623Sjkim        /*
426234623Sjkim         * Now we can write the possibly modified source line to the
427306536Sjkim         * preprocessor file(s).
428234623Sjkim         */
429233237Sjkim        FlWriteFile (ASL_FILE_PREPROCESSOR, Gbl_CurrentLineBuffer,
430233237Sjkim            strlen (Gbl_CurrentLineBuffer));
431233237Sjkim    }
432233237Sjkim}
433233237Sjkim
434233237Sjkim
435233237Sjkim/*******************************************************************************
436233237Sjkim *
437233237Sjkim * FUNCTION:    PrDoDirective
438233237Sjkim *
439233237Sjkim * PARAMETERS:  Directive               - Pointer to directive name token
440233237Sjkim *              Next                    - "Next" buffer from GetNextToken
441233237Sjkim *
442252279Sjkim * RETURN:      None.
443233237Sjkim *
444233237Sjkim * DESCRIPTION: Main processing for all preprocessor directives
445233237Sjkim *
446233237Sjkim ******************************************************************************/
447233237Sjkim
448233237Sjkimstatic void
449233237SjkimPrDoDirective (
450233237Sjkim    char                    *DirectiveToken,
451252279Sjkim    char                    **Next)
452233237Sjkim{
453233237Sjkim    char                    *Token = Gbl_MainTokenBuffer;
454284460Sjkim    char                    *Token2 = NULL;
455233237Sjkim    char                    *End;
456233237Sjkim    UINT64                  Value;
457233237Sjkim    ACPI_SIZE               TokenOffset;
458233237Sjkim    int                     Directive;
459233237Sjkim    ACPI_STATUS             Status;
460233237Sjkim
461233237Sjkim
462233237Sjkim    if (!DirectiveToken)
463233237Sjkim    {
464233237Sjkim        goto SyntaxError;
465233237Sjkim    }
466233237Sjkim
467233237Sjkim    Directive = PrMatchDirective (DirectiveToken);
468233237Sjkim    if (Directive == ASL_DIRECTIVE_NOT_FOUND)
469233237Sjkim    {
470233237Sjkim        PrError (ASL_ERROR, ASL_MSG_UNKNOWN_DIRECTIVE,
471233237Sjkim            THIS_TOKEN_OFFSET (DirectiveToken));
472233237Sjkim
473284460Sjkim        DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
474233237Sjkim            "#%s: Unknown directive\n",
475233237Sjkim            Gbl_CurrentLineNumber, DirectiveToken);
476233237Sjkim        return;
477233237Sjkim    }
478233237Sjkim
479252279Sjkim    /*
480306536Sjkim     * Emit a line directive into the preprocessor file (.pre) after
481306536Sjkim     * every matched directive. This is passed through to the compiler
482306536Sjkim     * so that error/warning messages are kept in sync with the
483306536Sjkim     * original source file.
484306536Sjkim     */
485306536Sjkim    FlPrintFile (ASL_FILE_PREPROCESSOR, "#line %u \"%s\" // #%s\n",
486306536Sjkim        Gbl_CurrentLineNumber, Gbl_Files[ASL_FILE_INPUT].Filename,
487306536Sjkim        Gbl_DirectiveInfo[Directive].Name);
488306536Sjkim
489306536Sjkim    /*
490252279Sjkim     * If we are currently ignoring this block and we encounter a #else or
491252279Sjkim     * #elif, we must ignore their blocks also if the parent block is also
492252279Sjkim     * being ignored.
493252279Sjkim     */
494252279Sjkim    if (Gbl_IgnoringThisCodeBlock)
495252279Sjkim    {
496252279Sjkim        switch (Directive)
497252279Sjkim        {
498252279Sjkim        case PR_DIRECTIVE_ELSE:
499252279Sjkim        case PR_DIRECTIVE_ELIF:
500233237Sjkim
501306536Sjkim            if (Gbl_DirectiveStack &&
502306536Sjkim                Gbl_DirectiveStack->IgnoringThisCodeBlock)
503252279Sjkim            {
504252279Sjkim                PrDbgPrint ("Ignoring", Gbl_DirectiveInfo[Directive].Name);
505252279Sjkim                return;
506252279Sjkim            }
507252279Sjkim            break;
508252279Sjkim
509252279Sjkim        default:
510252279Sjkim            break;
511252279Sjkim        }
512233237Sjkim    }
513233237Sjkim
514233237Sjkim    /*
515233237Sjkim     * Need to always check for #else, #elif, #endif regardless of
516233237Sjkim     * whether we are ignoring the current code block, since these
517233237Sjkim     * are conditional code block terminators.
518233237Sjkim     */
519233237Sjkim    switch (Directive)
520233237Sjkim    {
521252279Sjkim    case PR_DIRECTIVE_ELSE:
522252279Sjkim
523252279Sjkim        Gbl_IgnoringThisCodeBlock = !(Gbl_IgnoringThisCodeBlock);
524252279Sjkim        PrDbgPrint ("Executing", "else block");
525252279Sjkim        return;
526252279Sjkim
527233237Sjkim    case PR_DIRECTIVE_ELIF:
528250838Sjkim
529252279Sjkim        Gbl_IgnoringThisCodeBlock = !(Gbl_IgnoringThisCodeBlock);
530252279Sjkim        Directive = PR_DIRECTIVE_IF;
531252279Sjkim
532252279Sjkim        if (Gbl_IgnoringThisCodeBlock == TRUE)
533233237Sjkim        {
534233237Sjkim            /* Not executing the ELSE part -- all done here */
535252279Sjkim            PrDbgPrint ("Ignoring", "elif block");
536233237Sjkim            return;
537233237Sjkim        }
538233237Sjkim
539252279Sjkim        /*
540252279Sjkim         * After this, we will execute the IF part further below.
541252279Sjkim         * First, however, pop off the original #if directive.
542252279Sjkim         */
543252279Sjkim        if (ACPI_FAILURE (PrPopDirective ()))
544252279Sjkim        {
545252279Sjkim            PrError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL,
546252279Sjkim                THIS_TOKEN_OFFSET (DirectiveToken));
547252279Sjkim        }
548233237Sjkim
549252279Sjkim        PrDbgPrint ("Executing", "elif block");
550233237Sjkim        break;
551233237Sjkim
552252279Sjkim    case PR_DIRECTIVE_ENDIF:
553250838Sjkim
554252279Sjkim        PrDbgPrint ("Executing", "endif");
555233237Sjkim
556252279Sjkim        /* Pop the owning #if/#ifdef/#ifndef */
557250838Sjkim
558252279Sjkim        if (ACPI_FAILURE (PrPopDirective ()))
559233237Sjkim        {
560233237Sjkim            PrError (ASL_ERROR, ASL_MSG_ENDIF_MISMATCH,
561233237Sjkim                THIS_TOKEN_OFFSET (DirectiveToken));
562233237Sjkim        }
563233237Sjkim        return;
564233237Sjkim
565233237Sjkim    default:
566233237Sjkim        break;
567233237Sjkim    }
568233237Sjkim
569252279Sjkim    /* Most directives have at least one argument */
570252279Sjkim
571284460Sjkim    if (Gbl_DirectiveInfo[Directive].ArgCount >= 1)
572252279Sjkim    {
573252279Sjkim        Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next);
574252279Sjkim        if (!Token)
575252279Sjkim        {
576252279Sjkim            goto SyntaxError;
577252279Sjkim        }
578252279Sjkim    }
579252279Sjkim
580284460Sjkim    if (Gbl_DirectiveInfo[Directive].ArgCount >= 2)
581284460Sjkim    {
582284460Sjkim        Token2 = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next);
583284460Sjkim        if (!Token2)
584284460Sjkim        {
585284460Sjkim            goto SyntaxError;
586284460Sjkim        }
587284460Sjkim    }
588284460Sjkim
589233237Sjkim    /*
590233237Sjkim     * At this point, if we are ignoring the current code block,
591233237Sjkim     * do not process any more directives (i.e., ignore them also.)
592252279Sjkim     * For "if" style directives, open/push a new block anyway. We
593252279Sjkim     * must do this to keep track of #endif directives
594233237Sjkim     */
595252279Sjkim    if (Gbl_IgnoringThisCodeBlock)
596233237Sjkim    {
597252279Sjkim        switch (Directive)
598252279Sjkim        {
599252279Sjkim        case PR_DIRECTIVE_IF:
600252279Sjkim        case PR_DIRECTIVE_IFDEF:
601252279Sjkim        case PR_DIRECTIVE_IFNDEF:
602252279Sjkim
603252279Sjkim            PrPushDirective (Directive, Token);
604252279Sjkim            PrDbgPrint ("Ignoring", Gbl_DirectiveInfo[Directive].Name);
605252279Sjkim            break;
606252279Sjkim
607252279Sjkim        default:
608252279Sjkim            break;
609252279Sjkim        }
610252279Sjkim
611233237Sjkim        return;
612233237Sjkim    }
613233237Sjkim
614252279Sjkim    /*
615252279Sjkim     * Execute the directive
616252279Sjkim     */
617252279Sjkim    PrDbgPrint ("Begin execution", Gbl_DirectiveInfo[Directive].Name);
618233237Sjkim
619252279Sjkim    switch (Directive)
620252279Sjkim    {
621252279Sjkim    case PR_DIRECTIVE_IF:
622233237Sjkim
623252279Sjkim        TokenOffset = Token - Gbl_MainTokenBuffer;
624252279Sjkim
625252279Sjkim        /* Need to expand #define macros in the expression string first */
626252279Sjkim
627252279Sjkim        Status = PrResolveIntegerExpression (
628252279Sjkim            &Gbl_CurrentLineBuffer[TokenOffset-1], &Value);
629252279Sjkim        if (ACPI_FAILURE (Status))
630233237Sjkim        {
631252279Sjkim            return;
632233237Sjkim        }
633233237Sjkim
634252279Sjkim        PrPushDirective (Directive, Token);
635252279Sjkim        if (!Value)
636252279Sjkim        {
637252279Sjkim            Gbl_IgnoringThisCodeBlock = TRUE;
638252279Sjkim        }
639252279Sjkim
640284460Sjkim        DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
641252279Sjkim            "Resolved #if: %8.8X%8.8X %s\n",
642252279Sjkim            Gbl_CurrentLineNumber, ACPI_FORMAT_UINT64 (Value),
643252279Sjkim            Gbl_IgnoringThisCodeBlock ? "<Skipping Block>" : "<Executing Block>");
644252279Sjkim        break;
645252279Sjkim
646252279Sjkim    case PR_DIRECTIVE_IFDEF:
647252279Sjkim
648252279Sjkim        PrPushDirective (Directive, Token);
649252279Sjkim        if (!PrMatchDefine (Token))
650252279Sjkim        {
651252279Sjkim            Gbl_IgnoringThisCodeBlock = TRUE;
652252279Sjkim        }
653252279Sjkim
654252279Sjkim        PrDbgPrint ("Evaluated", "ifdef");
655252279Sjkim        break;
656252279Sjkim
657252279Sjkim    case PR_DIRECTIVE_IFNDEF:
658252279Sjkim
659252279Sjkim        PrPushDirective (Directive, Token);
660252279Sjkim        if (PrMatchDefine (Token))
661252279Sjkim        {
662252279Sjkim            Gbl_IgnoringThisCodeBlock = TRUE;
663252279Sjkim        }
664252279Sjkim
665252279Sjkim        PrDbgPrint ("Evaluated", "ifndef");
666252279Sjkim        break;
667252279Sjkim
668233237Sjkim    case PR_DIRECTIVE_DEFINE:
669233237Sjkim        /*
670233237Sjkim         * By definition, if first char after the name is a paren,
671233237Sjkim         * this is a function macro.
672233237Sjkim         */
673233237Sjkim        TokenOffset = Token - Gbl_MainTokenBuffer + strlen (Token);
674233237Sjkim        if (*(&Gbl_CurrentLineBuffer[TokenOffset]) == '(')
675233237Sjkim        {
676233237Sjkim#ifndef MACROS_SUPPORTED
677306536Sjkim            AcpiOsPrintf (
678306536Sjkim                "%s ERROR - line %u: #define macros are not supported yet\n",
679306536Sjkim                Gbl_CurrentLineBuffer, Gbl_LogicalLineNumber);
680234623Sjkim            exit(1);
681233237Sjkim#else
682233237Sjkim            PrAddMacro (Token, Next);
683233237Sjkim#endif
684233237Sjkim        }
685233237Sjkim        else
686233237Sjkim        {
687233237Sjkim            /* Use the remainder of the line for the #define */
688233237Sjkim
689233237Sjkim            Token2 = *Next;
690233237Sjkim            if (Token2)
691233237Sjkim            {
692233237Sjkim                while ((*Token2 == ' ') || (*Token2 == '\t'))
693233237Sjkim                {
694233237Sjkim                    Token2++;
695233237Sjkim                }
696306536Sjkim
697233237Sjkim                End = Token2;
698233237Sjkim                while (*End != '\n')
699233237Sjkim                {
700233237Sjkim                    End++;
701233237Sjkim                }
702306536Sjkim
703233237Sjkim                *End = 0;
704233237Sjkim            }
705233237Sjkim            else
706233237Sjkim            {
707233237Sjkim                Token2 = "";
708233237Sjkim            }
709233237Sjkim#if 0
710233237Sjkim            Token2 = PrGetNextToken (NULL, "\n", /*PR_TOKEN_SEPARATORS,*/ Next);
711233237Sjkim            if (!Token2)
712233237Sjkim            {
713233237Sjkim                Token2 = "";
714233237Sjkim            }
715233237Sjkim#endif
716284460Sjkim            DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
717233237Sjkim                "New #define: %s->%s\n",
718306536Sjkim                Gbl_LogicalLineNumber, Token, Token2);
719233237Sjkim
720233237Sjkim            PrAddDefine (Token, Token2, FALSE);
721233237Sjkim        }
722233237Sjkim        break;
723233237Sjkim
724233237Sjkim    case PR_DIRECTIVE_ERROR:
725250838Sjkim
726233237Sjkim        /* Note: No macro expansion */
727233237Sjkim
728233237Sjkim        PrError (ASL_ERROR, ASL_MSG_ERROR_DIRECTIVE,
729233237Sjkim            THIS_TOKEN_OFFSET (Token));
730233237Sjkim
731252279Sjkim        Gbl_SourceLine = 0;
732252279Sjkim        Gbl_NextError = Gbl_ErrorLog;
733252279Sjkim        CmCleanupAndExit ();
734252279Sjkim        exit(1);
735250838Sjkim
736233237Sjkim    case PR_DIRECTIVE_INCLUDE:
737250838Sjkim
738233237Sjkim        Token = PrGetNextToken (NULL, " \"<>", Next);
739233237Sjkim        if (!Token)
740233237Sjkim        {
741233237Sjkim            goto SyntaxError;
742233237Sjkim        }
743233237Sjkim
744284460Sjkim        DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
745235945Sjkim            "Start #include file \"%s\"\n", Gbl_CurrentLineNumber,
746233237Sjkim            Token, Gbl_CurrentLineNumber);
747233237Sjkim
748284460Sjkim        PrDoIncludeFile (Token);
749233237Sjkim        break;
750233237Sjkim
751284460Sjkim    case PR_DIRECTIVE_INCLUDEBUFFER:
752284460Sjkim
753284460Sjkim        Token = PrGetNextToken (NULL, " \"<>", Next);
754284460Sjkim        if (!Token)
755284460Sjkim        {
756284460Sjkim            goto SyntaxError;
757284460Sjkim        }
758284460Sjkim
759284460Sjkim        Token2 = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next);
760284460Sjkim        if (!Token2)
761284460Sjkim        {
762284460Sjkim            goto SyntaxError;
763284460Sjkim        }
764284460Sjkim
765284460Sjkim        DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
766284460Sjkim            "Start #includebuffer input from file \"%s\", buffer name %s\n",
767284460Sjkim            Gbl_CurrentLineNumber, Token, Token2);
768284460Sjkim
769284460Sjkim        PrDoIncludeBuffer (Token, Token2);
770284460Sjkim        break;
771284460Sjkim
772234623Sjkim    case PR_DIRECTIVE_LINE:
773250838Sjkim
774234623Sjkim        TokenOffset = Token - Gbl_MainTokenBuffer;
775234623Sjkim
776234623Sjkim        Status = PrResolveIntegerExpression (
777234623Sjkim            &Gbl_CurrentLineBuffer[TokenOffset-1], &Value);
778234623Sjkim        if (ACPI_FAILURE (Status))
779234623Sjkim        {
780234623Sjkim            return;
781234623Sjkim        }
782234623Sjkim
783284460Sjkim        DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
784234623Sjkim            "User #line invocation %s\n", Gbl_CurrentLineNumber,
785234623Sjkim            Token);
786234623Sjkim
787234623Sjkim        Gbl_CurrentLineNumber = (UINT32) Value;
788234623Sjkim
789234623Sjkim        /* Emit #line into the preprocessor file */
790234623Sjkim
791234623Sjkim        FlPrintFile (ASL_FILE_PREPROCESSOR, "#line %u \"%s\"\n",
792234623Sjkim            Gbl_CurrentLineNumber, Gbl_Files[ASL_FILE_INPUT].Filename);
793234623Sjkim        break;
794234623Sjkim
795233237Sjkim    case PR_DIRECTIVE_PRAGMA:
796233237Sjkim
797250838Sjkim        if (!strcmp (Token, "disable"))
798233237Sjkim        {
799250838Sjkim            Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next);
800250838Sjkim            if (!Token)
801250838Sjkim            {
802250838Sjkim                goto SyntaxError;
803250838Sjkim            }
804250838Sjkim
805250838Sjkim            TokenOffset = Token - Gbl_MainTokenBuffer;
806250838Sjkim            AslDisableException (&Gbl_CurrentLineBuffer[TokenOffset]);
807250838Sjkim        }
808250838Sjkim        else if (!strcmp (Token, "message"))
809250838Sjkim        {
810250838Sjkim            Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next);
811250838Sjkim            if (!Token)
812250838Sjkim            {
813250838Sjkim                goto SyntaxError;
814250838Sjkim            }
815250838Sjkim
816250838Sjkim            TokenOffset = Token - Gbl_MainTokenBuffer;
817250838Sjkim            AcpiOsPrintf ("%s\n", &Gbl_CurrentLineBuffer[TokenOffset]);
818250838Sjkim        }
819250838Sjkim        else
820250838Sjkim        {
821233237Sjkim            PrError (ASL_ERROR, ASL_MSG_UNKNOWN_PRAGMA,
822233237Sjkim                THIS_TOKEN_OFFSET (Token));
823233237Sjkim            return;
824233237Sjkim        }
825233237Sjkim
826233237Sjkim        break;
827233237Sjkim
828233237Sjkim    case PR_DIRECTIVE_UNDEF:
829250838Sjkim
830284460Sjkim        DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
831233237Sjkim            "#undef: %s\n", Gbl_CurrentLineNumber, Token);
832233237Sjkim
833233237Sjkim        PrRemoveDefine (Token);
834233237Sjkim        break;
835233237Sjkim
836233237Sjkim    case PR_DIRECTIVE_WARNING:
837250838Sjkim
838252279Sjkim        PrError (ASL_WARNING, ASL_MSG_WARNING_DIRECTIVE,
839233237Sjkim            THIS_TOKEN_OFFSET (Token));
840306536Sjkim
841306536Sjkim        Gbl_SourceLine = 0;
842306536Sjkim        Gbl_NextError = Gbl_ErrorLog;
843233237Sjkim        break;
844233237Sjkim
845233237Sjkim    default:
846250838Sjkim
847233237Sjkim        /* Should never get here */
848284460Sjkim        DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
849233237Sjkim            "Unrecognized directive: %u\n",
850233237Sjkim            Gbl_CurrentLineNumber, Directive);
851233237Sjkim        break;
852233237Sjkim    }
853233237Sjkim
854233237Sjkim    return;
855233237Sjkim
856233237SjkimSyntaxError:
857233237Sjkim
858233237Sjkim    PrError (ASL_ERROR, ASL_MSG_DIRECTIVE_SYNTAX,
859233237Sjkim        THIS_TOKEN_OFFSET (DirectiveToken));
860233237Sjkim    return;
861233237Sjkim}
862233237Sjkim
863233237Sjkim
864233237Sjkim/*******************************************************************************
865233237Sjkim *
866306536Sjkim * FUNCTION:    PrGetNextLine, PrGetNextLineInit
867306536Sjkim *
868306536Sjkim * PARAMETERS:  Handle              - Open file handle for the source file
869306536Sjkim *
870306536Sjkim * RETURN:      Status of the GetLine operation:
871306536Sjkim *              AE_OK               - Normal line, OK status
872306536Sjkim *              ASL_IGNORE_LINE     - Line is blank or part of a multi-line
873306536Sjkim *                                      comment
874306536Sjkim *              ASL_EOF             - End-of-file reached
875306536Sjkim *
876306536Sjkim * DESCRIPTION: Get the next text line from the input file. Does not strip
877306536Sjkim *              comments.
878306536Sjkim *
879306536Sjkim ******************************************************************************/
880306536Sjkim
881306536Sjkim#define PR_NORMAL_TEXT          0
882306536Sjkim#define PR_MULTI_LINE_COMMENT   1
883306536Sjkim#define PR_SINGLE_LINE_COMMENT  2
884306536Sjkim#define PR_QUOTED_STRING        3
885306536Sjkim
886306536Sjkimstatic UINT8                    AcpiGbl_LineScanState = PR_NORMAL_TEXT;
887306536Sjkim
888306536Sjkimstatic void
889306536SjkimPrGetNextLineInit (
890306536Sjkim    void)
891306536Sjkim{
892306536Sjkim    AcpiGbl_LineScanState = 0;
893306536Sjkim}
894306536Sjkim
895306536Sjkimstatic UINT32
896306536SjkimPrGetNextLine (
897306536Sjkim    FILE                    *Handle)
898306536Sjkim{
899306536Sjkim    UINT32                  i;
900306536Sjkim    int                     c = 0;
901306536Sjkim    int                     PreviousChar;
902306536Sjkim
903306536Sjkim
904306536Sjkim    /* Always clear the global line buffer */
905306536Sjkim
906306536Sjkim    memset (Gbl_CurrentLineBuffer, 0, Gbl_LineBufferSize);
907306536Sjkim    for (i = 0; ;)
908306536Sjkim    {
909306536Sjkim        /*
910306536Sjkim         * If line is too long, expand the line buffers. Also increases
911306536Sjkim         * Gbl_LineBufferSize.
912306536Sjkim         */
913306536Sjkim        if (i >= Gbl_LineBufferSize)
914306536Sjkim        {
915306536Sjkim            UtExpandLineBuffers ();
916306536Sjkim        }
917306536Sjkim
918306536Sjkim        PreviousChar = c;
919306536Sjkim        c = getc (Handle);
920306536Sjkim        if (c == EOF)
921306536Sjkim        {
922306536Sjkim            /*
923306536Sjkim             * On EOF: If there is anything in the line buffer, terminate
924306536Sjkim             * it with a newline, and catch the EOF on the next call
925306536Sjkim             * to this function.
926306536Sjkim             */
927306536Sjkim            if (i > 0)
928306536Sjkim            {
929306536Sjkim                Gbl_CurrentLineBuffer[i] = '\n';
930306536Sjkim                return (AE_OK);
931306536Sjkim            }
932306536Sjkim
933306536Sjkim            return (ASL_EOF);
934306536Sjkim        }
935306536Sjkim
936306536Sjkim        /* Update state machine as necessary */
937306536Sjkim
938306536Sjkim        switch (AcpiGbl_LineScanState)
939306536Sjkim        {
940306536Sjkim        case PR_NORMAL_TEXT:
941306536Sjkim
942306536Sjkim            /* Check for multi-line comment start */
943306536Sjkim
944306536Sjkim            if ((PreviousChar == '/') && (c == '*'))
945306536Sjkim            {
946306536Sjkim                AcpiGbl_LineScanState = PR_MULTI_LINE_COMMENT;
947306536Sjkim            }
948306536Sjkim
949306536Sjkim            /* Check for single-line comment start */
950306536Sjkim
951306536Sjkim            else if ((PreviousChar == '/') && (c == '/'))
952306536Sjkim            {
953306536Sjkim                AcpiGbl_LineScanState = PR_SINGLE_LINE_COMMENT;
954306536Sjkim            }
955306536Sjkim
956306536Sjkim            /* Check for quoted string start */
957306536Sjkim
958306536Sjkim            else if (PreviousChar == '"')
959306536Sjkim            {
960306536Sjkim                AcpiGbl_LineScanState = PR_QUOTED_STRING;
961306536Sjkim            }
962306536Sjkim            break;
963306536Sjkim
964306536Sjkim        case PR_QUOTED_STRING:
965306536Sjkim
966306536Sjkim            if (PreviousChar == '"')
967306536Sjkim            {
968306536Sjkim                AcpiGbl_LineScanState = PR_NORMAL_TEXT;
969306536Sjkim            }
970306536Sjkim            break;
971306536Sjkim
972306536Sjkim        case PR_MULTI_LINE_COMMENT:
973306536Sjkim
974306536Sjkim            /* Check for multi-line comment end */
975306536Sjkim
976306536Sjkim            if ((PreviousChar == '*') && (c == '/'))
977306536Sjkim            {
978306536Sjkim                AcpiGbl_LineScanState = PR_NORMAL_TEXT;
979306536Sjkim            }
980306536Sjkim            break;
981306536Sjkim
982306536Sjkim        case PR_SINGLE_LINE_COMMENT: /* Just ignore text until EOL */
983306536Sjkim        default:
984306536Sjkim            break;
985306536Sjkim        }
986306536Sjkim
987306536Sjkim        /* Always copy the character into line buffer */
988306536Sjkim
989306536Sjkim        Gbl_CurrentLineBuffer[i] = (char) c;
990306536Sjkim        i++;
991306536Sjkim
992306536Sjkim        /* Always exit on end-of-line */
993306536Sjkim
994306536Sjkim        if (c == '\n')
995306536Sjkim        {
996306536Sjkim            /* Handle multi-line comments */
997306536Sjkim
998306536Sjkim            if (AcpiGbl_LineScanState == PR_MULTI_LINE_COMMENT)
999306536Sjkim            {
1000306536Sjkim                return (ASL_IGNORE_LINE);
1001306536Sjkim            }
1002306536Sjkim
1003306536Sjkim            /* End of single-line comment */
1004306536Sjkim
1005306536Sjkim            if (AcpiGbl_LineScanState == PR_SINGLE_LINE_COMMENT)
1006306536Sjkim            {
1007306536Sjkim                AcpiGbl_LineScanState = PR_NORMAL_TEXT;
1008306536Sjkim                return (AE_OK);
1009306536Sjkim            }
1010306536Sjkim
1011306536Sjkim            /* Blank line */
1012306536Sjkim
1013306536Sjkim            if (i == 1)
1014306536Sjkim            {
1015306536Sjkim                return (ASL_IGNORE_LINE);
1016306536Sjkim            }
1017306536Sjkim
1018306536Sjkim            return (AE_OK);
1019306536Sjkim        }
1020306536Sjkim    }
1021306536Sjkim}
1022306536Sjkim
1023306536Sjkim
1024306536Sjkim/*******************************************************************************
1025306536Sjkim *
1026233237Sjkim * FUNCTION:    PrMatchDirective
1027233237Sjkim *
1028233237Sjkim * PARAMETERS:  Directive           - Pointer to directive name token
1029233237Sjkim *
1030233237Sjkim * RETURN:      Index into command array, -1 if not found
1031233237Sjkim *
1032233237Sjkim * DESCRIPTION: Lookup the incoming directive in the known directives table.
1033233237Sjkim *
1034233237Sjkim ******************************************************************************/
1035233237Sjkim
1036233237Sjkimstatic int
1037233237SjkimPrMatchDirective (
1038233237Sjkim    char                    *Directive)
1039233237Sjkim{
1040233237Sjkim    int                     i;
1041233237Sjkim
1042233237Sjkim
1043233237Sjkim    if (!Directive || Directive[0] == 0)
1044233237Sjkim    {
1045233237Sjkim        return (ASL_DIRECTIVE_NOT_FOUND);
1046233237Sjkim    }
1047233237Sjkim
1048233237Sjkim    for (i = 0; Gbl_DirectiveInfo[i].Name; i++)
1049233237Sjkim    {
1050233237Sjkim        if (!strcmp (Gbl_DirectiveInfo[i].Name, Directive))
1051233237Sjkim        {
1052233237Sjkim            return (i);
1053233237Sjkim        }
1054233237Sjkim    }
1055233237Sjkim
1056233237Sjkim    return (ASL_DIRECTIVE_NOT_FOUND);    /* Command not recognized */
1057233237Sjkim}
1058252279Sjkim
1059252279Sjkim
1060252279Sjkim/*******************************************************************************
1061252279Sjkim *
1062252279Sjkim * FUNCTION:    PrPushDirective
1063252279Sjkim *
1064252279Sjkim * PARAMETERS:  Directive           - Encoded directive ID
1065252279Sjkim *              Argument            - String containing argument to the
1066252279Sjkim *                                    directive
1067252279Sjkim *
1068252279Sjkim * RETURN:      None
1069252279Sjkim *
1070252279Sjkim * DESCRIPTION: Push an item onto the directive stack. Used for processing
1071252279Sjkim *              nested #if/#else type conditional compilation directives.
1072252279Sjkim *              Specifically: Used on detection of #if/#ifdef/#ifndef to open
1073252279Sjkim *              a block.
1074252279Sjkim *
1075252279Sjkim ******************************************************************************/
1076252279Sjkim
1077252279Sjkimstatic void
1078252279SjkimPrPushDirective (
1079252279Sjkim    int                     Directive,
1080252279Sjkim    char                    *Argument)
1081252279Sjkim{
1082252279Sjkim    DIRECTIVE_INFO          *Info;
1083252279Sjkim
1084252279Sjkim
1085252279Sjkim    /* Allocate and populate a stack info item */
1086252279Sjkim
1087252279Sjkim    Info = ACPI_ALLOCATE (sizeof (DIRECTIVE_INFO));
1088252279Sjkim
1089252279Sjkim    Info->Next = Gbl_DirectiveStack;
1090252279Sjkim    Info->Directive = Directive;
1091252279Sjkim    Info->IgnoringThisCodeBlock = Gbl_IgnoringThisCodeBlock;
1092252279Sjkim    strncpy (Info->Argument, Argument, MAX_ARGUMENT_LENGTH);
1093252279Sjkim
1094252279Sjkim    DbgPrint (ASL_DEBUG_OUTPUT,
1095252279Sjkim        "Pr(%.4u) - [%u %s] %*s Pushed [#%s %s]: IgnoreFlag = %s\n",
1096252279Sjkim        Gbl_CurrentLineNumber, Gbl_IfDepth,
1097252279Sjkim        Gbl_IgnoringThisCodeBlock ? "I" : "E",
1098252279Sjkim        Gbl_IfDepth * 4, " ",
1099252279Sjkim        Gbl_DirectiveInfo[Directive].Name,
1100252279Sjkim        Argument, Gbl_IgnoringThisCodeBlock ? "TRUE" : "FALSE");
1101252279Sjkim
1102252279Sjkim    /* Push new item */
1103252279Sjkim
1104252279Sjkim    Gbl_DirectiveStack = Info;
1105252279Sjkim    Gbl_IfDepth++;
1106252279Sjkim}
1107252279Sjkim
1108252279Sjkim
1109252279Sjkim/*******************************************************************************
1110252279Sjkim *
1111252279Sjkim * FUNCTION:    PrPopDirective
1112252279Sjkim *
1113252279Sjkim * PARAMETERS:  None
1114252279Sjkim *
1115252279Sjkim * RETURN:      Status. Error if the stack is empty.
1116252279Sjkim *
1117252279Sjkim * DESCRIPTION: Pop an item off the directive stack. Used for processing
1118252279Sjkim *              nested #if/#else type conditional compilation directives.
1119252279Sjkim *              Specifically: Used on detection of #elif and #endif to remove
1120252279Sjkim *              the original #if/#ifdef/#ifndef from the stack and close
1121252279Sjkim *              the block.
1122252279Sjkim *
1123252279Sjkim ******************************************************************************/
1124252279Sjkim
1125252279Sjkimstatic ACPI_STATUS
1126252279SjkimPrPopDirective (
1127252279Sjkim    void)
1128252279Sjkim{
1129252279Sjkim    DIRECTIVE_INFO          *Info;
1130252279Sjkim
1131252279Sjkim
1132252279Sjkim    /* Check for empty stack */
1133252279Sjkim
1134252279Sjkim    Info = Gbl_DirectiveStack;
1135252279Sjkim    if (!Info)
1136252279Sjkim    {
1137252279Sjkim        return (AE_ERROR);
1138252279Sjkim    }
1139252279Sjkim
1140252279Sjkim    /* Pop one item, keep globals up-to-date */
1141252279Sjkim
1142252279Sjkim    Gbl_IfDepth--;
1143252279Sjkim    Gbl_IgnoringThisCodeBlock = Info->IgnoringThisCodeBlock;
1144252279Sjkim    Gbl_DirectiveStack = Info->Next;
1145252279Sjkim
1146252279Sjkim    DbgPrint (ASL_DEBUG_OUTPUT,
1147252279Sjkim        "Pr(%.4u) - [%u %s] %*s Popped [#%s %s]: IgnoreFlag now = %s\n",
1148252279Sjkim        Gbl_CurrentLineNumber, Gbl_IfDepth,
1149252279Sjkim        Gbl_IgnoringThisCodeBlock ? "I" : "E",
1150252279Sjkim        Gbl_IfDepth * 4, " ",
1151252279Sjkim        Gbl_DirectiveInfo[Info->Directive].Name,
1152252279Sjkim        Info->Argument, Gbl_IgnoringThisCodeBlock ? "TRUE" : "FALSE");
1153252279Sjkim
1154252279Sjkim    ACPI_FREE (Info);
1155252279Sjkim    return (AE_OK);
1156252279Sjkim}
1157252279Sjkim
1158252279Sjkim
1159252279Sjkim/*******************************************************************************
1160252279Sjkim *
1161252279Sjkim * FUNCTION:    PrDbgPrint
1162252279Sjkim *
1163252279Sjkim * PARAMETERS:  Action              - Action being performed
1164252279Sjkim *              DirectiveName       - Directive being processed
1165252279Sjkim *
1166252279Sjkim * RETURN:      None
1167252279Sjkim *
1168252279Sjkim * DESCRIPTION: Special debug print for directive processing.
1169252279Sjkim *
1170252279Sjkim ******************************************************************************/
1171252279Sjkim
1172252279Sjkimstatic void
1173252279SjkimPrDbgPrint (
1174252279Sjkim    char                    *Action,
1175252279Sjkim    char                    *DirectiveName)
1176252279Sjkim{
1177252279Sjkim
1178252279Sjkim    DbgPrint (ASL_DEBUG_OUTPUT, "Pr(%.4u) - [%u %s] "
1179284460Sjkim        "%*s %s #%s, IfDepth %u\n",
1180252279Sjkim        Gbl_CurrentLineNumber, Gbl_IfDepth,
1181252279Sjkim        Gbl_IgnoringThisCodeBlock ? "I" : "E",
1182252279Sjkim        Gbl_IfDepth * 4, " ",
1183252279Sjkim        Action, DirectiveName, Gbl_IfDepth);
1184252279Sjkim}
1185284460Sjkim
1186284460Sjkim
1187284460Sjkim/*******************************************************************************
1188284460Sjkim *
1189284460Sjkim * FUNCTION:    PrDoIncludeFile
1190284460Sjkim *
1191284460Sjkim * PARAMETERS:  Pathname                - Name of the input file
1192284460Sjkim *
1193284460Sjkim * RETURN:      None.
1194284460Sjkim *
1195284460Sjkim * DESCRIPTION: Open an include file, from #include.
1196284460Sjkim *
1197284460Sjkim ******************************************************************************/
1198284460Sjkim
1199284460Sjkimstatic void
1200284460SjkimPrDoIncludeFile (
1201284460Sjkim    char                    *Pathname)
1202284460Sjkim{
1203284460Sjkim    char                    *FullPathname;
1204284460Sjkim
1205284460Sjkim
1206284460Sjkim    (void) PrOpenIncludeFile (Pathname, "r", &FullPathname);
1207284460Sjkim}
1208284460Sjkim
1209284460Sjkim
1210284460Sjkim/*******************************************************************************
1211284460Sjkim *
1212284460Sjkim * FUNCTION:    PrDoIncludeBuffer
1213284460Sjkim *
1214284460Sjkim * PARAMETERS:  Pathname                - Name of the input binary file
1215284460Sjkim *              BufferName              - ACPI namepath of the buffer
1216284460Sjkim *
1217284460Sjkim * RETURN:      None.
1218284460Sjkim *
1219284460Sjkim * DESCRIPTION: Create an ACPI buffer object from a binary file. The contents
1220284460Sjkim *              of the file are emitted into the buffer object as ascii
1221284460Sjkim *              hex data. From #includebuffer.
1222284460Sjkim *
1223284460Sjkim ******************************************************************************/
1224284460Sjkim
1225284460Sjkimstatic void
1226284460SjkimPrDoIncludeBuffer (
1227284460Sjkim    char                    *Pathname,
1228284460Sjkim    char                    *BufferName)
1229284460Sjkim{
1230284460Sjkim    char                    *FullPathname;
1231284460Sjkim    FILE                    *BinaryBufferFile;
1232284460Sjkim    UINT32                  i = 0;
1233284460Sjkim    UINT8                   c;
1234284460Sjkim
1235284460Sjkim
1236284460Sjkim    BinaryBufferFile = PrOpenIncludeFile (Pathname, "rb", &FullPathname);
1237284460Sjkim    if (!BinaryBufferFile)
1238284460Sjkim    {
1239284460Sjkim        return;
1240284460Sjkim    }
1241284460Sjkim
1242284460Sjkim    /* Emit "Name (XXXX, Buffer() {" header */
1243284460Sjkim
1244284460Sjkim    FlPrintFile (ASL_FILE_PREPROCESSOR, "Name (%s, Buffer()\n{", BufferName);
1245284460Sjkim
1246284460Sjkim    /* Dump the entire file in ascii hex format */
1247284460Sjkim
1248284460Sjkim    while (fread (&c, 1, 1, BinaryBufferFile))
1249284460Sjkim    {
1250284460Sjkim        if (!(i % 8))
1251284460Sjkim        {
1252284460Sjkim            FlPrintFile (ASL_FILE_PREPROCESSOR, "\n   ", c);
1253284460Sjkim        }
1254284460Sjkim
1255284460Sjkim        FlPrintFile (ASL_FILE_PREPROCESSOR, " 0x%2.2X,", c);
1256284460Sjkim        i++;
1257284460Sjkim    }
1258284460Sjkim
1259284460Sjkim    DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
1260284460Sjkim        "#includebuffer: read %u bytes from %s\n",
1261284460Sjkim        Gbl_CurrentLineNumber, i, FullPathname);
1262284460Sjkim
1263284460Sjkim    /* Close the Name() operator */
1264284460Sjkim
1265284460Sjkim    FlPrintFile (ASL_FILE_PREPROCESSOR, "\n})\n", BufferName);
1266284460Sjkim    fclose (BinaryBufferFile);
1267284460Sjkim}
1268