diff options
author | H. Peter Anvin <hpa@zytor.com> | 2020-07-05 15:27:04 -0700 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2020-07-05 15:27:04 -0700 |
commit | 63769c588e2d0ecc49b898c0a5c035cf0d11e78e (patch) | |
tree | ce7859cca6de47fb384238187181071af909add9 | |
parent | 37c0942409298317aa5206f09250527793b3b593 (diff) | |
parent | 122c5fb75986adc37dfb147cc2a613e3ebc66e80 (diff) | |
download | nasm-63769c588e2d0ecc49b898c0a5c035cf0d11e78e.tar.gz |
Merge remote-tracking branch 'github/nasm-2.15.xx'
-rw-r--r-- | asm/listing.c | 50 | ||||
-rw-r--r-- | asm/nasm.c | 105 | ||||
-rw-r--r-- | asm/preproc.c | 179 | ||||
-rw-r--r-- | asm/srcfile.c | 41 | ||||
-rw-r--r-- | asm/srcfile.h | 77 | ||||
-rwxr-xr-x | doc/genps.pl | 4 | ||||
-rw-r--r-- | include/nasm.h | 7 | ||||
-rw-r--r-- | test/exitrep.asm | 30 |
8 files changed, 303 insertions, 190 deletions
diff --git a/asm/listing.c b/asm/listing.c index 6d6f3606..f6ef6d1b 100644 --- a/asm/listing.c +++ b/asm/listing.c @@ -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; } } @@ -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(); } /** @@ -1918,14 +1933,39 @@ static fatal_func die_hard(errflags true_type, errflags severity) } /* + * 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, * and in particular try to avoid memory allocations. */ 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, ¤tfile); - 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); diff --git a/asm/preproc.c b/asm/preproc.c index 116ceef6..a2c5083d 100644 --- a/asm/preproc.c +++ b/asm/preproc.c @@ -231,6 +231,17 @@ struct SMacro { }; /* + * "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 * effectively self-re-invoking multi-line macros which simply @@ -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) +static void pp_error_list_macros(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; - } - } + const MMacro *m; + + severity |= ERR_PP_LISTMACRO | ERR_NO_SEVERITY | ERR_HERE; - m = inc->mstk.mstk; - if (m && m->name && !m->nolist) { - src_update(inc->where); + while ((m = src_error_down())) { nasm_error(severity, "... from macro `%s' defined", m->name); } -} - -static void pp_error_list_macros(errflags severity) -{ - struct src_location saved; - if (!istk) - return; - - severity |= ERR_PP_LISTMACRO | ERR_NO_SEVERITY | ERR_HERE; - saved = src_where(); - pp_list_macro_istk(istk, severity); - src_update(saved); + src_error_reset(); } const struct preproc_ops nasmpp = { diff --git a/asm/srcfile.c b/asm/srcfile.c index a27fffac..b44c021c 100644 --- a/asm/srcfile.c +++ b/asm/srcfile.c @@ -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); +} diff --git a/asm/srcfile.h b/asm/srcfile.h index 759ceabf..a26e1e4f 100644 --- a/asm/srcfile.h +++ b/asm/srcfile.h @@ -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 */ diff --git a/doc/genps.pl b/doc/genps.pl index b5a1a8a2..72985cc7 100755 --- a/doc/genps.pl +++ b/doc/genps.pl @@ -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', diff --git a/include/nasm.h b/include/nasm.h index 046f5fb9..616ffb37 100644 --- a/include/nasm.h +++ b/include/nasm.h @@ -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 diff --git a/test/exitrep.asm b/test/exitrep.asm index 4e1b6e3c..755f05d5 100644 --- a/test/exitrep.asm +++ b/test/exitrep.asm @@ -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 -testrep +%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 .nolist + + testrep_nl + testrep_nl .nolist |