1 /*****************************************************************************/
5 /* Macros for the ca65 macroassembler */
9 /* (C) 1998-2011, Ullrich von Bassewitz */
10 /* Roemerstrasse 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 /*****************************************************************************/
59 /*****************************************************************************/
61 /*****************************************************************************/
65 static unsigned HT_GenHash (const void* Key);
66 /* Generate the hash over a key. */
68 static const void* HT_GetKey (void* Entry);
69 /* Given a pointer to the user entry data, return a pointer to the key */
71 static int HT_Compare (const void* Key1, const void* Key2);
72 /* Compare two keys. The function must return a value less than zero if
73 * Key1 is smaller than Key2, zero if both are equal, and a value greater
74 * than zero if Key1 is greater then Key2.
79 /*****************************************************************************/
81 /*****************************************************************************/
85 /* Struct that describes an identifer (macro param, local list) */
86 typedef struct IdDesc IdDesc;
88 IdDesc* Next; /* Linked list */
89 StrBuf Id; /* Identifier, dynamically allocated */
94 /* Struct that describes a macro definition */
96 HashNode Node; /* Hash list node */
97 Macro* List; /* List of all macros */
98 unsigned LocalCount; /* Count of local symbols */
99 IdDesc* Locals; /* List of local symbols */
100 unsigned ParamCount; /* Parameter count of macro */
101 IdDesc* Params; /* Identifiers of macro parameters */
102 unsigned TokCount; /* Number of tokens for this macro */
103 TokNode* TokRoot; /* Root of token list */
104 TokNode* TokLast; /* Pointer to last token in list */
105 StrBuf Name; /* Macro name, dynamically allocated */
106 unsigned Expansions; /* Number of active macro expansions */
107 unsigned char Style; /* Macro style */
108 unsigned char Incomplete; /* Macro is currently built */
111 /* Hash table functions */
112 static const HashFunctions HashFunc = {
118 /* Macro hash table */
119 static HashTable MacroTab = STATIC_HASHTABLE_INITIALIZER (117, &HashFunc);
121 /* Structs that holds data for a macro expansion */
122 typedef struct MacExp MacExp;
124 MacExp* Next; /* Pointer to next expansion */
125 Macro* M; /* Which macro do we expand? */
126 unsigned IfSP; /* .IF stack pointer at start of expansion */
127 TokNode* Exp; /* Pointer to current token */
128 TokNode* Final; /* Pointer to final token */
129 unsigned LocalStart; /* Start of counter for local symbol names */
130 unsigned ParamCount; /* Number of actual parameters */
131 TokNode** Params; /* List of actual parameters */
132 TokNode* ParamExp; /* Node for expanding parameters */
133 int LISlot; /* Slot for additional line infos */
136 /* Maximum number of nested macro expansions */
137 #define MAX_MACEXPANSIONS 256U
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;
148 /* Define style macros disabled if != 0 */
149 static unsigned DisableDefines = 0;
153 /*****************************************************************************/
154 /* Hash table functions */
155 /*****************************************************************************/
159 static unsigned HT_GenHash (const void* Key)
160 /* Generate the hash over a key. */
162 return HashBuf (Key);
167 static const void* HT_GetKey (void* Entry)
168 /* Given a pointer to the user entry data, return a pointer to the index */
170 return &((Macro*) Entry)->Name;
175 static int HT_Compare (const void* Key1, const void* Key2)
176 /* Compare two keys. The function must return a value less than zero if
177 * Key1 is smaller than Key2, zero if both are equal, and a value greater
178 * than zero if Key1 is greater then Key2.
181 return SB_Compare (Key1, Key2);
186 /*****************************************************************************/
188 /*****************************************************************************/
192 static IdDesc* NewIdDesc (const StrBuf* Id)
193 /* Create a new IdDesc, initialize and return it */
195 /* Allocate memory */
196 IdDesc* ID = xmalloc (sizeof (IdDesc));
198 /* Initialize the struct */
201 SB_Copy (&ID->Id, Id);
203 /* Return the new struct */
209 static void FreeIdDesc (IdDesc* ID)
215 /* Free the structure itself */
221 static void FreeIdDescList (IdDesc* ID)
222 /* Free a complete list of IdDesc structures */
233 static Macro* NewMacro (const StrBuf* Name, unsigned char Style)
234 /* Generate a new macro entry, initialize and return it */
236 /* Allocate memory */
237 Macro* M = xmalloc (sizeof (Macro));
239 /* Initialize the macro struct */
240 InitHashNode (&M->Node);
249 SB_Copy (&M->Name, Name);
254 /* Insert the macro into the hash table */
255 HT_Insert (&MacroTab, &M->Node);
257 /* Return the new macro struct */
263 static void FreeMacro (Macro* M)
264 /* Free a macro entry which has already been removed from the macro table. */
269 FreeIdDescList (M->Locals);
271 /* Free identifiers of parameters */
272 FreeIdDescList (M->Params);
274 /* Free the token list for the macro */
275 while ((T = M->TokRoot) != 0) {
276 M->TokRoot = T->Next;
280 /* Free the macro name */
283 /* Free the macro structure itself */
289 static MacExp* NewMacExp (Macro* M)
290 /* Create a new expansion structure for the given macro */
294 /* Allocate memory */
295 MacExp* E = xmalloc (sizeof (MacExp));
297 /* Initialize the data */
299 E->IfSP = GetIfStack ();
302 E->LocalStart = LocalName;
303 LocalName += M->LocalCount;
305 E->Params = xmalloc (M->ParamCount * sizeof (TokNode*));
306 for (I = 0; I < M->ParamCount; ++I) {
310 E->LISlot = AllocLineInfoSlot (LI_TYPE_MACRO, MacExpansions);
312 /* Mark the macro as expanding */
315 /* One macro expansion more */
318 /* Return the new macro expansion */
324 static void FreeMacExp (MacExp* E)
325 /* Remove and free the current macro expansion */
329 /* One macro expansion less */
332 /* No longer expanding this macro */
335 /* Free the parameter lists */
336 for (I = 0; I < E->ParamCount; ++I) {
337 /* Free one parameter list */
338 TokNode* N = E->Params[I];
340 TokNode* P = N->Next;
347 /* Free the additional line info slot */
348 FreeLineInfoSlot (E->LISlot);
350 /* Free the final token if we have one */
352 FreeTokNode (E->Final);
355 /* Free the structure itself */
361 static void MacSkipDef (unsigned Style)
362 /* Skip a macro definition */
364 if (Style == MAC_STYLE_CLASSIC) {
365 /* Skip tokens until we reach the final .endmacro */
366 while (CurTok.Tok != TOK_ENDMACRO && CurTok.Tok != TOK_EOF) {
369 if (CurTok.Tok != TOK_EOF) {
372 Error ("`.ENDMACRO' expected");
375 /* Skip until end of line */
382 void MacDef (unsigned Style)
383 /* Parse a macro definition */
389 /* We expect a macro name here */
390 if (CurTok.Tok != TOK_IDENT) {
391 Error ("Identifier expected");
394 } else if (!UbiquitousIdents && FindInstruction (&CurTok.SVal) >= 0) {
395 /* The identifier is a name of a 6502 instruction, which is not
396 * allowed if not explicitly enabled.
398 Error ("Cannot use an instruction as macro name");
403 /* Did we already define that macro? */
404 if (HT_Find (&MacroTab, &CurTok.SVal) != 0) {
405 /* Macro is already defined */
406 Error ("A macro named `%m%p' is already defined", &CurTok.SVal);
407 /* Skip tokens until we reach the final .endmacro */
412 /* Define the macro */
413 M = NewMacro (&CurTok.SVal, Style);
415 /* Switch to raw token mode and skip the macro name */
416 EnterRawTokenMode ();
419 /* If we have a DEFINE style macro, we may have parameters in braces,
420 * otherwise we may have parameters without braces.
422 if (Style == MAC_STYLE_CLASSIC) {
425 if (CurTok.Tok == TOK_LPAREN) {
433 /* Parse the parameter list */
436 while (CurTok.Tok == TOK_IDENT) {
438 /* Create a struct holding the identifier */
439 IdDesc* I = NewIdDesc (&CurTok.SVal);
441 /* Insert the struct into the list, checking for duplicate idents */
442 if (M->ParamCount == 0) {
445 IdDesc* List = M->Params;
447 if (SB_Compare (&List->Id, &CurTok.SVal) == 0) {
448 Error ("Duplicate symbol `%m%p'", &CurTok.SVal);
450 if (List->Next == 0) {
463 /* Maybe there are more params... */
464 if (CurTok.Tok == TOK_COMMA) {
472 /* For class macros, we expect a separator token, for define style macros,
473 * we expect the closing paren.
475 if (Style == MAC_STYLE_CLASSIC) {
477 } else if (HaveParams) {
481 /* Preparse the macro body. We will read the tokens until we reach end of
482 * file, or a .endmacro (or end of line for DEFINE style macros) and store
483 * them into an token list internal to the macro. For classic macros, there
484 * the .LOCAL command is detected and removed at this time.
488 /* Check for end of macro */
489 if (Style == MAC_STYLE_CLASSIC) {
490 /* In classic macros, only .endmacro is allowed */
491 if (CurTok.Tok == TOK_ENDMACRO) {
495 /* May not have end of file in a macro definition */
496 if (CurTok.Tok == TOK_EOF) {
497 Error ("`.ENDMACRO' expected");
501 /* Accept a newline or end of file for new style macros */
502 if (TokIsSep (CurTok.Tok)) {
507 /* Check for a .LOCAL declaration */
508 if (CurTok.Tok == TOK_LOCAL && Style == MAC_STYLE_CLASSIC) {
514 /* Skip .local or comma */
517 /* Need an identifer */
518 if (CurTok.Tok != TOK_IDENT && CurTok.Tok != TOK_LOCAL_IDENT) {
519 Error ("Identifier expected");
524 /* Put the identifier into the locals list and skip it */
525 I = NewIdDesc (&CurTok.SVal);
531 /* Check for end of list */
532 if (CurTok.Tok != TOK_COMMA) {
538 /* We need end of line after the locals */
543 /* Create a token node for the current token */
546 /* If the token is an ident, check if it is a local parameter */
547 if (CurTok.Tok == TOK_IDENT) {
549 IdDesc* I = M->Params;
551 if (SB_Compare (&I->Id, &CurTok.SVal) == 0) {
552 /* Local param name, replace it */
553 N->T.Tok = TOK_MACPARAM;
562 /* Insert the new token in the list */
563 if (M->TokCount == 0) {
565 M->TokRoot = M->TokLast = N;
567 /* We have already tokens */
568 M->TokLast->Next = N;
573 /* Read the next token */
577 /* Skip the .endmacro for a classic macro */
578 if (Style == MAC_STYLE_CLASSIC) {
582 /* Reset the Incomplete flag now that parsing is done */
586 /* Switch out of raw token mode */
587 LeaveRawTokenMode ();
592 void MacUndef (const StrBuf* Name, unsigned char Style)
593 /* Undefine the macro with the given name and style. A style mismatch is
594 * treated as if the macro didn't exist.
597 /* Search for the macro */
598 Macro* M = HT_FindEntry (&MacroTab, Name);
600 /* Don't let the user kid with us */
601 if (M == 0 || M->Style != Style) {
602 Error ("No such macro: %m%p", Name);
605 if (M->Expansions > 0) {
606 Error ("Cannot delete a macro that is currently expanded");
610 /* Remove the macro from the macro table */
611 HT_RemoveEntry (&MacroTab, M);
613 /* Free the macro structure */
619 static int MacExpand (void* Data)
620 /* If we're currently expanding a macro, set the the scanner token and
621 * attribute to the next value and return true. If we are not expanding
622 * a macro, return false.
625 /* Cast the Data pointer to the actual data structure */
626 MacExp* Mac = (MacExp*) Data;
628 /* Check if we should abort this macro */
634 /* Abort any open .IF statements in this macro expansion */
635 CleanupIfStack (Mac->IfSP);
637 /* Terminate macro expansion */
641 /* We're expanding a macro. Check if we are expanding one of the
647 /* Ok, use token from parameter list, but don't use its line info */
648 TokSet (Mac->ParamExp, LI_SLOT_INV);
650 /* Set pointer to next token */
651 Mac->ParamExp = Mac->ParamExp->Next;
657 /* We're not expanding macro parameters. Check if we have tokens left from
662 /* Use next macro token */
663 TokSet (Mac->Exp, Mac->LISlot);
665 /* Set pointer to next token */
666 Mac->Exp = Mac->Exp->Next;
668 /* Is it a request for actual parameter count? */
669 if (CurTok.Tok == TOK_PARAMCOUNT) {
670 CurTok.Tok = TOK_INTCON;
671 CurTok.IVal = Mac->ParamCount;
675 /* Is it the name of a macro parameter? */
676 if (CurTok.Tok == TOK_MACPARAM) {
678 /* Start to expand the parameter token list */
679 Mac->ParamExp = Mac->Params[CurTok.IVal];
681 /* Go back and expand the parameter */
685 /* If it's an identifier, it may in fact be a local symbol */
686 if ((CurTok.Tok == TOK_IDENT || CurTok.Tok == TOK_LOCAL_IDENT) &&
687 Mac->M->LocalCount) {
688 /* Search for the local symbol in the list */
690 IdDesc* I = Mac->M->Locals;
692 if (SB_Compare (&CurTok.SVal, &I->Id) == 0) {
693 /* This is in fact a local symbol, change the name. Be sure
694 * to generate a local label name if the original name was
695 * a local label, and also generate a name that cannot be
696 * generated by a user.
698 if (SB_At (&I->Id, 0) == LocalStart) {
699 /* Must generate a local symbol */
700 SB_Printf (&CurTok.SVal, "%cLOCAL-MACRO_SYMBOL-%04X",
701 LocalStart, Mac->LocalStart + Index);
704 SB_Printf (&CurTok.SVal, "LOCAL-MACRO_SYMBOL-%04X",
705 Mac->LocalStart + Index);
718 /* The token was successfully set */
722 /* No more macro tokens. Do we have a final token? */
725 /* Set the final token and remove it */
726 TokSet (Mac->Final, LI_SLOT_INV);
727 FreeTokNode (Mac->Final);
730 /* Problem: When a .define style macro is expanded within the call
731 * of a classic one, the latter may be terminated and removed while
732 * the expansion of the .define style macro is still active. Because
733 * line info slots are "stacked", this runs into a CHECK FAILED. For
734 * now, we will fix that by removing the .define style macro expansion
735 * immediately, once the final token is placed. The better solution
736 * would probably be to not require AllocLineInfoSlot/FreeLineInfoSlot
737 * to be called in FIFO order, but this is a bigger change.
739 /* End of macro expansion and pop the input function */
743 /* The token was successfully set */
748 /* End of macro expansion */
751 /* Pop the input function */
754 /* No token available */
760 static void StartExpClassic (MacExp* E)
761 /* Start expanding a classic macro */
765 /* Skip the macro name */
768 /* Read the actual parameters */
769 while (!TokIsSep (CurTok.Tok)) {
773 /* Check for maximum parameter count */
774 if (E->ParamCount >= E->M->ParamCount) {
775 ErrorSkip ("Too many macro parameters");
779 /* The macro may optionally be enclosed in curly braces */
780 Term = GetTokListTerm (TOK_COMMA);
782 /* Read tokens for one parameter, accept empty params */
784 while (CurTok.Tok != Term && CurTok.Tok != TOK_SEP) {
788 /* Check for end of file */
789 if (CurTok.Tok == TOK_EOF) {
790 Error ("Unexpected end of file");
795 /* Get the next token in a node */
798 /* Insert it into the list */
800 E->Params [E->ParamCount] = T;
810 /* One parameter more */
813 /* If the macro argument was enclosed in curly braces, end-of-line
814 * is an error. Skip the closing curly brace.
816 if (Term == TOK_RCURLY) {
817 if (CurTok.Tok == TOK_SEP) {
818 Error ("End of line encountered within macro argument");
824 /* Check for a comma */
825 if (CurTok.Tok == TOK_COMMA) {
832 /* We must be at end of line now, otherwise something is wrong */
835 /* Insert a new token input function */
836 PushInput (MacExpand, E, ".MACRO");
841 static void StartExpDefine (MacExp* E)
842 /* Start expanding a DEFINE style macro */
844 /* A define style macro must be called with as many actual parameters
845 * as there are formal ones. Get the parameter count.
847 unsigned Count = E->M->ParamCount;
849 /* Skip the current token */
852 /* Read the actual parameters */
857 /* The macro may optionally be enclosed in curly braces */
858 token_t Term = GetTokListTerm (TOK_COMMA);
860 /* Check if there is really a parameter */
861 if (TokIsSep (CurTok.Tok) || CurTok.Tok == Term) {
862 ErrorSkip ("Macro parameter #%u is empty", E->ParamCount+1);
867 /* Read tokens for one parameter */
873 /* Get the next token in a node */
876 /* Insert it into the list */
878 E->Params [E->ParamCount] = T;
887 } while (CurTok.Tok != Term && !TokIsSep (CurTok.Tok));
889 /* One parameter more */
892 /* If the macro argument was enclosed in curly braces, end-of-line
893 * is an error. Skip the closing curly brace.
895 if (Term == TOK_RCURLY) {
896 if (TokIsSep (CurTok.Tok)) {
897 Error ("End of line encountered within macro argument");
903 /* Check for a comma */
905 if (CurTok.Tok == TOK_COMMA) {
908 Error ("`,' expected");
913 /* Macro expansion will overwrite the current token. This is a problem
914 * for define style macros since these are called from the scanner level.
915 * To avoid it, remember the current token and re-insert it, once macro
918 E->Final = NewTokNode ();
920 /* Insert a new token input function */
921 PushInput (MacExpand, E, ".DEFINE");
926 void MacExpandStart (Macro* M)
927 /* Start expanding a macro */
931 /* Check the argument */
932 PRECONDITION (M && (M->Style != MAC_STYLE_DEFINE || DisableDefines == 0));
934 /* We cannot expand an incomplete macro */
936 Error ("Cannot expand an incomplete macro");
940 /* Don't allow too many nested macro expansions - otherwise it is possible
941 * to force an endless loop and assembler crash.
943 if (MacExpansions >= MAX_MACEXPANSIONS) {
944 Error ("Too many nested macro expansions");
948 /* Create a structure holding expansion data */
951 /* Call the apropriate subroutine */
953 case MAC_STYLE_CLASSIC: StartExpClassic (E); break;
954 case MAC_STYLE_DEFINE: StartExpDefine (E); break;
955 default: Internal ("Invalid macro style: %d", M->Style);
962 /* Abort the current macro expansion */
964 /* Must have an expansion */
965 CHECK (MacExpansions > 0);
967 /* Set a flag so macro expansion will terminate on the next call */
973 Macro* FindMacro (const StrBuf* Name)
974 /* Try to find the macro with the given name and return it. If no macro with
975 * this name was found, return NULL.
978 Macro* M = HT_FindEntry (&MacroTab, Name);
979 return (M != 0 && M->Style == MAC_STYLE_CLASSIC)? M : 0;
984 Macro* FindDefine (const StrBuf* Name)
985 /* Try to find the define style macro with the given name and return it. If no
986 * such macro was found, return NULL.
991 /* Never if disabled */
992 if (DisableDefines) {
996 /* Check if we have such a macro */
997 M = HT_FindEntry (&MacroTab, Name);
998 return (M != 0 && M->Style == MAC_STYLE_DEFINE)? M : 0;
1003 int InMacExpansion (void)
1004 /* Return true if we're currently expanding a macro */
1006 return (MacExpansions > 0);
1011 void DisableDefineStyleMacros (void)
1012 /* Disable define style macros until EnableDefineStyleMacros is called */
1019 void EnableDefineStyleMacros (void)
1020 /* Re-enable define style macros previously disabled with
1021 * DisableDefineStyleMacros.
1024 PRECONDITION (DisableDefines > 0);