[nasm:master] preproc: get rid of the prepreprocessor and the nop preprocessor
nasm-bot for H. Peter Anvin (Intel)
hpa at zytor.com
Thu Jul 9 23:44:04 PDT 2020
Commit-ID: 32322a9a93e52ab7406f996f9fd67d0634bed7bd
Gitweb: http://repo.or.cz/w/nasm.git?a=commitdiff;h=32322a9a93e52ab7406f996f9fd67d0634bed7bd
Author: H. Peter Anvin (Intel) <hpa at zytor.com>
AuthorDate: Thu, 9 Jul 2020 23:34:52 -0700
Committer: H. Peter Anvin (Intel) <hpa at zytor.com>
CommitDate: Thu, 9 Jul 2020 23:34:52 -0700
preproc: get rid of the prepreprocessor and the nop preprocessor
Fold the prepreprocessor and the nop preprocessor into the main
preprocessor. This means handling # cpp-like lines and TASM
compatibility tokens in the preprocessor proper, but that is really
not very hard to do.
Signed-off-by: H. Peter Anvin (Intel) <hpa at zytor.com>
---
Makefile.in | 1 -
Mkfiles/msvc.mak | 1 -
Mkfiles/openwcom.mak | 1 -
asm/nasm.c | 20 +--
asm/pptok.dat | 15 +-
asm/pptok.pl | 80 +++++++++-
asm/preproc-nop.c | 205 -------------------------
asm/preproc.c | 414 +++++++++++++++++++++++++--------------------------
asm/preproc.h | 4 +-
include/nasm.h | 11 +-
10 files changed, 311 insertions(+), 441 deletions(-)
diff --git a/Makefile.in b/Makefile.in
index bb023d02..3152aca1 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -132,7 +132,6 @@ LIBOBJ = stdlib/snprintf.$(O) stdlib/vsnprintf.$(O) stdlib/strlcpy.$(O) \
asm/stdscan.$(O) \
asm/strfunc.$(O) asm/tokhash.$(O) \
asm/segalloc.$(O) \
- asm/preproc-nop.$(O) \
asm/rdstrnum.$(O) \
asm/srcfile.$(O) \
macros/macros.$(O) \
diff --git a/Mkfiles/msvc.mak b/Mkfiles/msvc.mak
index 9346c293..9e6cc361 100644
--- a/Mkfiles/msvc.mak
+++ b/Mkfiles/msvc.mak
@@ -96,7 +96,6 @@ LIBOBJ = stdlib\snprintf.$(O) stdlib\vsnprintf.$(O) stdlib\strlcpy.$(O) \
asm\stdscan.$(O) \
asm\strfunc.$(O) asm\tokhash.$(O) \
asm\segalloc.$(O) \
- asm\preproc-nop.$(O) \
asm\rdstrnum.$(O) \
asm\srcfile.$(O) \
macros\macros.$(O) \
diff --git a/Mkfiles/openwcom.mak b/Mkfiles/openwcom.mak
index 262a0419..d15dd667 100644
--- a/Mkfiles/openwcom.mak
+++ b/Mkfiles/openwcom.mak
@@ -85,7 +85,6 @@ LIBOBJ = stdlib\snprintf.$(O) stdlib\vsnprintf.$(O) stdlib\strlcpy.$(O) &
asm\stdscan.$(O) &
asm\strfunc.$(O) asm\tokhash.$(O) &
asm\segalloc.$(O) &
- asm\preproc-nop.$(O) &
asm\rdstrnum.$(O) &
asm\srcfile.$(O) &
macros\macros.$(O) &
diff --git a/asm/nasm.c b/asm/nasm.c
index c5d9aff1..918bce91 100644
--- a/asm/nasm.c
+++ b/asm/nasm.c
@@ -143,9 +143,9 @@ static struct RAA *offsets;
static struct SAA *forwrefs; /* keep track of forward references */
static const struct forwrefinfo *forwref;
-static const struct preproc_ops *preproc;
+#define preproc (&preproc_nasm) /* Hack */
static struct strlist *include_path;
-bool pp_noline; /* Ignore %line directives */
+static enum preproc_opt ppopt;
#define OP_NORMAL (1U << 0)
#define OP_PREPROCESS (1U << 1)
@@ -364,7 +364,7 @@ static void define_macros(void)
*/
static void preproc_init(struct strlist *ipath)
{
- preproc->init();
+ preproc->init(ppopt);
define_macros();
preproc->include_path(ipath);
}
@@ -549,7 +549,6 @@ int main(int argc, char **argv)
offsets = raa_init();
forwrefs = saa_init((int32_t)sizeof(struct forwrefinfo));
- preproc = &nasmpp;
operating_mode = OP_NORMAL;
parse_cmdline(argc, argv, 1);
@@ -574,6 +573,11 @@ int main(int argc, char **argv)
}
}
+ /* Have we enabled TASM mode? */
+ if (tasm_compatible_mode) {
+ ppopt |= PP_TASM;
+ nasm_ctype_tasm_mode();
+ }
preproc_init(include_path);
parse_cmdline(argc, argv, 2);
@@ -1138,10 +1142,8 @@ static bool process_arg(char *p, char *q, int pass)
break;
case 't':
- if (pass == 2) {
+ if (pass == 1)
tasm_compatible_mode = true;
- nasm_ctype_tasm_mode();
- }
break;
case 'v':
@@ -1156,7 +1158,7 @@ static bool process_arg(char *p, char *q, int pass)
case 'a': /* assemble only - don't preprocess */
if (pass == 1)
- preproc = &preproc_nop;
+ ppopt |= PP_TRIVIAL;
break;
case 'w':
@@ -1325,7 +1327,7 @@ static bool process_arg(char *p, char *q, int pass)
keep_all = true;
break;
case OPT_NO_LINE:
- pp_noline = true;
+ ppopt |= PP_NOLINE;
break;
case OPT_DEBUG:
debug_nasm = param ? strtoul(param, NULL, 10) : debug_nasm+1;
diff --git a/asm/pptok.dat b/asm/pptok.dat
index 9b890a19..3dede0bc 100644
--- a/asm/pptok.dat
+++ b/asm/pptok.dat
@@ -40,11 +40,12 @@
%if*
%elif*
-# Condition tests
+# Condition tests.
*
*ctx
*def
*defalias
+*difi
*empty
*env
*id
@@ -101,3 +102,15 @@
%undefalias
%use
%warning
+
+# These directives do not require % in TASM-compatible mode
+ at arg
+ at elif
+ at else
+ at endif
+ at if
+ at ifdef
+ at ifdifi
+ at ifndef
+ at include
+ at local
diff --git a/asm/pptok.pl b/asm/pptok.pl
index 5498cb46..0ac044f4 100755
--- a/asm/pptok.pl
+++ b/asm/pptok.pl
@@ -63,15 +63,19 @@ while (defined($line = <IN>)) {
} elsif ($line =~ /^\*(.*)$/) {
# Condition tail
push(@cond, $1);
+ } elsif ($line =~ /^\@(.*)$/) {
+ # TASM compatibility directive
+ push(@tasm, $1);
}
}
close(IN);
# Always sort %if first
- at cctok = sort { $a eq 'if' ? -1 : $b eq 'if' ? 1 : $a cmp $b } @cctok;
- at cond = sort @cond;
- at pptok = sort @pptok;
+ at cctok = sort { $a eq 'if' ? -1 : $b eq 'if' ? 1 : $a cmp $b } @cctok;
+ at cond = sort @cond;
+ at pptok = sort @pptok;
@ppitok = sort @ppitok;
+ at tasm = sort @tasm;
# Generate the expanded list including conditionals. The conditionals
# are at the beginning, padded to a power of 2, with the inverses
@@ -217,14 +221,15 @@ if ($what eq 'c') {
}
print OUT "};\n";
- print OUT "enum preproc_token pp_token_hash(const char *token)\n";
- print OUT "{\n";
-
# Put a large value in unused slots. This makes it extremely unlikely
# that any combination that involves unused slot will pass the range test.
# This speeds up rejection of unrecognized tokens, i.e. identifiers.
print OUT "#define UNUSED_HASH_ENTRY (65535/3)\n";
+ print OUT "\n\n/* Primary preprocessor token hash */\n\n";
+
+ print OUT "enum preproc_token pp_token_hash(const char *token)\n";
+ print OUT "{\n";
print OUT " static const int16_t hash1[$n] = {\n";
for ($i = 0; $i < $n; $i++) {
my $h = ${$g}[$i*2+0];
@@ -261,6 +266,69 @@ if ($what eq 'c') {
print OUT "\n";
print OUT " return ix;\n";
print OUT "}\n";
+
+ my %tasmtokens = ();
+ foreach $pt (@tasm) {
+ # TASM compatiblity token
+ $nasmt = '%'.$pt;
+ if (!defined($tokens{$nasmt})) {
+ die "$in: TASM compat token $pt does not have a ".
+ "corresponding $nasmt\n";
+ }
+ $tasmtokens{$pt} = $tokens{$nasmt};
+ }
+
+ @hashinfo = gen_perfect_hash(\%tasmtokens);
+ if (!@hashinfo) {
+ die "$0: no hash found\n";
+ }
+
+ # Paranoia...
+ verify_hash_table(\%tasmtokens, \@hashinfo);
+
+ ($n, $sv, $g) = @hashinfo;
+ die if ($n & ($n-1));
+
+ print OUT "\n\n/* TASM compatibility preprocessor token hash */\n";
+
+ print OUT "enum preproc_token pp_tasm_token_hash(const char *token)\n";
+ print OUT "{\n";
+ print OUT " static const int16_t hash1[$n] = {\n";
+ for ($i = 0; $i < $n; $i++) {
+ my $h = ${$g}[$i*2+0];
+ print OUT " ", defined($h) ? $h : 'UNUSED_HASH_ENTRY', ",\n";
+ }
+ print OUT " };\n";
+
+ print OUT " static const int16_t hash2[$n] = {\n";
+ for ($i = 0; $i < $n; $i++) {
+ my $h = ${$g}[$i*2+1];
+ print OUT " ", defined($h) ? $h : 'UNUSED_HASH_ENTRY', ",\n";
+ }
+ print OUT " };\n";
+
+ print OUT " uint32_t k1, k2;\n";
+ print OUT " uint64_t crc;\n";
+ # For correct overflow behavior, "ix" should be unsigned of the same
+ # width as the hash arrays.
+ print OUT " uint16_t ix;\n";
+ print OUT "\n";
+
+ printf OUT " crc = crc64i(UINT64_C(0x%08x%08x), token);\n",
+ $$sv[0], $$sv[1];
+ print OUT " k1 = (uint32_t)crc;\n";
+ print OUT " k2 = (uint32_t)(crc >> 32);\n";
+ print OUT "\n";
+ printf OUT " ix = hash1[k1 & 0x%x] + hash2[k2 & 0x%x];\n", $n-1, $n-1;
+ printf OUT " if (ix >= %d)\n", scalar(@pptok);
+ 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 "\n";
+ print OUT " return ix;\n";
+ print OUT "}\n";
}
#
diff --git a/asm/preproc-nop.c b/asm/preproc-nop.c
deleted file mode 100644
index a927880c..00000000
--- a/asm/preproc-nop.c
+++ /dev/null
@@ -1,205 +0,0 @@
-/* ----------------------------------------------------------------------- *
- *
- * Copyright 1996-2016 The NASM Authors - All Rights Reserved
- * See the file AUTHORS included with the NASM distribution for
- * the specific copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following
- * conditions are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * ----------------------------------------------------------------------- */
-
-/*
- * This is a null preprocessor which just copies lines from input
- * to output. It's used when someone explicitly requests that NASM
- * not preprocess their source file.
- */
-
-#include "compiler.h"
-
-#include "nctype.h"
-#include <time.h>
-
-#include "nasm.h"
-#include "nasmlib.h"
-#include "error.h"
-#include "preproc.h"
-#include "listing.h"
-
-#define BUF_DELTA 512
-
-static FILE *nop_fp;
-static int32_t nop_lineinc;
-
-static void nop_init(void)
-{
- /* Nothing to do */
-}
-
-static void nop_reset(const char *file, enum preproc_mode mode,
- struct strlist *deplist)
-{
- (void)mode; /* placate compilers */
-
- src_set(0, file);
- nop_lineinc = 1;
- nop_fp = nasm_open_read(file, NF_TEXT);
-
- if (!nop_fp)
- nasm_fatalf(ERR_NOFILE, "unable to open input file `%s'", file);
-
- strlist_add(deplist, file);
-}
-
-static char *nop_getline(void)
-{
- char *buffer, *p, *q;
- int bufsize;
-
- bufsize = BUF_DELTA;
- buffer = nasm_malloc(BUF_DELTA);
- src_set_linnum(src_get_linnum() + nop_lineinc);
-
- while (1) { /* Loop to handle %line */
- p = buffer;
- while (1) { /* Loop to handle long lines */
- q = fgets(p, bufsize - (p - buffer), nop_fp);
- if (!q)
- break;
- p += strlen(p);
- if (p > buffer && p[-1] == '\n')
- break;
- if (p - buffer > bufsize - 10) {
- int offset;
- offset = p - buffer;
- bufsize += BUF_DELTA;
- buffer = nasm_realloc(buffer, bufsize);
- p = buffer + offset;
- }
- }
-
- if (!q && p == buffer) {
- nasm_free(buffer);
- return NULL;
- }
-
- /*
- * Play safe: remove CRs, LFs and any spurious ^Zs, if any of
- * them are present at the end of the line.
- */
- buffer[strcspn(buffer, "\r\n\032")] = '\0';
-
- if (!nasm_strnicmp(buffer, "%line", 5)) {
- int32_t ln;
- int li;
- char *nm = nasm_malloc(strlen(buffer));
- int conv = sscanf(buffer + 5, "%"PRId32"+%d %s", &ln, &li, nm);
- if (conv >= 2) {
- if (!pp_noline)
- src_set(ln, conv >= 3 ? nm : NULL);
- nop_lineinc = li;
- }
- nasm_free(nm);
- if (conv >= 2)
- continue;
- }
- break;
- }
-
- lfmt->line(LIST_READ, src_get_linnum(), buffer);
-
- return buffer;
-}
-
-static void nop_cleanup_pass(void)
-{
- if (nop_fp) {
- fclose(nop_fp);
- nop_fp = NULL;
- }
-}
-
-static void nop_cleanup_session(void)
-{
- /* Nothing we need to do */
-}
-
-static void nop_extra_stdmac(macros_t *macros)
-{
- (void)macros;
-}
-
-static void nop_pre_define(char *definition)
-{
- (void)definition;
-}
-
-static void nop_pre_undefine(char *definition)
-{
- (void)definition;
-}
-
-static void nop_pre_include(char *fname)
-{
- (void)fname;
-}
-
-static void nop_pre_command(const char *what, char *string)
-{
- (void)what;
- (void)string;
-}
-
-static void nop_include_path(struct strlist *list)
-{
- (void)list;
-}
-
-static void nop_error_list_macros(errflags severity)
-{
- (void)severity;
-}
-
-static bool nop_suppress_error(errflags severity)
-{
- (void)severity;
- return false;
-}
-
-const struct preproc_ops preproc_nop = {
- nop_init,
- nop_reset,
- nop_getline,
- nop_cleanup_pass,
- nop_cleanup_session,
- nop_extra_stdmac,
- nop_pre_define,
- nop_pre_undefine,
- nop_pre_include,
- nop_pre_command,
- nop_include_path,
- nop_error_list_macros,
- nop_suppress_error
-};
diff --git a/asm/preproc.c b/asm/preproc.c
index 68078ec8..c342d0a5 100644
--- a/asm/preproc.c
+++ b/asm/preproc.c
@@ -82,15 +82,23 @@
* other directives. This structure is initialized to zero on each
* pass; this *must* reflect the default initial state.
*/
-static struct pp_opts {
+static struct pp_config {
bool noaliases;
bool sane_empty_expansion;
-} ppopt;
+} ppconf;
+/*
+ * Preprocessor debug-related flags
+ */
static enum pp_debug_flags {
PDBG_MACROS = 1 /* Collect macro information */
} ppdbg;
+/*
+ * Preprocessor options configured on the command line
+ */
+static enum preproc_opt ppopt;
+
typedef struct SMacro SMacro;
typedef struct MMacro MMacro;
typedef struct MMacroInvocation MMacroInvocation;
@@ -582,22 +590,6 @@ static int is_condition(enum preproc_token arg)
return PP_IS_COND(arg) || (arg == PP_ELSE) || (arg == PP_ENDIF);
}
-/* For TASM compatibility we need to be able to recognise TASM compatible
- * conditional compilation directives. Using the NASM pre-processor does
- * not work, so we look for them specifically from the following list and
- * then jam in the equivalent NASM directive into the input stream.
- */
-
-enum {
- TM_ARG, TM_ELIF, TM_ELSE, TM_ENDIF, TM_IF, TM_IFDEF, TM_IFDIFI,
- TM_IFNDEF, TM_INCLUDE, TM_LOCAL
-};
-
-static const char * const tasm_directives[] = {
- "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
- "ifndef", "include", "local"
-};
-
static int StackSize = 4;
static const char *StackPointer = "ebp";
static int ArgOffset = 8;
@@ -892,90 +884,6 @@ static const char *pp_getenv(const Token *t, bool warn)
return v;
}
-/*
- * Handle TASM specific directives, which do not contain a % in
- * front of them. We do it here because I could not find any other
- * place to do it for the moment, and it is a hack (ideally it would
- * be nice to be able to use the NASM pre-processor to do it).
- */
-static char *check_tasm_directive(char *line)
-{
- int32_t i, j, k, m, len;
- char *p, *q, *oldline, oldchar;
-
- p = nasm_skip_spaces(line);
-
- /* Binary search for the directive name */
- i = -1;
- j = ARRAY_SIZE(tasm_directives);
- q = nasm_skip_word(p);
- len = q - p;
- if (len) {
- oldchar = p[len];
- p[len] = 0;
- while (j - i > 1) {
- k = (j + i) / 2;
- m = nasm_stricmp(p, tasm_directives[k]);
- if (m == 0) {
- /* We have found a directive, so jam a % in front of it
- * so that NASM will then recognise it as one if it's own.
- */
- p[len] = oldchar;
- len = strlen(p);
- oldline = line;
- line = nasm_malloc(len + 2);
- line[0] = '%';
- if (k == TM_IFDIFI) {
- /*
- * NASM does not recognise IFDIFI, so we convert
- * it to %if 0. This is not used in NASM
- * compatible code, but does need to parse for the
- * TASM macro package.
- */
- strcpy(line + 1, "if 0");
- } else {
- memcpy(line + 1, p, len + 1);
- }
- nasm_free(oldline);
- return line;
- } else if (m < 0) {
- j = k;
- } else
- i = k;
- }
- p[len] = oldchar;
- }
- return line;
-}
-
-/*
- * The pre-preprocessing stage... This function translates line
- * number indications as they emerge from GNU cpp (`# lineno "file"
- * flags') into NASM preprocessor line number indications (`%line
- * lineno file').
- */
-static char *prepreproc(char *line)
-{
- int lineno, fnlen;
- char *fname, *oldline;
-
- if (line[0] == '#' && line[1] == ' ') {
- oldline = line;
- fname = oldline + 2;
- lineno = atoi(fname);
- fname += strspn(fname, "0123456789 ");
- if (*fname == '"')
- fname++;
- fnlen = strcspn(fname, "\"");
- line = nasm_malloc(20 + fnlen);
- snprintf(line, 20 + fnlen, "%%line %d %.*s", lineno, fnlen, fname);
- nasm_free(oldline);
- }
- if (tasm_compatible_mode)
- return check_tasm_directive(line);
- return line;
-}
-
/*
* Free a linked list of tokens.
*/
@@ -2421,7 +2329,7 @@ restart:
(nparam <= 0 || m->nparam == 0 || nparam == m->nparam ||
(m->greedy && nparam >= m->nparam-1))) {
if (m->alias && !find_alias) {
- if (!ppopt.noaliases) {
+ if (!ppconf.noaliases) {
name = tok_text(m->expansion);
goto restart;
} else {
@@ -2602,6 +2510,15 @@ static enum cond_state if_condition(Token * tline, enum preproc_token ct)
break;
}
+ case PP_IFDIFI:
+ /*
+ * %ifdifi doesn't actually exist; it ignores its argument and is
+ * always false. This exists solely to stub out the corresponding
+ * TASM directive.
+ */
+ j = false;
+ goto fail;
+
case PP_IFENV:
tline = expand_smacro(tline);
j = false; /* have we matched yet? */
@@ -3100,7 +3017,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 || ppopt.noaliases || defining_alias) {
+ } else if (!smac->alias || ppconf.noaliases || defining_alias) {
/*
* We're redefining, so we have to take over an
* existing SMacro structure. This means freeing
@@ -3169,7 +3086,7 @@ 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 (!ppopt.noaliases) {
+ if (!ppconf.noaliases) {
if (s->in_progress) {
nasm_nonfatal("macro alias loop");
} else {
@@ -3255,7 +3172,7 @@ static bool parse_mmacro_spec(Token *tline, MMacro *def, const char *directive)
def->dlist = tline->next;
tline->next = NULL;
comma = count_mmac_params(def->dlist, &def->ndefs, &def->defaults);
- if (!ppopt.sane_empty_expansion && comma) {
+ if (!ppconf.sane_empty_expansion && comma) {
*comma = NULL;
def->ndefs--;
nasm_warn(WARN_MACRO_PARAMS_LEGACY,
@@ -3313,8 +3230,8 @@ static void do_pragma_preproc(Token *tline)
txt = tok_text(tline);
if (!nasm_stricmp(txt, "sane_empty_expansion")) {
tline = skip_white(tline->next);
- ppopt.sane_empty_expansion =
- pp_get_boolean_option(tline, ppopt.sane_empty_expansion);
+ ppconf.sane_empty_expansion =
+ pp_get_boolean_option(tline, ppconf.sane_empty_expansion);
} else {
/* Unknown pragma, ignore for now */
}
@@ -3422,6 +3339,78 @@ static void do_clear(enum clear_what what, bool context)
}
}
+/*
+ * Process a %line directive, including the gcc/cpp compatibility
+ * form with a # at the front.
+ */
+static int line_directive(Token *origline, Token *tline)
+{
+ int k, m;
+ bool err;
+ const char *dname;
+
+ /*
+ * Valid syntaxes:
+ * %line nnn[+mmm] [filename]
+ * %line nnn[+mmm] "filename" flags...
+ *
+ * "flags" are for gcc compatibility and are currently ignored.
+ *
+ * '#' at the beginning of the line is also treated as a %line
+ * directive, again for compatibility with gcc.
+ */
+ if ((ppopt & PP_NOLINE) || istk->mstk.mstk)
+ goto done;
+
+ dname = tok_text(tline);
+ tline = tline->next;
+ tline = skip_white(tline);
+ if (!tok_type(tline, TOK_NUMBER)) {
+ nasm_nonfatal("`%s' expects a line number", dname);
+ goto done;
+ }
+ k = readnum(tok_text(tline), &err);
+ m = 1;
+ tline = tline->next;
+ if (tok_is(tline, '+') || tok_is(tline, '-')) {
+ bool minus = tok_is(tline, '-');
+ tline = tline->next;
+ if (!tok_type(tline, TOK_NUMBER)) {
+ nasm_nonfatal("`%s' expects a line increment", dname);
+ goto done;
+ }
+ m = readnum(tok_text(tline), &err);
+ if (minus)
+ m = -m;
+ tline = tline->next;
+ }
+ tline = skip_white(tline);
+ if (tline) {
+ if (tline->type == TOK_STRING) {
+ /*
+ * If this is a quoted string, ignore anything after
+ * it; this allows for compatiblity with gcc's
+ * additional flags options.
+ */
+ src_set_fname(unquote_token(tline));
+ } else {
+ char *fname = detoken(tline, false);
+ src_set_fname(fname);
+ nasm_free(fname);
+ }
+ }
+ src_set_linnum(k);
+
+ istk->where = src_where();
+ istk->lineinc = m;
+ goto done;
+
+done:
+ free_tlist(origline);
+ return DIRECTIVE_FOUND;
+}
+
+
/**
* find and process preprocessor directive in passed line
* Find out if a line contains a preprocessor directive, and deal
@@ -3439,10 +3428,8 @@ static int do_directive(Token *tline, Token **output)
{
enum preproc_token op;
int j;
- bool err;
enum nolist_flags nolist;
bool casesense;
- int k, m;
int offset;
const char *p;
char *q, *qbuf;
@@ -3465,70 +3452,59 @@ static int do_directive(Token *tline, Token **output)
*output = NULL; /* No output generated */
origline = tline;
+ /* cpp-like line directive, must not be preceeded by whitespace */
+ if (tok_is(tline, '#'))
+ return line_directive(origline, tline);
+
tline = skip_white(tline);
- if (!tline || !tok_type(tline, TOK_PREPROC_ID))
- return NO_DIRECTIVE_FOUND;
+ if (!tline)
+ return NO_DIRECTIVE_FOUND;
- dname = tok_text(tline);
- if (dname[1] == '%')
- return NO_DIRECTIVE_FOUND;
+ switch (tline->type) {
+ case TOK_PREPROC_ID:
+ dname = tok_text(tline);
+ if (dname[1] == '%' || dname[1] == '$')
+ return NO_DIRECTIVE_FOUND;
- op = pp_token_hash(dname);
+ op = pp_token_hash(dname);
+ break;
- casesense = true;
- if (PP_HAS_CASE(op) & PP_INSENSITIVE(op)) {
- casesense = false;
- op--;
+ case TOK_ID:
+ if (likely(!(ppopt & PP_TASM)))
+ return NO_DIRECTIVE_FOUND;
+
+ dname = tok_text(tline);
+ op = pp_tasm_token_hash(dname);
+ break;
+
+ default:
+ return NO_DIRECTIVE_FOUND;
}
- /*
- * %line directives are always processed immediately and
- * unconditionally, as they are intended to reflect position
- * in externally preprocessed sources.
- */
- if (op == PP_LINE) {
+ switch (op) {
+ case PP_INVALID:
+ return NO_DIRECTIVE_FOUND;
+
+ case PP_LINE:
/*
- * Syntax is `%line nnn[+mmm] [filename]'
+ * %line directives are always processed immediately and
+ * unconditionally, as they are intended to reflect position
+ * in externally preprocessed sources.
*/
- if (pp_noline || istk->mstk.mstk)
- goto done;
+ if (op == PP_LINE)
+ return line_directive(origline, tline);
- tline = tline->next;
- tline = skip_white(tline);
- if (!tok_type(tline, TOK_NUMBER)) {
- nasm_nonfatal("`%s' expects line number", dname);
- goto done;
- }
- k = readnum(tok_text(tline), &err);
- m = 1;
- tline = tline->next;
- if (tok_is(tline, '+') || tok_is(tline, '-')) {
- bool minus = tok_is(tline, '-');
- tline = tline->next;
- if (!tok_type(tline, TOK_NUMBER)) {
- nasm_nonfatal("`%s' expects line increment", dname);
- goto done;
- }
- m = readnum(tok_text(tline), &err);
- if (minus)
- m = -m;
- tline = tline->next;
- }
- tline = skip_white(tline);
- if (tline) {
- if (tline->type == TOK_STRING) {
- src_set_fname(unquote_token(tline));
- } else {
- char *fname = detoken(tline, false);
- src_set_fname(fname);
- nasm_free(fname);
- }
- }
- src_set_linnum(k);
+ default:
+ break;
+ }
- istk->where = src_where();
- istk->lineinc = m;
+ if (unlikely(ppopt & PP_TRIVIAL))
goto done;
+
+ casesense = true;
+ if (PP_HAS_CASE(op) & PP_INSENSITIVE(op)) {
+ casesense = false;
+ op--;
}
/*
@@ -4703,7 +4679,7 @@ issue_error:
case PP_ALIASES:
tline = tline->next;
tline = expand_smacro(tline);
- ppopt.noaliases = !pp_get_boolean_option(tline, !ppopt.noaliases);
+ ppconf.noaliases = !pp_get_boolean_option(tline, !ppconf.noaliases);
break;
case PP_LINE:
@@ -5244,7 +5220,7 @@ static SMacro *expand_one_smacro(Token ***tpp)
* checking for parameters if necessary.
*/
list_for_each(m, head) {
- if (unlikely(m->alias && ppopt.noaliases))
+ if (unlikely(m->alias && ppconf.noaliases))
continue;
if (!mstrcmp(m->name, mname, m->casesense))
break;
@@ -6004,7 +5980,7 @@ static MMacro *is_mmacro(Token * tline, int *nparamp, Token ***paramsp)
*!-
*! It is highly recommended to use this option in new code.
*/
- if (!ppopt.sane_empty_expansion) {
+ if (!ppconf.sane_empty_expansion) {
if (!found) {
if (raw_nparam == 0 && !empty_args) {
/*
@@ -6190,7 +6166,7 @@ static struct debug_macro_addr *
debug_macro_get_addr_inv(int32_t seg, struct debug_macro_inv *inv)
{
struct debug_macro_addr *addr;
- static_assert(offsetof(struct debug_macro_addr, tree) == 0);
+ nasm_static_assert(offsetof(struct debug_macro_addr, tree) == 0);
if (likely(seg == inv->lastseg))
return inv->addr.last;
@@ -6280,7 +6256,7 @@ static void debug_macro_end(MMacro *m)
static void free_debug_macro_addr_tree(struct rbtree *tree)
{
struct rbtree *left, *right;
- static_assert(offsetof(struct debug_macro_addr,tree) == 0);
+ nasm_static_assert(offsetof(struct debug_macro_addr,tree) == 0);
if (!tree)
return;
@@ -6573,11 +6549,13 @@ static bool pp_suppress_error(errflags severity)
static Token *
stdmac_file(const SMacro *s, Token **params, int nparams)
{
+ const char *fname = src_get_fname();
+
(void)s;
(void)params;
(void)nparams;
- return make_tok_qstr(NULL, src_get_fname());
+ return fname ? make_tok_qstr(NULL, fname) : NULL;
}
static Token *
@@ -6648,60 +6626,25 @@ static void pp_add_magic_stdmac(void)
}
}
-static void
-pp_reset(const char *file, enum preproc_mode mode, struct strlist *dep_list)
+static void pp_reset_stdmac(enum preproc_mode mode)
{
int apass;
struct Include *inc;
- cstk = NULL;
- defining = NULL;
- nested_mac_count = 0;
- nested_rep_count = 0;
- init_macros();
- unique = 0;
- deplist = dep_list;
- pp_mode = mode;
-
- /* Reset options to default */
- nasm_zero(ppopt);
-
- /* Disable all debugging info, except in the last pass */
- ppdbg = 0;
- if (pass_final()) {
- if (dfmt->debug_macros)
- ppdbg |= PDBG_MACROS;
- }
-
- if (!use_loaded)
- use_loaded = nasm_malloc(use_package_count * sizeof(bool));
- memset(use_loaded, 0, use_package_count * sizeof(bool));
-
- /* First set up the top level input file */
- nasm_new(istk);
- istk->fp = nasm_open_read(file, NF_TEXT);
- if (!istk->fp) {
- nasm_fatalf(ERR_NOFILE, "unable to open input file `%s'%s%s",
- file, errno ? " " : "", errno ? strerror(errno) : "");
- }
- src_set(0, file);
- istk->where = src_where();
- istk->lineinc = 1;
-
- strlist_add(deplist, file);
-
/*
* Set up the stdmac packages as a virtual include file,
* indicated by a null file pointer.
*/
nasm_new(inc);
inc->next = istk;
- src_set(0, NULL);
- inc->where = src_where();
inc->nolist = inc->noline = !list_option('b');
istk = inc;
if (!istk->nolist)
lfmt->uplevel(LIST_INCLUDE, 0);
+ if (!istk->noline)
+ src_set(0, NULL);
+
+ istk->where = src_where();
pp_add_magic_stdmac();
@@ -6747,8 +6690,55 @@ pp_reset(const char *file, enum preproc_mode mode, struct strlist *dep_list)
define_smacro("__?PASS?__", true, make_tok_num(NULL, apass), NULL);
}
-static void pp_init(void)
+static void pp_reset(const char *file, enum preproc_mode mode,
+ struct strlist *dep_list)
+{
+ cstk = NULL;
+ defining = NULL;
+ nested_mac_count = 0;
+ nested_rep_count = 0;
+ init_macros();
+ unique = 0;
+ deplist = dep_list;
+ pp_mode = mode;
+
+ /* Reset options to default */
+ nasm_zero(ppconf);
+
+ /* Disable all debugging info, except in the last pass */
+ ppdbg = 0;
+ if (!(ppopt & PP_TRIVIAL)) {
+ if (pass_final()) {
+ if (dfmt->debug_macros)
+ ppdbg |= PDBG_MACROS;
+ }
+ }
+
+ memset(use_loaded, 0, use_package_count * sizeof(bool));
+
+ /* First set up the top level input file */
+ nasm_new(istk);
+ istk->fp = nasm_open_read(file, NF_TEXT);
+ if (!istk->fp) {
+ nasm_fatalf(ERR_NOFILE, "unable to open input file `%s'%s%s",
+ file, errno ? " " : "", errno ? strerror(errno) : "");
+ }
+ src_set(0, file);
+ istk->where = src_where();
+ istk->lineinc = 1;
+
+ strlist_add(deplist, file);
+
+ do_predef = false;
+
+ if (!(ppopt & PP_TRIVIAL))
+ pp_reset_stdmac(mode);
+}
+
+static void pp_init(enum preproc_opt opt)
{
+ ppopt = opt;
+ nasm_newn(use_loaded, use_package_count);
}
/*
@@ -6909,7 +6899,6 @@ static Token *pp_tokline(void)
nasm_free(line);
}
} else if ((line = read_line())) {
- line = prepreproc(line);
tline = tokenize(line);
nasm_free(line);
} else {
@@ -7236,7 +7225,8 @@ static void pp_error_list_macros(errflags severity)
src_error_reset();
}
-const struct preproc_ops nasmpp = {
+/* The normal NASM preprocessor */
+const struct preproc_ops preproc_nasm = {
pp_init,
pp_reset,
pp_getline,
diff --git a/asm/preproc.h b/asm/preproc.h
index 14d4cfd3..71130466 100644
--- a/asm/preproc.h
+++ b/asm/preproc.h
@@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- *
*
- * Copyright 1996-2009 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,12 +43,12 @@
extern const char * const pp_directives[];
extern const uint8_t pp_directives_len[];
-extern bool pp_noline;
/* Pointer to a macro chain */
typedef const unsigned char macros_t;
enum preproc_token pp_token_hash(const char *token);
+enum preproc_token pp_tasm_token_hash(const char *token);
/* Opens an include file or input file. This uses the include path. */
FILE *pp_input_fopen(const char *filename, enum file_flags mode);
diff --git a/include/nasm.h b/include/nasm.h
index 22fd6264..df1593e4 100644
--- a/include/nasm.h
+++ b/include/nasm.h
@@ -344,11 +344,17 @@ enum preproc_mode {
PP_PREPROC /* Preprocessing only */
};
+enum preproc_opt {
+ PP_TRIVIAL = 1, /* Only %line or # directives */
+ PP_NOLINE = 2, /* Ignore %line and # directives */
+ PP_TASM = 4 /* TASM compatibility hacks */
+};
+
struct preproc_ops {
/*
* Called once at the very start of assembly.
*/
- void (*init)(void);
+ void (*init)(enum preproc_opt opt);
/*
* Called at the start of a pass; given a file name, the number
@@ -398,8 +404,7 @@ struct preproc_ops {
bool (*suppress_error)(errflags severity);
};
-extern const struct preproc_ops nasmpp;
-extern const struct preproc_ops preproc_nop;
+extern const struct preproc_ops preproc_nasm;
/* List of dependency files */
extern struct strlist *depend_list;
More information about the Nasm-commits
mailing list