preproc: distinguish between directives and functions

Some preprocessor functions have the same name as directives. In those
cases, they should be expanded as functions if and only if they are
followed by a left parenthesis. Although it is not inherently true that
either preprocessor functions require a paren nor that directives
cannot start with one, but it is true and will remain true for all
cases where there is a namespace collision.

Signed-off-by: H. Peter Anvin <hpa@zytor.com>
This commit is contained in:
H. Peter Anvin 2022-11-11 19:51:22 -08:00
parent 359e21e773
commit 3fe5b3f5a1
2 changed files with 25 additions and 7 deletions

View file

@ -1,7 +1,7 @@
#!/usr/bin/perl
## --------------------------------------------------------------------------
##
## Copyright 1996-2020 The NASM Authors - All Rights Reserved
## Copyright 1996-2022 The NASM Authors - All Rights Reserved
## See the file AUTHORS included with the NASM distribution for
## the specific copyright holders.
##
@ -132,7 +132,8 @@ if ($what eq 'h') {
}
$n++;
}
printf OUT " %-24s = %3d\n", 'PP_INVALID', -1;
printf OUT " %-24s = %3d,\n", 'PP_count', $n;
printf OUT " %-24s = %3d\n", 'PP_invalid', -1;
print OUT "};\n";
print OUT "\n";
@ -257,11 +258,11 @@ if ($what eq 'c') {
print OUT "\n";
print OUT " ix = hashdata[k1] + hashdata[k2];\n";
printf OUT " if (ix >= %d)\n", scalar(@pptok);
print OUT " return PP_INVALID;\n";
print OUT " return PP_invalid;\n";
print OUT "\n";
print OUT " if (!pp_directives[ix] || nasm_stricmp(pp_directives[ix], token))\n";
print OUT " return PP_INVALID;\n";
print OUT " return PP_invalid;\n";
print OUT "\n";
print OUT " return ix;\n";
print OUT "}\n";
@ -315,11 +316,11 @@ if ($what eq 'c') {
# Comparing to pptok here is correct, because this hash produces
# an enum preproc_token value directly.
printf OUT " if (ix >= %d)\n", scalar(@pptok);
print OUT " return PP_INVALID;\n";
print OUT " return PP_invalid;\n";
print OUT "\n";
print OUT " if (!pp_directives[ix] || nasm_stricmp(pp_directives[ix]+1, token))\n";
print OUT " return PP_INVALID;\n";
print OUT " return PP_invalid;\n";
print OUT "\n";
print OUT " return ix;\n";
print OUT "}\n";

View file

@ -111,6 +111,13 @@ typedef struct Line Line;
typedef struct Include Include;
typedef struct Cond Cond;
/*
* Map of preprocessor directives that are also preprocessor functions;
* if they are at the beginning of a line they are a function if and
* only if they are followed by a (
*/
static bool pp_op_may_be_function[PP_count];
/*
* This is the internal form which we break input lines up into.
* Typically stored in linked lists.
@ -3757,7 +3764,7 @@ static int do_directive(Token *tline, Token **output)
}
switch (op) {
case PP_INVALID:
case PP_invalid:
return NO_DIRECTIVE_FOUND;
case PP_LINE:
@ -3828,6 +3835,11 @@ static int do_directive(Token *tline, Token **output)
}
}
if (pp_op_may_be_function[op]) {
if (tok_is(skip_white(tline->next), '('))
return NO_DIRECTIVE_FOUND; /* Expand as a preprocessor function */
}
switch (op) {
default:
nasm_nonfatal("unknown preprocessor directive `%s'", dname);
@ -7001,6 +7013,11 @@ static void pp_add_magic_stdmac(void)
}
}
define_smacro(m->name, m->casesense, NULL, &tmpl);
if (m->name[0] == '%') {
enum preproc_token op = pp_token_hash(m->name);
if (op != PP_invalid)
pp_op_may_be_function[op] = true;
}
}
/* %is...() macro functions */