preproc: add %is...() function-like macros

Add the first "preprocessor functions". These are simply "magic"
single-line macros with a suitable expansion function. The first
application is functions equal to the %if directives, e.g.
%ifdef blah == %if %isdef(blah) except can be used anywhere (not just
in %if statements like defined() in C.)

Signed-off-by: H. Peter Anvin <hpa@zytor.com>
This commit is contained in:
H. Peter Anvin 2020-07-11 20:43:40 -07:00
parent 80e1774b90
commit d831915543
2 changed files with 52 additions and 14 deletions

View File

@ -124,9 +124,11 @@ if ($what eq 'h') {
print OUT "enum preproc_token {\n";
$n = 0;
my $maxlen = 0;
foreach $pt (@pptok) {
if (defined($pt)) {
printf OUT " %-24s = %3d,\n", "PP_\U$pt\E", $n;
$maxlen = length($pt) if (length($pt) > $maxlen);
}
$n++;
}
@ -143,6 +145,8 @@ if ($what eq 'h') {
printf OUT "#define PP_HAS_CASE(x) ((x) >= PP_%s)\n",
uc($pptok[$first_itoken]);
print OUT "#define PP_INSENSITIVE(x) ((x) & 1)\n";
# The +1 here is for the initial % sign
printf OUT "#define PP_TOKLEN_MAX %d\n", $maxlen+1;
print OUT "\n";
foreach $ct (@cctok) {

View File

@ -3050,8 +3050,10 @@ static SMacro *define_smacro(const char *mname, bool casesense,
smac->params = tmpl->params;
smac->alias = tmpl->alias;
smac->greedy = tmpl->greedy;
if (tmpl->expand)
smac->expand = tmpl->expand;
if (tmpl->expand) {
smac->expand = tmpl->expand;
smac->expandpvt = tmpl->expandpvt;
}
}
if (list_option('s')) {
list_smacro_def((smac->alias ? PP_DEFALIAS : PP_DEFINE)
@ -5543,8 +5545,8 @@ static SMacro *expand_one_smacro(Token ***tpp)
/* Note: we own the expansion this returns. */
t = m->expand(m, params, nparam);
tafter = tline->next; /* Skip past the macro call */
tline->next = NULL; /* Truncate list at the macro call end */
tafter = tline->next; /* Skip past the macro call */
tline->next = NULL; /* Truncate list at the macro call end */
tline = tafter;
tup = NULL;
@ -6634,33 +6636,65 @@ stdmac_ptr(const SMacro *s, Token **params, int nparams)
}
}
static Token *
stdmac_is(const SMacro *s, Token **params, int nparams)
{
int retval;
struct Token *pline = params[0];
(void)nparams;
params[0] = NULL; /* Don't free this later */
retval = if_condition(pline, s->expandpvt.u) == COND_IF_TRUE;
return make_tok_num(NULL, retval);
}
/* Add magic standard macros */
struct magic_macros {
const char *name;
int nparam;
ExpandSMacro func;
};
static const struct magic_macros magic_macros[] =
{
{ "__?FILE?__", 0, stdmac_file },
{ "__?LINE?__", 0, stdmac_line },
{ "__?BITS?__", 0, stdmac_bits },
{ "__?PTR?__", 0, stdmac_ptr },
{ NULL, 0, NULL }
};
static void pp_add_magic_stdmac(void)
{
static const struct magic_macros magic_macros[] = {
{ "__?FILE?__", 0, stdmac_file },
{ "__?LINE?__", 0, stdmac_line },
{ "__?BITS?__", 0, stdmac_bits },
{ "__?PTR?__", 0, stdmac_ptr },
{ NULL, 0, NULL }
};
const struct magic_macros *m;
SMacro tmpl;
enum preproc_token pt;
char name_buf[PP_TOKLEN_MAX+1];
/* Simple standard magic macros */
nasm_zero(tmpl);
for (m = magic_macros; m->name; m++) {
tmpl.nparam = m->nparam;
tmpl.expand = m->func;
define_smacro(m->name, true, NULL, &tmpl);
}
/* %is...() macro functions */
tmpl.nparam = 1;
tmpl.greedy = true;
tmpl.expand = stdmac_is;
name_buf[0] = '%';
name_buf[1] = 'i';
name_buf[2] = 's';
for (pt = PP_IF; pt < PP_IFN; pt++) {
if (pp_directives[pt]) {
nasm_new(tmpl.params);
tmpl.params[0].flags = SPARM_GREEDY;
strcpy(name_buf+3, pp_directives[pt]+3);
tmpl.expandpvt.u = pt;
define_smacro(name_buf, false, NULL, &tmpl);
}
}
}
static void pp_reset_stdmac(enum preproc_mode mode)