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