prutils.c revision 1.1.1.17 1 1.1 christos /******************************************************************************
2 1.1 christos *
3 1.1 christos * Module Name: prutils - Preprocessor utilities
4 1.1 christos *
5 1.1 christos *****************************************************************************/
6 1.1 christos
7 1.1.1.16 christos /******************************************************************************
8 1.1.1.16 christos *
9 1.1.1.16 christos * 1. Copyright Notice
10 1.1.1.16 christos *
11 1.1.1.17 christos * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
12 1.1 christos * All rights reserved.
13 1.1 christos *
14 1.1.1.16 christos * 2. License
15 1.1.1.16 christos *
16 1.1.1.16 christos * 2.1. This is your license from Intel Corp. under its intellectual property
17 1.1.1.16 christos * rights. You may have additional license terms from the party that provided
18 1.1.1.16 christos * you this software, covering your right to use that party's intellectual
19 1.1.1.16 christos * property rights.
20 1.1.1.16 christos *
21 1.1.1.16 christos * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22 1.1.1.16 christos * copy of the source code appearing in this file ("Covered Code") an
23 1.1.1.16 christos * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24 1.1.1.16 christos * base code distributed originally by Intel ("Original Intel Code") to copy,
25 1.1.1.16 christos * make derivatives, distribute, use and display any portion of the Covered
26 1.1.1.16 christos * Code in any form, with the right to sublicense such rights; and
27 1.1.1.16 christos *
28 1.1.1.16 christos * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29 1.1.1.16 christos * license (with the right to sublicense), under only those claims of Intel
30 1.1.1.16 christos * patents that are infringed by the Original Intel Code, to make, use, sell,
31 1.1.1.16 christos * offer to sell, and import the Covered Code and derivative works thereof
32 1.1.1.16 christos * solely to the minimum extent necessary to exercise the above copyright
33 1.1.1.16 christos * license, and in no event shall the patent license extend to any additions
34 1.1.1.16 christos * to or modifications of the Original Intel Code. No other license or right
35 1.1.1.16 christos * is granted directly or by implication, estoppel or otherwise;
36 1.1.1.16 christos *
37 1.1.1.16 christos * The above copyright and patent license is granted only if the following
38 1.1.1.16 christos * conditions are met:
39 1.1.1.16 christos *
40 1.1.1.16 christos * 3. Conditions
41 1.1.1.16 christos *
42 1.1.1.16 christos * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43 1.1.1.16 christos * Redistribution of source code of any substantial portion of the Covered
44 1.1.1.16 christos * Code or modification with rights to further distribute source must include
45 1.1.1.16 christos * the above Copyright Notice, the above License, this list of Conditions,
46 1.1.1.16 christos * and the following Disclaimer and Export Compliance provision. In addition,
47 1.1.1.16 christos * Licensee must cause all Covered Code to which Licensee contributes to
48 1.1.1.16 christos * contain a file documenting the changes Licensee made to create that Covered
49 1.1.1.16 christos * Code and the date of any change. Licensee must include in that file the
50 1.1.1.16 christos * documentation of any changes made by any predecessor Licensee. Licensee
51 1.1.1.16 christos * must include a prominent statement that the modification is derived,
52 1.1.1.16 christos * directly or indirectly, from Original Intel Code.
53 1.1.1.16 christos *
54 1.1.1.16 christos * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55 1.1.1.16 christos * Redistribution of source code of any substantial portion of the Covered
56 1.1.1.16 christos * Code or modification without rights to further distribute source must
57 1.1.1.16 christos * include the following Disclaimer and Export Compliance provision in the
58 1.1.1.16 christos * documentation and/or other materials provided with distribution. In
59 1.1.1.16 christos * addition, Licensee may not authorize further sublicense of source of any
60 1.1.1.16 christos * portion of the Covered Code, and must include terms to the effect that the
61 1.1.1.16 christos * license from Licensee to its licensee is limited to the intellectual
62 1.1.1.16 christos * property embodied in the software Licensee provides to its licensee, and
63 1.1.1.16 christos * not to intellectual property embodied in modifications its licensee may
64 1.1.1.16 christos * make.
65 1.1.1.16 christos *
66 1.1.1.16 christos * 3.3. Redistribution of Executable. Redistribution in executable form of any
67 1.1.1.16 christos * substantial portion of the Covered Code or modification must reproduce the
68 1.1.1.16 christos * above Copyright Notice, and the following Disclaimer and Export Compliance
69 1.1.1.16 christos * provision in the documentation and/or other materials provided with the
70 1.1.1.16 christos * distribution.
71 1.1.1.16 christos *
72 1.1.1.16 christos * 3.4. Intel retains all right, title, and interest in and to the Original
73 1.1.1.16 christos * Intel Code.
74 1.1.1.16 christos *
75 1.1.1.16 christos * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76 1.1.1.16 christos * Intel shall be used in advertising or otherwise to promote the sale, use or
77 1.1.1.16 christos * other dealings in products derived from or relating to the Covered Code
78 1.1.1.16 christos * without prior written authorization from Intel.
79 1.1.1.16 christos *
80 1.1.1.16 christos * 4. Disclaimer and Export Compliance
81 1.1.1.16 christos *
82 1.1.1.16 christos * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83 1.1.1.16 christos * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84 1.1.1.16 christos * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85 1.1.1.16 christos * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86 1.1.1.16 christos * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87 1.1.1.16 christos * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88 1.1.1.16 christos * PARTICULAR PURPOSE.
89 1.1.1.16 christos *
90 1.1.1.16 christos * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91 1.1.1.16 christos * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92 1.1.1.16 christos * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93 1.1.1.16 christos * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94 1.1.1.16 christos * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95 1.1.1.16 christos * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96 1.1.1.16 christos * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97 1.1.1.16 christos * LIMITED REMEDY.
98 1.1.1.16 christos *
99 1.1.1.16 christos * 4.3. Licensee shall not export, either directly or indirectly, any of this
100 1.1.1.16 christos * software or system incorporating such software without first obtaining any
101 1.1.1.16 christos * required license or other approval from the U. S. Department of Commerce or
102 1.1.1.16 christos * any other agency or department of the United States Government. In the
103 1.1.1.16 christos * event Licensee exports any such software from the United States or
104 1.1.1.16 christos * re-exports any such software from a foreign destination, Licensee shall
105 1.1.1.16 christos * ensure that the distribution and export/re-export of the software is in
106 1.1.1.16 christos * compliance with all laws, regulations, orders, or other restrictions of the
107 1.1.1.16 christos * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108 1.1.1.16 christos * any of its subsidiaries will export/re-export any technical data, process,
109 1.1.1.16 christos * software, or service, directly or indirectly, to any country for which the
110 1.1.1.16 christos * United States government or any agency thereof requires an export license,
111 1.1.1.16 christos * other governmental approval, or letter of assurance, without first obtaining
112 1.1.1.16 christos * such license, approval or letter.
113 1.1.1.16 christos *
114 1.1.1.16 christos *****************************************************************************
115 1.1.1.16 christos *
116 1.1.1.16 christos * Alternatively, you may choose to be licensed under the terms of the
117 1.1.1.16 christos * following license:
118 1.1.1.16 christos *
119 1.1 christos * Redistribution and use in source and binary forms, with or without
120 1.1 christos * modification, are permitted provided that the following conditions
121 1.1 christos * are met:
122 1.1 christos * 1. Redistributions of source code must retain the above copyright
123 1.1 christos * notice, this list of conditions, and the following disclaimer,
124 1.1 christos * without modification.
125 1.1 christos * 2. Redistributions in binary form must reproduce at minimum a disclaimer
126 1.1 christos * substantially similar to the "NO WARRANTY" disclaimer below
127 1.1 christos * ("Disclaimer") and any redistribution must be conditioned upon
128 1.1 christos * including a substantially similar Disclaimer requirement for further
129 1.1 christos * binary redistribution.
130 1.1 christos * 3. Neither the names of the above-listed copyright holders nor the names
131 1.1 christos * of any contributors may be used to endorse or promote products derived
132 1.1 christos * from this software without specific prior written permission.
133 1.1 christos *
134 1.1 christos * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
135 1.1 christos * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
136 1.1.1.12 christos * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
137 1.1 christos * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
138 1.1.1.16 christos * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
139 1.1.1.16 christos * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
140 1.1.1.16 christos * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
141 1.1.1.16 christos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
142 1.1.1.16 christos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
143 1.1.1.16 christos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
144 1.1.1.16 christos * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
145 1.1.1.16 christos *
146 1.1.1.16 christos * Alternatively, you may choose to be licensed under the terms of the
147 1.1.1.16 christos * GNU General Public License ("GPL") version 2 as published by the Free
148 1.1.1.16 christos * Software Foundation.
149 1.1.1.16 christos *
150 1.1.1.16 christos *****************************************************************************/
151 1.1 christos
152 1.1 christos #include "aslcompiler.h"
153 1.1 christos
154 1.1 christos #define _COMPONENT ASL_PREPROCESSOR
155 1.1 christos ACPI_MODULE_NAME ("prutils")
156 1.1 christos
157 1.1 christos
158 1.1 christos /******************************************************************************
159 1.1 christos *
160 1.1 christos * FUNCTION: PrGetNextToken
161 1.1 christos *
162 1.1 christos * PARAMETERS: Buffer - Current line buffer
163 1.1 christos * MatchString - String with valid token delimiters
164 1.1 christos * Next - Set to next possible token in buffer
165 1.1 christos *
166 1.1 christos * RETURN: Next token (null-terminated). Modifies the input line.
167 1.1 christos * Remainder of line is stored in *Next.
168 1.1 christos *
169 1.1 christos * DESCRIPTION: Local implementation of strtok() with local storage for the
170 1.1 christos * next pointer. Not only thread-safe, but allows multiple
171 1.1 christos * parsing of substrings such as expressions.
172 1.1 christos *
173 1.1 christos *****************************************************************************/
174 1.1 christos
175 1.1 christos char *
176 1.1 christos PrGetNextToken (
177 1.1 christos char *Buffer,
178 1.1 christos char *MatchString,
179 1.1 christos char **Next)
180 1.1 christos {
181 1.1 christos char *TokenStart;
182 1.1 christos
183 1.1 christos
184 1.1 christos if (!Buffer)
185 1.1 christos {
186 1.1 christos /* Use Next if it is valid */
187 1.1 christos
188 1.1 christos Buffer = *Next;
189 1.1 christos if (!(*Next))
190 1.1 christos {
191 1.1 christos return (NULL);
192 1.1 christos }
193 1.1 christos }
194 1.1 christos
195 1.1 christos /* Skip any leading delimiters */
196 1.1 christos
197 1.1 christos while (*Buffer)
198 1.1 christos {
199 1.1 christos if (strchr (MatchString, *Buffer))
200 1.1 christos {
201 1.1 christos Buffer++;
202 1.1 christos }
203 1.1 christos else
204 1.1 christos {
205 1.1 christos break;
206 1.1 christos }
207 1.1 christos }
208 1.1 christos
209 1.1 christos /* Anything left on the line? */
210 1.1 christos
211 1.1 christos if (!(*Buffer))
212 1.1 christos {
213 1.1 christos *Next = NULL;
214 1.1 christos return (NULL);
215 1.1 christos }
216 1.1 christos
217 1.1 christos TokenStart = Buffer;
218 1.1 christos
219 1.1 christos /* Find the end of this token */
220 1.1 christos
221 1.1 christos while (*Buffer)
222 1.1 christos {
223 1.1 christos if (strchr (MatchString, *Buffer))
224 1.1 christos {
225 1.1 christos *Buffer = 0;
226 1.1 christos *Next = Buffer+1;
227 1.1 christos if (!**Next)
228 1.1 christos {
229 1.1 christos *Next = NULL;
230 1.1 christos }
231 1.1.1.5 christos
232 1.1 christos return (TokenStart);
233 1.1 christos }
234 1.1.1.5 christos
235 1.1 christos Buffer++;
236 1.1 christos }
237 1.1 christos
238 1.1 christos *Next = NULL;
239 1.1 christos return (TokenStart);
240 1.1 christos }
241 1.1 christos
242 1.1 christos
243 1.1 christos /*******************************************************************************
244 1.1 christos *
245 1.1 christos * FUNCTION: PrError
246 1.1 christos *
247 1.1 christos * PARAMETERS: Level - Seriousness (Warning/error, etc.)
248 1.1 christos * MessageId - Index into global message buffer
249 1.1 christos * Column - Column in current line
250 1.1 christos *
251 1.1 christos * RETURN: None
252 1.1 christos *
253 1.1 christos * DESCRIPTION: Preprocessor error reporting. Front end to AslCommonError2
254 1.1 christos *
255 1.1 christos ******************************************************************************/
256 1.1 christos
257 1.1 christos void
258 1.1 christos PrError (
259 1.1 christos UINT8 Level,
260 1.1.1.2 christos UINT16 MessageId,
261 1.1 christos UINT32 Column)
262 1.1 christos {
263 1.1 christos #if 0
264 1.1.1.9 christos AcpiOsPrintf ("%s (%u) : %s", AslGbl_Files[ASL_FILE_INPUT].Filename,
265 1.1.1.9 christos AslGbl_CurrentLineNumber, AslGbl_CurrentLineBuffer);
266 1.1 christos #endif
267 1.1 christos
268 1.1 christos
269 1.1 christos if (Column > 120)
270 1.1 christos {
271 1.1 christos Column = 0;
272 1.1 christos }
273 1.1 christos
274 1.1 christos /* TBD: Need Logical line number? */
275 1.1 christos
276 1.1 christos AslCommonError2 (Level, MessageId,
277 1.1.1.9 christos AslGbl_CurrentLineNumber, Column,
278 1.1.1.9 christos AslGbl_CurrentLineBuffer,
279 1.1.1.9 christos AslGbl_Files[ASL_FILE_INPUT].Filename, "Preprocessor");
280 1.1 christos
281 1.1.1.9 christos AslGbl_PreprocessorError = TRUE;
282 1.1 christos }
283 1.1 christos
284 1.1 christos
285 1.1 christos /*******************************************************************************
286 1.1 christos *
287 1.1.1.14 christos * FUNCTION: PrReplaceResizeSubstring
288 1.1.1.14 christos *
289 1.1.1.14 christos * PARAMETERS: Args - Struct containing name, offset & usecount
290 1.1.1.14 christos * Diff1 - Difference in lengths when new < old
291 1.1.1.14 christos * Diff2 - Difference in lengths when new > old
292 1.1.1.14 christos * i - The curr. no. of iteration of replacement
293 1.1.1.14 christos * Token - Substring that replaces Args->Name
294 1.1.1.14 christos *
295 1.1.1.14 christos * RETURN: None
296 1.1.1.14 christos *
297 1.1.1.14 christos * DESCRIPTION: Advanced substring replacement in a string using resized buffer.
298 1.1.1.14 christos *
299 1.1.1.14 christos ******************************************************************************/
300 1.1.1.14 christos
301 1.1.1.14 christos void
302 1.1.1.14 christos PrReplaceResizeSubstring(
303 1.1.1.14 christos PR_MACRO_ARG *Args,
304 1.1.1.14 christos UINT32 Diff1,
305 1.1.1.14 christos UINT32 Diff2,
306 1.1.1.14 christos UINT32 i,
307 1.1.1.14 christos char *Token)
308 1.1.1.14 christos {
309 1.1.1.14 christos UINT32 b, PrevOffset;
310 1.1.1.14 christos char *temp;
311 1.1.1.14 christos char macro_sep[64];
312 1.1.1.14 christos
313 1.1.1.14 christos
314 1.1.1.14 christos AslGbl_MacroTokenReplaceBuffer = (char *) realloc (AslGbl_MacroTokenReplaceBuffer,
315 1.1.1.14 christos (2 * (strlen (AslGbl_MacroTokenBuffer))));
316 1.1.1.14 christos
317 1.1.1.14 christos strcpy (macro_sep, "~,() {}!*/%+-<>=&^|\"\t\n");
318 1.1.1.14 christos
319 1.1.1.14 christos /*
320 1.1.1.14 christos * When the replacement argument (during invocation) length
321 1.1.1.14 christos * < replaced parameter (in the macro function definition
322 1.1.1.14 christos * and its expansion) length
323 1.1.1.14 christos */
324 1.1.1.14 christos if (Diff1 != 0)
325 1.1.1.14 christos {
326 1.1.1.14 christos /*
327 1.1.1.14 christos * We save the offset value to reset it after replacing each
328 1.1.1.14 christos * instance of each arg and setting the offset value to
329 1.1.1.14 christos * the start of the arg to be replaced since it changes
330 1.1.1.14 christos * with each iteration when arg length != token length
331 1.1.1.14 christos */
332 1.1.1.14 christos PrevOffset = Args->Offset[i];
333 1.1.1.14 christos temp = strstr (AslGbl_MacroTokenBuffer, Args->Name);
334 1.1.1.15 christos if (temp == NULL)
335 1.1.1.15 christos {
336 1.1.1.15 christos return;
337 1.1.1.15 christos }
338 1.1.1.14 christos
339 1.1.1.14 christos ResetHere1:
340 1.1.1.14 christos temp = strstr (temp, Args->Name);
341 1.1.1.15 christos if (temp == NULL)
342 1.1.1.15 christos {
343 1.1.1.15 christos return;
344 1.1.1.15 christos }
345 1.1.1.14 christos Args->Offset[i] = strlen (AslGbl_MacroTokenBuffer) -
346 1.1.1.14 christos strlen (temp);
347 1.1.1.14 christos if (Args->Offset[i] == 0)
348 1.1.1.14 christos {
349 1.1.1.14 christos goto JumpHere1;
350 1.1.1.14 christos }
351 1.1.1.14 christos if ((strchr (macro_sep, AslGbl_MacroTokenBuffer[(Args->Offset[i] - 1)])) &&
352 1.1.1.14 christos (strchr (macro_sep, AslGbl_MacroTokenBuffer[(Args->Offset[i] + strlen (Args->Name))])))
353 1.1.1.14 christos {
354 1.1.1.14 christos Args->Offset[i] += 0;
355 1.1.1.14 christos }
356 1.1.1.14 christos else
357 1.1.1.14 christos {
358 1.1.1.14 christos temp += strlen (Args->Name);
359 1.1.1.14 christos goto ResetHere1;
360 1.1.1.14 christos }
361 1.1.1.14 christos
362 1.1.1.14 christos /*
363 1.1.1.14 christos * For now, we simply set the extra char positions (generated
364 1.1.1.14 christos * due to longer name replaced by shorter name) to whitespace
365 1.1.1.14 christos * chars so it will be ignored during compilation
366 1.1.1.14 christos */
367 1.1.1.14 christos JumpHere1:
368 1.1.1.14 christos b = strlen (Token) + Args->Offset[i];
369 1.1.1.14 christos memset (&AslGbl_MacroTokenBuffer[b], ' ', Diff1);
370 1.1.1.14 christos
371 1.1.1.14 christos # if 0
372 1.1.1.14 christos
373 1.1.1.14 christos /* Work in progress as of 03/08/2023 - experimental 'if' block
374 1.1.1.14 christos * to test code for removing extra whitespaces from the macro
375 1.1.1.14 christos * replacement when replacement arg < replaced param
376 1.1.1.14 christos */
377 1.1.1.14 christos char Buff[8192];
378 1.1.1.14 christos /* char* Replace; */
379 1.1.1.14 christos /* Replace = Buff; */
380 1.1.1.14 christos
381 1.1.1.14 christos for (j = 0; j < strlen (AslGbl_MacroTokenBuffer); j++)
382 1.1.1.14 christos {
383 1.1.1.14 christos Buff[j] = AslGbl_MacroTokenBuffer[j];
384 1.1.1.14 christos }
385 1.1.1.14 christos Buff[strlen (AslGbl_MacroTokenBuffer)] = '\0';
386 1.1.1.15 christos /* fprintf(stderr, "Buff: %s\n", Buff); */
387 1.1.1.14 christos
388 1.1.1.14 christos UINT32 len = strlen (Buff);
389 1.1.1.14 christos
390 1.1.1.14 christos for (j = 0; j < len; j++)
391 1.1.1.14 christos {
392 1.1.1.14 christos if (Buff[0] == ' ')
393 1.1.1.14 christos {
394 1.1.1.14 christos for (j = 0; j < (len - 1); j++)
395 1.1.1.14 christos {
396 1.1.1.14 christos Buff[j] = Buff[j + 1];
397 1.1.1.14 christos }
398 1.1.1.14 christos Buff[j] = '\0';
399 1.1.1.14 christos len--;
400 1.1.1.14 christos j = -1;
401 1.1.1.14 christos continue;
402 1.1.1.14 christos }
403 1.1.1.14 christos
404 1.1.1.14 christos if (Buff[j] == ' ' && Buff[j + 1] == ' ')
405 1.1.1.14 christos {
406 1.1.1.14 christos for (k = 0; k < (len - 1); k++)
407 1.1.1.14 christos {
408 1.1.1.14 christos Buff[j] = Buff[j + 1];
409 1.1.1.14 christos }
410 1.1.1.14 christos Buff[j] = '\0';
411 1.1.1.14 christos len--;
412 1.1.1.14 christos j--;
413 1.1.1.14 christos }
414 1.1.1.14 christos }
415 1.1.1.15 christos /* fprintf(stderr, "Buff: %s\n", Buff); */
416 1.1.1.14 christos
417 1.1.1.14 christos for (k = 0; k < strlen (Buff); k++)
418 1.1.1.14 christos {
419 1.1.1.14 christos AslGbl_MacroTokenBuffer[k] = Buff[k];
420 1.1.1.14 christos }
421 1.1.1.14 christos #endif
422 1.1.1.14 christos
423 1.1.1.14 christos PrReplaceData (
424 1.1.1.14 christos &AslGbl_MacroTokenBuffer[Args->Offset[i]],
425 1.1.1.14 christos strlen (Token), Token, strlen (Token));
426 1.1.1.14 christos
427 1.1.1.14 christos temp = NULL;
428 1.1.1.14 christos Args->Offset[i] = PrevOffset;
429 1.1.1.14 christos }
430 1.1.1.14 christos
431 1.1.1.14 christos /*
432 1.1.1.14 christos * When the replacement argument (during invocation) length
433 1.1.1.14 christos * > replaced parameter (in the macro function definition
434 1.1.1.14 christos * and its expansion) length
435 1.1.1.14 christos */
436 1.1.1.14 christos else if (Diff2 != 0)
437 1.1.1.14 christos {
438 1.1.1.14 christos /* Doing the same thing with offset value as for prev case */
439 1.1.1.14 christos
440 1.1.1.14 christos PrevOffset = Args->Offset[i];
441 1.1.1.14 christos temp = strstr (AslGbl_MacroTokenBuffer, Args->Name);
442 1.1.1.15 christos if (temp == NULL)
443 1.1.1.15 christos {
444 1.1.1.15 christos return;
445 1.1.1.15 christos }
446 1.1.1.14 christos
447 1.1.1.14 christos ResetHere2:
448 1.1.1.14 christos temp = strstr (temp, Args->Name);
449 1.1.1.15 christos if (temp == NULL)
450 1.1.1.15 christos {
451 1.1.1.15 christos return;
452 1.1.1.15 christos }
453 1.1.1.14 christos Args->Offset[i] = strlen (AslGbl_MacroTokenBuffer) -
454 1.1.1.14 christos strlen (temp);
455 1.1.1.14 christos if (Args->Offset[i] == 0)
456 1.1.1.14 christos {
457 1.1.1.14 christos goto JumpHere2;
458 1.1.1.14 christos }
459 1.1.1.14 christos if ((strchr (macro_sep, AslGbl_MacroTokenBuffer[(Args->Offset[i] - 1)])) &&
460 1.1.1.14 christos (strchr (macro_sep, AslGbl_MacroTokenBuffer[(Args->Offset[i] + strlen (Args->Name))])))
461 1.1.1.14 christos {
462 1.1.1.14 christos Args->Offset[i] += 0;
463 1.1.1.14 christos }
464 1.1.1.14 christos else
465 1.1.1.14 christos {
466 1.1.1.14 christos temp+= strlen (Args->Name);
467 1.1.1.14 christos goto ResetHere2;
468 1.1.1.14 christos }
469 1.1.1.14 christos
470 1.1.1.14 christos /*
471 1.1.1.14 christos * We will need to allocate some extra space in our buffer to
472 1.1.1.14 christos * accommodate the increase in the replacement string length
473 1.1.1.14 christos * over the shorter outgoing arg string and do the replacement
474 1.1.1.14 christos * at the correct offset value which is resetted every iteration
475 1.1.1.14 christos */
476 1.1.1.14 christos JumpHere2:
477 1.1.1.17 christos memcpy (AslGbl_MacroTokenReplaceBuffer, AslGbl_MacroTokenBuffer, Args->Offset[i]);
478 1.1.1.14 christos strcat (AslGbl_MacroTokenReplaceBuffer, Token);
479 1.1.1.14 christos strcat (AslGbl_MacroTokenReplaceBuffer, (AslGbl_MacroTokenBuffer +
480 1.1.1.14 christos (Args->Offset[i] + strlen (Args->Name))));
481 1.1.1.14 christos
482 1.1.1.14 christos strcpy (AslGbl_MacroTokenBuffer, AslGbl_MacroTokenReplaceBuffer);
483 1.1.1.14 christos
484 1.1.1.14 christos temp = NULL;
485 1.1.1.14 christos Args->Offset[i] = PrevOffset;
486 1.1.1.14 christos }
487 1.1.1.14 christos
488 1.1.1.14 christos /*
489 1.1.1.14 christos * When the replacement argument (during invocation) length =
490 1.1.1.14 christos * replaced parameter (in the macro function definition and
491 1.1.1.14 christos * its expansion) length
492 1.1.1.14 christos */
493 1.1.1.14 christos else
494 1.1.1.14 christos {
495 1.1.1.14 christos
496 1.1.1.14 christos /*
497 1.1.1.14 christos * We still need to reset the offset for each iteration even when
498 1.1.1.14 christos * arg and param lengths are same since any macro func invocation
499 1.1.1.14 christos * could use various cases for each separate arg-param pair
500 1.1.1.14 christos */
501 1.1.1.14 christos PrevOffset = Args->Offset[i];
502 1.1.1.14 christos temp = strstr (AslGbl_MacroTokenBuffer, Args->Name);
503 1.1.1.15 christos if (temp == NULL)
504 1.1.1.15 christos {
505 1.1.1.15 christos return;
506 1.1.1.15 christos }
507 1.1.1.14 christos
508 1.1.1.14 christos ResetHere3:
509 1.1.1.14 christos temp = strstr (temp, Args->Name);
510 1.1.1.15 christos if (temp == NULL)
511 1.1.1.15 christos {
512 1.1.1.15 christos return;
513 1.1.1.15 christos }
514 1.1.1.14 christos Args->Offset[i] = strlen (AslGbl_MacroTokenBuffer) -
515 1.1.1.14 christos strlen (temp);
516 1.1.1.14 christos if (Args->Offset[i] == 0)
517 1.1.1.14 christos {
518 1.1.1.14 christos goto JumpHere3;
519 1.1.1.14 christos }
520 1.1.1.14 christos if ((strchr (macro_sep, AslGbl_MacroTokenBuffer[(Args->Offset[i] - 1)])) &&
521 1.1.1.14 christos (strchr (macro_sep, AslGbl_MacroTokenBuffer[(Args->Offset[i] + strlen (Args->Name))])))
522 1.1.1.14 christos {
523 1.1.1.14 christos Args->Offset[i] += 0;
524 1.1.1.14 christos }
525 1.1.1.14 christos else
526 1.1.1.14 christos {
527 1.1.1.14 christos temp += strlen (Args->Name);
528 1.1.1.14 christos goto ResetHere3;
529 1.1.1.14 christos }
530 1.1.1.14 christos
531 1.1.1.14 christos JumpHere3:
532 1.1.1.14 christos PrReplaceData (
533 1.1.1.14 christos &AslGbl_MacroTokenBuffer[Args->Offset[i]],
534 1.1.1.14 christos strlen (Args->Name), Token, strlen (Token));
535 1.1.1.14 christos temp = NULL;
536 1.1.1.14 christos Args->Offset[i] = PrevOffset;
537 1.1.1.14 christos }
538 1.1.1.14 christos }
539 1.1.1.14 christos
540 1.1.1.14 christos
541 1.1.1.14 christos /*******************************************************************************
542 1.1.1.14 christos *
543 1.1 christos * FUNCTION: PrReplaceData
544 1.1 christos *
545 1.1 christos * PARAMETERS: Buffer - Original(target) buffer pointer
546 1.1 christos * LengthToRemove - Length to be removed from target buffer
547 1.1 christos * BufferToAdd - Data to be inserted into target buffer
548 1.1 christos * LengthToAdd - Length of BufferToAdd
549 1.1 christos *
550 1.1.1.14 christos * RETURN: Pointer to where the buffer is replaced with data
551 1.1 christos *
552 1.1 christos * DESCRIPTION: Generic buffer data replacement.
553 1.1 christos *
554 1.1 christos ******************************************************************************/
555 1.1 christos
556 1.1.1.14 christos char *
557 1.1 christos PrReplaceData (
558 1.1 christos char *Buffer,
559 1.1 christos UINT32 LengthToRemove,
560 1.1 christos char *BufferToAdd,
561 1.1 christos UINT32 LengthToAdd)
562 1.1 christos {
563 1.1 christos UINT32 BufferLength;
564 1.1 christos
565 1.1 christos
566 1.1 christos /* Buffer is a string, so the length must include the terminating zero */
567 1.1 christos
568 1.1 christos BufferLength = strlen (Buffer) + 1;
569 1.1 christos
570 1.1 christos if (LengthToRemove != LengthToAdd)
571 1.1 christos {
572 1.1 christos /*
573 1.1 christos * Move some of the existing data
574 1.1 christos * 1) If adding more bytes than removing, make room for the new data
575 1.1 christos * 2) if removing more bytes than adding, delete the extra space
576 1.1 christos */
577 1.1 christos if (LengthToRemove > 0)
578 1.1 christos {
579 1.1 christos memmove ((Buffer + LengthToAdd), (Buffer + LengthToRemove),
580 1.1 christos (BufferLength - LengthToRemove));
581 1.1 christos }
582 1.1 christos }
583 1.1 christos
584 1.1.1.14 christos
585 1.1 christos /* Now we can move in the new data */
586 1.1 christos
587 1.1 christos if (LengthToAdd > 0)
588 1.1 christos {
589 1.1 christos memmove (Buffer, BufferToAdd, LengthToAdd);
590 1.1 christos }
591 1.1.1.14 christos return (Buffer + LengthToAdd);
592 1.1 christos }
593 1.1 christos
594 1.1 christos
595 1.1 christos /*******************************************************************************
596 1.1 christos *
597 1.1 christos * FUNCTION: PrOpenIncludeFile
598 1.1 christos *
599 1.1 christos * PARAMETERS: Filename - Filename or pathname for include file
600 1.1 christos *
601 1.1 christos * RETURN: None.
602 1.1 christos *
603 1.1 christos * DESCRIPTION: Open an include file and push it on the input file stack.
604 1.1 christos *
605 1.1 christos ******************************************************************************/
606 1.1 christos
607 1.1.1.4 christos FILE *
608 1.1 christos PrOpenIncludeFile (
609 1.1.1.4 christos char *Filename,
610 1.1.1.4 christos char *OpenMode,
611 1.1.1.4 christos char **FullPathname)
612 1.1 christos {
613 1.1 christos FILE *IncludeFile;
614 1.1 christos ASL_INCLUDE_DIR *NextDir;
615 1.1 christos
616 1.1 christos
617 1.1 christos /* Start the actual include file on the next line */
618 1.1 christos
619 1.1.1.9 christos AslGbl_CurrentLineOffset++;
620 1.1 christos
621 1.1 christos /* Attempt to open the include file */
622 1.1 christos /* If the file specifies an absolute path, just open it */
623 1.1 christos
624 1.1 christos if ((Filename[0] == '/') ||
625 1.1 christos (Filename[0] == '\\') ||
626 1.1 christos (Filename[1] == ':'))
627 1.1 christos {
628 1.1.1.4 christos IncludeFile = PrOpenIncludeWithPrefix (
629 1.1.1.4 christos "", Filename, OpenMode, FullPathname);
630 1.1 christos if (!IncludeFile)
631 1.1 christos {
632 1.1 christos goto ErrorExit;
633 1.1 christos }
634 1.1.1.4 christos return (IncludeFile);
635 1.1 christos }
636 1.1 christos
637 1.1 christos /*
638 1.1 christos * The include filename is not an absolute path.
639 1.1 christos *
640 1.1 christos * First, search for the file within the "local" directory -- meaning
641 1.1 christos * the same directory that contains the source file.
642 1.1 christos *
643 1.1 christos * Construct the file pathname from the global directory name.
644 1.1 christos */
645 1.1.1.4 christos IncludeFile = PrOpenIncludeWithPrefix (
646 1.1.1.9 christos AslGbl_DirectoryPath, Filename, OpenMode, FullPathname);
647 1.1 christos if (IncludeFile)
648 1.1 christos {
649 1.1.1.4 christos return (IncludeFile);
650 1.1 christos }
651 1.1 christos
652 1.1 christos /*
653 1.1 christos * Second, search for the file within the (possibly multiple)
654 1.1 christos * directories specified by the -I option on the command line.
655 1.1 christos */
656 1.1.1.9 christos NextDir = AslGbl_IncludeDirList;
657 1.1 christos while (NextDir)
658 1.1 christos {
659 1.1.1.4 christos IncludeFile = PrOpenIncludeWithPrefix (
660 1.1.1.4 christos NextDir->Dir, Filename, OpenMode, FullPathname);
661 1.1 christos if (IncludeFile)
662 1.1 christos {
663 1.1.1.4 christos return (IncludeFile);
664 1.1 christos }
665 1.1 christos
666 1.1 christos NextDir = NextDir->Next;
667 1.1 christos }
668 1.1 christos
669 1.1 christos /* We could not open the include file after trying very hard */
670 1.1 christos
671 1.1 christos ErrorExit:
672 1.1.1.9 christos sprintf (AslGbl_MainTokenBuffer, "%s, %s", Filename, strerror (errno));
673 1.1 christos PrError (ASL_ERROR, ASL_MSG_INCLUDE_FILE_OPEN, 0);
674 1.1.1.4 christos return (NULL);
675 1.1 christos }
676 1.1 christos
677 1.1 christos
678 1.1 christos /*******************************************************************************
679 1.1 christos *
680 1.1 christos * FUNCTION: FlOpenIncludeWithPrefix
681 1.1 christos *
682 1.1 christos * PARAMETERS: PrefixDir - Prefix directory pathname. Can be a zero
683 1.1 christos * length string.
684 1.1 christos * Filename - The include filename from the source ASL.
685 1.1 christos *
686 1.1 christos * RETURN: Valid file descriptor if successful. Null otherwise.
687 1.1 christos *
688 1.1 christos * DESCRIPTION: Open an include file and push it on the input file stack.
689 1.1 christos *
690 1.1 christos ******************************************************************************/
691 1.1 christos
692 1.1 christos FILE *
693 1.1 christos PrOpenIncludeWithPrefix (
694 1.1 christos char *PrefixDir,
695 1.1.1.4 christos char *Filename,
696 1.1.1.4 christos char *OpenMode,
697 1.1.1.4 christos char **FullPathname)
698 1.1 christos {
699 1.1 christos FILE *IncludeFile;
700 1.1 christos char *Pathname;
701 1.1 christos
702 1.1 christos
703 1.1 christos /* Build the full pathname to the file */
704 1.1 christos
705 1.1 christos Pathname = FlMergePathnames (PrefixDir, Filename);
706 1.1 christos
707 1.1 christos DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
708 1.1 christos "Include: Opening file - \"%s\"\n",
709 1.1.1.9 christos AslGbl_CurrentLineNumber, Pathname);
710 1.1 christos
711 1.1 christos /* Attempt to open the file, push if successful */
712 1.1 christos
713 1.1.1.4 christos IncludeFile = fopen (Pathname, OpenMode);
714 1.1 christos if (!IncludeFile)
715 1.1 christos {
716 1.1 christos return (NULL);
717 1.1 christos }
718 1.1 christos
719 1.1 christos /* Push the include file on the open input file stack */
720 1.1 christos
721 1.1 christos PrPushInputFileStack (IncludeFile, Pathname);
722 1.1.1.4 christos *FullPathname = Pathname;
723 1.1 christos return (IncludeFile);
724 1.1 christos }
725 1.1 christos
726 1.1 christos
727 1.1 christos /*******************************************************************************
728 1.1 christos *
729 1.1 christos * FUNCTION: AslPushInputFileStack
730 1.1 christos *
731 1.1 christos * PARAMETERS: InputFile - Open file pointer
732 1.1 christos * Filename - Name of the file
733 1.1 christos *
734 1.1 christos * RETURN: None
735 1.1 christos *
736 1.1 christos * DESCRIPTION: Push the InputFile onto the file stack, and point the parser
737 1.1 christos * to this file. Called when an include file is successfully
738 1.1 christos * opened.
739 1.1 christos *
740 1.1 christos ******************************************************************************/
741 1.1 christos
742 1.1 christos void
743 1.1 christos PrPushInputFileStack (
744 1.1 christos FILE *InputFile,
745 1.1 christos char *Filename)
746 1.1 christos {
747 1.1 christos PR_FILE_NODE *Fnode;
748 1.1 christos
749 1.1 christos
750 1.1.1.9 christos AslGbl_HasIncludeFiles = TRUE;
751 1.1.1.4 christos
752 1.1 christos /* Save the current state in an Fnode */
753 1.1 christos
754 1.1 christos Fnode = UtLocalCalloc (sizeof (PR_FILE_NODE));
755 1.1 christos
756 1.1.1.9 christos Fnode->File = AslGbl_Files[ASL_FILE_INPUT].Handle;
757 1.1.1.9 christos Fnode->Next = AslGbl_InputFileList;
758 1.1.1.9 christos Fnode->Filename = AslGbl_Files[ASL_FILE_INPUT].Filename;
759 1.1.1.9 christos Fnode->CurrentLineNumber = AslGbl_CurrentLineNumber;
760 1.1 christos
761 1.1 christos /* Push it on the stack */
762 1.1 christos
763 1.1.1.9 christos AslGbl_InputFileList = Fnode;
764 1.1 christos
765 1.1 christos DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
766 1.1 christos "Push InputFile Stack: handle %p\n\n",
767 1.1.1.9 christos AslGbl_CurrentLineNumber, InputFile);
768 1.1 christos
769 1.1 christos /* Reset the global line count and filename */
770 1.1 christos
771 1.1.1.9 christos AslGbl_Files[ASL_FILE_INPUT].Filename =
772 1.1.1.7 christos UtLocalCacheCalloc (strlen (Filename) + 1);
773 1.1.1.9 christos strcpy (AslGbl_Files[ASL_FILE_INPUT].Filename, Filename);
774 1.1.1.2 christos
775 1.1.1.9 christos AslGbl_Files[ASL_FILE_INPUT].Handle = InputFile;
776 1.1.1.9 christos AslGbl_CurrentLineNumber = 1;
777 1.1 christos
778 1.1 christos /* Emit a new #line directive for the include file */
779 1.1 christos
780 1.1.1.2 christos FlPrintFile (ASL_FILE_PREPROCESSOR, "#line %u \"%s\"\n", 1, Filename);
781 1.1 christos }
782 1.1 christos
783 1.1 christos
784 1.1 christos /*******************************************************************************
785 1.1 christos *
786 1.1 christos * FUNCTION: AslPopInputFileStack
787 1.1 christos *
788 1.1 christos * PARAMETERS: None
789 1.1 christos *
790 1.1 christos * RETURN: 0 if a node was popped, -1 otherwise
791 1.1 christos *
792 1.1 christos * DESCRIPTION: Pop the top of the input file stack and point the parser to
793 1.1 christos * the saved parse buffer contained in the fnode. Also, set the
794 1.1 christos * global line counters to the saved values. This function is
795 1.1 christos * called when an include file reaches EOF.
796 1.1 christos *
797 1.1 christos ******************************************************************************/
798 1.1 christos
799 1.1 christos BOOLEAN
800 1.1 christos PrPopInputFileStack (
801 1.1 christos void)
802 1.1 christos {
803 1.1 christos PR_FILE_NODE *Fnode;
804 1.1 christos
805 1.1 christos
806 1.1.1.9 christos Fnode = AslGbl_InputFileList;
807 1.1 christos DbgPrint (ASL_PARSE_OUTPUT, "\n" PR_PREFIX_ID
808 1.1 christos "Pop InputFile Stack, Fnode %p\n\n",
809 1.1.1.9 christos AslGbl_CurrentLineNumber, Fnode);
810 1.1 christos
811 1.1 christos if (!Fnode)
812 1.1 christos {
813 1.1 christos return (FALSE);
814 1.1 christos }
815 1.1 christos
816 1.1 christos /* Close the current include file */
817 1.1 christos
818 1.1.1.9 christos fclose (AslGbl_Files[ASL_FILE_INPUT].Handle);
819 1.1 christos
820 1.1 christos /* Update the top-of-stack */
821 1.1 christos
822 1.1.1.9 christos AslGbl_InputFileList = Fnode->Next;
823 1.1 christos
824 1.1 christos /* Reset global line counter and filename */
825 1.1 christos
826 1.1.1.9 christos AslGbl_Files[ASL_FILE_INPUT].Filename = Fnode->Filename;
827 1.1.1.9 christos AslGbl_Files[ASL_FILE_INPUT].Handle = Fnode->File;
828 1.1.1.9 christos AslGbl_CurrentLineNumber = Fnode->CurrentLineNumber;
829 1.1 christos
830 1.1 christos /* Emit a new #line directive after the include file */
831 1.1 christos
832 1.1 christos FlPrintFile (ASL_FILE_PREPROCESSOR, "#line %u \"%s\"\n",
833 1.1.1.9 christos AslGbl_CurrentLineNumber, Fnode->Filename);
834 1.1 christos
835 1.1 christos /* All done with this node */
836 1.1 christos
837 1.1 christos ACPI_FREE (Fnode);
838 1.1 christos return (TRUE);
839 1.1 christos }
840