]> git.sur5r.net Git - cc65/blob - src/ca65/macro.c
Don't allow too many nested macro expansions. Until now, it was possible to
[cc65] / src / ca65 / macro.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                  macro.c                                  */
4 /*                                                                           */
5 /*                    Macros for the ca65 macroassembler                     */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 1998-2011, Ullrich von Bassewitz                                      */
10 /*                Roemerstrasse 52                                           */
11 /*                D-70794 Filderstadt                                        */
12 /* EMail:         uz@cc65.org                                                */
13 /*                                                                           */
14 /*                                                                           */
15 /* This software is provided 'as-is', without any expressed or implied       */
16 /* warranty.  In no event will the authors be held liable for any damages    */
17 /* arising from the use of this software.                                    */
18 /*                                                                           */
19 /* Permission is granted to anyone to use this software for any purpose,     */
20 /* including commercial applications, and to alter it and redistribute it    */
21 /* freely, subject to the following restrictions:                            */
22 /*                                                                           */
23 /* 1. The origin of this software must not be misrepresented; you must not   */
24 /*    claim that you wrote the original software. If you use this software   */
25 /*    in a product, an acknowledgment in the product documentation would be  */
26 /*    appreciated but is not required.                                       */
27 /* 2. Altered source versions must be plainly marked as such, and must not   */
28 /*    be misrepresented as being the original software.                      */
29 /* 3. This notice may not be removed or altered from any source              */
30 /*    distribution.                                                          */
31 /*                                                                           */
32 /*****************************************************************************/
33
34
35
36 #include <stdio.h>
37 #include <string.h>
38
39 /* common */
40 #include "check.h"
41 #include "hashstr.h"
42 #include "hashtab.h"
43 #include "xmalloc.h"
44
45 /* ca65 */
46 #include "condasm.h"
47 #include "error.h"
48 #include "global.h"
49 #include "instr.h"
50 #include "istack.h"
51 #include "lineinfo.h"
52 #include "nexttok.h"
53 #include "pseudo.h"
54 #include "toklist.h"
55 #include "macro.h"
56
57
58
59 /*****************************************************************************/
60 /*                                 Forwards                                  */
61 /*****************************************************************************/
62
63
64
65 static unsigned HT_GenHash (const void* Key);
66 /* Generate the hash over a key. */
67
68 static const void* HT_GetKey (void* Entry);
69 /* Given a pointer to the user entry data, return a pointer to the key */
70
71 static HashNode* HT_GetHashNode (void* Entry);
72 /* Given a pointer to the user entry data, return a pointer to the hash node */
73
74 static int HT_Compare (const void* Key1, const void* Key2);
75 /* Compare two keys. The function must return a value less than zero if
76  * Key1 is smaller than Key2, zero if both are equal, and a value greater
77  * than zero if Key1 is greater then Key2.
78  */
79
80
81
82 /*****************************************************************************/
83 /*                                   Data                                    */
84 /*****************************************************************************/
85
86
87
88 /* Struct that describes an identifer (macro param, local list) */
89 typedef struct IdDesc IdDesc;
90 struct IdDesc {
91     IdDesc*         Next;       /* Linked list */
92     StrBuf          Id;         /* Identifier, dynamically allocated */
93 };
94
95
96
97 /* Struct that describes a macro definition */
98 typedef struct Macro Macro;
99 struct Macro {
100     HashNode        Node;       /* Hash list node */
101     Macro*          List;       /* List of all macros */
102     unsigned        LocalCount; /* Count of local symbols */
103     IdDesc*         Locals;     /* List of local symbols */
104     unsigned        ParamCount; /* Parameter count of macro */
105     IdDesc*         Params;     /* Identifiers of macro parameters */
106     unsigned        TokCount;   /* Number of tokens for this macro */
107     TokNode*        TokRoot;    /* Root of token list */
108     TokNode*        TokLast;    /* Pointer to last token in list */
109     unsigned char   Style;      /* Macro style */
110     unsigned char   Incomplete; /* Macro is currently built */
111     StrBuf          Name;       /* Macro name, dynamically allocated */
112 };
113
114 /* Hash table functions */
115 static const HashFunctions HashFunc = {
116     HT_GenHash,
117     HT_GetKey,
118     HT_GetHashNode,
119     HT_Compare
120 };
121
122 /* Macro hash table */
123 static HashTable MacroTab = STATIC_HASHTABLE_INITIALIZER (117, &HashFunc);
124
125 /* Global macro data */
126 static Macro*   MacroRoot = 0;  /* List of all macros */
127
128 /* Structs that holds data for a macro expansion */
129 typedef struct MacExp MacExp;
130 struct MacExp {
131     MacExp*     Next;           /* Pointer to next expansion */
132     Macro*      M;              /* Which macro do we expand? */
133     unsigned    IfSP;           /* .IF stack pointer at start of expansion */
134     TokNode*    Exp;            /* Pointer to current token */
135     TokNode*    Final;          /* Pointer to final token */
136     unsigned    LocalStart;     /* Start of counter for local symbol names */
137     unsigned    ParamCount;     /* Number of actual parameters */
138     TokNode**   Params;         /* List of actual parameters */
139     TokNode*    ParamExp;       /* Node for expanding parameters */
140     unsigned    LISlot;         /* Slot for additional line infos */
141 };
142
143 /* Maximum number of nested macro expansions */
144 #define MAX_MACEXPANSIONS       256U
145
146 /* Number of active macro expansions */
147 static unsigned MacExpansions = 0;
148
149 /* Flag if a macro expansion should get aborted */
150 static int DoMacAbort = 0;
151
152 /* Counter to create local names for symbols */
153 static unsigned LocalName = 0;
154
155
156
157 /*****************************************************************************/
158 /*                           Hash table functions                            */
159 /*****************************************************************************/
160
161
162
163 static unsigned HT_GenHash (const void* Key)
164 /* Generate the hash over a key. */
165 {
166     return HashBuf (Key);
167 }
168
169
170
171 static const void* HT_GetKey (void* Entry)
172 /* Given a pointer to the user entry data, return a pointer to the index */
173 {
174     return &((Macro*) Entry)->Name;
175 }
176
177
178
179 static HashNode* HT_GetHashNode (void* Entry)
180 /* Given a pointer to the user entry data, return a pointer to the hash node */
181 {
182     return &((Macro*) Entry)->Node;
183 }
184
185
186
187 static int HT_Compare (const void* Key1, const void* Key2)
188 /* Compare two keys. The function must return a value less than zero if
189  * Key1 is smaller than Key2, zero if both are equal, and a value greater
190  * than zero if Key1 is greater then Key2.
191  */
192 {
193     return SB_Compare (Key1, Key2);
194 }
195
196
197
198 /*****************************************************************************/
199 /*                                   Code                                    */
200 /*****************************************************************************/
201
202
203
204 static IdDesc* NewIdDesc (const StrBuf* Id)
205 /* Create a new IdDesc, initialize and return it */
206 {
207     /* Allocate memory */
208     IdDesc* I = xmalloc (sizeof (IdDesc));
209
210     /* Initialize the struct */
211     I->Next = 0;
212     SB_Init (&I->Id);
213     SB_Copy (&I->Id, Id);
214
215     /* Return the new struct */
216     return I;
217 }
218
219
220
221 static Macro* NewMacro (const StrBuf* Name, unsigned char Style)
222 /* Generate a new macro entry, initialize and return it */
223 {
224     /* Allocate memory */
225     Macro* M = xmalloc (sizeof (Macro));
226
227     /* Initialize the macro struct */
228     InitHashNode (&M->Node, M);
229     M->LocalCount = 0;
230     M->Locals     = 0;
231     M->ParamCount = 0;
232     M->Params     = 0;
233     M->TokCount   = 0;
234     M->TokRoot    = 0;
235     M->TokLast    = 0;
236     M->Style      = Style;
237     M->Incomplete = 1;
238     SB_Init (&M->Name);
239     SB_Copy (&M->Name, Name);
240
241     /* Insert the macro into the global macro list */
242     M->List = MacroRoot;
243     MacroRoot = M;
244
245     /* Insert the macro into the hash table */
246     HT_Insert (&MacroTab, &M->Node);
247
248     /* Return the new macro struct */
249     return M;
250 }
251
252
253
254 static MacExp* NewMacExp (Macro* M)
255 /* Create a new expansion structure for the given macro */
256 {
257     unsigned I;
258
259     /* Allocate memory */
260     MacExp* E = xmalloc (sizeof (MacExp));
261
262     /* Initialize the data */
263     E->M          = M;
264     E->IfSP       = GetIfStack ();
265     E->Exp        = M->TokRoot;
266     E->Final      = 0;
267     E->LocalStart = LocalName;
268     LocalName    += M->LocalCount;
269     E->ParamCount = 0;
270     E->Params     = xmalloc (M->ParamCount * sizeof (TokNode*));
271     E->ParamExp   = 0;
272     for (I = 0; I < M->ParamCount; ++I) {
273         E->Params[I] = 0;
274     }
275     E->LISlot     = AllocLineInfoSlot (LI_TYPE_MACRO, MacExpansions);
276
277     /* One macro expansion more */
278     ++MacExpansions;
279
280     /* Return the new macro expansion */
281     return E;
282 }
283
284
285
286 static void FreeMacExp (MacExp* E)
287 /* Remove and free the current macro expansion */
288 {
289     unsigned I;
290
291     /* One macro expansion less */
292     --MacExpansions;
293
294     /* Free the parameter lists */
295     for (I = 0; I < E->ParamCount; ++I) {
296         /* Free one parameter list */
297         TokNode* N = E->Params[I];
298         while (N) {
299             TokNode* P = N->Next;
300             FreeTokNode (N);
301             N = P;
302         }
303     }
304     xfree (E->Params);
305
306     /* Free the additional line info slot */
307     FreeLineInfoSlot (E->LISlot);
308
309     /* Free the final token if we have one */
310     if (E->Final) {
311         FreeTokNode (E->Final);
312     }
313
314     /* Free the structure itself */
315     xfree (E);
316 }
317
318
319
320 static void MacSkipDef (unsigned Style)
321 /* Skip a macro definition */
322 {
323     if (Style == MAC_STYLE_CLASSIC) {
324         /* Skip tokens until we reach the final .endmacro */
325         while (CurTok.Tok != TOK_ENDMACRO && CurTok.Tok != TOK_EOF) {
326             NextTok ();
327         }
328         if (CurTok.Tok != TOK_EOF) {
329             SkipUntilSep ();
330         } else {
331             Error ("`.ENDMACRO' expected");
332         }
333     } else {
334         /* Skip until end of line */
335         SkipUntilSep ();
336     }
337 }
338
339
340
341 void MacDef (unsigned Style)
342 /* Parse a macro definition */
343 {
344     Macro* M;
345     TokNode* N;
346     int HaveParams;
347
348     /* We expect a macro name here */
349     if (CurTok.Tok != TOK_IDENT) {
350         Error ("Identifier expected");
351         MacSkipDef (Style);
352         return;
353     } else if (!UbiquitousIdents && FindInstruction (&CurTok.SVal) >= 0) {
354         /* The identifier is a name of a 6502 instruction, which is not
355          * allowed if not explicitly enabled.
356          */
357         Error ("Cannot use an instruction as macro name");
358         MacSkipDef (Style);
359         return;
360     }
361
362     /* Did we already define that macro? */
363     if (HT_Find (&MacroTab, &CurTok.SVal) != 0) {
364         /* Macro is already defined */
365         Error ("A macro named `%m%p' is already defined", &CurTok.SVal);
366         /* Skip tokens until we reach the final .endmacro */
367         MacSkipDef (Style);
368         return;
369     }
370
371     /* Define the macro */
372     M = NewMacro (&CurTok.SVal, Style);
373
374     /* Switch to raw token mode and skip the macro name */
375     EnterRawTokenMode ();
376     NextTok ();
377
378     /* If we have a DEFINE style macro, we may have parameters in braces,
379      * otherwise we may have parameters without braces.
380      */
381     if (Style == MAC_STYLE_CLASSIC) {
382         HaveParams = 1;
383     } else {
384         if (CurTok.Tok == TOK_LPAREN) {
385             HaveParams = 1;
386             NextTok ();
387         } else {
388             HaveParams = 0;
389         }
390     }
391
392     /* Parse the parameter list */
393     if (HaveParams) {
394
395         while (CurTok.Tok == TOK_IDENT) {
396
397             /* Create a struct holding the identifier */
398             IdDesc* I = NewIdDesc (&CurTok.SVal);
399
400             /* Insert the struct into the list, checking for duplicate idents */
401             if (M->ParamCount == 0) {
402                 M->Params = I;
403             } else {
404                 IdDesc* List = M->Params;
405                 while (1) {
406                     if (SB_Compare (&List->Id, &CurTok.SVal) == 0) {
407                         Error ("Duplicate symbol `%m%p'", &CurTok.SVal);
408                     }
409                     if (List->Next == 0) {
410                         break;
411                     } else {
412                         List = List->Next;
413                     }
414                 }
415                 List->Next = I;
416             }
417             ++M->ParamCount;
418
419             /* Skip the name */
420             NextTok ();
421
422             /* Maybe there are more params... */
423             if (CurTok.Tok == TOK_COMMA) {
424                 NextTok ();
425             } else {
426                 break;
427             }
428         }
429     }
430
431     /* For class macros, we expect a separator token, for define style macros,
432      * we expect the closing paren.
433      */
434     if (Style == MAC_STYLE_CLASSIC) {
435         ConsumeSep ();
436     } else if (HaveParams) {
437         ConsumeRParen ();
438     }
439
440     /* Preparse the macro body. We will read the tokens until we reach end of
441      * file, or a .endmacro (or end of line for DEFINE style macros) and store
442      * them into an token list internal to the macro. For classic macros, there
443      * the .LOCAL command is detected and removed at this time.
444      */
445     while (1) {
446
447         /* Check for end of macro */
448         if (Style == MAC_STYLE_CLASSIC) {
449             /* In classic macros, only .endmacro is allowed */
450             if (CurTok.Tok == TOK_ENDMACRO) {
451                 /* Done */
452                 break;
453             }
454             /* May not have end of file in a macro definition */
455             if (CurTok.Tok == TOK_EOF) {
456                 Error ("`.ENDMACRO' expected");
457                 goto Done;
458             }
459         } else {
460             /* Accept a newline or end of file for new style macros */
461             if (TokIsSep (CurTok.Tok)) {
462                 break;
463             }
464         }
465
466         /* Check for a .LOCAL declaration */
467         if (CurTok.Tok == TOK_LOCAL && Style == MAC_STYLE_CLASSIC) {
468
469             while (1) {
470
471                 IdDesc* I;
472
473                 /* Skip .local or comma */
474                 NextTok ();
475
476                 /* Need an identifer */
477                 if (CurTok.Tok != TOK_IDENT && CurTok.Tok != TOK_LOCAL_IDENT) {
478                     Error ("Identifier expected");
479                     SkipUntilSep ();
480                     break;
481                 }
482
483                 /* Put the identifier into the locals list and skip it */
484                 I = NewIdDesc (&CurTok.SVal);
485                 I->Next = M->Locals;
486                 M->Locals = I;
487                 ++M->LocalCount;
488                 NextTok ();
489
490                 /* Check for end of list */
491                 if (CurTok.Tok != TOK_COMMA) {
492                     break;
493                 }
494
495             }
496
497             /* We need end of line after the locals */
498             ConsumeSep ();
499             continue;
500         }
501
502         /* Create a token node for the current token */
503         N = NewTokNode ();
504
505         /* If the token is an ident, check if it is a local parameter */
506         if (CurTok.Tok == TOK_IDENT) {
507             unsigned Count = 0;
508             IdDesc* I = M->Params;
509             while (I) {
510                 if (SB_Compare (&I->Id, &CurTok.SVal) == 0) {
511                     /* Local param name, replace it */
512                     N->T.Tok  = TOK_MACPARAM;
513                     N->T.IVal = Count;
514                     break;
515                 }
516                 ++Count;
517                 I = I->Next;
518             }
519         }
520
521         /* Insert the new token in the list */
522         if (M->TokCount == 0) {
523             /* First token */
524             M->TokRoot = M->TokLast = N;
525         } else {
526             /* We have already tokens */
527             M->TokLast->Next = N;
528             M->TokLast = N;
529         }
530         ++M->TokCount;
531
532         /* Read the next token */
533         NextTok ();
534     }
535
536     /* Skip the .endmacro for a classic macro */
537     if (Style == MAC_STYLE_CLASSIC) {
538         NextTok ();
539     }
540
541     /* Reset the Incomplete flag now that parsing is done */
542     M->Incomplete = 0;
543
544 Done:
545     /* Switch out of raw token mode */
546     LeaveRawTokenMode ();
547 }
548
549
550
551 static int MacExpand (void* Data)
552 /* If we're currently expanding a macro, set the the scanner token and
553  * attribute to the next value and return true. If we are not expanding
554  * a macro, return false.
555  */
556 {
557     /* Cast the Data pointer to the actual data structure */
558     MacExp* Mac = (MacExp*) Data;
559
560     /* Check if we should abort this macro */
561     if (DoMacAbort) {
562
563         /* Reset the flag */
564         DoMacAbort = 0;
565
566         /* Abort any open .IF statements in this macro expansion */
567         CleanupIfStack (Mac->IfSP);
568
569         /* Terminate macro expansion */
570         goto MacEnd;
571     }
572
573     /* We're expanding a macro. Check if we are expanding one of the
574      * macro parameters.
575      */
576     if (Mac->ParamExp) {
577
578         /* Ok, use token from parameter list */
579         TokSet (Mac->ParamExp, Mac->LISlot);
580
581         /* Set pointer to next token */
582         Mac->ParamExp = Mac->ParamExp->Next;
583
584         /* Done */
585         return 1;
586
587     }
588
589     /* We're not expanding macro parameters. Check if we have tokens left from
590      * the macro itself.
591      */
592     if (Mac->Exp) {
593
594         /* Use next macro token */
595         TokSet (Mac->Exp, Mac->LISlot);
596
597         /* Set pointer to next token */
598         Mac->Exp = Mac->Exp->Next;
599
600         /* Is it a request for actual parameter count? */
601         if (CurTok.Tok == TOK_PARAMCOUNT) {
602             CurTok.Tok  = TOK_INTCON;
603             CurTok.IVal = Mac->ParamCount;
604             return 1;
605         }
606
607         /* Is it the name of a macro parameter? */
608         if (CurTok.Tok == TOK_MACPARAM) {
609
610             /* Start to expand the parameter token list */
611             Mac->ParamExp = Mac->Params [CurTok.IVal];
612
613             /* Recursive call to expand the parameter */
614             return MacExpand (Mac);
615         }
616
617         /* If it's an identifier, it may in fact be a local symbol */
618         if ((CurTok.Tok == TOK_IDENT || CurTok.Tok == TOK_LOCAL_IDENT) &&
619             Mac->M->LocalCount) {
620             /* Search for the local symbol in the list */
621             unsigned Index = 0;
622             IdDesc* I = Mac->M->Locals;
623             while (I) {
624                 if (SB_Compare (&CurTok.SVal, &I->Id) == 0) {
625                     /* This is in fact a local symbol, change the name. Be sure
626                      * to generate a local label name if the original name was
627                      * a local label, and also generate a name that cannot be
628                      * generated by a user.
629                      */
630                     if (SB_At (&I->Id, 0) == LocalStart) {
631                         /* Must generate a local symbol */
632                         SB_Printf (&CurTok.SVal, "%cLOCAL-MACRO_SYMBOL-%04X",
633                                    LocalStart, Mac->LocalStart + Index);
634                     } else {
635                         /* Global symbol */
636                         SB_Printf (&CurTok.SVal, "LOCAL-MACRO_SYMBOL-%04X",
637                                    Mac->LocalStart + Index);
638                     }
639                     break;
640                 }
641                 /* Next symbol */
642                 ++Index;
643                 I = I->Next;
644             }
645
646             /* Done */
647             return 1;
648         }
649
650         /* The token was successfully set */
651         return 1;
652
653     }
654
655     /* No more macro tokens. Do we have a final token? */
656     if (Mac->Final) {
657
658         /* Set the final token and remove it */
659         TokSet (Mac->Final, Mac->LISlot);
660         FreeTokNode (Mac->Final);
661         Mac->Final = 0;
662
663         /* The token was successfully set */
664         return 1;
665
666     }
667
668 MacEnd:
669     /* End of macro expansion */
670     FreeMacExp (Mac);
671
672     /* Pop the input function */
673     PopInput ();
674
675     /* No token available */
676     return 0;
677 }
678
679
680
681 static void StartExpClassic (Macro* M)
682 /* Start expanding the classic macro M */
683 {
684     MacExp*     E;
685     token_t     Term;
686
687
688     /* Create a structure holding expansion data. This must be done before
689      * skipping the macro name, because the call to NextTok may cause a new
690      * expansion if the next token is actually a .define style macro.
691      */
692     E = NewMacExp (M);
693
694     /* Skip the macro name */
695     NextTok ();
696
697     /* Read the actual parameters */
698     while (!TokIsSep (CurTok.Tok)) {
699
700         TokNode* Last;
701
702         /* Check for maximum parameter count */
703         if (E->ParamCount >= M->ParamCount) {
704             ErrorSkip ("Too many macro parameters");
705             break;
706         }
707
708         /* The macro may optionally be enclosed in curly braces */
709         Term = GetTokListTerm (TOK_COMMA);
710
711         /* Read tokens for one parameter, accept empty params */
712         Last = 0;
713         while (CurTok.Tok != Term && CurTok.Tok != TOK_SEP) {
714
715             TokNode* T;
716
717             /* Check for end of file */
718             if (CurTok.Tok == TOK_EOF) {
719                 Error ("Unexpected end of file");
720                 FreeMacExp (E);
721                 return;
722             }
723
724             /* Get the next token in a node */
725             T = NewTokNode ();
726
727             /* Insert it into the list */
728             if (Last == 0) {
729                 E->Params [E->ParamCount] = T;
730             } else {
731                 Last->Next = T;
732             }
733             Last = T;
734
735             /* And skip it... */
736             NextTok ();
737         }
738
739         /* One parameter more */
740         ++E->ParamCount;
741
742         /* If the macro argument was enclosed in curly braces, end-of-line
743          * is an error. Skip the closing curly brace.
744          */
745         if (Term == TOK_RCURLY) {
746             if (CurTok.Tok == TOK_SEP) {
747                 Error ("End of line encountered within macro argument");
748                 break;
749             }
750             NextTok ();
751         }
752
753         /* Check for a comma */
754         if (CurTok.Tok == TOK_COMMA) {
755             NextTok ();
756         } else {
757             break;
758         }
759     }
760
761     /* We must be at end of line now, otherwise something is wrong */
762     ExpectSep ();
763
764     /* Insert a new token input function */
765     PushInput (MacExpand, E, ".MACRO");
766 }
767
768
769
770 static void StartExpDefine (Macro* M)
771 /* Start expanding a DEFINE style macro */
772 {
773     /* Create a structure holding expansion data */
774     MacExp* E = NewMacExp (M);
775
776     /* A define style macro must be called with as many actual parameters
777      * as there are formal ones. Get the parameter count.
778      */
779     unsigned Count = M->ParamCount;
780
781     /* Skip the current token */
782     NextTok ();
783
784     /* Read the actual parameters */
785     while (Count--) {
786
787         TokNode*   Last;
788
789         /* The macro may optionally be enclosed in curly braces */
790         token_t Term = GetTokListTerm (TOK_COMMA);
791
792         /* Check if there is really a parameter */
793         if (TokIsSep (CurTok.Tok) || CurTok.Tok == Term) {
794             ErrorSkip ("Macro parameter #%u is empty", E->ParamCount+1);
795             FreeMacExp (E);
796             return;
797         }
798
799         /* Read tokens for one parameter */
800         Last = 0;
801         do {
802
803             TokNode* T;
804
805             /* Get the next token in a node */
806             T = NewTokNode ();
807
808             /* Insert it into the list */
809             if (Last == 0) {
810                 E->Params [E->ParamCount] = T;
811             } else {
812                 Last->Next = T;
813             }
814             Last = T;
815
816             /* And skip it... */
817             NextTok ();
818
819         } while (CurTok.Tok != Term && !TokIsSep (CurTok.Tok));
820
821         /* One parameter more */
822         ++E->ParamCount;
823
824         /* If the macro argument was enclosed in curly braces, end-of-line
825          * is an error. Skip the closing curly brace.
826          */
827         if (Term == TOK_RCURLY) {
828             if (TokIsSep (CurTok.Tok)) {
829                 Error ("End of line encountered within macro argument");
830                 break;
831             }
832             NextTok ();
833         }
834
835         /* Check for a comma */
836         if (Count > 0) {
837             if (CurTok.Tok == TOK_COMMA) {
838                 NextTok ();
839             } else {
840                 Error ("`,' expected");
841             }
842         }
843     }
844
845     /* Macro expansion will overwrite the current token. This is a problem
846      * for define style macros since these are called from the scanner level.
847      * To avoid it, remember the current token and re-insert it, once macro
848      * expansion is done.
849      */
850     E->Final = NewTokNode ();
851
852     /* Insert a new token input function */
853     PushInput (MacExpand, E, ".DEFINE");
854 }
855
856
857
858 void MacExpandStart (void)
859 /* Start expanding the macro in SVal */
860 {
861     /* Search for the macro */
862     Macro* M = HT_FindEntry (&MacroTab, &CurTok.SVal);
863     CHECK (M != 0);
864
865     /* We cannot expand an incomplete macro */
866     if (M->Incomplete) {
867         Error ("Cannot expand an incomplete macro");
868         return;
869     }
870
871     /* Don't allow too many nested macro expansions - otherwise it is possible
872      * to force an endless loop and assembler crash.
873      */
874     if (MacExpansions >= MAX_MACEXPANSIONS) {
875         Error ("Too many nested macro expansions");
876         return;
877     }
878
879     /* Call the apropriate subroutine */
880     switch (M->Style) {
881         case MAC_STYLE_CLASSIC: StartExpClassic (M);    break;
882         case MAC_STYLE_DEFINE:  StartExpDefine (M);     break;
883         default:                Internal ("Invalid macro style: %d", M->Style);
884     }
885 }
886
887
888
889 void MacAbort (void)
890 /* Abort the current macro expansion */
891 {
892     /* Must have an expansion */
893     CHECK (MacExpansions > 0);
894
895     /* Set a flag so macro expansion will terminate on the next call */
896     DoMacAbort = 1;
897 }
898
899
900
901 int IsMacro (const StrBuf* Name)
902 /* Return true if the given name is the name of a macro */
903 {
904     return (HT_Find (&MacroTab, Name) != 0);
905 }
906
907
908
909 int IsDefine (const StrBuf* Name)
910 /* Return true if the given name is the name of a define style macro */
911 {
912     Macro* M = HT_FindEntry (&MacroTab, Name);
913     return (M != 0 && M->Style == MAC_STYLE_DEFINE);
914 }
915
916
917
918 int InMacExpansion (void)
919 /* Return true if we're currently expanding a macro */
920 {
921     return (MacExpansions > 0);
922 }
923
924
925
926