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; |
} |
} |