summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Kanios <keith@kanios.net>2009-07-12 00:19:55 -0500
committerKeith Kanios <keith@kanios.net>2009-07-12 00:19:55 -0500
commit852f1eeed56c7ff2c53df0e09f57fe3cd6a395b5 (patch)
tree023bc8e3a05e7eb3c4c049ffa1d60a01da24a289
parent093513d0bc2658d5387150ca15d21461de3adbc0 (diff)
downloadnasm-852f1eeed56c7ff2c53df0e09f57fe3cd6a395b5.tar.gz
preproc: add %exitmacro support and clean up recursive macro handling
-rw-r--r--preproc.c46
1 files changed, 37 insertions, 9 deletions
diff --git a/preproc.c b/preproc.c
index 9fcebfa4..e549b795 100644
--- a/preproc.c
+++ b/preproc.c
@@ -138,7 +138,7 @@ struct MMacro {
bool plus; /* is the last parameter greedy? */
bool nolist; /* is this macro listing-inhibited? */
int64_t in_progress; /* is this macro currently being expanded? */
- int64_t max_depth; /* maximum number of recursive expansions allowed */
+ int32_t max_depth; /* maximum number of recursive expansions allowed */
Token *dlist; /* All defaults as one list */
Token **defaults; /* Parameter default pointers */
int ndefs; /* number of default parameters */
@@ -318,6 +318,12 @@ enum {
#define DIRECTIVE_FOUND 1
/*
+ * This define sets the upper limit for smacro and recursive mmacro
+ * expansions
+ */
+#define DEADMAN_LIMIT (1 << 20)
+
+/*
* Condition codes. Note that we use c_ prefix not C_ because C_ is
* used in nasm.h for the "real" condition codes. At _this_ level,
* we treat CXZ and ECXZ as condition codes, albeit non-invertible
@@ -2071,13 +2077,15 @@ static int do_directive(Token * tline)
* If we're in a %rep block, another %rep nests, so should be let through.
*/
if (defining && i != PP_MACRO && i != PP_IMACRO &&
+ i != PP_RMACRO && i != PP_RIMACRO &&
i != PP_ENDMACRO && i != PP_ENDM &&
(defining->name || (i != PP_ENDREP && i != PP_REP))) {
return NO_DIRECTIVE_FOUND;
}
if (defining) {
- if (i == PP_MACRO || i == PP_IMACRO) {
+ if (i == PP_MACRO || i == PP_IMACRO ||
+ i == PP_RMACRO || i == PP_RIMACRO) {
nested_mac_count++;
return NO_DIRECTIVE_FOUND;
} else if (nested_mac_count > 0) {
@@ -2596,12 +2604,14 @@ static int do_directive(Token * tline)
if (defining) {
error(ERR_FATAL,
"`%%%smacro': already defining a macro",
- (i == PP_IMACRO ? "i" : ""));
- /* todo: change the above as well... */
+ (i == PP_IMACRO ? "i" :
+ i == PP_RMACRO ? "r" :
+ i == PP_RIMACRO ? "ri" : ""));
return DIRECTIVE_FOUND;
}
defining = nasm_malloc(sizeof(MMacro));
- defining->max_depth = (((i == PP_RMACRO) || (i == PP_RIMACRO)) ? 65536 : 0);
+ defining->max_depth = (((i == PP_RMACRO) || (i == PP_RIMACRO))
+ ? (DEADMAN_LIMIT) : 0);
defining->casesense = ((i == PP_MACRO) || (i == PP_RMACRO));
if (!parse_mmacro_spec(tline, defining, pp_directives[i])) {
nasm_free(defining);
@@ -2631,13 +2641,31 @@ static int do_directive(Token * tline)
error(ERR_NONFATAL, "`%s': not defining a macro", tline->text);
return DIRECTIVE_FOUND;
}
- mmhead = (MMacro **) hash_findi_add(&mmacros, defining->name);
+ mmhead = (MMacro **) hash_findi_add(&mmacros, defining->name);
defining->next = *mmhead;
- *mmhead = defining;
+ *mmhead = defining;
defining = NULL;
free_tlist(origline);
return DIRECTIVE_FOUND;
+ case PP_EXITMACRO:
+ /*
+ * We must search along istk->expansion until we hit a
+ * macro-end marker for a macro with a name. Then we set
+ * its `in_progress' flag to 0.
+ */
+ for (l = istk->expansion; l; l = l->next)
+ if (l->finishes && l->finishes->name)
+ break;
+
+ if (l) {
+ l->finishes->in_progress = 0;
+ } else {
+ error(ERR_NONFATAL, "`%%exitmacro' not within `%%macro' block");
+ }
+ free_tlist(origline);
+ return DIRECTIVE_FOUND;
+
case PP_UNMACRO:
case PP_UNIMACRO:
{
@@ -3648,7 +3676,6 @@ static Token *expand_mmac_params(Token * tline)
* Tokens from input to output a lot of the time, rather than
* actually bothering to destroy and replicate.)
*/
-#define DEADMAN_LIMIT (1 << 20)
static Token *expand_smacro(Token * tline)
{
@@ -4566,12 +4593,13 @@ static char *pp_getline(void)
*/
if (m->prev != NULL) {
pop_mmacro(m);
+ l->finishes->in_progress --;
} else {
nasm_free(m->params);
free_tlist(m->iline);
nasm_free(m->paramlen);
+ l->finishes->in_progress = 0;
}
- l->finishes->in_progress --;
} else
free_mmacro(m);
}