diff options
author | H. Peter Anvin <hpa@zytor.com> | 2019-08-27 16:38:48 -0700 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2019-08-27 16:42:41 -0700 |
commit | d235408c65fc8176fdd94dd9f7d49074828bfa86 (patch) | |
tree | 1c1813452456e38e4af96a9046b96ac0e4b43998 /asm | |
parent | eaef851689e1d83608741cd5ac7c65e4e47d4acb (diff) | |
download | nasm-d235408c65fc8176fdd94dd9f7d49074828bfa86.tar.gz |
preproc: standard macros now C-safe, %aliases off, fix %? recursion
Enough users expect the namespace starting with underscore to be safe
for symbols. Change our private namespace from __foo__ to
__?foo?__. Use %defalias to provide backwards compatiblity (by using
%defalias instead of %define, we handle the case properly where the
user changes the value.)
Add a preprocessor directive:
%aliases off
... to disable all smacro aliases and thereby making the namespace
clean.
Finally, fix infinite recursion when seeing %? or %?? due to
paste_tokens(). If we don't paste anything, the expansion is done.
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'asm')
-rw-r--r-- | asm/float.c | 10 | ||||
-rw-r--r-- | asm/nasm.c | 22 | ||||
-rw-r--r-- | asm/pptok.dat | 1 | ||||
-rw-r--r-- | asm/preproc.c | 99 | ||||
-rw-r--r-- | asm/tokens.dat | 62 | ||||
-rwxr-xr-x | asm/tokhash.pl | 6 |
6 files changed, 138 insertions, 62 deletions
diff --git a/asm/float.c b/asm/float.c index 3ae59f0e..77d576c6 100644 --- a/asm/float.c +++ b/asm/float.c @@ -737,18 +737,18 @@ static int to_float(const char *str, int s, uint8_t *result, if (str[0] == '_') { /* Special tokens */ - switch (str[2]) { - case 'n': /* __nan__ */ + switch (str[3]) { + case 'n': /* __?nan?__ */ case 'N': - case 'q': /* __qnan__ */ + case 'q': /* __?qnan?__ */ case 'Q': type = FL_QNAN; break; - case 's': /* __snan__ */ + case 's': /* __?snan?__ */ case 'S': type = FL_SNAN; break; - case 'i': /* __infinity__ */ + case 'i': /* __?infinity?__ */ case 'I': type = FL_INFINITY; break; @@ -299,29 +299,29 @@ static void define_macros(void) char temp[128]; if (oct->have_local) { - strftime(temp, sizeof temp, "__DATE__=\"%Y-%m-%d\"", &oct->local); + strftime(temp, sizeof temp, "__?DATE?__=\"%Y-%m-%d\"", &oct->local); preproc->pre_define(temp); - strftime(temp, sizeof temp, "__DATE_NUM__=%Y%m%d", &oct->local); + strftime(temp, sizeof temp, "__?DATE_NUM?__=%Y%m%d", &oct->local); preproc->pre_define(temp); - strftime(temp, sizeof temp, "__TIME__=\"%H:%M:%S\"", &oct->local); + strftime(temp, sizeof temp, "__?TIME?__=\"%H:%M:%S\"", &oct->local); preproc->pre_define(temp); - strftime(temp, sizeof temp, "__TIME_NUM__=%H%M%S", &oct->local); + strftime(temp, sizeof temp, "__?TIME_NUM?__=%H%M%S", &oct->local); preproc->pre_define(temp); } if (oct->have_gm) { - strftime(temp, sizeof temp, "__UTC_DATE__=\"%Y-%m-%d\"", &oct->gm); + strftime(temp, sizeof temp, "__?UTC_DATE?__=\"%Y-%m-%d\"", &oct->gm); preproc->pre_define(temp); - strftime(temp, sizeof temp, "__UTC_DATE_NUM__=%Y%m%d", &oct->gm); + strftime(temp, sizeof temp, "__?UTC_DATE_NUM?__=%Y%m%d", &oct->gm); preproc->pre_define(temp); - strftime(temp, sizeof temp, "__UTC_TIME__=\"%H:%M:%S\"", &oct->gm); + strftime(temp, sizeof temp, "__?UTC_TIME?__=\"%H:%M:%S\"", &oct->gm); preproc->pre_define(temp); - strftime(temp, sizeof temp, "__UTC_TIME_NUM__=%H%M%S", &oct->gm); + strftime(temp, sizeof temp, "__?UTC_TIME_NUM?__=%H%M%S", &oct->gm); preproc->pre_define(temp); } if (oct->have_posix) { - snprintf(temp, sizeof temp, "__POSIX_TIME__=%"PRId64, oct->posix); + snprintf(temp, sizeof temp, "__?POSIX_TIME?__=%"PRId64, oct->posix); preproc->pre_define(temp); } @@ -330,7 +330,7 @@ static void define_macros(void) * we have to put shortname of the alias itself here * otherwise ABI backward compatibility gets broken. */ - snprintf(temp, sizeof(temp), "__OUTPUT_FORMAT__=%s", + snprintf(temp, sizeof(temp), "__?OUTPUT_FORMAT?__=%s", ofmt_alias ? ofmt_alias->shortname : ofmt->shortname); preproc->pre_define(temp); @@ -344,7 +344,7 @@ static void define_macros(void) * Debug format, if any */ if (dfmt != &null_debug_form) { - snprintf(temp, sizeof(temp), "__DEBUG_FORMAT__=%s", dfmt->shortname); + snprintf(temp, sizeof(temp), "__?DEBUG_FORMAT?__=%s", dfmt->shortname); preproc->pre_define(temp); } } diff --git a/asm/pptok.dat b/asm/pptok.dat index 45610958..bb908a31 100644 --- a/asm/pptok.dat +++ b/asm/pptok.dat @@ -70,6 +70,7 @@ %un!macro # Other directives +%aliases %arg %clear %depend diff --git a/asm/preproc.c b/asm/preproc.c index c8d86656..694527dc 100644 --- a/asm/preproc.c +++ b/asm/preproc.c @@ -444,6 +444,7 @@ static int LocalOffset = 0; static Context *cstk; static Include *istk; static const struct strlist *ipath_list; +static bool do_aliases; static struct strlist *deplist; @@ -1603,6 +1604,55 @@ static int ppscan(void *private_data, struct tokenval *tokval) } /* + * 1. An expression (true if nonzero 0) + * 2. The keywords true, on, yes for true + * 3. The keywords false, off, no for false + * 4. An empty line, for true + * + * On error, return defval (usually the previous value) + */ +static bool pp_get_boolean_option(Token *tline, bool defval) +{ + static const char * const noyes[] = { + "no", "yes", + "false", "true", + "off", "on" + }; + struct ppscan pps; + struct tokenval tokval; + expr *evalresult; + + skip_white_(tline); + if (!tline || !tline->type) + return true; + + if (tline->type == TOK_ID) { + size_t i; + for (i = 0; i < ARRAY_SIZE(noyes); i++) + if (!nasm_stricmp(tline->text, noyes[i])) + return i & 1; + } + + pps.tptr = NULL; + pps.tptr = tline; + pps.ntokens = -1; + tokval.t_type = TOKEN_INVALID; + evalresult = evaluate(ppscan, &pps, &tokval, NULL, true, NULL); + + if (!evalresult) + return true; + + if (tokval.t_type) + nasm_warn(WARN_OTHER, "trailing garbage after expression ignored"); + if (!is_really_simple(evalresult)) { + nasm_nonfatal("boolean flag expression must be a constant"); + return defval; + } + + return reloc_value(evalresult) != 0; +} + +/* * Compare a string to the name of an existing macro; this is a * simple wrapper which calls either strcmp or nasm_stricmp * depending on the value of the `casesense' parameter. @@ -1801,7 +1851,7 @@ FILE *pp_input_fopen(const char *filename, enum file_flags mode) */ static bool smacro_defined(Context * ctx, const char *name, int nparam, SMacro ** defn, - bool nocase) + bool nocase, bool find_alias) { struct hash_table *smtbl; SMacro *m; @@ -1817,12 +1867,22 @@ smacro_defined(Context * ctx, const char *name, int nparam, SMacro ** defn, } else { smtbl = &smacros; } + +restart: m = (SMacro *) hash_findix(smtbl, name); while (m) { if (!mstrcmp(m->name, name, m->casesense && nocase) && (nparam <= 0 || m->nparam == 0 || nparam == m->nparam || (m->greedy && nparam >= m->nparam-1))) { + if (m->alias && !find_alias) { + if (do_aliases) { + name = m->name; + goto restart; + } else { + continue; + } + } if (defn) { *defn = (nparam == m->nparam || nparam == -1) ? m : NULL; } @@ -1963,7 +2023,7 @@ static enum cond_state if_condition(Token * tline, enum preproc_token ct) dname); goto fail; } - if (smacro_defined(NULL, tline->text, 0, NULL, true)) + if (smacro_defined(NULL, tline->text, 0, NULL, true, false)) j = true; tline = tline->next; } @@ -2460,7 +2520,7 @@ static SMacro *define_smacro(const char *mname, bool casesense, while (1) { ctx = get_ctx(mname, &mname); - if (!smacro_defined(ctx, mname, nparam, &smac, casesense)) { + if (!smacro_defined(ctx, mname, nparam, &smac, casesense, true)) { /* Create a new macro */ smtbl = ctx ? &ctx->localmac : &smacros; smhead = (SMacro **) hash_findi_add(smtbl, mname); @@ -2476,7 +2536,7 @@ static SMacro *define_smacro(const char *mname, bool casesense, * some others didn't. What is the right thing to do here? */ goto fail; - } else if (!smac->alias || defining_alias) { + } else if (!smac->alias || !do_aliases || defining_alias) { /* * We're redefining, so we have to take over an * existing SMacro structure. This means freeing @@ -2545,6 +2605,8 @@ static void undef_smacro(const char *mname, bool undefalias) while ((s = *sp) != NULL) { if (!mstrcmp(s->name, mname, s->casesense)) { if (s->alias && !undefalias) { + if (!do_aliases) + continue; if (s->in_progress) { nasm_nonfatal("macro alias loop"); } else { @@ -3916,6 +3978,12 @@ issue_error: define_smacro(mname, casesense, macro_start, NULL); break; + case PP_ALIASES: + tline = tline->next; + tline = expand_smacro(tline); + do_aliases = pp_get_boolean_option(tline, do_aliases); + break; + case PP_LINE: /* * Syntax is `%line nnn[+mmm] [filename]' @@ -4371,7 +4439,7 @@ static Token *expand_mmac_params(Token * tline) cc = find_cc(tt); if (cc == -1) { nasm_nonfatal("macro parameter `%s' is not a condition code", - text); + t->text); text = NULL; break; } @@ -4534,6 +4602,8 @@ static SMacro *expand_one_smacro(Token ***tpp) * checking for parameters if necessary. */ list_for_each(m, head) { + if (unlikely(m->alias && !do_aliases)) + continue; if (!mstrcmp(m->name, mname, m->casesense)) break; } @@ -4986,8 +5056,10 @@ static Token *expand_smacro_noreset(Token * tline) * Also we look for %+ tokens and concatenate the tokens * before and after them (without white spaces in between). */ - paste_tokens(&thead, tmatch, ARRAY_SIZE(tmatch), true); - + if (!paste_tokens(&thead, tmatch, ARRAY_SIZE(tmatch), true)) { + tline = thead; + break; + } expanded = false; } @@ -5578,10 +5650,10 @@ struct magic_macros { }; static const struct magic_macros magic_macros[] = { - { "__FILE__", 0, stdmac_file }, - { "__LINE__", 0, stdmac_line }, - { "__BITS__", 0, stdmac_bits }, - { "__PTR__", 0, stdmac_ptr }, + { "__?FILE?__", 0, stdmac_file }, + { "__?LINE?__", 0, stdmac_line }, + { "__?BITS?__", 0, stdmac_bits }, + { "__?PTR?__", 0, stdmac_ptr }, { NULL, 0, NULL } }; @@ -5613,6 +5685,7 @@ pp_reset(const char *file, enum preproc_mode mode, struct strlist *dep_list) unique = 0; deplist = dep_list; pp_mode = mode; + do_aliases = true; if (!use_loaded) use_loaded = nasm_malloc(use_package_count * sizeof(bool)); @@ -5656,7 +5729,7 @@ pp_reset(const char *file, enum preproc_mode mode, struct strlist *dep_list) do_predef = true; /* - * Define the __PASS__ macro. This is defined here unlike all the + * Define the __?PASS?__ macro. This is defined here unlike all the * other builtins, because it is special -- it varies between * passes -- but there is really no particular reason to make it * magic. @@ -5680,7 +5753,7 @@ pp_reset(const char *file, enum preproc_mode mode, struct strlist *dep_list) panic(); } - define_smacro("__PASS__", true, make_tok_num(apass), NULL); + define_smacro("__?PASS?__", true, make_tok_num(apass), NULL); } static void pp_init(void) diff --git a/asm/tokens.dat b/asm/tokens.dat index d75640cf..ad26420d 100644 --- a/asm/tokens.dat +++ b/asm/tokens.dat @@ -92,42 +92,42 @@ to ptr % TOKEN_FLOAT, 0, 0, 0 -__infinity__ -__nan__ -__qnan__ -__snan__ - -% TOKEN_FLOATIZE, 0, 0, FLOAT_{__float*__} -__float8__ -__float16__ -__float32__ -__float64__ -__float80m__ -__float80e__ -__float128l__ -__float128h__ - -% TOKEN_STRFUNC, 0, 0, STRFUNC_{__*__} -__utf16__ -__utf16le__ -__utf16be__ -__utf32__ -__utf32le__ -__utf32be__ - -% TOKEN_IFUNC, 0, 0, IFUNC_{__*__} -__ilog2e__ -__ilog2w__ -__ilog2f__ -__ilog2c__ +__?infinity?__ +__?nan?__ +__?qnan?__ +__?snan?__ + +% TOKEN_FLOATIZE, 0, 0, FLOAT_{__?float*?__} +__?float8?__ +__?float16?__ +__?float32?__ +__?float64?__ +__?float80m?__ +__?float80e?__ +__?float128l?__ +__?float128h?__ + +% TOKEN_STRFUNC, 0, 0, STRFUNC_{__?*?__} +__?utf16?__ +__?utf16le?__ +__?utf16be?__ +__?utf32?__ +__?utf32le?__ +__?utf32be?__ + +% TOKEN_IFUNC, 0, 0, IFUNC_{__?*?__} +__?ilog2e?__ +__?ilog2w?__ +__?ilog2f?__ +__?ilog2c?__ % TOKEN_*, 0, 0, 0 seg wrt -% TOKEN_{__*__}, 0, 0, 0 -__masm_ptr__ -__masm_flat__ +% TOKEN_{__?*?__}, 0, 0, 0 +__?masm_ptr?__ +__?masm_flat?__ % TOKEN_DECORATOR, 0, TFLAG_BRC | TFLAG_BRDCAST , BRC_1TO{1to*} 1to2 diff --git a/asm/tokhash.pl b/asm/tokhash.pl index 4636e12e..f831265b 100755 --- a/asm/tokhash.pl +++ b/asm/tokhash.pl @@ -57,7 +57,7 @@ my($output, $insns_dat, $regs_dat, $tokens_dat) = @ARGV; # open(ID, '<', $insns_dat) or die "$0: cannot open $insns_dat: $!\n"; while (defined($line = <ID>)) { - if ($line =~ /^([A-Z0-9_]+)(|cc)\s/) { + if ($line =~ /^([\?\@A-Z0-9_]+)(|cc)\s/) { $insn = $1.$2; ($token = $1) =~ tr/A-Z/a-z/; @@ -88,7 +88,7 @@ close(ID); # open(RD, '<', $regs_dat) or die "$0: cannot open $regs_dat: $!\n"; while (defined($line = <RD>)) { - if ($line =~ /^([a-z0-9_-]+)\s*\S+\s*\S+\s*[0-9]+\s*(\S*)/) { + if ($line =~ /^([\?\@a-z0-9_-]+)\s*\S+\s*\S+\s*[0-9]+\s*(\S*)/) { $reg = $1; $reg_flag = $2; @@ -144,6 +144,7 @@ while (defined($line = <TD>)) { my $head = $1, $tail = $3; my $px = $2; + $px =~ s/\?/\\?/g; $px =~ s/\*/(.*)/g; if ($token =~ /$px/i) { $data = $head."\U$1".$tail; @@ -153,6 +154,7 @@ while (defined($line = <TD>)) { } $data =~ s/\*/\U$token/g; + $data =~ s/\?//g; push(@tokendata, "\"$token\", ".length($token).", $data"); } |