[Nasm-commits] [nasm:preproc-rewrite] preproc.c: initial branch of revamped preprocessor

nasm-bot for Keith Kanios keith at kanios.net
Thu Jun 4 19:56:22 PDT 2020


Commit-ID:  973d4a49e81fa4fc1d246d34582ef1713dcd2628
Gitweb:     http://repo.or.cz/w/nasm.git?a=commitdiff;h=973d4a49e81fa4fc1d246d34582ef1713dcd2628
Author:     Keith Kanios <keith at kanios.net>
AuthorDate: Sun, 1 Aug 2010 02:30:33 -0500
Committer:  Keith Kanios <keith at kanios.net>
CommitDate: Sun, 1 Aug 2010 02:30:33 -0500

preproc.c: initial branch of revamped preprocessor



---
 preproc.c | 1456 ++++++++++++++++++++++++++++++++-----------------------------
 1 file changed, 758 insertions(+), 698 deletions(-)

diff --git a/preproc.c b/preproc.c
index d75b58eb..44c44ec7 100644
--- a/preproc.c
+++ b/preproc.c
@@ -83,7 +83,8 @@
 
 typedef struct SMacro SMacro;
 typedef struct MMacro MMacro;
-typedef struct MMacroInvocation MMacroInvocation;
+typedef struct ExpDef ExpDef;
+typedef struct ExpInv ExpInv;
 typedef struct Context Context;
 typedef struct Token Token;
 typedef struct Blocks Blocks;
@@ -113,64 +114,6 @@ struct SMacro {
     Token *expansion;
 };
 
-/*
- * Store the definition of a multi-line macro. This is also used to
- * store the interiors of `%rep...%endrep' blocks, which are
- * effectively self-re-invoking multi-line macros which simply
- * don't have a name or bother to appear in the hash tables. %rep
- * blocks are signified by having a NULL `name' field.
- *
- * In a MMacro describing a `%rep' block, the `in_progress' field
- * isn't merely boolean, but gives the number of repeats left to
- * run.
- *
- * The `next' field is used for storing MMacros in hash tables; the
- * `next_active' field is for stacking them on istk entries.
- *
- * When a MMacro is being expanded, `params', `iline', `nparam',
- * `paramlen', `rotate' and `unique' are local to the invocation.
- */
-struct MMacro {
-    MMacro *next;
-    MMacroInvocation *prev;     /* previous invocation */
-    char *name;
-    int nparam_min, nparam_max;
-    bool casesense;
-    bool plus;                  /* is the last parameter greedy? */
-    bool nolist;                /* is this macro listing-inhibited? */
-    int64_t in_progress;        /* is this macro currently being expanded? */
-    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 */
-    Line *expansion;
-
-    MMacro *next_active;
-    MMacro *rep_nest;           /* used for nesting %rep */
-    Token **params;             /* actual parameters */
-    Token *iline;               /* invocation line */
-    unsigned int nparam, rotate;
-    int *paramlen;
-    uint64_t unique;
-    int lineno;                 /* Current line number on expansion */
-    uint64_t condcnt;           /* number of if blocks... */
-};
-
-
-/* Store the definition of a multi-line macro, as defined in a
- * previous recursive macro expansion.
- */
-struct MMacroInvocation {
-    MMacroInvocation *prev;     /* previous invocation */
-    Token **params;             /* actual parameters */
-    Token *iline;               /* invocation line */
-    unsigned int nparam, rotate;
-    int *paramlen;
-    uint64_t unique;
-    uint64_t condcnt;
-};
-
-
 /*
  * The context stack is composed of a linked list of these.
  */
@@ -246,10 +189,84 @@ struct Token {
  */
 struct Line {
     Line *next;
-    MMacro *finishes;
     Token *first;
 };
 
+/*
+ * Expansion Types
+ */
+enum pp_exp_type {
+    EXP_NONE = 0, EXP_PREDEF,
+	EXP_MMACRO, EXP_REP,
+    EXP_IF,
+    EXP_MAX = INT_MAX       /* Keep compiler from reducing the range */
+};
+
+/*
+ * Store the definition of an expansion. This is also used to
+ * store the interiors of `%rep...%endrep' blocks, which are
+ * effectively self-re-invoking multi-line macros which simply
+ * don't have a name or bother to appear in the hash tables. %rep
+ * blocks are signified by having a NULL `name' field.
+ *
+ * In a ExpDef describing a `%rep' block, the `cur_depth' field
+ * isn't merely boolean, but gives the number of repeats left to
+ * run.
+ *
+ * The `next' field is used for storing ExpDef in hash tables; the
+ * `prev' field is for the `expansions` linked-list.
+ */
+struct ExpDef {
+    ExpDef *prev;               /* previous definition */
+	ExpDef *next;				/* next in hash table */
+    enum pp_exp_type type;      /* expansion type */
+    char *name;
+    int nparam_min, nparam_max;
+    bool casesense;
+    bool plus;                  /* is the last parameter greedy? */
+    bool nolist;                /* is this expansion listing-inhibited? */
+    Token *dlist;               /* All defaults as one list */
+    Token **defaults;           /* Parameter default pointers */
+    int ndefs;                  /* number of default parameters */
+	
+	Line *label;
+    Line *line;
+	Line *last;
+	
+	uint32_t def_depth;			/* current number of definition pairs deep */
+    uint32_t cur_depth;         /* current number of expansions */
+    uint32_t max_depth;         /* maximum number of expansions allowed */	
+
+	int state;					/* condition state */
+	bool ignoring;				/* ignoring definition lines */
+};
+
+/*
+ * Store the invocation of an expansion.
+ *
+ * The `prev' field is for the `istk->expansion` linked-list.
+ *
+ * When an expansion is being expanded, `params', `iline', `nparam',
+ * `paramlen', `rotate' and `unique' are local to the invocation.
+ */
+struct ExpInv {
+    ExpInv *prev;               /* previous invocation */
+    enum pp_exp_type type;      /* expansion type */
+    ExpDef *def;                /* pointer to expansion definition */
+	Line *label;                /* pointer to label */
+	char *label_text;			/* pointer to label text */
+    Line *current;              /* pointer to current line in invocation */
+	
+    Token **params;             /* actual parameters */
+    Token *iline;               /* invocation line */
+    unsigned int nparam, rotate;
+    int *paramlen;
+	
+	uint64_t unique;
+    bool emitting;
+    int lineno;                 /* current line number in expansion */
+};
+
 /*
  * To handle an arbitrary level of file inclusion, we maintain a
  * stack (ie linked list) of these things.
@@ -258,10 +275,9 @@ struct Include {
     Include *next;
     FILE *fp;
     Cond *conds;
-    Line *expansion;
+    ExpInv *expansion;
     char *fname;
     int lineno, lineinc;
-    MMacro *mstk;       /* stack of active macros/reps */
 };
 
 /*
@@ -281,10 +297,6 @@ struct IncPath {
  * included from within the true branch of a `%if' won't terminate
  * it and cause confusion: instead, rightly, it'll cause an error.)
  */
-struct Cond {
-    Cond *next;
-    int state;
-};
 enum {
     /*
      * These states are for use just after %if or %elif: IF_TRUE
@@ -349,15 +361,6 @@ static const enum pp_conds inverse_ccs[] = {
     c_Z, c_NO, c_NP, c_PO, c_PE, -1, c_NS, c_NZ
 };
 
-/*
- * Directive names.
- */
-/* If this is a an IF, ELIF, ELSE or ENDIF keyword */
-static int is_condition(enum preproc_token arg)
-{
-    return PP_IS_COND(arg) || (arg == PP_ELSE) || (arg == PP_ENDIF);
-}
-
 /* For TASM compatibility we need to be able to recognise TASM compatible
  * conditional compilation directives. Using the NASM pre-processor does
  * not work, so we look for them specifically from the following list and
@@ -394,9 +397,9 @@ static bool do_predef;
 static ListGen *list;
 
 /*
- * The current set of multi-line macros we have defined.
+ * The current set of expansion definitions we have defined.
  */
-static struct hash_table mmacros;
+static struct hash_table expdefs;
 
 /*
  * The current set of single-line macros we have defined.
@@ -404,10 +407,14 @@ static struct hash_table mmacros;
 static struct hash_table smacros;
 
 /*
- * The multi-line macro we are currently defining, or the %rep
- * block we are currently reading, if any.
+ * Linked List of all active expansion definitions
  */
-static MMacro *defining;
+struct ExpDef *expansions = NULL;
+
+/*
+ * The expansion we are currently defining
+ */
+static ExpDef *defining = NULL;
 
 static uint64_t nested_mac_count;
 static uint64_t nested_rep_count;
@@ -457,7 +464,11 @@ static void *new_Block(size_t size);
 static void delete_Blocks(void);
 static Token *new_Token(Token * next, enum pp_token_type type,
                         const char *text, int txtlen);
+static Token *copy_Token(Token * tline);
 static Token *delete_Token(Token * t);
+static Line *new_Line(void);
+static ExpDef *new_ExpDef(void);
+static ExpInv *new_ExpInv(void);
 
 /*
  * Macros for safe checking of token pointers, avoid *(NULL)
@@ -590,15 +601,15 @@ static void free_llist(Line * list)
 }
 
 /*
- * Free an MMacro
+ * Free an ExpDef
  */
-static void free_mmacro(MMacro * m)
+static void free_expdef(ExpDef * ed)
 {
-    nasm_free(m->name);
-    free_tlist(m->dlist);
-    nasm_free(m->defaults);
-    free_llist(m->expansion);
-    nasm_free(m);
+    nasm_free(ed->name);
+    free_tlist(ed->dlist);
+    nasm_free(ed->defaults);
+    free_llist(ed->line);
+    nasm_free(ed);
 }
 
 /*
@@ -621,25 +632,25 @@ static void free_smacro_table(struct hash_table *smt)
     hash_free(smt);
 }
 
-static void free_mmacro_table(struct hash_table *mmt)
+static void free_mmacro_table(struct hash_table *edt)
 {
-    MMacro *m, *tmp;
+    ExpDef *ed, *tmp;
     const char *key;
     struct hash_tbl_node *it = NULL;
 
     it = NULL;
-    while ((m = hash_iterate(mmt, &it, &key)) != NULL) {
+    while ((ed = hash_iterate(edt, &it, &key)) != NULL) {
         nasm_free((void *)key);
-        list_for_each_safe(m ,tmp, m)
-            free_mmacro(m);
+        list_for_each_safe(ed ,tmp, ed)
+            free_expdef(ed);
     }
-    hash_free(mmt);
+    hash_free(edt);
 }
 
 static void free_macros(void)
 {
     free_smacro_table(&smacros);
-    free_mmacro_table(&mmacros);
+    free_mmacro_table(&expdefs);
 }
 
 /*
@@ -648,7 +659,7 @@ static void free_macros(void)
 static void init_macros(void)
 {
     hash_init(&smacros, HASH_LARGE);
-    hash_init(&mmacros, HASH_LARGE);
+    hash_init(&expdefs, HASH_LARGE);
 }
 
 /*
@@ -698,7 +709,7 @@ hash_findix(struct hash_table *hash, const char *str)
 }
 
 /*
- * read line from standart macros set,
+ * read line from standard macros set,
  * if there no more left -- return NULL
  */
 static char *line_from_stdmac(void)
@@ -739,6 +750,7 @@ static char *line_from_stdmac(void)
             stdmacpos = extrastdmac;
             any_extrastdmac = false;
         } else if (do_predef) {
+			ExpInv *ei;
             Line *pd, *l;
             Token *head, **tail, *t;
 
@@ -757,12 +769,14 @@ static char *line_from_stdmac(void)
                     tail = &(*tail)->next;
                 }
 
-                l           = nasm_malloc(sizeof(Line));
-                l->next     = istk->expansion;
-                l->first    = head;
-                l->finishes = NULL;
-
-                istk->expansion = l;
+                l = new_Line();
+                l->first = head;
+				ei = new_ExpInv();
+				ei->type = EXP_PREDEF;
+				ei->current = l;
+				ei->emitting = true;
+				ei->prev = istk->expansion;
+                istk->expansion = ei;
             }
             do_predef = false;
         }
@@ -1192,6 +1206,34 @@ static Token *new_Token(Token * next, enum pp_token_type type,
     return t;
 }
 
+static Token *copy_Token(Token * tline)
+{
+    Token *t, *tt, *first = NULL, *prev = NULL;
+    int i;
+	for (tt = tline; tt != NULL; tt = tt->next) {
+		if (!freeTokens) {
+			freeTokens = (Token *) new_Block(TOKEN_BLOCKSIZE * sizeof(Token));
+			for (i = 0; i < TOKEN_BLOCKSIZE - 1; i++)
+				freeTokens[i].next = &freeTokens[i + 1];
+			freeTokens[i].next = NULL;
+		}
+		t = freeTokens;
+		freeTokens = t->next;
+		t->next = NULL;
+		t->text = ((tt->text != NULL) ? strdup(tt->text) : NULL);
+		t->a.mac = tt->a.mac;
+		t->a.len = tt->a.len;
+		t->type = tt->type;
+		if (prev != NULL) {
+			prev->next = t;
+		} else {
+			first = t;
+		}
+		prev = t;
+	}
+    return first;
+}
+
 static Token *delete_Token(Token * t)
 {
     Token *next = t->next;
@@ -1279,6 +1321,72 @@ static char *detoken(Token * tlist, bool expand_locals)
     return line;
 }
 
+/*
+ * Initialize a new Line
+ */
+static Line *new_Line(void)
+{
+	Line *l = nasm_malloc(sizeof(Line));
+	l->next = NULL;
+	l->first = NULL;
+	return l;
+}
+
+
+/*
+ * Initialize a new Expansion Definition
+ */
+static ExpDef *new_ExpDef(void)
+{
+	ExpDef *ed = nasm_malloc(sizeof(ExpDef));
+	ed->prev = NULL;
+	ed->next = NULL;
+	ed->type = EXP_NONE;
+	ed->name = NULL;
+	ed->nparam_min = 0;
+	ed->nparam_max = 0;
+	ed->casesense = true;
+	ed->plus = false;
+	ed->label = NULL;
+	ed->line = NULL;
+	ed->last = NULL;
+	ed->dlist = NULL;
+	ed->defaults = NULL;
+	ed->ndefs = 0;
+	ed->state = COND_NEVER;
+	ed->nolist = false;
+	ed->def_depth = 0;
+	ed->cur_depth = 0;
+	ed->max_depth = 0;
+	ed->ignoring = false;
+	return ed;
+}
+
+
+/*
+ * Initialize a new Expansion Instance
+ */
+static ExpInv *new_ExpInv(void)
+{
+	unique ++;
+	ExpInv *ei = nasm_malloc(sizeof(ExpInv));
+	ei->prev = NULL;
+	ei->type = EXP_NONE;
+	ei->def = NULL;
+	ei->label = NULL;
+	ei->label_text = NULL;
+	ei->current = NULL;
+	ei->params = NULL;
+	ei->iline = NULL;
+	ei->nparam = 0;
+	ei->rotate = 0;
+	ei->paramlen = NULL;
+	ei->unique = unique;
+	ei->emitting = false;
+	ei->lineno = 0;
+	return ei;
+}
+
 /*
  * A scanner, suitable for use by the expression evaluator, which
  * operates on a line of Tokens. Expects a pointer to a pointer to
@@ -1787,7 +1895,7 @@ static bool if_condition(Token * tline, enum preproc_token ct)
     case PPC_IFMACRO:
     {
         bool found = false;
-        MMacro searching, *mmac;
+        ExpDef searching, *ed;
 
         skip_white_(tline);
         tline = expand_id(tline);
@@ -1800,9 +1908,9 @@ static bool if_condition(Token * tline, enum preproc_token ct)
         searching.casesense = true;
         searching.plus = false;
         searching.nolist = false;
-        searching.in_progress = 0;
+        //searching.in_progress = 0;
         searching.max_depth = 0;
-        searching.rep_nest = NULL;
+        //searching.rep_nest = NULL;
         searching.nparam_min = 0;
         searching.nparam_max = INT_MAX;
         tline = expand_smacro(tline->next);
@@ -1843,17 +1951,17 @@ static bool if_condition(Token * tline, enum preproc_token ct)
             tline = tline->next;
             searching.plus = true;
         }
-        mmac = (MMacro *) hash_findix(&mmacros, searching.name);
-        while (mmac) {
-            if (!strcmp(mmac->name, searching.name) &&
-                (mmac->nparam_min <= searching.nparam_max
+        ed = (ExpDef *) hash_findix(&expdefs, searching.name);
+        while (ed != NULL) {
+            if (!strcmp(ed->name, searching.name) &&
+                (ed->nparam_min <= searching.nparam_max
                  || searching.plus)
-                && (searching.nparam_min <= mmac->nparam_max
-                    || mmac->plus)) {
+                && (searching.nparam_min <= ed->nparam_max
+                    || ed->plus)) {
                 found = true;
                 break;
             }
-            mmac = mmac->next;
+            ed = ed->next;
         }
         if (tline && tline->next)
             error(ERR_WARNING|ERR_PASS1,
@@ -2018,7 +2126,7 @@ static void undef_smacro(Context *ctx, const char *mname)
 /*
  * Parse a mmacro specification.
  */
-static bool parse_mmacro_spec(Token *tline, MMacro *def, const char *directive)
+static bool parse_mmacro_spec(Token *tline, ExpDef *def, const char *directive)
 {
     bool err;
 
@@ -2030,12 +2138,11 @@ static bool parse_mmacro_spec(Token *tline, MMacro *def, const char *directive)
         return false;
     }
 
-    def->prev = NULL;
     def->name = nasm_strdup(tline->text);
     def->plus = false;
     def->nolist = false;
-    def->in_progress = 0;
-    def->rep_nest = NULL;
+//    def->in_progress = 0;
+//    def->rep_nest = NULL;
     def->nparam_min = 0;
     def->nparam_max = 0;
 
@@ -2089,7 +2196,7 @@ static bool parse_mmacro_spec(Token *tline, MMacro *def, const char *directive)
         def->dlist = NULL;
         def->defaults = NULL;
     }
-    def->expansion = NULL;
+    def->line = NULL;
 
     if (def->defaults && def->ndefs > def->nparam_max - def->nparam_min &&
         !def->plus)
@@ -2138,13 +2245,11 @@ static int do_directive(Token * tline)
     const char *mname;
     Include *inc;
     Context *ctx;
-    Cond *cond;
-    MMacro *mmac, **mmhead;
     Token *t, *tt, *param_start, *macro_start, *last, **tptr, *origline;
-    Line *l;
     struct tokenval tokval;
     expr *evalresult;
-    MMacro *tmp_defining;       /* Used when manipulating rep_nest */
+    ExpDef *ed, *eed, **edhead;
+	ExpInv *ei, *eei;
     int64_t count;
     size_t len;
     int severity;
@@ -2159,72 +2264,15 @@ static int do_directive(Token * tline)
 
     i = pp_token_hash(tline->text);
 
-    /*
-     * FIXME: We zap execution of PP_RMACRO, PP_IRMACRO, PP_EXITMACRO
-     * since they are known to be buggy at moment, we need to fix them
-     * in future release (2.09-2.10)
-     */
-    if (i == PP_RMACRO || i == PP_RMACRO || i == PP_EXITMACRO) {
-        error(ERR_NONFATAL, "unknown preprocessor directive `%s'",
-              tline->text);
-       return NO_DIRECTIVE_FOUND;
-    }
-
-    /*
-     * If we're in a non-emitting branch of a condition construct,
-     * or walking to the end of an already terminated %rep block,
-     * we should ignore all directives except for condition
-     * directives.
-     */
-    if (((istk->conds && !emitting(istk->conds->state)) ||
-         (istk->mstk && !istk->mstk->in_progress)) && !is_condition(i)) {
-        return NO_DIRECTIVE_FOUND;
-    }
-
-    /*
-     * If we're defining a macro or reading a %rep block, we should
-     * ignore all directives except for %macro/%imacro (which nest),
-     * %endm/%endmacro, and (only if we're in a %rep block) %endrep.
-     * 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_IRMACRO &&
-        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 ||
-            i == PP_RMACRO || i == PP_IRMACRO) {
-            nested_mac_count++;
-            return NO_DIRECTIVE_FOUND;
-        } else if (nested_mac_count > 0) {
-            if (i == PP_ENDMACRO) {
-                nested_mac_count--;
-                return NO_DIRECTIVE_FOUND;
-            }
-        }
-        if (!defining->name) {
-            if (i == PP_REP) {
-                nested_rep_count++;
-                return NO_DIRECTIVE_FOUND;
-            } else if (nested_rep_count > 0) {
-                if (i == PP_ENDREP) {
-                    nested_rep_count--;
-                    return NO_DIRECTIVE_FOUND;
-                }
-            }
-        }
-    }
-
     switch (i) {
     case PP_INVALID:
+		if (defining != NULL) return NO_DIRECTIVE_FOUND;
         error(ERR_NONFATAL, "unknown preprocessor directive `%s'",
               tline->text);
         return NO_DIRECTIVE_FOUND;      /* didn't get it */
 
     case PP_STACKSIZE:
+		if (defining != NULL) return NO_DIRECTIVE_FOUND;
         /* Directive to tell NASM what the default stack size is. The
          * default is for a 16-bit stack, and this can be overriden with
          * %stacksize large.
@@ -2274,6 +2322,7 @@ static int do_directive(Token * tline)
         return DIRECTIVE_FOUND;
 
     case PP_ARG:
+		if (defining != NULL) return NO_DIRECTIVE_FOUND;
         /* TASM like ARG directive to define arguments to functions, in
          * the following form:
          *
@@ -2343,6 +2392,7 @@ static int do_directive(Token * tline)
         return DIRECTIVE_FOUND;
 
     case PP_LOCAL:
+		if (defining != NULL) return NO_DIRECTIVE_FOUND;
         /* TASM like LOCAL directive to define local variables for a
          * function, in the following form:
          *
@@ -2424,6 +2474,7 @@ static int do_directive(Token * tline)
         return DIRECTIVE_FOUND;
 
     case PP_CLEAR:
+		if (defining != NULL) return NO_DIRECTIVE_FOUND;
         if (tline->next)
             error(ERR_WARNING|ERR_PASS1,
                   "trailing garbage after `%%clear' ignored");
@@ -2433,6 +2484,7 @@ static int do_directive(Token * tline)
         return DIRECTIVE_FOUND;
 
     case PP_DEPEND:
+		if (defining != NULL) return NO_DIRECTIVE_FOUND;
         t = tline->next = expand_smacro(tline->next);
         skip_white_(t);
         if (!t || (t->type != TOK_STRING &&
@@ -2458,6 +2510,7 @@ static int do_directive(Token * tline)
         return DIRECTIVE_FOUND;
 
     case PP_INCLUDE:
+		if (defining != NULL) return NO_DIRECTIVE_FOUND;
         t = tline->next = expand_smacro(tline->next);
         skip_white_(t);
 
@@ -2475,7 +2528,6 @@ static int do_directive(Token * tline)
             nasm_unquote_cstr(p, i);
         inc = nasm_malloc(sizeof(Include));
         inc->next = istk;
-        inc->conds = NULL;
         inc->fp = inc_fopen(p, dephead, &deptail, pass == 0);
         if (!inc->fp) {
             /* -MG given but file not found */
@@ -2485,7 +2537,6 @@ static int do_directive(Token * tline)
             inc->lineno = src_set_linnum(0);
             inc->lineinc = 1;
             inc->expansion = NULL;
-            inc->mstk = NULL;
             istk = inc;
             list->uplevel(LIST_INCLUDE);
         }
@@ -2493,6 +2544,7 @@ static int do_directive(Token * tline)
         return DIRECTIVE_FOUND;
 
     case PP_USE:
+		if (defining != NULL) return NO_DIRECTIVE_FOUND;
     {
         static macros_t *use_pkg;
         const char *pkg_macro = NULL;
@@ -2528,6 +2580,7 @@ static int do_directive(Token * tline)
     case PP_PUSH:
     case PP_REPL:
     case PP_POP:
+		if (defining != NULL) return NO_DIRECTIVE_FOUND;
         tline = tline->next;
         skip_white_(tline);
         tline = expand_id(tline);
@@ -2587,6 +2640,7 @@ static int do_directive(Token * tline)
         goto issue_error;
 
 issue_error:
+		if (defining != NULL) return NO_DIRECTIVE_FOUND;
     {
         /* Only error out if this is the final pass */
         if (pass != 2 && i != PP_FATAL)
@@ -2613,39 +2667,59 @@ issue_error:
     }
 
     CASE_PP_IF:
-        if (istk->conds && !emitting(istk->conds->state))
-            j = COND_NEVER;
-        else {
-            j = if_condition(tline->next, i);
-            tline->next = NULL; /* it got freed */
-            j = j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
-        }
-        cond = nasm_malloc(sizeof(Cond));
-        cond->next = istk->conds;
-        cond->state = j;
-        istk->conds = cond;
-        if(istk->mstk)
-            istk->mstk->condcnt ++;
+		if (defining != NULL) {
+			if (defining->type == EXP_IF) {
+				defining->def_depth ++;	
+			}
+			return NO_DIRECTIVE_FOUND;
+		}
+		if ((istk->expansion != NULL) &&
+			(istk->expansion->emitting == false)) {
+			j = COND_NEVER;
+		} else {
+			j = if_condition(tline->next, i);
+			tline->next = NULL; /* it got freed */
+			j = (((j < 0) ? COND_NEVER : j) ? COND_IF_TRUE : COND_IF_FALSE);
+		}
+		ed = new_ExpDef();
+		ed->type = EXP_IF;
+		ed->state = j;
+		ed->nolist = NULL;
+		ed->def_depth = 0;
+		ed->cur_depth = 0;
+		ed->max_depth = 0;
+		ed->ignoring = ((ed->state == COND_IF_TRUE) ? false : true);
+		ed->prev = defining;
+		defining = ed;
         free_tlist(origline);
         return DIRECTIVE_FOUND;
 
     CASE_PP_ELIF:
-        if (!istk->conds)
-            error(ERR_FATAL, "`%s': no matching `%%if'", pp_directives[i]);
-        switch(istk->conds->state) {
-        case COND_IF_TRUE:
-            istk->conds->state = COND_DONE;
-            break;
+		if (defining != NULL) {
+			if ((defining->type != EXP_IF) || (defining->def_depth > 0)) {
+				return NO_DIRECTIVE_FOUND;	
+			}
+		}
+		if ((defining == NULL) ||	(defining->type != EXP_IF)) {
+			error(ERR_FATAL, "`%s': no matching `%%if'", pp_directives[i]);
+		}
+        switch (defining->state) {
+		case COND_IF_TRUE:
+			defining->state = COND_DONE;
+			defining->ignoring = true;
+			break;
 
-        case COND_DONE:
-        case COND_NEVER:
-            break;
+		case COND_DONE:
+		case COND_NEVER:
+			defining->ignoring = true;
+			break;
 
         case COND_ELSE_TRUE:
         case COND_ELSE_FALSE:
             error_precond(ERR_WARNING|ERR_PASS1,
                           "`%%elif' after `%%else' ignored");
-            istk->conds->state = COND_NEVER;
+			defining->state = COND_NEVER;
+			defining->ignoring = true;
             break;
 
         case COND_IF_FALSE:
@@ -2659,53 +2733,81 @@ issue_error:
              */
             j = if_condition(expand_mmac_params(tline->next), i);
             tline->next = NULL; /* it got freed */
-            istk->conds->state =
+			defining->state =
                 j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
+			defining->ignoring = ((defining->state == COND_IF_TRUE) ? false : true);
             break;
         }
         free_tlist(origline);
         return DIRECTIVE_FOUND;
 
     case PP_ELSE:
+		if (defining != NULL) {
+			if ((defining->type != EXP_IF) || (defining->def_depth > 0)) {
+				return NO_DIRECTIVE_FOUND;	
+			}
+		}
         if (tline->next)
             error_precond(ERR_WARNING|ERR_PASS1,
                           "trailing garbage after `%%else' ignored");
-        if (!istk->conds)
-            error(ERR_FATAL, "`%%else': no matching `%%if'");
-        switch(istk->conds->state) {
-        case COND_IF_TRUE:
-        case COND_DONE:
-            istk->conds->state = COND_ELSE_FALSE;
-            break;
-
-        case COND_NEVER:
-            break;
-
-        case COND_IF_FALSE:
-            istk->conds->state = COND_ELSE_TRUE;
-            break;
+		if ((defining == NULL) || (defining->type != EXP_IF)) {
+			error(ERR_FATAL, "`%s': no matching `%%if'", pp_directives[i]);
+		}
+        switch (defining->state) {
+		case COND_IF_TRUE:
+		case COND_DONE:
+			defining->state = COND_ELSE_FALSE;
+			defining->ignoring = true;
+			break;
+
+		case COND_NEVER:
+			defining->ignoring = true;
+			break;
+
+		case COND_IF_FALSE:
+			defining->state = COND_ELSE_TRUE;
+			defining->ignoring = false;
+			break;
 
         case COND_ELSE_TRUE:
         case COND_ELSE_FALSE:
             error_precond(ERR_WARNING|ERR_PASS1,
                           "`%%else' after `%%else' ignored.");
-            istk->conds->state = COND_NEVER;
+			defining->state = COND_NEVER;
+			defining->ignoring = true;
             break;
         }
         free_tlist(origline);
         return DIRECTIVE_FOUND;
 
     case PP_ENDIF:
+		if (defining != NULL) {
+			if (defining->type == EXP_IF) {
+				if (defining->def_depth > 0) {
+					defining->def_depth --;
+					return NO_DIRECTIVE_FOUND;
+				}
+			} else {
+				return NO_DIRECTIVE_FOUND;
+			}
+		}
         if (tline->next)
             error_precond(ERR_WARNING|ERR_PASS1,
                           "trailing garbage after `%%endif' ignored");
-        if (!istk->conds)
-            error(ERR_FATAL, "`%%endif': no matching `%%if'");
-        cond = istk->conds;
-        istk->conds = cond->next;
-        nasm_free(cond);
-        if(istk->mstk)
-            istk->mstk->condcnt --;
+		if ((defining == NULL) || (defining->type != EXP_IF)) {
+			error(ERR_NONFATAL, "`%%endif': no matching `%%if'");
+		}
+		ed = defining;
+		defining = ed->prev;
+		ed->prev = expansions;
+		expansions = ed;
+		ei = new_ExpInv();
+		ei->type = EXP_IF;
+		ei->def = ed;
+		ei->current = ed->line;
+		ei->emitting = true;
+		ei->prev = istk->expansion;
+		istk->expansion = ei;
         free_tlist(origline);
         return DIRECTIVE_FOUND;
 
@@ -2713,99 +2815,123 @@ issue_error:
     case PP_IRMACRO:
     case PP_MACRO:
     case PP_IMACRO:
-        if (defining) {
-            error(ERR_FATAL, "`%s': already defining a macro",
-                  pp_directives[i]);
-            return DIRECTIVE_FOUND;
-        }
-        defining = nasm_malloc(sizeof(MMacro));
-        defining->max_depth =
+		if (defining != NULL) {
+			if (defining->type == EXP_MMACRO) {
+				defining->def_depth ++;
+			}
+			return NO_DIRECTIVE_FOUND;
+		}
+		ed = new_ExpDef();	
+		ed->max_depth =
             (i == PP_RMACRO) || (i == PP_IRMACRO) ? DEADMAN_LIMIT : 0;
-        defining->casesense = (i == PP_MACRO) || (i == PP_RMACRO);
-        if (!parse_mmacro_spec(tline, defining, pp_directives[i])) {
-            nasm_free(defining);
-            defining = NULL;
+		ed->casesense = (i == PP_MACRO) || (i == PP_RMACRO);
+        if (!parse_mmacro_spec(tline, ed, pp_directives[i])) {
+            nasm_free(ed);
+            ed = NULL;
             return DIRECTIVE_FOUND;
         }
-
-        mmac = (MMacro *) hash_findix(&mmacros, defining->name);
-        while (mmac) {
-            if (!strcmp(mmac->name, defining->name) &&
-                (mmac->nparam_min <= defining->nparam_max
-                 || defining->plus)
-                && (defining->nparam_min <= mmac->nparam_max
-                    || mmac->plus)) {
-                error(ERR_WARNING|ERR_PASS1,
-                      "redefining multi-line macro `%s'", defining->name);
-                return DIRECTIVE_FOUND;
-            }
-            mmac = mmac->next;
-        }
+		ed->type = EXP_MMACRO;
+		ed->def_depth = 0;
+		ed->cur_depth = 0;
+		ed->max_depth = (ed->max_depth + 1);
+		ed->ignoring = false;
+		ed->prev = defining;
+		defining = ed;
+
+		eed = (ExpDef *) hash_findix(&expdefs, ed->name);
+		while (eed) {
+			if (!strcmp(eed->name, ed->name) &&
+				(eed->nparam_min <= ed->nparam_max
+				 || ed->plus)
+				&& (ed->nparam_min <= eed->nparam_max
+					|| eed->plus)) {
+					error(ERR_WARNING|ERR_PASS1,
+						  "redefining multi-line macro `%s'", ed->name);
+					return DIRECTIVE_FOUND;
+				}
+			eed = eed->next;
+		}
         free_tlist(origline);
         return DIRECTIVE_FOUND;
 
     case PP_ENDM:
     case PP_ENDMACRO:
-        if (! (defining && defining->name)) {
-            error(ERR_NONFATAL, "`%s': not defining a macro", tline->text);
-            return DIRECTIVE_FOUND;
-        }
-        mmhead = (MMacro **) hash_findi_add(&mmacros, defining->name);
-        defining->next = *mmhead;
-        *mmhead = defining;
-        defining = NULL;
+		if (defining != NULL) {
+			if (defining->type == EXP_MMACRO) {
+				if (defining->def_depth > 0) {
+					defining->def_depth --;
+					return NO_DIRECTIVE_FOUND;
+				}
+			} else {
+				return NO_DIRECTIVE_FOUND;
+			}
+		}
+		if (!(defining) || (defining->type != EXP_MMACRO)) {
+			error(ERR_NONFATAL, "`%s': not defining a macro", tline->text);
+			return DIRECTIVE_FOUND;
+		}
+		edhead = (ExpDef **) hash_findi_add(&expdefs, defining->name);
+		defining->next = *edhead;
+		*edhead = defining;
+		ed = defining;
+		defining = ed->prev;
+		ed->prev = expansions;
+		expansions = ed;
+		ed = 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
-         * bypass all lines between exitmacro and endmacro.
-         */
-        list_for_each(l, istk->expansion)
-            if (l->finishes && l->finishes->name)
-                break;
-
-        if (l) {
-            /*
-             * Remove all conditional entries relative to this
-             * macro invocation. (safe to do in this context)
-             */
-            for ( ; l->finishes->condcnt > 0; l->finishes->condcnt --) {
-                cond = istk->conds;
-                istk->conds = cond->next;
-                nasm_free(cond);
-            }
-            istk->expansion = l;
-        } else {
-            error(ERR_NONFATAL, "`%%exitmacro' not within `%%macro' block");
-        }
+		if (defining != NULL) return NO_DIRECTIVE_FOUND;
+		/*
+		 * We must search along istk->expansion until we hit a
+		 * macro invocation. Then we disable the emitting state(s)
+		 * between exitmacro and endmacro.
+		 */
+		for (ei = istk->expansion; ei != NULL; ei = ei->prev) {
+			if(ei->type == EXP_MMACRO) {
+				break;
+			}
+		}
+			
+		if (ei != NULL) {
+			/*
+			 * Set all invocations leading back to the macro
+			 * invocation to a non-emitting state.
+			 */
+			for (eei = istk->expansion; eei != ei; eei = eei->prev) {
+				eei->emitting = false;
+			}
+			eei->emitting = false;
+		} else {
+			error(ERR_NONFATAL, "`%%exitmacro' not within `%%macro' block");
+		}
         free_tlist(origline);
         return DIRECTIVE_FOUND;
 
     case PP_UNMACRO:
     case PP_UNIMACRO:
+		if (defining != NULL) return NO_DIRECTIVE_FOUND;
     {
-        MMacro **mmac_p;
-        MMacro spec;
+        ExpDef **ed_p;
+        ExpDef spec;
 
         spec.casesense = (i == PP_UNMACRO);
         if (!parse_mmacro_spec(tline, &spec, pp_directives[i])) {
             return DIRECTIVE_FOUND;
         }
-        mmac_p = (MMacro **) hash_findi(&mmacros, spec.name, NULL);
-        while (mmac_p && *mmac_p) {
-            mmac = *mmac_p;
-            if (mmac->casesense == spec.casesense &&
-                !mstrcmp(mmac->name, spec.name, spec.casesense) &&
-                mmac->nparam_min == spec.nparam_min &&
-                mmac->nparam_max == spec.nparam_max &&
-                mmac->plus == spec.plus) {
-                *mmac_p = mmac->next;
-                free_mmacro(mmac);
+        ed_p = (ExpDef **) hash_findi(&expdefs, spec.name, NULL);
+        while (ed_p && *ed_p) {
+            ed = *ed_p;
+            if (ed->casesense == spec.casesense &&
+                !mstrcmp(ed->name, spec.name, spec.casesense) &&
+                ed->nparam_min == spec.nparam_min &&
+                ed->nparam_max == spec.nparam_max &&
+                ed->plus == spec.plus) {
+                *ed_p = ed->next;
+                free_expdef(ed);
             } else {
-                mmac_p = &mmac->next;
+                ed_p = &ed->next;
             }
         }
         free_tlist(origline);
@@ -2814,6 +2940,7 @@ issue_error:
     }
 
     case PP_ROTATE:
+		if (defining != NULL) return NO_DIRECTIVE_FOUND;
         if (tline->next && tline->next->type == TOK_WHITESPACE)
             tline = tline->next;
         if (!tline->next) {
@@ -2839,26 +2966,33 @@ issue_error:
             error(ERR_NONFATAL, "non-constant value given to `%%rotate'");
             return DIRECTIVE_FOUND;
         }
-        mmac = istk->mstk;
-        while (mmac && !mmac->name)     /* avoid mistaking %reps for macros */
-            mmac = mmac->next_active;
-        if (!mmac) {
-            error(ERR_NONFATAL, "`%%rotate' invoked outside a macro call");
-        } else if (mmac->nparam == 0) {
-            error(ERR_NONFATAL,
-                  "`%%rotate' invoked within macro without parameters");
-        } else {
-            int rotate = mmac->rotate + reloc_value(evalresult);
-
-            rotate %= (int)mmac->nparam;
-            if (rotate < 0)
-                rotate += mmac->nparam;
-
-            mmac->rotate = rotate;
-        }
+		for (ei = istk->expansion; ei != NULL; ei = ei->prev) {
+			if (ei->type == EXP_MMACRO) {
+				break;
+			}
+		}
+		if (ei == NULL) {
+			error(ERR_NONFATAL, "`%%rotate' invoked outside a macro call");
+		} else if (ei->nparam == 0) {
+			error(ERR_NONFATAL,
+				  "`%%rotate' invoked within macro without parameters");
+		} else {
+			int rotate = ei->rotate + reloc_value(evalresult);
+			
+			rotate %= (int)ei->nparam;
+			if (rotate < 0)
+				rotate += ei->nparam;
+			ei->rotate = rotate;
+		}
         return DIRECTIVE_FOUND;
 
     case PP_REP:
+		if (defining != NULL) {
+			if (defining->type == EXP_REP) {
+				defining->def_depth ++;
+			}
+			return NO_DIRECTIVE_FOUND;
+		}
         nolist = false;
         do {
             tline = tline->next;
@@ -2895,26 +3029,29 @@ issue_error:
             count = 0;
         }
         free_tlist(origline);
-
-        tmp_defining = defining;
-        defining = nasm_malloc(sizeof(MMacro));
-        defining->prev = NULL;
-        defining->name = NULL;  /* flags this macro as a %rep block */
-        defining->casesense = false;
-        defining->plus = false;
-        defining->nolist = nolist;
-        defining->in_progress = count;
-        defining->max_depth = 0;
-        defining->nparam_min = defining->nparam_max = 0;
-        defining->defaults = NULL;
-        defining->dlist = NULL;
-        defining->expansion = NULL;
-        defining->next_active = istk->mstk;
-        defining->rep_nest = tmp_defining;
+		ed = new_ExpDef();
+		ed->type = EXP_REP;
+		ed->nolist = nolist;
+		ed->def_depth = 0;
+		ed->cur_depth = 1;
+		ed->max_depth = (count - 1);
+		ed->ignoring = false;
+		ed->prev = defining;
+		defining = ed;
         return DIRECTIVE_FOUND;
 
     case PP_ENDREP:
-        if (!defining || defining->name) {
+		if (defining != NULL) {
+			if (defining->type == EXP_REP) {
+				if (defining->def_depth > 0) {
+					defining->def_depth --;
+					return NO_DIRECTIVE_FOUND;
+				}
+			} else {
+				return NO_DIRECTIVE_FOUND;
+			}
+		}
+        if ((defining == NULL) || (defining->type != EXP_REP)) {
             error(ERR_NONFATAL, "`%%endrep': no matching `%%rep'");
             return DIRECTIVE_FOUND;
         }
@@ -2930,34 +3067,48 @@ issue_error:
          * continues) until the whole expansion is forcibly removed
          * from istk->expansion by a %exitrep.
          */
-        l = nasm_malloc(sizeof(Line));
-        l->next = istk->expansion;
-        l->finishes = defining;
-        l->first = NULL;
-        istk->expansion = l;
-
-        istk->mstk = defining;
-
-        list->uplevel(defining->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
-        tmp_defining = defining;
-        defining = defining->rep_nest;
+		ed = defining;
+		defining = ed->prev;
+		ed->prev = expansions;
+		expansions = ed;
+		ei = new_ExpInv();
+		ei->type = EXP_REP;
+		ei->def = ed;
+		ei->current = ed->line;
+		ei->emitting = ((ed->max_depth > 0) ? true : false);
+		list->uplevel(ed->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
+		ei->prev = istk->expansion;
+		istk->expansion = ei;
         free_tlist(origline);
         return DIRECTIVE_FOUND;
 
     case PP_EXITREP:
-        /*
-         * We must search along istk->expansion until we hit a
-         * macro-end marker for a macro with no name. Then we set
-         * its `in_progress' flag to 0.
-         */
-        list_for_each(l, istk->expansion)
-            if (l->finishes && !l->finishes->name)
-                break;
-
-        if (l)
-            l->finishes->in_progress = 1;
-        else
-            error(ERR_NONFATAL, "`%%exitrep' not within `%%rep' block");
+		if (defining != NULL) return NO_DIRECTIVE_FOUND;
+		/*
+		 * We must search along istk->expansion until we hit a
+		 * rep invocation. Then we disable the emitting state(s)
+		 * between exitrep and endrep.
+		 */
+		for (ei = istk->expansion; ei != NULL; ei = ei->prev) {
+			if (ei->type == EXP_REP) {
+				break;
+			}
+		}
+			
+		if (ei != NULL) {
+			/*
+			 * Set all invocations leading back to the rep
+			 * invocation to a non-emitting state.
+			 */
+			for (eei = istk->expansion; eei != ei; eei = eei->prev) {
+				eei->emitting = false;
+			}
+			eei->emitting = false;
+			eei->current = NULL;
+			eei->def->cur_depth = eei->def->max_depth;
+		} else {
+			error(ERR_NONFATAL, "`%%exitrep' not within `%%rep' block");
+		}
         free_tlist(origline);
         return DIRECTIVE_FOUND;
 
@@ -2965,6 +3116,7 @@ issue_error:
     case PP_IXDEFINE:
     case PP_DEFINE:
     case PP_IDEFINE:
+		if (defining != NULL) return NO_DIRECTIVE_FOUND;
         casesense = (i == PP_DEFINE || i == PP_XDEFINE);
 
         tline = tline->next;
@@ -3056,6 +3208,7 @@ issue_error:
         return DIRECTIVE_FOUND;
 
     case PP_UNDEF:
+		if (defining != NULL) return NO_DIRECTIVE_FOUND;
         tline = tline->next;
         skip_white_(tline);
         tline = expand_id(tline);
@@ -3079,6 +3232,7 @@ issue_error:
 
     case PP_DEFSTR:
     case PP_IDEFSTR:
+		if (defining != NULL) return NO_DIRECTIVE_FOUND;
         casesense = (i == PP_DEFSTR);
 
         tline = tline->next;
@@ -3120,6 +3274,7 @@ issue_error:
 
     case PP_DEFTOK:
     case PP_IDEFTOK:
+		if (defining != NULL) return NO_DIRECTIVE_FOUND;
         casesense = (i == PP_DEFTOK);
 
         tline = tline->next;
@@ -3166,6 +3321,7 @@ issue_error:
         return DIRECTIVE_FOUND;
 
     case PP_PATHSEARCH:
+		if (defining != NULL) return NO_DIRECTIVE_FOUND;
     {
         FILE *fp;
         StrList *xsl = NULL;
@@ -3232,6 +3388,7 @@ issue_error:
     }
 
     case PP_STRLEN:
+		if (defining != NULL) return NO_DIRECTIVE_FOUND;
         casesense = true;
 
         tline = tline->next;
@@ -3278,6 +3435,7 @@ issue_error:
         return DIRECTIVE_FOUND;
 
     case PP_STRCAT:
+		if (defining != NULL) return NO_DIRECTIVE_FOUND;
         casesense = true;
 
         tline = tline->next;
@@ -3339,6 +3497,7 @@ issue_error:
         return DIRECTIVE_FOUND;
 
     case PP_SUBSTR:
+		if (defining != NULL) return NO_DIRECTIVE_FOUND;
     {
         int64_t a1, a2;
         size_t len;
@@ -3437,6 +3596,7 @@ issue_error:
 
     case PP_ASSIGN:
     case PP_IASSIGN:
+		if (defining != NULL) return NO_DIRECTIVE_FOUND;
         casesense = (i == PP_ASSIGN);
 
         tline = tline->next;
@@ -3494,6 +3654,7 @@ issue_error:
         return DIRECTIVE_FOUND;
 
     case PP_LINE:
+		if (defining != NULL) return NO_DIRECTIVE_FOUND;
         /*
          * Syntax is `%line nnn[+mmm] [filename]'
          */
@@ -3684,12 +3845,12 @@ static bool paste_tokens(Token **head, bool handle_paste_tokens)
 /*
  * expands to a list of tokens from %{x:y}
  */
-static Token *expand_mmac_params_range(MMacro *mac, Token *tline, Token ***last)
+static Token *expand_mmac_params_range(ExpInv *ei, Token *tline, Token ***last)
 {
     Token *t = tline, **tt, *tm, *head;
     char *pos;
     int fst, lst, j, i;
-
+	
     pos = strchr(tline->text, ':');
     nasm_assert(pos);
 
@@ -3705,12 +3866,12 @@ static Token *expand_mmac_params_range(MMacro *mac, Token *tline, Token ***last)
         goto err;
 
     /* the values should be sane */
-    if ((fst > (int)mac->nparam || fst < (-(int)mac->nparam)) ||
-        (lst > (int)mac->nparam || lst < (-(int)mac->nparam)))
+    if ((fst > (int)ei->nparam || fst < (-(int)ei->nparam)) ||
+        (lst > (int)ei->nparam || lst < (-(int)ei->nparam)))
         goto err;
 
-    fst = fst < 0 ? fst + (int)mac->nparam + 1: fst;
-    lst = lst < 0 ? lst + (int)mac->nparam + 1: lst;
+    fst = fst < 0 ? fst + (int)ei->nparam + 1: fst;
+    lst = lst < 0 ? lst + (int)ei->nparam + 1: lst;
 
     /* counted from zero */
     fst--, lst--;
@@ -3718,15 +3879,15 @@ static Token *expand_mmac_params_range(MMacro *mac, Token *tline, Token ***last)
     /*
      * it will be at least one token
      */
-    tm = mac->params[(fst + mac->rotate) % mac->nparam];
+    tm = ei->params[(fst + ei->rotate) % ei->nparam];
     t = new_Token(NULL, tm->type, tm->text, 0);
     head = t, tt = &t->next;
     if (fst < lst) {
         for (i = fst + 1; i <= lst; i++) {
             t = new_Token(NULL, TOK_OTHER, ",", 0);
             *tt = t, tt = &t->next;
-            j = (i + mac->rotate) % mac->nparam;
-            tm = mac->params[j];
+            j = (i + ei->rotate) % ei->nparam;
+            tm = ei->params[j];
             t = new_Token(NULL, tm->type, tm->text, 0);
             *tt = t, tt = &t->next;
         }
@@ -3734,8 +3895,8 @@ static Token *expand_mmac_params_range(MMacro *mac, Token *tline, Token ***last)
         for (i = fst - 1; i >= lst; i--) {
             t = new_Token(NULL, TOK_OTHER, ",", 0);
             *tt = t, tt = &t->next;
-            j = (i + mac->rotate) % mac->nparam;
-            tm = mac->params[j];
+            j = (i + ei->rotate) % ei->nparam;
+            tm = ei->params[j];
             t = new_Token(NULL, tm->type, tm->text, 0);
             *tt = t, tt = &t->next;
         }
@@ -3774,15 +3935,17 @@ static Token *expand_mmac_params(Token * tline)
             char tmpbuf[30];
             unsigned int n;
             int i;
-            MMacro *mac;
+			ExpInv *ei;
 
             t = tline;
             tline = tline->next;
 
-            mac = istk->mstk;
-            while (mac && !mac->name)   /* avoid mistaking %reps for macros */
-                mac = mac->next_active;
-            if (!mac) {
+			for (ei = istk->expansion; ei != NULL; ei = ei->prev) {
+				if (ei->type == EXP_MMACRO) {
+					break;
+				}
+			}
+            if (ei == NULL) {
                 error(ERR_NONFATAL, "`%s': not in a macro call", t->text);
             } else {
                 pos = strchr(t->text, ':');
@@ -3793,24 +3956,29 @@ static Token *expand_mmac_params(Token * tline)
                          * forms %1, %-1, %+1, %%foo, %0.
                          */
                     case '0':
-                        type = TOK_NUMBER;
-                        snprintf(tmpbuf, sizeof(tmpbuf), "%d", mac->nparam);
-                        text = nasm_strdup(tmpbuf);
-                        break;
+						if ((strlen(t->text) > 2) && (t->text[2] == '0')) {
+							type = TOK_ID;
+							text = nasm_strdup(ei->label_text);
+						} else {
+							type = TOK_NUMBER;
+							snprintf(tmpbuf, sizeof(tmpbuf), "%d", ei->nparam);
+							text = nasm_strdup(tmpbuf);
+						}
+						break;
                     case '%':
                         type = TOK_ID;
                         snprintf(tmpbuf, sizeof(tmpbuf), "..@%"PRIu64".",
-                                 mac->unique);
+                                 ei->unique);
                         text = nasm_strcat(tmpbuf, t->text + 2);
                         break;
                     case '-':
                         n = atoi(t->text + 2) - 1;
-                        if (n >= mac->nparam)
+                        if (n >= ei->nparam)
                             tt = NULL;
                         else {
-                            if (mac->nparam > 1)
-                                n = (n + mac->rotate) % mac->nparam;
-                            tt = mac->params[n];
+                            if (ei->nparam > 1)
+                                n = (n + ei->rotate) % ei->nparam;
+                            tt = ei->params[n];
                         }
                         cc = find_cc(tt);
                         if (cc == -1) {
@@ -3831,12 +3999,12 @@ static Token *expand_mmac_params(Token * tline)
                         break;
                     case '+':
                         n = atoi(t->text + 2) - 1;
-                        if (n >= mac->nparam)
+                        if (n >= ei->nparam)
                             tt = NULL;
                         else {
-                            if (mac->nparam > 1)
-                                n = (n + mac->rotate) % mac->nparam;
-                            tt = mac->params[n];
+                            if (ei->nparam > 1)
+                                n = (n + ei->rotate) % ei->nparam;
+                            tt = ei->params[n];
                         }
                         cc = find_cc(tt);
                         if (cc == -1) {
@@ -3851,15 +4019,15 @@ static Token *expand_mmac_params(Token * tline)
                         break;
                     default:
                         n = atoi(t->text + 1) - 1;
-                        if (n >= mac->nparam)
+                        if (n >= ei->nparam)
                             tt = NULL;
                         else {
-                            if (mac->nparam > 1)
-                                n = (n + mac->rotate) % mac->nparam;
-                            tt = mac->params[n];
+                            if (ei->nparam > 1)
+                                n = (n + ei->rotate) % ei->nparam;
+                            tt = ei->params[n];
                         }
                         if (tt) {
-                            for (i = 0; i < mac->paramlen[n]; i++) {
+                            for (i = 0; i < ei->paramlen[n]; i++) {
                                 *tail = new_Token(NULL, tt->type, tt->text, 0);
                                 tail = &(*tail)->next;
                                 tt = tt->next;
@@ -3873,7 +4041,7 @@ static Token *expand_mmac_params(Token * tline)
                      * seems we have a parameters range here
                      */
                     Token *head, **last;
-                    head = expand_mmac_params_range(mac, t, &last);
+                    head = expand_mmac_params_range(ei, t, &last);
                     if (head != t) {
                         *tail = head;
                         *last = tline;
@@ -4318,19 +4486,19 @@ static Token *expand_id(Token * tline)
 
 /*
  * Determine whether the given line constitutes a multi-line macro
- * call, and return the MMacro structure called if so. Doesn't have
+ * call, and return the ExpDef structure called if so. Doesn't have
  * to check for an initial label - that's taken care of in
  * expand_mmacro - but must check numbers of parameters. Guaranteed
  * to be called with tline->type == TOK_ID, so the putative macro
  * name is easy to find.
  */
-static MMacro *is_mmacro(Token * tline, Token *** params_array)
+static ExpDef *is_mmacro(Token * tline, Token *** params_array)
 {
-    MMacro *head, *m;
+    ExpDef *head, *ed;
     Token **params;
     int nparam;
 
-    head = (MMacro *) hash_findix(&mmacros, tline->text);
+    head = (ExpDef *) hash_findix(&expdefs, tline->text);
 
     /*
      * Efficiency: first we see if any macro exists with the given
@@ -4338,10 +4506,10 @@ static MMacro *is_mmacro(Token * tline, Token *** params_array)
      * count the parameters, and then we look further along the
      * list if necessary to find the proper MMacro.
      */
-    list_for_each(m, head)
-        if (!mstrcmp(m->name, tline->text, m->casesense))
+    list_for_each(ed, head)
+        if (!mstrcmp(ed->name, tline->text, ed->casesense))
             break;
-    if (!m)
+    if (!ed)
         return NULL;
 
     /*
@@ -4351,36 +4519,23 @@ static MMacro *is_mmacro(Token * tline, Token *** params_array)
     count_mmac_params(tline->next, &nparam, &params);
 
     /*
-     * So we know how many parameters we've got. Find the MMacro
+     * So we know how many parameters we've got. Find the ExpDef
      * structure that handles this number.
      */
-    while (m) {
-        if (m->nparam_min <= nparam
-            && (m->plus || nparam <= m->nparam_max)) {
-            /*
-             * This one is right. Just check if cycle removal
-             * prohibits us using it before we actually celebrate...
-             */
-            if (m->in_progress > m->max_depth) {
-                if (m->max_depth > 0) {
-                    error(ERR_WARNING,
-                          "reached maximum recursion depth of %i",
-                          m->max_depth);
-                }
-                nasm_free(params);
-                return NULL;
-            }
+    while (ed) {
+        if (ed->nparam_min <= nparam
+            && (ed->plus || nparam <= ed->nparam_max)) {
             /*
              * It's right, and we can use it. Add its default
              * parameters to the end of our list if necessary.
              */
-            if (m->defaults && nparam < m->nparam_min + m->ndefs) {
+            if (ed->defaults && nparam < ed->nparam_min + ed->ndefs) {
                 params =
                     nasm_realloc(params,
-                                 ((m->nparam_min + m->ndefs +
+                                 ((ed->nparam_min + ed->ndefs +
                                    1) * sizeof(*params)));
-                while (nparam < m->nparam_min + m->ndefs) {
-                    params[nparam] = m->defaults[nparam - m->nparam_min];
+                while (nparam < ed->nparam_min + ed->ndefs) {
+                    params[nparam] = ed->defaults[nparam - ed->nparam_min];
                     nparam++;
                 }
             }
@@ -4389,8 +4544,8 @@ static MMacro *is_mmacro(Token * tline, Token *** params_array)
              * we're in Plus mode), ignore parameters beyond
              * nparam_max.
              */
-            if (m->plus && nparam > m->nparam_max)
-                nparam = m->nparam_max;
+            if (ed->plus && nparam > ed->nparam_max)
+                nparam = ed->nparam_max;
             /*
              * Then terminate the parameter list, and leave.
              */
@@ -4400,14 +4555,14 @@ static MMacro *is_mmacro(Token * tline, Token *** params_array)
             }
             params[nparam] = NULL;
             *params_array = params;
-            return m;
+            return ed;
         }
         /*
          * This one wasn't right: look for the next one with the
          * same name.
          */
-        list_for_each(m, m->next)
-            if (!mstrcmp(m->name, tline->text, m->casesense))
+        list_for_each(ed, ed->next)
+            if (!mstrcmp(ed->name, tline->text, ed->casesense))
                 break;
     }
 
@@ -4422,51 +4577,6 @@ static MMacro *is_mmacro(Token * tline, Token *** params_array)
     return NULL;
 }
 
-
-/*
- * Save MMacro invocation specific fields in
- * preparation for a recursive macro expansion
- */
-static void push_mmacro(MMacro *m)
-{
-    MMacroInvocation *i;
-
-    i = nasm_malloc(sizeof(MMacroInvocation));
-    i->prev = m->prev;
-    i->params = m->params;
-    i->iline = m->iline;
-    i->nparam = m->nparam;
-    i->rotate = m->rotate;
-    i->paramlen = m->paramlen;
-    i->unique = m->unique;
-    i->condcnt = m->condcnt;
-    m->prev = i;
-}
-
-
-/*
- * Restore MMacro invocation specific fields that were
- * saved during a previous recursive macro expansion
- */
-static void pop_mmacro(MMacro *m)
-{
-    MMacroInvocation *i;
-
-    if (m->prev) {
-        i = m->prev;
-        m->prev = i->prev;
-        m->params = i->params;
-        m->iline = i->iline;
-        m->nparam = i->nparam;
-        m->rotate = i->rotate;
-        m->paramlen = i->paramlen;
-        m->unique = i->unique;
-        m->condcnt = i->condcnt;
-        nasm_free(i);
-    }
-}
-
-
 /*
  * Expand the multi-line macro call made by the given line, if
  * there is one to be expanded. If there is, push the expansion on
@@ -4478,8 +4588,9 @@ static int expand_mmacro(Token * tline)
     Token *label = NULL;
     int dont_prepend = 0;
     Token **params, *t, *mtok, *tt;
-    MMacro *m;
-    Line *l, *ll;
+    Line *l;
+	ExpDef *ed;
+	ExpInv *ei;
     int i, nparam, *paramlen;
     const char *mname;
 
@@ -4489,8 +4600,8 @@ static int expand_mmacro(Token * tline)
     if (!tok_type_(t, TOK_ID) && !tok_type_(t, TOK_PREPROC_ID))
         return 0;
     mtok = t;
-    m = is_mmacro(t, &params);
-    if (m) {
+	ed = is_mmacro(t, &params);
+    if (ed != NULL) {
         mname = t->text;
     } else {
         Token *last;
@@ -4510,7 +4621,7 @@ static int expand_mmacro(Token * tline)
             if (tok_type_(t, TOK_WHITESPACE))
                 last = t, t = t->next;
         }
-        if (!tok_type_(t, TOK_ID) || !(m = is_mmacro(t, &params)))
+        if (!tok_type_(t, TOK_ID) || !(ed = is_mmacro(t, &params)))
             return 0;
         last->next = NULL;
         mname = t->text;
@@ -4527,7 +4638,7 @@ static int expand_mmacro(Token * tline)
 
     for (i = 0; params[i]; i++) {
         int brace = false;
-        int comma = (!m->plus || i < nparam - 1);
+        int comma = (!ed->plus || i < nparam - 1);
 
         t = params[i];
         skip_white_(t);
@@ -4548,6 +4659,17 @@ static int expand_mmacro(Token * tline)
         }
     }
 
+	if (ed->cur_depth >= ed->max_depth) {
+		if (ed->max_depth > 1) {
+			error(ERR_WARNING,
+				  "reached maximum macro recursion depth of %i for %s",
+				  ed->max_depth,ed->name);
+		}
+		return 0;
+	} else {
+		ed->cur_depth ++;
+	}
+
     /*
      * OK, we have a MMacro structure together with a set of
      * parameters. We must now go through the expansion and push
@@ -4561,42 +4683,34 @@ static int expand_mmacro(Token * tline)
      * macro as in progress, and set up its invocation-specific
      * variables.
      */
-    ll = nasm_malloc(sizeof(Line));
-    ll->next = istk->expansion;
-    ll->finishes = m;
-    ll->first = NULL;
-    istk->expansion = ll;
-
-    /*
-     * Save the previous MMacro expansion in the case of
-     * macro recursion
-     */
-    if (m->max_depth && m->in_progress)
-        push_mmacro(m);
-
-    m->in_progress ++;
-    m->params = params;
-    m->iline = tline;
-    m->nparam = nparam;
-    m->rotate = 0;
-    m->paramlen = paramlen;
-    m->unique = unique++;
-    m->lineno = 0;
-    m->condcnt = 0;
-
-    m->next_active = istk->mstk;
-    istk->mstk = m;
-
+	ei = new_ExpInv();
+	ei->type = EXP_MMACRO;
+	ei->def = ed;
+//	ei->label = label;
+	ei->label_text = detoken(label, false);
+	ei->current = ed->line;
+	ei->emitting = true;
+//	ei->iline = tline;
+	ei->params = params;
+	ei->nparam = nparam;
+	ei->rotate = 0;
+	ei->paramlen = paramlen;
+	ei->lineno = 0;
+
+	ei->prev = istk->expansion;
+	istk->expansion = ei;
+	
+	/***** todo: relocate %? (Q) and %?? (QQ); %00 already relocated *****/
+	/*
     list_for_each(l, m->expansion) {
         Token **tail;
 
-        ll = nasm_malloc(sizeof(Line));
-        ll->finishes = NULL;
-        ll->next = istk->expansion;
-        istk->expansion = ll;
-        tail = &ll->first;
+        l = new_Line();
+        l->next = istk->expansion;
+        istk->expansion = l;
+        tail = &l->first;
 
-        list_for_each(t, l->first) {
+        list_for_each(t, ei->current->first) {
             Token *x = t;
             switch (t->type) {
             case TOK_PREPROC_Q:
@@ -4612,7 +4726,7 @@ static int expand_mmacro(Token * tline)
                     if (!x)
                         continue;
                 }
-                /* fall through */
+                // fall through
             default:
                 tt = *tail = new_Token(NULL, x->type, x->text, 0);
                 break;
@@ -4620,7 +4734,7 @@ static int expand_mmacro(Token * tline)
             tail = &tt->next;
         }
         *tail = NULL;
-    }
+    */
 
     /*
      * If we had a label, push it on as the first line of
@@ -4630,11 +4744,9 @@ static int expand_mmacro(Token * tline)
         if (dont_prepend < 0)
             free_tlist(startline);
         else {
-            ll = nasm_malloc(sizeof(Line));
-            ll->finishes = NULL;
-            ll->next = istk->expansion;
-            istk->expansion = ll;
-            ll->first = startline;
+            l = new_Line();
+            ei->label = l;
+            l->first = startline;
             if (!dont_prepend) {
                 while (label->next)
                     label = label->next;
@@ -4643,7 +4755,7 @@ static int expand_mmacro(Token * tline)
         }
     }
 
-    list->uplevel(m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
+    list->uplevel(ed->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
 
     return 1;
 }
@@ -4655,11 +4767,15 @@ static void verror(int severity, const char *fmt, va_list arg)
 
     vsnprintf(buff, sizeof(buff), fmt, arg);
 
-    if (istk && istk->mstk && istk->mstk->name)
-        nasm_error(severity, "(%s:%d) %s", istk->mstk->name,
-               istk->mstk->lineno, buff);
-    else
+    if ((istk != NULL) &&
+		(istk->expansion != NULL) &&
+		(istk->expansion->type == EXP_MMACRO)) {
+		ExpDef *ed = istk->expansion->def;
+        nasm_error(severity, "(%s:%d) %s", ed->name,
+				   istk->expansion->lineno, buff);
+    } else {
         nasm_error(severity, "%s", buff);
+	}
 }
 
 /*
@@ -4671,7 +4787,10 @@ static void error(int severity, const char *fmt, ...)
     va_list arg;
 
     /* If we're in a dead branch of IF or something like it, ignore the error */
-    if (istk && istk->conds && !emitting(istk->conds->state))
+	if ((istk != NULL) &&
+		(istk->expansion != NULL) &&
+		(istk->expansion->type == EXP_IF) &&
+		!emitting(istk->expansion->def->state))
         return;
 
     va_start(arg, fmt);
@@ -4690,7 +4809,10 @@ static void error_precond(int severity, const char *fmt, ...)
     va_list arg;
 
     /* Only ignore the error if it's really in a dead branch */
-    if (istk && istk->conds && istk->conds->state == COND_NEVER)
+	if ((istk != NULL) &&
+		(istk->expansion != NULL) &&
+		(istk->expansion->type == EXP_IF) &&
+		(istk->expansion->def->state == COND_NEVER))
         return;
 
     va_start(arg, fmt);
@@ -4706,9 +4828,7 @@ pp_reset(char *file, int apass, ListGen * listgen, StrList **deplist)
     cstk = NULL;
     istk = nasm_malloc(sizeof(Include));
     istk->next = NULL;
-    istk->conds = NULL;
     istk->expansion = NULL;
-    istk->mstk = NULL;
     istk->fp = fopen(file, "r");
     istk->fname = NULL;
     src_set_fname(nasm_strdup(file));
@@ -4763,114 +4883,79 @@ static char *pp_getline(void)
 {
     char *line;
     Token *tline;
-
+	
     while (1) {
         /*
-         * Fetch a tokenized line, either from the macro-expansion
+         * Fetch a tokenized line, either from the expansion
          * buffer or from the input file.
          */
         tline = NULL;
-        while (istk->expansion && istk->expansion->finishes) {
-            Line *l = istk->expansion;
-            if (!l->finishes->name && l->finishes->in_progress > 1) {
-                Line *ll;
-
-                /*
-                 * This is a macro-end marker for a macro with no
-                 * name, which means it's not really a macro at all
-                 * but a %rep block, and the `in_progress' field is
-                 * more than 1, meaning that we still need to
-                 * repeat. (1 means the natural last repetition; 0
-                 * means termination by %exitrep.) We have
-                 * therefore expanded up to the %endrep, and must
-                 * push the whole block on to the expansion buffer
-                 * again. We don't bother to remove the macro-end
-                 * marker: we'd only have to generate another one
-                 * if we did.
-                 */
-                l->finishes->in_progress--;
-                list_for_each(l, l->finishes->expansion) {
-                    Token *t, *tt, **tail;
-
-                    ll = nasm_malloc(sizeof(Line));
-                    ll->next = istk->expansion;
-                    ll->finishes = NULL;
-                    ll->first = NULL;
-                    tail = &ll->first;
-
-                    list_for_each(t, l->first) {
-                        if (t->text || t->type == TOK_WHITESPACE) {
-                            tt = *tail = new_Token(NULL, t->type, t->text, 0);
-                            tail = &tt->next;
-                        }
-                    }
-
-                    istk->expansion = ll;
-                }
-            } else {
-                /*
-                 * Check whether a `%rep' was started and not ended
-                 * within this macro expansion. This can happen and
-                 * should be detected. It's a fatal error because
-                 * I'm too confused to work out how to recover
-                 * sensibly from it.
-                 */
-                if (defining) {
-                    if (defining->name)
-                        error(ERR_PANIC,
-                              "defining with name in expansion");
-                    else if (istk->mstk->name)
-                        error(ERR_FATAL,
-                              "`%%rep' without `%%endrep' within"
-                              " expansion of macro `%s'",
-                              istk->mstk->name);
-                }
-
-                /*
-                 * FIXME:  investigate the relationship at this point between
-                 * istk->mstk and l->finishes
-                 */
-                {
-                    MMacro *m = istk->mstk;
-                    istk->mstk = m->next_active;
-                    if (m->name) {
-                        /*
-                         * This was a real macro call, not a %rep, and
-                         * therefore the parameter information needs to
-                         * be freed.
-                         */
-                        if (m->prev) {
-                            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;
-                        }
-                    } else
-                        free_mmacro(m);
-                }
-                istk->expansion = l->next;
-                nasm_free(l);
-                list->downlevel(LIST_MACRO);
-            }
-        }
+		
         while (1) {             /* until we get a line we can use */
-
-            if (istk->expansion) {      /* from a macro expansion */
-                char *p;
-                Line *l = istk->expansion;
-                if (istk->mstk)
-                    istk->mstk->lineno++;
-                tline = l->first;
-                istk->expansion = l->next;
-                nasm_free(l);
-                p = detoken(tline, false);
-                list->line(LIST_MACRO, p);
-                nasm_free(p);
-                break;
-            }
+			/*
+			 * Fetch a tokenized line from the expansion buffer
+			 */
+            if (istk->expansion != NULL) {
+				
+				ExpInv *e = istk->expansion;
+				if (e->current != NULL) {
+					if (e->emitting == false) {
+						e->current = NULL;
+						continue;
+					}
+					Line *l = NULL;
+					l = e->current;
+					e->current = l->next;
+					e->lineno++;
+					tline = copy_Token(l->first);
+					if (((e->type == EXP_REP) || (e->type == EXP_MMACRO))
+						&& (e->def->nolist == false)) {
+						char *p = detoken(tline, false);
+						list->line(LIST_MACRO, p);
+						nasm_free(p);
+					}
+					break;
+				} else if ((e->type == EXP_REP) &&
+						   (e->def->cur_depth < e->def->max_depth)) {
+					e->def->cur_depth ++;
+					e->current = e->def->line;
+					e->lineno = 0;
+					continue;
+				} else {
+					istk->expansion = e->prev;
+					ExpDef *ed = e->def;
+					if (ed != NULL) {
+						if (ed->cur_depth > 0) {
+							ed->cur_depth --;
+						} else if ((ed->type != EXP_MMACRO) && (ed->type != EXP_IF)) {
+							/***** should this really be right here??? *****/
+							/*
+							Line *l = NULL, *ll = NULL;
+							for (l = ed->line; l != NULL;) {
+								if (l->first != NULL) {
+									free_tlist(l->first);
+									l->first = NULL;
+								}
+								ll = l;
+								l = l->next;
+								nasm_free(ll);
+							}
+							expansions = ed->prev;
+							nasm_free(ed);
+							*/
+						}
+						if ((e->type == EXP_REP) || (e->type == EXP_MMACRO)) {
+							list->downlevel(LIST_MACRO);
+						}
+					}
+					nasm_free(e);
+					continue;
+				}
+			}
+
+			/*
+			 * Read in line from input and tokenize
+			 */
             line = read_line();
             if (line) {         /* from the current input file */
                 line = prepreproc(line);
@@ -4878,15 +4963,17 @@ static char *pp_getline(void)
                 nasm_free(line);
                 break;
             }
+			
             /*
              * The current file has ended; work down the istk
              */
             {
                 Include *i = istk;
                 fclose(i->fp);
-                if (i->conds)
-                    error(ERR_FATAL,
-                          "expected `%%endif' before end of file");
+				if (i->expansion != NULL) {
+					error(ERR_FATAL,
+						  "end of file while still in an expansion");
+				}
                 /* only set line and file name if there's a next node */
                 if (i->next) {
                     src_set_linnum(i->lineno);
@@ -4895,64 +4982,50 @@ static char *pp_getline(void)
                 istk = i->next;
                 list->downlevel(LIST_INCLUDE);
                 nasm_free(i);
-                if (!istk)
+                if (istk == NULL) {
                     return NULL;
-                if (istk->expansion && istk->expansion->finishes)
-                    break;
+				}
+				continue;
             }
-        }
-
-        /*
-         * We must expand MMacro parameters and MMacro-local labels
-         * _before_ we plunge into directive processing, to cope
-         * with things like `%define something %1' such as STRUC
-         * uses. Unless we're _defining_ a MMacro, in which case
-         * those tokens should be left alone to go into the
-         * definition; and unless we're in a non-emitting
-         * condition, in which case we don't want to meddle with
-         * anything.
-         */
-        if (!defining && !(istk->conds && !emitting(istk->conds->state))
-            && !(istk->mstk && !istk->mstk->in_progress)) {
-            tline = expand_mmac_params(tline);
-        }
-
+		}
+		
+		if (defining == NULL) {
+			tline = expand_mmac_params(tline);
+		}
+		
         /*
          * Check the line to see if it's a preprocessor directive.
          */
         if (do_directive(tline) == DIRECTIVE_FOUND) {
             continue;
-        } else if (defining) {
+        } else if (defining != NULL) {
             /*
-             * We're defining a multi-line macro. We emit nothing
-             * at all, and just
-             * shove the tokenized line on to the macro definition.
+             * We're defining an expansion. We emit nothing at all,
+			 * and just shove the tokenized line on to the definition.
              */
-            Line *l = nasm_malloc(sizeof(Line));
-            l->next = defining->expansion;
-            l->first = tline;
-            l->finishes = NULL;
-            defining->expansion = l;
+			if (defining->ignoring == false) {
+				Line *l = new_Line();
+				l->first = tline;
+				if (defining->line == NULL) {
+					defining->line = l;
+					defining->last = l;
+				} else {
+					defining->last->next = l;
+					defining->last = l;
+				}
+			} else {
+				//free_tlist(tline);	/***** sanity check: is this supposed to be here? *****/
+			}
             continue;
-        } else if (istk->conds && !emitting(istk->conds->state)) {
+        } else if ((istk->expansion != NULL) &&
+				   (istk->expansion->emitting != true)) {
             /*
-             * We're in a non-emitting branch of a condition block.
+             * We're in a non-emitting branch of an expansion.
              * Emit nothing at all, not even a blank line: when we
-             * emerge from the condition we'll give a line-number
+             * emerge from the expansion we'll give a line-number
              * directive so we keep our place correctly.
              */
-            free_tlist(tline);
-            continue;
-        } else if (istk->mstk && !istk->mstk->in_progress) {
-            /*
-             * We're in a %rep block which has been terminated, so
-             * we're walking through to the %endrep without
-             * emitting anything. Emit nothing at all, not even a
-             * blank line: when we emerge from the %rep block we'll
-             * give a line-number directive so we keep our place
-             * correctly.
-             */
-            free_tlist(tline);
+			free_tlist(tline);
             continue;
         } else {
             tline = expand_smacro(tline);
@@ -4960,36 +5033,28 @@ static char *pp_getline(void)
                 /*
                  * De-tokenize the line again, and emit it.
                  */
-                line = detoken(tline, true);
-                free_tlist(tline);
+				line = detoken(tline, true);
+				free_tlist(tline);
                 break;
             } else {
                 continue;       /* expand_mmacro calls free_tlist */
             }
         }
-    }
-
-    return line;
+	}
+	return line;
 }
 
 static void pp_cleanup(int pass)
 {
-    if (defining) {
-        if (defining->name) {
-            error(ERR_NONFATAL,
-                  "end of file while still defining macro `%s'",
-                  defining->name);
-        } else {
-            error(ERR_NONFATAL, "end of file while still in %%rep");
-        }
-
-        free_mmacro(defining);
-        defining = NULL;
+    if (defining != NULL) {
+		error(ERR_NONFATAL, "end of file while still defining an expansion");
+		nasm_free(defining);	/***** todo: free everything to avoid mem leaks *****/
+		defining = NULL;
     }
-    while (cstk)
+    while (cstk != NULL)
         ctx_pop();
     free_macros();
-    while (istk) {
+    while (istk != NULL) {
         Include *i = istk;
         istk = istk->next;
         fclose(i->fp);
@@ -5039,10 +5104,9 @@ void pp_pre_include(char *fname)
     space = new_Token(name, TOK_WHITESPACE, NULL, 0);
     inc = new_Token(space, TOK_PREPROC_ID, "%include", 0);
 
-    l = nasm_malloc(sizeof(Line));
+    l = new_Line();
     l->next = predef;
     l->first = inc;
-    l->finishes = NULL;
     predef = l;
 }
 
@@ -5061,10 +5125,9 @@ void pp_pre_define(char *definition)
     if (equals)
         *equals = '=';
 
-    l = nasm_malloc(sizeof(Line));
+    l = new_Line();
     l->next = predef;
     l->first = def;
-    l->finishes = NULL;
     predef = l;
 }
 
@@ -5077,18 +5140,15 @@ void pp_pre_undefine(char *definition)
     def = new_Token(space, TOK_PREPROC_ID, "%undef", 0);
     space->next = tokenize(definition);
 
-    l = nasm_malloc(sizeof(Line));
+    l = new_Line();
     l->next = predef;
     l->first = def;
-    l->finishes = NULL;
     predef = l;
 }
 
 /*
- * Added by Keith Kanios:
- *
  * This function is used to assist with "runtime" preprocessor
- * directives. (e.g. pp_runtime("%define __BITS__ 64");)
+ * directives, e.g. pp_runtime("%define __BITS__ 64");
  *
  * ERRORS ARE IGNORED HERE, SO MAKE COMPLETELY SURE THAT YOU
  * PASS A VALID STRING TO THIS FUNCTION!!!!!


More information about the Nasm-commits mailing list