xref: /netbsd-src/sys/external/bsd/acpica/dist/compiler/prmacros.c (revision c7960b37466ae0fd417c32e6acbb4b956ac7a121)
1ff4a156dSchristos /******************************************************************************
2ff4a156dSchristos  *
3ff4a156dSchristos  * Module Name: prmacros - Preprocessor #define macro support
4ff4a156dSchristos  *
5ff4a156dSchristos  *****************************************************************************/
6ff4a156dSchristos 
7ff4a156dSchristos /*
8*046a2985Schristos  * Copyright (C) 2000 - 2023, Intel Corp.
9ff4a156dSchristos  * All rights reserved.
10ff4a156dSchristos  *
11ff4a156dSchristos  * Redistribution and use in source and binary forms, with or without
12ff4a156dSchristos  * modification, are permitted provided that the following conditions
13ff4a156dSchristos  * are met:
14ff4a156dSchristos  * 1. Redistributions of source code must retain the above copyright
15ff4a156dSchristos  *    notice, this list of conditions, and the following disclaimer,
16ff4a156dSchristos  *    without modification.
17ff4a156dSchristos  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18ff4a156dSchristos  *    substantially similar to the "NO WARRANTY" disclaimer below
19ff4a156dSchristos  *    ("Disclaimer") and any redistribution must be conditioned upon
20ff4a156dSchristos  *    including a substantially similar Disclaimer requirement for further
21ff4a156dSchristos  *    binary redistribution.
22ff4a156dSchristos  * 3. Neither the names of the above-listed copyright holders nor the names
23ff4a156dSchristos  *    of any contributors may be used to endorse or promote products derived
24ff4a156dSchristos  *    from this software without specific prior written permission.
25ff4a156dSchristos  *
26ff4a156dSchristos  * Alternatively, this software may be distributed under the terms of the
27ff4a156dSchristos  * GNU General Public License ("GPL") version 2 as published by the Free
28ff4a156dSchristos  * Software Foundation.
29ff4a156dSchristos  *
30ff4a156dSchristos  * NO WARRANTY
31ff4a156dSchristos  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32ff4a156dSchristos  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3346a330b4Schristos  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
34ff4a156dSchristos  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35ff4a156dSchristos  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36ff4a156dSchristos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37ff4a156dSchristos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38ff4a156dSchristos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39ff4a156dSchristos  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40ff4a156dSchristos  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41ff4a156dSchristos  * POSSIBILITY OF SUCH DAMAGES.
42ff4a156dSchristos  */
43ff4a156dSchristos 
44ff4a156dSchristos #include "aslcompiler.h"
45ff4a156dSchristos 
46ff4a156dSchristos #define _COMPONENT          ASL_PREPROCESSOR
47ff4a156dSchristos         ACPI_MODULE_NAME    ("prmacros")
48ff4a156dSchristos 
49ff4a156dSchristos 
50ff4a156dSchristos /*******************************************************************************
51ff4a156dSchristos  *
52ff4a156dSchristos  * FUNCTION:    PrDumpPredefinedNames
53ff4a156dSchristos  *
54ff4a156dSchristos  * PARAMETERS:  None
55ff4a156dSchristos  *
56ff4a156dSchristos  * RETURN:      None
57ff4a156dSchristos  *
58ff4a156dSchristos  * DESCRIPTION: Dump the list of #defines. Used as the preprocessor starts, to
59ff4a156dSchristos  *              display the names that were defined on the command line.
60ff4a156dSchristos  *              Debug information only.
61ff4a156dSchristos  *
62ff4a156dSchristos  ******************************************************************************/
63ff4a156dSchristos 
64ff4a156dSchristos void
65ff4a156dSchristos PrDumpPredefinedNames (
66ff4a156dSchristos     void)
67ff4a156dSchristos {
68ff4a156dSchristos     PR_DEFINE_INFO          *DefineInfo;
69ff4a156dSchristos 
70ff4a156dSchristos 
714c4e8184Schristos     DefineInfo = AslGbl_DefineList;
72ff4a156dSchristos     while (DefineInfo)
73ff4a156dSchristos     {
74ff4a156dSchristos         DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
75ff4a156dSchristos             "Predefined #define: %s->%s\n",
76ff4a156dSchristos             0, DefineInfo->Identifier, DefineInfo->Replacement);
77ff4a156dSchristos 
78ff4a156dSchristos         DefineInfo = DefineInfo->Next;
79ff4a156dSchristos     }
80ff4a156dSchristos }
81ff4a156dSchristos 
82ff4a156dSchristos 
83ff4a156dSchristos /*******************************************************************************
84ff4a156dSchristos  *
85ff4a156dSchristos  * FUNCTION:    PrAddDefine
86ff4a156dSchristos  *
87ff4a156dSchristos  * PARAMETERS:  Identifier          - Name to be replaced
88ff4a156dSchristos  *              Replacement         - Replacement for Identifier
89ff4a156dSchristos  *              Persist             - Keep define across multiple compiles?
90ff4a156dSchristos  *
91ff4a156dSchristos  * RETURN:      A new define_info struct. NULL on error.
92ff4a156dSchristos  *
93ff4a156dSchristos  * DESCRIPTION: Add a new #define to the global list
94ff4a156dSchristos  *
95ff4a156dSchristos  ******************************************************************************/
96ff4a156dSchristos 
97ff4a156dSchristos PR_DEFINE_INFO *
98ff4a156dSchristos PrAddDefine (
99ff4a156dSchristos     char                    *Identifier,
100ff4a156dSchristos     char                    *Replacement,
101ff4a156dSchristos     BOOLEAN                 Persist)
102ff4a156dSchristos {
103ff4a156dSchristos     char                    *IdentifierString;
104ff4a156dSchristos     char                    *ReplacementString;
105ff4a156dSchristos     PR_DEFINE_INFO          *DefineInfo;
106ff4a156dSchristos 
107ff4a156dSchristos 
108ff4a156dSchristos     if (!Replacement)
109ff4a156dSchristos     {
110ff4a156dSchristos         Replacement = "";
111ff4a156dSchristos     }
112ff4a156dSchristos 
113ff4a156dSchristos     /* Check for already-defined first */
114ff4a156dSchristos 
115ff4a156dSchristos     DefineInfo = PrMatchDefine (Identifier);
116ff4a156dSchristos     if (DefineInfo)
117ff4a156dSchristos     {
118783af925Schristos         DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
119ff4a156dSchristos             "#define: name already exists: %s\n",
1204c4e8184Schristos             AslGbl_CurrentLineNumber, Identifier);
121ff4a156dSchristos 
122ff4a156dSchristos         /*
123ff4a156dSchristos          * Name already exists. This is only an error if the target name
124ff4a156dSchristos          * is different.
125ff4a156dSchristos          */
126ff4a156dSchristos         if (strcmp (Replacement, DefineInfo->Replacement))
127ff4a156dSchristos         {
128ff4a156dSchristos             PrError (ASL_ERROR, ASL_MSG_EXISTING_NAME,
129ff4a156dSchristos                 THIS_TOKEN_OFFSET (Identifier));
130ff4a156dSchristos 
131ff4a156dSchristos             return (NULL);
132ff4a156dSchristos         }
133ff4a156dSchristos 
134ff4a156dSchristos         return (DefineInfo);
135ff4a156dSchristos     }
136ff4a156dSchristos 
137ff4a156dSchristos     /* Copy input strings */
138ff4a156dSchristos 
139ff4a156dSchristos     IdentifierString = UtLocalCalloc (strlen (Identifier) + 1);
140ff4a156dSchristos     strcpy (IdentifierString, Identifier);
141ff4a156dSchristos 
142ff4a156dSchristos     ReplacementString = UtLocalCalloc (strlen (Replacement) + 1);
143ff4a156dSchristos     strcpy (ReplacementString, Replacement);
144ff4a156dSchristos 
145ff4a156dSchristos     /* Init and link new define info struct */
146ff4a156dSchristos 
147ff4a156dSchristos     DefineInfo = UtLocalCalloc (sizeof (PR_DEFINE_INFO));
148ff4a156dSchristos     DefineInfo->Replacement = ReplacementString;
149ff4a156dSchristos     DefineInfo->Identifier = IdentifierString;
150ff4a156dSchristos     DefineInfo->Persist = Persist;
151ff4a156dSchristos 
1524c4e8184Schristos     if (AslGbl_DefineList)
153ff4a156dSchristos     {
1544c4e8184Schristos         AslGbl_DefineList->Previous = DefineInfo;
155ff4a156dSchristos     }
156ff4a156dSchristos 
1574c4e8184Schristos     DefineInfo->Next = AslGbl_DefineList;
1584c4e8184Schristos     AslGbl_DefineList = DefineInfo;
159ff4a156dSchristos     return (DefineInfo);
160ff4a156dSchristos }
161ff4a156dSchristos 
162ff4a156dSchristos 
163ff4a156dSchristos /*******************************************************************************
164ff4a156dSchristos  *
165ff4a156dSchristos  * FUNCTION:    PrRemoveDefine
166ff4a156dSchristos  *
167ff4a156dSchristos  * PARAMETERS:  DefineName          - Name of define to be removed
168ff4a156dSchristos  *
169ff4a156dSchristos  * RETURN:      None
170ff4a156dSchristos  *
171ff4a156dSchristos  * DESCRIPTION: Implements #undef. Remove a #define if found in the global
172ff4a156dSchristos  *              list. No error if the target of the #undef does not exist,
173ff4a156dSchristos  *              as per the C #undef definition.
174ff4a156dSchristos  *
175ff4a156dSchristos  ******************************************************************************/
176ff4a156dSchristos 
177ff4a156dSchristos void
178ff4a156dSchristos PrRemoveDefine (
179ff4a156dSchristos     char                    *DefineName)
180ff4a156dSchristos {
181ff4a156dSchristos     PR_DEFINE_INFO          *DefineInfo;
182ff4a156dSchristos 
183ff4a156dSchristos 
184ff4a156dSchristos     /* Match name and delete the node */
185ff4a156dSchristos 
1864c4e8184Schristos     DefineInfo = AslGbl_DefineList;
187ff4a156dSchristos     while (DefineInfo)
188ff4a156dSchristos     {
189ff4a156dSchristos         if (!strcmp (DefineName, DefineInfo->Identifier))
190ff4a156dSchristos         {
191ff4a156dSchristos             /* Remove from linked list */
192ff4a156dSchristos 
193ff4a156dSchristos             if (DefineInfo->Previous)
194ff4a156dSchristos             {
195ff4a156dSchristos                 (DefineInfo->Previous)->Next = DefineInfo->Next;
196ff4a156dSchristos             }
197ff4a156dSchristos             else
198ff4a156dSchristos             {
1994c4e8184Schristos                 AslGbl_DefineList = DefineInfo->Next;
200ff4a156dSchristos             }
201ff4a156dSchristos 
202ff4a156dSchristos             if (DefineInfo->Next)
203ff4a156dSchristos             {
204ff4a156dSchristos                 (DefineInfo->Next)->Previous = DefineInfo->Previous;
205ff4a156dSchristos             }
206ff4a156dSchristos 
207ff4a156dSchristos             free (DefineInfo);
208ff4a156dSchristos             return;
209ff4a156dSchristos         }
210ff4a156dSchristos 
211ff4a156dSchristos         DefineInfo = DefineInfo->Next;
212ff4a156dSchristos     }
213ff4a156dSchristos 
214ff4a156dSchristos     /*
215ff4a156dSchristos      * Name was not found. By definition of #undef, this is not
216ff4a156dSchristos      * an error, however.
217ff4a156dSchristos      */
218ff4a156dSchristos     DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
219ff4a156dSchristos         "#undef: could not find %s\n",
2204c4e8184Schristos         AslGbl_CurrentLineNumber, DefineName);
221ff4a156dSchristos }
222ff4a156dSchristos 
223ff4a156dSchristos 
224ff4a156dSchristos /*******************************************************************************
225ff4a156dSchristos  *
226ff4a156dSchristos  * FUNCTION:    PrMatchDefine
227ff4a156dSchristos  *
228ff4a156dSchristos  * PARAMETERS:  MatchString         - Name associated with the #define
229ff4a156dSchristos  *
230ff4a156dSchristos  * RETURN:      Matched string if found. NULL otherwise.
231ff4a156dSchristos  *
232ff4a156dSchristos  * DESCRIPTION: Find a name in global #define list
233ff4a156dSchristos  *
234ff4a156dSchristos  ******************************************************************************/
235ff4a156dSchristos 
236ff4a156dSchristos PR_DEFINE_INFO *
237ff4a156dSchristos PrMatchDefine (
238ff4a156dSchristos     char                    *MatchString)
239ff4a156dSchristos {
240ff4a156dSchristos     PR_DEFINE_INFO          *DefineInfo;
241ff4a156dSchristos 
242ff4a156dSchristos 
2434c4e8184Schristos     DefineInfo = AslGbl_DefineList;
244ff4a156dSchristos     while (DefineInfo)
245ff4a156dSchristos     {
246ff4a156dSchristos         if (!strcmp (MatchString, DefineInfo->Identifier))
247ff4a156dSchristos         {
248ff4a156dSchristos             return (DefineInfo);
249ff4a156dSchristos         }
250ff4a156dSchristos 
251ff4a156dSchristos         DefineInfo = DefineInfo->Next;
252ff4a156dSchristos     }
253ff4a156dSchristos 
254ff4a156dSchristos     return (NULL);
255ff4a156dSchristos }
256ff4a156dSchristos 
257ff4a156dSchristos 
258ff4a156dSchristos /*******************************************************************************
259ff4a156dSchristos  *
260ff4a156dSchristos  * FUNCTION:    PrAddMacro
261ff4a156dSchristos  *
262ff4a156dSchristos  * PARAMETERS:  Name                - Start of the macro definition
263ff4a156dSchristos  *              Next                - "Next" buffer from GetNextToken
264ff4a156dSchristos  *
265ff4a156dSchristos  * RETURN:      None
266ff4a156dSchristos  *
267ff4a156dSchristos  * DESCRIPTION: Add a new macro to the list of #defines. Handles argument
268ff4a156dSchristos  *              processing.
269ff4a156dSchristos  *
270ff4a156dSchristos  ******************************************************************************/
271ff4a156dSchristos 
272ff4a156dSchristos void
273ff4a156dSchristos PrAddMacro (
274ff4a156dSchristos     char                    *Name,
275ff4a156dSchristos     char                    **Next)
276ff4a156dSchristos {
277ff4a156dSchristos     char                    *Token = NULL;
278ff4a156dSchristos     ACPI_SIZE               TokenOffset;
279ff4a156dSchristos     ACPI_SIZE               MacroBodyOffset;
280ff4a156dSchristos     PR_DEFINE_INFO          *DefineInfo;
281ff4a156dSchristos     PR_MACRO_ARG            *Args;
282ff4a156dSchristos     char                    *Body;
283ff4a156dSchristos     char                    *BodyInSource;
284ff4a156dSchristos     UINT32                  i;
285ff4a156dSchristos     UINT16                  UseCount = 0;
286ff4a156dSchristos     UINT16                  ArgCount = 0;
287ff4a156dSchristos     UINT32                  Depth = 1;
288*046a2985Schristos     /*UINT32                  Depth = 1;*/
289ff4a156dSchristos     UINT32                  EndOfArgList;
290ff4a156dSchristos     char                    BufferChar;
291ff4a156dSchristos 
292ff4a156dSchristos     /* Find the end of the arguments list */
293ff4a156dSchristos 
2944c4e8184Schristos     TokenOffset = Name - AslGbl_MainTokenBuffer + strlen (Name) + 1;
295ff4a156dSchristos     while (1)
296ff4a156dSchristos     {
2974c4e8184Schristos         BufferChar = AslGbl_CurrentLineBuffer[TokenOffset];
298ff4a156dSchristos         if (BufferChar == '(')
299ff4a156dSchristos         {
300ff4a156dSchristos             Depth++;
301ff4a156dSchristos         }
302ff4a156dSchristos         else if (BufferChar == ')')
303ff4a156dSchristos         {
304ff4a156dSchristos             Depth--;
305ff4a156dSchristos         }
306ff4a156dSchristos         else if (BufferChar == 0)
307ff4a156dSchristos         {
308ff4a156dSchristos             PrError (ASL_ERROR, ASL_MSG_MACRO_SYNTAX, TokenOffset);
309ff4a156dSchristos             return;
310ff4a156dSchristos         }
311ff4a156dSchristos 
312ff4a156dSchristos         if (Depth == 0)
313ff4a156dSchristos         {
314ff4a156dSchristos             /* Found arg list end */
315ff4a156dSchristos 
316ff4a156dSchristos             EndOfArgList = TokenOffset;
317ff4a156dSchristos             break;
318ff4a156dSchristos         }
319ff4a156dSchristos 
320ff4a156dSchristos         TokenOffset++;
321ff4a156dSchristos     }
322ff4a156dSchristos 
323ff4a156dSchristos     /* At this point, we know that we have a reasonable argument list */
324ff4a156dSchristos 
325ff4a156dSchristos     Args = UtLocalCalloc (sizeof (PR_MACRO_ARG) * PR_MAX_MACRO_ARGS);
326ff4a156dSchristos 
327ff4a156dSchristos     /* Get the macro argument names */
328ff4a156dSchristos 
329ff4a156dSchristos     for (i = 0; i < PR_MAX_MACRO_ARGS; i++)
330ff4a156dSchristos     {
331ff4a156dSchristos         Token = PrGetNextToken (NULL, PR_MACRO_SEPARATORS, Next);
332*046a2985Schristos 
333ff4a156dSchristos         if (!Token)
334ff4a156dSchristos         {
335ff4a156dSchristos             /* This is the case for a NULL macro body */
336ff4a156dSchristos 
337ff4a156dSchristos             BodyInSource = "";
338ff4a156dSchristos             goto AddMacroToList;
339ff4a156dSchristos         }
340ff4a156dSchristos 
341ff4a156dSchristos         /* Don't go beyond the argument list */
342ff4a156dSchristos 
3434c4e8184Schristos         TokenOffset = Token - AslGbl_MainTokenBuffer + strlen (Token);
344ff4a156dSchristos         if (TokenOffset > EndOfArgList)
345ff4a156dSchristos         {
346ff4a156dSchristos             break;
347ff4a156dSchristos         }
348ff4a156dSchristos 
349ff4a156dSchristos         DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
350*046a2985Schristos             "Macro param: %s\n",
3514c4e8184Schristos             AslGbl_CurrentLineNumber, Token);
352ff4a156dSchristos 
353ff4a156dSchristos         Args[i].Name = UtLocalCalloc (strlen (Token) + 1);
354ff4a156dSchristos         strcpy (Args[i].Name, Token);
355ff4a156dSchristos 
356ff4a156dSchristos         Args[i].UseCount = 0;
357ff4a156dSchristos         ArgCount++;
358ff4a156dSchristos         if (ArgCount >= PR_MAX_MACRO_ARGS)
359ff4a156dSchristos         {
360ff4a156dSchristos             PrError (ASL_ERROR, ASL_MSG_TOO_MANY_ARGUMENTS, TokenOffset);
361460301d4Schristos             goto ErrorExit;
362ff4a156dSchristos         }
363ff4a156dSchristos     }
364ff4a156dSchristos 
365ff4a156dSchristos     /* Get the macro body. Token now points to start of body */
366ff4a156dSchristos 
3674c4e8184Schristos     MacroBodyOffset = Token - AslGbl_MainTokenBuffer;
368ff4a156dSchristos 
369ff4a156dSchristos     /* Match each method arg in the macro body for later use */
370ff4a156dSchristos 
371ff4a156dSchristos     while (Token)
372ff4a156dSchristos     {
373ff4a156dSchristos         /* Search the macro arg list for matching arg */
374ff4a156dSchristos 
37589b8eb6cSchristos         for (i = 0; ((i < PR_MAX_MACRO_ARGS) && Args[i].Name); i++)
376ff4a156dSchristos         {
377ff4a156dSchristos             /*
378ff4a156dSchristos              * Save argument offset within macro body. This is the mechanism
379ff4a156dSchristos              * used to expand the macro upon invocation.
380ff4a156dSchristos              *
381ff4a156dSchristos              * Handles multiple instances of the same argument
382ff4a156dSchristos              */
383ff4a156dSchristos             if (!strcmp (Token, Args[i].Name))
384ff4a156dSchristos             {
385ff4a156dSchristos                 UseCount = Args[i].UseCount;
386ff4a156dSchristos 
38771e38f1dSchristos                 Args[i].Offset[UseCount] =
3884c4e8184Schristos                     (Token - AslGbl_MainTokenBuffer) - MacroBodyOffset;
389ff4a156dSchristos 
390*046a2985Schristos 
391ff4a156dSchristos                 DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
392ff4a156dSchristos                     "Macro Arg #%u: %s UseCount %u Offset %u\n",
3934c4e8184Schristos                     AslGbl_CurrentLineNumber, i, Token,
394ff4a156dSchristos                     UseCount+1, Args[i].Offset[UseCount]);
395ff4a156dSchristos 
396ff4a156dSchristos                 Args[i].UseCount++;
397*046a2985Schristos 
398ff4a156dSchristos                 if (Args[i].UseCount >= PR_MAX_ARG_INSTANCES)
399ff4a156dSchristos                 {
400ff4a156dSchristos                     PrError (ASL_ERROR, ASL_MSG_TOO_MANY_ARGUMENTS,
401ff4a156dSchristos                         THIS_TOKEN_OFFSET (Token));
402ff4a156dSchristos 
403460301d4Schristos                     goto ErrorExit;
404ff4a156dSchristos                 }
405ff4a156dSchristos                 break;
406ff4a156dSchristos             }
407ff4a156dSchristos         }
408ff4a156dSchristos 
409ff4a156dSchristos         Token = PrGetNextToken (NULL, PR_MACRO_SEPARATORS, Next);
410ff4a156dSchristos     }
411ff4a156dSchristos 
4124c4e8184Schristos     BodyInSource = &AslGbl_CurrentLineBuffer[MacroBodyOffset];
413ff4a156dSchristos 
414ff4a156dSchristos 
415ff4a156dSchristos AddMacroToList:
416ff4a156dSchristos 
417ff4a156dSchristos     /* Check if name is already defined first */
418ff4a156dSchristos 
419ff4a156dSchristos     DefineInfo = PrMatchDefine (Name);
420ff4a156dSchristos     if (DefineInfo)
421ff4a156dSchristos     {
422ff4a156dSchristos         DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
423ff4a156dSchristos             "#define: macro name already exists: %s\n",
4244c4e8184Schristos             AslGbl_CurrentLineNumber, Name);
425ff4a156dSchristos 
426ff4a156dSchristos         /* Error only if not exactly the same macro */
427ff4a156dSchristos 
428ff4a156dSchristos         if (strcmp (DefineInfo->Body, BodyInSource) ||
429ff4a156dSchristos             (DefineInfo->ArgCount != ArgCount))
430ff4a156dSchristos         {
431ff4a156dSchristos             PrError (ASL_ERROR, ASL_MSG_EXISTING_NAME,
432ff4a156dSchristos                 THIS_TOKEN_OFFSET (Name));
433ff4a156dSchristos         }
434ff4a156dSchristos 
435460301d4Schristos         goto ErrorExit;
436ff4a156dSchristos     }
437ff4a156dSchristos 
438ff4a156dSchristos     DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
439ff4a156dSchristos         "Macro body: %s\n",
4404c4e8184Schristos         AslGbl_CurrentLineNumber, BodyInSource);
441ff4a156dSchristos 
442ff4a156dSchristos     /* Add macro to the #define list */
443ff4a156dSchristos 
444ff4a156dSchristos     DefineInfo = PrAddDefine (Name, BodyInSource, FALSE);
445ff4a156dSchristos     if (DefineInfo)
446ff4a156dSchristos     {
447ff4a156dSchristos         Body = UtLocalCalloc (strlen (BodyInSource) + 1);
448ff4a156dSchristos         strcpy (Body, BodyInSource);
449ff4a156dSchristos 
450ff4a156dSchristos         DefineInfo->Body = Body;
451ff4a156dSchristos         DefineInfo->Args = Args;
452ff4a156dSchristos         DefineInfo->ArgCount = ArgCount;
453ff4a156dSchristos     }
454460301d4Schristos 
455460301d4Schristos     return;
456460301d4Schristos 
457460301d4Schristos 
458460301d4Schristos ErrorExit:
459460301d4Schristos     ACPI_FREE (Args);
460460301d4Schristos     return;
461ff4a156dSchristos }
462ff4a156dSchristos 
463ff4a156dSchristos 
464ff4a156dSchristos /*******************************************************************************
465ff4a156dSchristos  *
466ff4a156dSchristos  * FUNCTION:    PrDoMacroInvocation
467ff4a156dSchristos  *
468ff4a156dSchristos  * PARAMETERS:  TokenBuffer         - Current line buffer
469ff4a156dSchristos  *              MacroStart          - Start of the macro invocation within
470ff4a156dSchristos  *                                    the token buffer
471ff4a156dSchristos  *              DefineInfo          - Info for this macro
472ff4a156dSchristos  *              Next                - "Next" buffer from GetNextToken
473ff4a156dSchristos  *
474ff4a156dSchristos  * RETURN:      None
475ff4a156dSchristos  *
476ff4a156dSchristos  * DESCRIPTION: Expand a macro invocation
477ff4a156dSchristos  *
478ff4a156dSchristos  ******************************************************************************/
479ff4a156dSchristos 
480ff4a156dSchristos void
481ff4a156dSchristos PrDoMacroInvocation (
482ff4a156dSchristos     char                    *TokenBuffer,
483ff4a156dSchristos     char                    *MacroStart,
484ff4a156dSchristos     PR_DEFINE_INFO          *DefineInfo,
485ff4a156dSchristos     char                    **Next)
486ff4a156dSchristos {
487ff4a156dSchristos     PR_MACRO_ARG            *Args;
488ff4a156dSchristos     char                    *Token = NULL;
489ff4a156dSchristos     UINT32                  TokenOffset;
490ff4a156dSchristos     UINT32                  Length;
491ff4a156dSchristos     UINT32                  i;
492*046a2985Schristos     UINT32                  Diff1;
493*046a2985Schristos     UINT32                  Diff2;
494ff4a156dSchristos 
495ff4a156dSchristos     /* Take a copy of the macro body for expansion */
496ff4a156dSchristos 
4974c4e8184Schristos     strcpy (AslGbl_MacroTokenBuffer, DefineInfo->Body);
498ff4a156dSchristos 
499ff4a156dSchristos     /* Replace each argument within the prototype body */
500ff4a156dSchristos 
501ff4a156dSchristos     Args = DefineInfo->Args;
502ff4a156dSchristos     if (!Args->Name)
503ff4a156dSchristos     {
504ff4a156dSchristos         /* This macro has no arguments */
505ff4a156dSchristos 
506ff4a156dSchristos         Token = PrGetNextToken (NULL, PR_MACRO_ARGUMENTS, Next);
507*046a2985Schristos 
508ff4a156dSchristos         if (!Token)
509ff4a156dSchristos         {
510ff4a156dSchristos             goto BadInvocation;
511ff4a156dSchristos         }
512ff4a156dSchristos 
513ff4a156dSchristos         TokenOffset = (MacroStart - TokenBuffer);
514ff4a156dSchristos         Length = Token - MacroStart + strlen (Token) + 1;
515ff4a156dSchristos 
516ff4a156dSchristos         PrReplaceData (
5174c4e8184Schristos             &AslGbl_CurrentLineBuffer[TokenOffset], Length,
5184c4e8184Schristos             AslGbl_MacroTokenBuffer, strlen (AslGbl_MacroTokenBuffer));
519ff4a156dSchristos         return;
520ff4a156dSchristos     }
521ff4a156dSchristos 
522ff4a156dSchristos     while (Args->Name)
523ff4a156dSchristos     {
524ff4a156dSchristos         /* Get the next argument from macro invocation */
525ff4a156dSchristos 
526ff4a156dSchristos         Token = PrGetNextToken (NULL, PR_MACRO_SEPARATORS, Next);
527ff4a156dSchristos         if (!Token)
528ff4a156dSchristos         {
529ff4a156dSchristos             goto BadInvocation;
530ff4a156dSchristos         }
531ff4a156dSchristos 
532*046a2985Schristos         /*
533*046a2985Schristos          * Avoid optimizing using just 1 signed int due to specific
534*046a2985Schristos          * non-portable implementations of signed ints
535*046a2985Schristos          */
536*046a2985Schristos         Diff1 = strlen (Args->Name) > strlen (Token) ? strlen (Args->Name) -
537*046a2985Schristos             strlen (Token) : 0;
538*046a2985Schristos 
539*046a2985Schristos         Diff2 = strlen (Args->Name) < strlen (Token) ? strlen (Token) -
540*046a2985Schristos             strlen (Args->Name) : 0;
541*046a2985Schristos 
542ff4a156dSchristos         /* Replace all instances of this argument */
543ff4a156dSchristos 
544ff4a156dSchristos         for (i = 0; i < Args->UseCount; i++)
545ff4a156dSchristos         {
546*046a2985Schristos             /*
547*046a2985Schristos              * To test the output of the preprocessed macro function that
548*046a2985Schristos              * is passed to the compiler
549*046a2985Schristos              */
550ff4a156dSchristos 
551*046a2985Schristos              /*
552*046a2985Schristos               * fprintf (stderr, "Current token = %s \t Current arg_name = %s \
553*046a2985Schristos               * \t strlen (Token) = %u \t strlen (Args->Name) = %u \t Offset = %u \
554*046a2985Schristos               * \t UseCount = %u \t", Token, Args->Name, strlen (Token), \
555*046a2985Schristos               *     strlen (Args->Name), Args->Offset[i], Args->UseCount);
556*046a2985Schristos               */
557ff4a156dSchristos 
558*046a2985Schristos             AslGbl_MacroTokenReplaceBuffer = (char *) calloc ((strlen (AslGbl_MacroTokenBuffer)), sizeof (char));
559*046a2985Schristos 
560*046a2985Schristos             PrReplaceResizeSubstring (Args, Diff1, Diff2, i, Token);
561ff4a156dSchristos 
562ff4a156dSchristos             DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
563ff4a156dSchristos                 "ExpandArg: %s\n",
5644c4e8184Schristos                 AslGbl_CurrentLineNumber, AslGbl_MacroTokenBuffer);
565ff4a156dSchristos         }
566ff4a156dSchristos 
567ff4a156dSchristos         Args++;
568ff4a156dSchristos     }
569ff4a156dSchristos 
570ff4a156dSchristos     if (!Token)
571ff4a156dSchristos     {
572ff4a156dSchristos         return;
573ff4a156dSchristos     }
574ff4a156dSchristos 
575ff4a156dSchristos     /* Replace the entire macro invocation with the expanded macro */
576ff4a156dSchristos 
577ff4a156dSchristos     TokenOffset = (MacroStart - TokenBuffer);
578ff4a156dSchristos     Length = Token - MacroStart + strlen (Token) + 1;
579ff4a156dSchristos 
580ff4a156dSchristos     PrReplaceData (
5814c4e8184Schristos         &AslGbl_CurrentLineBuffer[TokenOffset], Length,
5824c4e8184Schristos         AslGbl_MacroTokenBuffer, strlen (AslGbl_MacroTokenBuffer));
583ff4a156dSchristos 
584ff4a156dSchristos     return;
585ff4a156dSchristos 
586ff4a156dSchristos BadInvocation:
587ff4a156dSchristos     PrError (ASL_ERROR, ASL_MSG_INVALID_INVOCATION,
588ff4a156dSchristos         THIS_TOKEN_OFFSET (MacroStart));
589ff4a156dSchristos 
590ff4a156dSchristos     DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
591ff4a156dSchristos         "Bad macro invocation: %s\n",
5924c4e8184Schristos         AslGbl_CurrentLineNumber, AslGbl_MacroTokenBuffer);
593ff4a156dSchristos     return;
594ff4a156dSchristos }
595