1 /*****************************************************************************/
5 /* Macros for the ca65 macroassembler */
9 /* (C) 1998-2003 Ullrich von Bassewitz */
11 /* D-70794 Filderstadt */
12 /* EMail: uz@cc65.org */
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. */
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: */
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 */
32 /*****************************************************************************/
57 /*****************************************************************************/
59 /*****************************************************************************/
63 static unsigned HT_GenHash (const void* Key);
64 /* Generate the hash over a key. */
66 static const void* HT_GetKey (void* Entry);
67 /* Given a pointer to the user entry data, return a pointer to the key */
69 static HashNode* HT_GetHashNode (void* Entry);
70 /* Given a pointer to the user entry data, return a pointer to the hash node */
72 static int HT_Compare (const void* Key1, const void* Key2);
73 /* Compare two keys. The function must return a value less than zero if
74 * Key1 is smaller than Key2, zero if both are equal, and a value greater
75 * than zero if Key1 is greater then Key2.
80 /*****************************************************************************/
82 /*****************************************************************************/
86 /* Struct that describes an identifer (macro param, local list) */
87 typedef struct IdDesc IdDesc;
89 IdDesc* Next; /* Linked list */
90 char Id [1]; /* Identifier, dynamically allocated */
95 /* Struct that describes a macro definition */
96 typedef struct Macro Macro;
98 HashNode Node; /* Hash list node */
99 Macro* List; /* List of all macros */
100 unsigned LocalCount; /* Count of local symbols */
101 IdDesc* Locals; /* List of local symbols */
102 unsigned ParamCount; /* Parameter count of macro */
103 IdDesc* Params; /* Identifiers of macro parameters */
104 unsigned TokCount; /* Number of tokens for this macro */
105 TokNode* TokRoot; /* Root of token list */
106 TokNode* TokLast; /* Pointer to last token in list */
107 unsigned char Style; /* Macro style */
108 char Name [1]; /* Macro name, dynamically allocated */
111 /* Hash table functions */
112 static const HashFunctions HashFunc = {
119 /* Macro hash table */
120 static HashTable MacroTab = STATIC_HASHTABLE_INITIALIZER (117, &HashFunc);
122 /* Global macro data */
123 static Macro* MacroRoot = 0; /* List of all macros */
125 /* Structs that holds data for a macro expansion */
126 typedef struct MacExp MacExp;
128 MacExp* Next; /* Pointer to next expansion */
129 Macro* M; /* Which macro do we expand? */
130 unsigned IfSP; /* .IF stack pointer at start of expansion */
131 TokNode* Exp; /* Pointer to current token */
132 TokNode* Final; /* Pointer to final token */
133 unsigned LocalStart; /* Start of counter for local symbol names */
134 unsigned ParamCount; /* Number of actual parameters */
135 TokNode** Params; /* List of actual parameters */
136 TokNode* ParamExp; /* Node for expanding parameters */
139 /* Number of active macro expansions */
140 static unsigned MacExpansions = 0;
142 /* Flag if a macro expansion should get aborted */
143 static int DoMacAbort = 0;
145 /* Counter to create local names for symbols */
146 static unsigned LocalName = 0;
150 /*****************************************************************************/
151 /* Hash table functions */
152 /*****************************************************************************/
156 static unsigned HT_GenHash (const void* Key)
157 /* Generate the hash over a key. */
159 return HashStr (Key);
164 static const void* HT_GetKey (void* Entry)
165 /* Given a pointer to the user entry data, return a pointer to the index */
167 return ((Macro*) Entry)->Name;
172 static HashNode* HT_GetHashNode (void* Entry)
173 /* Given a pointer to the user entry data, return a pointer to the hash node */
175 return &((Macro*) Entry)->Node;
180 static int HT_Compare (const void* Key1, const void* Key2)
181 /* Compare two keys. The function must return a value less than zero if
182 * Key1 is smaller than Key2, zero if both are equal, and a value greater
183 * than zero if Key1 is greater then Key2.
186 return strcmp (Key1, Key2);
191 /*****************************************************************************/
193 /*****************************************************************************/
197 static IdDesc* NewIdDesc (const char* Id)
198 /* Create a new IdDesc, initialize and return it */
200 /* Allocate memory */
201 unsigned Len = strlen (Id);
202 IdDesc* I = xmalloc (sizeof (IdDesc) + Len);
204 /* Initialize the struct */
206 memcpy (I->Id, Id, Len);
209 /* Return the new struct */
215 static Macro* NewMacro (const char* Name, unsigned char Style)
216 /* Generate a new macro entry, initialize and return it */
218 /* Allocate memory */
219 unsigned Len = strlen (Name);
220 Macro* M = xmalloc (sizeof (Macro) + Len);
222 /* Initialize the macro struct */
223 InitHashNode (&M->Node, M);
232 memcpy (M->Name, Name, Len+1);
234 /* Insert the macro into the global macro list */
238 /* Insert the macro into the hash table */
239 HT_Insert (&MacroTab, &M->Node);
241 /* Return the new macro struct */
247 static MacExp* NewMacExp (Macro* M)
248 /* Create a new expansion structure for the given macro */
252 /* Allocate memory */
253 MacExp* E = xmalloc (sizeof (MacExp));
255 /* Initialize the data */
257 E->IfSP = GetIfStack ();
260 E->LocalStart = LocalName;
261 LocalName += M->LocalCount;
263 E->Params = xmalloc (M->ParamCount * sizeof (TokNode*));
265 for (I = 0; I < M->ParamCount; ++I) {
269 /* One macro expansion more */
272 /* Return the new macro expansion */
278 static void FreeMacExp (MacExp* E)
279 /* Remove and free the current macro expansion */
283 /* One macro expansion less */
286 /* Free the parameter list */
287 for (I = 0; I < E->ParamCount; ++I) {
288 xfree (E->Params [I]);
292 /* Free the final token if we have one */
294 FreeTokNode (E->Final);
297 /* Free the structure itself */
303 static void MacSkipDef (unsigned Style)
304 /* Skip a macro definition */
306 if (Style == MAC_STYLE_CLASSIC) {
307 /* Skip tokens until we reach the final .endmacro */
308 while (Tok != TOK_ENDMACRO && Tok != TOK_EOF) {
311 if (Tok != TOK_EOF) {
314 Error ("`.ENDMACRO' expected");
317 /* Skip until end of line */
324 void MacDef (unsigned Style)
325 /* Parse a macro definition */
331 /* We expect a macro name here */
332 if (Tok != TOK_IDENT) {
333 Error ("Identifier expected");
338 /* Did we already define that macro? */
339 if (HT_Find (&MacroTab, SVal) != 0) {
340 /* Macro is already defined */
341 Error ("A macro named `%s' is already defined", SVal);
342 /* Skip tokens until we reach the final .endmacro */
347 /* Define the macro */
348 M = NewMacro (SVal, Style);
350 /* Switch to raw token mode and skip the macro name */
351 EnterRawTokenMode ();
354 /* If we have a DEFINE style macro, we may have parameters in braces,
355 * otherwise we may have parameters without braces.
357 if (Style == MAC_STYLE_CLASSIC) {
360 if (Tok == TOK_LPAREN) {
368 /* Parse the parameter list */
371 while (Tok == TOK_IDENT) {
373 /* Create a struct holding the identifier */
374 IdDesc* I = NewIdDesc (SVal);
376 /* Insert the struct into the list, checking for duplicate idents */
377 if (M->ParamCount == 0) {
380 IdDesc* List = M->Params;
382 if (strcmp (List->Id, SVal) == 0) {
383 Error ("Duplicate symbol `%s'", SVal);
385 if (List->Next == 0) {
398 /* Maybe there are more params... */
399 if (Tok == TOK_COMMA) {
407 /* For class macros, we expect a separator token, for define style macros,
408 * we expect the closing paren.
410 if (Style == MAC_STYLE_CLASSIC) {
412 } else if (HaveParams) {
416 /* Preparse the macro body. We will read the tokens until we reach end of
417 * file, or a .endmacro (or end of line for DEFINE style macros) and store
418 * them into an token list internal to the macro. For classic macros, there
419 * the .LOCAL command is detected and removed at this time.
423 /* Check for end of macro */
424 if (Style == MAC_STYLE_CLASSIC) {
425 /* In classic macros, only .endmacro is allowed */
426 if (Tok == TOK_ENDMACRO) {
430 /* May not have end of file in a macro definition */
431 if (Tok == TOK_EOF) {
432 Error ("`.ENDMACRO' expected");
436 /* Accept a newline or end of file for new style macros */
437 if (TokIsSep (Tok)) {
442 /* Check for a .LOCAL declaration */
443 if (Tok == TOK_LOCAL && Style == MAC_STYLE_CLASSIC) {
449 /* Skip .local or comma */
452 /* Need an identifer */
453 if (Tok != TOK_IDENT) {
454 Error ("Identifier expected");
459 /* Put the identifier into the locals list and skip it */
460 I = NewIdDesc (SVal);
466 /* Check for end of list */
467 if (Tok != TOK_COMMA) {
473 /* We need end of line after the locals */
478 /* Create a token node for the current token */
481 /* If the token is an ident, check if it is a local parameter */
482 if (Tok == TOK_IDENT) {
484 IdDesc* I = M->Params;
486 if (strcmp (I->Id, SVal) == 0) {
487 /* Local param name, replace it */
488 T->Tok = TOK_MACPARAM;
497 /* Insert the new token in the list */
498 if (M->TokCount == 0) {
500 M->TokRoot = M->TokLast = T;
502 /* We have already tokens */
503 M->TokLast->Next = T;
508 /* Read the next token */
512 /* Skip the .endmacro for a classic macro */
513 if (Style == MAC_STYLE_CLASSIC) {
518 /* Switch out of raw token mode */
519 LeaveRawTokenMode ();
524 static int MacExpand (void* Data)
525 /* If we're currently expanding a macro, set the the scanner token and
526 * attribute to the next value and return true. If we are not expanding
527 * a macro, return false.
530 /* Cast the Data pointer to the actual data structure */
531 MacExp* Mac = (MacExp*) Data;
533 /* Check if we should abort this macro */
539 /* Abort any open .IF statements in this macro expansion */
540 CleanupIfStack (Mac->IfSP);
542 /* Terminate macro expansion */
546 /* We're expanding a macro. Check if we are expanding one of the
551 /* Ok, use token from parameter list */
552 TokSet (Mac->ParamExp);
554 /* Set pointer to next token */
555 Mac->ParamExp = Mac->ParamExp->Next;
562 /* We're not expanding macro parameters. Check if we have tokens left from
567 /* Use next macro token */
570 /* Set pointer to next token */
571 Mac->Exp = Mac->Exp->Next;
573 /* Is it a request for actual parameter count? */
574 if (Tok == TOK_PARAMCOUNT) {
576 IVal = Mac->ParamCount;
580 /* Is it the name of a macro parameter? */
581 if (Tok == TOK_MACPARAM) {
583 /* Start to expand the parameter token list */
584 Mac->ParamExp = Mac->Params [IVal];
586 /* Recursive call to expand the parameter */
587 return MacExpand (Mac);
590 /* If it's an identifier, it may in fact be a local symbol */
591 if (Tok == TOK_IDENT && Mac->M->LocalCount) {
592 /* Search for the local symbol in the list */
594 IdDesc* I = Mac->M->Locals;
596 if (strcmp (SVal, I->Id) == 0) {
597 /* This is in fact a local symbol, change the name. Be sure
598 * to generate a local label name if the original name was
599 * a local label, and also generate a name that cannot be
600 * generated by a user.
602 unsigned PrefixLen = (I->Id[0] == LocalStart);
603 sprintf (SVal, "%.*sLOCAL-MACRO-SYMBOL-%04X", PrefixLen,
604 I->Id, Mac->LocalStart + Index);
616 /* The token was successfully set */
621 /* No more macro tokens. Do we have a final token? */
624 /* Set the final token and remove it */
626 FreeTokNode (Mac->Final);
629 /* The token was successfully set */
635 /* End of macro expansion */
638 /* Pop the input function */
641 /* No token available */
647 static void StartExpClassic (Macro* M)
648 /* Start expanding the classic macro M */
652 /* Skip the macro name */
655 /* Create a structure holding expansion data */
658 /* Read the actual parameters */
659 while (!TokIsSep (Tok)) {
663 /* Check for maximum parameter count */
664 if (E->ParamCount >= M->ParamCount) {
665 Error ("Too many macro parameters");
670 /* Read tokens for one parameter, accept empty params */
672 while (Tok != TOK_COMMA && Tok != TOK_SEP) {
676 /* Check for end of file */
677 if (Tok == TOK_EOF) {
678 Error ("Unexpected end of file");
682 /* Get the next token in a node */
685 /* Insert it into the list */
687 E->Params [E->ParamCount] = T;
697 /* One parameter more */
700 /* Check for a comma */
701 if (Tok == TOK_COMMA) {
708 /* Insert a new token input function */
709 PushInput (MacExpand, E, ".MACRO");
714 static void StartExpDefine (Macro* M)
715 /* Start expanding a DEFINE style macro */
717 /* Create a structure holding expansion data */
718 MacExp* E = NewMacExp (M);
720 /* A define style macro must be called with as many actual parameters
721 * as there are formal ones. Get the parameter count.
723 unsigned Count = M->ParamCount;
725 /* Skip the current token */
728 /* Read the actual parameters */
733 /* Check if there is really a parameter */
734 if (TokIsSep (Tok) || Tok == TOK_COMMA) {
735 Error ("Macro parameter expected");
740 /* Read tokens for one parameter */
746 /* Get the next token in a node */
749 /* Insert it into the list */
751 E->Params [E->ParamCount] = T;
760 } while (Tok != TOK_COMMA && !TokIsSep (Tok));
762 /* One parameter more */
765 /* Check for a comma */
767 if (Tok == TOK_COMMA) {
770 Error ("`,' expected");
775 /* Macro expansion will overwrite the current token. This is a problem
776 * for define style macros since these are called from the scanner level.
777 * To avoid it, remember the current token and re-insert it if macro
780 E->Final = NewTokNode ();
782 /* Insert a new token input function */
783 PushInput (MacExpand, E, ".DEFINE");
788 void MacExpandStart (void)
789 /* Start expanding the macro in SVal */
791 /* Search for the macro */
792 Macro* M = HT_FindEntry (&MacroTab, SVal);
795 /* Call the apropriate subroutine */
797 case MAC_STYLE_CLASSIC: StartExpClassic (M); break;
798 case MAC_STYLE_DEFINE: StartExpDefine (M); break;
799 default: Internal ("Invalid macro style: %d", M->Style);
806 /* Abort the current macro expansion */
808 /* Must have an expansion */
809 CHECK (MacExpansions > 0);
811 /* Set a flag so macro expansion will terminate on the next call */
817 int IsMacro (const char* Name)
818 /* Return true if the given name is the name of a macro */
820 return (HT_Find (&MacroTab, Name) != 0);
825 int IsDefine (const char* Name)
826 /* Return true if the given name is the name of a define style macro */
828 Macro* M = HT_FindEntry (&MacroTab, Name);
829 return (M != 0 && M->Style == MAC_STYLE_DEFINE);
834 int InMacExpansion (void)
835 /* Return true if we're currently expanding a macro */
837 return (MacExpansions > 0);