diff options
author | H. Peter Anvin (Intel) <hpa@zytor.com> | 2019-08-15 01:14:23 -0700 |
---|---|---|
committer | H. Peter Anvin (Intel) <hpa@zytor.com> | 2019-08-15 01:14:23 -0700 |
commit | 97cbdd34d093d8f580b57c1d73df2e3e100b67b9 (patch) | |
tree | 0119c000d6a59aa9c26fbdbc3f3cb1906cfb6a04 | |
parent | 5e3d741b00ecbcfbc682697f033d698fce8b38b3 (diff) | |
download | nasm-97cbdd34d093d8f580b57c1d73df2e3e100b67b9.tar.gz |
preproc: simplify handling of conditionals and casesense
Simplify the handling of conditionals; remove the PPC_* types.
Automate the generation of case-sensitive versus case-insensitive
directives, and make it so the bulk of the code doesn't have to worry
about it.
Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
-rw-r--r-- | asm/pptok.dat | 51 | ||||
-rwxr-xr-x | asm/pptok.pl | 95 | ||||
-rw-r--r-- | asm/preproc.c | 163 |
3 files changed, 140 insertions, 169 deletions
diff --git a/asm/pptok.dat b/asm/pptok.dat index 2a465d43..45610958 100644 --- a/asm/pptok.dat +++ b/asm/pptok.dat @@ -35,6 +35,12 @@ # A * at the end indicates a condition; the list of conditions are # on lines starting with *; the negatives are auto-generated # + +# Condition stems. %if MUST BE FIRST in this list. +%if* +%elif* + +# Condition tests * *ctx *def @@ -47,15 +53,26 @@ *num *str *token + +# Directives with -i- versions for case insensitive +%!assign +%!defalias +%!define +%!defstr +%!deftok +%!macro +%!pathsearch +%!rmacro +%!strcat +%!strlen +%!substr +%!xdefine +%un!macro + +# Other directives %arg -%assign %clear -%defalias -%define -%defstr -%deftok %depend -%elif* %else %endif %endm @@ -65,39 +82,17 @@ %exitmacro %exitrep %fatal -%iassign -%idefalias -%idefine -%idefstr -%ideftok -%if* -%imacro %include -%ipathsearch -%irmacro -%istrcat -%istrlen -%isubstr -%ixdefine %line %local -%macro -%pathsearch %pop %pragma %push %rep %repl -%rmacro %rotate %stacksize -%strcat -%strlen -%substr %undef %undefalias -%unimacro -%unmacro %use %warning -%xdefine diff --git a/asm/pptok.pl b/asm/pptok.pl index 2c28508f..e01334ff 100755 --- a/asm/pptok.pl +++ b/asm/pptok.pl @@ -1,7 +1,7 @@ #!/usr/bin/perl ## -------------------------------------------------------------------------- -## -## Copyright 1996-2009 The NASM Authors - All Rights Reserved +## +## Copyright 1996-2019 The NASM Authors - All Rights Reserved ## See the file AUTHORS included with the NASM distribution for ## the specific copyright holders. ## @@ -15,7 +15,7 @@ ## 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 @@ -51,41 +51,63 @@ while (defined($line = <IN>)) { next if ($line eq ''); if ($line =~ /^\%(.*)\*$/) { + # Condition stem push(@cctok, $1); + } elsif ($line =~ /^\%(.*\!.*)$/) { + # Directive with case insensitity "i" option + # Mnemonic: ! is "upside down i" + push(@ppitok, $1); } elsif ($line =~ /^\%(.*)$/) { + # Other directive push(@pptok, $1); } elsif ($line =~ /^\*(.*)$/) { + # Condition tail push(@cond, $1); } } close(IN); -@cctok = sort @cctok; +# Always sort %if first +@cctok = sort { $a eq 'if' ? -1 : $b eq 'if' ? 1 : $a cmp $b } @cctok; @cond = sort @cond; @pptok = sort @pptok; +@ppitok = sort @ppitok; # Generate the expanded list including conditionals. The conditionals # are at the beginning, padded to a power of 2, with the inverses -# interspersed; this allows a simple mask to pick out the condition. +# following each group; this allows a simple mask to pick out the condition, +# polarity, and directive type. while ((scalar @cond) & (scalar @cond)-1) { - push(@cond, undef); + push(@cond, sprintf("_COND_%d", scalar @cond)); } @cptok = (); foreach $ct (@cctok) { foreach $cc (@cond) { - if (defined($cc)) { - push(@cptok, $ct.$cc); - push(@cptok, $ct.'n'.$cc); - } else { - push(@cptok, undef, undef); - } + push(@cptok, $ct.$cc); + } + foreach $cc (@cond) { + push(@cptok, $ct.'n'.$cc); } } -$first_uncond = $pptok[0]; +$first_uncond = scalar @cptok; @pptok = (@cptok, @pptok); +# Generate the list of case-specific tokens; these are in pairs +# with the -i- variant following the plain variant +if (scalar(@pptok) & 1) { + push(@pptok, 'CASE_PAD'); +} + +$first_itoken = scalar @pptok; +foreach $it (@ppitok) { + (my $at = $it) =~ s/\!//; + (my $bt = $it) =~ s/\!/i/; + + push(@pptok, $at, $bt); +} + open(OUT, '>', $out) or die "$0: cannot open: $out\n"; # @@ -100,41 +122,35 @@ if ($what eq 'h') { $n = 0; foreach $pt (@pptok) { if (defined($pt)) { - printf OUT " %-16s = %3d,\n", "PP_\U$pt\E", $n; + printf OUT " %-24s = %3d,\n", "PP_\U$pt\E", $n; } $n++; } - printf OUT " %-16s = %3d\n", 'PP_INVALID', -1; + printf OUT " %-24s = %3d\n", 'PP_INVALID', -1; print OUT "};\n"; print OUT "\n"; - print OUT "enum pp_conditional {\n"; - $n = 0; - $c = ''; - foreach $cc (@cond) { - if (defined($cc)) { - printf OUT "$c %-16s = %3d", "PPC_IF\U$cc\E", $n; - $c = ','; - } - $n += 2; - } - print OUT "\n};\n\n"; - - printf OUT "#define PP_COND(x) ((enum pp_conditional)((x) & 0x%x))\n", - (scalar(@cond)-1) << 1; - print OUT "#define PP_IS_COND(x) ((unsigned int)(x) < PP_\U$first_uncond\E)\n"; - print OUT "#define PP_NEGATIVE(x) ((x) & 1)\n"; + printf OUT "#define PP_COND(x) ((x) & 0x%x)\n", + (scalar(@cond)-1); + printf OUT "#define PP_IS_COND(x) ((unsigned int)(x) < PP_%s)\n", + uc($pptok[$first_uncond]); + printf OUT "#define PP_COND_NEGATIVE(x) (!!((x) & 0x%x))\n", scalar(@cond); + print OUT "\n"; + printf OUT "#define PP_HAS_CASE(x) ((x) >= PP_%s)\n", + uc($pptok[$first_itoken]); + print OUT "#define PP_INSENSITIVE(x) ((x) & 1)\n"; print OUT "\n"; foreach $ct (@cctok) { print OUT "#define CASE_PP_\U$ct\E"; $pref = " \\\n"; foreach $cc (@cond) { - if (defined($cc)) { - print OUT "$pref\tcase PP_\U${ct}${cc}\E: \\\n"; - print OUT "\tcase PP_\U${ct}N${cc}\E"; - $pref = ":\\\n"; - } + print OUT "$pref\tcase PP_\U${ct}${cc}\E"; + $pref = ":\\\n"; + } + foreach $cc (@cond) { + print OUT "$pref\tcase PP_\U${ct}N${cc}\E"; + $pref = ":\\\n"; } print OUT "\n"; # No colon or newline on the last one } @@ -153,7 +169,8 @@ if ($what eq 'c') { my $n = 0; foreach $pt (@pptok) { - if (defined($pt)) { + # Upper case characters signify internal use tokens only + if (defined($pt) && $pt !~ /[A-Z]/) { $tokens{'%'.$pt} = $n; if ($pt =~ /[\@\[\]\\_]/) { # Fail on characters which look like upper-case letters @@ -253,7 +270,7 @@ if ($what eq 'ph') { print OUT "# Automatically generated from $in by $0\n"; print OUT "# Do not edit\n"; print OUT "\n"; - + print OUT "%pptok_hash = (\n"; $n = 0; foreach $tok (@pptok) { @@ -265,5 +282,3 @@ if ($what eq 'ph') { print OUT ");\n"; print OUT "1;\n"; } - - diff --git a/asm/preproc.c b/asm/preproc.c index 664950fc..9c84e505 100644 --- a/asm/preproc.c +++ b/asm/preproc.c @@ -305,11 +305,7 @@ struct hash_table FileHash; * included from within the true branch of a `%if' won't terminate * it and cause confusion: instead, rightly, it'll cause an error.) */ -struct Cond { - Cond *next; - int state; -}; -enum { +enum cond_state { /* * These states are for use just after %if or %elif: IF_TRUE * means the condition has evaluated to truth so we are @@ -336,6 +332,10 @@ enum { */ COND_DONE, COND_NEVER }; +struct Cond { + Cond *next; + enum cond_state state; +}; #define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE ) /* @@ -1820,9 +1820,8 @@ static void count_mmac_params(Token * t, int *nparam, Token *** params) * * We must free the tline we get passed. */ -static bool if_condition(Token * tline, enum preproc_token ct) +static enum cond_state if_condition(Token * tline, enum preproc_token ct) { - enum pp_conditional i = PP_COND(ct); bool j; Token *t, *tt, *origline; struct ppscan pps; @@ -1830,11 +1829,13 @@ static bool if_condition(Token * tline, enum preproc_token ct) expr *evalresult; enum pp_token_type needtype; char *p; + const char *dname = pp_directives[ct]; + bool casesense = true; origline = tline; - switch (i) { - case PPC_IFCTX: + switch (PP_COND(ct)) { + case PP_IFCTX: j = false; /* have we matched yet? */ while (true) { skip_white_(tline); @@ -1842,9 +1843,8 @@ static bool if_condition(Token * tline, enum preproc_token ct) break; if (tline->type != TOK_ID) { nasm_nonfatal("`%s' expects context identifiers", - pp_directives[ct]); - free_tlist(origline); - return -1; + dname); + goto fail; } if (cstk && cstk->name && !nasm_stricmp(tline->text, cstk->name)) j = true; @@ -1852,7 +1852,7 @@ static bool if_condition(Token * tline, enum preproc_token ct) } break; - case PPC_IFDEF: + case PP_IFDEF: j = false; /* have we matched yet? */ while (tline) { skip_white_(tline); @@ -1860,7 +1860,7 @@ static bool if_condition(Token * tline, enum preproc_token ct) (tline->type != TOK_PREPROC_ID || tline->text[1] != '$'))) { nasm_nonfatal("`%s' expects macro identifiers", - pp_directives[ct]); + dname); goto fail; } if (smacro_defined(NULL, tline->text, 0, NULL, true)) @@ -1869,7 +1869,7 @@ static bool if_condition(Token * tline, enum preproc_token ct) } break; - case PPC_IFENV: + case PP_IFENV: tline = expand_smacro(tline); j = false; /* have we matched yet? */ while (tline) { @@ -1879,7 +1879,7 @@ static bool if_condition(Token * tline, enum preproc_token ct) (tline->type != TOK_PREPROC_ID || tline->text[1] != '!'))) { nasm_nonfatal("`%s' expects environment variable names", - pp_directives[ct]); + dname); goto fail; } p = tline->text; @@ -1893,15 +1893,17 @@ static bool if_condition(Token * tline, enum preproc_token ct) } break; - case PPC_IFIDN: - case PPC_IFIDNI: + case PP_IFIDNI: + casesense = false; + /* fall through */ + case PP_IFIDN: tline = expand_smacro(tline); t = tt = tline; while (tok_isnt_(tt, ",")) tt = tt->next; if (!tt) { nasm_nonfatal("`%s' expects two comma-separated arguments", - pp_directives[ct]); + dname); goto fail; } tt = tt->next; @@ -1909,7 +1911,7 @@ static bool if_condition(Token * tline, enum preproc_token ct) while ((t->type != TOK_OTHER || strcmp(t->text, ",")) && tt) { if (tt->type == TOK_OTHER && !strcmp(tt->text, ",")) { nasm_nonfatal("`%s': more than one comma on line", - pp_directives[ct]); + dname); goto fail; } if (t->type == TOK_WHITESPACE) { @@ -1933,11 +1935,11 @@ static bool if_condition(Token * tline, enum preproc_token ct) j = false; break; } - if (mmemcmp(t->text, tt->text, l1, i == PPC_IFIDN)) { + if (mmemcmp(t->text, tt->text, l1, casesense)) { j = false; break; } - } else if (mstrcmp(tt->text, t->text, i == PPC_IFIDN) != 0) { + } else if (mstrcmp(tt->text, t->text, casesense) != 0) { j = false; /* found mismatching tokens */ break; } @@ -1949,7 +1951,7 @@ static bool if_condition(Token * tline, enum preproc_token ct) j = false; /* trailing gunk on one end or other */ break; - case PPC_IFMACRO: + case PP_IFMACRO: { bool found = false; MMacro searching, *mmac; @@ -1957,7 +1959,7 @@ static bool if_condition(Token * tline, enum preproc_token ct) skip_white_(tline); tline = expand_id(tline); if (!tok_type_(tline, TOK_ID)) { - nasm_nonfatal("`%s' expects a macro name", pp_directives[ct]); + nasm_nonfatal("`%s' expects a macro name", dname); goto fail; } searching.name = nasm_strdup(tline->text); @@ -1974,7 +1976,7 @@ static bool if_condition(Token * tline, enum preproc_token ct) if (!tline) { } else if (!tok_type_(tline, TOK_NUMBER)) { nasm_nonfatal("`%s' expects a parameter count or nothing", - pp_directives[ct]); + dname); } else { searching.nparam_min = searching.nparam_max = read_param_count(tline->text); @@ -1985,7 +1987,7 @@ static bool if_condition(Token * tline, enum preproc_token ct) searching.nparam_max = INT_MAX; else if (!tok_type_(tline, TOK_NUMBER)) nasm_nonfatal("`%s' expects a parameter count after `-'", - pp_directives[ct]); + dname); else { searching.nparam_max = read_param_count(tline->text); if (searching.nparam_min > searching.nparam_max) { @@ -2017,13 +2019,13 @@ static bool if_condition(Token * tline, enum preproc_token ct) break; } - case PPC_IFID: + case PP_IFID: needtype = TOK_ID; goto iftype; - case PPC_IFNUM: + case PP_IFNUM: needtype = TOK_NUMBER; goto iftype; - case PPC_IFSTR: + case PP_IFSTR: needtype = TOK_STRING; goto iftype; @@ -2040,7 +2042,7 @@ iftype: j = tok_type_(t, needtype); break; - case PPC_IFTOKEN: + case PP_IFTOKEN: t = tline = expand_smacro(tline); while (tok_type_(t, TOK_WHITESPACE)) t = t->next; @@ -2054,7 +2056,7 @@ iftype: } break; - case PPC_IFEMPTY: + case PP_IFEMPTY: t = tline = expand_smacro(tline); while (tok_type_(t, TOK_WHITESPACE)) t = t->next; @@ -2062,7 +2064,7 @@ iftype: j = !t; /* Should be empty */ break; - case PPC_IF: + case PP_IF: pps.tptr = tline = expand_smacro(tline); pps.ntokens = -1; tokval.t_type = TOKEN_INVALID; @@ -2073,24 +2075,23 @@ iftype: nasm_warn(WARN_OTHER, "trailing garbage after expression ignored"); if (!is_simple(evalresult)) { nasm_nonfatal("non-constant value given to `%s'", - pp_directives[ct]); + dname); goto fail; } j = reloc_value(evalresult) != 0; break; default: - nasm_fatal("preprocessor directive `%s' not yet implemented", - pp_directives[ct]); + nasm_nonfatal("unknown preprocessor directive `%s'", dname); goto fail; } free_tlist(origline); - return j ^ PP_NEGATIVE(ct); + return (j ^ PP_COND_NEGATIVE(ct)) ? COND_IF_TRUE : COND_IF_FALSE; fail: free_tlist(origline); - return -1; + return COND_NEVER; } /* @@ -2451,7 +2452,7 @@ static bool is_macro_id(const Token *t) (t->type == TOK_PREPROC_ID && t->text[1] == '$')); } -static char *get_id(Token **tp, enum preproc_token pp, const char *err) +static char *get_id(Token **tp, const char *dname, const char *err) { char *id; Token *t = *tp; @@ -2461,7 +2462,7 @@ static char *get_id(Token **tp, enum preproc_token pp, const char *err) t = expand_id(t); if (!is_macro_id(t)) { - nasm_nonfatal("`%s' expects a %s", pp_directives[pp], + nasm_nonfatal("`%s' expects a %s", dname, err ? err : "macro identifier"); return NULL; } @@ -2523,16 +2524,13 @@ static int do_directive(Token *tline, Token **output) tline->text[1] == '!'))) return NO_DIRECTIVE_FOUND; + dname = tline->text; i = pp_token_hash(tline->text); - /* - * FIXME: We zap execution of PP_RMACRO, PP_IRMACRO, PP_EXITMACRO - * since they are known to be buggy at moment, we need to fix them - * in future release (2.09-2.10) - */ - if (i == PP_RMACRO || i == PP_IRMACRO || i == PP_EXITMACRO) { - nasm_nonfatal("unknown preprocessor directive `%s'", tline->text); - return NO_DIRECTIVE_FOUND; + casesense = true; + if (PP_HAS_CASE(i) & PP_INSENSITIVE(i)) { + casesense = false; + i--; } /* @@ -2552,16 +2550,14 @@ static int do_directive(Token *tline, Token **output) * %endm/%endmacro, and (only if we're in a %rep block) %endrep. * If we're in a %rep block, another %rep nests, so should be let through. */ - if (defining && i != PP_MACRO && i != PP_IMACRO && - i != PP_RMACRO && i != PP_IRMACRO && + if (defining && i != PP_MACRO && i != PP_RMACRO && i != PP_ENDMACRO && i != PP_ENDM && (defining->name || (i != PP_ENDREP && i != PP_REP))) { return NO_DIRECTIVE_FOUND; } if (defining) { - if (i == PP_MACRO || i == PP_IMACRO || - i == PP_RMACRO || i == PP_IRMACRO) { + if (i == PP_MACRO || i == PP_RMACRO) { nested_mac_count++; return NO_DIRECTIVE_FOUND; } else if (nested_mac_count > 0) { @@ -2583,11 +2579,9 @@ static int do_directive(Token *tline, Token **output) } } - dname = pp_directives[i]; /* Directive name, for error messages */ - casesense = true; /* Default to case sensitive */ switch (i) { default: - nasm_nonfatal("unknown preprocessor directive `%s'", tline->text); + nasm_nonfatal("unknown preprocessor directive `%s'", dname); return NO_DIRECTIVE_FOUND; /* didn't get it */ case PP_PRAGMA: @@ -2874,7 +2868,7 @@ static int do_directive(Token *tline, Token **output) static macros_t *use_pkg; const char *pkg_macro = NULL; - if (!(mname = get_id(&tline, i, "package name"))) + if (!(mname = get_id(&tline, dname, "package name"))) goto done; if (tline->next) nasm_warn(WARN_OTHER, "trailing garbage after `%s' ignored", dname); @@ -2995,7 +2989,6 @@ issue_error: else { j = if_condition(tline->next, i); tline->next = NULL; /* it got freed */ - j = j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE; } cond = nasm_malloc(sizeof(Cond)); cond->next = istk->conds; @@ -3035,12 +3028,10 @@ issue_error: */ j = if_condition(expand_mmac_params(tline->next), i); tline->next = NULL; /* it got freed */ - istk->conds->state = - j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE; + istk->conds->state = j; break; } - free_tlist(origline); - return DIRECTIVE_FOUND; + break; case PP_ELSE: if (tline->next) @@ -3083,10 +3074,6 @@ issue_error: istk->mstk->condcnt--; break; - case PP_IRMACRO: - case PP_IMACRO: - casesense = false; - /* fall through */ case PP_RMACRO: case PP_MACRO: if (defining) @@ -3332,11 +3319,6 @@ issue_error: nasm_nonfatal("`%%exitrep' not within `%%rep' block"); break; - case PP_IDEFINE: - case PP_IXDEFINE: - case PP_IDEFALIAS: - casesense = false; - /* fall through */ case PP_DEFINE: case PP_XDEFINE: case PP_DEFALIAS: @@ -3345,7 +3327,7 @@ issue_error: bool *eval_params = NULL; SMacro tmpl; - if (!(mname = get_id(&tline, i, NULL))) + if (!(mname = get_id(&tline, dname, NULL))) goto done; nasm_zero(tmpl); @@ -3425,7 +3407,7 @@ issue_error: last = tline, tline = tline->next; last->next = NULL; - if (unlikely(i == PP_DEFALIAS || i == PP_IDEFALIAS)) { + if (unlikely(i == PP_DEFALIAS)) { macro_start = tline; if (!is_macro_id(macro_start)) { nasm_nonfatal("`%s' expects a macro identifier to alias", @@ -3444,7 +3426,7 @@ issue_error: tmpl.alias = true; } else { /* Expand the macro definition now for %xdefine and %ixdefine */ - if (i == PP_XDEFINE || i == PP_IXDEFINE) + if (i == PP_XDEFINE) tline = expand_smacro(tline); macro_start = NULL; @@ -3480,7 +3462,7 @@ issue_error: case PP_UNDEF: case PP_UNDEFALIAS: - if (!(mname = get_id(&tline, i, NULL))) + if (!(mname = get_id(&tline, dname, NULL))) goto done; if (tline->next) nasm_warn(WARN_OTHER, "trailing garbage after macro name ignored"); @@ -3488,11 +3470,8 @@ issue_error: undef_smacro(mname, i == PP_UNDEFALIAS); break; - case PP_IDEFSTR: - casesense = false; - /* fall through */ case PP_DEFSTR: - if (!(mname = get_id(&tline, i, NULL))) + if (!(mname = get_id(&tline, dname, NULL))) goto done; last = tline; @@ -3514,11 +3493,8 @@ issue_error: define_smacro(mname, casesense, macro_start, NULL); break; - case PP_IDEFTOK: - casesense = false; - /* fall through */ case PP_DEFTOK: - if (!(mname = get_id(&tline, i, NULL))) + if (!(mname = get_id(&tline, dname, NULL))) goto done; last = tline; @@ -3552,14 +3528,11 @@ issue_error: free_tlist(tline); break; - case PP_IPATHSEARCH: - casesense = false; - /* fall through */ case PP_PATHSEARCH: { const char *found_path; - if (!(mname = get_id(&tline, i, NULL))) + if (!(mname = get_id(&tline, dname, NULL))) goto done; last = tline; @@ -3597,11 +3570,8 @@ issue_error: break; } - case PP_ISTRLEN: - casesense = false; - /* fall through */ case PP_STRLEN: - if (!(mname = get_id(&tline, i, NULL))) + if (!(mname = get_id(&tline, dname, NULL))) goto done; last = tline; @@ -3631,11 +3601,8 @@ issue_error: free_tlist(origline); return DIRECTIVE_FOUND; - case PP_ISTRCAT: - casesense = false; - /* fall through */ case PP_STRCAT: - if (!(mname = get_id(&tline, i, NULL))) + if (!(mname = get_id(&tline, dname, NULL))) goto done; last = tline; @@ -3680,15 +3647,12 @@ issue_error: free_tlist(tline); break; - case PP_ISUBSTR: - casesense = false; - /* fall through */ case PP_SUBSTR: { int64_t start, count; size_t len; - if (!(mname = get_id(&tline, i, NULL))) + if (!(mname = get_id(&tline, dname, NULL))) goto done; last = tline; @@ -3766,11 +3730,8 @@ issue_error: break; } - case PP_IASSIGN: - casesense = false; - /* fall through */ case PP_ASSIGN: - if (!(mname = get_id(&tline, i, NULL))) + if (!(mname = get_id(&tline, dname, NULL))) goto done; last = tline; |