xref: /netbsd-src/sys/external/bsd/acpica/dist/compiler/prexpress.c (revision 046a29855e04359424fd074e8313af6b6be8cfb6)
1 /******************************************************************************
2  *
3  * Module Name: prexpress - Preprocessor #if expression support
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2023, 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 MERCHANTABILITY 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 
46 #define _COMPONENT          ASL_PREPROCESSOR
47         ACPI_MODULE_NAME    ("prexpress")
48 
49 /* Local prototypes */
50 
51 static char *
52 PrExpandMacros (
53     char                    *Line);
54 
55 
56 #ifdef _UNDER_DEVELOPMENT
57 /******************************************************************************
58  *
59  * FUNCTION:    PrUnTokenize
60  *
61  * PARAMETERS:  Buffer              - Token Buffer
62  *              Next                - "Next" buffer from GetNextToken
63  *
64  * RETURN:      None
65  *
66  * DESCRIPTION: Un-tokenized the current token buffer. The implementation is
67  *              to simply set the null inserted by GetNextToken to a blank.
68  *              If Next is NULL, there were no tokens found in the Buffer,
69  *              so there is nothing to do.
70  *
71  *****************************************************************************/
72 
73 static void
PrUnTokenize(char * Buffer,char * Next)74 PrUnTokenize (
75     char                    *Buffer,
76     char                    *Next)
77 {
78     UINT32                  Length = strlen (Buffer);
79 
80 
81     if (!Next)
82     {
83         return;
84     }
85 
86     if (Buffer[Length] != '\n')
87     {
88         Buffer[strlen(Buffer)] = ' ';
89     }
90 }
91 #endif
92 
93 
94 /******************************************************************************
95  *
96  * FUNCTION:    PrExpandMacros
97  *
98  * PARAMETERS:  Line                - Pointer into the current line
99  *
100  * RETURN:      Updated pointer into the current line
101  *
102  * DESCRIPTION: Expand any macros found in the current line buffer.
103  *
104  *****************************************************************************/
105 
106 static char *
PrExpandMacros(char * Line)107 PrExpandMacros (
108     char                    *Line)
109 {
110     char                    *Token;
111     char                    *ReplaceString;
112     PR_DEFINE_INFO          *DefineInfo;
113     ACPI_SIZE               TokenOffset;
114     char                    *Next;
115     int                     OffsetAdjust;
116 
117 
118     strcpy (AslGbl_ExpressionTokenBuffer, AslGbl_CurrentLineBuffer);
119     Token = PrGetNextToken (AslGbl_ExpressionTokenBuffer, PR_EXPR_SEPARATORS, &Next);
120     OffsetAdjust = 0;
121 
122     while (Token)
123     {
124         DefineInfo = PrMatchDefine (Token);
125         if (DefineInfo)
126         {
127             if (DefineInfo->Body)
128             {
129                 /* This is a macro. TBD: Is this allowed? */
130 
131                 DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
132                     "Matched Macro: %s->%s\n",
133                     AslGbl_CurrentLineNumber, DefineInfo->Identifier,
134                     DefineInfo->Replacement);
135 
136                 PrDoMacroInvocation (AslGbl_ExpressionTokenBuffer, Token,
137                     DefineInfo, &Next);
138             }
139             else
140             {
141                 ReplaceString = DefineInfo->Replacement;
142 
143                 /* Replace the name in the original line buffer */
144 
145                 TokenOffset = Token - AslGbl_ExpressionTokenBuffer + OffsetAdjust;
146                 PrReplaceData (
147                     &AslGbl_CurrentLineBuffer[TokenOffset], strlen (Token),
148                     ReplaceString, strlen (ReplaceString));
149 
150                 /* Adjust for length difference between old and new name length */
151 
152                 OffsetAdjust += strlen (ReplaceString) - strlen (Token);
153 
154                 DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
155                     "Matched #define within expression: %s->%s\n",
156                     AslGbl_CurrentLineNumber, Token,
157                     *ReplaceString ? ReplaceString : "(NULL STRING)");
158             }
159         }
160 
161         Token = PrGetNextToken (NULL, PR_EXPR_SEPARATORS, &Next);
162     }
163 
164     return (Line);
165 }
166 
167 
168 /******************************************************************************
169  *
170  * FUNCTION:    PrIsDefined
171  *
172  * PARAMETERS:  Identifier          - Name to be resolved
173  *
174  * RETURN:      64-bit boolean integer value
175  *
176  * DESCRIPTION: Returns TRUE if the name is defined, FALSE otherwise (0).
177  *
178  *****************************************************************************/
179 
180 UINT64
PrIsDefined(char * Identifier)181 PrIsDefined (
182     char                    *Identifier)
183 {
184     UINT64                  Value;
185     PR_DEFINE_INFO          *DefineInfo;
186 
187 
188     DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
189         "**** Is defined?:  %s\n", AslGbl_CurrentLineNumber, Identifier);
190 
191     Value = 0; /* Default is "Not defined" -- FALSE */
192 
193     DefineInfo = PrMatchDefine (Identifier);
194     if (DefineInfo)
195     {
196         Value = ACPI_UINT64_MAX; /* TRUE */
197     }
198 
199     DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
200         "[#if defined %s] resolved to: %8.8X%8.8X\n",
201         AslGbl_CurrentLineNumber, Identifier, ACPI_FORMAT_UINT64 (Value));
202 
203     return (Value);
204 }
205 
206 
207 /******************************************************************************
208  *
209  * FUNCTION:    PrResolveDefine
210  *
211  * PARAMETERS:  Identifier          - Name to be resolved
212  *
213  * RETURN:      A 64-bit boolean integer value
214  *
215  * DESCRIPTION: Returns TRUE if the name is defined, FALSE otherwise (0).
216  *
217  *****************************************************************************/
218 
219 UINT64
PrResolveDefine(char * Identifier)220 PrResolveDefine (
221     char                    *Identifier)
222 {
223     UINT64                  Value;
224     PR_DEFINE_INFO          *DefineInfo;
225 
226 
227     DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
228         "**** Resolve #define:  %s\n", AslGbl_CurrentLineNumber, Identifier);
229 
230     Value = 0; /* Default is "Not defined" -- FALSE */
231 
232     DefineInfo = PrMatchDefine (Identifier);
233     if (DefineInfo)
234     {
235         Value = ACPI_UINT64_MAX; /* TRUE */
236     }
237 
238     DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
239         "[#if defined %s] resolved to: %8.8X%8.8X\n",
240         AslGbl_CurrentLineNumber, Identifier, ACPI_FORMAT_UINT64 (Value));
241 
242     return (Value);
243 }
244 
245 
246 /******************************************************************************
247  *
248  * FUNCTION:    PrResolveIntegerExpression
249  *
250  * PARAMETERS:  Line                - Pointer to integer expression
251  *              ReturnValue         - Where the resolved 64-bit integer is
252  *                                    returned.
253  *
254  * RETURN:      Status
255  *
256  * DESCRIPTION: Resolve an integer expression to a single value. Supports
257  *              both integer constants and labels.
258  *
259  *****************************************************************************/
260 
261 ACPI_STATUS
PrResolveIntegerExpression(char * Line,UINT64 * ReturnValue)262 PrResolveIntegerExpression (
263     char                    *Line,
264     UINT64                  *ReturnValue)
265 {
266     UINT64                  Result;
267     char                    *ExpandedLine;
268 
269 
270     DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
271         "**** Resolve #if:  %s\n", AslGbl_CurrentLineNumber, Line);
272 
273     /* Expand all macros within the expression first */
274 
275     ExpandedLine = PrExpandMacros (Line);
276 
277     /* Now we can evaluate the expression */
278 
279     Result = PrEvaluateExpression (ExpandedLine);
280     DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
281         "**** Expression Resolved to: %8.8X%8.8X\n",
282         AslGbl_CurrentLineNumber, ACPI_FORMAT_UINT64 (Result));
283 
284     *ReturnValue = Result;
285     return (AE_OK);
286 
287 #if 0
288 InvalidExpression:
289 
290     ACPI_FREE (EvalBuffer);
291     PrError (ASL_ERROR, ASL_MSG_INVALID_EXPRESSION, 0);
292     return (AE_ERROR);
293 
294 
295 NormalExit:
296 
297     DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
298         "**** Expression Resolved to: %8.8X%8.8X\n",
299         AslGbl_CurrentLineNumber, ACPI_FORMAT_UINT64 (Value1));
300 
301     *ReturnValue = Value1;
302     return (AE_OK);
303 #endif
304 }
305