1ff4a156dSchristos /******************************************************************************
2ff4a156dSchristos *
3ff4a156dSchristos * Module Name: prscan - Preprocessor start-up and file scan module
4ff4a156dSchristos *
5ff4a156dSchristos *****************************************************************************/
6ff4a156dSchristos
7ff4a156dSchristos /*
8*046a2985Schristos * Copyright (C) 2000 - 2023, Intel Corp.
9ff4a156dSchristos * All rights reserved.
10ff4a156dSchristos *
11ff4a156dSchristos * Redistribution and use in source and binary forms, with or without
12ff4a156dSchristos * modification, are permitted provided that the following conditions
13ff4a156dSchristos * are met:
14ff4a156dSchristos * 1. Redistributions of source code must retain the above copyright
15ff4a156dSchristos * notice, this list of conditions, and the following disclaimer,
16ff4a156dSchristos * without modification.
17ff4a156dSchristos * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18ff4a156dSchristos * substantially similar to the "NO WARRANTY" disclaimer below
19ff4a156dSchristos * ("Disclaimer") and any redistribution must be conditioned upon
20ff4a156dSchristos * including a substantially similar Disclaimer requirement for further
21ff4a156dSchristos * binary redistribution.
22ff4a156dSchristos * 3. Neither the names of the above-listed copyright holders nor the names
23ff4a156dSchristos * of any contributors may be used to endorse or promote products derived
24ff4a156dSchristos * from this software without specific prior written permission.
25ff4a156dSchristos *
26ff4a156dSchristos * Alternatively, this software may be distributed under the terms of the
27ff4a156dSchristos * GNU General Public License ("GPL") version 2 as published by the Free
28ff4a156dSchristos * Software Foundation.
29ff4a156dSchristos *
30ff4a156dSchristos * NO WARRANTY
31ff4a156dSchristos * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32ff4a156dSchristos * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3346a330b4Schristos * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
34ff4a156dSchristos * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35ff4a156dSchristos * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36ff4a156dSchristos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37ff4a156dSchristos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38ff4a156dSchristos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39ff4a156dSchristos * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40ff4a156dSchristos * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41ff4a156dSchristos * POSSIBILITY OF SUCH DAMAGES.
42ff4a156dSchristos */
43ff4a156dSchristos
44ff4a156dSchristos #define _DECLARE_PR_GLOBALS
45ff4a156dSchristos
46ff4a156dSchristos #include "aslcompiler.h"
47ff4a156dSchristos
48ff4a156dSchristos /*
49ff4a156dSchristos * TBDs:
50ff4a156dSchristos *
51ff4a156dSchristos * No nested macros, maybe never
52ff4a156dSchristos * Implement ASL "Include" as well as "#include" here?
53ff4a156dSchristos */
54ff4a156dSchristos #define _COMPONENT ASL_PREPROCESSOR
55ff4a156dSchristos ACPI_MODULE_NAME ("prscan")
56ff4a156dSchristos
57ff4a156dSchristos
58ff4a156dSchristos /* Local prototypes */
59ff4a156dSchristos
60ff4a156dSchristos static void
61ff4a156dSchristos PrPreprocessInputFile (
62ff4a156dSchristos void);
63ff4a156dSchristos
64ff4a156dSchristos static void
65ff4a156dSchristos PrDoDirective (
66ff4a156dSchristos char *DirectiveToken,
67ff4a156dSchristos char **Next);
68ff4a156dSchristos
69c72da027Schristos static void
70c72da027Schristos PrGetNextLineInit (
71c72da027Schristos void);
72c72da027Schristos
73c72da027Schristos static UINT32
74c72da027Schristos PrGetNextLine (
75c72da027Schristos FILE *Handle);
76c72da027Schristos
77ff4a156dSchristos static int
78ff4a156dSchristos PrMatchDirective (
79ff4a156dSchristos char *Directive);
80ff4a156dSchristos
81ff4a156dSchristos static void
82ff4a156dSchristos PrPushDirective (
83ff4a156dSchristos int Directive,
84ff4a156dSchristos char *Argument);
85ff4a156dSchristos
86ff4a156dSchristos static ACPI_STATUS
87ff4a156dSchristos PrPopDirective (
88ff4a156dSchristos void);
89ff4a156dSchristos
90ff4a156dSchristos static void
91ff4a156dSchristos PrDbgPrint (
92ff4a156dSchristos char *Action,
93ff4a156dSchristos char *DirectiveName);
94ff4a156dSchristos
95c72da027Schristos static void
96c72da027Schristos PrDoIncludeBuffer (
97c72da027Schristos char *Pathname,
98c72da027Schristos char *BufferName);
99c72da027Schristos
100c72da027Schristos static void
101c72da027Schristos PrDoIncludeFile (
102c72da027Schristos char *Pathname);
103c72da027Schristos
104ff4a156dSchristos
105ff4a156dSchristos /*
106ff4a156dSchristos * Supported preprocessor directives
107c72da027Schristos * Each entry is of the form "Name, ArgumentCount"
108ff4a156dSchristos */
1094c4e8184Schristos static const PR_DIRECTIVE_INFO AslGbl_DirectiveInfo[] =
110ff4a156dSchristos {
111ff4a156dSchristos {"define", 1},
112ff4a156dSchristos {"elif", 0}, /* Converted to #else..#if internally */
113ff4a156dSchristos {"else", 0},
114ff4a156dSchristos {"endif", 0},
115ff4a156dSchristos {"error", 1},
116ff4a156dSchristos {"if", 1},
117ff4a156dSchristos {"ifdef", 1},
118ff4a156dSchristos {"ifndef", 1},
119c72da027Schristos {"include", 0}, /* Argument is not standard format, so just use 0 here */
120c72da027Schristos {"includebuffer", 0}, /* Argument is not standard format, so just use 0 here */
121ff4a156dSchristos {"line", 1},
122ff4a156dSchristos {"pragma", 1},
123ff4a156dSchristos {"undef", 1},
124ff4a156dSchristos {"warning", 1},
125ff4a156dSchristos {NULL, 0}
126ff4a156dSchristos };
127ff4a156dSchristos
128c72da027Schristos /* This table must match ordering of above table exactly */
129c72da027Schristos
130ff4a156dSchristos enum Gbl_DirectiveIndexes
131ff4a156dSchristos {
132ff4a156dSchristos PR_DIRECTIVE_DEFINE = 0,
133ff4a156dSchristos PR_DIRECTIVE_ELIF,
134ff4a156dSchristos PR_DIRECTIVE_ELSE,
135ff4a156dSchristos PR_DIRECTIVE_ENDIF,
136ff4a156dSchristos PR_DIRECTIVE_ERROR,
137ff4a156dSchristos PR_DIRECTIVE_IF,
138ff4a156dSchristos PR_DIRECTIVE_IFDEF,
139ff4a156dSchristos PR_DIRECTIVE_IFNDEF,
140ff4a156dSchristos PR_DIRECTIVE_INCLUDE,
141c72da027Schristos PR_DIRECTIVE_INCLUDEBUFFER,
142ff4a156dSchristos PR_DIRECTIVE_LINE,
143ff4a156dSchristos PR_DIRECTIVE_PRAGMA,
144ff4a156dSchristos PR_DIRECTIVE_UNDEF,
145c72da027Schristos PR_DIRECTIVE_WARNING
146ff4a156dSchristos };
147ff4a156dSchristos
148ff4a156dSchristos #define ASL_DIRECTIVE_NOT_FOUND -1
149ff4a156dSchristos
150ff4a156dSchristos
151ff4a156dSchristos /*******************************************************************************
152ff4a156dSchristos *
153ff4a156dSchristos * FUNCTION: PrInitializePreprocessor
154ff4a156dSchristos *
155ff4a156dSchristos * PARAMETERS: None
156ff4a156dSchristos *
157ff4a156dSchristos * RETURN: None
158ff4a156dSchristos *
159ff4a156dSchristos * DESCRIPTION: Startup initialization for the Preprocessor.
160ff4a156dSchristos *
161ff4a156dSchristos ******************************************************************************/
162ff4a156dSchristos
163ff4a156dSchristos void
PrInitializePreprocessor(void)164ff4a156dSchristos PrInitializePreprocessor (
165ff4a156dSchristos void)
166ff4a156dSchristos {
167ff4a156dSchristos /* Init globals and the list of #defines */
168ff4a156dSchristos
169ff4a156dSchristos PrInitializeGlobals ();
1704c4e8184Schristos AslGbl_DefineList = NULL;
171ff4a156dSchristos }
172ff4a156dSchristos
173ff4a156dSchristos
174ff4a156dSchristos /*******************************************************************************
175ff4a156dSchristos *
176ff4a156dSchristos * FUNCTION: PrInitializeGlobals
177ff4a156dSchristos *
178ff4a156dSchristos * PARAMETERS: None
179ff4a156dSchristos *
180ff4a156dSchristos * RETURN: None
181ff4a156dSchristos *
182ff4a156dSchristos * DESCRIPTION: Initialize globals for the Preprocessor. Used for startuup
183ff4a156dSchristos * initialization and re-initialization between compiles during
184ff4a156dSchristos * a multiple source file compile.
185ff4a156dSchristos *
186ff4a156dSchristos ******************************************************************************/
187ff4a156dSchristos
188ff4a156dSchristos void
PrInitializeGlobals(void)189ff4a156dSchristos PrInitializeGlobals (
190ff4a156dSchristos void)
191ff4a156dSchristos {
192ff4a156dSchristos /* Init globals */
193ff4a156dSchristos
1944c4e8184Schristos AslGbl_InputFileList = NULL;
1954c4e8184Schristos AslGbl_CurrentLineNumber = 1;
1964c4e8184Schristos AslGbl_PreprocessorLineNumber = 1;
1974c4e8184Schristos AslGbl_PreprocessorError = FALSE;
198ff4a156dSchristos
199ff4a156dSchristos /* These are used to track #if/#else blocks (possibly nested) */
200ff4a156dSchristos
2014c4e8184Schristos AslGbl_IfDepth = 0;
2024c4e8184Schristos AslGbl_IgnoringThisCodeBlock = FALSE;
2034c4e8184Schristos AslGbl_DirectiveStack = NULL;
204ff4a156dSchristos }
205ff4a156dSchristos
206ff4a156dSchristos
207ff4a156dSchristos /*******************************************************************************
208ff4a156dSchristos *
209ff4a156dSchristos * FUNCTION: PrTerminatePreprocessor
210ff4a156dSchristos *
211ff4a156dSchristos * PARAMETERS: None
212ff4a156dSchristos *
213ff4a156dSchristos * RETURN: None
214ff4a156dSchristos *
215ff4a156dSchristos * DESCRIPTION: Termination of the preprocessor. Delete lists. Keep any
216ff4a156dSchristos * defines that were specified on the command line, in order to
217ff4a156dSchristos * support multiple compiles with a single compiler invocation.
218ff4a156dSchristos *
219ff4a156dSchristos ******************************************************************************/
220ff4a156dSchristos
221ff4a156dSchristos void
PrTerminatePreprocessor(void)222ff4a156dSchristos PrTerminatePreprocessor (
223ff4a156dSchristos void)
224ff4a156dSchristos {
225ff4a156dSchristos PR_DEFINE_INFO *DefineInfo;
226ff4a156dSchristos
227ff4a156dSchristos
228ff4a156dSchristos /*
229ff4a156dSchristos * The persistent defines (created on the command line) are always at the
230ff4a156dSchristos * end of the list. We save them.
231ff4a156dSchristos */
2324c4e8184Schristos while ((AslGbl_DefineList) && (!AslGbl_DefineList->Persist))
233ff4a156dSchristos {
2344c4e8184Schristos DefineInfo = AslGbl_DefineList;
2354c4e8184Schristos AslGbl_DefineList = DefineInfo->Next;
236ff4a156dSchristos
237ff4a156dSchristos ACPI_FREE (DefineInfo->Replacement);
238ff4a156dSchristos ACPI_FREE (DefineInfo->Identifier);
239ff4a156dSchristos ACPI_FREE (DefineInfo);
240ff4a156dSchristos }
241ff4a156dSchristos }
242ff4a156dSchristos
243ff4a156dSchristos
244ff4a156dSchristos /*******************************************************************************
245ff4a156dSchristos *
246ff4a156dSchristos * FUNCTION: PrDoPreprocess
247ff4a156dSchristos *
248ff4a156dSchristos * PARAMETERS: None
249ff4a156dSchristos *
250ff4a156dSchristos * RETURN: None
251ff4a156dSchristos *
252ff4a156dSchristos * DESCRIPTION: Main entry point for the iASL Preprocessor. Input file must
253ff4a156dSchristos * be already open. Handles multiple input files via the
254ff4a156dSchristos * #include directive.
255ff4a156dSchristos *
256ff4a156dSchristos ******************************************************************************/
257ff4a156dSchristos
258ff4a156dSchristos void
PrDoPreprocess(void)259ff4a156dSchristos PrDoPreprocess (
260ff4a156dSchristos void)
261ff4a156dSchristos {
262ff4a156dSchristos BOOLEAN MoreInputFiles;
263ff4a156dSchristos
264ff4a156dSchristos
265ff4a156dSchristos DbgPrint (ASL_DEBUG_OUTPUT, "Starting preprocessing phase\n\n");
266ff4a156dSchristos
267ff4a156dSchristos
268ff4a156dSchristos FlSeekFile (ASL_FILE_INPUT, 0);
269ff4a156dSchristos PrDumpPredefinedNames ();
270ff4a156dSchristos
271ff4a156dSchristos /* Main preprocessor loop, handles include files */
272ff4a156dSchristos
273ff4a156dSchristos do
274ff4a156dSchristos {
275ff4a156dSchristos PrPreprocessInputFile ();
276ff4a156dSchristos MoreInputFiles = PrPopInputFileStack ();
277ff4a156dSchristos
278ff4a156dSchristos } while (MoreInputFiles);
279ff4a156dSchristos
280c72da027Schristos /* Point compiler input to the new preprocessor output file (.pre) */
281ff4a156dSchristos
282ff4a156dSchristos FlCloseFile (ASL_FILE_INPUT);
2834c4e8184Schristos AslGbl_Files[ASL_FILE_INPUT].Handle = AslGbl_Files[ASL_FILE_PREPROCESSOR].Handle;
2844c4e8184Schristos AslCompilerin = AslGbl_Files[ASL_FILE_INPUT].Handle;
285ff4a156dSchristos
286ff4a156dSchristos /* Reset globals to allow compiler to run */
287ff4a156dSchristos
288ff4a156dSchristos FlSeekFile (ASL_FILE_INPUT, 0);
2894c4e8184Schristos if (!AslGbl_PreprocessOnly)
290c72da027Schristos {
2914c4e8184Schristos AslGbl_CurrentLineNumber = 0;
292c72da027Schristos }
293ff4a156dSchristos
294ff4a156dSchristos DbgPrint (ASL_DEBUG_OUTPUT, "Preprocessing phase complete \n\n");
295ff4a156dSchristos }
296ff4a156dSchristos
297ff4a156dSchristos
298ff4a156dSchristos /*******************************************************************************
299ff4a156dSchristos *
300ff4a156dSchristos * FUNCTION: PrPreprocessInputFile
301ff4a156dSchristos *
302ff4a156dSchristos * PARAMETERS: None
303ff4a156dSchristos *
304ff4a156dSchristos * RETURN: None
305ff4a156dSchristos *
306ff4a156dSchristos * DESCRIPTION: Preprocess one entire file, line-by-line.
307ff4a156dSchristos *
308ff4a156dSchristos * Input: Raw user ASL from ASL_FILE_INPUT
309c72da027Schristos * Output: Preprocessed file written to ASL_FILE_PREPROCESSOR and
310c72da027Schristos * (optionally) ASL_FILE_PREPROCESSOR_USER
311ff4a156dSchristos *
312ff4a156dSchristos ******************************************************************************/
313ff4a156dSchristos
314ff4a156dSchristos static void
PrPreprocessInputFile(void)315ff4a156dSchristos PrPreprocessInputFile (
316ff4a156dSchristos void)
317ff4a156dSchristos {
318c72da027Schristos UINT32 Status;
319ff4a156dSchristos char *Token;
320ff4a156dSchristos char *ReplaceString;
321ff4a156dSchristos PR_DEFINE_INFO *DefineInfo;
322ff4a156dSchristos ACPI_SIZE TokenOffset;
323ff4a156dSchristos char *Next;
324ff4a156dSchristos int OffsetAdjust;
325ff4a156dSchristos
326ff4a156dSchristos
327c72da027Schristos PrGetNextLineInit ();
328ff4a156dSchristos
329c72da027Schristos /* Scan source line-by-line and process directives. Then write the .i file */
330c72da027Schristos
3314c4e8184Schristos while ((Status = PrGetNextLine (AslGbl_Files[ASL_FILE_INPUT].Handle)) != ASL_EOF)
332ff4a156dSchristos {
3334c4e8184Schristos AslGbl_CurrentLineNumber++;
3344c4e8184Schristos AslGbl_LogicalLineNumber++;
335c72da027Schristos
336cfbb7280Schristos if (Status == ASL_IGNORE_LINE)
337c72da027Schristos {
338c72da027Schristos goto WriteEntireLine;
339c72da027Schristos }
340c72da027Schristos
341ff4a156dSchristos /* Need a copy of the input line for strok() */
342ff4a156dSchristos
3434c4e8184Schristos strcpy (AslGbl_MainTokenBuffer, AslGbl_CurrentLineBuffer);
3444c4e8184Schristos Token = PrGetNextToken (AslGbl_MainTokenBuffer, PR_TOKEN_SEPARATORS, &Next);
345ff4a156dSchristos OffsetAdjust = 0;
346ff4a156dSchristos
347ff4a156dSchristos /* All preprocessor directives must begin with '#' */
348ff4a156dSchristos
349ff4a156dSchristos if (Token && (*Token == '#'))
350ff4a156dSchristos {
351ff4a156dSchristos if (strlen (Token) == 1)
352ff4a156dSchristos {
353ff4a156dSchristos Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, &Next);
354ff4a156dSchristos }
355ff4a156dSchristos else
356ff4a156dSchristos {
357ff4a156dSchristos Token++; /* Skip leading # */
358ff4a156dSchristos }
359ff4a156dSchristos
360ff4a156dSchristos /* Execute the directive, do not write line to output file */
361ff4a156dSchristos
362ff4a156dSchristos PrDoDirective (Token, &Next);
363ff4a156dSchristos continue;
364ff4a156dSchristos }
365ff4a156dSchristos
366ff4a156dSchristos /*
367ff4a156dSchristos * If we are currently within the part of an IF/ELSE block that is
368ff4a156dSchristos * FALSE, ignore the line and do not write it to the output file.
369ff4a156dSchristos * This continues until an #else or #endif is encountered.
370ff4a156dSchristos */
3714c4e8184Schristos if (AslGbl_IgnoringThisCodeBlock)
372ff4a156dSchristos {
373ff4a156dSchristos continue;
374ff4a156dSchristos }
375ff4a156dSchristos
376ff4a156dSchristos /* Match and replace all #defined names within this source line */
377ff4a156dSchristos
378ff4a156dSchristos while (Token)
379ff4a156dSchristos {
380ff4a156dSchristos DefineInfo = PrMatchDefine (Token);
381ff4a156dSchristos if (DefineInfo)
382ff4a156dSchristos {
383ff4a156dSchristos if (DefineInfo->Body)
384ff4a156dSchristos {
385ff4a156dSchristos /* This is a macro */
386ff4a156dSchristos
387ff4a156dSchristos DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
388ff4a156dSchristos "Matched Macro: %s->%s\n",
3894c4e8184Schristos AslGbl_CurrentLineNumber, DefineInfo->Identifier,
390ff4a156dSchristos DefineInfo->Replacement);
391ff4a156dSchristos
3924c4e8184Schristos PrDoMacroInvocation (AslGbl_MainTokenBuffer, Token,
393ff4a156dSchristos DefineInfo, &Next);
394ff4a156dSchristos }
395ff4a156dSchristos else
396ff4a156dSchristos {
397ff4a156dSchristos ReplaceString = DefineInfo->Replacement;
398ff4a156dSchristos
399ff4a156dSchristos /* Replace the name in the original line buffer */
400ff4a156dSchristos
4014c4e8184Schristos TokenOffset = Token - AslGbl_MainTokenBuffer + OffsetAdjust;
402ff4a156dSchristos PrReplaceData (
4034c4e8184Schristos &AslGbl_CurrentLineBuffer[TokenOffset], strlen (Token),
404ff4a156dSchristos ReplaceString, strlen (ReplaceString));
405ff4a156dSchristos
406ff4a156dSchristos /* Adjust for length difference between old and new name length */
407ff4a156dSchristos
408ff4a156dSchristos OffsetAdjust += strlen (ReplaceString) - strlen (Token);
409ff4a156dSchristos
410ff4a156dSchristos DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
411ff4a156dSchristos "Matched #define: %s->%s\n",
4124c4e8184Schristos AslGbl_CurrentLineNumber, Token,
413ff4a156dSchristos *ReplaceString ? ReplaceString : "(NULL STRING)");
414ff4a156dSchristos }
415ff4a156dSchristos }
416ff4a156dSchristos
417ff4a156dSchristos Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, &Next);
418ff4a156dSchristos }
419ff4a156dSchristos
4204c4e8184Schristos AslGbl_PreprocessorLineNumber++;
421ff4a156dSchristos
422c72da027Schristos
423c72da027Schristos WriteEntireLine:
424ff4a156dSchristos /*
425ff4a156dSchristos * Now we can write the possibly modified source line to the
426c72da027Schristos * preprocessor file(s).
427ff4a156dSchristos */
4284c4e8184Schristos FlWriteFile (ASL_FILE_PREPROCESSOR, AslGbl_CurrentLineBuffer,
4294c4e8184Schristos strlen (AslGbl_CurrentLineBuffer));
430ff4a156dSchristos }
431ff4a156dSchristos }
432ff4a156dSchristos
433ff4a156dSchristos
434ff4a156dSchristos /*******************************************************************************
435ff4a156dSchristos *
436ff4a156dSchristos * FUNCTION: PrDoDirective
437ff4a156dSchristos *
438ff4a156dSchristos * PARAMETERS: Directive - Pointer to directive name token
439ff4a156dSchristos * Next - "Next" buffer from GetNextToken
440ff4a156dSchristos *
441ff4a156dSchristos * RETURN: None.
442ff4a156dSchristos *
443ff4a156dSchristos * DESCRIPTION: Main processing for all preprocessor directives
444ff4a156dSchristos *
445ff4a156dSchristos ******************************************************************************/
446ff4a156dSchristos
447ff4a156dSchristos static void
PrDoDirective(char * DirectiveToken,char ** Next)448ff4a156dSchristos PrDoDirective (
449ff4a156dSchristos char *DirectiveToken,
450ff4a156dSchristos char **Next)
451ff4a156dSchristos {
4524c4e8184Schristos char *Token = AslGbl_MainTokenBuffer;
453c72da027Schristos char *Token2 = NULL;
454ff4a156dSchristos char *End;
455ff4a156dSchristos UINT64 Value;
456ff4a156dSchristos ACPI_SIZE TokenOffset;
457ff4a156dSchristos int Directive;
458ff4a156dSchristos ACPI_STATUS Status;
459ff4a156dSchristos
460ff4a156dSchristos
461ff4a156dSchristos if (!DirectiveToken)
462ff4a156dSchristos {
463ff4a156dSchristos goto SyntaxError;
464ff4a156dSchristos }
465ff4a156dSchristos
466ff4a156dSchristos Directive = PrMatchDirective (DirectiveToken);
467ff4a156dSchristos if (Directive == ASL_DIRECTIVE_NOT_FOUND)
468ff4a156dSchristos {
469ff4a156dSchristos PrError (ASL_ERROR, ASL_MSG_UNKNOWN_DIRECTIVE,
470ff4a156dSchristos THIS_TOKEN_OFFSET (DirectiveToken));
471ff4a156dSchristos
472c72da027Schristos DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
473ff4a156dSchristos "#%s: Unknown directive\n",
4744c4e8184Schristos AslGbl_CurrentLineNumber, DirectiveToken);
475ff4a156dSchristos return;
476ff4a156dSchristos }
477ff4a156dSchristos
478ff4a156dSchristos /*
479c72da027Schristos * Emit a line directive into the preprocessor file (.pre) after
480c72da027Schristos * every matched directive. This is passed through to the compiler
481c72da027Schristos * so that error/warning messages are kept in sync with the
482c72da027Schristos * original source file.
483c72da027Schristos */
484c72da027Schristos FlPrintFile (ASL_FILE_PREPROCESSOR, "#line %u \"%s\" // #%s\n",
4854c4e8184Schristos AslGbl_CurrentLineNumber, AslGbl_Files[ASL_FILE_INPUT].Filename,
4864c4e8184Schristos AslGbl_DirectiveInfo[Directive].Name);
487c72da027Schristos
488c72da027Schristos /*
489ff4a156dSchristos * If we are currently ignoring this block and we encounter a #else or
490ff4a156dSchristos * #elif, we must ignore their blocks also if the parent block is also
491ff4a156dSchristos * being ignored.
492ff4a156dSchristos */
4934c4e8184Schristos if (AslGbl_IgnoringThisCodeBlock)
494ff4a156dSchristos {
495ff4a156dSchristos switch (Directive)
496ff4a156dSchristos {
497ff4a156dSchristos case PR_DIRECTIVE_ELSE:
498ff4a156dSchristos case PR_DIRECTIVE_ELIF:
499ff4a156dSchristos
5004c4e8184Schristos if (AslGbl_DirectiveStack &&
5014c4e8184Schristos AslGbl_DirectiveStack->IgnoringThisCodeBlock)
502ff4a156dSchristos {
5034c4e8184Schristos PrDbgPrint ("Ignoring", AslGbl_DirectiveInfo[Directive].Name);
504ff4a156dSchristos return;
505ff4a156dSchristos }
506ff4a156dSchristos break;
507ff4a156dSchristos
508ff4a156dSchristos default:
509ff4a156dSchristos break;
510ff4a156dSchristos }
511ff4a156dSchristos }
512ff4a156dSchristos
513ff4a156dSchristos /*
514ff4a156dSchristos * Need to always check for #else, #elif, #endif regardless of
515ff4a156dSchristos * whether we are ignoring the current code block, since these
516ff4a156dSchristos * are conditional code block terminators.
517ff4a156dSchristos */
518ff4a156dSchristos switch (Directive)
519ff4a156dSchristos {
520ff4a156dSchristos case PR_DIRECTIVE_ELSE:
521ff4a156dSchristos
5224c4e8184Schristos AslGbl_IgnoringThisCodeBlock = !(AslGbl_IgnoringThisCodeBlock);
523ff4a156dSchristos PrDbgPrint ("Executing", "else block");
524ff4a156dSchristos return;
525ff4a156dSchristos
526ff4a156dSchristos case PR_DIRECTIVE_ELIF:
527ff4a156dSchristos
5284c4e8184Schristos AslGbl_IgnoringThisCodeBlock = !(AslGbl_IgnoringThisCodeBlock);
529ff4a156dSchristos Directive = PR_DIRECTIVE_IF;
530ff4a156dSchristos
5314c4e8184Schristos if (AslGbl_IgnoringThisCodeBlock == TRUE)
532ff4a156dSchristos {
533ff4a156dSchristos /* Not executing the ELSE part -- all done here */
534ff4a156dSchristos PrDbgPrint ("Ignoring", "elif block");
535ff4a156dSchristos return;
536ff4a156dSchristos }
537ff4a156dSchristos
538ff4a156dSchristos /*
539ff4a156dSchristos * After this, we will execute the IF part further below.
540ff4a156dSchristos * First, however, pop off the original #if directive.
541ff4a156dSchristos */
542ff4a156dSchristos if (ACPI_FAILURE (PrPopDirective ()))
543ff4a156dSchristos {
544ff4a156dSchristos PrError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL,
545ff4a156dSchristos THIS_TOKEN_OFFSET (DirectiveToken));
546ff4a156dSchristos }
547ff4a156dSchristos
548ff4a156dSchristos PrDbgPrint ("Executing", "elif block");
549ff4a156dSchristos break;
550ff4a156dSchristos
551ff4a156dSchristos case PR_DIRECTIVE_ENDIF:
552ff4a156dSchristos
553ff4a156dSchristos PrDbgPrint ("Executing", "endif");
554ff4a156dSchristos
555ff4a156dSchristos /* Pop the owning #if/#ifdef/#ifndef */
556ff4a156dSchristos
557ff4a156dSchristos if (ACPI_FAILURE (PrPopDirective ()))
558ff4a156dSchristos {
559ff4a156dSchristos PrError (ASL_ERROR, ASL_MSG_ENDIF_MISMATCH,
560ff4a156dSchristos THIS_TOKEN_OFFSET (DirectiveToken));
561ff4a156dSchristos }
562ff4a156dSchristos return;
563ff4a156dSchristos
564ff4a156dSchristos default:
565ff4a156dSchristos break;
566ff4a156dSchristos }
567ff4a156dSchristos
568ff4a156dSchristos /* Most directives have at least one argument */
569ff4a156dSchristos
5704c4e8184Schristos if (AslGbl_DirectiveInfo[Directive].ArgCount >= 1)
571ff4a156dSchristos {
572ff4a156dSchristos Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next);
573ff4a156dSchristos if (!Token)
574ff4a156dSchristos {
575ff4a156dSchristos goto SyntaxError;
576ff4a156dSchristos }
577ff4a156dSchristos }
578ff4a156dSchristos
5794c4e8184Schristos if (AslGbl_DirectiveInfo[Directive].ArgCount >= 2)
580c72da027Schristos {
581c72da027Schristos Token2 = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next);
582c72da027Schristos if (!Token2)
583c72da027Schristos {
584c72da027Schristos goto SyntaxError;
585c72da027Schristos }
586c72da027Schristos }
587c72da027Schristos
588ff4a156dSchristos /*
589ff4a156dSchristos * At this point, if we are ignoring the current code block,
590ff4a156dSchristos * do not process any more directives (i.e., ignore them also.)
591ff4a156dSchristos * For "if" style directives, open/push a new block anyway. We
592ff4a156dSchristos * must do this to keep track of #endif directives
593ff4a156dSchristos */
5944c4e8184Schristos if (AslGbl_IgnoringThisCodeBlock)
595ff4a156dSchristos {
596ff4a156dSchristos switch (Directive)
597ff4a156dSchristos {
598ff4a156dSchristos case PR_DIRECTIVE_IF:
599ff4a156dSchristos case PR_DIRECTIVE_IFDEF:
600ff4a156dSchristos case PR_DIRECTIVE_IFNDEF:
601ff4a156dSchristos
602ff4a156dSchristos PrPushDirective (Directive, Token);
6034c4e8184Schristos PrDbgPrint ("Ignoring", AslGbl_DirectiveInfo[Directive].Name);
604ff4a156dSchristos break;
605ff4a156dSchristos
606ff4a156dSchristos default:
607ff4a156dSchristos break;
608ff4a156dSchristos }
609ff4a156dSchristos
610ff4a156dSchristos return;
611ff4a156dSchristos }
612ff4a156dSchristos
613ff4a156dSchristos /*
614ff4a156dSchristos * Execute the directive
615ff4a156dSchristos */
6164c4e8184Schristos PrDbgPrint ("Begin execution", AslGbl_DirectiveInfo[Directive].Name);
617ff4a156dSchristos
618ff4a156dSchristos switch (Directive)
619ff4a156dSchristos {
620ff4a156dSchristos case PR_DIRECTIVE_IF:
621ff4a156dSchristos
6224c4e8184Schristos TokenOffset = Token - AslGbl_MainTokenBuffer;
623ff4a156dSchristos
624ff4a156dSchristos /* Need to expand #define macros in the expression string first */
625ff4a156dSchristos
626ff4a156dSchristos Status = PrResolveIntegerExpression (
6274c4e8184Schristos &AslGbl_CurrentLineBuffer[TokenOffset-1], &Value);
628ff4a156dSchristos if (ACPI_FAILURE (Status))
629ff4a156dSchristos {
630ff4a156dSchristos return;
631ff4a156dSchristos }
632ff4a156dSchristos
633ff4a156dSchristos PrPushDirective (Directive, Token);
634ff4a156dSchristos if (!Value)
635ff4a156dSchristos {
6364c4e8184Schristos AslGbl_IgnoringThisCodeBlock = TRUE;
637ff4a156dSchristos }
638ff4a156dSchristos
639c72da027Schristos DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
640ff4a156dSchristos "Resolved #if: %8.8X%8.8X %s\n",
6414c4e8184Schristos AslGbl_CurrentLineNumber, ACPI_FORMAT_UINT64 (Value),
6424c4e8184Schristos AslGbl_IgnoringThisCodeBlock ? "<Skipping Block>" : "<Executing Block>");
643ff4a156dSchristos break;
644ff4a156dSchristos
645ff4a156dSchristos case PR_DIRECTIVE_IFDEF:
646ff4a156dSchristos
647ff4a156dSchristos PrPushDirective (Directive, Token);
648ff4a156dSchristos if (!PrMatchDefine (Token))
649ff4a156dSchristos {
6504c4e8184Schristos AslGbl_IgnoringThisCodeBlock = TRUE;
651ff4a156dSchristos }
652ff4a156dSchristos
653ff4a156dSchristos PrDbgPrint ("Evaluated", "ifdef");
654ff4a156dSchristos break;
655ff4a156dSchristos
656ff4a156dSchristos case PR_DIRECTIVE_IFNDEF:
657ff4a156dSchristos
658ff4a156dSchristos PrPushDirective (Directive, Token);
659ff4a156dSchristos if (PrMatchDefine (Token))
660ff4a156dSchristos {
6614c4e8184Schristos AslGbl_IgnoringThisCodeBlock = TRUE;
662ff4a156dSchristos }
663ff4a156dSchristos
664ff4a156dSchristos PrDbgPrint ("Evaluated", "ifndef");
665ff4a156dSchristos break;
666ff4a156dSchristos
667ff4a156dSchristos case PR_DIRECTIVE_DEFINE:
668ff4a156dSchristos /*
669ff4a156dSchristos * By definition, if first char after the name is a paren,
670ff4a156dSchristos * this is a function macro.
671ff4a156dSchristos */
6724c4e8184Schristos TokenOffset = Token - AslGbl_MainTokenBuffer + strlen (Token);
6734c4e8184Schristos if (*(&AslGbl_CurrentLineBuffer[TokenOffset]) == '(')
674ff4a156dSchristos {
675*046a2985Schristos
676*046a2985Schristos #ifdef MACROS_SUPPORTED
67771e38f1dSchristos AcpiOsPrintf(
67871e38f1dSchristos "%s ERROR - line %u: #define macros are not supported yet\n",
6794c4e8184Schristos AslGbl_CurrentLineBuffer, AslGbl_LogicalLineNumber);
680ff4a156dSchristos exit(1);
681ff4a156dSchristos #else
682ff4a156dSchristos PrAddMacro (Token, Next);
683ff4a156dSchristos #endif
684ff4a156dSchristos }
685*046a2985Schristos
686*046a2985Schristos
687ff4a156dSchristos else
688ff4a156dSchristos {
689ff4a156dSchristos /* Use the remainder of the line for the #define */
690ff4a156dSchristos
691ff4a156dSchristos Token2 = *Next;
692ff4a156dSchristos if (Token2)
693ff4a156dSchristos {
694ff4a156dSchristos while ((*Token2 == ' ') || (*Token2 == '\t'))
695ff4a156dSchristos {
696ff4a156dSchristos Token2++;
697ff4a156dSchristos }
69871e38f1dSchristos
699ff4a156dSchristos End = Token2;
700ff4a156dSchristos while (*End != '\n')
701ff4a156dSchristos {
702ff4a156dSchristos End++;
703ff4a156dSchristos }
70471e38f1dSchristos
705ff4a156dSchristos *End = 0;
706ff4a156dSchristos }
707ff4a156dSchristos else
708ff4a156dSchristos {
709ff4a156dSchristos Token2 = "";
710ff4a156dSchristos }
711ff4a156dSchristos #if 0
712ff4a156dSchristos Token2 = PrGetNextToken (NULL, "\n", /*PR_TOKEN_SEPARATORS,*/ Next);
713ff4a156dSchristos if (!Token2)
714ff4a156dSchristos {
715ff4a156dSchristos Token2 = "";
716ff4a156dSchristos }
717ff4a156dSchristos #endif
718c72da027Schristos DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
719ff4a156dSchristos "New #define: %s->%s\n",
7204c4e8184Schristos AslGbl_LogicalLineNumber, Token, Token2);
721ff4a156dSchristos
722ff4a156dSchristos PrAddDefine (Token, Token2, FALSE);
723ff4a156dSchristos }
724ff4a156dSchristos break;
725ff4a156dSchristos
726ff4a156dSchristos case PR_DIRECTIVE_ERROR:
727ff4a156dSchristos
728ff4a156dSchristos /* Note: No macro expansion */
729ff4a156dSchristos
730ff4a156dSchristos PrError (ASL_ERROR, ASL_MSG_ERROR_DIRECTIVE,
731ff4a156dSchristos THIS_TOKEN_OFFSET (Token));
732ff4a156dSchristos
7334c4e8184Schristos AslGbl_SourceLine = 0;
7344c4e8184Schristos AslGbl_NextError = AslGbl_ErrorLog;
735ff4a156dSchristos CmCleanupAndExit ();
736ff4a156dSchristos exit(1);
737ff4a156dSchristos
738ff4a156dSchristos case PR_DIRECTIVE_INCLUDE:
739ff4a156dSchristos
740ff4a156dSchristos Token = PrGetNextToken (NULL, " \"<>", Next);
741ff4a156dSchristos if (!Token)
742ff4a156dSchristos {
743ff4a156dSchristos goto SyntaxError;
744ff4a156dSchristos }
745ff4a156dSchristos
746c72da027Schristos DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
7474c4e8184Schristos "Start #include file \"%s\"\n", AslGbl_CurrentLineNumber,
748783af925Schristos Token);
749ff4a156dSchristos
750c72da027Schristos PrDoIncludeFile (Token);
751c72da027Schristos break;
752c72da027Schristos
753c72da027Schristos case PR_DIRECTIVE_INCLUDEBUFFER:
754c72da027Schristos
755c72da027Schristos Token = PrGetNextToken (NULL, " \"<>", Next);
756c72da027Schristos if (!Token)
757c72da027Schristos {
758c72da027Schristos goto SyntaxError;
759c72da027Schristos }
760c72da027Schristos
761c72da027Schristos Token2 = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next);
762c72da027Schristos if (!Token2)
763c72da027Schristos {
764c72da027Schristos goto SyntaxError;
765c72da027Schristos }
766c72da027Schristos
767c72da027Schristos DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
768c72da027Schristos "Start #includebuffer input from file \"%s\", buffer name %s\n",
7694c4e8184Schristos AslGbl_CurrentLineNumber, Token, Token2);
770c72da027Schristos
771c72da027Schristos PrDoIncludeBuffer (Token, Token2);
772ff4a156dSchristos break;
773ff4a156dSchristos
774ff4a156dSchristos case PR_DIRECTIVE_LINE:
775ff4a156dSchristos
7764c4e8184Schristos TokenOffset = Token - AslGbl_MainTokenBuffer;
777ff4a156dSchristos
778ff4a156dSchristos Status = PrResolveIntegerExpression (
7794c4e8184Schristos &AslGbl_CurrentLineBuffer[TokenOffset-1], &Value);
780ff4a156dSchristos if (ACPI_FAILURE (Status))
781ff4a156dSchristos {
782ff4a156dSchristos return;
783ff4a156dSchristos }
784ff4a156dSchristos
785c72da027Schristos DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
7864c4e8184Schristos "User #line invocation %s\n", AslGbl_CurrentLineNumber,
787ff4a156dSchristos Token);
788ff4a156dSchristos
7894c4e8184Schristos AslGbl_CurrentLineNumber = (UINT32) Value;
790ff4a156dSchristos
791ff4a156dSchristos /* Emit #line into the preprocessor file */
792ff4a156dSchristos
793ff4a156dSchristos FlPrintFile (ASL_FILE_PREPROCESSOR, "#line %u \"%s\"\n",
7944c4e8184Schristos AslGbl_CurrentLineNumber, AslGbl_Files[ASL_FILE_INPUT].Filename);
795ff4a156dSchristos break;
796ff4a156dSchristos
797ff4a156dSchristos case PR_DIRECTIVE_PRAGMA:
798ff4a156dSchristos
799ff4a156dSchristos if (!strcmp (Token, "disable"))
800ff4a156dSchristos {
801ff4a156dSchristos Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next);
802ff4a156dSchristos if (!Token)
803ff4a156dSchristos {
804ff4a156dSchristos goto SyntaxError;
805ff4a156dSchristos }
806ff4a156dSchristos
8074c4e8184Schristos TokenOffset = Token - AslGbl_MainTokenBuffer;
8084c4e8184Schristos AslDisableException (&AslGbl_CurrentLineBuffer[TokenOffset]);
809ff4a156dSchristos }
810ff4a156dSchristos else if (!strcmp (Token, "message"))
811ff4a156dSchristos {
812ff4a156dSchristos Token = PrGetNextToken (NULL, PR_TOKEN_SEPARATORS, Next);
813ff4a156dSchristos if (!Token)
814ff4a156dSchristos {
815ff4a156dSchristos goto SyntaxError;
816ff4a156dSchristos }
817ff4a156dSchristos
8184c4e8184Schristos TokenOffset = Token - AslGbl_MainTokenBuffer;
8194c4e8184Schristos AcpiOsPrintf ("%s\n", &AslGbl_CurrentLineBuffer[TokenOffset]);
820ff4a156dSchristos }
821ff4a156dSchristos else
822ff4a156dSchristos {
823ff4a156dSchristos PrError (ASL_ERROR, ASL_MSG_UNKNOWN_PRAGMA,
824ff4a156dSchristos THIS_TOKEN_OFFSET (Token));
825ff4a156dSchristos return;
826ff4a156dSchristos }
827ff4a156dSchristos
828ff4a156dSchristos break;
829ff4a156dSchristos
830ff4a156dSchristos case PR_DIRECTIVE_UNDEF:
831ff4a156dSchristos
832c72da027Schristos DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
8334c4e8184Schristos "#undef: %s\n", AslGbl_CurrentLineNumber, Token);
834ff4a156dSchristos
835ff4a156dSchristos PrRemoveDefine (Token);
836ff4a156dSchristos break;
837ff4a156dSchristos
838ff4a156dSchristos case PR_DIRECTIVE_WARNING:
839ff4a156dSchristos
840ff4a156dSchristos PrError (ASL_WARNING, ASL_MSG_WARNING_DIRECTIVE,
841ff4a156dSchristos THIS_TOKEN_OFFSET (Token));
842c72da027Schristos
8434c4e8184Schristos AslGbl_SourceLine = 0;
8444c4e8184Schristos AslGbl_NextError = AslGbl_ErrorLog;
845ff4a156dSchristos break;
846ff4a156dSchristos
847ff4a156dSchristos default:
848ff4a156dSchristos
849ff4a156dSchristos /* Should never get here */
850c72da027Schristos DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
851ff4a156dSchristos "Unrecognized directive: %u\n",
8524c4e8184Schristos AslGbl_CurrentLineNumber, Directive);
853ff4a156dSchristos break;
854ff4a156dSchristos }
855ff4a156dSchristos
856ff4a156dSchristos return;
857ff4a156dSchristos
858ff4a156dSchristos SyntaxError:
859ff4a156dSchristos
860ff4a156dSchristos PrError (ASL_ERROR, ASL_MSG_DIRECTIVE_SYNTAX,
861ff4a156dSchristos THIS_TOKEN_OFFSET (DirectiveToken));
862ff4a156dSchristos return;
863ff4a156dSchristos }
864ff4a156dSchristos
865ff4a156dSchristos
866ff4a156dSchristos /*******************************************************************************
867ff4a156dSchristos *
868c72da027Schristos * FUNCTION: PrGetNextLine, PrGetNextLineInit
869c72da027Schristos *
870c72da027Schristos * PARAMETERS: Handle - Open file handle for the source file
871c72da027Schristos *
872c72da027Schristos * RETURN: Status of the GetLine operation:
873c72da027Schristos * AE_OK - Normal line, OK status
874cfbb7280Schristos * ASL_IGNORE_LINE - Line is blank or part of a multi-line
875cfbb7280Schristos * comment
876c72da027Schristos * ASL_EOF - End-of-file reached
877c72da027Schristos *
878c72da027Schristos * DESCRIPTION: Get the next text line from the input file. Does not strip
879c72da027Schristos * comments.
880c72da027Schristos *
881c72da027Schristos ******************************************************************************/
882c72da027Schristos
883c72da027Schristos #define PR_NORMAL_TEXT 0
884c72da027Schristos #define PR_MULTI_LINE_COMMENT 1
885c72da027Schristos #define PR_SINGLE_LINE_COMMENT 2
886c72da027Schristos #define PR_QUOTED_STRING 3
887c72da027Schristos
888c72da027Schristos static UINT8 AcpiGbl_LineScanState = PR_NORMAL_TEXT;
889c72da027Schristos
890c72da027Schristos static void
PrGetNextLineInit(void)891c72da027Schristos PrGetNextLineInit (
892c72da027Schristos void)
893c72da027Schristos {
894c72da027Schristos AcpiGbl_LineScanState = 0;
895c72da027Schristos }
896c72da027Schristos
897c72da027Schristos static UINT32
PrGetNextLine(FILE * Handle)898c72da027Schristos PrGetNextLine (
899c72da027Schristos FILE *Handle)
900c72da027Schristos {
901c72da027Schristos UINT32 i;
902c72da027Schristos int c = 0;
903c72da027Schristos int PreviousChar;
904c72da027Schristos
905c72da027Schristos
906c72da027Schristos /* Always clear the global line buffer */
907c72da027Schristos
9084c4e8184Schristos memset (AslGbl_CurrentLineBuffer, 0, AslGbl_LineBufferSize);
909c72da027Schristos for (i = 0; ;)
910c72da027Schristos {
911c72da027Schristos /*
912c72da027Schristos * If line is too long, expand the line buffers. Also increases
9134c4e8184Schristos * AslGbl_LineBufferSize.
914c72da027Schristos */
9154c4e8184Schristos if (i >= AslGbl_LineBufferSize)
916c72da027Schristos {
917c72da027Schristos UtExpandLineBuffers ();
918c72da027Schristos }
919c72da027Schristos
920c72da027Schristos PreviousChar = c;
921c72da027Schristos c = getc (Handle);
922c72da027Schristos if (c == EOF)
923c72da027Schristos {
924cfbb7280Schristos /*
925cfbb7280Schristos * On EOF: If there is anything in the line buffer, terminate
926cfbb7280Schristos * it with a newline, and catch the EOF on the next call
927cfbb7280Schristos * to this function.
928cfbb7280Schristos */
929cfbb7280Schristos if (i > 0)
930cfbb7280Schristos {
9314c4e8184Schristos AslGbl_CurrentLineBuffer[i] = '\n';
932cfbb7280Schristos return (AE_OK);
933cfbb7280Schristos }
934cfbb7280Schristos
935c72da027Schristos return (ASL_EOF);
936c72da027Schristos }
937c72da027Schristos
938c72da027Schristos /* Update state machine as necessary */
939c72da027Schristos
940c72da027Schristos switch (AcpiGbl_LineScanState)
941c72da027Schristos {
942c72da027Schristos case PR_NORMAL_TEXT:
943c72da027Schristos
944c72da027Schristos /* Check for multi-line comment start */
945c72da027Schristos
946c72da027Schristos if ((PreviousChar == '/') && (c == '*'))
947c72da027Schristos {
948c72da027Schristos AcpiGbl_LineScanState = PR_MULTI_LINE_COMMENT;
949c72da027Schristos }
950c72da027Schristos
951c72da027Schristos /* Check for single-line comment start */
952c72da027Schristos
953c72da027Schristos else if ((PreviousChar == '/') && (c == '/'))
954c72da027Schristos {
955c72da027Schristos AcpiGbl_LineScanState = PR_SINGLE_LINE_COMMENT;
956c72da027Schristos }
957c72da027Schristos
958c72da027Schristos /* Check for quoted string start */
959c72da027Schristos
960c72da027Schristos else if (PreviousChar == '"')
961c72da027Schristos {
962c72da027Schristos AcpiGbl_LineScanState = PR_QUOTED_STRING;
963c72da027Schristos }
964c72da027Schristos break;
965c72da027Schristos
966c72da027Schristos case PR_QUOTED_STRING:
967c72da027Schristos
968c72da027Schristos if (PreviousChar == '"')
969c72da027Schristos {
970c72da027Schristos AcpiGbl_LineScanState = PR_NORMAL_TEXT;
971c72da027Schristos }
972c72da027Schristos break;
973c72da027Schristos
974c72da027Schristos case PR_MULTI_LINE_COMMENT:
975c72da027Schristos
976c72da027Schristos /* Check for multi-line comment end */
977c72da027Schristos
978c72da027Schristos if ((PreviousChar == '*') && (c == '/'))
979c72da027Schristos {
980c72da027Schristos AcpiGbl_LineScanState = PR_NORMAL_TEXT;
981c72da027Schristos }
982c72da027Schristos break;
983c72da027Schristos
984c72da027Schristos case PR_SINGLE_LINE_COMMENT: /* Just ignore text until EOL */
985c72da027Schristos default:
986c72da027Schristos break;
987c72da027Schristos }
988c72da027Schristos
989c72da027Schristos /* Always copy the character into line buffer */
990c72da027Schristos
9914c4e8184Schristos AslGbl_CurrentLineBuffer[i] = (char) c;
992c72da027Schristos i++;
993c72da027Schristos
994c72da027Schristos /* Always exit on end-of-line */
995c72da027Schristos
996c72da027Schristos if (c == '\n')
997c72da027Schristos {
998c72da027Schristos /* Handle multi-line comments */
999c72da027Schristos
1000c72da027Schristos if (AcpiGbl_LineScanState == PR_MULTI_LINE_COMMENT)
1001c72da027Schristos {
1002cfbb7280Schristos return (ASL_IGNORE_LINE);
1003c72da027Schristos }
1004c72da027Schristos
1005c72da027Schristos /* End of single-line comment */
1006c72da027Schristos
1007c72da027Schristos if (AcpiGbl_LineScanState == PR_SINGLE_LINE_COMMENT)
1008c72da027Schristos {
1009c72da027Schristos AcpiGbl_LineScanState = PR_NORMAL_TEXT;
1010c72da027Schristos return (AE_OK);
1011c72da027Schristos }
1012c72da027Schristos
1013c72da027Schristos /* Blank line */
1014c72da027Schristos
1015c72da027Schristos if (i == 1)
1016c72da027Schristos {
1017cfbb7280Schristos return (ASL_IGNORE_LINE);
1018c72da027Schristos }
101971e38f1dSchristos
1020c72da027Schristos return (AE_OK);
1021c72da027Schristos }
1022c72da027Schristos }
1023c72da027Schristos }
1024c72da027Schristos
1025c72da027Schristos
1026c72da027Schristos /*******************************************************************************
1027c72da027Schristos *
1028ff4a156dSchristos * FUNCTION: PrMatchDirective
1029ff4a156dSchristos *
1030ff4a156dSchristos * PARAMETERS: Directive - Pointer to directive name token
1031ff4a156dSchristos *
1032ff4a156dSchristos * RETURN: Index into command array, -1 if not found
1033ff4a156dSchristos *
1034ff4a156dSchristos * DESCRIPTION: Lookup the incoming directive in the known directives table.
1035ff4a156dSchristos *
1036ff4a156dSchristos ******************************************************************************/
1037ff4a156dSchristos
1038ff4a156dSchristos static int
PrMatchDirective(char * Directive)1039ff4a156dSchristos PrMatchDirective (
1040ff4a156dSchristos char *Directive)
1041ff4a156dSchristos {
1042ff4a156dSchristos int i;
1043ff4a156dSchristos
1044ff4a156dSchristos
1045ff4a156dSchristos if (!Directive || Directive[0] == 0)
1046ff4a156dSchristos {
1047ff4a156dSchristos return (ASL_DIRECTIVE_NOT_FOUND);
1048ff4a156dSchristos }
1049ff4a156dSchristos
10504c4e8184Schristos for (i = 0; AslGbl_DirectiveInfo[i].Name; i++)
1051ff4a156dSchristos {
10524c4e8184Schristos if (!strcmp (AslGbl_DirectiveInfo[i].Name, Directive))
1053ff4a156dSchristos {
1054ff4a156dSchristos return (i);
1055ff4a156dSchristos }
1056ff4a156dSchristos }
1057ff4a156dSchristos
1058ff4a156dSchristos return (ASL_DIRECTIVE_NOT_FOUND); /* Command not recognized */
1059ff4a156dSchristos }
1060ff4a156dSchristos
1061ff4a156dSchristos
1062ff4a156dSchristos /*******************************************************************************
1063ff4a156dSchristos *
1064ff4a156dSchristos * FUNCTION: PrPushDirective
1065ff4a156dSchristos *
1066ff4a156dSchristos * PARAMETERS: Directive - Encoded directive ID
1067ff4a156dSchristos * Argument - String containing argument to the
1068ff4a156dSchristos * directive
1069ff4a156dSchristos *
1070ff4a156dSchristos * RETURN: None
1071ff4a156dSchristos *
1072ff4a156dSchristos * DESCRIPTION: Push an item onto the directive stack. Used for processing
1073ff4a156dSchristos * nested #if/#else type conditional compilation directives.
1074ff4a156dSchristos * Specifically: Used on detection of #if/#ifdef/#ifndef to open
1075ff4a156dSchristos * a block.
1076ff4a156dSchristos *
1077ff4a156dSchristos ******************************************************************************/
1078ff4a156dSchristos
1079ff4a156dSchristos static void
PrPushDirective(int Directive,char * Argument)1080ff4a156dSchristos PrPushDirective (
1081ff4a156dSchristos int Directive,
1082ff4a156dSchristos char *Argument)
1083ff4a156dSchristos {
1084ff4a156dSchristos DIRECTIVE_INFO *Info;
1085ff4a156dSchristos
1086ff4a156dSchristos
1087ff4a156dSchristos /* Allocate and populate a stack info item */
1088ff4a156dSchristos
10894c4e8184Schristos Info = ACPI_CAST_PTR (DIRECTIVE_INFO,
10904c4e8184Schristos UtLocalCacheCalloc (sizeof (DIRECTIVE_INFO)));
1091ff4a156dSchristos
10924c4e8184Schristos Info->Next = AslGbl_DirectiveStack;
1093ff4a156dSchristos Info->Directive = Directive;
10944c4e8184Schristos Info->IgnoringThisCodeBlock = AslGbl_IgnoringThisCodeBlock;
1095062782b3Schristos AcpiUtSafeStrncpy (Info->Argument, Argument, MAX_ARGUMENT_LENGTH);
1096ff4a156dSchristos
1097ff4a156dSchristos DbgPrint (ASL_DEBUG_OUTPUT,
1098ff4a156dSchristos "Pr(%.4u) - [%u %s] %*s Pushed [#%s %s]: IgnoreFlag = %s\n",
10994c4e8184Schristos AslGbl_CurrentLineNumber, AslGbl_IfDepth,
11004c4e8184Schristos AslGbl_IgnoringThisCodeBlock ? "I" : "E",
11014c4e8184Schristos AslGbl_IfDepth * 4, " ",
11024c4e8184Schristos AslGbl_DirectiveInfo[Directive].Name,
11034c4e8184Schristos Argument, AslGbl_IgnoringThisCodeBlock ? "TRUE" : "FALSE");
1104ff4a156dSchristos
1105ff4a156dSchristos /* Push new item */
1106ff4a156dSchristos
11074c4e8184Schristos AslGbl_DirectiveStack = Info;
11084c4e8184Schristos AslGbl_IfDepth++;
1109ff4a156dSchristos }
1110ff4a156dSchristos
1111ff4a156dSchristos
1112ff4a156dSchristos /*******************************************************************************
1113ff4a156dSchristos *
1114ff4a156dSchristos * FUNCTION: PrPopDirective
1115ff4a156dSchristos *
1116ff4a156dSchristos * PARAMETERS: None
1117ff4a156dSchristos *
1118ff4a156dSchristos * RETURN: Status. Error if the stack is empty.
1119ff4a156dSchristos *
1120ff4a156dSchristos * DESCRIPTION: Pop an item off the directive stack. Used for processing
1121ff4a156dSchristos * nested #if/#else type conditional compilation directives.
1122ff4a156dSchristos * Specifically: Used on detection of #elif and #endif to remove
1123ff4a156dSchristos * the original #if/#ifdef/#ifndef from the stack and close
1124ff4a156dSchristos * the block.
1125ff4a156dSchristos *
1126ff4a156dSchristos ******************************************************************************/
1127ff4a156dSchristos
1128ff4a156dSchristos static ACPI_STATUS
PrPopDirective(void)1129ff4a156dSchristos PrPopDirective (
1130ff4a156dSchristos void)
1131ff4a156dSchristos {
1132ff4a156dSchristos DIRECTIVE_INFO *Info;
1133ff4a156dSchristos
1134ff4a156dSchristos
1135ff4a156dSchristos /* Check for empty stack */
1136ff4a156dSchristos
11374c4e8184Schristos Info = AslGbl_DirectiveStack;
1138ff4a156dSchristos if (!Info)
1139ff4a156dSchristos {
1140ff4a156dSchristos return (AE_ERROR);
1141ff4a156dSchristos }
1142ff4a156dSchristos
1143ff4a156dSchristos /* Pop one item, keep globals up-to-date */
1144ff4a156dSchristos
11454c4e8184Schristos AslGbl_IfDepth--;
11464c4e8184Schristos AslGbl_IgnoringThisCodeBlock = Info->IgnoringThisCodeBlock;
11474c4e8184Schristos AslGbl_DirectiveStack = Info->Next;
1148ff4a156dSchristos
1149ff4a156dSchristos DbgPrint (ASL_DEBUG_OUTPUT,
1150ff4a156dSchristos "Pr(%.4u) - [%u %s] %*s Popped [#%s %s]: IgnoreFlag now = %s\n",
11514c4e8184Schristos AslGbl_CurrentLineNumber, AslGbl_IfDepth,
11524c4e8184Schristos AslGbl_IgnoringThisCodeBlock ? "I" : "E",
11534c4e8184Schristos AslGbl_IfDepth * 4, " ",
11544c4e8184Schristos AslGbl_DirectiveInfo[Info->Directive].Name,
11554c4e8184Schristos Info->Argument, AslGbl_IgnoringThisCodeBlock ? "TRUE" : "FALSE");
1156ff4a156dSchristos
1157ff4a156dSchristos return (AE_OK);
1158ff4a156dSchristos }
1159ff4a156dSchristos
1160ff4a156dSchristos
1161ff4a156dSchristos /*******************************************************************************
1162ff4a156dSchristos *
1163ff4a156dSchristos * FUNCTION: PrDbgPrint
1164ff4a156dSchristos *
1165ff4a156dSchristos * PARAMETERS: Action - Action being performed
1166ff4a156dSchristos * DirectiveName - Directive being processed
1167ff4a156dSchristos *
1168ff4a156dSchristos * RETURN: None
1169ff4a156dSchristos *
1170ff4a156dSchristos * DESCRIPTION: Special debug print for directive processing.
1171ff4a156dSchristos *
1172ff4a156dSchristos ******************************************************************************/
1173ff4a156dSchristos
1174ff4a156dSchristos static void
PrDbgPrint(char * Action,char * DirectiveName)1175ff4a156dSchristos PrDbgPrint (
1176ff4a156dSchristos char *Action,
1177ff4a156dSchristos char *DirectiveName)
1178ff4a156dSchristos {
1179ff4a156dSchristos
1180ff4a156dSchristos DbgPrint (ASL_DEBUG_OUTPUT, "Pr(%.4u) - [%u %s] "
1181c72da027Schristos "%*s %s #%s, IfDepth %u\n",
11824c4e8184Schristos AslGbl_CurrentLineNumber, AslGbl_IfDepth,
11834c4e8184Schristos AslGbl_IgnoringThisCodeBlock ? "I" : "E",
11844c4e8184Schristos AslGbl_IfDepth * 4, " ",
11854c4e8184Schristos Action, DirectiveName, AslGbl_IfDepth);
1186ff4a156dSchristos }
1187c72da027Schristos
1188c72da027Schristos
1189c72da027Schristos /*******************************************************************************
1190c72da027Schristos *
1191c72da027Schristos * FUNCTION: PrDoIncludeFile
1192c72da027Schristos *
1193c72da027Schristos * PARAMETERS: Pathname - Name of the input file
1194c72da027Schristos *
1195c72da027Schristos * RETURN: None.
1196c72da027Schristos *
1197c72da027Schristos * DESCRIPTION: Open an include file, from #include.
1198c72da027Schristos *
1199c72da027Schristos ******************************************************************************/
1200c72da027Schristos
1201c72da027Schristos static void
PrDoIncludeFile(char * Pathname)1202c72da027Schristos PrDoIncludeFile (
1203c72da027Schristos char *Pathname)
1204c72da027Schristos {
1205c72da027Schristos char *FullPathname;
1206c72da027Schristos
1207c72da027Schristos
1208c72da027Schristos (void) PrOpenIncludeFile (Pathname, "r", &FullPathname);
1209c72da027Schristos }
1210c72da027Schristos
1211c72da027Schristos
1212c72da027Schristos /*******************************************************************************
1213c72da027Schristos *
1214c72da027Schristos * FUNCTION: PrDoIncludeBuffer
1215c72da027Schristos *
1216c72da027Schristos * PARAMETERS: Pathname - Name of the input binary file
1217c72da027Schristos * BufferName - ACPI namepath of the buffer
1218c72da027Schristos *
1219c72da027Schristos * RETURN: None.
1220c72da027Schristos *
1221c72da027Schristos * DESCRIPTION: Create an ACPI buffer object from a binary file. The contents
1222c72da027Schristos * of the file are emitted into the buffer object as ascii
1223c72da027Schristos * hex data. From #includebuffer.
1224c72da027Schristos *
1225c72da027Schristos ******************************************************************************/
1226c72da027Schristos
1227c72da027Schristos static void
PrDoIncludeBuffer(char * Pathname,char * BufferName)1228c72da027Schristos PrDoIncludeBuffer (
1229c72da027Schristos char *Pathname,
1230c72da027Schristos char *BufferName)
1231c72da027Schristos {
1232c72da027Schristos char *FullPathname;
1233c72da027Schristos FILE *BinaryBufferFile;
1234c72da027Schristos UINT32 i = 0;
1235c72da027Schristos UINT8 c;
1236c72da027Schristos
1237c72da027Schristos
1238c72da027Schristos BinaryBufferFile = PrOpenIncludeFile (Pathname, "rb", &FullPathname);
1239c72da027Schristos if (!BinaryBufferFile)
1240c72da027Schristos {
1241c72da027Schristos return;
1242c72da027Schristos }
1243c72da027Schristos
1244c72da027Schristos /* Emit "Name (XXXX, Buffer() {" header */
1245c72da027Schristos
1246c72da027Schristos FlPrintFile (ASL_FILE_PREPROCESSOR, "Name (%s, Buffer()\n{", BufferName);
1247c72da027Schristos
1248c72da027Schristos /* Dump the entire file in ascii hex format */
1249c72da027Schristos
1250c72da027Schristos while (fread (&c, 1, 1, BinaryBufferFile))
1251c72da027Schristos {
1252c72da027Schristos if (!(i % 8))
1253c72da027Schristos {
1254783af925Schristos FlPrintFile (ASL_FILE_PREPROCESSOR, "\n ");
1255c72da027Schristos }
1256c72da027Schristos
1257c72da027Schristos FlPrintFile (ASL_FILE_PREPROCESSOR, " 0x%2.2X,", c);
1258c72da027Schristos i++;
1259c72da027Schristos }
1260c72da027Schristos
1261c72da027Schristos DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
1262c72da027Schristos "#includebuffer: read %u bytes from %s\n",
12634c4e8184Schristos AslGbl_CurrentLineNumber, i, FullPathname);
1264c72da027Schristos
1265c72da027Schristos /* Close the Name() operator */
1266c72da027Schristos
1267783af925Schristos FlPrintFile (ASL_FILE_PREPROCESSOR, "\n})\n");
1268c72da027Schristos fclose (BinaryBufferFile);
1269c72da027Schristos }
1270