summaryrefslogtreecommitdiff
path: root/asm
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2019-08-27 16:38:48 -0700
committerH. Peter Anvin <hpa@zytor.com>2019-08-27 16:42:41 -0700
commitd235408c65fc8176fdd94dd9f7d49074828bfa86 (patch)
tree1c1813452456e38e4af96a9046b96ac0e4b43998 /asm
parenteaef851689e1d83608741cd5ac7c65e4e47d4acb (diff)
downloadnasm-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.c10
-rw-r--r--asm/nasm.c22
-rw-r--r--asm/pptok.dat1
-rw-r--r--asm/preproc.c99
-rw-r--r--asm/tokens.dat62
-rwxr-xr-xasm/tokhash.pl6
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;
diff --git a/asm/nasm.c b/asm/nasm.c
index 4cf6f2ab..fd700df2 100644
--- a/asm/nasm.c
+++ b/asm/nasm.c
@@ -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");
}