prutils.c revision 1.16.6.1 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.16.6.1 perseant /******************************************************************************
8 1.16.6.1 perseant *
9 1.16.6.1 perseant * 1. Copyright Notice
10 1.16.6.1 perseant *
11 1.16.6.1 perseant * Some or all of this work - Copyright (c) 1999 - 2024, Intel Corp.
12 1.1 christos * All rights reserved.
13 1.1 christos *
14 1.16.6.1 perseant * 2. License
15 1.16.6.1 perseant *
16 1.16.6.1 perseant * 2.1. This is your license from Intel Corp. under its intellectual property
17 1.16.6.1 perseant * rights. You may have additional license terms from the party that provided
18 1.16.6.1 perseant * you this software, covering your right to use that party's intellectual
19 1.16.6.1 perseant * property rights.
20 1.16.6.1 perseant *
21 1.16.6.1 perseant * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22 1.16.6.1 perseant * copy of the source code appearing in this file ("Covered Code") an
23 1.16.6.1 perseant * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24 1.16.6.1 perseant * base code distributed originally by Intel ("Original Intel Code") to copy,
25 1.16.6.1 perseant * make derivatives, distribute, use and display any portion of the Covered
26 1.16.6.1 perseant * Code in any form, with the right to sublicense such rights; and
27 1.16.6.1 perseant *
28 1.16.6.1 perseant * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29 1.16.6.1 perseant * license (with the right to sublicense), under only those claims of Intel
30 1.16.6.1 perseant * patents that are infringed by the Original Intel Code, to make, use, sell,
31 1.16.6.1 perseant * offer to sell, and import the Covered Code and derivative works thereof
32 1.16.6.1 perseant * solely to the minimum extent necessary to exercise the above copyright
33 1.16.6.1 perseant * license, and in no event shall the patent license extend to any additions
34 1.16.6.1 perseant * to or modifications of the Original Intel Code. No other license or right
35 1.16.6.1 perseant * is granted directly or by implication, estoppel or otherwise;
36 1.16.6.1 perseant *
37 1.16.6.1 perseant * The above copyright and patent license is granted only if the following
38 1.16.6.1 perseant * conditions are met:
39 1.16.6.1 perseant *
40 1.16.6.1 perseant * 3. Conditions
41 1.16.6.1 perseant *
42 1.16.6.1 perseant * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43 1.16.6.1 perseant * Redistribution of source code of any substantial portion of the Covered
44 1.16.6.1 perseant * Code or modification with rights to further distribute source must include
45 1.16.6.1 perseant * the above Copyright Notice, the above License, this list of Conditions,
46 1.16.6.1 perseant * and the following Disclaimer and Export Compliance provision. In addition,
47 1.16.6.1 perseant * Licensee must cause all Covered Code to which Licensee contributes to
48 1.16.6.1 perseant * contain a file documenting the changes Licensee made to create that Covered
49 1.16.6.1 perseant * Code and the date of any change. Licensee must include in that file the
50 1.16.6.1 perseant * documentation of any changes made by any predecessor Licensee. Licensee
51 1.16.6.1 perseant * must include a prominent statement that the modification is derived,
52 1.16.6.1 perseant * directly or indirectly, from Original Intel Code.
53 1.16.6.1 perseant *
54 1.16.6.1 perseant * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55 1.16.6.1 perseant * Redistribution of source code of any substantial portion of the Covered
56 1.16.6.1 perseant * Code or modification without rights to further distribute source must
57 1.16.6.1 perseant * include the following Disclaimer and Export Compliance provision in the
58 1.16.6.1 perseant * documentation and/or other materials provided with distribution. In
59 1.16.6.1 perseant * addition, Licensee may not authorize further sublicense of source of any
60 1.16.6.1 perseant * portion of the Covered Code, and must include terms to the effect that the
61 1.16.6.1 perseant * license from Licensee to its licensee is limited to the intellectual
62 1.16.6.1 perseant * property embodied in the software Licensee provides to its licensee, and
63 1.16.6.1 perseant * not to intellectual property embodied in modifications its licensee may
64 1.16.6.1 perseant * make.
65 1.16.6.1 perseant *
66 1.16.6.1 perseant * 3.3. Redistribution of Executable. Redistribution in executable form of any
67 1.16.6.1 perseant * substantial portion of the Covered Code or modification must reproduce the
68 1.16.6.1 perseant * above Copyright Notice, and the following Disclaimer and Export Compliance
69 1.16.6.1 perseant * provision in the documentation and/or other materials provided with the
70 1.16.6.1 perseant * distribution.
71 1.16.6.1 perseant *
72 1.16.6.1 perseant * 3.4. Intel retains all right, title, and interest in and to the Original
73 1.16.6.1 perseant * Intel Code.
74 1.16.6.1 perseant *
75 1.16.6.1 perseant * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76 1.16.6.1 perseant * Intel shall be used in advertising or otherwise to promote the sale, use or
77 1.16.6.1 perseant * other dealings in products derived from or relating to the Covered Code
78 1.16.6.1 perseant * without prior written authorization from Intel.
79 1.16.6.1 perseant *
80 1.16.6.1 perseant * 4. Disclaimer and Export Compliance
81 1.16.6.1 perseant *
82 1.16.6.1 perseant * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83 1.16.6.1 perseant * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84 1.16.6.1 perseant * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85 1.16.6.1 perseant * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86 1.16.6.1 perseant * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87 1.16.6.1 perseant * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88 1.16.6.1 perseant * PARTICULAR PURPOSE.
89 1.16.6.1 perseant *
90 1.16.6.1 perseant * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91 1.16.6.1 perseant * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92 1.16.6.1 perseant * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93 1.16.6.1 perseant * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94 1.16.6.1 perseant * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95 1.16.6.1 perseant * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96 1.16.6.1 perseant * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97 1.16.6.1 perseant * LIMITED REMEDY.
98 1.16.6.1 perseant *
99 1.16.6.1 perseant * 4.3. Licensee shall not export, either directly or indirectly, any of this
100 1.16.6.1 perseant * software or system incorporating such software without first obtaining any
101 1.16.6.1 perseant * required license or other approval from the U. S. Department of Commerce or
102 1.16.6.1 perseant * any other agency or department of the United States Government. In the
103 1.16.6.1 perseant * event Licensee exports any such software from the United States or
104 1.16.6.1 perseant * re-exports any such software from a foreign destination, Licensee shall
105 1.16.6.1 perseant * ensure that the distribution and export/re-export of the software is in
106 1.16.6.1 perseant * compliance with all laws, regulations, orders, or other restrictions of the
107 1.16.6.1 perseant * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108 1.16.6.1 perseant * any of its subsidiaries will export/re-export any technical data, process,
109 1.16.6.1 perseant * software, or service, directly or indirectly, to any country for which the
110 1.16.6.1 perseant * United States government or any agency thereof requires an export license,
111 1.16.6.1 perseant * other governmental approval, or letter of assurance, without first obtaining
112 1.16.6.1 perseant * such license, approval or letter.
113 1.16.6.1 perseant *
114 1.16.6.1 perseant *****************************************************************************
115 1.16.6.1 perseant *
116 1.16.6.1 perseant * Alternatively, you may choose to be licensed under the terms of the
117 1.16.6.1 perseant * following license:
118 1.16.6.1 perseant *
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.14 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.16.6.1 perseant * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
139 1.16.6.1 perseant * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
140 1.16.6.1 perseant * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
141 1.16.6.1 perseant * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
142 1.16.6.1 perseant * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
143 1.16.6.1 perseant * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
144 1.16.6.1 perseant * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
145 1.16.6.1 perseant *
146 1.16.6.1 perseant * Alternatively, you may choose to be licensed under the terms of the
147 1.16.6.1 perseant * GNU General Public License ("GPL") version 2 as published by the Free
148 1.16.6.1 perseant * Software Foundation.
149 1.16.6.1 perseant *
150 1.16.6.1 perseant *****************************************************************************/
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.7 christos
232 1.1 christos return (TokenStart);
233 1.1 christos }
234 1.7 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.4 christos UINT16 MessageId,
261 1.1 christos UINT32 Column)
262 1.1 christos {
263 1.1 christos #if 0
264 1.11 christos AcpiOsPrintf ("%s (%u) : %s", AslGbl_Files[ASL_FILE_INPUT].Filename,
265 1.11 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.11 christos AslGbl_CurrentLineNumber, Column,
278 1.11 christos AslGbl_CurrentLineBuffer,
279 1.11 christos AslGbl_Files[ASL_FILE_INPUT].Filename, "Preprocessor");
280 1.1 christos
281 1.11 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.16 christos * FUNCTION: PrReplaceResizeSubstring
288 1.16 christos *
289 1.16 christos * PARAMETERS: Args - Struct containing name, offset & usecount
290 1.16 christos * Diff1 - Difference in lengths when new < old
291 1.16 christos * Diff2 - Difference in lengths when new > old
292 1.16 christos * i - The curr. no. of iteration of replacement
293 1.16 christos * Token - Substring that replaces Args->Name
294 1.16 christos *
295 1.16 christos * RETURN: None
296 1.16 christos *
297 1.16 christos * DESCRIPTION: Advanced substring replacement in a string using resized buffer.
298 1.16 christos *
299 1.16 christos ******************************************************************************/
300 1.16 christos
301 1.16 christos void
302 1.16 christos PrReplaceResizeSubstring(
303 1.16 christos PR_MACRO_ARG *Args,
304 1.16 christos UINT32 Diff1,
305 1.16 christos UINT32 Diff2,
306 1.16 christos UINT32 i,
307 1.16 christos char *Token)
308 1.16 christos {
309 1.16 christos UINT32 b, PrevOffset;
310 1.16 christos char *temp;
311 1.16 christos char macro_sep[64];
312 1.16 christos
313 1.16 christos
314 1.16 christos AslGbl_MacroTokenReplaceBuffer = (char *) realloc (AslGbl_MacroTokenReplaceBuffer,
315 1.16 christos (2 * (strlen (AslGbl_MacroTokenBuffer))));
316 1.16 christos
317 1.16 christos strcpy (macro_sep, "~,() {}!*/%+-<>=&^|\"\t\n");
318 1.16 christos
319 1.16 christos /*
320 1.16 christos * When the replacement argument (during invocation) length
321 1.16 christos * < replaced parameter (in the macro function definition
322 1.16 christos * and its expansion) length
323 1.16 christos */
324 1.16 christos if (Diff1 != 0)
325 1.16 christos {
326 1.16 christos /*
327 1.16 christos * We save the offset value to reset it after replacing each
328 1.16 christos * instance of each arg and setting the offset value to
329 1.16 christos * the start of the arg to be replaced since it changes
330 1.16 christos * with each iteration when arg length != token length
331 1.16 christos */
332 1.16 christos PrevOffset = Args->Offset[i];
333 1.16 christos temp = strstr (AslGbl_MacroTokenBuffer, Args->Name);
334 1.16.6.1 perseant if (temp == NULL)
335 1.16.6.1 perseant {
336 1.16.6.1 perseant return;
337 1.16.6.1 perseant }
338 1.16 christos
339 1.16 christos ResetHere1:
340 1.16 christos temp = strstr (temp, Args->Name);
341 1.16.6.1 perseant if (temp == NULL)
342 1.16.6.1 perseant {
343 1.16.6.1 perseant return;
344 1.16.6.1 perseant }
345 1.16 christos Args->Offset[i] = strlen (AslGbl_MacroTokenBuffer) -
346 1.16 christos strlen (temp);
347 1.16 christos if (Args->Offset[i] == 0)
348 1.16 christos {
349 1.16 christos goto JumpHere1;
350 1.16 christos }
351 1.16 christos if ((strchr (macro_sep, AslGbl_MacroTokenBuffer[(Args->Offset[i] - 1)])) &&
352 1.16 christos (strchr (macro_sep, AslGbl_MacroTokenBuffer[(Args->Offset[i] + strlen (Args->Name))])))
353 1.16 christos {
354 1.16 christos Args->Offset[i] += 0;
355 1.16 christos }
356 1.16 christos else
357 1.16 christos {
358 1.16 christos temp += strlen (Args->Name);
359 1.16 christos goto ResetHere1;
360 1.16 christos }
361 1.16 christos
362 1.16 christos /*
363 1.16 christos * For now, we simply set the extra char positions (generated
364 1.16 christos * due to longer name replaced by shorter name) to whitespace
365 1.16 christos * chars so it will be ignored during compilation
366 1.16 christos */
367 1.16 christos JumpHere1:
368 1.16 christos b = strlen (Token) + Args->Offset[i];
369 1.16 christos memset (&AslGbl_MacroTokenBuffer[b], ' ', Diff1);
370 1.16 christos
371 1.16 christos # if 0
372 1.16 christos
373 1.16 christos /* Work in progress as of 03/08/2023 - experimental 'if' block
374 1.16 christos * to test code for removing extra whitespaces from the macro
375 1.16 christos * replacement when replacement arg < replaced param
376 1.16 christos */
377 1.16 christos char Buff[8192];
378 1.16 christos /* char* Replace; */
379 1.16 christos /* Replace = Buff; */
380 1.16 christos
381 1.16 christos for (j = 0; j < strlen (AslGbl_MacroTokenBuffer); j++)
382 1.16 christos {
383 1.16 christos Buff[j] = AslGbl_MacroTokenBuffer[j];
384 1.16 christos }
385 1.16 christos Buff[strlen (AslGbl_MacroTokenBuffer)] = '\0';
386 1.16.6.1 perseant /* fprintf(stderr, "Buff: %s\n", Buff); */
387 1.16 christos
388 1.16 christos UINT32 len = strlen (Buff);
389 1.16 christos
390 1.16 christos for (j = 0; j < len; j++)
391 1.16 christos {
392 1.16 christos if (Buff[0] == ' ')
393 1.16 christos {
394 1.16 christos for (j = 0; j < (len - 1); j++)
395 1.16 christos {
396 1.16 christos Buff[j] = Buff[j + 1];
397 1.16 christos }
398 1.16 christos Buff[j] = '\0';
399 1.16 christos len--;
400 1.16 christos j = -1;
401 1.16 christos continue;
402 1.16 christos }
403 1.16 christos
404 1.16 christos if (Buff[j] == ' ' && Buff[j + 1] == ' ')
405 1.16 christos {
406 1.16 christos for (k = 0; k < (len - 1); k++)
407 1.16 christos {
408 1.16 christos Buff[j] = Buff[j + 1];
409 1.16 christos }
410 1.16 christos Buff[j] = '\0';
411 1.16 christos len--;
412 1.16 christos j--;
413 1.16 christos }
414 1.16 christos }
415 1.16.6.1 perseant /* fprintf(stderr, "Buff: %s\n", Buff); */
416 1.16 christos
417 1.16 christos for (k = 0; k < strlen (Buff); k++)
418 1.16 christos {
419 1.16 christos AslGbl_MacroTokenBuffer[k] = Buff[k];
420 1.16 christos }
421 1.16 christos #endif
422 1.16 christos
423 1.16 christos PrReplaceData (
424 1.16 christos &AslGbl_MacroTokenBuffer[Args->Offset[i]],
425 1.16 christos strlen (Token), Token, strlen (Token));
426 1.16 christos
427 1.16 christos temp = NULL;
428 1.16 christos Args->Offset[i] = PrevOffset;
429 1.16 christos }
430 1.16 christos
431 1.16 christos /*
432 1.16 christos * When the replacement argument (during invocation) length
433 1.16 christos * > replaced parameter (in the macro function definition
434 1.16 christos * and its expansion) length
435 1.16 christos */
436 1.16 christos else if (Diff2 != 0)
437 1.16 christos {
438 1.16 christos /* Doing the same thing with offset value as for prev case */
439 1.16 christos
440 1.16 christos PrevOffset = Args->Offset[i];
441 1.16 christos temp = strstr (AslGbl_MacroTokenBuffer, Args->Name);
442 1.16.6.1 perseant if (temp == NULL)
443 1.16.6.1 perseant {
444 1.16.6.1 perseant return;
445 1.16.6.1 perseant }
446 1.16 christos
447 1.16 christos ResetHere2:
448 1.16 christos temp = strstr (temp, Args->Name);
449 1.16.6.1 perseant if (temp == NULL)
450 1.16.6.1 perseant {
451 1.16.6.1 perseant return;
452 1.16.6.1 perseant }
453 1.16 christos Args->Offset[i] = strlen (AslGbl_MacroTokenBuffer) -
454 1.16 christos strlen (temp);
455 1.16 christos if (Args->Offset[i] == 0)
456 1.16 christos {
457 1.16 christos goto JumpHere2;
458 1.16 christos }
459 1.16 christos if ((strchr (macro_sep, AslGbl_MacroTokenBuffer[(Args->Offset[i] - 1)])) &&
460 1.16 christos (strchr (macro_sep, AslGbl_MacroTokenBuffer[(Args->Offset[i] + strlen (Args->Name))])))
461 1.16 christos {
462 1.16 christos Args->Offset[i] += 0;
463 1.16 christos }
464 1.16 christos else
465 1.16 christos {
466 1.16 christos temp+= strlen (Args->Name);
467 1.16 christos goto ResetHere2;
468 1.16 christos }
469 1.16 christos
470 1.16 christos /*
471 1.16 christos * We will need to allocate some extra space in our buffer to
472 1.16 christos * accommodate the increase in the replacement string length
473 1.16 christos * over the shorter outgoing arg string and do the replacement
474 1.16 christos * at the correct offset value which is resetted every iteration
475 1.16 christos */
476 1.16 christos JumpHere2:
477 1.16 christos strncpy (AslGbl_MacroTokenReplaceBuffer, AslGbl_MacroTokenBuffer, Args->Offset[i]);
478 1.16 christos strcat (AslGbl_MacroTokenReplaceBuffer, Token);
479 1.16 christos strcat (AslGbl_MacroTokenReplaceBuffer, (AslGbl_MacroTokenBuffer +
480 1.16 christos (Args->Offset[i] + strlen (Args->Name))));
481 1.16 christos
482 1.16 christos strcpy (AslGbl_MacroTokenBuffer, AslGbl_MacroTokenReplaceBuffer);
483 1.16 christos
484 1.16 christos temp = NULL;
485 1.16 christos Args->Offset[i] = PrevOffset;
486 1.16 christos }
487 1.16 christos
488 1.16 christos /*
489 1.16 christos * When the replacement argument (during invocation) length =
490 1.16 christos * replaced parameter (in the macro function definition and
491 1.16 christos * its expansion) length
492 1.16 christos */
493 1.16 christos else
494 1.16 christos {
495 1.16 christos
496 1.16 christos /*
497 1.16 christos * We still need to reset the offset for each iteration even when
498 1.16 christos * arg and param lengths are same since any macro func invocation
499 1.16 christos * could use various cases for each separate arg-param pair
500 1.16 christos */
501 1.16 christos PrevOffset = Args->Offset[i];
502 1.16 christos temp = strstr (AslGbl_MacroTokenBuffer, Args->Name);
503 1.16.6.1 perseant if (temp == NULL)
504 1.16.6.1 perseant {
505 1.16.6.1 perseant return;
506 1.16.6.1 perseant }
507 1.16 christos
508 1.16 christos ResetHere3:
509 1.16 christos temp = strstr (temp, Args->Name);
510 1.16.6.1 perseant if (temp == NULL)
511 1.16.6.1 perseant {
512 1.16.6.1 perseant return;
513 1.16.6.1 perseant }
514 1.16 christos Args->Offset[i] = strlen (AslGbl_MacroTokenBuffer) -
515 1.16 christos strlen (temp);
516 1.16 christos if (Args->Offset[i] == 0)
517 1.16 christos {
518 1.16 christos goto JumpHere3;
519 1.16 christos }
520 1.16 christos if ((strchr (macro_sep, AslGbl_MacroTokenBuffer[(Args->Offset[i] - 1)])) &&
521 1.16 christos (strchr (macro_sep, AslGbl_MacroTokenBuffer[(Args->Offset[i] + strlen (Args->Name))])))
522 1.16 christos {
523 1.16 christos Args->Offset[i] += 0;
524 1.16 christos }
525 1.16 christos else
526 1.16 christos {
527 1.16 christos temp += strlen (Args->Name);
528 1.16 christos goto ResetHere3;
529 1.16 christos }
530 1.16 christos
531 1.16 christos JumpHere3:
532 1.16 christos PrReplaceData (
533 1.16 christos &AslGbl_MacroTokenBuffer[Args->Offset[i]],
534 1.16 christos strlen (Args->Name), Token, strlen (Token));
535 1.16 christos temp = NULL;
536 1.16 christos Args->Offset[i] = PrevOffset;
537 1.16 christos }
538 1.16 christos }
539 1.16 christos
540 1.16 christos
541 1.16 christos /*******************************************************************************
542 1.16 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.16 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.16 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.16 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.16 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.6 christos FILE *
608 1.1 christos PrOpenIncludeFile (
609 1.6 christos char *Filename,
610 1.6 christos char *OpenMode,
611 1.6 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.11 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.6 christos IncludeFile = PrOpenIncludeWithPrefix (
629 1.6 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.6 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.6 christos IncludeFile = PrOpenIncludeWithPrefix (
646 1.11 christos AslGbl_DirectoryPath, Filename, OpenMode, FullPathname);
647 1.1 christos if (IncludeFile)
648 1.1 christos {
649 1.6 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.11 christos NextDir = AslGbl_IncludeDirList;
657 1.1 christos while (NextDir)
658 1.1 christos {
659 1.6 christos IncludeFile = PrOpenIncludeWithPrefix (
660 1.6 christos NextDir->Dir, Filename, OpenMode, FullPathname);
661 1.1 christos if (IncludeFile)
662 1.1 christos {
663 1.6 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.11 christos snprintf (AslGbl_MainTokenBuffer, ASL_DEFAULT_LINE_BUFFER_SIZE, "%s, %s",
673 1.16.6.1 perseant Filename, strerror (errno));
674 1.1 christos PrError (ASL_ERROR, ASL_MSG_INCLUDE_FILE_OPEN, 0);
675 1.6 christos return (NULL);
676 1.1 christos }
677 1.1 christos
678 1.1 christos
679 1.1 christos /*******************************************************************************
680 1.1 christos *
681 1.1 christos * FUNCTION: FlOpenIncludeWithPrefix
682 1.1 christos *
683 1.1 christos * PARAMETERS: PrefixDir - Prefix directory pathname. Can be a zero
684 1.1 christos * length string.
685 1.1 christos * Filename - The include filename from the source ASL.
686 1.1 christos *
687 1.1 christos * RETURN: Valid file descriptor if successful. Null otherwise.
688 1.1 christos *
689 1.1 christos * DESCRIPTION: Open an include file and push it on the input file stack.
690 1.1 christos *
691 1.1 christos ******************************************************************************/
692 1.1 christos
693 1.1 christos FILE *
694 1.1 christos PrOpenIncludeWithPrefix (
695 1.1 christos char *PrefixDir,
696 1.6 christos char *Filename,
697 1.6 christos char *OpenMode,
698 1.6 christos char **FullPathname)
699 1.1 christos {
700 1.1 christos FILE *IncludeFile;
701 1.1 christos char *Pathname;
702 1.1 christos
703 1.1 christos
704 1.1 christos /* Build the full pathname to the file */
705 1.1 christos
706 1.1 christos Pathname = FlMergePathnames (PrefixDir, Filename);
707 1.1 christos
708 1.1 christos DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
709 1.1 christos "Include: Opening file - \"%s\"\n",
710 1.11 christos AslGbl_CurrentLineNumber, Pathname);
711 1.1 christos
712 1.1 christos /* Attempt to open the file, push if successful */
713 1.1 christos
714 1.6 christos IncludeFile = fopen (Pathname, OpenMode);
715 1.1 christos if (!IncludeFile)
716 1.1 christos {
717 1.1 christos return (NULL);
718 1.1 christos }
719 1.1 christos
720 1.1 christos /* Push the include file on the open input file stack */
721 1.1 christos
722 1.1 christos PrPushInputFileStack (IncludeFile, Pathname);
723 1.6 christos *FullPathname = Pathname;
724 1.1 christos return (IncludeFile);
725 1.1 christos }
726 1.1 christos
727 1.1 christos
728 1.1 christos /*******************************************************************************
729 1.1 christos *
730 1.1 christos * FUNCTION: AslPushInputFileStack
731 1.1 christos *
732 1.1 christos * PARAMETERS: InputFile - Open file pointer
733 1.1 christos * Filename - Name of the file
734 1.1 christos *
735 1.1 christos * RETURN: None
736 1.1 christos *
737 1.1 christos * DESCRIPTION: Push the InputFile onto the file stack, and point the parser
738 1.1 christos * to this file. Called when an include file is successfully
739 1.1 christos * opened.
740 1.1 christos *
741 1.1 christos ******************************************************************************/
742 1.1 christos
743 1.1 christos void
744 1.1 christos PrPushInputFileStack (
745 1.1 christos FILE *InputFile,
746 1.1 christos char *Filename)
747 1.1 christos {
748 1.1 christos PR_FILE_NODE *Fnode;
749 1.1 christos
750 1.1 christos
751 1.11 christos AslGbl_HasIncludeFiles = TRUE;
752 1.6 christos
753 1.1 christos /* Save the current state in an Fnode */
754 1.1 christos
755 1.1 christos Fnode = UtLocalCalloc (sizeof (PR_FILE_NODE));
756 1.1 christos
757 1.11 christos Fnode->File = AslGbl_Files[ASL_FILE_INPUT].Handle;
758 1.11 christos Fnode->Next = AslGbl_InputFileList;
759 1.11 christos Fnode->Filename = AslGbl_Files[ASL_FILE_INPUT].Filename;
760 1.11 christos Fnode->CurrentLineNumber = AslGbl_CurrentLineNumber;
761 1.1 christos
762 1.1 christos /* Push it on the stack */
763 1.1 christos
764 1.11 christos AslGbl_InputFileList = Fnode;
765 1.1 christos
766 1.1 christos DbgPrint (ASL_PARSE_OUTPUT, PR_PREFIX_ID
767 1.1 christos "Push InputFile Stack: handle %p\n\n",
768 1.11 christos AslGbl_CurrentLineNumber, InputFile);
769 1.1 christos
770 1.1 christos /* Reset the global line count and filename */
771 1.1 christos
772 1.11 christos AslGbl_Files[ASL_FILE_INPUT].Filename =
773 1.9 christos UtLocalCacheCalloc (strlen (Filename) + 1);
774 1.11 christos strcpy (AslGbl_Files[ASL_FILE_INPUT].Filename, Filename);
775 1.4 christos
776 1.11 christos AslGbl_Files[ASL_FILE_INPUT].Handle = InputFile;
777 1.11 christos AslGbl_CurrentLineNumber = 1;
778 1.1 christos
779 1.1 christos /* Emit a new #line directive for the include file */
780 1.1 christos
781 1.4 christos FlPrintFile (ASL_FILE_PREPROCESSOR, "#line %u \"%s\"\n", 1, Filename);
782 1.1 christos }
783 1.1 christos
784 1.1 christos
785 1.1 christos /*******************************************************************************
786 1.1 christos *
787 1.1 christos * FUNCTION: AslPopInputFileStack
788 1.1 christos *
789 1.1 christos * PARAMETERS: None
790 1.1 christos *
791 1.1 christos * RETURN: 0 if a node was popped, -1 otherwise
792 1.1 christos *
793 1.1 christos * DESCRIPTION: Pop the top of the input file stack and point the parser to
794 1.1 christos * the saved parse buffer contained in the fnode. Also, set the
795 1.1 christos * global line counters to the saved values. This function is
796 1.1 christos * called when an include file reaches EOF.
797 1.1 christos *
798 1.1 christos ******************************************************************************/
799 1.1 christos
800 1.1 christos BOOLEAN
801 1.1 christos PrPopInputFileStack (
802 1.1 christos void)
803 1.1 christos {
804 1.1 christos PR_FILE_NODE *Fnode;
805 1.1 christos
806 1.1 christos
807 1.11 christos Fnode = AslGbl_InputFileList;
808 1.1 christos DbgPrint (ASL_PARSE_OUTPUT, "\n" PR_PREFIX_ID
809 1.1 christos "Pop InputFile Stack, Fnode %p\n\n",
810 1.11 christos AslGbl_CurrentLineNumber, Fnode);
811 1.1 christos
812 1.1 christos if (!Fnode)
813 1.1 christos {
814 1.1 christos return (FALSE);
815 1.1 christos }
816 1.1 christos
817 1.1 christos /* Close the current include file */
818 1.1 christos
819 1.11 christos fclose (AslGbl_Files[ASL_FILE_INPUT].Handle);
820 1.1 christos
821 1.1 christos /* Update the top-of-stack */
822 1.1 christos
823 1.11 christos AslGbl_InputFileList = Fnode->Next;
824 1.1 christos
825 1.1 christos /* Reset global line counter and filename */
826 1.1 christos
827 1.11 christos AslGbl_Files[ASL_FILE_INPUT].Filename = Fnode->Filename;
828 1.11 christos AslGbl_Files[ASL_FILE_INPUT].Handle = Fnode->File;
829 1.11 christos AslGbl_CurrentLineNumber = Fnode->CurrentLineNumber;
830 1.1 christos
831 1.1 christos /* Emit a new #line directive after the include file */
832 1.1 christos
833 1.1 christos FlPrintFile (ASL_FILE_PREPROCESSOR, "#line %u \"%s\"\n",
834 1.11 christos AslGbl_CurrentLineNumber, Fnode->Filename);
835 1.1 christos
836 1.1 christos /* All done with this node */
837 1.1 christos
838 1.1 christos ACPI_FREE (Fnode);
839 1.1 christos return (TRUE);
840 1.1 christos }
841