1 /*****************************************************************************/
5 /* Macros for the ca65 macroassembler */
9 /* (C) 1998-2008 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 /*****************************************************************************/
58 /*****************************************************************************/
60 /*****************************************************************************/
64 static unsigned HT_GenHash (const void* Key);
65 /* Generate the hash over a key. */
67 static const void* HT_GetKey (void* Entry);
68 /* Given a pointer to the user entry data, return a pointer to the key */
70 static HashNode* HT_GetHashNode (void* Entry);
71 /* Given a pointer to the user entry data, return a pointer to the hash node */
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.
81 /*****************************************************************************/
83 /*****************************************************************************/
87 /* Struct that describes an identifer (macro param, local list) */
88 typedef struct IdDesc IdDesc;
90 IdDesc* Next; /* Linked list */
91 StrBuf Id; /* Identifier, dynamically allocated */
96 /* Struct that describes a macro definition */
97 typedef struct Macro 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 */
112 /* Hash table functions */
113 static const HashFunctions HashFunc = {
120 /* Macro hash table */
121 static HashTable MacroTab = STATIC_HASHTABLE_INITIALIZER (117, &HashFunc);
123 /* Global macro data */
124 static Macro* MacroRoot = 0; /* List of all macros */
126 /* Structs that holds data for a macro expansion */
127 typedef struct MacExp 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 */
140 /* Number of active macro expansions */
141 static unsigned MacExpansions = 0;
143 /* Flag if a macro expansion should get aborted */
144 static int DoMacAbort = 0;
146 /* Counter to create local names for symbols */
147 static unsigned LocalName = 0;
151 /*****************************************************************************/
152 /* Hash table functions */
153 /*****************************************************************************/
157 static unsigned HT_GenHash (const void* Key)
158 /* Generate the hash over a key. */
160 return HashBuf (Key);
165 static const void* HT_GetKey (void* Entry)
166 /* Given a pointer to the user entry data, return a pointer to the index */
168 return &((Macro*) Entry)->Name;
173 static HashNode* HT_GetHashNode (void* Entry)
174 /* Given a pointer to the user entry data, return a pointer to the hash node */
176 return &((Macro*) Entry)->Node;
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.
187 return SB_Compare (Key1, Key2);
192 /*****************************************************************************/
194 /*****************************************************************************/
198 static IdDesc* NewIdDesc (const StrBuf* Id)
199 /* Create a new IdDesc, initialize and return it */
201 /* Allocate memory */
202 IdDesc* I = xmalloc (sizeof (IdDesc));
204 /* Initialize the struct */
206 I->Id = AUTO_STRBUF_INITIALIZER;
207 SB_Copy (&I->Id, Id);
209 /* Return the new struct */
215 static Macro* NewMacro (const StrBuf* Name, unsigned char Style)
216 /* Generate a new macro entry, initialize and return it */
218 /* Allocate memory */
219 Macro* M = xmalloc (sizeof (Macro));
221 /* Initialize the macro struct */
222 InitHashNode (&M->Node, M);
231 M->Name = AUTO_STRBUF_INITIALIZER;
232 SB_Copy (&M->Name, Name);
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 lists */
287 for (I = 0; I < E->ParamCount; ++I) {
288 /* Free one parameter list */
289 TokNode* N = E->Params[I];
291 TokNode* P = N->Next;
298 /* Free the final token if we have one */
300 FreeTokNode (E->Final);
303 /* Free the structure itself */
309 static void MacSkipDef (unsigned Style)
310 /* Skip a macro definition */
312 if (Style == MAC_STYLE_CLASSIC) {
313 /* Skip tokens until we reach the final .endmacro */
314 while (Tok != TOK_ENDMACRO && Tok != TOK_EOF) {
317 if (Tok != TOK_EOF) {
320 Error ("`.ENDMACRO' expected");
323 /* Skip until end of line */
330 void MacDef (unsigned Style)
331 /* Parse a macro definition */
337 /* We expect a macro name here */
338 if (Tok != TOK_IDENT) {
339 Error ("Identifier expected");
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.
346 Error ("Cannot use an instruction as macro name");
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 */
360 /* Define the macro */
361 M = NewMacro (&SVal, Style);
363 /* Switch to raw token mode and skip the macro name */
364 EnterRawTokenMode ();
367 /* If we have a DEFINE style macro, we may have parameters in braces,
368 * otherwise we may have parameters without braces.
370 if (Style == MAC_STYLE_CLASSIC) {
373 if (Tok == TOK_LPAREN) {
381 /* Parse the parameter list */
384 while (Tok == TOK_IDENT) {
386 /* Create a struct holding the identifier */
387 IdDesc* I = NewIdDesc (&SVal);
389 /* Insert the struct into the list, checking for duplicate idents */
390 if (M->ParamCount == 0) {
393 IdDesc* List = M->Params;
395 if (SB_Compare (&List->Id, &SVal) == 0) {
396 Error ("Duplicate symbol `%m%p'", &SVal);
398 if (List->Next == 0) {
411 /* Maybe there are more params... */
412 if (Tok == TOK_COMMA) {
420 /* For class macros, we expect a separator token, for define style macros,
421 * we expect the closing paren.
423 if (Style == MAC_STYLE_CLASSIC) {
425 } else if (HaveParams) {
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.
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) {
443 /* May not have end of file in a macro definition */
444 if (Tok == TOK_EOF) {
445 Error ("`.ENDMACRO' expected");
449 /* Accept a newline or end of file for new style macros */
450 if (TokIsSep (Tok)) {
455 /* Check for a .LOCAL declaration */
456 if (Tok == TOK_LOCAL && Style == MAC_STYLE_CLASSIC) {
462 /* Skip .local or comma */
465 /* Need an identifer */
466 if (Tok != TOK_IDENT && Tok != TOK_LOCAL_IDENT) {
467 Error ("Identifier expected");
472 /* Put the identifier into the locals list and skip it */
473 I = NewIdDesc (&SVal);
479 /* Check for end of list */
480 if (Tok != TOK_COMMA) {
486 /* We need end of line after the locals */
491 /* Create a token node for the current token */
494 /* If the token is an ident, check if it is a local parameter */
495 if (Tok == TOK_IDENT) {
497 IdDesc* I = M->Params;
499 if (SB_Compare (&I->Id, &SVal) == 0) {
500 /* Local param name, replace it */
501 T->Tok = TOK_MACPARAM;
510 /* Insert the new token in the list */
511 if (M->TokCount == 0) {
513 M->TokRoot = M->TokLast = T;
515 /* We have already tokens */
516 M->TokLast->Next = T;
521 /* Read the next token */
525 /* Skip the .endmacro for a classic macro */
526 if (Style == MAC_STYLE_CLASSIC) {
531 /* Switch out of raw token mode */
532 LeaveRawTokenMode ();
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.
543 /* Cast the Data pointer to the actual data structure */
544 MacExp* Mac = (MacExp*) Data;
546 /* Check if we should abort this macro */
552 /* Abort any open .IF statements in this macro expansion */
553 CleanupIfStack (Mac->IfSP);
555 /* Terminate macro expansion */
559 /* We're expanding a macro. Check if we are expanding one of the
564 /* Ok, use token from parameter list */
565 TokSet (Mac->ParamExp);
567 /* Set pointer to next token */
568 Mac->ParamExp = Mac->ParamExp->Next;
575 /* We're not expanding macro parameters. Check if we have tokens left from
580 /* Use next macro token */
583 /* Set pointer to next token */
584 Mac->Exp = Mac->Exp->Next;
586 /* Is it a request for actual parameter count? */
587 if (Tok == TOK_PARAMCOUNT) {
589 IVal = Mac->ParamCount;
593 /* Is it the name of a macro parameter? */
594 if (Tok == TOK_MACPARAM) {
596 /* Start to expand the parameter token list */
597 Mac->ParamExp = Mac->Params [IVal];
599 /* Recursive call to expand the parameter */
600 return MacExpand (Mac);
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 */
607 IdDesc* I = Mac->M->Locals;
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.
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);
621 SB_Printf (&SVal, "LOCAL-MACRO_SYMBOL-%04X",
622 Mac->LocalStart + Index);
635 /* The token was successfully set */
640 /* No more macro tokens. Do we have a final token? */
643 /* Set the final token and remove it */
645 FreeTokNode (Mac->Final);
648 /* The token was successfully set */
654 /* End of macro expansion */
657 /* Pop the input function */
660 /* No token available */
666 static void StartExpClassic (Macro* M)
667 /* Start expanding the classic macro M */
673 /* Skip the macro name */
676 /* Create a structure holding expansion data */
679 /* Read the actual parameters */
680 while (!TokIsSep (Tok)) {
684 /* Check for maximum parameter count */
685 if (E->ParamCount >= M->ParamCount) {
686 ErrorSkip ("Too many macro parameters");
690 /* The macro may optionally be enclosed in curly braces */
691 Term = GetTokListTerm (TOK_COMMA);
693 /* Read tokens for one parameter, accept empty params */
695 while (Tok != Term && Tok != TOK_SEP) {
699 /* Check for end of file */
700 if (Tok == TOK_EOF) {
701 Error ("Unexpected end of file");
706 /* Get the next token in a node */
709 /* Insert it into the list */
711 E->Params [E->ParamCount] = T;
721 /* One parameter more */
724 /* If the macro argument was enclosed in curly braces, end-of-line
725 * is an error. Skip the closing curly brace.
727 if (Term == TOK_RCURLY) {
728 if (Tok == TOK_SEP) {
729 Error ("End of line encountered within macro argument");
735 /* Check for a comma */
736 if (Tok == TOK_COMMA) {
743 /* We must be at end of line now, otherwise something is wrong */
746 /* Insert a new token input function */
747 PushInput (MacExpand, E, ".MACRO");
752 static void StartExpDefine (Macro* M)
753 /* Start expanding a DEFINE style macro */
755 /* Create a structure holding expansion data */
756 MacExp* E = NewMacExp (M);
758 /* A define style macro must be called with as many actual parameters
759 * as there are formal ones. Get the parameter count.
761 unsigned Count = M->ParamCount;
763 /* Skip the current token */
766 /* Read the actual parameters */
771 /* The macro may optionally be enclosed in curly braces */
772 Token Term = GetTokListTerm (TOK_COMMA);
774 /* Check if there is really a parameter */
775 if (TokIsSep (Tok) || Tok == Term) {
776 ErrorSkip ("Macro parameter #%u is empty", E->ParamCount+1);
781 /* Read tokens for one parameter */
787 /* Get the next token in a node */
790 /* Insert it into the list */
792 E->Params [E->ParamCount] = T;
801 } while (Tok != Term && !TokIsSep (Tok));
803 /* One parameter more */
806 /* If the macro argument was enclosed in curly braces, end-of-line
807 * is an error. Skip the closing curly brace.
809 if (Term == TOK_RCURLY) {
810 if (TokIsSep (Tok)) {
811 Error ("End of line encountered within macro argument");
817 /* Check for a comma */
819 if (Tok == TOK_COMMA) {
822 Error ("`,' expected");
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
832 E->Final = NewTokNode ();
834 /* Insert a new token input function */
835 PushInput (MacExpand, E, ".DEFINE");
840 void MacExpandStart (void)
841 /* Start expanding the macro in SVal */
843 /* Search for the macro */
844 Macro* M = HT_FindEntry (&MacroTab, &SVal);
847 /* Call the apropriate subroutine */
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);
858 /* Abort the current macro expansion */
860 /* Must have an expansion */
861 CHECK (MacExpansions > 0);
863 /* Set a flag so macro expansion will terminate on the next call */
869 int IsMacro (const StrBuf* Name)
870 /* Return true if the given name is the name of a macro */
872 return (HT_Find (&MacroTab, Name) != 0);
877 int IsDefine (const StrBuf* Name)
878 /* Return true if the given name is the name of a define style macro */
880 Macro* M = HT_FindEntry (&MacroTab, Name);
881 return (M != 0 && M->Style == MAC_STYLE_DEFINE);
886 int InMacExpansion (void)
887 /* Return true if we're currently expanding a macro */
889 return (MacExpansions > 0);