1 /*****************************************************************************/
5 /* Macros for the ca65 macroassembler */
9 /* (C) 1998-2003 Ullrich von Bassewitz */
11 /* D-70597 Stuttgart */
12 /* EMail: uz@musoftware.de */
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 /*****************************************************************************/
56 /*****************************************************************************/
58 /*****************************************************************************/
62 /* Struct that describes an identifer (macro param, local list) */
63 typedef struct IdDesc_ IdDesc;
65 IdDesc* Next; /* Linked list */
66 char Id [1]; /* Identifier, dynamically allocated */
71 /* Struct that describes a macro definition */
72 typedef struct Macro_ Macro;
74 Macro* Next; /* Next macro with same hash */
75 Macro* List; /* List of all macros */
76 unsigned LocalCount; /* Count of local symbols */
77 IdDesc* Locals; /* List of local symbols */
78 unsigned ParamCount; /* Parameter count of macro */
79 IdDesc* Params; /* Identifiers of macro parameters */
80 unsigned TokCount; /* Number of tokens for this macro */
81 TokNode* TokRoot; /* Root of token list */
82 TokNode* TokLast; /* Pointer to last token in list */
83 unsigned char Style; /* Macro style */
84 char Name [1]; /* Macro name, dynamically allocated */
87 /* Macro hash table */
88 #define HASHTAB_SIZE 117
89 static Macro* MacroTab [HASHTAB_SIZE];
91 /* Global macro data */
92 static Macro* MacroRoot = 0; /* List of all macros */
94 /* Structs that holds data for a macro expansion */
95 typedef struct MacExp_ MacExp;
97 MacExp* Next; /* Pointer to next expansion */
98 Macro* M; /* Which macro do we expand? */
99 unsigned IfSP; /* .IF stack pointer at start of expansion */
100 TokNode* Exp; /* Pointer to current token */
101 TokNode* Final; /* Pointer to final token */
102 unsigned LocalStart; /* Start of counter for local symbol names */
103 unsigned ParamCount; /* Number of actual parameters */
104 TokNode** Params; /* List of actual parameters */
105 TokNode* ParamExp; /* Node for expanding parameters */
108 /* Number of active macro expansions */
109 static unsigned MacExpansions = 0;
111 /* Flag if a macro expansion should get aborted */
112 static int DoMacAbort = 0;
114 /* Counter to create local names for symbols */
115 static unsigned LocalName = 0;
119 /*****************************************************************************/
121 /*****************************************************************************/
125 static IdDesc* NewIdDesc (const char* Id)
126 /* Create a new IdDesc, initialize and return it */
128 /* Allocate memory */
129 unsigned Len = strlen (Id);
130 IdDesc* I = xmalloc (sizeof (IdDesc) + Len);
132 /* Initialize the struct */
134 memcpy (I->Id, Id, Len);
137 /* Return the new struct */
143 static Macro* NewMacro (const char* Name, unsigned HashVal, unsigned char Style)
144 /* Generate a new macro entry, initialize and return it */
146 /* Allocate memory */
147 unsigned Len = strlen (Name);
148 Macro* M = xmalloc (sizeof (Macro) + Len);
150 /* Initialize the macro struct */
159 memcpy (M->Name, Name, Len);
160 M->Name [Len] = '\0';
162 /* Insert the macro into the global macro list */
166 /* Insert the macro into the hash table */
167 M->Next = MacroTab [HashVal];
168 MacroTab [HashVal] = M;
170 /* Return the new macro struct */
176 static MacExp* NewMacExp (Macro* M)
177 /* Create a new expansion structure for the given macro */
181 /* Allocate memory */
182 MacExp* E = xmalloc (sizeof (MacExp));
184 /* Initialize the data */
186 E->IfSP = GetIfStack ();
189 E->LocalStart = LocalName;
190 LocalName += M->LocalCount;
192 E->Params = xmalloc (M->ParamCount * sizeof (TokNode*));
194 for (I = 0; I < M->ParamCount; ++I) {
198 /* One macro expansion more */
201 /* Return the new macro expansion */
207 static void FreeMacExp (MacExp* E)
208 /* Remove and free the current macro expansion */
212 /* One macro expansion less */
215 /* Free the parameter list */
216 for (I = 0; I < E->ParamCount; ++I) {
217 xfree (E->Params [I]);
221 /* Free the final token if we have one */
223 FreeTokNode (E->Final);
226 /* Free the structure itself */
232 static void MacSkipDef (unsigned Style)
233 /* Skip a macro definition */
235 if (Style == MAC_STYLE_CLASSIC) {
236 /* Skip tokens until we reach the final .endmacro */
237 while (Tok != TOK_ENDMACRO && Tok != TOK_EOF) {
240 if (Tok != TOK_EOF) {
243 Error (ERR_ENDMACRO_EXPECTED);
246 /* Skip until end of line */
253 static Macro* MacFind (const char* Name, unsigned HashVal)
254 /* Search for a macro in the hash table */
256 /* Search for the identifier */
257 Macro* M = MacroTab [HashVal];
259 if (strcmp (Name, M->Name) == 0) {
269 void MacDef (unsigned Style)
270 /* Parse a macro definition */
277 /* We expect a macro name here */
278 if (Tok != TOK_IDENT) {
279 Error (ERR_IDENT_EXPECTED);
284 /* Generate the hash value */
285 HashVal = HashStr (SVal) % HASHTAB_SIZE;
287 /* Did we already define that macro? */
288 if (MacFind (SVal, HashVal) != 0) {
289 /* Macro is already defined */
290 Error (ERR_SYM_ALREADY_DEFINED, SVal);
291 /* Skip tokens until we reach the final .endmacro */
296 /* Define the macro */
297 M = NewMacro (SVal, HashVal, Style);
299 /* Switch to raw token mode and skip the macro name */
300 EnterRawTokenMode ();
303 /* If we have a DEFINE style macro, we may have parameters in braces,
304 * otherwise we may have parameters without braces.
306 if (Style == MAC_STYLE_CLASSIC) {
309 if (Tok == TOK_LPAREN) {
317 /* Parse the parameter list */
320 while (Tok == TOK_IDENT) {
322 /* Create a struct holding the identifier */
323 IdDesc* I = NewIdDesc (SVal);
325 /* Insert the struct into the list, checking for duplicate idents */
326 if (M->ParamCount == 0) {
329 IdDesc* List = M->Params;
331 if (strcmp (List->Id, SVal) == 0) {
332 Error (ERR_SYM_ALREADY_DEFINED, SVal);
334 if (List->Next == 0) {
347 /* Maybe there are more params... */
348 if (Tok == TOK_COMMA) {
356 /* For class macros, we expect a separator token, for define style macros,
357 * we expect the closing paren.
359 if (Style == MAC_STYLE_CLASSIC) {
361 } else if (HaveParams) {
365 /* Preparse the macro body. We will read the tokens until we reach end of
366 * file, or a .endmacro (or end of line for DEFINE style macros) and store
367 * them into an token list internal to the macro. For classic macros, there
368 * the .LOCAL command is detected and removed at this time.
372 /* Check for end of macro */
373 if (Style == MAC_STYLE_CLASSIC) {
374 /* In classic macros, only .endmacro is allowed */
375 if (Tok == TOK_ENDMACRO) {
379 /* May not have end of file in a macro definition */
380 if (Tok == TOK_EOF) {
381 Error (ERR_ENDMACRO_EXPECTED);
385 /* Accept a newline or end of file for new style macros */
386 if (TokIsSep (Tok)) {
391 /* Check for a .LOCAL declaration */
392 if (Tok == TOK_LOCAL && Style == MAC_STYLE_CLASSIC) {
398 /* Skip .local or comma */
401 /* Need an identifer */
402 if (Tok != TOK_IDENT) {
403 Error (ERR_IDENT_EXPECTED);
408 /* Put the identifier into the locals list and skip it */
409 I = NewIdDesc (SVal);
415 /* Check for end of list */
416 if (Tok != TOK_COMMA) {
422 /* We need end of line after the locals */
427 /* Create a token node for the current token */
430 /* If the token is an ident, check if it is a local parameter */
431 if (Tok == TOK_IDENT) {
433 IdDesc* I = M->Params;
435 if (strcmp (I->Id, SVal) == 0) {
436 /* Local param name, replace it */
437 T->Tok = TOK_MACPARAM;
446 /* Insert the new token in the list */
447 if (M->TokCount == 0) {
449 M->TokRoot = M->TokLast = T;
451 /* We have already tokens */
452 M->TokLast->Next = T;
457 /* Read the next token */
461 /* Skip the .endmacro for a classic macro */
462 if (Style == MAC_STYLE_CLASSIC) {
467 /* Switch out of raw token mode */
468 LeaveRawTokenMode ();
473 static int MacExpand (void* Data)
474 /* If we're currently expanding a macro, set the the scanner token and
475 * attribute to the next value and return true. If we are not expanding
476 * a macro, return false.
479 /* Cast the Data pointer to the actual data structure */
480 MacExp* Mac = (MacExp*) Data;
482 /* Check if we should abort this macro */
488 /* Abort any open .IF statements in this macro expansion */
489 CleanupIfStack (Mac->IfSP);
491 /* Terminate macro expansion */
495 /* We're expanding a macro. Check if we are expanding one of the
500 /* Ok, use token from parameter list */
501 TokSet (Mac->ParamExp);
503 /* Set pointer to next token */
504 Mac->ParamExp = Mac->ParamExp->Next;
511 /* We're not expanding macro parameters. Check if we have tokens left from
516 /* Use next macro token */
519 /* Set pointer to next token */
520 Mac->Exp = Mac->Exp->Next;
522 /* Is it a request for actual parameter count? */
523 if (Tok == TOK_PARAMCOUNT) {
525 IVal = Mac->ParamCount;
529 /* Is it the name of a macro parameter? */
530 if (Tok == TOK_MACPARAM) {
532 /* Start to expand the parameter token list */
533 Mac->ParamExp = Mac->Params [IVal];
535 /* Recursive call to expand the parameter */
536 return MacExpand (Mac);
539 /* If it's an identifier, it may in fact be a local symbol */
540 if (Tok == TOK_IDENT && Mac->M->LocalCount) {
541 /* Search for the local symbol in the list */
543 IdDesc* I = Mac->M->Locals;
545 if (strcmp (SVal, I->Id) == 0) {
546 /* This is in fact a local symbol, change the name. Be sure
547 * to generate a local label name if the original name was
548 * a local label, and also generate a name that cannot be
549 * generated by a user.
551 unsigned PrefixLen = (I->Id[0] == LocalStart);
552 sprintf (SVal, "%.*sLOCAL-MACRO-SYMBOL-%04X", PrefixLen,
553 I->Id, Mac->LocalStart + Index);
565 /* The token was successfully set */
570 /* No more macro tokens. Do we have a final token? */
573 /* Set the final token and remove it */
575 FreeTokNode (Mac->Final);
578 /* The token was successfully set */
584 /* End of macro expansion */
587 /* Pop the input function */
590 /* No token available */
596 static void StartExpClassic (Macro* M)
597 /* Start expanding the classic macro M */
601 /* Skip the macro name */
604 /* Create a structure holding expansion data */
607 /* Read the actual parameters */
608 while (!TokIsSep (Tok)) {
612 /* Check for maximum parameter count */
613 if (E->ParamCount >= M->ParamCount) {
614 Error (ERR_TOO_MANY_PARAMS);
619 /* Read tokens for one parameter, accept empty params */
621 while (Tok != TOK_COMMA && Tok != TOK_SEP) {
625 /* Check for end of file */
626 if (Tok == TOK_EOF) {
627 Error (ERR_UNEXPECTED_EOF);
631 /* Get the next token in a node */
634 /* Insert it into the list */
636 E->Params [E->ParamCount] = T;
646 /* One parameter more */
649 /* Check for a comma */
650 if (Tok == TOK_COMMA) {
657 /* Insert a new token input function */
658 PushInput (MacExpand, E, ".MACRO");
663 static void StartExpDefine (Macro* M)
664 /* Start expanding a DEFINE style macro */
666 /* Create a structure holding expansion data */
667 MacExp* E = NewMacExp (M);
669 /* A define style macro must be called with as many actual parameters
670 * as there are formal ones. Get the parameter count.
672 unsigned Count = M->ParamCount;
674 /* Skip the current token */
677 /* Read the actual parameters */
682 /* Check if there is really a parameter */
683 if (TokIsSep (Tok) || Tok == TOK_COMMA) {
684 Error (ERR_MACRO_PARAM_EXPECTED);
689 /* Read tokens for one parameter */
695 /* Get the next token in a node */
698 /* Insert it into the list */
700 E->Params [E->ParamCount] = T;
709 } while (Tok != TOK_COMMA && !TokIsSep (Tok));
711 /* One parameter more */
714 /* Check for a comma */
716 if (Tok == TOK_COMMA) {
719 Error (ERR_COMMA_EXPECTED);
724 /* Macro expansion will overwrite the current token. This is a problem
725 * for define style macros since these are called from the scanner level.
726 * To avoid it, remember the current token and re-insert it if macro
729 E->Final = NewTokNode ();
731 /* Insert a new token input function */
732 PushInput (MacExpand, E, ".DEFINE");
737 void MacExpandStart (void)
738 /* Start expanding the macro in SVal */
740 /* Search for the macro */
741 Macro* M = MacFind (SVal, HashStr (SVal) % HASHTAB_SIZE);
744 /* Call the apropriate subroutine */
746 case MAC_STYLE_CLASSIC: StartExpClassic (M); break;
747 case MAC_STYLE_DEFINE: StartExpDefine (M); break;
748 default: Internal ("Invalid macro style: %d", M->Style);
755 /* Abort the current macro expansion */
757 /* Must have an expansion */
758 CHECK (MacExpansions > 0);
760 /* Set a flag so macro expansion will terminate on the next call */
766 int IsMacro (const char* Name)
767 /* Return true if the given name is the name of a macro */
769 return MacFind (Name, HashStr (Name) % HASHTAB_SIZE) != 0;
774 int IsDefine (const char* Name)
775 /* Return true if the given name is the name of a define style macro */
777 Macro* M = MacFind (Name, HashStr (Name) % HASHTAB_SIZE);
778 return (M != 0 && M->Style == MAC_STYLE_DEFINE);
783 int InMacExpansion (void)
784 /* Return true if we're currently expanding a macro */
786 return (MacExpansions > 0);