1233237Sjkim/******************************************************************************
2233237Sjkim *
3233237Sjkim * Module Name: prmacros - Preprocessor #define macro support
4233237Sjkim *
5233237Sjkim *****************************************************************************/
6233237Sjkim
7233237Sjkim/*
8306536Sjkim * Copyright (C) 2000 - 2016, 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);
363281075Sdim            goto ErrorExit;
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
390306536Sjkim                Args[i].Offset[UseCount] =
391306536Sjkim                    (Token - Gbl_MainTokenBuffer) - MacroBodyOffset;
392233237Sjkim
393233237Sjkim                DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
394233237Sjkim                    "Macro Arg #%u: %s UseCount %u Offset %u \n",
395233237Sjkim                    Gbl_CurrentLineNumber, i, Token,
396233237Sjkim                    UseCount+1, Args[i].Offset[UseCount]);
397233237Sjkim
398233237Sjkim                Args[i].UseCount++;
399233237Sjkim                if (Args[i].UseCount >= PR_MAX_ARG_INSTANCES)
400233237Sjkim                {
401233237Sjkim                    PrError (ASL_ERROR, ASL_MSG_TOO_MANY_ARGUMENTS,
402233237Sjkim                        THIS_TOKEN_OFFSET (Token));
403233237Sjkim
404281075Sdim                    goto ErrorExit;
405233237Sjkim                }
406233237Sjkim                break;
407233237Sjkim            }
408233237Sjkim        }
409233237Sjkim
410233237Sjkim        Token = PrGetNextToken (NULL, PR_MACRO_SEPARATORS, Next);
411233237Sjkim    }
412233237Sjkim
413233237Sjkim    BodyInSource = &Gbl_CurrentLineBuffer[MacroBodyOffset];
414233237Sjkim
415233237Sjkim
416233237SjkimAddMacroToList:
417233237Sjkim
418233237Sjkim    /* Check if name is already defined first */
419233237Sjkim
420233237Sjkim    DefineInfo = PrMatchDefine (Name);
421233237Sjkim    if (DefineInfo)
422233237Sjkim    {
423233237Sjkim        DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
424233237Sjkim            "#define: macro name already exists: %s\n",
425233237Sjkim            Gbl_CurrentLineNumber, Name);
426233237Sjkim
427233237Sjkim        /* Error only if not exactly the same macro */
428233237Sjkim
429233237Sjkim        if (strcmp (DefineInfo->Body, BodyInSource) ||
430233237Sjkim            (DefineInfo->ArgCount != ArgCount))
431233237Sjkim        {
432233237Sjkim            PrError (ASL_ERROR, ASL_MSG_EXISTING_NAME,
433233237Sjkim                THIS_TOKEN_OFFSET (Name));
434233237Sjkim        }
435233237Sjkim
436281075Sdim        goto ErrorExit;
437233237Sjkim    }
438233237Sjkim
439233237Sjkim    DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
440233237Sjkim        "Macro body: %s \n",
441233237Sjkim        Gbl_CurrentLineNumber, BodyInSource);
442233237Sjkim
443233237Sjkim    /* Add macro to the #define list */
444233237Sjkim
445233237Sjkim    DefineInfo = PrAddDefine (Name, BodyInSource, FALSE);
446233237Sjkim    if (DefineInfo)
447233237Sjkim    {
448233237Sjkim        Body = UtLocalCalloc (strlen (BodyInSource) + 1);
449233237Sjkim        strcpy (Body, BodyInSource);
450233237Sjkim
451233237Sjkim        DefineInfo->Body = Body;
452233237Sjkim        DefineInfo->Args = Args;
453233237Sjkim        DefineInfo->ArgCount = ArgCount;
454233237Sjkim    }
455281075Sdim
456281075Sdim    return;
457281075Sdim
458281075Sdim
459281075SdimErrorExit:
460281075Sdim    ACPI_FREE (Args);
461281075Sdim    return;
462233237Sjkim}
463233237Sjkim
464233237Sjkim
465233237Sjkim/*******************************************************************************
466233237Sjkim *
467233237Sjkim * FUNCTION:    PrDoMacroInvocation
468233237Sjkim *
469233237Sjkim * PARAMETERS:  TokenBuffer         - Current line buffer
470233237Sjkim *              MacroStart          - Start of the macro invocation within
471233237Sjkim *                                    the token buffer
472233237Sjkim *              DefineInfo          - Info for this macro
473233237Sjkim *              Next                - "Next" buffer from GetNextToken
474233237Sjkim *
475233237Sjkim * RETURN:      None
476233237Sjkim *
477233237Sjkim * DESCRIPTION: Expand a macro invocation
478233237Sjkim *
479233237Sjkim ******************************************************************************/
480233237Sjkim
481233237Sjkimvoid
482233237SjkimPrDoMacroInvocation (
483233237Sjkim    char                    *TokenBuffer,
484233237Sjkim    char                    *MacroStart,
485233237Sjkim    PR_DEFINE_INFO          *DefineInfo,
486233237Sjkim    char                    **Next)
487233237Sjkim{
488233237Sjkim    PR_MACRO_ARG            *Args;
489233237Sjkim    char                    *Token = NULL;
490233237Sjkim    UINT32                  TokenOffset;
491233237Sjkim    UINT32                  Length;
492233237Sjkim    UINT32                  i;
493233237Sjkim
494233237Sjkim
495233237Sjkim    /* Take a copy of the macro body for expansion */
496233237Sjkim
497233237Sjkim    strcpy (Gbl_MacroTokenBuffer, DefineInfo->Body);
498233237Sjkim
499233237Sjkim    /* Replace each argument within the prototype body */
500233237Sjkim
501233237Sjkim    Args = DefineInfo->Args;
502233237Sjkim    if (!Args->Name)
503233237Sjkim    {
504233237Sjkim        /* This macro has no arguments */
505233237Sjkim
506233237Sjkim        Token = PrGetNextToken (NULL, PR_MACRO_ARGUMENTS, Next);
507233237Sjkim        if (!Token)
508233237Sjkim        {
509233237Sjkim            goto BadInvocation;
510233237Sjkim        }
511233237Sjkim
512233237Sjkim        TokenOffset = (MacroStart - TokenBuffer);
513233237Sjkim        Length = Token - MacroStart + strlen (Token) + 1;
514233237Sjkim
515233237Sjkim        PrReplaceData (
516233237Sjkim            &Gbl_CurrentLineBuffer[TokenOffset], Length,
517233237Sjkim            Gbl_MacroTokenBuffer, strlen (Gbl_MacroTokenBuffer));
518233237Sjkim        return;
519233237Sjkim    }
520233237Sjkim
521233237Sjkim    while (Args->Name)
522233237Sjkim    {
523233237Sjkim        /* Get the next argument from macro invocation */
524233237Sjkim
525233237Sjkim        Token = PrGetNextToken (NULL, PR_MACRO_SEPARATORS, Next);
526233237Sjkim        if (!Token)
527233237Sjkim        {
528233237Sjkim            goto BadInvocation;
529233237Sjkim        }
530233237Sjkim
531233237Sjkim        /* Replace all instances of this argument */
532233237Sjkim
533233237Sjkim        for (i = 0; i < Args->UseCount; i++)
534233237Sjkim        {
535233237Sjkim            /* Offset zero indicates "arg not used" */
536233237Sjkim            /* TBD: Not really needed now, with UseCount available */
537233237Sjkim
538233237Sjkim            if (Args->Offset[i] == 0)
539233237Sjkim            {
540233237Sjkim                break;
541233237Sjkim            }
542233237Sjkim
543233237Sjkim            PrReplaceData (
544233237Sjkim                &Gbl_MacroTokenBuffer[Args->Offset[i]], strlen (Args->Name),
545233237Sjkim                Token, strlen (Token));
546233237Sjkim
547233237Sjkim            DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
548233237Sjkim                "ExpandArg: %s \n",
549233237Sjkim                Gbl_CurrentLineNumber, Gbl_MacroTokenBuffer);
550233237Sjkim        }
551233237Sjkim
552233237Sjkim        Args++;
553233237Sjkim    }
554233237Sjkim
555233237Sjkim    /* TBD: need to make sure macro was not invoked with too many arguments */
556233237Sjkim
557233237Sjkim    if (!Token)
558233237Sjkim    {
559233237Sjkim        return;
560233237Sjkim    }
561233237Sjkim
562233237Sjkim    /* Replace the entire macro invocation with the expanded macro */
563233237Sjkim
564233237Sjkim    TokenOffset = (MacroStart - TokenBuffer);
565233237Sjkim    Length = Token - MacroStart + strlen (Token) + 1;
566233237Sjkim
567233237Sjkim    PrReplaceData (
568233237Sjkim        &Gbl_CurrentLineBuffer[TokenOffset], Length,
569233237Sjkim        Gbl_MacroTokenBuffer, strlen (Gbl_MacroTokenBuffer));
570233237Sjkim
571233237Sjkim    return;
572233237Sjkim
573233237Sjkim
574233237SjkimBadInvocation:
575233237Sjkim    PrError (ASL_ERROR, ASL_MSG_INVALID_INVOCATION,
576233237Sjkim        THIS_TOKEN_OFFSET (MacroStart));
577233237Sjkim
578233237Sjkim    DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
579233237Sjkim        "Bad macro invocation: %s \n",
580233237Sjkim        Gbl_CurrentLineNumber, Gbl_MacroTokenBuffer);
581233237Sjkim    return;
582233237Sjkim}
583