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 HashNode* HT_GetHashNode (void* Entry);
72 /* Given a pointer to the user entry data, return a pointer to the hash node */
74 static int HT_Compare (const void* Key1, const void* Key2);
75 /* Compare two keys. The function must return a value less than zero if
76 * Key1 is smaller than Key2, zero if both are equal, and a value greater
77 * than zero if Key1 is greater then Key2.
82 /*****************************************************************************/
84 /*****************************************************************************/
88 /* Struct that describes an identifer (macro param, local list) */
89 typedef struct IdDesc IdDesc;
91 IdDesc* Next; /* Linked list */
92 StrBuf Id; /* Identifier, dynamically allocated */
97 /* Struct that describes a macro definition */
98 typedef struct Macro Macro;
100 HashNode Node; /* Hash list node */
101 Macro* List; /* List of all macros */
102 unsigned LocalCount; /* Count of local symbols */
103 IdDesc* Locals; /* List of local symbols */
104 unsigned ParamCount; /* Parameter count of macro */
105 IdDesc* Params; /* Identifiers of macro parameters */
106 unsigned TokCount; /* Number of tokens for this macro */
107 TokNode* TokRoot; /* Root of token list */
108 TokNode* TokLast; /* Pointer to last token in list */
109 unsigned char Style; /* Macro style */
110 StrBuf Name; /* Macro name, dynamically allocated */
113 /* Hash table functions */
114 static const HashFunctions HashFunc = {
121 /* Macro hash table */
122 static HashTable MacroTab = STATIC_HASHTABLE_INITIALIZER (117, &HashFunc);
124 /* Global macro data */
125 static Macro* MacroRoot = 0; /* List of all macros */
127 /* Structs that holds data for a macro expansion */
128 typedef struct MacExp MacExp;
130 MacExp* Next; /* Pointer to next expansion */
131 Macro* M; /* Which macro do we expand? */
132 unsigned IfSP; /* .IF stack pointer at start of expansion */
133 TokNode* Exp; /* Pointer to current token */
134 TokNode* Final; /* Pointer to final token */
135 unsigned LocalStart; /* Start of counter for local symbol names */
136 unsigned ParamCount; /* Number of actual parameters */
137 TokNode** Params; /* List of actual parameters */
138 TokNode* ParamExp; /* Node for expanding parameters */
139 unsigned LISlot; /* Slot for additional line infos */
142 /* Number of active macro expansions */
143 static unsigned MacExpansions = 0;
145 /* Flag if a macro expansion should get aborted */
146 static int DoMacAbort = 0;
148 /* Counter to create local names for symbols */
149 static unsigned LocalName = 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 HashNode* HT_GetHashNode (void* Entry)
176 /* Given a pointer to the user entry data, return a pointer to the hash node */
178 return &((Macro*) Entry)->Node;
183 static int HT_Compare (const void* Key1, const void* Key2)
184 /* Compare two keys. The function must return a value less than zero if
185 * Key1 is smaller than Key2, zero if both are equal, and a value greater
186 * than zero if Key1 is greater then Key2.
189 return SB_Compare (Key1, Key2);
194 /*****************************************************************************/
196 /*****************************************************************************/
200 static IdDesc* NewIdDesc (const StrBuf* Id)
201 /* Create a new IdDesc, initialize and return it */
203 /* Allocate memory */
204 IdDesc* I = xmalloc (sizeof (IdDesc));
206 /* Initialize the struct */
209 SB_Copy (&I->Id, Id);
211 /* Return the new struct */
217 static Macro* NewMacro (const StrBuf* Name, unsigned char Style)
218 /* Generate a new macro entry, initialize and return it */
220 /* Allocate memory */
221 Macro* M = xmalloc (sizeof (Macro));
223 /* Initialize the macro struct */
224 InitHashNode (&M->Node, M);
234 SB_Copy (&M->Name, Name);
236 /* Insert the macro into the global macro list */
240 /* Insert the macro into the hash table */
241 HT_Insert (&MacroTab, &M->Node);
243 /* Return the new macro struct */
249 static MacExp* NewMacExp (Macro* M)
250 /* Create a new expansion structure for the given macro */
254 /* Allocate memory */
255 MacExp* E = xmalloc (sizeof (MacExp));
257 /* Initialize the data */
259 E->IfSP = GetIfStack ();
262 E->LocalStart = LocalName;
263 LocalName += M->LocalCount;
265 E->Params = xmalloc (M->ParamCount * sizeof (TokNode*));
267 for (I = 0; I < M->ParamCount; ++I) {
270 E->LISlot = AllocLineInfoSlot (LI_TYPE_MACRO, MacExpansions);
272 /* One macro expansion more */
275 /* Return the new macro expansion */
281 static void FreeMacExp (MacExp* E)
282 /* Remove and free the current macro expansion */
286 /* One macro expansion less */
289 /* Free the parameter lists */
290 for (I = 0; I < E->ParamCount; ++I) {
291 /* Free one parameter list */
292 TokNode* N = E->Params[I];
294 TokNode* P = N->Next;
301 /* Free the additional line info slot */
302 FreeLineInfoSlot (E->LISlot);
304 /* Free the final token if we have one */
306 FreeTokNode (E->Final);
309 /* Free the structure itself */
315 static void MacSkipDef (unsigned Style)
316 /* Skip a macro definition */
318 if (Style == MAC_STYLE_CLASSIC) {
319 /* Skip tokens until we reach the final .endmacro */
320 while (CurTok.Tok != TOK_ENDMACRO && CurTok.Tok != TOK_EOF) {
323 if (CurTok.Tok != TOK_EOF) {
326 Error ("`.ENDMACRO' expected");
329 /* Skip until end of line */
336 void MacDef (unsigned Style)
337 /* Parse a macro definition */
343 /* We expect a macro name here */
344 if (CurTok.Tok != TOK_IDENT) {
345 Error ("Identifier expected");
348 } else if (!UbiquitousIdents && FindInstruction (&CurTok.SVal) >= 0) {
349 /* The identifier is a name of a 6502 instruction, which is not
350 * allowed if not explicitly enabled.
352 Error ("Cannot use an instruction as macro name");
357 /* Did we already define that macro? */
358 if (HT_Find (&MacroTab, &CurTok.SVal) != 0) {
359 /* Macro is already defined */
360 Error ("A macro named `%m%p' is already defined", &CurTok.SVal);
361 /* Skip tokens until we reach the final .endmacro */
366 /* Define the macro */
367 M = NewMacro (&CurTok.SVal, Style);
369 /* Switch to raw token mode and skip the macro name */
370 EnterRawTokenMode ();
373 /* If we have a DEFINE style macro, we may have parameters in braces,
374 * otherwise we may have parameters without braces.
376 if (Style == MAC_STYLE_CLASSIC) {
379 if (CurTok.Tok == TOK_LPAREN) {
387 /* Parse the parameter list */
390 while (CurTok.Tok == TOK_IDENT) {
392 /* Create a struct holding the identifier */
393 IdDesc* I = NewIdDesc (&CurTok.SVal);
395 /* Insert the struct into the list, checking for duplicate idents */
396 if (M->ParamCount == 0) {
399 IdDesc* List = M->Params;
401 if (SB_Compare (&List->Id, &CurTok.SVal) == 0) {
402 Error ("Duplicate symbol `%m%p'", &CurTok.SVal);
404 if (List->Next == 0) {
417 /* Maybe there are more params... */
418 if (CurTok.Tok == TOK_COMMA) {
426 /* For class macros, we expect a separator token, for define style macros,
427 * we expect the closing paren.
429 if (Style == MAC_STYLE_CLASSIC) {
431 } else if (HaveParams) {
435 /* Preparse the macro body. We will read the tokens until we reach end of
436 * file, or a .endmacro (or end of line for DEFINE style macros) and store
437 * them into an token list internal to the macro. For classic macros, there
438 * the .LOCAL command is detected and removed at this time.
442 /* Check for end of macro */
443 if (Style == MAC_STYLE_CLASSIC) {
444 /* In classic macros, only .endmacro is allowed */
445 if (CurTok.Tok == TOK_ENDMACRO) {
449 /* May not have end of file in a macro definition */
450 if (CurTok.Tok == TOK_EOF) {
451 Error ("`.ENDMACRO' expected");
455 /* Accept a newline or end of file for new style macros */
456 if (TokIsSep (CurTok.Tok)) {
461 /* Check for a .LOCAL declaration */
462 if (CurTok.Tok == TOK_LOCAL && Style == MAC_STYLE_CLASSIC) {
468 /* Skip .local or comma */
471 /* Need an identifer */
472 if (CurTok.Tok != TOK_IDENT && CurTok.Tok != TOK_LOCAL_IDENT) {
473 Error ("Identifier expected");
478 /* Put the identifier into the locals list and skip it */
479 I = NewIdDesc (&CurTok.SVal);
485 /* Check for end of list */
486 if (CurTok.Tok != TOK_COMMA) {
492 /* We need end of line after the locals */
497 /* Create a token node for the current token */
500 /* If the token is an ident, check if it is a local parameter */
501 if (CurTok.Tok == TOK_IDENT) {
503 IdDesc* I = M->Params;
505 if (SB_Compare (&I->Id, &CurTok.SVal) == 0) {
506 /* Local param name, replace it */
507 N->T.Tok = TOK_MACPARAM;
516 /* Insert the new token in the list */
517 if (M->TokCount == 0) {
519 M->TokRoot = M->TokLast = N;
521 /* We have already tokens */
522 M->TokLast->Next = N;
527 /* Read the next token */
531 /* Skip the .endmacro for a classic macro */
532 if (Style == MAC_STYLE_CLASSIC) {
537 /* Switch out of raw token mode */
538 LeaveRawTokenMode ();
543 static int MacExpand (void* Data)
544 /* If we're currently expanding a macro, set the the scanner token and
545 * attribute to the next value and return true. If we are not expanding
546 * a macro, return false.
549 /* Cast the Data pointer to the actual data structure */
550 MacExp* Mac = (MacExp*) Data;
552 /* Check if we should abort this macro */
558 /* Abort any open .IF statements in this macro expansion */
559 CleanupIfStack (Mac->IfSP);
561 /* Terminate macro expansion */
565 /* We're expanding a macro. Check if we are expanding one of the
570 /* Ok, use token from parameter list */
571 TokSet (Mac->ParamExp, Mac->LISlot);
573 /* Set pointer to next token */
574 Mac->ParamExp = Mac->ParamExp->Next;
581 /* We're not expanding macro parameters. Check if we have tokens left from
586 /* Use next macro token */
587 TokSet (Mac->Exp, Mac->LISlot);
589 /* Set pointer to next token */
590 Mac->Exp = Mac->Exp->Next;
592 /* Is it a request for actual parameter count? */
593 if (CurTok.Tok == TOK_PARAMCOUNT) {
594 CurTok.Tok = TOK_INTCON;
595 CurTok.IVal = Mac->ParamCount;
599 /* Is it the name of a macro parameter? */
600 if (CurTok.Tok == TOK_MACPARAM) {
602 /* Start to expand the parameter token list */
603 Mac->ParamExp = Mac->Params [CurTok.IVal];
605 /* Recursive call to expand the parameter */
606 return MacExpand (Mac);
609 /* If it's an identifier, it may in fact be a local symbol */
610 if ((CurTok.Tok == TOK_IDENT || CurTok.Tok == TOK_LOCAL_IDENT) &&
611 Mac->M->LocalCount) {
612 /* Search for the local symbol in the list */
614 IdDesc* I = Mac->M->Locals;
616 if (SB_Compare (&CurTok.SVal, &I->Id) == 0) {
617 /* This is in fact a local symbol, change the name. Be sure
618 * to generate a local label name if the original name was
619 * a local label, and also generate a name that cannot be
620 * generated by a user.
622 if (SB_At (&I->Id, 0) == LocalStart) {
623 /* Must generate a local symbol */
624 SB_Printf (&CurTok.SVal, "%cLOCAL-MACRO_SYMBOL-%04X",
625 LocalStart, Mac->LocalStart + Index);
628 SB_Printf (&CurTok.SVal, "LOCAL-MACRO_SYMBOL-%04X",
629 Mac->LocalStart + Index);
642 /* The token was successfully set */
647 /* No more macro tokens. Do we have a final token? */
650 /* Set the final token and remove it */
651 TokSet (Mac->Final, Mac->LISlot);
652 FreeTokNode (Mac->Final);
655 /* The token was successfully set */
661 /* End of macro expansion */
664 /* Pop the input function */
667 /* No token available */
673 static void StartExpClassic (Macro* M)
674 /* Start expanding the classic macro M */
680 /* Create a structure holding expansion data. This must be done before
681 * skipping the macro name, because the call to NextTok may cause a new
682 * expansion if the next token is actually a .define style macro.
686 /* Skip the macro name */
689 /* Read the actual parameters */
690 while (!TokIsSep (CurTok.Tok)) {
694 /* Check for maximum parameter count */
695 if (E->ParamCount >= M->ParamCount) {
696 ErrorSkip ("Too many macro parameters");
700 /* The macro may optionally be enclosed in curly braces */
701 Term = GetTokListTerm (TOK_COMMA);
703 /* Read tokens for one parameter, accept empty params */
705 while (CurTok.Tok != Term && CurTok.Tok != TOK_SEP) {
709 /* Check for end of file */
710 if (CurTok.Tok == TOK_EOF) {
711 Error ("Unexpected end of file");
716 /* Get the next token in a node */
719 /* Insert it into the list */
721 E->Params [E->ParamCount] = T;
731 /* One parameter more */
734 /* If the macro argument was enclosed in curly braces, end-of-line
735 * is an error. Skip the closing curly brace.
737 if (Term == TOK_RCURLY) {
738 if (CurTok.Tok == TOK_SEP) {
739 Error ("End of line encountered within macro argument");
745 /* Check for a comma */
746 if (CurTok.Tok == TOK_COMMA) {
753 /* We must be at end of line now, otherwise something is wrong */
756 /* Insert a new token input function */
757 PushInput (MacExpand, E, ".MACRO");
762 static void StartExpDefine (Macro* M)
763 /* Start expanding a DEFINE style macro */
765 /* Create a structure holding expansion data */
766 MacExp* E = NewMacExp (M);
768 /* A define style macro must be called with as many actual parameters
769 * as there are formal ones. Get the parameter count.
771 unsigned Count = M->ParamCount;
773 /* Skip the current token */
776 /* Read the actual parameters */
781 /* The macro may optionally be enclosed in curly braces */
782 token_t Term = GetTokListTerm (TOK_COMMA);
784 /* Check if there is really a parameter */
785 if (TokIsSep (CurTok.Tok) || CurTok.Tok == Term) {
786 ErrorSkip ("Macro parameter #%u is empty", E->ParamCount+1);
791 /* Read tokens for one parameter */
797 /* Get the next token in a node */
800 /* Insert it into the list */
802 E->Params [E->ParamCount] = T;
811 } while (CurTok.Tok != Term && !TokIsSep (CurTok.Tok));
813 /* One parameter more */
816 /* If the macro argument was enclosed in curly braces, end-of-line
817 * is an error. Skip the closing curly brace.
819 if (Term == TOK_RCURLY) {
820 if (TokIsSep (CurTok.Tok)) {
821 Error ("End of line encountered within macro argument");
827 /* Check for a comma */
829 if (CurTok.Tok == TOK_COMMA) {
832 Error ("`,' expected");
837 /* Macro expansion will overwrite the current token. This is a problem
838 * for define style macros since these are called from the scanner level.
839 * To avoid it, remember the current token and re-insert it, once macro
842 E->Final = NewTokNode ();
844 /* Insert a new token input function */
845 PushInput (MacExpand, E, ".DEFINE");
850 void MacExpandStart (void)
851 /* Start expanding the macro in SVal */
853 /* Search for the macro */
854 Macro* M = HT_FindEntry (&MacroTab, &CurTok.SVal);
857 /* Call the apropriate subroutine */
859 case MAC_STYLE_CLASSIC: StartExpClassic (M); break;
860 case MAC_STYLE_DEFINE: StartExpDefine (M); break;
861 default: Internal ("Invalid macro style: %d", M->Style);
868 /* Abort the current macro expansion */
870 /* Must have an expansion */
871 CHECK (MacExpansions > 0);
873 /* Set a flag so macro expansion will terminate on the next call */
879 int IsMacro (const StrBuf* Name)
880 /* Return true if the given name is the name of a macro */
882 return (HT_Find (&MacroTab, Name) != 0);
887 int IsDefine (const StrBuf* Name)
888 /* Return true if the given name is the name of a define style macro */
890 Macro* M = HT_FindEntry (&MacroTab, Name);
891 return (M != 0 && M->Style == MAC_STYLE_DEFINE);
896 int InMacExpansion (void)
897 /* Return true if we're currently expanding a macro */
899 return (MacExpansions > 0);