prexpress.c revision 306536
1/******************************************************************************
2 *
3 * Module Name: prexpress - Preprocessor #if expression support
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2016, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions, and the following disclaimer,
16 *    without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 *    substantially similar to the "NO WARRANTY" disclaimer below
19 *    ("Disclaimer") and any redistribution must be conditioned upon
20 *    including a substantially similar Disclaimer requirement for further
21 *    binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 *    of any contributors may be used to endorse or promote products derived
24 *    from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#include <contrib/dev/acpica/compiler/aslcompiler.h>
45#include <contrib/dev/acpica/compiler/dtcompiler.h>
46
47
48#define _COMPONENT          ASL_PREPROCESSOR
49        ACPI_MODULE_NAME    ("prexpress")
50
51/* Local prototypes */
52
53static char *
54PrExpandMacros (
55    char                    *Line);
56
57
58#ifdef _UNDER_DEVELOPMENT
59/******************************************************************************
60 *
61 * FUNCTION:    PrUnTokenize
62 *
63 * PARAMETERS:  Buffer              - Token Buffer
64 *              Next                - "Next" buffer from GetNextToken
65 *
66 * RETURN:      None
67 *
68 * DESCRIPTION: Un-tokenized the current token buffer. The implementation is
69 *              to simply set the null inserted by GetNextToken to a blank.
70 *              If Next is NULL, there were no tokens found in the Buffer,
71 *              so there is nothing to do.
72 *
73 *****************************************************************************/
74
75static void
76PrUnTokenize (
77    char                    *Buffer,
78    char                    *Next)
79{
80    UINT32                  Length = strlen (Buffer);
81
82
83    if (!Next)
84    {
85        return;
86    }
87
88    if (Buffer[Length] != '\n')
89    {
90        Buffer[strlen(Buffer)] = ' ';
91    }
92}
93#endif
94
95
96/******************************************************************************
97 *
98 * FUNCTION:    PrExpandMacros
99 *
100 * PARAMETERS:  Line                - Pointer into the current line
101 *
102 * RETURN:      Updated pointer into the current line
103 *
104 * DESCRIPTION: Expand any macros found in the current line buffer.
105 *
106 *****************************************************************************/
107
108static char *
109PrExpandMacros (
110    char                    *Line)
111{
112    char                    *Token;
113    char                    *ReplaceString;
114    PR_DEFINE_INFO          *DefineInfo;
115    ACPI_SIZE               TokenOffset;
116    char                    *Next;
117    int                     OffsetAdjust;
118
119
120    strcpy (Gbl_ExpressionTokenBuffer, Gbl_CurrentLineBuffer);
121    Token = PrGetNextToken (Gbl_ExpressionTokenBuffer, PR_EXPR_SEPARATORS, &Next);
122    OffsetAdjust = 0;
123
124    while (Token)
125    {
126        DefineInfo = PrMatchDefine (Token);
127        if (DefineInfo)
128        {
129            if (DefineInfo->Body)
130            {
131                /* This is a macro. TBD: Is this allowed? */
132
133                DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
134                    "Matched Macro: %s->%s\n",
135                    Gbl_CurrentLineNumber, DefineInfo->Identifier,
136                    DefineInfo->Replacement);
137
138                PrDoMacroInvocation (Gbl_ExpressionTokenBuffer, Token,
139                    DefineInfo, &Next);
140            }
141            else
142            {
143                ReplaceString = DefineInfo->Replacement;
144
145                /* Replace the name in the original line buffer */
146
147                TokenOffset = Token - Gbl_ExpressionTokenBuffer + OffsetAdjust;
148                PrReplaceData (
149                    &Gbl_CurrentLineBuffer[TokenOffset], strlen (Token),
150                    ReplaceString, strlen (ReplaceString));
151
152                /* Adjust for length difference between old and new name length */
153
154                OffsetAdjust += strlen (ReplaceString) - strlen (Token);
155
156                DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
157                    "Matched #define within expression: %s->%s\n",
158                    Gbl_CurrentLineNumber, Token,
159                    *ReplaceString ? ReplaceString : "(NULL STRING)");
160            }
161        }
162
163        Token = PrGetNextToken (NULL, PR_EXPR_SEPARATORS, &Next);
164    }
165
166    return (Line);
167}
168
169
170/******************************************************************************
171 *
172 * FUNCTION:    PrIsDefined
173 *
174 * PARAMETERS:  Identifier          - Name to be resolved
175 *
176 * RETURN:      64-bit boolean integer value
177 *
178 * DESCRIPTION: Returns TRUE if the name is defined, FALSE otherwise (0).
179 *
180 *****************************************************************************/
181
182UINT64
183PrIsDefined (
184    char                    *Identifier)
185{
186    UINT64                  Value;
187    PR_DEFINE_INFO          *DefineInfo;
188
189
190    DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
191        "**** Is defined?:  %s\n", Gbl_CurrentLineNumber, Identifier);
192
193    Value = 0; /* Default is "Not defined" -- FALSE */
194
195    DefineInfo = PrMatchDefine (Identifier);
196    if (DefineInfo)
197    {
198        Value = ACPI_UINT64_MAX; /* TRUE */
199    }
200
201    DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
202        "[#if defined %s] resolved to: %8.8X%8.8X\n",
203        Gbl_CurrentLineNumber, Identifier, ACPI_FORMAT_UINT64 (Value));
204
205    return (Value);
206}
207
208
209/******************************************************************************
210 *
211 * FUNCTION:    PrResolveDefine
212 *
213 * PARAMETERS:  Identifier          - Name to be resolved
214 *
215 * RETURN:      A 64-bit boolean integer value
216 *
217 * DESCRIPTION: Returns TRUE if the name is defined, FALSE otherwise (0).
218 *
219 *****************************************************************************/
220
221UINT64
222PrResolveDefine (
223    char                    *Identifier)
224{
225    UINT64                  Value;
226    PR_DEFINE_INFO          *DefineInfo;
227
228
229    DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
230        "**** Resolve #define:  %s\n", Gbl_CurrentLineNumber, Identifier);
231
232    Value = 0; /* Default is "Not defined" -- FALSE */
233
234    DefineInfo = PrMatchDefine (Identifier);
235    if (DefineInfo)
236    {
237        Value = ACPI_UINT64_MAX; /* TRUE */
238    }
239
240    DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
241        "[#if defined %s] resolved to: %8.8X%8.8X\n",
242        Gbl_CurrentLineNumber, Identifier, ACPI_FORMAT_UINT64 (Value));
243
244    return (Value);
245}
246
247
248/******************************************************************************
249 *
250 * FUNCTION:    PrResolveIntegerExpression
251 *
252 * PARAMETERS:  Line                - Pointer to integer expression
253 *              ReturnValue         - Where the resolved 64-bit integer is
254 *                                    returned.
255 *
256 * RETURN:      Status
257 *
258 * DESCRIPTION: Resolve an integer expression to a single value. Supports
259 *              both integer constants and labels.
260 *
261 *****************************************************************************/
262
263ACPI_STATUS
264PrResolveIntegerExpression (
265    char                    *Line,
266    UINT64                  *ReturnValue)
267{
268    UINT64                  Result;
269    char                    *ExpandedLine;
270
271
272    DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
273        "**** Resolve #if:  %s\n", Gbl_CurrentLineNumber, Line);
274
275    /* Expand all macros within the expression first */
276
277    ExpandedLine = PrExpandMacros (Line);
278
279    /* Now we can evaluate the expression */
280
281    Result = PrEvaluateExpression (ExpandedLine);
282    DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
283        "**** Expression Resolved to: %8.8X%8.8X\n",
284        Gbl_CurrentLineNumber, ACPI_FORMAT_UINT64 (Result));
285
286    *ReturnValue = Result;
287    return (AE_OK);
288
289#if 0
290InvalidExpression:
291
292    ACPI_FREE (EvalBuffer);
293    PrError (ASL_ERROR, ASL_MSG_INVALID_EXPRESSION, 0);
294    return (AE_ERROR);
295
296
297NormalExit:
298
299    DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
300        "**** Expression Resolved to: %8.8X%8.8X\n",
301        Gbl_CurrentLineNumber, ACPI_FORMAT_UINT64 (Value1));
302
303    *ReturnValue = Value1;
304    return (AE_OK);
305#endif
306}
307