Merge remote-tracking branch 'github/nasm-2.15.xx'

This commit is contained in:
H. Peter Anvin 2020-07-05 15:27:04 -07:00
commit 63769c588e
8 changed files with 304 additions and 191 deletions

View file

@ -49,14 +49,6 @@
#define LIST_INDENT 40
#define LIST_HEXBIT 18
typedef struct MacroInhibit MacroInhibit;
static struct MacroInhibit {
MacroInhibit *next;
int level;
int inhibiting;
} *mistack;
static const char xdigit[] = "0123456789ABCDEF";
#define HEX(a,b) (*(a)=xdigit[((b)>>4)&15],(a)[1]=xdigit[(b)&15]);
@ -135,12 +127,6 @@ static void list_cleanup(void)
if (!listfp)
return;
while (mistack) {
MacroInhibit *temp = mistack;
mistack = temp->next;
nasm_free(temp);
}
list_emit();
fclose(listfp);
listfp = NULL;
@ -172,10 +158,6 @@ static void list_init(const char *fname)
list_errors = NULL;
listlevel = 0;
suppress = 0;
nasm_new(mistack);
mistack->next = NULL;
mistack->level = 0;
mistack->inhibiting = true;
}
static void list_out(int64_t offset, char *str)
@ -292,21 +274,14 @@ static void list_output(const struct out_data *data)
static void list_line(int type, int32_t lineno, const char *line)
{
(void)type;
if (!listfp)
return;
if (user_nolist)
return;
if (mistack && mistack->inhibiting) {
if (type == LIST_MACRO)
return;
else { /* pop the m i stack */
MacroInhibit *temp = mistack;
mistack = temp->next;
nasm_free(temp);
}
}
list_emit();
if (lineno >= 0)
listlineno = lineno;
@ -316,15 +291,6 @@ static void list_line(int type, int32_t lineno, const char *line)
listlevel_e = listlevel;
}
static void mistack_push(bool inhibiting)
{
MacroInhibit *temp = nasm_malloc(sizeof(MacroInhibit));
temp->next = mistack;
temp->level = listlevel;
temp->inhibiting = inhibiting;
mistack = temp;
}
static void list_uplevel(int type, int64_t size)
{
if (!listfp)
@ -343,13 +309,6 @@ static void list_uplevel(int type, int64_t size)
case LIST_INCLUDE:
listlevel++;
if (mistack && mistack->inhibiting)
mistack_push(false);
break;
case LIST_MACRO_NOLIST:
listlevel++;
mistack_push(true);
break;
default:
@ -374,11 +333,6 @@ static void list_downlevel(int type)
default:
listlevel--;
while (mistack && mistack->level > listlevel) {
MacroInhibit *temp = mistack;
mistack = temp->next;
nasm_free(temp);
}
break;
}
}

View file

@ -644,7 +644,7 @@ int main(int argc, char **argv)
location.known = false;
_pass_type = PASS_FIRST; /* We emulate this assembly pass */
_pass_type = PASS_PREPROC;
preproc->reset(inname, PP_PREPROC, depend_list);
while ((line = preproc->getline())) {
@ -1651,8 +1651,19 @@ static void assemble_file(const char *fname, struct strlist *depend_list)
while (!terminate_after_phase && !pass_final()) {
_passn++;
if (pass_type() != PASS_OPT || !global_offset_changed)
switch (pass_type()) {
case PASS_INIT:
_pass_type = PASS_FIRST;
break;
case PASS_OPT:
if (global_offset_changed)
break; /* One more optimization pass */
/* fall through */
default:
_pass_type++;
break;
}
global_offset_changed = 0;
/*
@ -1830,8 +1841,12 @@ static bool skip_this_pass(errflags severity)
if (type == ERR_LISTMSG)
return true;
/* This message not applicable unless pass_final */
return (severity & ERR_PASS2) && !pass_final();
/*
* This message not applicable unless it is the last pass we are going
* to execute; this can be either the final code-generation pass or
* the single pass executed in preproc-only mode.
*/
return (severity & ERR_PASS2) && !pass_final_or_preproc();
}
/**
@ -1917,6 +1932,32 @@ static fatal_func die_hard(errflags true_type, errflags severity)
exit(true_type - ERR_FATAL + 1);
}
/*
* Returns the struct src_location appropriate for use, after some
* potential filename mangling.
*/
static struct src_location error_where(errflags severity)
{
struct src_location where;
if (severity & ERR_NOFILE) {
where.filename = NULL;
where.lineno = 0;
} else {
where = src_where_error();
if (!where.filename) {
where.filename =
inname && inname[0] ? inname :
outname && outname[0] ? outname :
NULL;
where.lineno = 0;
}
}
return where;
}
/*
* error reporting for critical and panic errors: minimize
* the amount of system dependencies for getting a message out,
@ -1924,8 +1965,7 @@ static fatal_func die_hard(errflags true_type, errflags severity)
*/
fatal_func nasm_verror_critical(errflags severity, const char *fmt, va_list args)
{
const char *currentfile = no_file_name;
int32_t lineno = 0;
struct src_location where;
errflags true_type = severity & ERR_MASK;
static bool been_here = false;
@ -1934,22 +1974,15 @@ fatal_func nasm_verror_critical(errflags severity, const char *fmt, va_list args
been_here = true;
if (!(severity & ERR_NOFILE)) {
src_get(&lineno, &currentfile);
if (!currentfile) {
currentfile =
inname && inname[0] ? inname :
outname && outname[0] ? outname :
no_file_name;
lineno = 0;
}
}
where = error_where(severity);
if (!where.filename)
where.filename = no_file_name;
fputs(error_pfx_table[severity], error_file);
fputs(currentfile, error_file);
if (lineno) {
fputs(where.filename, error_file);
if (where.lineno) {
fprintf(error_file, "%s%"PRId32"%s",
errfmt->beforeline, lineno, errfmt->afterline);
errfmt->beforeline, where.lineno, errfmt->afterline);
}
fputs(errfmt->beforemsg, error_file);
vfprintf(error_file, fmt, args);
@ -1963,11 +1996,10 @@ fatal_func nasm_verror_critical(errflags severity, const char *fmt, va_list args
*/
struct nasm_errtext {
struct nasm_errtext *next;
const char *currentfile; /* Owned by the filename system */
char *msg; /* Owned by this structure */
struct src_location where; /* Owned by the srcfile system */
errflags severity;
errflags true_type;
int32_t lineno;
};
struct nasm_errhold {
struct nasm_errhold *up;
@ -2052,17 +2084,7 @@ void nasm_verror(errflags severity, const char *fmt, va_list args)
et->severity = severity;
et->true_type = true_type;
et->msg = nasm_vasprintf(fmt, args);
if (!(severity & ERR_NOFILE)) {
src_get(&et->lineno, &et->currentfile);
if (!et->currentfile) {
et->currentfile =
inname && inname[0] ? inname :
outname && outname[0] ? outname :
NULL;
et->lineno = 0;
}
}
et->where = error_where(severity);
if (errhold_stack && true_type <= ERR_NONFATAL) {
/* It is a tentative error */
@ -2094,8 +2116,7 @@ static void nasm_issue_error(struct nasm_errtext *et)
char linestr[64]; /* Formatted line number if applicable */
const errflags severity = et->severity;
const errflags true_type = et->true_type;
const char * const currentfile = et->currentfile;
const uint32_t lineno = et->lineno;
const struct src_location where = et->where;
if (severity & ERR_NO_SEVERITY)
pfx = "";
@ -2114,17 +2135,17 @@ static void nasm_issue_error(struct nasm_errtext *et)
}
*linestr = 0;
if (lineno) {
if (where.lineno) {
snprintf(linestr, sizeof linestr, "%s%"PRId32"%s",
errfmt->beforeline, lineno, errfmt->afterline);
errfmt->beforeline, where.lineno, errfmt->afterline);
}
if (!skip_this_pass(severity)) {
const char *file = currentfile ? currentfile : no_file_name;
const char *file = where.filename ? where.filename : no_file_name;
const char *here = "";
if (severity & ERR_HERE) {
here = currentfile ? " here" : " in an unknown location";
here = where.filename ? " here" : " in an unknown location";
}
if (warn_list && true_type < ERR_NONFATAL &&
@ -2161,12 +2182,12 @@ static void nasm_issue_error(struct nasm_errtext *et)
* pass1 or preprocessor warnings in the list file
*/
if (severity & ERR_HERE) {
if (lineno)
if (where.lineno)
lfmt->error(severity, "%s%s at %s:%"PRId32"%s",
pfx, et->msg, currentfile, lineno, warnsuf);
else if (currentfile)
pfx, et->msg, where.filename, where.lineno, warnsuf);
else if (where.filename)
lfmt->error(severity, "%s%s in file %s%s",
pfx, et->msg, currentfile, warnsuf);
pfx, et->msg, where.filename, warnsuf);
else
lfmt->error(severity, "%s%s in an unknown location%s",
pfx, et->msg, warnsuf);

View file

@ -230,6 +230,17 @@ struct SMacro {
bool alias; /* This is an alias macro */
};
/*
* "No listing" flags. Inside a loop (%rep..%endrep) we may have
* macro listing suppressed with .nolist, but we still need to
* update line numbers for error messages and debug information...
* unless we are nested inside an actual .nolist macro.
*/
enum nolist_flags {
NL_LIST = 1, /* Suppress list output */
NL_LINE = 2 /* Don't update line information */
};
/*
* Store the definition of a multi-line macro. This is also used to
* store the interiors of `%rep...%endrep' blocks, which are
@ -264,9 +275,9 @@ struct MMacro {
#endif
char *name;
int nparam_min, nparam_max;
enum nolist_flags nolist; /* is this macro listing-inhibited? */
bool casesense;
bool plus; /* is the last parameter greedy? */
bool nolist; /* is this macro listing-inhibited? */
bool capture_label; /* macro definition has %00; capture label */
int32_t in_progress; /* is this macro currently being expanded? */
int32_t max_depth; /* maximum number of recursive expansions allowed */
@ -447,16 +458,22 @@ struct Line {
/*
* To handle an arbitrary level of file inclusion, we maintain a
* stack (ie linked list) of these things.
*
* Note: when we issue a message for a continuation line, we want to
* issue it for the actual *start* of the continuation line. This means
* we need to remember how many lines to skip over for the next one.
*/
struct Include {
Include *next;
FILE *fp;
Cond *conds;
Line *expansion;
uint64_t nolist; /* Listing inhibit counter */
uint64_t noline; /* Line number update inhibit counter */
struct mstk mstk;
struct src_location where; /* Filename and current line number */
struct src_location where; /* Filename and current line number */
int32_t lineinc; /* Increment given by %line */
bool nolist;
int32_t lineskip; /* Accounting for passed continuation lines */
};
/*
@ -1298,10 +1315,13 @@ static char *line_from_file(FILE *f)
unsigned int size, next;
const unsigned int delta = 512;
const unsigned int pad = 8;
unsigned int nr_cont = 0;
bool cont = false;
char *buffer, *p;
istk->where.lineno += istk->lineskip + istk->lineinc;
src_set_linnum(istk->where.lineno);
istk->lineskip = 0;
size = delta;
p = buffer = nasm_malloc(size);
@ -1345,7 +1365,7 @@ static char *line_from_file(FILE *f)
ungetc(next, f);
if (next == '\r' || next == '\n') {
cont = true;
nr_cont++;
istk->lineskip += istk->lineinc;
continue;
}
break;
@ -1360,9 +1380,6 @@ static char *line_from_file(FILE *f)
*p++ = c;
} while (c);
istk->where.lineno += (nr_cont + 1) * istk->lineinc;
src_set_linnum(istk->where.lineno);
return buffer;
}
@ -1382,8 +1399,8 @@ static char *read_line(void)
if (!line)
return NULL;
if (!istk->nolist)
lfmt->line(LIST_READ, istk->where.lineno, line);
if (!istk->nolist)
lfmt->line(LIST_READ, istk->where.lineno, line);
return line;
}
@ -3184,7 +3201,7 @@ static bool parse_mmacro_spec(Token *tline, MMacro *def, const char *directive)
#endif
def->name = dup_text(tline);
def->plus = false;
def->nolist = false;
def->nolist = 0;
def->nparam_min = 0;
def->nparam_max = 0;
@ -3216,7 +3233,8 @@ static bool parse_mmacro_spec(Token *tline, MMacro *def, const char *directive)
tline->next->len == 7 &&
!nasm_stricmp(tline->next->text.a, ".nolist")) {
tline = tline->next;
def->nolist = !list_option('f') || istk->nolist;
if (!list_option('f'))
def->nolist |= NL_LIST|NL_LINE;
}
/*
@ -3413,7 +3431,7 @@ static int do_directive(Token *tline, Token **output)
enum preproc_token op;
int j;
bool err;
bool nolist;
enum nolist_flags nolist;
bool casesense;
int k, m;
int offset;
@ -3851,10 +3869,12 @@ static int do_directive(Token *tline, Token **output)
/* -MG given but file not found, or repeated %require */
nasm_free(inc);
} else {
src_set(0, found_path ? found_path : p);
inc->where = src_where();
inc->lineinc = 1;
inc->nolist = istk->nolist;
inc->noline = istk->noline;
if (!inc->noline)
src_set(0, found_path ? found_path : p);
istk = inc;
lfmt->uplevel(LIST_INCLUDE, 0);
}
@ -3880,8 +3900,10 @@ static int do_directive(Token *tline, Token **output)
stdmacpos = pkg->macros;
nasm_new(inc);
inc->next = istk;
src_set(0, NULL);
inc->nolist = !list_option('b') || istk->nolist;
inc->nolist = istk->nolist + !list_option('b');
inc->noline = istk->noline;
if (!inc->noline)
src_set(0, NULL);
istk = inc;
lfmt->uplevel(LIST_INCLUDE, 0);
}
@ -4206,11 +4228,12 @@ issue_error:
{
MMacro *tmp_defining;
nolist = false;
nolist = 0;
tline = skip_white(tline->next);
if (tok_type(tline, TOK_ID) && tline->len == 7 &&
!nasm_memicmp(tline->text.a, ".nolist", 7)) {
nolist = !list_option('f') || istk->nolist;
if (!list_option('f'))
nolist |= NL_LIST; /* ... but update line numbers */
tline = skip_white(tline->next);
}
@ -4287,7 +4310,11 @@ issue_error:
istk->mstk.mstk = defining;
lfmt->uplevel(defining->nolist ? LIST_MACRO_NOLIST : LIST_MACRO, 0);
/* A loop does not change istk->noline */
istk->nolist += !!(defining->nolist & NL_LIST);
if (!istk->nolist)
lfmt->uplevel(LIST_MACRO, 0);
defining = defining->dstk.mstk;
break;
@ -4752,9 +4779,8 @@ static bool paste_tokens(Token **head, const struct tokseq_match *m,
if (!handle_explicit)
break;
/* Left pasting token is start of line */
/* Left pasting token is start of line, just drop %+ */
if (!prev_nonspace) {
nasm_nonfatal("No lvalue found on pasting");
tok = delete_Token(tok);
break;
}
@ -4767,28 +4793,25 @@ static bool paste_tokens(Token **head, const struct tokseq_match *m,
/* Delete leading whitespace */
next = zap_white(t->next);
/* Delete the %+ token itself */
nasm_assert(next == tok);
next = delete_Token(next);
/* Delete trailing whitespace */
next = zap_white(next);
/*
* Delete the %+ token itself, followed by any whitespace.
* In a sequence of %+ ... %+ ... %+ pasting sequences where
* some expansions in the middle have ended up empty,
* we can end up having multiple %+ tokens in a row;
* just drop whem in that case.
*/
while (next) {
if (next->type == TOK_PASTE || next->type == TOK_WHITESPACE)
next = delete_Token(next);
else
break;
}
/*
* No ending token, this might happen in two
* cases
*
* 1) There indeed no right token at all
* 2) There is a bare "%define ID" statement,
* and @ID does expand to whitespace.
*
* So technically we need to do a grammar analysis
* in another stage of parsing, but for now lets don't
* change the behaviour people used to. Simply allow
* whitespace after paste token.
* Nothing after? Just leave the existing token.
*/
if (!next) {
*prev_nonspace = tok = NULL; /* End of line */
t->next = tok = NULL; /* End of line */
break;
}
@ -6342,10 +6365,18 @@ static int expand_mmacro(Token * tline)
}
}
lfmt->uplevel(m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO, 0);
istk->nolist += !!(m->nolist & NL_LIST);
istk->noline += !!(m->nolist & NL_LINE);
if (list_option('m') && !m->nolist)
list_mmacro_call(m);
if (!istk->nolist) {
lfmt->uplevel(LIST_MACRO, 0);
if (list_option('m'))
list_mmacro_call(m);
}
if (!istk->noline)
src_macro_push(m, istk->where);
return 1;
}
@ -6568,6 +6599,8 @@ static Token *pp_tokline(void)
while (l && l->finishes) {
MMacro *fm = l->finishes;
nasm_assert(fm == istk->mstk.mstk);
if (!fm->name && fm->in_progress > 1) {
/*
* This is a macro-end marker for a macro with no
@ -6647,6 +6680,22 @@ static Token *pp_tokline(void)
}
}
if (fm->nolist & NL_LIST) {
istk->nolist--;
} else if (!istk->nolist) {
lfmt->downlevel(LIST_MACRO);
}
if (fm->nolist & NL_LINE) {
istk->noline--;
} else if (!istk->noline) {
if (fm == src_macro_current())
src_macro_pop();
src_update(l->where);
}
istk->where = l->where;
/*
* FIXME It is incorrect to always free_mmacro here.
* It leads to usage-after-free.
@ -6658,10 +6707,9 @@ static Token *pp_tokline(void)
free_mmacro(m);
#endif
}
istk->where = l->where;
istk->expansion = l->next;
nasm_free(l);
lfmt->downlevel(LIST_MACRO);
return &tok_pop;
}
@ -6676,6 +6724,9 @@ static Token *pp_tokline(void)
tline = l->first;
nasm_free(l);
if (!istk->noline)
src_update(istk->where);
if (!istk->nolist) {
line = detoken(tline, false);
lfmt->line(LIST_MACRO, istk->where.lineno, line);
@ -6992,44 +7043,20 @@ static Token *make_tok_char(Token *next, char op)
}
/*
* Descend the istk looking for macro definitions; we have to
* recurse because we want to show the messages in top-down order.
* Descent the macro hierarchy and display the expansion after
* encountering an error message.
*/
static void pp_list_macro_istk(Include *inc, errflags severity)
{
MMacro *m;
Include *inext;
/* Find the next higher level true macro invocation if any */
inext = inc->next;
if (inext && inext->mstk.mmac) {
while (inext) {
if (inext->mstk.mstk->name) {
pp_list_macro_istk(inext, severity);
break;
}
inext = inext->next;
}
}
m = inc->mstk.mstk;
if (m && m->name && !m->nolist) {
src_update(inc->where);
nasm_error(severity, "... from macro `%s' defined", m->name);
}
}
static void pp_error_list_macros(errflags severity)
{
struct src_location saved;
if (!istk)
return;
const MMacro *m;
severity |= ERR_PP_LISTMACRO | ERR_NO_SEVERITY | ERR_HERE;
saved = src_where();
pp_list_macro_istk(istk, severity);
src_update(saved);
while ((m = src_error_down())) {
nasm_error(severity, "... from macro `%s' defined", m->name);
}
src_error_reset();
}
const struct preproc_ops nasmpp = {

View file

@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- *
*
* Copyright 1996-2018 The NASM Authors - All Rights Reserved
* Copyright 1996-2020 The NASM Authors - All Rights Reserved
* See the file AUTHORS included with the NASM distribution for
* the specific copyright holders.
*
@ -32,7 +32,14 @@
* ----------------------------------------------------------------------- */
/*
* srcfile.c - keep track of the current position in the input stream
* srcfile.c - keep track of the current position in the input stream.
*
* This is used for error messages, listing, and debug information. In
* both cases we also want to understand where inside a non-nolist
* macro we may be.
*
* This hierarchy is a stack that is kept as a doubly-linked list, as
* we want to traverse it in either top-down order or bottom-up.
*/
#include "compiler.h"
@ -42,7 +49,9 @@
#include "hashtbl.h"
#include "srcfile.h"
struct src_location _src_here;
struct src_location_stack _src_top;
struct src_location_stack *_src_bottom = &_src_top;
struct src_location_stack *_src_error = &_src_top;
static struct hash_table filename_hash;
@ -75,8 +84,8 @@ const char *src_set_fname(const char *newname)
}
}
oldname = _src_here.filename;
_src_here.filename = newname;
oldname = _src_bottom->l.filename;
_src_bottom->l.filename = newname;
return oldname;
}
@ -85,3 +94,25 @@ void src_set(int32_t line, const char *fname)
src_set_fname(fname);
src_set_linnum(line);
}
void src_macro_push(const void *macro, struct src_location where)
{
struct src_location_stack *sl;
nasm_new(sl);
sl->l = where;
sl->macro = macro;
sl->up = _src_bottom;
_src_bottom->down = sl;
_src_bottom = sl;
}
void src_macro_pop(void)
{
struct src_location_stack *sl = _src_bottom;
_src_bottom = sl->up;
_src_bottom->down = NULL;
nasm_free(sl);
}

View file

@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- *
*
* Copyright 1996-2016 The NASM Authors - All Rights Reserved
* Copyright 1996-2020 The NASM Authors - All Rights Reserved
* See the file AUTHORS included with the NASM distribution for
* the specific copyright holders.
*
@ -43,24 +43,31 @@ struct src_location {
const char *filename;
int32_t lineno;
};
extern struct src_location _src_here;
struct src_location_stack {
struct src_location l;
struct src_location_stack *up, *down;
const void *macro;
};
extern struct src_location_stack _src_top;
extern struct src_location_stack *_src_bottom;
extern struct src_location_stack *_src_error;
void src_init(void);
void src_free(void);
const char *src_set_fname(const char *newname);
static inline const char *src_get_fname(void)
{
return _src_here.filename;
return _src_bottom->l.filename;
}
static inline int32_t src_set_linnum(int32_t newline)
{
int32_t oldline = _src_here.lineno;
_src_here.lineno = newline;
int32_t oldline = _src_bottom->l.lineno;
_src_bottom->l.lineno = newline;
return oldline;
}
static inline int32_t src_get_linnum(void)
{
return _src_here.lineno;
return _src_bottom->l.lineno;
}
/* Can be used when there is no need for the old information */
@ -80,15 +87,16 @@ static inline int32_t src_get(int32_t *xline, const char **xname)
{
const char *xn = *xname;
int32_t xl = *xline;
int32_t line = _src_bottom->l.lineno;
*xline = _src_here.lineno;
*xname = _src_here.filename;
*xline = line;
*xname = _src_bottom->l.filename;
/* The return value is expected to be optimized out almost everywhere */
if (!xn || xn != _src_here.filename)
if (!xn || xn != _src_bottom->l.filename)
return -2;
else
return _src_here.lineno - xl;
return line - xl;
}
/*
@ -96,7 +104,39 @@ static inline int32_t src_get(int32_t *xline, const char **xname)
*/
static inline struct src_location src_where(void)
{
return _src_here;
return _src_bottom->l;
}
/*
* Returns the top-level information as a structure. Use this for panic
* errors, since descent is not possible there.
*/
static inline struct src_location src_where_top(void)
{
return _src_top.l;
}
/*
* Returns the appropriate level of the location stack to use for error
* messages. This is the same as the top level except during the descent
* through the macro hierarchy for elucidation;
*/
static inline struct src_location src_where_error(void)
{
return _src_error->l;
}
static inline const void *src_error_down(void)
{
if (_src_error->down) {
_src_error = _src_error->down;
return _src_error->macro;
} else {
return NULL;
}
}
static inline void src_error_reset(void)
{
_src_error = &_src_top;
}
/*
@ -106,9 +146,20 @@ static inline struct src_location src_where(void)
*/
static inline struct src_location src_update(struct src_location whence)
{
struct src_location old = _src_here;
_src_here = whence;
struct src_location old = _src_bottom->l;
_src_bottom->l = whence;
return old;
}
/*
* Push/pop macro expansion level. "macroname" must remain constant at
* least until the same macro expansion level is popped.
*/
void src_macro_push(const void *macroname, struct src_location where);
static inline const void *src_macro_current(void)
{
return _src_bottom->macro;
}
void src_macro_pop(void);
#endif /* ASM_SRCFILE_H */

View file

@ -237,7 +237,7 @@ if (defined($fontmap)) {
'dieresis', undef, 'ring', 'cedilla', undef, 'hungarumlaut',
'ogonek', 'caron', 'space', 'exclam', 'quotedbl', 'numbersign',
'dollar', 'percent', 'ampersand', 'quoteright', 'parenleft',
'parenright', 'asterisk', 'plus', 'comma', 'minus', 'period',
'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period',
'slash', 'zero', 'one', 'two', 'three', 'four', 'five', 'six',
'seven', 'eight', 'nine', 'colon', 'semicolon', 'less', 'equal',
'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
@ -254,7 +254,7 @@ if (defined($fontmap)) {
'scaron', 'guilsignlright', 'oe', undef, 'zcaron', 'Ydieresis',
'space', 'exclamdown', 'cent', 'sterling', 'currency', 'yen',
'brokenbar', 'section', 'dieresis', 'copyright', 'ordfeminine',
'guillemotleft', 'logicalnot', 'hyphen', 'registered', 'macron',
'guillemotleft', 'logicalnot', 'minus', 'registered', 'macron',
'degree', 'plusminus', 'twosuperior', 'threesuperior', 'acute', 'mu',
'paragraph', 'periodcentered', 'cedilla', 'onesuperior',
'ordmasculine', 'guillemotright', 'onequarter', 'onehalf',

View file

@ -428,7 +428,6 @@ static inline char *nasm_skip_identifier(const char *str)
enum {
LIST_READ,
LIST_MACRO,
LIST_MACRO_NOLIST,
LIST_INCLUDE,
LIST_INCBIN,
LIST_TIMES
@ -1284,6 +1283,7 @@ struct optimization {
*/
enum pass_type {
PASS_INIT, /* Initialization, not doing anything yet */
PASS_PREPROC, /* Preprocess-only mode (similar to PASS_FIRST) */
PASS_FIRST, /* The very first pass over the code */
PASS_OPT, /* Optimization pass */
PASS_STAB, /* Stabilization pass (original pass 1) */
@ -1319,6 +1319,11 @@ static inline bool pass_final(void)
{
return pass_type() >= PASS_FINAL;
}
/* True for code generation *or* preprocess-only mode */
static inline bool pass_final_or_preproc(void)
{
return pass_type() >= PASS_FINAL || pass_type() == PASS_PREPROC;
}
/*
* The actual pass number. 0 is used during initialization, the very

View file

@ -1,16 +1,40 @@
%macro testrep 0.nolist
%macro testrep 0-1
%assign i 1
%rep 4
%rep %1 4
mov eax,i
%if i==3
%exitrep
%endif
mov ebx,i
%warning in %?%1 iteration i
%if i >= 3
%error iteration i should not be seen
%endif
%assign i i+1
%endrep
ret
%endmacro
%macro testrep_nl 0-1.nolist
%assign i 1
%rep %1 4
mov eax,i
%if i==3
%exitrep
%endif
%warning in %?%1 iteration i
mov ebx,i
%if i >= 3
%error iteration i should not be seen
%endif
%assign i i+1
%endrep
ret
%endmacro
testrep
testrep
testrep .nolist
testrep_nl
testrep_nl .nolist