1 /*****************************************************************************/
5 /* Macros for the ca65 macroassembler */
9 /* (C) 1998-2000 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 /*****************************************************************************/
55 /*****************************************************************************/
57 /*****************************************************************************/
61 /* Struct that describes an identifer (macro param, local list) */
62 typedef struct IdDesc_ IdDesc;
64 IdDesc* Next; /* Linked list */
65 char Id [1]; /* Identifier, dynamically allocated */
70 /* Struct that describes a macro definition */
71 typedef struct Macro_ Macro;
73 Macro* Next; /* Next macro with same hash */
74 Macro* List; /* List of all macros */
75 unsigned LocalCount; /* Count of local symbols */
76 IdDesc* Locals; /* List of local symbols */
77 unsigned ParamCount; /* Parameter count of macro */
78 IdDesc* Params; /* Identifiers of macro parameters */
79 unsigned TokCount; /* Number of tokens for this macro */
80 TokNode* TokRoot; /* Root of token list */
81 TokNode* TokLast; /* Pointer to last token in list */
82 unsigned char Style; /* Macro style */
83 char Name [1]; /* Macro name, dynamically allocated */
86 /* Macro hash table */
87 #define HASHTAB_SIZE 117
88 static Macro* MacroTab [HASHTAB_SIZE];
90 /* Global macro data */
91 static Macro* MacroRoot = 0; /* List of all macros */
93 /* Structs that holds data for a macro expansion */
94 typedef struct MacExp_ MacExp;
96 MacExp* Next; /* Pointer to next expansion */
97 Macro* M; /* Which macro do we expand? */
98 unsigned IfSP; /* .IF stack pointer at start of expansion */
99 TokNode* Exp; /* Pointer to current token */
100 TokNode* Final; /* Pointer to final token */
101 unsigned LocalStart; /* Start of counter for local symbol names */
102 unsigned ParamCount; /* Number of actual parameters */
103 TokNode** Params; /* List of actual parameters */
104 TokNode* ParamExp; /* Node for expanding parameters */
107 /* Number of active macro expansions */
108 static unsigned MacExpansions = 0;
110 /* Flag if a macro expansion should get aborted */
111 static int DoMacAbort = 0;
113 /* Counter to create local names for symbols */
114 static unsigned LocalName = 0;
118 /*****************************************************************************/
120 /*****************************************************************************/
124 static IdDesc* NewIdDesc (const char* Id)
125 /* Create a new IdDesc, initialize and return it */
127 /* Allocate memory */
128 unsigned Len = strlen (Id);
129 IdDesc* I = xmalloc (sizeof (IdDesc) + Len);
131 /* Initialize the struct */
133 memcpy (I->Id, Id, Len);
136 /* Return the new struct */
142 static Macro* NewMacro (const char* Name, unsigned HashVal, unsigned char Style)
143 /* Generate a new macro entry, initialize and return it */
145 /* Allocate memory */
146 unsigned Len = strlen (Name);
147 Macro* M = xmalloc (sizeof (Macro) + Len);
149 /* Initialize the macro struct */
157 memcpy (M->Name, Name, Len);
158 M->Name [Len] = '\0';
160 /* Insert the macro into the global macro list */
164 /* Insert the macro into the hash table */
165 M->Next = MacroTab [HashVal];
166 MacroTab [HashVal] = M;
168 /* Return the new macro struct */
174 static MacExp* NewMacExp (Macro* M)
175 /* Create a new expansion structure for the given macro */
179 /* Allocate memory */
180 MacExp* E = xmalloc (sizeof (MacExp));
182 /* Initialize the data */
184 E->IfSP = GetIfStack ();
187 E->LocalStart = LocalName;
188 LocalName += M->LocalCount;
190 E->Params = xmalloc (M->ParamCount * sizeof (TokNode*));
192 for (I = 0; I < M->ParamCount; ++I) {
196 /* One macro expansion more */
199 /* Return the new macro expansion */
205 static void FreeMacExp (MacExp* E)
206 /* Remove and free the current macro expansion */
210 /* One macro expansion less */
213 /* Free the parameter list */
214 for (I = 0; I < E->ParamCount; ++I) {
215 xfree (E->Params [I]);
219 /* Free the final token if we have one */
221 FreeTokNode (E->Final);
224 /* Free the structure itself */
230 static void MacSkipDef (unsigned Style)
231 /* Skip a macro definition */
233 if (Style == MAC_STYLE_CLASSIC) {
234 /* Skip tokens until we reach the final .endmacro */
235 while (Tok != TOK_ENDMACRO && Tok != TOK_EOF) {
238 if (Tok != TOK_EOF) {
241 Error (ERR_ENDMACRO_EXPECTED);
244 /* Skip until end of line */
251 static Macro* MacFind (const char* Name, unsigned HashVal)
252 /* Search for a macro in the hash table */
254 /* Search for the identifier */
255 Macro* M = MacroTab [HashVal];
257 if (strcmp (Name, M->Name) == 0) {
267 void MacDef (unsigned Style)
268 /* Parse a macro definition */
275 /* We expect a macro name here */
276 if (Tok != TOK_IDENT) {
277 Error (ERR_IDENT_EXPECTED);
282 /* Generate the hash value */
283 HashVal = HashStr (SVal) % HASHTAB_SIZE;
285 /* Did we already define that macro? */
286 if (MacFind (SVal, HashVal) != 0) {
287 /* Macro is already defined */
288 Error (ERR_SYM_ALREADY_DEFINED, SVal);
289 /* Skip tokens until we reach the final .endmacro */
294 /* Define the macro */
295 M = NewMacro (SVal, HashVal, Style);
297 /* Switch to raw token mode and skip the macro name */
298 EnterRawTokenMode ();
301 /* If we have a DEFINE style macro, we may have parameters in braces,
302 * otherwise we may have parameters without braces.
304 if (Style == MAC_STYLE_CLASSIC) {
307 if (Tok == TOK_LPAREN) {
315 /* Parse the parameter list */
318 while (Tok == TOK_IDENT) {
320 /* Create a struct holding the identifier */
321 IdDesc* I = NewIdDesc (SVal);
323 /* Insert the struct into the list, checking for duplicate idents */
324 if (M->ParamCount == 0) {
327 IdDesc* List = M->Params;
329 if (strcmp (List->Id, SVal) == 0) {
330 Error (ERR_SYM_ALREADY_DEFINED, SVal);
332 if (List->Next == 0) {
345 /* Maybe there are more params... */
346 if (Tok == TOK_COMMA) {
354 /* For class macros, we expect a separator token, for define style macros,
355 * we expect the closing paren.
357 if (Style == MAC_STYLE_CLASSIC) {
359 } else if (HaveParams) {
363 /* Preparse the macro body. We will read the tokens until we reach end of
364 * file, or a .endmacro (or end of line for DEFINE style macros) and store
365 * them into an token list internal to the macro. For classic macros, there
366 * the .LOCAL command is detected and removed at this time.
370 /* Check for end of macro */
371 if (Style == MAC_STYLE_CLASSIC) {
372 /* In classic macros, only .endmacro is allowed */
373 if (Tok == TOK_ENDMACRO) {
377 /* May not have end of file in a macro definition */
378 if (Tok == TOK_EOF) {
379 Error (ERR_ENDMACRO_EXPECTED);
383 /* Accept a newline or end of file for new style macros */
384 if (Tok == TOK_SEP || Tok == TOK_EOF) {
389 /* Check for a .LOCAL declaration */
390 if (Tok == TOK_LOCAL && Style == MAC_STYLE_CLASSIC) {
396 /* Skip .local or comma */
399 /* Need an identifer */
400 if (Tok != TOK_IDENT) {
401 Error (ERR_IDENT_EXPECTED);
406 /* Put the identifier into the locals list and skip it */
407 I = NewIdDesc (SVal);
413 /* Check for end of list */
414 if (Tok != TOK_COMMA) {
420 /* We need end of line after the locals */
425 /* Create a token node for the current token */
428 /* If the token is an ident, check if it is a local parameter */
429 if (Tok == TOK_IDENT) {
431 IdDesc* I = M->Params;
433 if (strcmp (I->Id, SVal) == 0) {
434 /* Local param name, replace it */
435 T->Tok = TOK_MACPARAM;
444 /* Insert the new token in the list */
445 if (M->TokCount == 0) {
447 M->TokRoot = M->TokLast = T;
449 /* We have already tokens */
450 M->TokLast->Next = T;
455 /* Read the next token */
459 /* Skip the .endmacro for a classic macro */
460 if (Style == MAC_STYLE_CLASSIC) {
465 /* Switch out of raw token mode */
466 LeaveRawTokenMode ();
471 static int MacExpand (void* Data)
472 /* If we're currently expanding a macro, set the the scanner token and
473 * attribute to the next value and return true. If we are not expanding
474 * a macro, return false.
477 /* Cast the Data pointer to the actual data structure */
478 MacExp* Mac = (MacExp*) Data;
480 /* Check if we should abort this macro */
486 /* Abort any open .IF statements in this macro expansion */
487 CleanupIfStack (Mac->IfSP);
489 /* Terminate macro expansion */
493 /* We're expanding a macro. Check if we are expanding one of the
498 /* Ok, use token from parameter list */
499 TokSet (Mac->ParamExp);
501 /* Set pointer to next token */
502 Mac->ParamExp = Mac->ParamExp->Next;
509 /* We're not expanding macro parameters. Check if we have tokens left from
514 /* Use next macro token */
517 /* Set pointer to next token */
518 Mac->Exp = Mac->Exp->Next;
520 /* Is it a request for actual parameter count? */
521 if (Tok == TOK_PARAMCOUNT) {
523 IVal = Mac->ParamCount;
527 /* Is it the name of a macro parameter? */
528 if (Tok == TOK_MACPARAM) {
530 /* Start to expand the parameter token list */
531 Mac->ParamExp = Mac->Params [IVal];
533 /* Recursive call to expand the parameter */
534 return MacExpand (Mac);
537 /* If it's an identifier, it may in fact be a local symbol */
538 if (Tok == TOK_IDENT && Mac->M->LocalCount) {
539 /* Search for the local symbol in the list */
541 IdDesc* I = Mac->M->Locals;
543 if (strcmp (SVal, I->Id) == 0) {
544 /* This is in fact a local symbol, change the name */
545 sprintf (SVal, "___%04X__", Mac->LocalStart + Index);
557 /* The token was successfully set */
562 /* No more macro tokens. Do we have a final token? */
565 /* Set the final token and remove it */
567 FreeTokNode (Mac->Final);
570 /* The token was successfully set */
576 /* End of macro expansion */
579 /* Pop the input function */
582 /* No token available */
588 static void StartExpClassic (Macro* M)
589 /* Start expanding the classic macro M */
593 /* Skip the macro name */
596 /* Create a structure holding expansion data */
599 /* Read the actual parameters */
600 while (Tok != TOK_SEP && Tok != TOK_EOF) {
604 /* Check for maximum parameter count */
605 if (E->ParamCount >= M->ParamCount) {
606 Error (ERR_TOO_MANY_PARAMS);
611 /* Read tokens for one parameter, accept empty params */
613 while (Tok != TOK_COMMA && Tok != TOK_SEP) {
617 /* Check for end of file */
618 if (Tok == TOK_EOF) {
623 /* Get the next token in a node */
626 /* Insert it into the list */
628 E->Params [E->ParamCount] = T;
638 /* One parameter more */
641 /* Check for a comma */
642 if (Tok == TOK_COMMA) {
649 /* Insert a new token input function */
650 PushInput (MacExpand, E, ".MACRO");
655 static void StartExpDefine (Macro* M)
656 /* Start expanding a DEFINE style macro */
658 /* Create a structure holding expansion data */
659 MacExp* E = NewMacExp (M);
661 /* A define style macro must be called with as many actual parameters
662 * as there are formal ones. Get the parameter count.
664 unsigned Count = M->ParamCount;
666 /* Skip the current token */
669 /* Read the actual parameters */
674 /* Check if there is really a parameter */
675 if (Tok == TOK_SEP || Tok == TOK_EOF || Tok == TOK_COMMA) {
676 Error (ERR_MACRO_PARAM_EXPECTED);
681 /* Read tokens for one parameter */
687 /* Get the next token in a node */
690 /* Insert it into the list */
692 E->Params [E->ParamCount] = T;
701 } while (Tok != TOK_COMMA && Tok != TOK_SEP && Tok != TOK_EOF);
703 /* One parameter more */
706 /* Check for a comma */
708 if (Tok == TOK_COMMA) {
711 Error (ERR_COMMA_EXPECTED);
716 /* Macro expansion will overwrite the current token. This is a problem
717 * for define style macros since these are called from the scanner level.
718 * To avoid it, remember the current token and re-insert it if macro
721 E->Final = NewTokNode ();
723 /* Insert a new token input function */
724 PushInput (MacExpand, E, ".DEFINE");
729 void MacExpandStart (void)
730 /* Start expanding the macro in SVal */
732 /* Search for the macro */
733 Macro* M = MacFind (SVal, HashStr (SVal) % HASHTAB_SIZE);
736 /* Call the apropriate subroutine */
738 case MAC_STYLE_CLASSIC: StartExpClassic (M); break;
739 case MAC_STYLE_DEFINE: StartExpDefine (M); break;
740 default: Internal ("Invalid macro style: %d", M->Style);
747 /* Abort the current macro expansion */
749 /* Must have an expansion */
750 CHECK (MacExpansions > 0);
752 /* Set a flag so macro expansion will terminate on the next call */
758 int IsMacro (const char* Name)
759 /* Return true if the given name is the name of a macro */
761 return MacFind (SVal, HashStr (SVal) % HASHTAB_SIZE) != 0;
766 int IsDefine (const char* Name)
767 /* Return true if the given name is the name of a define style macro */
769 Macro* M = MacFind (SVal, HashStr (SVal) % HASHTAB_SIZE);
770 return (M != 0 && M->Style == MAC_STYLE_DEFINE);
775 int InMacExpansion (void)
776 /* Return true if we're currently expanding a macro */
778 return (MacExpansions > 0);