xref: /illumos-gate/usr/src/cmd/acpi/iasl/prmacros.c (revision 1566bc3431383e39ac9bc7fb7f00feff9c06acda)
1 /******************************************************************************
2  *
3  * Module Name: prmacros - Preprocessor #define macro support
4  *
5  *****************************************************************************/
6 
7 /******************************************************************************
8  *
9  * 1. Copyright Notice
10  *
11  * Some or all of this work - Copyright (c) 1999 - 2018, Intel Corp.
12  * All rights reserved.
13  *
14  * 2. License
15  *
16  * 2.1. This is your license from Intel Corp. under its intellectual property
17  * rights. You may have additional license terms from the party that provided
18  * you this software, covering your right to use that party's intellectual
19  * property rights.
20  *
21  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22  * copy of the source code appearing in this file ("Covered Code") an
23  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24  * base code distributed originally by Intel ("Original Intel Code") to copy,
25  * make derivatives, distribute, use and display any portion of the Covered
26  * Code in any form, with the right to sublicense such rights; and
27  *
28  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29  * license (with the right to sublicense), under only those claims of Intel
30  * patents that are infringed by the Original Intel Code, to make, use, sell,
31  * offer to sell, and import the Covered Code and derivative works thereof
32  * solely to the minimum extent necessary to exercise the above copyright
33  * license, and in no event shall the patent license extend to any additions
34  * to or modifications of the Original Intel Code. No other license or right
35  * is granted directly or by implication, estoppel or otherwise;
36  *
37  * The above copyright and patent license is granted only if the following
38  * conditions are met:
39  *
40  * 3. Conditions
41  *
42  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43  * Redistribution of source code of any substantial portion of the Covered
44  * Code or modification with rights to further distribute source must include
45  * the above Copyright Notice, the above License, this list of Conditions,
46  * and the following Disclaimer and Export Compliance provision. In addition,
47  * Licensee must cause all Covered Code to which Licensee contributes to
48  * contain a file documenting the changes Licensee made to create that Covered
49  * Code and the date of any change. Licensee must include in that file the
50  * documentation of any changes made by any predecessor Licensee. Licensee
51  * must include a prominent statement that the modification is derived,
52  * directly or indirectly, from Original Intel Code.
53  *
54  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55  * Redistribution of source code of any substantial portion of the Covered
56  * Code or modification without rights to further distribute source must
57  * include the following Disclaimer and Export Compliance provision in the
58  * documentation and/or other materials provided with distribution. In
59  * addition, Licensee may not authorize further sublicense of source of any
60  * portion of the Covered Code, and must include terms to the effect that the
61  * license from Licensee to its licensee is limited to the intellectual
62  * property embodied in the software Licensee provides to its licensee, and
63  * not to intellectual property embodied in modifications its licensee may
64  * make.
65  *
66  * 3.3. Redistribution of Executable. Redistribution in executable form of any
67  * substantial portion of the Covered Code or modification must reproduce the
68  * above Copyright Notice, and the following Disclaimer and Export Compliance
69  * provision in the documentation and/or other materials provided with the
70  * distribution.
71  *
72  * 3.4. Intel retains all right, title, and interest in and to the Original
73  * Intel Code.
74  *
75  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76  * Intel shall be used in advertising or otherwise to promote the sale, use or
77  * other dealings in products derived from or relating to the Covered Code
78  * without prior written authorization from Intel.
79  *
80  * 4. Disclaimer and Export Compliance
81  *
82  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88  * PARTICULAR PURPOSE.
89  *
90  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97  * LIMITED REMEDY.
98  *
99  * 4.3. Licensee shall not export, either directly or indirectly, any of this
100  * software or system incorporating such software without first obtaining any
101  * required license or other approval from the U. S. Department of Commerce or
102  * any other agency or department of the United States Government. In the
103  * event Licensee exports any such software from the United States or
104  * re-exports any such software from a foreign destination, Licensee shall
105  * ensure that the distribution and export/re-export of the software is in
106  * compliance with all laws, regulations, orders, or other restrictions of the
107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108  * any of its subsidiaries will export/re-export any technical data, process,
109  * software, or service, directly or indirectly, to any country for which the
110  * United States government or any agency thereof requires an export license,
111  * other governmental approval, or letter of assurance, without first obtaining
112  * such license, approval or letter.
113  *
114  *****************************************************************************
115  *
116  * Alternatively, you may choose to be licensed under the terms of the
117  * following license:
118  *
119  * Redistribution and use in source and binary forms, with or without
120  * modification, are permitted provided that the following conditions
121  * are met:
122  * 1. Redistributions of source code must retain the above copyright
123  *    notice, this list of conditions, and the following disclaimer,
124  *    without modification.
125  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
126  *    substantially similar to the "NO WARRANTY" disclaimer below
127  *    ("Disclaimer") and any redistribution must be conditioned upon
128  *    including a substantially similar Disclaimer requirement for further
129  *    binary redistribution.
130  * 3. Neither the names of the above-listed copyright holders nor the names
131  *    of any contributors may be used to endorse or promote products derived
132  *    from this software without specific prior written permission.
133  *
134  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
135  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
136  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
137  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
138  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
139  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
140  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
141  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
142  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
143  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
144  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
145  *
146  * Alternatively, you may choose to be licensed under the terms of the
147  * GNU General Public License ("GPL") version 2 as published by the Free
148  * Software Foundation.
149  *
150  *****************************************************************************/
151 
152 #include "aslcompiler.h"
153 
154 #define _COMPONENT          ASL_PREPROCESSOR
155         ACPI_MODULE_NAME    ("prmacros")
156 
157 
158 /*******************************************************************************
159  *
160  * FUNCTION:    PrDumpPredefinedNames
161  *
162  * PARAMETERS:  None
163  *
164  * RETURN:      None
165  *
166  * DESCRIPTION: Dump the list of #defines. Used as the preprocessor starts, to
167  *              display the names that were defined on the command line.
168  *              Debug information only.
169  *
170  ******************************************************************************/
171 
172 void
173 PrDumpPredefinedNames (
174     void)
175 {
176     PR_DEFINE_INFO          *DefineInfo;
177 
178 
179     DefineInfo = Gbl_DefineList;
180     while (DefineInfo)
181     {
182         DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
183             "Predefined #define: %s->%s\n",
184             0, DefineInfo->Identifier, DefineInfo->Replacement);
185 
186         DefineInfo = DefineInfo->Next;
187     }
188 }
189 
190 
191 /*******************************************************************************
192  *
193  * FUNCTION:    PrAddDefine
194  *
195  * PARAMETERS:  Identifier          - Name to be replaced
196  *              Replacement         - Replacement for Identifier
197  *              Persist             - Keep define across multiple compiles?
198  *
199  * RETURN:      A new define_info struct. NULL on error.
200  *
201  * DESCRIPTION: Add a new #define to the global list
202  *
203  ******************************************************************************/
204 
205 PR_DEFINE_INFO *
206 PrAddDefine (
207     char                    *Identifier,
208     char                    *Replacement,
209     BOOLEAN                 Persist)
210 {
211     char                    *IdentifierString;
212     char                    *ReplacementString;
213     PR_DEFINE_INFO          *DefineInfo;
214 
215 
216     if (!Replacement)
217     {
218         Replacement = "";
219     }
220 
221     /* Check for already-defined first */
222 
223     DefineInfo = PrMatchDefine (Identifier);
224     if (DefineInfo)
225     {
226         DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID,
227             "#define: name already exists: %s\n",
228             Gbl_CurrentLineNumber, Identifier);
229 
230         /*
231          * Name already exists. This is only an error if the target name
232          * is different.
233          */
234         if (strcmp (Replacement, DefineInfo->Replacement))
235         {
236             PrError (ASL_ERROR, ASL_MSG_EXISTING_NAME,
237                 THIS_TOKEN_OFFSET (Identifier));
238 
239             return (NULL);
240         }
241 
242         return (DefineInfo);
243     }
244 
245     /* Copy input strings */
246 
247     IdentifierString = UtLocalCalloc (strlen (Identifier) + 1);
248     strcpy (IdentifierString, Identifier);
249 
250     ReplacementString = UtLocalCalloc (strlen (Replacement) + 1);
251     strcpy (ReplacementString, Replacement);
252 
253     /* Init and link new define info struct */
254 
255     DefineInfo = UtLocalCalloc (sizeof (PR_DEFINE_INFO));
256     DefineInfo->Replacement = ReplacementString;
257     DefineInfo->Identifier = IdentifierString;
258     DefineInfo->Persist = Persist;
259 
260     if (Gbl_DefineList)
261     {
262         Gbl_DefineList->Previous = DefineInfo;
263     }
264 
265     DefineInfo->Next = Gbl_DefineList;
266     Gbl_DefineList = DefineInfo;
267     return (DefineInfo);
268 }
269 
270 
271 /*******************************************************************************
272  *
273  * FUNCTION:    PrRemoveDefine
274  *
275  * PARAMETERS:  DefineName          - Name of define to be removed
276  *
277  * RETURN:      None
278  *
279  * DESCRIPTION: Implements #undef. Remove a #define if found in the global
280  *              list. No error if the target of the #undef does not exist,
281  *              as per the C #undef definition.
282  *
283  ******************************************************************************/
284 
285 void
286 PrRemoveDefine (
287     char                    *DefineName)
288 {
289     PR_DEFINE_INFO          *DefineInfo;
290 
291 
292     /* Match name and delete the node */
293 
294     DefineInfo = Gbl_DefineList;
295     while (DefineInfo)
296     {
297         if (!strcmp (DefineName, DefineInfo->Identifier))
298         {
299             /* Remove from linked list */
300 
301             if (DefineInfo->Previous)
302             {
303                 (DefineInfo->Previous)->Next = DefineInfo->Next;
304             }
305             else
306             {
307                 Gbl_DefineList = DefineInfo->Next;
308             }
309 
310             if (DefineInfo->Next)
311             {
312                 (DefineInfo->Next)->Previous = DefineInfo->Previous;
313             }
314 
315             free (DefineInfo);
316             return;
317         }
318 
319         DefineInfo = DefineInfo->Next;
320     }
321 
322     /*
323      * Name was not found. By definition of #undef, this is not
324      * an error, however.
325      */
326     DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
327         "#undef: could not find %s\n",
328         Gbl_CurrentLineNumber, DefineName);
329 }
330 
331 
332 /*******************************************************************************
333  *
334  * FUNCTION:    PrMatchDefine
335  *
336  * PARAMETERS:  MatchString         - Name associated with the #define
337  *
338  * RETURN:      Matched string if found. NULL otherwise.
339  *
340  * DESCRIPTION: Find a name in global #define list
341  *
342  ******************************************************************************/
343 
344 PR_DEFINE_INFO *
345 PrMatchDefine (
346     char                    *MatchString)
347 {
348     PR_DEFINE_INFO          *DefineInfo;
349 
350 
351     DefineInfo = Gbl_DefineList;
352     while (DefineInfo)
353     {
354         if (!strcmp (MatchString, DefineInfo->Identifier))
355         {
356             return (DefineInfo);
357         }
358 
359         DefineInfo = DefineInfo->Next;
360     }
361 
362     return (NULL);
363 }
364 
365 
366 /*******************************************************************************
367  *
368  * FUNCTION:    PrAddMacro
369  *
370  * PARAMETERS:  Name                - Start of the macro definition
371  *              Next                - "Next" buffer from GetNextToken
372  *
373  * RETURN:      None
374  *
375  * DESCRIPTION: Add a new macro to the list of #defines. Handles argument
376  *              processing.
377  *
378  ******************************************************************************/
379 
380 void
381 PrAddMacro (
382     char                    *Name,
383     char                    **Next)
384 {
385     char                    *Token = NULL;
386     ACPI_SIZE               TokenOffset;
387     ACPI_SIZE               MacroBodyOffset;
388     PR_DEFINE_INFO          *DefineInfo;
389     PR_MACRO_ARG            *Args;
390     char                    *Body;
391     char                    *BodyInSource;
392     UINT32                  i;
393     UINT16                  UseCount = 0;
394     UINT16                  ArgCount = 0;
395     UINT32                  Depth = 1;
396     UINT32                  EndOfArgList;
397     char                    BufferChar;
398 
399 
400     /* Find the end of the arguments list */
401 
402     TokenOffset = Name - Gbl_MainTokenBuffer + strlen (Name) + 1;
403     while (1)
404     {
405         BufferChar = Gbl_CurrentLineBuffer[TokenOffset];
406         if (BufferChar == '(')
407         {
408             Depth++;
409         }
410         else if (BufferChar == ')')
411         {
412             Depth--;
413         }
414         else if (BufferChar == 0)
415         {
416             PrError (ASL_ERROR, ASL_MSG_MACRO_SYNTAX, TokenOffset);
417             return;
418         }
419 
420         if (Depth == 0)
421         {
422             /* Found arg list end */
423 
424             EndOfArgList = TokenOffset;
425             break;
426         }
427 
428         TokenOffset++;
429     }
430 
431     /* At this point, we know that we have a reasonable argument list */
432 
433     Args = UtLocalCalloc (sizeof (PR_MACRO_ARG) * PR_MAX_MACRO_ARGS);
434 
435     /* Get the macro argument names */
436 
437     for (i = 0; i < PR_MAX_MACRO_ARGS; i++)
438     {
439         Token = PrGetNextToken (NULL, PR_MACRO_SEPARATORS, Next);
440         if (!Token)
441         {
442             /* This is the case for a NULL macro body */
443 
444             BodyInSource = "";
445             goto AddMacroToList;
446         }
447 
448         /* Don't go beyond the argument list */
449 
450         TokenOffset = Token - Gbl_MainTokenBuffer + strlen (Token);
451         if (TokenOffset > EndOfArgList)
452         {
453             break;
454         }
455 
456         DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
457             "Macro arg: %s \n",
458             Gbl_CurrentLineNumber, Token);
459 
460         Args[i].Name = UtLocalCalloc (strlen (Token) + 1);
461         strcpy (Args[i].Name, Token);
462 
463         Args[i].UseCount = 0;
464 
465         ArgCount++;
466         if (ArgCount >= PR_MAX_MACRO_ARGS)
467         {
468             PrError (ASL_ERROR, ASL_MSG_TOO_MANY_ARGUMENTS, TokenOffset);
469             goto ErrorExit;
470         }
471     }
472 
473     /* Get the macro body. Token now points to start of body */
474 
475     MacroBodyOffset = Token - Gbl_MainTokenBuffer;
476 
477     /* Match each method arg in the macro body for later use */
478 
479     Token = PrGetNextToken (NULL, PR_MACRO_SEPARATORS, Next);
480     while (Token)
481     {
482         /* Search the macro arg list for matching arg */
483 
484         for (i = 0; ((i < PR_MAX_MACRO_ARGS) && Args[i].Name); i++)
485         {
486             /*
487              * Save argument offset within macro body. This is the mechanism
488              * used to expand the macro upon invocation.
489              *
490              * Handles multiple instances of the same argument
491              */
492             if (!strcmp (Token, Args[i].Name))
493             {
494                 UseCount = Args[i].UseCount;
495 
496                 Args[i].Offset[UseCount] =
497                     (Token - Gbl_MainTokenBuffer) - MacroBodyOffset;
498 
499                 DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
500                     "Macro Arg #%u: %s UseCount %u Offset %u \n",
501                     Gbl_CurrentLineNumber, i, Token,
502                     UseCount+1, Args[i].Offset[UseCount]);
503 
504                 Args[i].UseCount++;
505                 if (Args[i].UseCount >= PR_MAX_ARG_INSTANCES)
506                 {
507                     PrError (ASL_ERROR, ASL_MSG_TOO_MANY_ARGUMENTS,
508                         THIS_TOKEN_OFFSET (Token));
509 
510                     goto ErrorExit;
511                 }
512                 break;
513             }
514         }
515 
516         Token = PrGetNextToken (NULL, PR_MACRO_SEPARATORS, Next);
517     }
518 
519     BodyInSource = &Gbl_CurrentLineBuffer[MacroBodyOffset];
520 
521 
522 AddMacroToList:
523 
524     /* Check if name is already defined first */
525 
526     DefineInfo = PrMatchDefine (Name);
527     if (DefineInfo)
528     {
529         DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
530             "#define: macro name already exists: %s\n",
531             Gbl_CurrentLineNumber, Name);
532 
533         /* Error only if not exactly the same macro */
534 
535         if (strcmp (DefineInfo->Body, BodyInSource) ||
536             (DefineInfo->ArgCount != ArgCount))
537         {
538             PrError (ASL_ERROR, ASL_MSG_EXISTING_NAME,
539                 THIS_TOKEN_OFFSET (Name));
540         }
541 
542         goto ErrorExit;
543     }
544 
545     DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
546         "Macro body: %s \n",
547         Gbl_CurrentLineNumber, BodyInSource);
548 
549     /* Add macro to the #define list */
550 
551     DefineInfo = PrAddDefine (Name, BodyInSource, FALSE);
552     if (DefineInfo)
553     {
554         Body = UtLocalCalloc (strlen (BodyInSource) + 1);
555         strcpy (Body, BodyInSource);
556 
557         DefineInfo->Body = Body;
558         DefineInfo->Args = Args;
559         DefineInfo->ArgCount = ArgCount;
560     }
561 
562     return;
563 
564 
565 ErrorExit:
566     ACPI_FREE (Args);
567     return;
568 }
569 
570 
571 /*******************************************************************************
572  *
573  * FUNCTION:    PrDoMacroInvocation
574  *
575  * PARAMETERS:  TokenBuffer         - Current line buffer
576  *              MacroStart          - Start of the macro invocation within
577  *                                    the token buffer
578  *              DefineInfo          - Info for this macro
579  *              Next                - "Next" buffer from GetNextToken
580  *
581  * RETURN:      None
582  *
583  * DESCRIPTION: Expand a macro invocation
584  *
585  ******************************************************************************/
586 
587 void
588 PrDoMacroInvocation (
589     char                    *TokenBuffer,
590     char                    *MacroStart,
591     PR_DEFINE_INFO          *DefineInfo,
592     char                    **Next)
593 {
594     PR_MACRO_ARG            *Args;
595     char                    *Token = NULL;
596     UINT32                  TokenOffset;
597     UINT32                  Length;
598     UINT32                  i;
599 
600 
601     /* Take a copy of the macro body for expansion */
602 
603     strcpy (Gbl_MacroTokenBuffer, DefineInfo->Body);
604 
605     /* Replace each argument within the prototype body */
606 
607     Args = DefineInfo->Args;
608     if (!Args->Name)
609     {
610         /* This macro has no arguments */
611 
612         Token = PrGetNextToken (NULL, PR_MACRO_ARGUMENTS, Next);
613         if (!Token)
614         {
615             goto BadInvocation;
616         }
617 
618         TokenOffset = (MacroStart - TokenBuffer);
619         Length = Token - MacroStart + strlen (Token) + 1;
620 
621         PrReplaceData (
622             &Gbl_CurrentLineBuffer[TokenOffset], Length,
623             Gbl_MacroTokenBuffer, strlen (Gbl_MacroTokenBuffer));
624         return;
625     }
626 
627     while (Args->Name)
628     {
629         /* Get the next argument from macro invocation */
630 
631         Token = PrGetNextToken (NULL, PR_MACRO_SEPARATORS, Next);
632         if (!Token)
633         {
634             goto BadInvocation;
635         }
636 
637         /* Replace all instances of this argument */
638 
639         for (i = 0; i < Args->UseCount; i++)
640         {
641             /* Offset zero indicates "arg not used" */
642             /* TBD: Not really needed now, with UseCount available */
643 
644             if (Args->Offset[i] == 0)
645             {
646                 break;
647             }
648 
649             PrReplaceData (
650                 &Gbl_MacroTokenBuffer[Args->Offset[i]], strlen (Args->Name),
651                 Token, strlen (Token));
652 
653             DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
654                 "ExpandArg: %s \n",
655                 Gbl_CurrentLineNumber, Gbl_MacroTokenBuffer);
656         }
657 
658         Args++;
659     }
660 
661     /* TBD: need to make sure macro was not invoked with too many arguments */
662 
663     if (!Token)
664     {
665         return;
666     }
667 
668     /* Replace the entire macro invocation with the expanded macro */
669 
670     TokenOffset = (MacroStart - TokenBuffer);
671     Length = Token - MacroStart + strlen (Token) + 1;
672 
673     PrReplaceData (
674         &Gbl_CurrentLineBuffer[TokenOffset], Length,
675         Gbl_MacroTokenBuffer, strlen (Gbl_MacroTokenBuffer));
676 
677     return;
678 
679 
680 BadInvocation:
681     PrError (ASL_ERROR, ASL_MSG_INVALID_INVOCATION,
682         THIS_TOKEN_OFFSET (MacroStart));
683 
684     DbgPrint (ASL_DEBUG_OUTPUT, PR_PREFIX_ID
685         "Bad macro invocation: %s \n",
686         Gbl_CurrentLineNumber, Gbl_MacroTokenBuffer);
687     return;
688 }
689