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 /*****************************************************************************/
39 #include "../common/hashstr.h"
50 /*****************************************************************************/
52 /*****************************************************************************/
56 /* Struct that describes an identifer (macro param, local list) */
57 typedef struct IdDesc_ IdDesc;
59 IdDesc* Next; /* Linked list */
60 char Id [1]; /* Identifier, dynamically allocated */
65 /* Struct that describes a macro definition */
66 typedef struct Macro_ Macro;
68 Macro* Next; /* Next macro with same hash */
69 Macro* List; /* List of all macros */
70 unsigned LocalCount; /* Count of local symbols */
71 IdDesc* Locals; /* List of local symbols */
72 unsigned ParamCount; /* Parameter count of macro */
73 IdDesc* Params; /* Identifiers of macro parameters */
74 unsigned TokCount; /* Number of tokens for this macro */
75 TokNode* TokRoot; /* Root of token list */
76 TokNode* TokLast; /* Pointer to last token in list */
77 unsigned char Style; /* Macro style */
78 char Name [1]; /* Macro name, dynamically allocated */
81 /* Macro hash table */
82 #define HASHTAB_SIZE 117
83 static Macro* MacroTab [HASHTAB_SIZE];
85 /* Global macro data */
86 static Macro* MacroRoot = 0; /* List of all macros */
88 /* Structs that holds data for a macro expansion */
89 typedef struct MacExp_ MacExp;
91 MacExp* Next; /* Pointer to next expansion */
92 Macro* M; /* Which macro do we expand? */
93 TokNode* Exp; /* Pointer to current token */
94 TokNode* Final; /* Pointer to final token */
95 unsigned LocalStart; /* Start of counter for local symbol names */
96 unsigned ParamCount; /* Number of actual parameters */
97 TokNode** Params; /* List of actual parameters */
98 TokNode* ParamExp; /* Node for expanding parameters */
101 /* Data for macro expansions */
102 #define MAX_MACRO_EXPANSIONS 255
103 static unsigned MacroNesting = 0;
104 static MacExp* CurMac = 0;
105 static unsigned LocalName = 0;
109 /*****************************************************************************/
111 /*****************************************************************************/
115 static IdDesc* NewIdDesc (const char* Id)
116 /* Create a new IdDesc, initialize and return it */
118 /* Allocate memory */
119 unsigned Len = strlen (Id);
120 IdDesc* I = Xmalloc (sizeof (IdDesc) + Len);
122 /* Initialize the struct */
124 memcpy (I->Id, Id, Len);
127 /* Return the new struct */
133 static Macro* NewMacro (const char* Name, unsigned HashVal, unsigned char Style)
134 /* Generate a new macro entry, initialize and return it */
136 /* Allocate memory */
137 unsigned Len = strlen (Name);
138 Macro* M = Xmalloc (sizeof (Macro) + Len);
140 /* Initialize the macro struct */
148 memcpy (M->Name, Name, Len);
149 M->Name [Len] = '\0';
151 /* Insert the macro into the global macro list */
155 /* Insert the macro into the hash table */
156 M->Next = MacroTab [HashVal];
157 MacroTab [HashVal] = M;
159 /* Return the new macro struct */
165 static MacExp* NewMacExp (Macro* M)
166 /* Create a new expansion structure for the given macro */
170 /* Allocate memory */
171 MacExp* E = Xmalloc (sizeof (MacExp));
173 /* Initialize the data */
177 E->LocalStart = LocalName;
178 LocalName += M->LocalCount;
180 E->Params = Xmalloc (M->ParamCount * sizeof (TokNode*));
182 for (I = 0; I < M->ParamCount; ++I) {
186 /* And return it... */
192 static void MacInsertExp (MacExp* E)
193 /* Insert a macro expansion into the list */
202 static void FreeMacExp (void)
203 /* Remove and free the current macro expansion */
208 /* Free the parameter list */
209 for (I = 0; I < CurMac->ParamCount; ++I) {
210 Xfree (CurMac->Params [I]);
212 Xfree (CurMac->Params);
214 /* Free the final token if we have one */
216 FreeTokNode (CurMac->Final);
219 /* Reset the list pointer */
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);
298 /* If we have a DEFINE style macro, we may have parameters in braces,
299 * otherwise we may have parameters without braces.
301 if (Style == MAC_STYLE_CLASSIC) {
304 if (Tok == TOK_LPAREN) {
312 /* Parse the parameter list */
315 while (Tok == TOK_IDENT) {
317 /* Create a struct holding the identifier */
318 IdDesc* I = NewIdDesc (SVal);
320 /* Insert the struct into the list, checking for duplicate idents */
321 if (M->ParamCount == 0) {
324 IdDesc* List = M->Params;
326 if (strcmp (List->Id, SVal) == 0) {
327 Error (ERR_SYM_ALREADY_DEFINED, SVal);
329 if (List->Next == 0) {
342 /* Maybe there are more params... */
343 if (Tok == TOK_COMMA) {
351 /* For class macros, we expect a separator token, for define style macros,
352 * we expect the closing paren.
354 if (Style == MAC_STYLE_CLASSIC) {
356 } else if (HaveParams) {
360 /* Preparse the macro body. We will read the tokens until we reach end of
361 * file, or a .endmacro (or end of line for DEFINE style macros) and store
362 * them into an token list internal to the macro. For classic macros, there
363 * the .LOCAL command is detected and removed at this time.
367 /* Check for end of macro */
368 if (Style == MAC_STYLE_CLASSIC) {
369 /* In classic macros, only .endmacro is allowed */
370 if (Tok == TOK_ENDMACRO) {
374 /* May not have end of file in a macro definition */
375 if (Tok == TOK_EOF) {
376 Error (ERR_ENDMACRO_EXPECTED);
380 /* Accept a newline or end of file for new style macros */
381 if (Tok == TOK_SEP || Tok == TOK_EOF) {
386 /* Check for a .LOCAL declaration */
387 if (Tok == TOK_LOCAL && Style == MAC_STYLE_CLASSIC) {
393 /* Skip .local or comma */
396 /* Need an identifer */
397 if (Tok != TOK_IDENT) {
398 Error (ERR_IDENT_EXPECTED);
403 /* Put the identifier into the locals list and skip it */
404 I = NewIdDesc (SVal);
410 /* Check for end of list */
411 if (Tok != TOK_COMMA) {
417 /* We need end of line after the locals */
422 /* Create a token node for the current token */
425 /* If the token is an ident, check if it is a local parameter */
426 if (Tok == TOK_IDENT) {
428 IdDesc* I = M->Params;
430 if (strcmp (I->Id, SVal) == 0) {
431 /* Local param name, replace it */
432 T->Tok = TOK_MACPARAM;
441 /* Insert the new token in the list */
442 if (M->TokCount == 0) {
444 M->TokRoot = M->TokLast = T;
446 /* We have already tokens */
447 M->TokLast->Next = T;
452 /* Read the next token */
456 /* Skip the .endmacro for a classic macro */
457 if (Style == MAC_STYLE_CLASSIC) {
464 static void StartExpClassic (Macro* M)
465 /* Start expanding the classic macro M */
469 /* Skip the macro name */
472 /* Create a structure holding expansion data */
475 /* Read the actual parameters */
476 while (Tok != TOK_SEP && Tok != TOK_EOF) {
480 /* Check for maximum parameter count */
481 if (E->ParamCount >= M->ParamCount) {
482 Error (ERR_TOO_MANY_PARAMS);
487 /* Read tokens for one parameter, accept empty params */
489 while (Tok != TOK_COMMA && Tok != TOK_SEP) {
493 /* Check for end of file */
494 if (Tok == TOK_EOF) {
499 /* Get the next token in a node */
502 /* Insert it into the list */
504 E->Params [E->ParamCount] = T;
514 /* One parameter more */
517 /* Check for a comma */
518 if (Tok == TOK_COMMA) {
525 /* Insert the newly created structure into the expansion list */
531 static void StartExpDefine (Macro* M)
532 /* Start expanding a DEFINE style macro */
534 /* Create a structure holding expansion data */
535 MacExp* E = NewMacExp (M);
537 /* A define style macro must be called with as many actual parameters
538 * as there are formal ones. Get the parameter count.
540 unsigned Count = M->ParamCount;
542 /* Skip the current token */
545 /* Read the actual parameters */
550 /* Check if there is really a parameter */
551 if (Tok == TOK_SEP || Tok == TOK_EOF || Tok == TOK_COMMA) {
552 Error (ERR_MACRO_PARAM_EXPECTED);
557 /* Read tokens for one parameter */
563 /* Get the next token in a node */
566 /* Insert it into the list */
568 E->Params [E->ParamCount] = T;
577 } while (Tok != TOK_COMMA && Tok != TOK_SEP && Tok != TOK_EOF);
579 /* One parameter more */
582 /* Check for a comma */
584 if (Tok == TOK_COMMA) {
587 Error (ERR_COMMA_EXPECTED);
592 /* Macro expansion will overwrite the current token. This is a problem
593 * for define style macros since these are called from the scanner level.
594 * To avoid it, remember the current token and re-insert it if macro
597 E->Final = NewTokNode ();
599 /* Insert the newly created structure into the expansion list */
605 void MacExpandStart (void)
606 /* Start expanding the macro in SVal */
610 /* Beware of runoff macros */
611 if (MacroNesting == MAX_MACRO_EXPANSIONS) {
612 Fatal (FAT_MACRO_NESTING);
615 /* Search for the macro */
616 M = MacFind (SVal, HashStr (SVal) % HASHTAB_SIZE);
619 /* Call the apropriate subroutine */
621 case MAC_STYLE_CLASSIC: StartExpClassic (M); break;
622 case MAC_STYLE_DEFINE: StartExpDefine (M); break;
623 default: Internal ("Invalid macro style: %d", M->Style);
630 /* If we're currently expanding a macro, set the the scanner token and
631 * attribute to the next value and return true. If we are not expanding
632 * a macro, return false.
635 if (MacroNesting == 0) {
636 /* Not expanding a macro */
640 /* We're expanding a macro. Check if we are expanding one of the
643 if (CurMac->ParamExp) {
645 /* Ok, use token from parameter list */
646 TokSet (CurMac->ParamExp);
648 /* Set pointer to next token */
649 CurMac->ParamExp = CurMac->ParamExp->Next;
654 } else if (CurMac->Exp) {
656 /* We're not expanding a parameter, use next macro token */
657 TokSet (CurMac->Exp);
659 /* Set pointer to next token */
660 CurMac->Exp = CurMac->Exp->Next;
662 /* Is it a request for actual parameter count? */
663 if (Tok == TOK_PARAMCOUNT) {
665 IVal = CurMac->ParamCount;
669 /* Is it an .exitmacro command? */
670 if (Tok == TOK_EXITMACRO) {
671 /* Forced exit from macro expansion */
676 /* Is it the name of a macro parameter? */
677 if (Tok == TOK_MACPARAM) {
679 /* Start to expand the parameter token list */
680 CurMac->ParamExp = CurMac->Params [IVal];
682 /* Recursive call to expand the parameter */
686 /* If it's an identifier, it may in fact be a local symbol */
687 if (Tok == TOK_IDENT && CurMac->M->LocalCount) {
688 /* Search for the local symbol in the list */
690 IdDesc* I = CurMac->M->Locals;
692 if (strcmp (SVal, I->Id) == 0) {
693 /* This is in fact a local symbol, change the name */
694 sprintf (SVal, "___%04X__", CurMac->LocalStart + Index);
706 /* The token was successfully set */
709 } else if (CurMac->Final) {
711 /* Set the final token and remove it */
712 TokSet (CurMac->Final);
713 FreeTokNode (CurMac->Final);
716 /* The token was successfully set */
721 /* End of macro expansion */
731 /* Abort the current macro expansion */
733 /* Must have an expansion */
736 /* Free current structure */
742 int IsMacro (const char* Name)
743 /* Return true if the given name is the name of a macro */
745 return MacFind (SVal, HashStr (SVal) % HASHTAB_SIZE) != 0;
750 int IsDefine (const char* Name)
751 /* Return true if the given name is the name of a define style macro */
753 Macro* M = MacFind (SVal, HashStr (SVal) % HASHTAB_SIZE);
754 return (M != 0 && M->Style == MAC_STYLE_DEFINE);
759 int InMacExpansion (void)
760 /* Return true if we're currently expanding a macro */
762 return MacroNesting != 0;