| Index: third_party/yasm/patched-yasm/modules/preprocs/nasm/nasm-pp.c
|
| ===================================================================
|
| --- third_party/yasm/patched-yasm/modules/preprocs/nasm/nasm-pp.c (revision 71129)
|
| +++ third_party/yasm/patched-yasm/modules/preprocs/nasm/nasm-pp.c (working copy)
|
| @@ -63,6 +63,7 @@
|
| {
|
| SMacro *next;
|
| char *name;
|
| + int level;
|
| int casesense;
|
| int nparam;
|
| int in_progress;
|
| @@ -276,14 +277,14 @@
|
| "%elifid", "%elifidn", "%elifidni", "%elifmacro", "%elifnctx", "%elifndef",
|
| "%elifnid", "%elifnidn", "%elifnidni", "%elifnmacro", "%elifnnum", "%elifnstr",
|
| "%elifnum", "%elifstr", "%else", "%endif", "%endm", "%endmacro",
|
| - "%endrep", "%error", "%exitrep", "%iassign", "%idefine", "%if",
|
| + "%endrep", "%endscope", "%error", "%exitrep", "%iassign", "%idefine", "%if",
|
| "%ifctx", "%ifdef", "%ifid", "%ifidn", "%ifidni", "%ifmacro", "%ifnctx",
|
| "%ifndef", "%ifnid", "%ifnidn", "%ifnidni", "%ifnmacro", "%ifnnum",
|
| "%ifnstr", "%ifnum", "%ifstr", "%imacro", "%include",
|
| "%ixdefine", "%line",
|
| "%local",
|
| "%macro", "%pop", "%push", "%rep", "%repl", "%rotate",
|
| - "%stacksize",
|
| + "%scope", "%stacksize",
|
| "%strlen", "%substr", "%undef", "%xdefine"
|
| };
|
| enum
|
| @@ -293,14 +294,14 @@
|
| PP_ELIFID, PP_ELIFIDN, PP_ELIFIDNI, PP_ELIFMACRO, PP_ELIFNCTX, PP_ELIFNDEF,
|
| PP_ELIFNID, PP_ELIFNIDN, PP_ELIFNIDNI, PP_ELIFNMACRO, PP_ELIFNNUM, PP_ELIFNSTR,
|
| PP_ELIFNUM, PP_ELIFSTR, PP_ELSE, PP_ENDIF, PP_ENDM, PP_ENDMACRO,
|
| - PP_ENDREP, PP_ERROR, PP_EXITREP, PP_IASSIGN, PP_IDEFINE, PP_IF,
|
| + PP_ENDREP, PP_ENDSCOPE, PP_ERROR, PP_EXITREP, PP_IASSIGN, PP_IDEFINE, PP_IF,
|
| PP_IFCTX, PP_IFDEF, PP_IFID, PP_IFIDN, PP_IFIDNI, PP_IFMACRO, PP_IFNCTX,
|
| PP_IFNDEF, PP_IFNID, PP_IFNIDN, PP_IFNIDNI, PP_IFNMACRO, PP_IFNNUM,
|
| PP_IFNSTR, PP_IFNUM, PP_IFSTR, PP_IMACRO, PP_INCLUDE,
|
| PP_IXDEFINE, PP_LINE,
|
| PP_LOCAL,
|
| PP_MACRO, PP_POP, PP_PUSH, PP_REP, PP_REPL, PP_ROTATE,
|
| - PP_STACKSIZE,
|
| + PP_SCOPE, PP_STACKSIZE,
|
| PP_STRLEN, PP_SUBSTR, PP_UNDEF, PP_XDEFINE
|
| };
|
|
|
| @@ -338,6 +339,7 @@
|
| static const char *StackPointer = "ebp";
|
| static int ArgOffset = 8;
|
| static int LocalOffset = 4;
|
| +static int Level = 0;
|
|
|
|
|
| static Context *cstk;
|
| @@ -538,13 +540,10 @@
|
| char *p, *oldline, oldchar, *q, oldchar2;
|
| TMEndItem *end;
|
|
|
| - if ((p = strchr(line, ';')))
|
| - *p = '\0';
|
| -
|
| p = line;
|
|
|
| /* Skip whitespace */
|
| - while (isspace(*p) && *p != 0)
|
| + while (isspace(*p) && *p != 0 && *p != ';')
|
| p++;
|
|
|
| /* Ignore nasm directives */
|
| @@ -553,7 +552,7 @@
|
|
|
| /* Binary search for the directive name */
|
| len = 0;
|
| - while (!isspace(p[len]) && p[len] != 0)
|
| + while (!isspace(p[len]) && p[len] != 0 && p[len] != ';')
|
| len++;
|
| if (!len)
|
| return line;
|
| @@ -871,10 +870,10 @@
|
| /* Skip whitespaces */
|
| while (isspace(*q) && *q)
|
| q++;
|
| - while (*q) {
|
| + while (*q && *q != ';') {
|
| p = q;
|
| - for (; *q && *q != ':' && !isspace(*q); q++);
|
| - if (!*q)
|
| + for (; *q && *q != ';' && *q != ':' && !isspace(*q); q++);
|
| + if (!*q || *q == ';')
|
| break;
|
| /* segment register name */
|
| for (assume = TAssumes; assume->segreg; assume++)
|
| @@ -888,20 +887,22 @@
|
| assume->segreg = nasm_strndup(p, q-p);
|
| assume[1].segreg = NULL;
|
| }
|
| - for (; *q && *q != ':' && isspace(*q); q++);
|
| + for (; *q && *q != ';' && *q != ':' && isspace(*q); q++);
|
| if (*q != ':')
|
| error(ERR_FATAL, "expected `:' instead of `%c'", *q);
|
| for (q++; *q && isspace(*q); q++);
|
|
|
| /* segment name */
|
| p = q;
|
| - for (; *q && *q != ',' && !isspace(*q); q++);
|
| + for (; *q && *q != ';' && *q != ',' && !isspace(*q); q++);
|
| assume->segment = nasm_strndup(p, q-p);
|
| for (; *q && isspace(*q); q++);
|
| - if (*q && *q != ',')
|
| + if (*q && *q != ';' && *q != ',')
|
| error(ERR_FATAL, "expected `,' instead of `%c'", *q);
|
|
|
| - for (q++; *q && isspace(*q); q++);
|
| + if (*q && *q != ';')
|
| + q++;
|
| + for (; *q && isspace(*q); q++);
|
| }
|
| TAssumes[i].segreg = NULL;
|
| TAssumes = nasm_realloc(TAssumes, (i+1)*sizeof(*TAssumes));
|
| @@ -1894,6 +1895,7 @@
|
| int nocase)
|
| {
|
| SMacro *m;
|
| + int highest_level = -1;
|
|
|
| if (ctx)
|
| m = ctx->localmac;
|
| @@ -1911,8 +1913,9 @@
|
| while (m)
|
| {
|
| if (!mstrcmp(m->name, name, m->casesense && nocase) &&
|
| - (nparam <= 0 || m->nparam == 0 || nparam == m->nparam))
|
| + (nparam <= 0 || m->nparam == 0 || nparam == m->nparam) && (highest_level < 0 || m->level > highest_level))
|
| {
|
| + highest_level = m->level;
|
| if (defn)
|
| {
|
| if (nparam == m->nparam || nparam == -1)
|
| @@ -1920,12 +1923,11 @@
|
| else
|
| *defn = NULL;
|
| }
|
| - return TRUE;
|
| }
|
| m = m->next;
|
| }
|
|
|
| - return FALSE;
|
| + return highest_level >= 0;
|
| }
|
|
|
| /*
|
| @@ -2791,6 +2793,68 @@
|
| free_tlist(origline);
|
| break;
|
|
|
| + case PP_SCOPE:
|
| + if (tline->next)
|
| + error(ERR_WARNING, "trailing garbage after `%%scope' ignored");
|
| + Level++;
|
| + free_tlist(origline);
|
| + break;
|
| +
|
| + case PP_ENDSCOPE:
|
| + if (tline->next)
|
| + error(ERR_WARNING, "trailing garbage after `%%endscope' ignored");
|
| + if (!Level)
|
| + error(ERR_NONFATAL,
|
| + "`%%endscope': already popped all levels");
|
| + else
|
| + {
|
| + for (k = 0; k < NHASH; k++)
|
| + {
|
| + SMacro **smlast = &smacros[k];
|
| + smac = smacros[k];
|
| + while (smac)
|
| + {
|
| + if (smac->level < Level)
|
| + {
|
| + smlast = &smac->next;
|
| + smac = smac->next;
|
| + }
|
| + else
|
| + {
|
| + *smlast = smac->next;
|
| + nasm_free(smac->name);
|
| + free_tlist(smac->expansion);
|
| + nasm_free(smac);
|
| + smac = *smlast;
|
| + }
|
| + }
|
| + }
|
| + for (ctx = cstk; ctx; ctx = ctx->next)
|
| + {
|
| + SMacro **smlast = &ctx->localmac;
|
| + smac = ctx->localmac;
|
| + while (smac)
|
| + {
|
| + if (smac->level < Level)
|
| + {
|
| + smlast = &smac->next;
|
| + smac = smac->next;
|
| + }
|
| + else
|
| + {
|
| + *smlast = smac->next;
|
| + nasm_free(smac->name);
|
| + free_tlist(smac->expansion);
|
| + nasm_free(smac);
|
| + smac = *smlast;
|
| + }
|
| + }
|
| + }
|
| + Level--;
|
| + }
|
| + free_tlist(origline);
|
| + break;
|
| +
|
| case PP_ERROR:
|
| tline->next = expand_smacro(tline->next);
|
| tline = tline->next;
|
| @@ -3315,16 +3379,22 @@
|
| free_tlist(macro_start);
|
| return DIRECTIVE_FOUND;
|
| }
|
| - else
|
| + else if (smac->level == Level)
|
| {
|
| /*
|
| - * We're redefining, so we have to take over an
|
| - * existing SMacro structure. This means freeing
|
| - * what was already in it.
|
| + * We're redefining in the same level, so we have to
|
| + * take over an existing SMacro structure. This means
|
| + * freeing what was already in it.
|
| */
|
| nasm_free(smac->name);
|
| free_tlist(smac->expansion);
|
| }
|
| + else
|
| + {
|
| + smac = nasm_malloc(sizeof(SMacro));
|
| + smac->next = *smhead;
|
| + *smhead = smac;
|
| + }
|
| }
|
| else
|
| {
|
| @@ -3335,6 +3405,7 @@
|
| smac->name = nasm_strdup(mname);
|
| smac->casesense = ((i == PP_DEFINE) || (i == PP_XDEFINE));
|
| smac->nparam = nparam;
|
| + smac->level = Level;
|
| smac->expansion = macro_start;
|
| smac->in_progress = FALSE;
|
| free_tlist(origline);
|
| @@ -3459,6 +3530,7 @@
|
| smac->name = nasm_strdup(mname);
|
| smac->casesense = (i == PP_STRLEN);
|
| smac->nparam = 0;
|
| + smac->level = 0;
|
| smac->expansion = macro_start;
|
| smac->in_progress = FALSE;
|
| free_tlist(tline);
|
| @@ -3569,6 +3641,7 @@
|
| smac->name = nasm_strdup(mname);
|
| smac->casesense = (i == PP_SUBSTR);
|
| smac->nparam = 0;
|
| + smac->level = 0;
|
| smac->expansion = macro_start;
|
| smac->in_progress = FALSE;
|
| free_tlist(tline);
|
| @@ -3664,6 +3737,7 @@
|
| smac->name = nasm_strdup(mname);
|
| smac->casesense = (i == PP_ASSIGN);
|
| smac->nparam = 0;
|
| + smac->level = 0;
|
| smac->expansion = macro_start;
|
| smac->in_progress = FALSE;
|
| free_tlist(origline);
|
| @@ -3784,105 +3858,51 @@
|
| char *text = NULL;
|
| int type = 0, cc; /* type = 0 to placate optimisers */
|
| char tmpbuf[30];
|
| + char *second_text = NULL;
|
| int n, i;
|
| MMacro *mac;
|
|
|
| t = tline;
|
| tline = tline->next;
|
|
|
| + second_text = strchr(t->text, ':');
|
| +
|
| mac = istk->mstk;
|
| while (mac && !mac->name) /* avoid mistaking %reps for macros */
|
| mac = mac->next_active;
|
| if (!mac)
|
| error(ERR_NONFATAL, "`%s': not in a macro call", t->text);
|
| else
|
| - switch (t->text[1])
|
| + {
|
| + if (second_text)
|
| {
|
| - /*
|
| - * We have to make a substitution of one of the
|
| - * forms %1, %-1, %+1, %%foo, %0.
|
| - */
|
| - case '0':
|
| - type = TOK_NUMBER;
|
| - sprintf(tmpbuf, "%ld", mac->nparam);
|
| - text = nasm_strdup(tmpbuf);
|
| - break;
|
| - case '%':
|
| - type = TOK_ID;
|
| - sprintf(tmpbuf, "..@%lu.", mac->unique);
|
| - text = nasm_strcat(tmpbuf, t->text + 2);
|
| - break;
|
| - case '-':
|
| - n = atoi(t->text + 2) - 1;
|
| - if (n >= mac->nparam)
|
| + int end = atoi(second_text+1)-1;
|
| + int is_fst = 1;
|
| + int k;
|
| + n = atoi(t->text + 1)-1;
|
| + if (end < 0)
|
| + end += mac->nparam;
|
| +
|
| + for (k = n; k <= end; k++)
|
| + {
|
| + if (k >= mac->nparam)
|
| tt = NULL;
|
| else
|
| {
|
| if (mac->nparam > 1)
|
| - n = (n + mac->rotate) % mac->nparam;
|
| - tt = mac->params[n];
|
| + k = (k + mac->rotate) % mac->nparam;
|
| + tt = mac->params[k];
|
| }
|
| - cc = find_cc(tt);
|
| - if (cc == -1)
|
| + if (tt)
|
| {
|
| - error(ERR_NONFATAL,
|
| - "macro parameter %d is not a condition code",
|
| - n + 1);
|
| - text = NULL;
|
| - }
|
| - else
|
| - {
|
| - type = TOK_ID;
|
| - if (inverse_ccs[cc] == -1)
|
| + if (!is_fst && mac->paramlen[k])
|
| {
|
| - error(ERR_NONFATAL,
|
| - "condition code `%s' is not invertible",
|
| - conditions[cc]);
|
| - text = NULL;
|
| + *tail = new_Token(NULL, TOK_OTHER, ",", 0);
|
| + tail = &(*tail)->next;
|
| }
|
| - else
|
| - text =
|
| - nasm_strdup(conditions[inverse_ccs
|
| - [cc]]);
|
| - }
|
| - break;
|
| - case '+':
|
| - n = atoi(t->text + 2) - 1;
|
| - if (n >= mac->nparam)
|
| - tt = NULL;
|
| - else
|
| - {
|
| - if (mac->nparam > 1)
|
| - n = (n + mac->rotate) % mac->nparam;
|
| - tt = mac->params[n];
|
| - }
|
| - cc = find_cc(tt);
|
| - if (cc == -1)
|
| - {
|
| - error(ERR_NONFATAL,
|
| - "macro parameter %d is not a condition code",
|
| - n + 1);
|
| - text = NULL;
|
| - }
|
| - else
|
| - {
|
| - type = TOK_ID;
|
| - text = nasm_strdup(conditions[cc]);
|
| - }
|
| - break;
|
| - default:
|
| - n = atoi(t->text + 1) - 1;
|
| - if (n >= mac->nparam)
|
| - tt = NULL;
|
| - else
|
| - {
|
| - if (mac->nparam > 1)
|
| - n = (n + mac->rotate) % mac->nparam;
|
| - tt = mac->params[n];
|
| - }
|
| - if (tt)
|
| - {
|
| - for (i = 0; i < mac->paramlen[n]; i++)
|
| + if (mac->paramlen[k])
|
| + is_fst = 0;
|
| + for (i = 0; i < mac->paramlen[k]; i++)
|
| {
|
| *tail =
|
| new_Token(NULL, tt->type, tt->text,
|
| @@ -3892,8 +3912,111 @@
|
| }
|
| }
|
| text = NULL; /* we've done it here */
|
| - break;
|
| + }
|
| }
|
| + else
|
| + {
|
| + switch (t->text[1])
|
| + {
|
| + /*
|
| + * We have to make a substitution of one of the
|
| + * forms %1, %-1, %+1, %%foo, %0.
|
| + */
|
| + case '0':
|
| + type = TOK_NUMBER;
|
| + sprintf(tmpbuf, "%ld", mac->nparam);
|
| + text = nasm_strdup(tmpbuf);
|
| + break;
|
| + case '%':
|
| + type = TOK_ID;
|
| + sprintf(tmpbuf, "..@%lu.", mac->unique);
|
| + text = nasm_strcat(tmpbuf, t->text + 2);
|
| + break;
|
| + case '-':
|
| + n = atoi(t->text + 2) - 1;
|
| + if (n >= mac->nparam)
|
| + tt = NULL;
|
| + else
|
| + {
|
| + if (mac->nparam > 1)
|
| + n = (n + mac->rotate) % mac->nparam;
|
| + tt = mac->params[n];
|
| + }
|
| + cc = find_cc(tt);
|
| + if (cc == -1)
|
| + {
|
| + error(ERR_NONFATAL,
|
| + "macro parameter %d is not a condition code",
|
| + n + 1);
|
| + text = NULL;
|
| + }
|
| + else
|
| + {
|
| + type = TOK_ID;
|
| + if (inverse_ccs[cc] == -1)
|
| + {
|
| + error(ERR_NONFATAL,
|
| + "condition code `%s' is not invertible",
|
| + conditions[cc]);
|
| + text = NULL;
|
| + }
|
| + else
|
| + text =
|
| + nasm_strdup(conditions[inverse_ccs
|
| + [cc]]);
|
| + }
|
| + break;
|
| + case '+':
|
| + n = atoi(t->text + 2) - 1;
|
| + if (n >= mac->nparam)
|
| + tt = NULL;
|
| + else
|
| + {
|
| + if (mac->nparam > 1)
|
| + n = (n + mac->rotate) % mac->nparam;
|
| + tt = mac->params[n];
|
| + }
|
| + cc = find_cc(tt);
|
| + if (cc == -1)
|
| + {
|
| + error(ERR_NONFATAL,
|
| + "macro parameter %d is not a condition code",
|
| + n + 1);
|
| + text = NULL;
|
| + }
|
| + else
|
| + {
|
| + type = TOK_ID;
|
| + text = nasm_strdup(conditions[cc]);
|
| + }
|
| + break;
|
| + default:
|
| + n = atoi(t->text + 1) - 1;
|
| + if (n >= mac->nparam)
|
| + tt = NULL;
|
| + else
|
| + {
|
| + if (mac->nparam > 1)
|
| + n = (n + mac->rotate) % mac->nparam;
|
| + tt = mac->params[n];
|
| + }
|
| + if (tt)
|
| + {
|
| + for (i = 0; i < mac->paramlen[n]; i++)
|
| + {
|
| + *tail =
|
| + new_Token(NULL, tt->type, tt->text,
|
| + 0);
|
| + tail = &(*tail)->next;
|
| + tt = tt->next;
|
| + }
|
| + }
|
| + text = NULL; /* we've done it here */
|
| + break;
|
| + }
|
| + }
|
| + }
|
| +
|
| if (!text)
|
| {
|
| delete_Token(t);
|
| @@ -4674,8 +4797,8 @@
|
| }
|
|
|
| /*
|
| - * Since preprocessor always operate only on the line that didn't
|
| - * arrived yet, we should always use ERR_OFFBY1. Also since user
|
| + * Since preprocessor always operates only on the line that didn't
|
| + * arrive yet, we should always use ERR_OFFBY1. Also since user
|
| * won't want to see same error twice (preprocessing is done once
|
| * per pass) we will want to show errors only during pass one.
|
| */
|
| @@ -4690,7 +4813,11 @@
|
| return;
|
|
|
| va_start(arg, fmt);
|
| +#ifdef HAVE_VSNPRINTF
|
| + vsnprintf(buff, sizeof(buff), fmt, arg);
|
| +#else
|
| vsprintf(buff, fmt, arg);
|
| +#endif
|
| va_end(arg);
|
|
|
| if (istk && istk->mstk && istk->mstk->name)
|
| @@ -5062,7 +5189,13 @@
|
| free_llist(builtindef);
|
| free_llist(stddef);
|
| free_llist(predef);
|
| + builtindef = NULL;
|
| + stddef = NULL;
|
| + predef = NULL;
|
| + freeTokens = NULL;
|
| delete_Blocks();
|
| + blocks.next = NULL;
|
| + blocks.chunk = NULL;
|
| }
|
| }
|
|
|
|
|