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