1 /******************************************************************************
2  *
3  * Module Name: prexpress - Preprocessor #if expression support
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2015, 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 "aslcompiler.h"
45 #include "dtcompiler.h"
46 
47 
48 #define _COMPONENT          ASL_PREPROCESSOR
49         ACPI_MODULE_NAME    ("prexpress")
50 
51 /* Local prototypes */
52 
53 static char *
54 PrExpandMacros (
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 
75 static void
76 PrUnTokenize (
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 
108 static char *
109 PrExpandMacros (
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 
182 UINT64
183 PrIsDefined (
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 
221 UINT64
222 PrResolveDefine (
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 
263 ACPI_STATUS
264 PrResolveIntegerExpression (
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
290 InvalidExpression:
291 
292     ACPI_FREE (EvalBuffer);
293     PrError (ASL_ERROR, ASL_MSG_INVALID_EXPRESSION, 0);
294     return (AE_ERROR);
295 
296 
297 NormalExit:
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