1 /*****************************************************************************/
5 /* Macros for the ca65 macroassembler */
9 /* (C) 1998-2003 Ullrich von Bassewitz */
10 /* Römerstrasse 52 */
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 for equality */
77 /*****************************************************************************/
79 /*****************************************************************************/
83 /* Struct that describes an identifer (macro param, local list) */
84 typedef struct IdDesc IdDesc;
86 IdDesc* Next; /* Linked list */
87 char Id [1]; /* Identifier, dynamically allocated */
92 /* Struct that describes a macro definition */
93 typedef struct Macro Macro;
95 HashNode Node; /* Hash list node */
96 Macro* List; /* List of all macros */
97 unsigned LocalCount; /* Count of local symbols */
98 IdDesc* Locals; /* List of local symbols */
99 unsigned ParamCount; /* Parameter count of macro */
100 IdDesc* Params; /* Identifiers of macro parameters */
101 unsigned TokCount; /* Number of tokens for this macro */
102 TokNode* TokRoot; /* Root of token list */
103 TokNode* TokLast; /* Pointer to last token in list */
104 unsigned char Style; /* Macro style */
105 char Name [1]; /* Macro name, dynamically allocated */
108 /* Hash table functions */
109 static const HashFunctions HashFunc = {
116 /* Macro hash table */
117 static HashTable MacroTab = STATIC_HASHTABLE_INITIALIZER (117, &HashFunc);
119 /* Global macro data */
120 static Macro* MacroRoot = 0; /* List of all macros */
122 /* Structs that holds data for a macro expansion */
123 typedef struct MacExp MacExp;
125 MacExp* Next; /* Pointer to next expansion */
126 Macro* M; /* Which macro do we expand? */
127 unsigned IfSP; /* .IF stack pointer at start of expansion */
128 TokNode* Exp; /* Pointer to current token */
129 TokNode* Final; /* Pointer to final token */
130 unsigned LocalStart; /* Start of counter for local symbol names */
131 unsigned ParamCount; /* Number of actual parameters */
132 TokNode** Params; /* List of actual parameters */
133 TokNode* ParamExp; /* Node for expanding parameters */
136 /* Number of active macro expansions */
137 static unsigned MacExpansions = 0;
139 /* Flag if a macro expansion should get aborted */
140 static int DoMacAbort = 0;
142 /* Counter to create local names for symbols */
143 static unsigned LocalName = 0;
147 /*****************************************************************************/
148 /* Hash table functions */
149 /*****************************************************************************/
153 static unsigned HT_GenHash (const void* Key)
154 /* Generate the hash over a key. */
156 return HashStr (Key);
161 static const void* HT_GetKey (void* Entry)
162 /* Given a pointer to the user entry data, return a pointer to the index */
164 return ((Macro*) Entry)->Name;
169 static HashNode* HT_GetHashNode (void* Entry)
170 /* Given a pointer to the user entry data, return a pointer to the hash node */
172 return &((Macro*) Entry)->Node;
177 static int HT_Compare (const void* Key1, const void* Key2)
178 /* Compare two keys for equality */
180 return (strcmp (Key1, Key2) == 0);
185 /*****************************************************************************/
187 /*****************************************************************************/
191 static IdDesc* NewIdDesc (const char* Id)
192 /* Create a new IdDesc, initialize and return it */
194 /* Allocate memory */
195 unsigned Len = strlen (Id);
196 IdDesc* I = xmalloc (sizeof (IdDesc) + Len);
198 /* Initialize the struct */
200 memcpy (I->Id, Id, Len);
203 /* Return the new struct */
209 static Macro* NewMacro (const char* Name, unsigned char Style)
210 /* Generate a new macro entry, initialize and return it */
212 /* Allocate memory */
213 unsigned Len = strlen (Name);
214 Macro* M = xmalloc (sizeof (Macro) + Len);
216 /* Initialize the macro struct */
217 InitHashNode (&M->Node, M);
226 memcpy (M->Name, Name, Len+1);
228 /* Insert the macro into the global macro list */
232 /* Insert the macro into the hash table */
233 HT_Insert (&MacroTab, &M->Node);
235 /* Return the new macro struct */
241 static MacExp* NewMacExp (Macro* M)
242 /* Create a new expansion structure for the given macro */
246 /* Allocate memory */
247 MacExp* E = xmalloc (sizeof (MacExp));
249 /* Initialize the data */
251 E->IfSP = GetIfStack ();
254 E->LocalStart = LocalName;
255 LocalName += M->LocalCount;
257 E->Params = xmalloc (M->ParamCount * sizeof (TokNode*));
259 for (I = 0; I < M->ParamCount; ++I) {
263 /* One macro expansion more */
266 /* Return the new macro expansion */
272 static void FreeMacExp (MacExp* E)
273 /* Remove and free the current macro expansion */
277 /* One macro expansion less */
280 /* Free the parameter list */
281 for (I = 0; I < E->ParamCount; ++I) {
282 xfree (E->Params [I]);
286 /* Free the final token if we have one */
288 FreeTokNode (E->Final);
291 /* Free the structure itself */
297 static void MacSkipDef (unsigned Style)
298 /* Skip a macro definition */
300 if (Style == MAC_STYLE_CLASSIC) {
301 /* Skip tokens until we reach the final .endmacro */
302 while (Tok != TOK_ENDMACRO && Tok != TOK_EOF) {
305 if (Tok != TOK_EOF) {
308 Error (ERR_ENDMACRO_EXPECTED);
311 /* Skip until end of line */
318 void MacDef (unsigned Style)
319 /* Parse a macro definition */
325 /* We expect a macro name here */
326 if (Tok != TOK_IDENT) {
327 Error (ERR_IDENT_EXPECTED);
332 /* Did we already define that macro? */
333 if (HT_Find (&MacroTab, SVal) != 0) {
334 /* Macro is already defined */
335 Error (ERR_SYM_ALREADY_DEFINED, SVal);
336 /* Skip tokens until we reach the final .endmacro */
341 /* Define the macro */
342 M = NewMacro (SVal, Style);
344 /* Switch to raw token mode and skip the macro name */
345 EnterRawTokenMode ();
348 /* If we have a DEFINE style macro, we may have parameters in braces,
349 * otherwise we may have parameters without braces.
351 if (Style == MAC_STYLE_CLASSIC) {
354 if (Tok == TOK_LPAREN) {
362 /* Parse the parameter list */
365 while (Tok == TOK_IDENT) {
367 /* Create a struct holding the identifier */
368 IdDesc* I = NewIdDesc (SVal);
370 /* Insert the struct into the list, checking for duplicate idents */
371 if (M->ParamCount == 0) {
374 IdDesc* List = M->Params;
376 if (strcmp (List->Id, SVal) == 0) {
377 Error (ERR_SYM_ALREADY_DEFINED, SVal);
379 if (List->Next == 0) {
392 /* Maybe there are more params... */
393 if (Tok == TOK_COMMA) {
401 /* For class macros, we expect a separator token, for define style macros,
402 * we expect the closing paren.
404 if (Style == MAC_STYLE_CLASSIC) {
406 } else if (HaveParams) {
410 /* Preparse the macro body. We will read the tokens until we reach end of
411 * file, or a .endmacro (or end of line for DEFINE style macros) and store
412 * them into an token list internal to the macro. For classic macros, there
413 * the .LOCAL command is detected and removed at this time.
417 /* Check for end of macro */
418 if (Style == MAC_STYLE_CLASSIC) {
419 /* In classic macros, only .endmacro is allowed */
420 if (Tok == TOK_ENDMACRO) {
424 /* May not have end of file in a macro definition */
425 if (Tok == TOK_EOF) {
426 Error (ERR_ENDMACRO_EXPECTED);
430 /* Accept a newline or end of file for new style macros */
431 if (TokIsSep (Tok)) {
436 /* Check for a .LOCAL declaration */
437 if (Tok == TOK_LOCAL && Style == MAC_STYLE_CLASSIC) {
443 /* Skip .local or comma */
446 /* Need an identifer */
447 if (Tok != TOK_IDENT) {
448 Error (ERR_IDENT_EXPECTED);
453 /* Put the identifier into the locals list and skip it */
454 I = NewIdDesc (SVal);
460 /* Check for end of list */
461 if (Tok != TOK_COMMA) {
467 /* We need end of line after the locals */
472 /* Create a token node for the current token */
475 /* If the token is an ident, check if it is a local parameter */
476 if (Tok == TOK_IDENT) {
478 IdDesc* I = M->Params;
480 if (strcmp (I->Id, SVal) == 0) {
481 /* Local param name, replace it */
482 T->Tok = TOK_MACPARAM;
491 /* Insert the new token in the list */
492 if (M->TokCount == 0) {
494 M->TokRoot = M->TokLast = T;
496 /* We have already tokens */
497 M->TokLast->Next = T;
502 /* Read the next token */
506 /* Skip the .endmacro for a classic macro */
507 if (Style == MAC_STYLE_CLASSIC) {
512 /* Switch out of raw token mode */
513 LeaveRawTokenMode ();
518 static int MacExpand (void* Data)
519 /* If we're currently expanding a macro, set the the scanner token and
520 * attribute to the next value and return true. If we are not expanding
521 * a macro, return false.
524 /* Cast the Data pointer to the actual data structure */
525 MacExp* Mac = (MacExp*) Data;
527 /* Check if we should abort this macro */
533 /* Abort any open .IF statements in this macro expansion */
534 CleanupIfStack (Mac->IfSP);
536 /* Terminate macro expansion */
540 /* We're expanding a macro. Check if we are expanding one of the
545 /* Ok, use token from parameter list */
546 TokSet (Mac->ParamExp);
548 /* Set pointer to next token */
549 Mac->ParamExp = Mac->ParamExp->Next;
556 /* We're not expanding macro parameters. Check if we have tokens left from
561 /* Use next macro token */
564 /* Set pointer to next token */
565 Mac->Exp = Mac->Exp->Next;
567 /* Is it a request for actual parameter count? */
568 if (Tok == TOK_PARAMCOUNT) {
570 IVal = Mac->ParamCount;
574 /* Is it the name of a macro parameter? */
575 if (Tok == TOK_MACPARAM) {
577 /* Start to expand the parameter token list */
578 Mac->ParamExp = Mac->Params [IVal];
580 /* Recursive call to expand the parameter */
581 return MacExpand (Mac);
584 /* If it's an identifier, it may in fact be a local symbol */
585 if (Tok == TOK_IDENT && Mac->M->LocalCount) {
586 /* Search for the local symbol in the list */
588 IdDesc* I = Mac->M->Locals;
590 if (strcmp (SVal, I->Id) == 0) {
591 /* This is in fact a local symbol, change the name. Be sure
592 * to generate a local label name if the original name was
593 * a local label, and also generate a name that cannot be
594 * generated by a user.
596 unsigned PrefixLen = (I->Id[0] == LocalStart);
597 sprintf (SVal, "%.*sLOCAL-MACRO-SYMBOL-%04X", PrefixLen,
598 I->Id, Mac->LocalStart + Index);
610 /* The token was successfully set */
615 /* No more macro tokens. Do we have a final token? */
618 /* Set the final token and remove it */
620 FreeTokNode (Mac->Final);
623 /* The token was successfully set */
629 /* End of macro expansion */
632 /* Pop the input function */
635 /* No token available */
641 static void StartExpClassic (Macro* M)
642 /* Start expanding the classic macro M */
646 /* Skip the macro name */
649 /* Create a structure holding expansion data */
652 /* Read the actual parameters */
653 while (!TokIsSep (Tok)) {
657 /* Check for maximum parameter count */
658 if (E->ParamCount >= M->ParamCount) {
659 Error (ERR_TOO_MANY_PARAMS);
664 /* Read tokens for one parameter, accept empty params */
666 while (Tok != TOK_COMMA && Tok != TOK_SEP) {
670 /* Check for end of file */
671 if (Tok == TOK_EOF) {
672 Error (ERR_UNEXPECTED_EOF);
676 /* Get the next token in a node */
679 /* Insert it into the list */
681 E->Params [E->ParamCount] = T;
691 /* One parameter more */
694 /* Check for a comma */
695 if (Tok == TOK_COMMA) {
702 /* Insert a new token input function */
703 PushInput (MacExpand, E, ".MACRO");
708 static void StartExpDefine (Macro* M)
709 /* Start expanding a DEFINE style macro */
711 /* Create a structure holding expansion data */
712 MacExp* E = NewMacExp (M);
714 /* A define style macro must be called with as many actual parameters
715 * as there are formal ones. Get the parameter count.
717 unsigned Count = M->ParamCount;
719 /* Skip the current token */
722 /* Read the actual parameters */
727 /* Check if there is really a parameter */
728 if (TokIsSep (Tok) || Tok == TOK_COMMA) {
729 Error (ERR_MACRO_PARAM_EXPECTED);
734 /* Read tokens for one parameter */
740 /* Get the next token in a node */
743 /* Insert it into the list */
745 E->Params [E->ParamCount] = T;
754 } while (Tok != TOK_COMMA && !TokIsSep (Tok));
756 /* One parameter more */
759 /* Check for a comma */
761 if (Tok == TOK_COMMA) {
764 Error (ERR_COMMA_EXPECTED);
769 /* Macro expansion will overwrite the current token. This is a problem
770 * for define style macros since these are called from the scanner level.
771 * To avoid it, remember the current token and re-insert it if macro
774 E->Final = NewTokNode ();
776 /* Insert a new token input function */
777 PushInput (MacExpand, E, ".DEFINE");
782 void MacExpandStart (void)
783 /* Start expanding the macro in SVal */
785 /* Search for the macro */
786 Macro* M = HT_FindEntry (&MacroTab, SVal);
789 /* Call the apropriate subroutine */
791 case MAC_STYLE_CLASSIC: StartExpClassic (M); break;
792 case MAC_STYLE_DEFINE: StartExpDefine (M); break;
793 default: Internal ("Invalid macro style: %d", M->Style);
800 /* Abort the current macro expansion */
802 /* Must have an expansion */
803 CHECK (MacExpansions > 0);
805 /* Set a flag so macro expansion will terminate on the next call */
811 int IsMacro (const char* Name)
812 /* Return true if the given name is the name of a macro */
814 return (HT_Find (&MacroTab, Name) != 0);
819 int IsDefine (const char* Name)
820 /* Return true if the given name is the name of a define style macro */
822 Macro* M = HT_FindEntry (&MacroTab, Name);
823 return (M != 0 && M->Style == MAC_STYLE_DEFINE);
828 int InMacExpansion (void)
829 /* Return true if we're currently expanding a macro */
831 return (MacExpansions > 0);