1233237Sjkim/******************************************************************************
2233237Sjkim *
3233237Sjkim * Module Name: prscan - Preprocessor start-up and file scan module
4233237Sjkim *
5233237Sjkim *****************************************************************************/
6233237Sjkim
7316303Sjkim/******************************************************************************
8316303Sjkim *
9316303Sjkim * 1. Copyright Notice
10316303Sjkim *
11316303Sjkim * Some or all of this work - Copyright (c) 1999 - 2017, Intel Corp.
12233237Sjkim * All rights reserved.
13233237Sjkim *
14316303Sjkim * 2. License
15316303Sjkim *
16316303Sjkim * 2.1. This is your license from Intel Corp. under its intellectual property
17316303Sjkim * rights. You may have additional license terms from the party that provided
18316303Sjkim * you this software, covering your right to use that party's intellectual
19316303Sjkim * property rights.
20316303Sjkim *
21316303Sjkim * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22316303Sjkim * copy of the source code appearing in this file ("Covered Code") an
23316303Sjkim * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24316303Sjkim * base code distributed originally by Intel ("Original Intel Code") to copy,
25316303Sjkim * make derivatives, distribute, use and display any portion of the Covered
26316303Sjkim * Code in any form, with the right to sublicense such rights; and
27316303Sjkim *
28316303Sjkim * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29316303Sjkim * license (with the right to sublicense), under only those claims of Intel
30316303Sjkim * patents that are infringed by the Original Intel Code, to make, use, sell,
31316303Sjkim * offer to sell, and import the Covered Code and derivative works thereof
32316303Sjkim * solely to the minimum extent necessary to exercise the above copyright
33316303Sjkim * license, and in no event shall the patent license extend to any additions
34316303Sjkim * to or modifications of the Original Intel Code. No other license or right
35316303Sjkim * is granted directly or by implication, estoppel or otherwise;
36316303Sjkim *
37316303Sjkim * The above copyright and patent license is granted only if the following
38316303Sjkim * conditions are met:
39316303Sjkim *
40316303Sjkim * 3. Conditions
41316303Sjkim *
42316303Sjkim * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43316303Sjkim * Redistribution of source code of any substantial portion of the Covered
44316303Sjkim * Code or modification with rights to further distribute source must include
45316303Sjkim * the above Copyright Notice, the above License, this list of Conditions,
46316303Sjkim * and the following Disclaimer and Export Compliance provision. In addition,
47316303Sjkim * Licensee must cause all Covered Code to which Licensee contributes to
48316303Sjkim * contain a file documenting the changes Licensee made to create that Covered
49316303Sjkim * Code and the date of any change. Licensee must include in that file the
50316303Sjkim * documentation of any changes made by any predecessor Licensee. Licensee
51316303Sjkim * must include a prominent statement that the modification is derived,
52316303Sjkim * directly or indirectly, from Original Intel Code.
53316303Sjkim *
54316303Sjkim * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55316303Sjkim * Redistribution of source code of any substantial portion of the Covered
56316303Sjkim * Code or modification without rights to further distribute source must
57316303Sjkim * include the following Disclaimer and Export Compliance provision in the
58316303Sjkim * documentation and/or other materials provided with distribution. In
59316303Sjkim * addition, Licensee may not authorize further sublicense of source of any
60316303Sjkim * portion of the Covered Code, and must include terms to the effect that the
61316303Sjkim * license from Licensee to its licensee is limited to the intellectual
62316303Sjkim * property embodied in the software Licensee provides to its licensee, and
63316303Sjkim * not to intellectual property embodied in modifications its licensee may
64316303Sjkim * make.
65316303Sjkim *
66316303Sjkim * 3.3. Redistribution of Executable. Redistribution in executable form of any
67316303Sjkim * substantial portion of the Covered Code or modification must reproduce the
68316303Sjkim * above Copyright Notice, and the following Disclaimer and Export Compliance
69316303Sjkim * provision in the documentation and/or other materials provided with the
70316303Sjkim * distribution.
71316303Sjkim *
72316303Sjkim * 3.4. Intel retains all right, title, and interest in and to the Original
73316303Sjkim * Intel Code.
74316303Sjkim *
75316303Sjkim * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76316303Sjkim * Intel shall be used in advertising or otherwise to promote the sale, use or
77316303Sjkim * other dealings in products derived from or relating to the Covered Code
78316303Sjkim * without prior written authorization from Intel.
79316303Sjkim *
80316303Sjkim * 4. Disclaimer and Export Compliance
81316303Sjkim *
82316303Sjkim * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83316303Sjkim * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84316303Sjkim * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85316303Sjkim * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86316303Sjkim * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87316303Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88316303Sjkim * PARTICULAR PURPOSE.
89316303Sjkim *
90316303Sjkim * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91316303Sjkim * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92316303Sjkim * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93316303Sjkim * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94316303Sjkim * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95316303Sjkim * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96316303Sjkim * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97316303Sjkim * LIMITED REMEDY.
98316303Sjkim *
99316303Sjkim * 4.3. Licensee shall not export, either directly or indirectly, any of this
100316303Sjkim * software or system incorporating such software without first obtaining any
101316303Sjkim * required license or other approval from the U. S. Department of Commerce or
102316303Sjkim * any other agency or department of the United States Government. In the
103316303Sjkim * event Licensee exports any such software from the United States or
104316303Sjkim * re-exports any such software from a foreign destination, Licensee shall
105316303Sjkim * ensure that the distribution and export/re-export of the software is in
106316303Sjkim * compliance with all laws, regulations, orders, or other restrictions of the
107316303Sjkim * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108316303Sjkim * any of its subsidiaries will export/re-export any technical data, process,
109316303Sjkim * software, or service, directly or indirectly, to any country for which the
110316303Sjkim * United States government or any agency thereof requires an export license,
111316303Sjkim * other governmental approval, or letter of assurance, without first obtaining
112316303Sjkim * such license, approval or letter.
113316303Sjkim *
114316303Sjkim *****************************************************************************
115316303Sjkim *
116316303Sjkim * Alternatively, you may choose to be licensed under the terms of the
117316303Sjkim * following license:
118316303Sjkim *
119233237Sjkim * Redistribution and use in source and binary forms, with or without
120233237Sjkim * modification, are permitted provided that the following conditions
121233237Sjkim * are met:
122233237Sjkim * 1. Redistributions of source code must retain the above copyright
123233237Sjkim *    notice, this list of conditions, and the following disclaimer,
124233237Sjkim *    without modification.
125233237Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
126233237Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
127233237Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
128233237Sjkim *    including a substantially similar Disclaimer requirement for further
129233237Sjkim *    binary redistribution.
130233237Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
131233237Sjkim *    of any contributors may be used to endorse or promote products derived
132233237Sjkim *    from this software without specific prior written permission.
133233237Sjkim *
134316303Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
135316303Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
136316303Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
137316303Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
138316303Sjkim * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
139316303Sjkim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
140316303Sjkim * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
141316303Sjkim * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
142316303Sjkim * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
143316303Sjkim * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
144316303Sjkim * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
145316303Sjkim *
146316303Sjkim * Alternatively, you may choose to be licensed under the terms of the
147233237Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
148233237Sjkim * Software Foundation.
149233237Sjkim *
150316303Sjkim *****************************************************************************/
151233237Sjkim
152233237Sjkim#define _DECLARE_PR_GLOBALS
153233237Sjkim
154233250Sjkim#include <contrib/dev/acpica/compiler/aslcompiler.h>
155233237Sjkim
156233237Sjkim/*
157233237Sjkim * TBDs:
158233237Sjkim *
159233237Sjkim * No nested macros, maybe never
160233237Sjkim * Implement ASL "Include" as well as "#include" here?
161233237Sjkim */
162233237Sjkim#define _COMPONENT          ASL_PREPROCESSOR
163233237Sjkim        ACPI_MODULE_NAME    ("prscan")
164233237Sjkim
165233237Sjkim
166233237Sjkim/* Local prototypes */
167233237Sjkim
168233237Sjkimstatic void
169233237SjkimPrPreprocessInputFile (
170233237Sjkim    void);
171233237Sjkim
172233237Sjkimstatic void
173233237SjkimPrDoDirective (
174233237Sjkim    char                    *DirectiveToken,
175252279Sjkim    char                    **Next);
176233237Sjkim
177284583Sjkimstatic void
178284583SjkimPrGetNextLineInit (
179284583Sjkim    void);
180284583Sjkim
181284583Sjkimstatic UINT32
182284583SjkimPrGetNextLine (
183284583Sjkim    FILE                    *Handle);
184284583Sjkim
185233237Sjkimstatic int
186233237SjkimPrMatchDirective (
187233237Sjkim    char                    *Directive);
188233237Sjkim
189252279Sjkimstatic void
190252279SjkimPrPushDirective (
191252279Sjkim    int                     Directive,
192252279Sjkim    char                    *Argument);
193252279Sjkim
194252279Sjkimstatic ACPI_STATUS
195252279SjkimPrPopDirective (
196252279Sjkim    void);
197252279Sjkim
198252279Sjkimstatic void
199252279SjkimPrDbgPrint (
200252279Sjkim    char                    *Action,
201252279Sjkim    char                    *DirectiveName);
202252279Sjkim
203283092Sjkimstatic void
204283092SjkimPrDoIncludeBuffer (
205283092Sjkim    char                    *Pathname,
206283092Sjkim    char                    *BufferName);
207252279Sjkim
208283092Sjkimstatic void
209283092SjkimPrDoIncludeFile (
210283092Sjkim    char                    *Pathname);
211283092Sjkim
212283092Sjkim
213233237Sjkim/*
214233237Sjkim * Supported preprocessor directives
215283092Sjkim * Each entry is of the form "Name, ArgumentCount"
216233237Sjkim */
217233237Sjkimstatic const PR_DIRECTIVE_INFO      Gbl_DirectiveInfo[] =
218233237Sjkim{
219283092Sjkim    {"define",          1},
220283092Sjkim    {"elif",            0}, /* Converted to #else..#if internally */
221283092Sjkim    {"else",            0},
222283092Sjkim    {"endif",           0},
223283092Sjkim    {"error",           1},
224283092Sjkim    {"if",              1},
225283092Sjkim    {"ifdef",           1},
226283092Sjkim    {"ifndef",          1},
227283092Sjkim    {"include",         0}, /* Argument is not standard format, so just use 0 here */
228283092Sjkim    {"includebuffer",   0}, /* Argument is not standard format, so just use 0 here */
229283092Sjkim    {"line",            1},
230283092Sjkim    {"pragma",          1},
231283092Sjkim    {"undef",           1},
232283092Sjkim    {"warning",         1},
233283092Sjkim    {NULL,              0}
234233237Sjkim};
235233237Sjkim
236283092Sjkim/* This table must match ordering of above table exactly */
237283092Sjkim
238233237Sjkimenum Gbl_DirectiveIndexes
239233237Sjkim{
240233237Sjkim    PR_DIRECTIVE_DEFINE = 0,
241233237Sjkim    PR_DIRECTIVE_ELIF,
242233237Sjkim    PR_DIRECTIVE_ELSE,
243233237Sjkim    PR_DIRECTIVE_ENDIF,
244233237Sjkim    PR_DIRECTIVE_ERROR,
245233237Sjkim    PR_DIRECTIVE_IF,
246233237Sjkim    PR_DIRECTIVE_IFDEF,
247233237Sjkim    PR_DIRECTIVE_IFNDEF,
248233237Sjkim    PR_DIRECTIVE_INCLUDE,
249283092Sjkim    PR_DIRECTIVE_INCLUDEBUFFER,
250233237Sjkim    PR_DIRECTIVE_LINE,
251233237Sjkim    PR_DIRECTIVE_PRAGMA,
252233237Sjkim    PR_DIRECTIVE_UNDEF,
253285797Sjkim    PR_DIRECTIVE_WARNING
254233237Sjkim};
255233237Sjkim
256233237Sjkim#define ASL_DIRECTIVE_NOT_FOUND     -1
257233237Sjkim
258233237Sjkim
259233237Sjkim/*******************************************************************************
260233237Sjkim *
261233237Sjkim * FUNCTION:    PrInitializePreprocessor
262233237Sjkim *
263233237Sjkim * PARAMETERS:  None
264233237Sjkim *
265233237Sjkim * RETURN:      None
266233237Sjkim *
267233237Sjkim * DESCRIPTION: Startup initialization for the Preprocessor.
268233237Sjkim *
269233237Sjkim ******************************************************************************/
270233237Sjkim
271233237Sjkimvoid
272233237SjkimPrInitializePreprocessor (
273233237Sjkim    void)
274233237Sjkim{
275233237Sjkim    /* Init globals and the list of #defines */
276233237Sjkim
277233237Sjkim    PrInitializeGlobals ();
278233237Sjkim    Gbl_DefineList = NULL;
279233237Sjkim}
280233237Sjkim
281233237Sjkim
282233237Sjkim/*******************************************************************************
283233237Sjkim *
284233237Sjkim * FUNCTION:    PrInitializeGlobals
285233237Sjkim *
286233237Sjkim * PARAMETERS:  None
287233237Sjkim *
288233237Sjkim * RETURN:      None
289233237Sjkim *
290233237Sjkim * DESCRIPTION: Initialize globals for the Preprocessor. Used for startuup
291233237Sjkim *              initialization and re-initialization between compiles during
292233237Sjkim *              a multiple source file compile.
293233237Sjkim *
294233237Sjkim ******************************************************************************/
295233237Sjkim
296233237Sjkimvoid
297233237SjkimPrInitializeGlobals (
298233237Sjkim    void)
299233237Sjkim{
300233237Sjkim    /* Init globals */
301233237Sjkim
302233237Sjkim    Gbl_InputFileList = NULL;
303284583Sjkim    Gbl_CurrentLineNumber = 1;
304233237Sjkim    Gbl_PreprocessorLineNumber = 1;
305233237Sjkim    Gbl_PreprocessorError = FALSE;
306252279Sjkim
307252279Sjkim    /* These are used to track #if/#else blocks (possibly nested) */
308252279Sjkim
309252279Sjkim    Gbl_IfDepth = 0;
310252279Sjkim    Gbl_IgnoringThisCodeBlock = FALSE;
311252279Sjkim    Gbl_DirectiveStack = NULL;
312233237Sjkim}
313233237Sjkim
314233237Sjkim
315233237Sjkim/*******************************************************************************
316233237Sjkim *
317233237Sjkim * FUNCTION:    PrTerminatePreprocessor
318233237Sjkim *
319233237Sjkim * PARAMETERS:  None
320233237Sjkim *
321233237Sjkim * RETURN:      None
322233237Sjkim *
323233237Sjkim * DESCRIPTION: Termination of the preprocessor. Delete lists. Keep any
324233237Sjkim *              defines that were specified on the command line, in order to
325233237Sjkim *              support multiple compiles with a single compiler invocation.
326233237Sjkim *
327233237Sjkim ******************************************************************************/
328233237Sjkim
329233237Sjkimvoid
330233237SjkimPrTerminatePreprocessor (
331233237Sjkim    void)
332233237Sjkim{
333233237Sjkim    PR_DEFINE_INFO          *DefineInfo;
334233237Sjkim
335233237Sjkim
336233237Sjkim    /*
337233237Sjkim     * The persistent defines (created on the command line) are always at the
338233237Sjkim     * end of the list. We save them.
339233237Sjkim     */
340233237Sjkim    while ((Gbl_DefineList) && (!Gbl_DefineList->Persist))
341233237Sjkim    {
342233237Sjkim        DefineInfo = Gbl_DefineList;
343233237Sjkim        Gbl_DefineList = DefineInfo->Next;
344233237Sjkim
345233237Sjkim        ACPI_FREE (DefineInfo->Replacement);
346233237Sjkim        ACPI_FREE (DefineInfo->Identifier);
347233237Sjkim        ACPI_FREE (DefineInfo);
348233237Sjkim    }
349233237Sjkim}
350233237Sjkim
351233237Sjkim
352233237Sjkim/*******************************************************************************
353233237Sjkim *
354233237Sjkim * FUNCTION:    PrDoPreprocess
355233237Sjkim *
356233237Sjkim * PARAMETERS:  None
357233237Sjkim *
358252279Sjkim * RETURN:      None
359233237Sjkim *
360233237Sjkim * DESCRIPTION: Main entry point for the iASL Preprocessor. Input file must
361233237Sjkim *              be already open. Handles multiple input files via the
362233237Sjkim *              #include directive.
363233237Sjkim *
364233237Sjkim ******************************************************************************/
365233237Sjkim
366252279Sjkimvoid
367233237SjkimPrDoPreprocess (
368233237Sjkim    void)
369233237Sjkim{
370233237Sjkim    BOOLEAN                 MoreInputFiles;
371233237Sjkim
372233237Sjkim
373233237Sjkim    DbgPrint (ASL_DEBUG_OUTPUT, "Starting preprocessing phase\n\n");
374233237Sjkim
375233237Sjkim
376233237Sjkim    FlSeekFile (ASL_FILE_INPUT, 0);
377233237Sjkim    PrDumpPredefinedNames ();
378233237Sjkim
379233237Sjkim    /* Main preprocessor loop, handles include files */
380233237Sjkim
381233237Sjkim    do
382233237Sjkim    {
383233237Sjkim        PrPreprocessInputFile ();
384233237Sjkim        MoreInputFiles = PrPopInputFileStack ();
385233237Sjkim
386233237Sjkim    } while (MoreInputFiles);
387233237Sjkim
388284583Sjkim    /* Point compiler input to the new preprocessor output file (.pre) */
389233237Sjkim
390233237Sjkim    FlCloseFile (ASL_FILE_INPUT);
391233237Sjkim    Gbl_Files[ASL_FILE_INPUT].Handle = Gbl_Files[ASL_FILE_PREPROCESSOR].Handle;
392233237Sjkim    AslCompilerin = Gbl_Files[ASL_FILE_INPUT].Handle;
393233237Sjkim
394233237Sjkim    /* Reset globals to allow compiler to run */
395233237Sjkim
396233237Sjkim    FlSeekFile (ASL_FILE_INPUT, 0);
397284583Sjkim    if (!Gbl_PreprocessOnly)
398284583Sjkim    {
399284583Sjkim        Gbl_CurrentLineNumber = 0;
400284583Sjkim    }
401233237Sjkim
402233237Sjkim    DbgPrint (ASL_DEBUG_OUTPUT, "Preprocessing phase complete \n\n");
403233237Sjkim}
404233237Sjkim
405233237Sjkim
406233237Sjkim/*******************************************************************************
407233237Sjkim *
408233237Sjkim * FUNCTION:    PrPreprocessInputFile
409233237Sjkim *
410233237Sjkim * PARAMETERS:  None
411233237Sjkim *
412233237Sjkim * RETURN:      None
413233237Sjkim *
414233237Sjkim * DESCRIPTION: Preprocess one entire file, line-by-line.
415233237Sjkim *
416233237Sjkim * Input:  Raw user ASL from ASL_FILE_INPUT
417284583Sjkim * Output: Preprocessed file written to ASL_FILE_PREPROCESSOR and
418284583Sjkim *         (optionally) ASL_FILE_PREPROCESSOR_USER
419233237Sjkim *
420233237Sjkim ******************************************************************************/
421233237Sjkim
422233237Sjkimstatic void
423233237SjkimPrPreprocessInputFile (
424233237Sjkim    void)
425233237Sjkim{
426284583Sjkim    UINT32                  Status;
427233237Sjkim    char                    *Token;
428233237Sjkim    char                    *ReplaceString;
429233237Sjkim    PR_DEFINE_INFO          *DefineInfo;
430233237Sjkim    ACPI_SIZE               TokenOffset;
431233237Sjkim    char                    *Next;
432233237Sjkim    int                     OffsetAdjust;
433233237Sjkim
434233237Sjkim
435284583Sjkim    PrGetNextLineInit ();
436284583Sjkim
437285797Sjkim    /* Scan source line-by-line and process directives. Then write the .i file */
438233237Sjkim
439284583Sjkim    while ((Status = PrGetNextLine (Gbl_Files[ASL_FILE_INPUT].Handle)) != ASL_EOF)
440233237Sjkim    {
441284583Sjkim        Gbl_CurrentLineNumber++;
442284583Sjkim        Gbl_LogicalLineNumber++;
443284583Sjkim
444298714Sjkim        if (Status == ASL_IGNORE_LINE)
445284583Sjkim        {
446284583Sjkim            goto WriteEntireLine;
447284583Sjkim        }
448284583Sjkim
449233237Sjkim        /* Need a copy of the input line for strok() */
450233237Sjkim
451233237Sjkim        strcpy (Gbl_MainTokenBuffer, Gbl_CurrentLineBuffer);
452233237Sjkim        Token = PrGetNextToken (Gbl_MainTokenBuffer, PR_TOKEN_SEPARATORS, &Next);
453233237Sjkim        OffsetAdjust = 0;
454233237Sjkim
455233237Sjkim        /* All preprocessor directives must begin with '#' */
456233237Sjkim
457233237Sjkim        if (Token && (*Token == '#'))
458233237Sjkim        {
459233237Sjkim            if (strlen (Token) == 1)
460233237Sjkim            {
461233237Sjkim                Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, &Next);
462233237Sjkim            }
463233237Sjkim            else
464233237Sjkim            {
465233237Sjkim                Token++;    /* Skip leading # */
466233237Sjkim            }
467233237Sjkim
468233237Sjkim            /* Execute the directive, do not write line to output file */
469233237Sjkim
470252279Sjkim            PrDoDirective (Token, &Next);
471233237Sjkim            continue;
472233237Sjkim        }
473233237Sjkim
474233237Sjkim        /*
475233237Sjkim         * If we are currently within the part of an IF/ELSE block that is
476233237Sjkim         * FALSE, ignore the line and do not write it to the output file.
477233237Sjkim         * This continues until an #else or #endif is encountered.
478233237Sjkim         */
479252279Sjkim        if (Gbl_IgnoringThisCodeBlock)
480233237Sjkim        {
481233237Sjkim            continue;
482233237Sjkim        }
483233237Sjkim
484233237Sjkim        /* Match and replace all #defined names within this source line */
485233237Sjkim
486233237Sjkim        while (Token)
487233237Sjkim        {
488233237Sjkim            DefineInfo = PrMatchDefine (Token);
489233237Sjkim            if (DefineInfo)
490233237Sjkim            {
491233237Sjkim                if (DefineInfo->Body)
492233237Sjkim                {
493233237Sjkim                    /* This is a macro */
494233237Sjkim
495233237Sjkim                    DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
496233237Sjkim                        "Matched Macro: %s->%s\n",
497233237Sjkim                        Gbl_CurrentLineNumber, DefineInfo->Identifier,
498233237Sjkim                        DefineInfo->Replacement);
499233237Sjkim
500233237Sjkim                    PrDoMacroInvocation (Gbl_MainTokenBuffer, Token,
501233237Sjkim                        DefineInfo, &Next);
502233237Sjkim                }
503233237Sjkim                else
504233237Sjkim                {
505233237Sjkim                    ReplaceString = DefineInfo->Replacement;
506233237Sjkim
507233237Sjkim                    /* Replace the name in the original line buffer */
508233237Sjkim
509233237Sjkim                    TokenOffset = Token - Gbl_MainTokenBuffer + OffsetAdjust;
510233237Sjkim                    PrReplaceData (
511233237Sjkim                        &Gbl_CurrentLineBuffer[TokenOffset], strlen (Token),
512233237Sjkim                        ReplaceString, strlen (ReplaceString));
513233237Sjkim
514233237Sjkim                    /* Adjust for length difference between old and new name length */
515233237Sjkim
516233237Sjkim                    OffsetAdjust += strlen (ReplaceString) - strlen (Token);
517233237Sjkim
518233237Sjkim                    DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
519233237Sjkim                        "Matched #define: %s->%s\n",
520233237Sjkim                        Gbl_CurrentLineNumber, Token,
521233237Sjkim                        *ReplaceString ? ReplaceString : "(NULL STRING)");
522233237Sjkim                }
523233237Sjkim            }
524233237Sjkim
525233237Sjkim            Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, &Next);
526233237Sjkim        }
527233237Sjkim
528234623Sjkim        Gbl_PreprocessorLineNumber++;
529234623Sjkim
530284583Sjkim
531284583SjkimWriteEntireLine:
532234623Sjkim        /*
533234623Sjkim         * Now we can write the possibly modified source line to the
534284583Sjkim         * preprocessor file(s).
535234623Sjkim         */
536233237Sjkim        FlWriteFile (ASL_FILE_PREPROCESSOR, Gbl_CurrentLineBuffer,
537233237Sjkim            strlen (Gbl_CurrentLineBuffer));
538233237Sjkim    }
539233237Sjkim}
540233237Sjkim
541233237Sjkim
542233237Sjkim/*******************************************************************************
543233237Sjkim *
544233237Sjkim * FUNCTION:    PrDoDirective
545233237Sjkim *
546233237Sjkim * PARAMETERS:  Directive               - Pointer to directive name token
547233237Sjkim *              Next                    - "Next" buffer from GetNextToken
548233237Sjkim *
549252279Sjkim * RETURN:      None.
550233237Sjkim *
551233237Sjkim * DESCRIPTION: Main processing for all preprocessor directives
552233237Sjkim *
553233237Sjkim ******************************************************************************/
554233237Sjkim
555233237Sjkimstatic void
556233237SjkimPrDoDirective (
557233237Sjkim    char                    *DirectiveToken,
558252279Sjkim    char                    **Next)
559233237Sjkim{
560233237Sjkim    char                    *Token = Gbl_MainTokenBuffer;
561283092Sjkim    char                    *Token2 = NULL;
562233237Sjkim    char                    *End;
563233237Sjkim    UINT64                  Value;
564233237Sjkim    ACPI_SIZE               TokenOffset;
565233237Sjkim    int                     Directive;
566233237Sjkim    ACPI_STATUS             Status;
567233237Sjkim
568233237Sjkim
569233237Sjkim    if (!DirectiveToken)
570233237Sjkim    {
571233237Sjkim        goto SyntaxError;
572233237Sjkim    }
573233237Sjkim
574233237Sjkim    Directive = PrMatchDirective (DirectiveToken);
575233237Sjkim    if (Directive == ASL_DIRECTIVE_NOT_FOUND)
576233237Sjkim    {
577233237Sjkim        PrError (ASL_ERROR, ASL_MSG_UNKNOWN_DIRECTIVE,
578233237Sjkim            THIS_TOKEN_OFFSET (DirectiveToken));
579233237Sjkim
580283092Sjkim        DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
581233237Sjkim            "#%s: Unknown directive\n",
582233237Sjkim            Gbl_CurrentLineNumber, DirectiveToken);
583233237Sjkim        return;
584233237Sjkim    }
585233237Sjkim
586252279Sjkim    /*
587285797Sjkim     * Emit a line directive into the preprocessor file (.pre) after
588285797Sjkim     * every matched directive. This is passed through to the compiler
589285797Sjkim     * so that error/warning messages are kept in sync with the
590285797Sjkim     * original source file.
591285797Sjkim     */
592285797Sjkim    FlPrintFile (ASL_FILE_PREPROCESSOR, "#line %u \"%s\" // #%s\n",
593285797Sjkim        Gbl_CurrentLineNumber, Gbl_Files[ASL_FILE_INPUT].Filename,
594285797Sjkim        Gbl_DirectiveInfo[Directive].Name);
595285797Sjkim
596285797Sjkim    /*
597252279Sjkim     * If we are currently ignoring this block and we encounter a #else or
598252279Sjkim     * #elif, we must ignore their blocks also if the parent block is also
599252279Sjkim     * being ignored.
600252279Sjkim     */
601252279Sjkim    if (Gbl_IgnoringThisCodeBlock)
602252279Sjkim    {
603252279Sjkim        switch (Directive)
604252279Sjkim        {
605252279Sjkim        case PR_DIRECTIVE_ELSE:
606252279Sjkim        case PR_DIRECTIVE_ELIF:
607233237Sjkim
608298714Sjkim            if (Gbl_DirectiveStack &&
609298714Sjkim                Gbl_DirectiveStack->IgnoringThisCodeBlock)
610252279Sjkim            {
611252279Sjkim                PrDbgPrint ("Ignoring", Gbl_DirectiveInfo[Directive].Name);
612252279Sjkim                return;
613252279Sjkim            }
614252279Sjkim            break;
615252279Sjkim
616252279Sjkim        default:
617252279Sjkim            break;
618252279Sjkim        }
619233237Sjkim    }
620233237Sjkim
621233237Sjkim    /*
622233237Sjkim     * Need to always check for #else, #elif, #endif regardless of
623233237Sjkim     * whether we are ignoring the current code block, since these
624233237Sjkim     * are conditional code block terminators.
625233237Sjkim     */
626233237Sjkim    switch (Directive)
627233237Sjkim    {
628252279Sjkim    case PR_DIRECTIVE_ELSE:
629252279Sjkim
630252279Sjkim        Gbl_IgnoringThisCodeBlock = !(Gbl_IgnoringThisCodeBlock);
631252279Sjkim        PrDbgPrint ("Executing", "else block");
632252279Sjkim        return;
633252279Sjkim
634233237Sjkim    case PR_DIRECTIVE_ELIF:
635250838Sjkim
636252279Sjkim        Gbl_IgnoringThisCodeBlock = !(Gbl_IgnoringThisCodeBlock);
637252279Sjkim        Directive = PR_DIRECTIVE_IF;
638252279Sjkim
639252279Sjkim        if (Gbl_IgnoringThisCodeBlock == TRUE)
640233237Sjkim        {
641233237Sjkim            /* Not executing the ELSE part -- all done here */
642252279Sjkim            PrDbgPrint ("Ignoring", "elif block");
643233237Sjkim            return;
644233237Sjkim        }
645233237Sjkim
646252279Sjkim        /*
647252279Sjkim         * After this, we will execute the IF part further below.
648252279Sjkim         * First, however, pop off the original #if directive.
649252279Sjkim         */
650252279Sjkim        if (ACPI_FAILURE (PrPopDirective ()))
651252279Sjkim        {
652252279Sjkim            PrError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL,
653252279Sjkim                THIS_TOKEN_OFFSET (DirectiveToken));
654252279Sjkim        }
655233237Sjkim
656252279Sjkim        PrDbgPrint ("Executing", "elif block");
657233237Sjkim        break;
658233237Sjkim
659252279Sjkim    case PR_DIRECTIVE_ENDIF:
660250838Sjkim
661252279Sjkim        PrDbgPrint ("Executing", "endif");
662233237Sjkim
663252279Sjkim        /* Pop the owning #if/#ifdef/#ifndef */
664250838Sjkim
665252279Sjkim        if (ACPI_FAILURE (PrPopDirective ()))
666233237Sjkim        {
667233237Sjkim            PrError (ASL_ERROR, ASL_MSG_ENDIF_MISMATCH,
668233237Sjkim                THIS_TOKEN_OFFSET (DirectiveToken));
669233237Sjkim        }
670233237Sjkim        return;
671233237Sjkim
672233237Sjkim    default:
673233237Sjkim        break;
674233237Sjkim    }
675233237Sjkim
676252279Sjkim    /* Most directives have at least one argument */
677252279Sjkim
678283092Sjkim    if (Gbl_DirectiveInfo[Directive].ArgCount >= 1)
679252279Sjkim    {
680252279Sjkim        Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next);
681252279Sjkim        if (!Token)
682252279Sjkim        {
683252279Sjkim            goto SyntaxError;
684252279Sjkim        }
685252279Sjkim    }
686252279Sjkim
687283092Sjkim    if (Gbl_DirectiveInfo[Directive].ArgCount >= 2)
688283092Sjkim    {
689283092Sjkim        Token2 = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next);
690283092Sjkim        if (!Token2)
691283092Sjkim        {
692283092Sjkim            goto SyntaxError;
693283092Sjkim        }
694283092Sjkim    }
695283092Sjkim
696233237Sjkim    /*
697233237Sjkim     * At this point, if we are ignoring the current code block,
698233237Sjkim     * do not process any more directives (i.e., ignore them also.)
699252279Sjkim     * For "if" style directives, open/push a new block anyway. We
700252279Sjkim     * must do this to keep track of #endif directives
701233237Sjkim     */
702252279Sjkim    if (Gbl_IgnoringThisCodeBlock)
703233237Sjkim    {
704252279Sjkim        switch (Directive)
705252279Sjkim        {
706252279Sjkim        case PR_DIRECTIVE_IF:
707252279Sjkim        case PR_DIRECTIVE_IFDEF:
708252279Sjkim        case PR_DIRECTIVE_IFNDEF:
709252279Sjkim
710252279Sjkim            PrPushDirective (Directive, Token);
711252279Sjkim            PrDbgPrint ("Ignoring", Gbl_DirectiveInfo[Directive].Name);
712252279Sjkim            break;
713252279Sjkim
714252279Sjkim        default:
715252279Sjkim            break;
716252279Sjkim        }
717252279Sjkim
718233237Sjkim        return;
719233237Sjkim    }
720233237Sjkim
721252279Sjkim    /*
722252279Sjkim     * Execute the directive
723252279Sjkim     */
724252279Sjkim    PrDbgPrint ("Begin execution", Gbl_DirectiveInfo[Directive].Name);
725233237Sjkim
726252279Sjkim    switch (Directive)
727252279Sjkim    {
728252279Sjkim    case PR_DIRECTIVE_IF:
729233237Sjkim
730252279Sjkim        TokenOffset = Token - Gbl_MainTokenBuffer;
731252279Sjkim
732252279Sjkim        /* Need to expand #define macros in the expression string first */
733252279Sjkim
734252279Sjkim        Status = PrResolveIntegerExpression (
735252279Sjkim            &Gbl_CurrentLineBuffer[TokenOffset-1], &Value);
736252279Sjkim        if (ACPI_FAILURE (Status))
737233237Sjkim        {
738252279Sjkim            return;
739233237Sjkim        }
740233237Sjkim
741252279Sjkim        PrPushDirective (Directive, Token);
742252279Sjkim        if (!Value)
743252279Sjkim        {
744252279Sjkim            Gbl_IgnoringThisCodeBlock = TRUE;
745252279Sjkim        }
746252279Sjkim
747283092Sjkim        DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
748252279Sjkim            "Resolved #if: %8.8X%8.8X %s\n",
749252279Sjkim            Gbl_CurrentLineNumber, ACPI_FORMAT_UINT64 (Value),
750252279Sjkim            Gbl_IgnoringThisCodeBlock ? "<Skipping Block>" : "<Executing Block>");
751252279Sjkim        break;
752252279Sjkim
753252279Sjkim    case PR_DIRECTIVE_IFDEF:
754252279Sjkim
755252279Sjkim        PrPushDirective (Directive, Token);
756252279Sjkim        if (!PrMatchDefine (Token))
757252279Sjkim        {
758252279Sjkim            Gbl_IgnoringThisCodeBlock = TRUE;
759252279Sjkim        }
760252279Sjkim
761252279Sjkim        PrDbgPrint ("Evaluated", "ifdef");
762252279Sjkim        break;
763252279Sjkim
764252279Sjkim    case PR_DIRECTIVE_IFNDEF:
765252279Sjkim
766252279Sjkim        PrPushDirective (Directive, Token);
767252279Sjkim        if (PrMatchDefine (Token))
768252279Sjkim        {
769252279Sjkim            Gbl_IgnoringThisCodeBlock = TRUE;
770252279Sjkim        }
771252279Sjkim
772252279Sjkim        PrDbgPrint ("Evaluated", "ifndef");
773252279Sjkim        break;
774252279Sjkim
775233237Sjkim    case PR_DIRECTIVE_DEFINE:
776233237Sjkim        /*
777233237Sjkim         * By definition, if first char after the name is a paren,
778233237Sjkim         * this is a function macro.
779233237Sjkim         */
780233237Sjkim        TokenOffset = Token - Gbl_MainTokenBuffer + strlen (Token);
781233237Sjkim        if (*(&Gbl_CurrentLineBuffer[TokenOffset]) == '(')
782233237Sjkim        {
783233237Sjkim#ifndef MACROS_SUPPORTED
784298714Sjkim            AcpiOsPrintf (
785298714Sjkim                "%s ERROR - line %u: #define macros are not supported yet\n",
786284583Sjkim                Gbl_CurrentLineBuffer, Gbl_LogicalLineNumber);
787234623Sjkim            exit(1);
788233237Sjkim#else
789233237Sjkim            PrAddMacro (Token, Next);
790233237Sjkim#endif
791233237Sjkim        }
792233237Sjkim        else
793233237Sjkim        {
794233237Sjkim            /* Use the remainder of the line for the #define */
795233237Sjkim
796233237Sjkim            Token2 = *Next;
797233237Sjkim            if (Token2)
798233237Sjkim            {
799233237Sjkim                while ((*Token2 == ' ') || (*Token2 == '\t'))
800233237Sjkim                {
801233237Sjkim                    Token2++;
802233237Sjkim                }
803298714Sjkim
804233237Sjkim                End = Token2;
805233237Sjkim                while (*End != '\n')
806233237Sjkim                {
807233237Sjkim                    End++;
808233237Sjkim                }
809298714Sjkim
810233237Sjkim                *End = 0;
811233237Sjkim            }
812233237Sjkim            else
813233237Sjkim            {
814233237Sjkim                Token2 = "";
815233237Sjkim            }
816233237Sjkim#if 0
817233237Sjkim            Token2 = PrGetNextToken (NULL, "\n", /*PR_TOKEN_SEPARATORS,*/ Next);
818233237Sjkim            if (!Token2)
819233237Sjkim            {
820233237Sjkim                Token2 = "";
821233237Sjkim            }
822233237Sjkim#endif
823283092Sjkim            DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
824233237Sjkim                "New #define: %s->%s\n",
825284583Sjkim                Gbl_LogicalLineNumber, Token, Token2);
826233237Sjkim
827233237Sjkim            PrAddDefine (Token, Token2, FALSE);
828233237Sjkim        }
829233237Sjkim        break;
830233237Sjkim
831233237Sjkim    case PR_DIRECTIVE_ERROR:
832250838Sjkim
833233237Sjkim        /* Note: No macro expansion */
834233237Sjkim
835233237Sjkim        PrError (ASL_ERROR, ASL_MSG_ERROR_DIRECTIVE,
836233237Sjkim            THIS_TOKEN_OFFSET (Token));
837233237Sjkim
838252279Sjkim        Gbl_SourceLine = 0;
839252279Sjkim        Gbl_NextError = Gbl_ErrorLog;
840252279Sjkim        CmCleanupAndExit ();
841252279Sjkim        exit(1);
842250838Sjkim
843233237Sjkim    case PR_DIRECTIVE_INCLUDE:
844250838Sjkim
845233237Sjkim        Token = PrGetNextToken (NULL, " \"<>", Next);
846233237Sjkim        if (!Token)
847233237Sjkim        {
848233237Sjkim            goto SyntaxError;
849233237Sjkim        }
850233237Sjkim
851283092Sjkim        DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
852235945Sjkim            "Start #include file \"%s\"\n", Gbl_CurrentLineNumber,
853233237Sjkim            Token, Gbl_CurrentLineNumber);
854233237Sjkim
855283092Sjkim        PrDoIncludeFile (Token);
856233237Sjkim        break;
857233237Sjkim
858283092Sjkim    case PR_DIRECTIVE_INCLUDEBUFFER:
859283092Sjkim
860283092Sjkim        Token = PrGetNextToken (NULL, " \"<>", Next);
861283092Sjkim        if (!Token)
862283092Sjkim        {
863283092Sjkim            goto SyntaxError;
864283092Sjkim        }
865283092Sjkim
866283092Sjkim        Token2 = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next);
867283092Sjkim        if (!Token2)
868283092Sjkim        {
869283092Sjkim            goto SyntaxError;
870283092Sjkim        }
871283092Sjkim
872283092Sjkim        DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
873283092Sjkim            "Start #includebuffer input from file \"%s\", buffer name %s\n",
874283092Sjkim            Gbl_CurrentLineNumber, Token, Token2);
875283092Sjkim
876283092Sjkim        PrDoIncludeBuffer (Token, Token2);
877283092Sjkim        break;
878283092Sjkim
879234623Sjkim    case PR_DIRECTIVE_LINE:
880250838Sjkim
881234623Sjkim        TokenOffset = Token - Gbl_MainTokenBuffer;
882234623Sjkim
883234623Sjkim        Status = PrResolveIntegerExpression (
884234623Sjkim            &Gbl_CurrentLineBuffer[TokenOffset-1], &Value);
885234623Sjkim        if (ACPI_FAILURE (Status))
886234623Sjkim        {
887234623Sjkim            return;
888234623Sjkim        }
889234623Sjkim
890283092Sjkim        DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
891234623Sjkim            "User #line invocation %s\n", Gbl_CurrentLineNumber,
892234623Sjkim            Token);
893234623Sjkim
894234623Sjkim        Gbl_CurrentLineNumber = (UINT32) Value;
895234623Sjkim
896234623Sjkim        /* Emit #line into the preprocessor file */
897234623Sjkim
898234623Sjkim        FlPrintFile (ASL_FILE_PREPROCESSOR, "#line %u \"%s\"\n",
899234623Sjkim            Gbl_CurrentLineNumber, Gbl_Files[ASL_FILE_INPUT].Filename);
900234623Sjkim        break;
901234623Sjkim
902233237Sjkim    case PR_DIRECTIVE_PRAGMA:
903233237Sjkim
904250838Sjkim        if (!strcmp (Token, "disable"))
905233237Sjkim        {
906250838Sjkim            Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next);
907250838Sjkim            if (!Token)
908250838Sjkim            {
909250838Sjkim                goto SyntaxError;
910250838Sjkim            }
911250838Sjkim
912250838Sjkim            TokenOffset = Token - Gbl_MainTokenBuffer;
913250838Sjkim            AslDisableException (&Gbl_CurrentLineBuffer[TokenOffset]);
914250838Sjkim        }
915250838Sjkim        else if (!strcmp (Token, "message"))
916250838Sjkim        {
917250838Sjkim            Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next);
918250838Sjkim            if (!Token)
919250838Sjkim            {
920250838Sjkim                goto SyntaxError;
921250838Sjkim            }
922250838Sjkim
923250838Sjkim            TokenOffset = Token - Gbl_MainTokenBuffer;
924250838Sjkim            AcpiOsPrintf ("%s\n", &Gbl_CurrentLineBuffer[TokenOffset]);
925250838Sjkim        }
926250838Sjkim        else
927250838Sjkim        {
928233237Sjkim            PrError (ASL_ERROR, ASL_MSG_UNKNOWN_PRAGMA,
929233237Sjkim                THIS_TOKEN_OFFSET (Token));
930233237Sjkim            return;
931233237Sjkim        }
932233237Sjkim
933233237Sjkim        break;
934233237Sjkim
935233237Sjkim    case PR_DIRECTIVE_UNDEF:
936250838Sjkim
937283092Sjkim        DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
938233237Sjkim            "#undef: %s\n", Gbl_CurrentLineNumber, Token);
939233237Sjkim
940233237Sjkim        PrRemoveDefine (Token);
941233237Sjkim        break;
942233237Sjkim
943233237Sjkim    case PR_DIRECTIVE_WARNING:
944250838Sjkim
945252279Sjkim        PrError (ASL_WARNING, ASL_MSG_WARNING_DIRECTIVE,
946233237Sjkim            THIS_TOKEN_OFFSET (Token));
947285797Sjkim
948285797Sjkim        Gbl_SourceLine = 0;
949285797Sjkim        Gbl_NextError = Gbl_ErrorLog;
950233237Sjkim        break;
951233237Sjkim
952233237Sjkim    default:
953250838Sjkim
954233237Sjkim        /* Should never get here */
955283092Sjkim        DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
956233237Sjkim            "Unrecognized directive: %u\n",
957233237Sjkim            Gbl_CurrentLineNumber, Directive);
958233237Sjkim        break;
959233237Sjkim    }
960233237Sjkim
961233237Sjkim    return;
962233237Sjkim
963233237SjkimSyntaxError:
964233237Sjkim
965233237Sjkim    PrError (ASL_ERROR, ASL_MSG_DIRECTIVE_SYNTAX,
966233237Sjkim        THIS_TOKEN_OFFSET (DirectiveToken));
967233237Sjkim    return;
968233237Sjkim}
969233237Sjkim
970233237Sjkim
971233237Sjkim/*******************************************************************************
972233237Sjkim *
973284583Sjkim * FUNCTION:    PrGetNextLine, PrGetNextLineInit
974284583Sjkim *
975284583Sjkim * PARAMETERS:  Handle              - Open file handle for the source file
976284583Sjkim *
977284583Sjkim * RETURN:      Status of the GetLine operation:
978284583Sjkim *              AE_OK               - Normal line, OK status
979298714Sjkim *              ASL_IGNORE_LINE     - Line is blank or part of a multi-line
980298714Sjkim *                                      comment
981284583Sjkim *              ASL_EOF             - End-of-file reached
982284583Sjkim *
983284583Sjkim * DESCRIPTION: Get the next text line from the input file. Does not strip
984284583Sjkim *              comments.
985284583Sjkim *
986284583Sjkim ******************************************************************************/
987284583Sjkim
988284583Sjkim#define PR_NORMAL_TEXT          0
989285797Sjkim#define PR_MULTI_LINE_COMMENT   1
990285797Sjkim#define PR_SINGLE_LINE_COMMENT  2
991285797Sjkim#define PR_QUOTED_STRING        3
992284583Sjkim
993284583Sjkimstatic UINT8                    AcpiGbl_LineScanState = PR_NORMAL_TEXT;
994284583Sjkim
995284583Sjkimstatic void
996284583SjkimPrGetNextLineInit (
997284583Sjkim    void)
998284583Sjkim{
999284583Sjkim    AcpiGbl_LineScanState = 0;
1000284583Sjkim}
1001284583Sjkim
1002284583Sjkimstatic UINT32
1003284583SjkimPrGetNextLine (
1004284583Sjkim    FILE                    *Handle)
1005284583Sjkim{
1006284583Sjkim    UINT32                  i;
1007284583Sjkim    int                     c = 0;
1008284583Sjkim    int                     PreviousChar;
1009284583Sjkim
1010284583Sjkim
1011284583Sjkim    /* Always clear the global line buffer */
1012284583Sjkim
1013284583Sjkim    memset (Gbl_CurrentLineBuffer, 0, Gbl_LineBufferSize);
1014284583Sjkim    for (i = 0; ;)
1015284583Sjkim    {
1016284583Sjkim        /*
1017284583Sjkim         * If line is too long, expand the line buffers. Also increases
1018284583Sjkim         * Gbl_LineBufferSize.
1019284583Sjkim         */
1020284583Sjkim        if (i >= Gbl_LineBufferSize)
1021284583Sjkim        {
1022284583Sjkim            UtExpandLineBuffers ();
1023284583Sjkim        }
1024284583Sjkim
1025284583Sjkim        PreviousChar = c;
1026284583Sjkim        c = getc (Handle);
1027284583Sjkim        if (c == EOF)
1028284583Sjkim        {
1029298714Sjkim            /*
1030298714Sjkim             * On EOF: If there is anything in the line buffer, terminate
1031298714Sjkim             * it with a newline, and catch the EOF on the next call
1032298714Sjkim             * to this function.
1033298714Sjkim             */
1034298714Sjkim            if (i > 0)
1035298714Sjkim            {
1036298714Sjkim                Gbl_CurrentLineBuffer[i] = '\n';
1037298714Sjkim                return (AE_OK);
1038298714Sjkim            }
1039298714Sjkim
1040284583Sjkim            return (ASL_EOF);
1041284583Sjkim        }
1042284583Sjkim
1043285797Sjkim        /* Update state machine as necessary */
1044284583Sjkim
1045285797Sjkim        switch (AcpiGbl_LineScanState)
1046284583Sjkim        {
1047285797Sjkim        case PR_NORMAL_TEXT:
1048284583Sjkim
1049285797Sjkim            /* Check for multi-line comment start */
1050284583Sjkim
1051285797Sjkim            if ((PreviousChar == '/') && (c == '*'))
1052285797Sjkim            {
1053285797Sjkim                AcpiGbl_LineScanState = PR_MULTI_LINE_COMMENT;
1054285797Sjkim            }
1055285797Sjkim
1056285797Sjkim            /* Check for single-line comment start */
1057285797Sjkim
1058285797Sjkim            else if ((PreviousChar == '/') && (c == '/'))
1059285797Sjkim            {
1060285797Sjkim                AcpiGbl_LineScanState = PR_SINGLE_LINE_COMMENT;
1061285797Sjkim            }
1062285797Sjkim
1063285797Sjkim            /* Check for quoted string start */
1064285797Sjkim
1065285797Sjkim            else if (PreviousChar == '"')
1066285797Sjkim            {
1067285797Sjkim                AcpiGbl_LineScanState = PR_QUOTED_STRING;
1068285797Sjkim            }
1069285797Sjkim            break;
1070285797Sjkim
1071285797Sjkim        case PR_QUOTED_STRING:
1072285797Sjkim
1073285797Sjkim            if (PreviousChar == '"')
1074285797Sjkim            {
1075285797Sjkim                AcpiGbl_LineScanState = PR_NORMAL_TEXT;
1076285797Sjkim            }
1077285797Sjkim            break;
1078285797Sjkim
1079285797Sjkim        case PR_MULTI_LINE_COMMENT:
1080285797Sjkim
1081285797Sjkim            /* Check for multi-line comment end */
1082285797Sjkim
1083285797Sjkim            if ((PreviousChar == '*') && (c == '/'))
1084285797Sjkim            {
1085285797Sjkim                AcpiGbl_LineScanState = PR_NORMAL_TEXT;
1086285797Sjkim            }
1087285797Sjkim            break;
1088285797Sjkim
1089285797Sjkim        case PR_SINGLE_LINE_COMMENT: /* Just ignore text until EOL */
1090285797Sjkim        default:
1091285797Sjkim            break;
1092284583Sjkim        }
1093284583Sjkim
1094284583Sjkim        /* Always copy the character into line buffer */
1095284583Sjkim
1096284583Sjkim        Gbl_CurrentLineBuffer[i] = (char) c;
1097284583Sjkim        i++;
1098284583Sjkim
1099284583Sjkim        /* Always exit on end-of-line */
1100284583Sjkim
1101284583Sjkim        if (c == '\n')
1102284583Sjkim        {
1103284583Sjkim            /* Handle multi-line comments */
1104284583Sjkim
1105285797Sjkim            if (AcpiGbl_LineScanState == PR_MULTI_LINE_COMMENT)
1106284583Sjkim            {
1107298714Sjkim                return (ASL_IGNORE_LINE);
1108284583Sjkim            }
1109285797Sjkim
1110285797Sjkim            /* End of single-line comment */
1111285797Sjkim
1112285797Sjkim            if (AcpiGbl_LineScanState == PR_SINGLE_LINE_COMMENT)
1113285797Sjkim            {
1114285797Sjkim                AcpiGbl_LineScanState = PR_NORMAL_TEXT;
1115285797Sjkim                return (AE_OK);
1116285797Sjkim            }
1117285797Sjkim
1118285797Sjkim            /* Blank line */
1119285797Sjkim
1120284583Sjkim            if (i == 1)
1121284583Sjkim            {
1122298714Sjkim                return (ASL_IGNORE_LINE);
1123284583Sjkim            }
1124298714Sjkim
1125284583Sjkim            return (AE_OK);
1126284583Sjkim        }
1127284583Sjkim    }
1128284583Sjkim}
1129284583Sjkim
1130284583Sjkim
1131284583Sjkim/*******************************************************************************
1132284583Sjkim *
1133233237Sjkim * FUNCTION:    PrMatchDirective
1134233237Sjkim *
1135233237Sjkim * PARAMETERS:  Directive           - Pointer to directive name token
1136233237Sjkim *
1137233237Sjkim * RETURN:      Index into command array, -1 if not found
1138233237Sjkim *
1139233237Sjkim * DESCRIPTION: Lookup the incoming directive in the known directives table.
1140233237Sjkim *
1141233237Sjkim ******************************************************************************/
1142233237Sjkim
1143233237Sjkimstatic int
1144233237SjkimPrMatchDirective (
1145233237Sjkim    char                    *Directive)
1146233237Sjkim{
1147233237Sjkim    int                     i;
1148233237Sjkim
1149233237Sjkim
1150233237Sjkim    if (!Directive || Directive[0] == 0)
1151233237Sjkim    {
1152233237Sjkim        return (ASL_DIRECTIVE_NOT_FOUND);
1153233237Sjkim    }
1154233237Sjkim
1155233237Sjkim    for (i = 0; Gbl_DirectiveInfo[i].Name; i++)
1156233237Sjkim    {
1157233237Sjkim        if (!strcmp (Gbl_DirectiveInfo[i].Name, Directive))
1158233237Sjkim        {
1159233237Sjkim            return (i);
1160233237Sjkim        }
1161233237Sjkim    }
1162233237Sjkim
1163233237Sjkim    return (ASL_DIRECTIVE_NOT_FOUND);    /* Command not recognized */
1164233237Sjkim}
1165252279Sjkim
1166252279Sjkim
1167252279Sjkim/*******************************************************************************
1168252279Sjkim *
1169252279Sjkim * FUNCTION:    PrPushDirective
1170252279Sjkim *
1171252279Sjkim * PARAMETERS:  Directive           - Encoded directive ID
1172252279Sjkim *              Argument            - String containing argument to the
1173252279Sjkim *                                    directive
1174252279Sjkim *
1175252279Sjkim * RETURN:      None
1176252279Sjkim *
1177252279Sjkim * DESCRIPTION: Push an item onto the directive stack. Used for processing
1178252279Sjkim *              nested #if/#else type conditional compilation directives.
1179252279Sjkim *              Specifically: Used on detection of #if/#ifdef/#ifndef to open
1180252279Sjkim *              a block.
1181252279Sjkim *
1182252279Sjkim ******************************************************************************/
1183252279Sjkim
1184252279Sjkimstatic void
1185252279SjkimPrPushDirective (
1186252279Sjkim    int                     Directive,
1187252279Sjkim    char                    *Argument)
1188252279Sjkim{
1189252279Sjkim    DIRECTIVE_INFO          *Info;
1190252279Sjkim
1191252279Sjkim
1192252279Sjkim    /* Allocate and populate a stack info item */
1193252279Sjkim
1194252279Sjkim    Info = ACPI_ALLOCATE (sizeof (DIRECTIVE_INFO));
1195252279Sjkim
1196252279Sjkim    Info->Next = Gbl_DirectiveStack;
1197252279Sjkim    Info->Directive = Directive;
1198252279Sjkim    Info->IgnoringThisCodeBlock = Gbl_IgnoringThisCodeBlock;
1199327557Sjkim    AcpiUtSafeStrncpy (Info->Argument, Argument, MAX_ARGUMENT_LENGTH);
1200252279Sjkim
1201252279Sjkim    DbgPrint (ASL_DEBUG_OUTPUT,
1202252279Sjkim        "Pr(%.4u) - [%u %s] %*s Pushed [#%s %s]: IgnoreFlag = %s\n",
1203252279Sjkim        Gbl_CurrentLineNumber, Gbl_IfDepth,
1204252279Sjkim        Gbl_IgnoringThisCodeBlock ? "I" : "E",
1205252279Sjkim        Gbl_IfDepth * 4, " ",
1206252279Sjkim        Gbl_DirectiveInfo[Directive].Name,
1207252279Sjkim        Argument, Gbl_IgnoringThisCodeBlock ? "TRUE" : "FALSE");
1208252279Sjkim
1209252279Sjkim    /* Push new item */
1210252279Sjkim
1211252279Sjkim    Gbl_DirectiveStack = Info;
1212252279Sjkim    Gbl_IfDepth++;
1213252279Sjkim}
1214252279Sjkim
1215252279Sjkim
1216252279Sjkim/*******************************************************************************
1217252279Sjkim *
1218252279Sjkim * FUNCTION:    PrPopDirective
1219252279Sjkim *
1220252279Sjkim * PARAMETERS:  None
1221252279Sjkim *
1222252279Sjkim * RETURN:      Status. Error if the stack is empty.
1223252279Sjkim *
1224252279Sjkim * DESCRIPTION: Pop an item off the directive stack. Used for processing
1225252279Sjkim *              nested #if/#else type conditional compilation directives.
1226252279Sjkim *              Specifically: Used on detection of #elif and #endif to remove
1227252279Sjkim *              the original #if/#ifdef/#ifndef from the stack and close
1228252279Sjkim *              the block.
1229252279Sjkim *
1230252279Sjkim ******************************************************************************/
1231252279Sjkim
1232252279Sjkimstatic ACPI_STATUS
1233252279SjkimPrPopDirective (
1234252279Sjkim    void)
1235252279Sjkim{
1236252279Sjkim    DIRECTIVE_INFO          *Info;
1237252279Sjkim
1238252279Sjkim
1239252279Sjkim    /* Check for empty stack */
1240252279Sjkim
1241252279Sjkim    Info = Gbl_DirectiveStack;
1242252279Sjkim    if (!Info)
1243252279Sjkim    {
1244252279Sjkim        return (AE_ERROR);
1245252279Sjkim    }
1246252279Sjkim
1247252279Sjkim    /* Pop one item, keep globals up-to-date */
1248252279Sjkim
1249252279Sjkim    Gbl_IfDepth--;
1250252279Sjkim    Gbl_IgnoringThisCodeBlock = Info->IgnoringThisCodeBlock;
1251252279Sjkim    Gbl_DirectiveStack = Info->Next;
1252252279Sjkim
1253252279Sjkim    DbgPrint (ASL_DEBUG_OUTPUT,
1254252279Sjkim        "Pr(%.4u) - [%u %s] %*s Popped [#%s %s]: IgnoreFlag now = %s\n",
1255252279Sjkim        Gbl_CurrentLineNumber, Gbl_IfDepth,
1256252279Sjkim        Gbl_IgnoringThisCodeBlock ? "I" : "E",
1257252279Sjkim        Gbl_IfDepth * 4, " ",
1258252279Sjkim        Gbl_DirectiveInfo[Info->Directive].Name,
1259252279Sjkim        Info->Argument, Gbl_IgnoringThisCodeBlock ? "TRUE" : "FALSE");
1260252279Sjkim
1261252279Sjkim    ACPI_FREE (Info);
1262252279Sjkim    return (AE_OK);
1263252279Sjkim}
1264252279Sjkim
1265252279Sjkim
1266252279Sjkim/*******************************************************************************
1267252279Sjkim *
1268252279Sjkim * FUNCTION:    PrDbgPrint
1269252279Sjkim *
1270252279Sjkim * PARAMETERS:  Action              - Action being performed
1271252279Sjkim *              DirectiveName       - Directive being processed
1272252279Sjkim *
1273252279Sjkim * RETURN:      None
1274252279Sjkim *
1275252279Sjkim * DESCRIPTION: Special debug print for directive processing.
1276252279Sjkim *
1277252279Sjkim ******************************************************************************/
1278252279Sjkim
1279252279Sjkimstatic void
1280252279SjkimPrDbgPrint (
1281252279Sjkim    char                    *Action,
1282252279Sjkim    char                    *DirectiveName)
1283252279Sjkim{
1284252279Sjkim
1285252279Sjkim    DbgPrint (ASL_DEBUG_OUTPUT, "Pr(%.4u) - [%u %s] "
1286283092Sjkim        "%*s %s #%s, IfDepth %u\n",
1287252279Sjkim        Gbl_CurrentLineNumber, Gbl_IfDepth,
1288252279Sjkim        Gbl_IgnoringThisCodeBlock ? "I" : "E",
1289252279Sjkim        Gbl_IfDepth * 4, " ",
1290252279Sjkim        Action, DirectiveName, Gbl_IfDepth);
1291252279Sjkim}
1292283092Sjkim
1293283092Sjkim
1294283092Sjkim/*******************************************************************************
1295283092Sjkim *
1296283092Sjkim * FUNCTION:    PrDoIncludeFile
1297283092Sjkim *
1298283092Sjkim * PARAMETERS:  Pathname                - Name of the input file
1299283092Sjkim *
1300283092Sjkim * RETURN:      None.
1301283092Sjkim *
1302283092Sjkim * DESCRIPTION: Open an include file, from #include.
1303283092Sjkim *
1304283092Sjkim ******************************************************************************/
1305283092Sjkim
1306283092Sjkimstatic void
1307283092SjkimPrDoIncludeFile (
1308283092Sjkim    char                    *Pathname)
1309283092Sjkim{
1310283092Sjkim    char                    *FullPathname;
1311283092Sjkim
1312283092Sjkim
1313283092Sjkim    (void) PrOpenIncludeFile (Pathname, "r", &FullPathname);
1314283092Sjkim}
1315283092Sjkim
1316283092Sjkim
1317283092Sjkim/*******************************************************************************
1318283092Sjkim *
1319283092Sjkim * FUNCTION:    PrDoIncludeBuffer
1320283092Sjkim *
1321283092Sjkim * PARAMETERS:  Pathname                - Name of the input binary file
1322283092Sjkim *              BufferName              - ACPI namepath of the buffer
1323283092Sjkim *
1324283092Sjkim * RETURN:      None.
1325283092Sjkim *
1326283092Sjkim * DESCRIPTION: Create an ACPI buffer object from a binary file. The contents
1327283092Sjkim *              of the file are emitted into the buffer object as ascii
1328283092Sjkim *              hex data. From #includebuffer.
1329283092Sjkim *
1330283092Sjkim ******************************************************************************/
1331283092Sjkim
1332283092Sjkimstatic void
1333283092SjkimPrDoIncludeBuffer (
1334283092Sjkim    char                    *Pathname,
1335283092Sjkim    char                    *BufferName)
1336283092Sjkim{
1337283092Sjkim    char                    *FullPathname;
1338283092Sjkim    FILE                    *BinaryBufferFile;
1339283092Sjkim    UINT32                  i = 0;
1340283092Sjkim    UINT8                   c;
1341283092Sjkim
1342283092Sjkim
1343283092Sjkim    BinaryBufferFile = PrOpenIncludeFile (Pathname, "rb", &FullPathname);
1344283092Sjkim    if (!BinaryBufferFile)
1345283092Sjkim    {
1346283092Sjkim        return;
1347283092Sjkim    }
1348283092Sjkim
1349283092Sjkim    /* Emit "Name (XXXX, Buffer() {" header */
1350283092Sjkim
1351283092Sjkim    FlPrintFile (ASL_FILE_PREPROCESSOR, "Name (%s, Buffer()\n{", BufferName);
1352283092Sjkim
1353283092Sjkim    /* Dump the entire file in ascii hex format */
1354283092Sjkim
1355283092Sjkim    while (fread (&c, 1, 1, BinaryBufferFile))
1356283092Sjkim    {
1357283092Sjkim        if (!(i % 8))
1358283092Sjkim        {
1359283092Sjkim            FlPrintFile (ASL_FILE_PREPROCESSOR, "\n   ", c);
1360283092Sjkim        }
1361283092Sjkim
1362283092Sjkim        FlPrintFile (ASL_FILE_PREPROCESSOR, " 0x%2.2X,", c);
1363283092Sjkim        i++;
1364283092Sjkim    }
1365283092Sjkim
1366283092Sjkim    DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
1367283092Sjkim        "#includebuffer: read %u bytes from %s\n",
1368283092Sjkim        Gbl_CurrentLineNumber, i, FullPathname);
1369283092Sjkim
1370283092Sjkim    /* Close the Name() operator */
1371283092Sjkim
1372283092Sjkim    FlPrintFile (ASL_FILE_PREPROCESSOR, "\n})\n", BufferName);
1373283092Sjkim    fclose (BinaryBufferFile);
1374283092Sjkim}
1375