1233237Sjkim/******************************************************************************
2233237Sjkim *
3233237Sjkim * Module Name: prexpress - Preprocessor #if expression support
4233237Sjkim *
5233237Sjkim *****************************************************************************/
6233237Sjkim
7233237Sjkim/*
8306536Sjkim * Copyright (C) 2000 - 2016, Intel Corp.
9233237Sjkim * All rights reserved.
10233237Sjkim *
11233237Sjkim * Redistribution and use in source and binary forms, with or without
12233237Sjkim * modification, are permitted provided that the following conditions
13233237Sjkim * are met:
14233237Sjkim * 1. Redistributions of source code must retain the above copyright
15233237Sjkim *    notice, this list of conditions, and the following disclaimer,
16233237Sjkim *    without modification.
17233237Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18233237Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
19233237Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
20233237Sjkim *    including a substantially similar Disclaimer requirement for further
21233237Sjkim *    binary redistribution.
22233237Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
23233237Sjkim *    of any contributors may be used to endorse or promote products derived
24233237Sjkim *    from this software without specific prior written permission.
25233237Sjkim *
26233237Sjkim * Alternatively, this software may be distributed under the terms of the
27233237Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
28233237Sjkim * Software Foundation.
29233237Sjkim *
30233237Sjkim * NO WARRANTY
31233237Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32233237Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33233237Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34233237Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35233237Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36233237Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37233237Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38233237Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39233237Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40233237Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41233237Sjkim * POSSIBILITY OF SUCH DAMAGES.
42233237Sjkim */
43233237Sjkim
44233250Sjkim#include <contrib/dev/acpica/compiler/aslcompiler.h>
45233250Sjkim#include <contrib/dev/acpica/compiler/dtcompiler.h>
46233237Sjkim
47233237Sjkim
48233237Sjkim#define _COMPONENT          ASL_PREPROCESSOR
49233237Sjkim        ACPI_MODULE_NAME    ("prexpress")
50233237Sjkim
51233237Sjkim/* Local prototypes */
52233237Sjkim
53233237Sjkimstatic char *
54233237SjkimPrExpandMacros (
55233237Sjkim    char                    *Line);
56233237Sjkim
57233237Sjkim
58233237Sjkim#ifdef _UNDER_DEVELOPMENT
59233237Sjkim/******************************************************************************
60233237Sjkim *
61233237Sjkim * FUNCTION:    PrUnTokenize
62233237Sjkim *
63233237Sjkim * PARAMETERS:  Buffer              - Token Buffer
64233237Sjkim *              Next                - "Next" buffer from GetNextToken
65233237Sjkim *
66233237Sjkim * RETURN:      None
67233237Sjkim *
68233237Sjkim * DESCRIPTION: Un-tokenized the current token buffer. The implementation is
69233237Sjkim *              to simply set the null inserted by GetNextToken to a blank.
70233237Sjkim *              If Next is NULL, there were no tokens found in the Buffer,
71233237Sjkim *              so there is nothing to do.
72233237Sjkim *
73233237Sjkim *****************************************************************************/
74233237Sjkim
75233237Sjkimstatic void
76233237SjkimPrUnTokenize (
77233237Sjkim    char                    *Buffer,
78233237Sjkim    char                    *Next)
79233237Sjkim{
80233237Sjkim    UINT32                  Length = strlen (Buffer);
81233237Sjkim
82233237Sjkim
83233237Sjkim    if (!Next)
84233237Sjkim    {
85233237Sjkim        return;
86233237Sjkim    }
87306536Sjkim
88233237Sjkim    if (Buffer[Length] != '\n')
89233237Sjkim    {
90233237Sjkim        Buffer[strlen(Buffer)] = ' ';
91233237Sjkim    }
92233237Sjkim}
93233237Sjkim#endif
94233237Sjkim
95233237Sjkim
96233237Sjkim/******************************************************************************
97233237Sjkim *
98233237Sjkim * FUNCTION:    PrExpandMacros
99233237Sjkim *
100233237Sjkim * PARAMETERS:  Line                - Pointer into the current line
101233237Sjkim *
102233237Sjkim * RETURN:      Updated pointer into the current line
103233237Sjkim *
104233237Sjkim * DESCRIPTION: Expand any macros found in the current line buffer.
105233237Sjkim *
106233237Sjkim *****************************************************************************/
107233237Sjkim
108233237Sjkimstatic char *
109233237SjkimPrExpandMacros (
110233237Sjkim    char                    *Line)
111233237Sjkim{
112233237Sjkim    char                    *Token;
113233237Sjkim    char                    *ReplaceString;
114233237Sjkim    PR_DEFINE_INFO          *DefineInfo;
115233237Sjkim    ACPI_SIZE               TokenOffset;
116233237Sjkim    char                    *Next;
117233237Sjkim    int                     OffsetAdjust;
118233237Sjkim
119233237Sjkim
120233237Sjkim    strcpy (Gbl_ExpressionTokenBuffer, Gbl_CurrentLineBuffer);
121233237Sjkim    Token = PrGetNextToken (Gbl_ExpressionTokenBuffer, PR_EXPR_SEPARATORS, &Next);
122233237Sjkim    OffsetAdjust = 0;
123233237Sjkim
124233237Sjkim    while (Token)
125233237Sjkim    {
126233237Sjkim        DefineInfo = PrMatchDefine (Token);
127233237Sjkim        if (DefineInfo)
128233237Sjkim        {
129233237Sjkim            if (DefineInfo->Body)
130233237Sjkim            {
131233237Sjkim                /* This is a macro. TBD: Is this allowed? */
132233237Sjkim
133233237Sjkim                DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
134233237Sjkim                    "Matched Macro: %s->%s\n",
135233237Sjkim                    Gbl_CurrentLineNumber, DefineInfo->Identifier,
136233237Sjkim                    DefineInfo->Replacement);
137233237Sjkim
138233237Sjkim                PrDoMacroInvocation (Gbl_ExpressionTokenBuffer, Token,
139233237Sjkim                    DefineInfo, &Next);
140233237Sjkim            }
141233237Sjkim            else
142233237Sjkim            {
143233237Sjkim                ReplaceString = DefineInfo->Replacement;
144233237Sjkim
145233237Sjkim                /* Replace the name in the original line buffer */
146233237Sjkim
147233237Sjkim                TokenOffset = Token - Gbl_ExpressionTokenBuffer + OffsetAdjust;
148233237Sjkim                PrReplaceData (
149233237Sjkim                    &Gbl_CurrentLineBuffer[TokenOffset], strlen (Token),
150233237Sjkim                    ReplaceString, strlen (ReplaceString));
151233237Sjkim
152233237Sjkim                /* Adjust for length difference between old and new name length */
153233237Sjkim
154233237Sjkim                OffsetAdjust += strlen (ReplaceString) - strlen (Token);
155233237Sjkim
156233237Sjkim                DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
157233237Sjkim                    "Matched #define within expression: %s->%s\n",
158233237Sjkim                    Gbl_CurrentLineNumber, Token,
159233237Sjkim                    *ReplaceString ? ReplaceString : "(NULL STRING)");
160233237Sjkim            }
161233237Sjkim        }
162233237Sjkim
163233237Sjkim        Token = PrGetNextToken (NULL, PR_EXPR_SEPARATORS, &Next);
164233237Sjkim    }
165233237Sjkim
166233237Sjkim    return (Line);
167233237Sjkim}
168233237Sjkim
169233237Sjkim
170233237Sjkim/******************************************************************************
171233237Sjkim *
172233237Sjkim * FUNCTION:    PrIsDefined
173233237Sjkim *
174233237Sjkim * PARAMETERS:  Identifier          - Name to be resolved
175233237Sjkim *
176233237Sjkim * RETURN:      64-bit boolean integer value
177233237Sjkim *
178233237Sjkim * DESCRIPTION: Returns TRUE if the name is defined, FALSE otherwise (0).
179233237Sjkim *
180233237Sjkim *****************************************************************************/
181233237Sjkim
182233237SjkimUINT64
183233237SjkimPrIsDefined (
184233237Sjkim    char                    *Identifier)
185233237Sjkim{
186233237Sjkim    UINT64                  Value;
187233237Sjkim    PR_DEFINE_INFO          *DefineInfo;
188233237Sjkim
189233237Sjkim
190233237Sjkim    DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
191233237Sjkim        "**** Is defined?:  %s\n", Gbl_CurrentLineNumber, Identifier);
192233237Sjkim
193233237Sjkim    Value = 0; /* Default is "Not defined" -- FALSE */
194233237Sjkim
195233237Sjkim    DefineInfo = PrMatchDefine (Identifier);
196233237Sjkim    if (DefineInfo)
197233237Sjkim    {
198233237Sjkim        Value = ACPI_UINT64_MAX; /* TRUE */
199233237Sjkim    }
200233237Sjkim
201233237Sjkim    DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
202233237Sjkim        "[#if defined %s] resolved to: %8.8X%8.8X\n",
203233237Sjkim        Gbl_CurrentLineNumber, Identifier, ACPI_FORMAT_UINT64 (Value));
204233237Sjkim
205233237Sjkim    return (Value);
206233237Sjkim}
207233237Sjkim
208233237Sjkim
209233237Sjkim/******************************************************************************
210233237Sjkim *
211233237Sjkim * FUNCTION:    PrResolveDefine
212233237Sjkim *
213233237Sjkim * PARAMETERS:  Identifier          - Name to be resolved
214233237Sjkim *
215233237Sjkim * RETURN:      A 64-bit boolean integer value
216233237Sjkim *
217233237Sjkim * DESCRIPTION: Returns TRUE if the name is defined, FALSE otherwise (0).
218233237Sjkim *
219233237Sjkim *****************************************************************************/
220233237Sjkim
221233237SjkimUINT64
222233237SjkimPrResolveDefine (
223233237Sjkim    char                    *Identifier)
224233237Sjkim{
225233237Sjkim    UINT64                  Value;
226233237Sjkim    PR_DEFINE_INFO          *DefineInfo;
227233237Sjkim
228233237Sjkim
229233237Sjkim    DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
230233237Sjkim        "**** Resolve #define:  %s\n", Gbl_CurrentLineNumber, Identifier);
231233237Sjkim
232233237Sjkim    Value = 0; /* Default is "Not defined" -- FALSE */
233233237Sjkim
234233237Sjkim    DefineInfo = PrMatchDefine (Identifier);
235233237Sjkim    if (DefineInfo)
236233237Sjkim    {
237233237Sjkim        Value = ACPI_UINT64_MAX; /* TRUE */
238233237Sjkim    }
239233237Sjkim
240233237Sjkim    DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
241233237Sjkim        "[#if defined %s] resolved to: %8.8X%8.8X\n",
242233237Sjkim        Gbl_CurrentLineNumber, Identifier, ACPI_FORMAT_UINT64 (Value));
243233237Sjkim
244233237Sjkim    return (Value);
245233237Sjkim}
246233237Sjkim
247233237Sjkim
248233237Sjkim/******************************************************************************
249233237Sjkim *
250233237Sjkim * FUNCTION:    PrResolveIntegerExpression
251233237Sjkim *
252233237Sjkim * PARAMETERS:  Line                - Pointer to integer expression
253233237Sjkim *              ReturnValue         - Where the resolved 64-bit integer is
254233237Sjkim *                                    returned.
255233237Sjkim *
256233237Sjkim * RETURN:      Status
257233237Sjkim *
258233237Sjkim * DESCRIPTION: Resolve an integer expression to a single value. Supports
259233237Sjkim *              both integer constants and labels.
260233237Sjkim *
261233237Sjkim *****************************************************************************/
262233237Sjkim
263233237SjkimACPI_STATUS
264233237SjkimPrResolveIntegerExpression (
265233237Sjkim    char                    *Line,
266233237Sjkim    UINT64                  *ReturnValue)
267233237Sjkim{
268233237Sjkim    UINT64                  Result;
269233237Sjkim    char                    *ExpandedLine;
270233237Sjkim
271233237Sjkim
272233237Sjkim    DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
273233237Sjkim        "**** Resolve #if:  %s\n", Gbl_CurrentLineNumber, Line);
274233237Sjkim
275233237Sjkim    /* Expand all macros within the expression first */
276233237Sjkim
277233237Sjkim    ExpandedLine = PrExpandMacros (Line);
278233237Sjkim
279233237Sjkim    /* Now we can evaluate the expression */
280233237Sjkim
281233237Sjkim    Result = PrEvaluateExpression (ExpandedLine);
282233237Sjkim    DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
283233237Sjkim        "**** Expression Resolved to: %8.8X%8.8X\n",
284233237Sjkim        Gbl_CurrentLineNumber, ACPI_FORMAT_UINT64 (Result));
285233237Sjkim
286233237Sjkim    *ReturnValue = Result;
287233237Sjkim    return (AE_OK);
288233237Sjkim
289233237Sjkim#if 0
290233237SjkimInvalidExpression:
291233237Sjkim
292233237Sjkim    ACPI_FREE (EvalBuffer);
293233237Sjkim    PrError (ASL_ERROR, ASL_MSG_INVALID_EXPRESSION, 0);
294233237Sjkim    return (AE_ERROR);
295233237Sjkim
296233237Sjkim
297233237SjkimNormalExit:
298233237Sjkim
299233237Sjkim    DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
300233237Sjkim        "**** Expression Resolved to: %8.8X%8.8X\n",
301233237Sjkim        Gbl_CurrentLineNumber, ACPI_FORMAT_UINT64 (Value1));
302233237Sjkim
303233237Sjkim    *ReturnValue = Value1;
304233237Sjkim    return (AE_OK);
305233237Sjkim#endif
306233237Sjkim}
307