1233237Sjkim/******************************************************************************
2233237Sjkim *
3233237Sjkim * Module Name: prmacros - Preprocessor #define macro support
4233237Sjkim *
5233237Sjkim *****************************************************************************/
6233237Sjkim
7233237Sjkim/*
8245582Sjkim * Copyright (C) 2000 - 2013, Intel Corp.
9233237Sjkim * All rights reserved.
10233237Sjkim *
11233237Sjkim * Redistribution and use in source and binary forms, with or without
12233237Sjkim * modification, are permitted provided that the following conditions
13233237Sjkim * are met:
14233237Sjkim * 1. Redistributions of source code must retain the above copyright
15233237Sjkim *    notice, this list of conditions, and the following disclaimer,
16233237Sjkim *    without modification.
17233237Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18233237Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
19233237Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
20233237Sjkim *    including a substantially similar Disclaimer requirement for further
21233237Sjkim *    binary redistribution.
22233237Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
23233237Sjkim *    of any contributors may be used to endorse or promote products derived
24233237Sjkim *    from this software without specific prior written permission.
25233237Sjkim *
26233237Sjkim * Alternatively, this software may be distributed under the terms of the
27233237Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
28233237Sjkim * Software Foundation.
29233237Sjkim *
30233237Sjkim * NO WARRANTY
31233237Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32233237Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33233237Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34233237Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35233237Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36233237Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37233237Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38233237Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39233237Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40233237Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41233237Sjkim * POSSIBILITY OF SUCH DAMAGES.
42233237Sjkim */
43233237Sjkim
44233250Sjkim#include <contrib/dev/acpica/compiler/aslcompiler.h>
45233250Sjkim#include <contrib/dev/acpica/compiler/dtcompiler.h>
46233237Sjkim
47233237Sjkim
48233237Sjkim#define _COMPONENT          ASL_PREPROCESSOR
49233237Sjkim        ACPI_MODULE_NAME    ("prmacros")
50233237Sjkim
51233237Sjkim
52233237Sjkim/*******************************************************************************
53233237Sjkim *
54233237Sjkim * FUNCTION:    PrDumpPredefinedNames
55233237Sjkim *
56233237Sjkim * PARAMETERS:  None
57233237Sjkim *
58233237Sjkim * RETURN:      None
59233237Sjkim *
60233237Sjkim * DESCRIPTION: Dump the list of #defines. Used as the preprocessor starts, to
61233237Sjkim *              display the names that were defined on the command line.
62233237Sjkim *              Debug information only.
63233237Sjkim *
64233237Sjkim ******************************************************************************/
65233237Sjkim
66233237Sjkimvoid
67233237SjkimPrDumpPredefinedNames (
68233237Sjkim    void)
69233237Sjkim{
70233237Sjkim    PR_DEFINE_INFO          *DefineInfo;
71233237Sjkim
72233237Sjkim
73233237Sjkim    DefineInfo = Gbl_DefineList;
74233237Sjkim    while (DefineInfo)
75233237Sjkim    {
76233237Sjkim        DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
77233237Sjkim            "Predefined #define: %s->%s\n",
78233237Sjkim            0, DefineInfo->Identifier, DefineInfo->Replacement);
79233237Sjkim
80233237Sjkim        DefineInfo = DefineInfo->Next;
81233237Sjkim    }
82233237Sjkim}
83233237Sjkim
84233237Sjkim
85233237Sjkim/*******************************************************************************
86233237Sjkim *
87233237Sjkim * FUNCTION:    PrAddDefine
88233237Sjkim *
89233237Sjkim * PARAMETERS:  Identifier          - Name to be replaced
90233237Sjkim *              Replacement         - Replacement for Identifier
91233237Sjkim *              Persist             - Keep define across multiple compiles?
92233237Sjkim *
93233237Sjkim * RETURN:      A new define_info struct. NULL on error.
94233237Sjkim *
95233237Sjkim * DESCRIPTION: Add a new #define to the global list
96233237Sjkim *
97233237Sjkim ******************************************************************************/
98233237Sjkim
99233237SjkimPR_DEFINE_INFO *
100233237SjkimPrAddDefine (
101233237Sjkim    char                    *Identifier,
102233237Sjkim    char                    *Replacement,
103233237Sjkim    BOOLEAN                 Persist)
104233237Sjkim{
105233237Sjkim    char                    *IdentifierString;
106233237Sjkim    char                    *ReplacementString;
107233237Sjkim    PR_DEFINE_INFO          *DefineInfo;
108233237Sjkim
109233237Sjkim
110233237Sjkim    if (!Replacement)
111233237Sjkim    {
112233237Sjkim        Replacement = "";
113233237Sjkim    }
114233237Sjkim
115233237Sjkim    /* Check for already-defined first */
116233237Sjkim
117233237Sjkim    DefineInfo = PrMatchDefine (Identifier);
118233237Sjkim    if (DefineInfo)
119233237Sjkim    {
120233237Sjkim        DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID,
121233237Sjkim            "#define: name already exists: %s\n",
122233237Sjkim            Gbl_CurrentLineNumber, Identifier);
123233237Sjkim
124233237Sjkim        /*
125233237Sjkim         * Name already exists. This is only an error if the target name
126233237Sjkim         * is different.
127233237Sjkim         */
128233237Sjkim        if (strcmp (Replacement, DefineInfo->Replacement))
129233237Sjkim        {
130233237Sjkim            PrError (ASL_ERROR, ASL_MSG_EXISTING_NAME,
131233237Sjkim                THIS_TOKEN_OFFSET (Identifier));
132233237Sjkim
133233237Sjkim            return (NULL);
134233237Sjkim        }
135233237Sjkim
136233237Sjkim        return (DefineInfo);
137233237Sjkim    }
138233237Sjkim
139233237Sjkim    /* Copy input strings */
140233237Sjkim
141233237Sjkim    IdentifierString = UtLocalCalloc (strlen (Identifier) + 1);
142233237Sjkim    strcpy (IdentifierString, Identifier);
143233237Sjkim
144233237Sjkim    ReplacementString = UtLocalCalloc (strlen (Replacement) + 1);
145233237Sjkim    strcpy (ReplacementString, Replacement);
146233237Sjkim
147233237Sjkim    /* Init and link new define info struct */
148233237Sjkim
149233237Sjkim    DefineInfo = UtLocalCalloc (sizeof (PR_DEFINE_INFO));
150233237Sjkim    DefineInfo->Replacement = ReplacementString;
151233237Sjkim    DefineInfo->Identifier = IdentifierString;
152233237Sjkim    DefineInfo->Persist = Persist;
153233237Sjkim
154233237Sjkim    if (Gbl_DefineList)
155233237Sjkim    {
156233237Sjkim        Gbl_DefineList->Previous = DefineInfo;
157233237Sjkim    }
158233237Sjkim
159233237Sjkim    DefineInfo->Next = Gbl_DefineList;
160233237Sjkim    Gbl_DefineList = DefineInfo;
161233237Sjkim    return (DefineInfo);
162233237Sjkim}
163233237Sjkim
164233237Sjkim
165233237Sjkim/*******************************************************************************
166233237Sjkim *
167233237Sjkim * FUNCTION:    PrRemoveDefine
168233237Sjkim *
169233237Sjkim * PARAMETERS:  DefineName          - Name of define to be removed
170233237Sjkim *
171233237Sjkim * RETURN:      None
172233237Sjkim *
173233237Sjkim * DESCRIPTION: Implements #undef. Remove a #define if found in the global
174233237Sjkim *              list. No error if the target of the #undef does not exist,
175233237Sjkim *              as per the C #undef definition.
176233237Sjkim *
177233237Sjkim ******************************************************************************/
178233237Sjkim
179233237Sjkimvoid
180233237SjkimPrRemoveDefine (
181233237Sjkim    char                    *DefineName)
182233237Sjkim{
183233237Sjkim    PR_DEFINE_INFO          *DefineInfo;
184233237Sjkim
185233237Sjkim
186233237Sjkim    /* Match name and delete the node */
187233237Sjkim
188233237Sjkim    DefineInfo = Gbl_DefineList;
189233237Sjkim    while (DefineInfo)
190233237Sjkim    {
191233237Sjkim        if (!strcmp (DefineName, DefineInfo->Identifier))
192233237Sjkim        {
193233237Sjkim            /* Remove from linked list */
194233237Sjkim
195233237Sjkim            if (DefineInfo->Previous)
196233237Sjkim            {
197233237Sjkim                (DefineInfo->Previous)->Next = DefineInfo->Next;
198233237Sjkim            }
199233237Sjkim            else
200233237Sjkim            {
201233237Sjkim                Gbl_DefineList = DefineInfo->Next;
202233237Sjkim            }
203233237Sjkim
204233237Sjkim            if (DefineInfo->Next)
205233237Sjkim            {
206233237Sjkim                (DefineInfo->Next)->Previous = DefineInfo->Previous;
207233237Sjkim            }
208233237Sjkim
209233237Sjkim            free (DefineInfo);
210233237Sjkim            return;
211233237Sjkim        }
212233237Sjkim
213233237Sjkim        DefineInfo = DefineInfo->Next;
214233237Sjkim    }
215233237Sjkim
216233237Sjkim    /*
217233237Sjkim     * Name was not found. By definition of #undef, this is not
218233237Sjkim     * an error, however.
219233237Sjkim     */
220233237Sjkim    DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
221233237Sjkim        "#undef: could not find %s\n",
222233237Sjkim        Gbl_CurrentLineNumber, DefineName);
223233237Sjkim}
224233237Sjkim
225233237Sjkim
226233237Sjkim/*******************************************************************************
227233237Sjkim *
228233237Sjkim * FUNCTION:    PrMatchDefine
229233237Sjkim *
230233237Sjkim * PARAMETERS:  MatchString         - Name associated with the #define
231233237Sjkim *
232233237Sjkim * RETURN:      Matched string if found. NULL otherwise.
233233237Sjkim *
234233237Sjkim * DESCRIPTION: Find a name in global #define list
235233237Sjkim *
236233237Sjkim ******************************************************************************/
237233237Sjkim
238233237SjkimPR_DEFINE_INFO *
239233237SjkimPrMatchDefine (
240233237Sjkim    char                    *MatchString)
241233237Sjkim{
242233237Sjkim    PR_DEFINE_INFO          *DefineInfo;
243233237Sjkim
244233237Sjkim
245233237Sjkim    DefineInfo = Gbl_DefineList;
246233237Sjkim    while (DefineInfo)
247233237Sjkim    {
248233237Sjkim        if (!strcmp (MatchString, DefineInfo->Identifier))
249233237Sjkim        {
250233237Sjkim            return (DefineInfo);
251233237Sjkim        }
252233237Sjkim
253233237Sjkim        DefineInfo = DefineInfo->Next;
254233237Sjkim    }
255233237Sjkim
256233237Sjkim    return (NULL);
257233237Sjkim}
258233237Sjkim
259233237Sjkim
260233237Sjkim/*******************************************************************************
261233237Sjkim *
262233237Sjkim * FUNCTION:    PrAddMacro
263233237Sjkim *
264233237Sjkim * PARAMETERS:  Name                - Start of the macro definition
265233237Sjkim *              Next                - "Next" buffer from GetNextToken
266233237Sjkim *
267233237Sjkim * RETURN:      None
268233237Sjkim *
269233237Sjkim * DESCRIPTION: Add a new macro to the list of #defines. Handles argument
270233237Sjkim *              processing.
271233237Sjkim *
272233237Sjkim ******************************************************************************/
273233237Sjkim
274233237Sjkimvoid
275233237SjkimPrAddMacro (
276233237Sjkim    char                    *Name,
277233237Sjkim    char                    **Next)
278233237Sjkim{
279233237Sjkim    char                    *Token = NULL;
280233237Sjkim    ACPI_SIZE               TokenOffset;
281233237Sjkim    ACPI_SIZE               MacroBodyOffset;
282233237Sjkim    PR_DEFINE_INFO          *DefineInfo;
283233237Sjkim    PR_MACRO_ARG            *Args;
284233237Sjkim    char                    *Body;
285233237Sjkim    char                    *BodyInSource;
286233237Sjkim    UINT32                  i;
287233237Sjkim    UINT16                  UseCount = 0;
288233237Sjkim    UINT16                  ArgCount = 0;
289233237Sjkim    UINT32                  Depth = 1;
290233237Sjkim    UINT32                  EndOfArgList;
291233237Sjkim    char                    BufferChar;
292233237Sjkim
293233237Sjkim
294233237Sjkim    /* Find the end of the arguments list */
295233237Sjkim
296233237Sjkim    TokenOffset = Name - Gbl_MainTokenBuffer + strlen (Name) + 1;
297233237Sjkim    while (1)
298233237Sjkim    {
299233237Sjkim        BufferChar = Gbl_CurrentLineBuffer[TokenOffset];
300233237Sjkim        if (BufferChar == '(')
301233237Sjkim        {
302233237Sjkim            Depth++;
303233237Sjkim        }
304233237Sjkim        else if (BufferChar == ')')
305233237Sjkim        {
306233237Sjkim            Depth--;
307233237Sjkim        }
308233237Sjkim        else if (BufferChar == 0)
309233237Sjkim        {
310233237Sjkim            PrError (ASL_ERROR, ASL_MSG_MACRO_SYNTAX, TokenOffset);
311233237Sjkim            return;
312233237Sjkim        }
313233237Sjkim
314233237Sjkim        if (Depth == 0)
315233237Sjkim        {
316233237Sjkim            /* Found arg list end */
317233237Sjkim
318233237Sjkim            EndOfArgList = TokenOffset;
319233237Sjkim            break;
320233237Sjkim        }
321233237Sjkim
322233237Sjkim        TokenOffset++;
323233237Sjkim    }
324233237Sjkim
325233237Sjkim    /* At this point, we know that we have a reasonable argument list */
326233237Sjkim
327233237Sjkim    Args = UtLocalCalloc (sizeof (PR_MACRO_ARG) * PR_MAX_MACRO_ARGS);
328233237Sjkim
329233237Sjkim    /* Get the macro argument names */
330233237Sjkim
331233237Sjkim    for (i = 0; i < PR_MAX_MACRO_ARGS; i++)
332233237Sjkim    {
333233237Sjkim        Token = PrGetNextToken (NULL, PR_MACRO_SEPARATORS, Next);
334233237Sjkim        if (!Token)
335233237Sjkim        {
336233237Sjkim            /* This is the case for a NULL macro body */
337233237Sjkim
338233237Sjkim            BodyInSource = "";
339233237Sjkim            goto AddMacroToList;
340233237Sjkim        }
341233237Sjkim
342233237Sjkim        /* Don't go beyond the argument list */
343233237Sjkim
344233237Sjkim        TokenOffset = Token - Gbl_MainTokenBuffer + strlen (Token);
345233237Sjkim        if (TokenOffset > EndOfArgList)
346233237Sjkim        {
347233237Sjkim            break;
348233237Sjkim        }
349233237Sjkim
350233237Sjkim        DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
351233237Sjkim            "Macro arg: %s \n",
352233237Sjkim            Gbl_CurrentLineNumber, Token);
353233237Sjkim
354233237Sjkim        Args[i].Name = UtLocalCalloc (strlen (Token) + 1);
355233237Sjkim        strcpy (Args[i].Name, Token);
356233237Sjkim
357233237Sjkim        Args[i].UseCount = 0;
358233237Sjkim
359233237Sjkim        ArgCount++;
360233237Sjkim        if (ArgCount >= PR_MAX_MACRO_ARGS)
361233237Sjkim        {
362233237Sjkim            PrError (ASL_ERROR, ASL_MSG_TOO_MANY_ARGUMENTS, TokenOffset);
363233237Sjkim            return;
364233237Sjkim        }
365233237Sjkim    }
366233237Sjkim
367233237Sjkim    /* Get the macro body. Token now points to start of body */
368233237Sjkim
369233237Sjkim    MacroBodyOffset = Token - Gbl_MainTokenBuffer;
370233237Sjkim
371233237Sjkim    /* Match each method arg in the macro body for later use */
372233237Sjkim
373233237Sjkim    Token = PrGetNextToken (NULL, PR_MACRO_SEPARATORS, Next);
374233237Sjkim    while (Token)
375233237Sjkim    {
376233237Sjkim        /* Search the macro arg list for matching arg */
377233237Sjkim
378233237Sjkim        for (i = 0; Args[i].Name && (i < PR_MAX_MACRO_ARGS); i++)
379233237Sjkim        {
380233237Sjkim            /*
381233237Sjkim             * Save argument offset within macro body. This is the mechanism
382233237Sjkim             * used to expand the macro upon invocation.
383233237Sjkim             *
384233237Sjkim             * Handles multiple instances of the same argument
385233237Sjkim             */
386233237Sjkim            if (!strcmp (Token, Args[i].Name))
387233237Sjkim            {
388233237Sjkim                UseCount = Args[i].UseCount;
389233237Sjkim
390233237Sjkim                Args[i].Offset[UseCount] = (Token - Gbl_MainTokenBuffer) - MacroBodyOffset;
391233237Sjkim
392233237Sjkim                DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
393233237Sjkim                    "Macro Arg #%u: %s UseCount %u Offset %u \n",
394233237Sjkim                    Gbl_CurrentLineNumber, i, Token,
395233237Sjkim                    UseCount+1, Args[i].Offset[UseCount]);
396233237Sjkim
397233237Sjkim                Args[i].UseCount++;
398233237Sjkim                if (Args[i].UseCount >= PR_MAX_ARG_INSTANCES)
399233237Sjkim                {
400233237Sjkim                    PrError (ASL_ERROR, ASL_MSG_TOO_MANY_ARGUMENTS,
401233237Sjkim                        THIS_TOKEN_OFFSET (Token));
402233237Sjkim
403233237Sjkim                    return;
404233237Sjkim                }
405233237Sjkim                break;
406233237Sjkim            }
407233237Sjkim        }
408233237Sjkim
409233237Sjkim        Token = PrGetNextToken (NULL, PR_MACRO_SEPARATORS, Next);
410233237Sjkim    }
411233237Sjkim
412233237Sjkim    BodyInSource = &Gbl_CurrentLineBuffer[MacroBodyOffset];
413233237Sjkim
414233237Sjkim
415233237SjkimAddMacroToList:
416233237Sjkim
417233237Sjkim    /* Check if name is already defined first */
418233237Sjkim
419233237Sjkim    DefineInfo = PrMatchDefine (Name);
420233237Sjkim    if (DefineInfo)
421233237Sjkim    {
422233237Sjkim        DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
423233237Sjkim            "#define: macro name already exists: %s\n",
424233237Sjkim            Gbl_CurrentLineNumber, Name);
425233237Sjkim
426233237Sjkim        /* Error only if not exactly the same macro */
427233237Sjkim
428233237Sjkim        if (strcmp (DefineInfo->Body, BodyInSource) ||
429233237Sjkim            (DefineInfo->ArgCount != ArgCount))
430233237Sjkim        {
431233237Sjkim            PrError (ASL_ERROR, ASL_MSG_EXISTING_NAME,
432233237Sjkim                THIS_TOKEN_OFFSET (Name));
433233237Sjkim        }
434233237Sjkim
435233237Sjkim        return;
436233237Sjkim    }
437233237Sjkim
438233237Sjkim    DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
439233237Sjkim        "Macro body: %s \n",
440233237Sjkim        Gbl_CurrentLineNumber, BodyInSource);
441233237Sjkim
442233237Sjkim    /* Add macro to the #define list */
443233237Sjkim
444233237Sjkim    DefineInfo = PrAddDefine (Name, BodyInSource, FALSE);
445233237Sjkim    if (DefineInfo)
446233237Sjkim    {
447233237Sjkim        Body = UtLocalCalloc (strlen (BodyInSource) + 1);
448233237Sjkim        strcpy (Body, BodyInSource);
449233237Sjkim
450233237Sjkim        DefineInfo->Body = Body;
451233237Sjkim        DefineInfo->Args = Args;
452233237Sjkim        DefineInfo->ArgCount = ArgCount;
453233237Sjkim    }
454233237Sjkim}
455233237Sjkim
456233237Sjkim
457233237Sjkim/*******************************************************************************
458233237Sjkim *
459233237Sjkim * FUNCTION:    PrDoMacroInvocation
460233237Sjkim *
461233237Sjkim * PARAMETERS:  TokenBuffer         - Current line buffer
462233237Sjkim *              MacroStart          - Start of the macro invocation within
463233237Sjkim *                                    the token buffer
464233237Sjkim *              DefineInfo          - Info for this macro
465233237Sjkim *              Next                - "Next" buffer from GetNextToken
466233237Sjkim *
467233237Sjkim * RETURN:      None
468233237Sjkim *
469233237Sjkim * DESCRIPTION: Expand a macro invocation
470233237Sjkim *
471233237Sjkim ******************************************************************************/
472233237Sjkim
473233237Sjkimvoid
474233237SjkimPrDoMacroInvocation (
475233237Sjkim    char                    *TokenBuffer,
476233237Sjkim    char                    *MacroStart,
477233237Sjkim    PR_DEFINE_INFO          *DefineInfo,
478233237Sjkim    char                    **Next)
479233237Sjkim{
480233237Sjkim    PR_MACRO_ARG            *Args;
481233237Sjkim    char                    *Token = NULL;
482233237Sjkim    UINT32                  TokenOffset;
483233237Sjkim    UINT32                  Length;
484233237Sjkim    UINT32                  i;
485233237Sjkim
486233237Sjkim
487233237Sjkim    /* Take a copy of the macro body for expansion */
488233237Sjkim
489233237Sjkim    strcpy (Gbl_MacroTokenBuffer, DefineInfo->Body);
490233237Sjkim
491233237Sjkim    /* Replace each argument within the prototype body */
492233237Sjkim
493233237Sjkim    Args = DefineInfo->Args;
494233237Sjkim    if (!Args->Name)
495233237Sjkim    {
496233237Sjkim        /* This macro has no arguments */
497233237Sjkim
498233237Sjkim        Token = PrGetNextToken (NULL, PR_MACRO_ARGUMENTS, Next);
499233237Sjkim        if (!Token)
500233237Sjkim        {
501233237Sjkim            goto BadInvocation;
502233237Sjkim        }
503233237Sjkim
504233237Sjkim        TokenOffset = (MacroStart - TokenBuffer);
505233237Sjkim        Length = Token - MacroStart + strlen (Token) + 1;
506233237Sjkim
507233237Sjkim        PrReplaceData (
508233237Sjkim            &Gbl_CurrentLineBuffer[TokenOffset], Length,
509233237Sjkim            Gbl_MacroTokenBuffer, strlen (Gbl_MacroTokenBuffer));
510233237Sjkim        return;
511233237Sjkim    }
512233237Sjkim
513233237Sjkim    while (Args->Name)
514233237Sjkim    {
515233237Sjkim        /* Get the next argument from macro invocation */
516233237Sjkim
517233237Sjkim        Token = PrGetNextToken (NULL, PR_MACRO_SEPARATORS, Next);
518233237Sjkim        if (!Token)
519233237Sjkim        {
520233237Sjkim            goto BadInvocation;
521233237Sjkim        }
522233237Sjkim
523233237Sjkim        /* Replace all instances of this argument */
524233237Sjkim
525233237Sjkim        for (i = 0; i < Args->UseCount; i++)
526233237Sjkim        {
527233237Sjkim            /* Offset zero indicates "arg not used" */
528233237Sjkim            /* TBD: Not really needed now, with UseCount available */
529233237Sjkim
530233237Sjkim            if (Args->Offset[i] == 0)
531233237Sjkim            {
532233237Sjkim                break;
533233237Sjkim            }
534233237Sjkim
535233237Sjkim            PrReplaceData (
536233237Sjkim                &Gbl_MacroTokenBuffer[Args->Offset[i]], strlen (Args->Name),
537233237Sjkim                Token, strlen (Token));
538233237Sjkim
539233237Sjkim            DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
540233237Sjkim                "ExpandArg: %s \n",
541233237Sjkim                Gbl_CurrentLineNumber, Gbl_MacroTokenBuffer);
542233237Sjkim        }
543233237Sjkim
544233237Sjkim        Args++;
545233237Sjkim    }
546233237Sjkim
547233237Sjkim    /* TBD: need to make sure macro was not invoked with too many arguments */
548233237Sjkim
549233237Sjkim    if (!Token)
550233237Sjkim    {
551233237Sjkim        return;
552233237Sjkim    }
553233237Sjkim
554233237Sjkim    /* Replace the entire macro invocation with the expanded macro */
555233237Sjkim
556233237Sjkim    TokenOffset = (MacroStart - TokenBuffer);
557233237Sjkim    Length = Token - MacroStart + strlen (Token) + 1;
558233237Sjkim
559233237Sjkim    PrReplaceData (
560233237Sjkim        &Gbl_CurrentLineBuffer[TokenOffset], Length,
561233237Sjkim        Gbl_MacroTokenBuffer, strlen (Gbl_MacroTokenBuffer));
562233237Sjkim
563233237Sjkim    return;
564233237Sjkim
565233237Sjkim
566233237SjkimBadInvocation:
567233237Sjkim    PrError (ASL_ERROR, ASL_MSG_INVALID_INVOCATION,
568233237Sjkim        THIS_TOKEN_OFFSET (MacroStart));
569233237Sjkim
570233237Sjkim    DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
571233237Sjkim        "Bad macro invocation: %s \n",
572233237Sjkim        Gbl_CurrentLineNumber, Gbl_MacroTokenBuffer);
573233237Sjkim    return;
574233237Sjkim}
575