From da10e7b85e7a85aa7b51605f66fc860914b3b571 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Wed, 12 Sep 2007 04:18:37 +0000 Subject: [PATCH] More automation in the preprocessor conditionals handling Further automate the production of preprocessor conditionals. Now the code automatically folds if/elif and the negatives. --- pptok.pl | 87 ++++++++++++++++++------- preproc.c | 220 +++++++++++++++++++------------------------------------------- 2 files changed, 131 insertions(+), 176 deletions(-) diff --git a/pptok.pl b/pptok.pl index 759a9a0..9a00ea2 100755 --- a/pptok.pl +++ b/pptok.pl @@ -17,9 +17,9 @@ while (defined($line = )) { $line =~ s/\s*\#.*$//; # Remove comments and trailing whitespace next if ($line eq ''); - if ($line =~ /^(\%.*)\*$/) { + if ($line =~ /^\%(.*)\*$/) { push(@cctok, $1); - } elsif ($line =~ /^(\%.*)$/) { + } elsif ($line =~ /^\%(.*)$/) { push(@pptok, $1); } elsif ($line =~ /^\*(.*)$/) { push(@cond, $1); @@ -29,16 +29,29 @@ close(IN); @cctok = sort @cctok; @cond = sort @cond; +@pptok = sort @pptok; + +# 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. -# Generate the expanded list including conditionals +while ((scalar @cond) & (scalar @cond)-1) { + push(@cond, undef); +} + +@cptok = (); foreach $ct (@cctok) { foreach $cc (@cond) { - push(@pptok, $ct.$cc); - push(@pptok, $ct.'n'.$cc); + if (defined($cc)) { + push(@cptok, $ct.$cc); + push(@cptok, $ct.'n'.$cc); + } else { + push(@cptok, undef, undef); + } } } - -@pptok = sort @pptok; +$first_uncond = $pptok[0]; +@pptok = (@cptok, @pptok); open(OUT, "> $out") or die "$0: cannot open: $out\n"; print OUT "/* Automatically generated from $in by $0 */\n"; @@ -50,21 +63,44 @@ print OUT "\n"; # if ($what eq 'h') { print OUT "enum preproc_token {\n"; + $n = 0; foreach $pt (@pptok) { - (my $px = $pt) =~ s/\%//g; - print OUT " PP_\U$px\E,\n"; + if (defined($pt)) { + printf OUT " %-16s = %3d,\n", "PP_\U$pt\E", $n; + } + $n++; } - print OUT " PP_INVALID = -1\n"; + printf OUT " %-16s = %3d\n", 'PP_INVALID', -1; print OUT "};\n"; print OUT "\n"; - $first_cc = $cond[0]; - $last_cc = $cond[(scalar @cond)-1]; + print OUT "enum pp_conditional {\n"; + $n = 0; + foreach $cc (@cond) { + if (defined($cc)) { + printf OUT " %-16s = %3d,\n", "PPC_IF\U$cc\E", $n; + } + $n += 2; + } + print OUT "};\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"; + print OUT "\n"; foreach $ct (@cctok) { - (my $cx = $ct) =~ s/\%//g; - print OUT "#define IS_PP_\U$cx\E(x) ((x) >= PP_\U$cx$first_cc\E && "; - print OUT "(x) <= PP_\U$cx$last_cc\E)\n"; + 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 "\n"; # No colon or newline on the last one } } @@ -75,10 +111,12 @@ if ($what eq 'c') { my %tokens = (); my @tokendata = (); + my $n = 0; foreach $pt (@pptok) { - (my $px = $pt) =~ s/\%//g; - $tokens{$pt} = scalar @tokendata; - push(@tokendata, $pt); + if (defined($pt)) { + $tokens{'%'.$pt} = $n; + } + $n++; } my @hashinfo = gen_perfect_hash(\%tokens); @@ -104,10 +142,13 @@ if ($what eq 'c') { print OUT "\n"; # Note that this is global. - printf OUT "const char * const pp_directives[%d] = {\n", - scalar(@tokendata); - foreach $d (@tokendata) { - print OUT " \"$d\",\n"; + printf OUT "const char * const pp_directives[%d] = {\n", scalar(@pptok); + foreach $d (@pptok) { + if (defined($d)) { + print OUT " \"%$d\",\n"; + } else { + print OUT " NULL,\n"; + } } print OUT "};\n"; @@ -149,7 +190,7 @@ if ($what eq 'c') { print OUT " }\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(@tokendata); + printf OUT " if (ix >= %d)\n", scalar(@pptok); print OUT " return PP_INVALID;\n"; print OUT "\n"; diff --git a/preproc.c b/preproc.c index 68aea7e..fa2a953 100644 --- a/preproc.c +++ b/preproc.c @@ -137,16 +137,18 @@ struct Context { * mechanism as an alternative to trying to find a sensible type of * quote to use on the filename we were passed. */ +enum pp_token_type { + TOK_NONE = 0, TOK_WHITESPACE, TOK_COMMENT, TOK_ID, + TOK_PREPROC_ID, TOK_STRING, + TOK_NUMBER, TOK_SMAC_END, TOK_OTHER, TOK_SMAC_PARAM, + TOK_INTERNAL_STRING +}; + struct Token { Token *next; char *text; SMacro *mac; /* associated macro for TOK_SMAC_END */ - int type; -}; -enum { - TOK_WHITESPACE = 1, TOK_COMMENT, TOK_ID, TOK_PREPROC_ID, TOK_STRING, - TOK_NUMBER, TOK_SMAC_END, TOK_OTHER, TOK_SMAC_PARAM, - TOK_INTERNAL_STRING + enum pp_token_type type; }; /* @@ -274,8 +276,7 @@ static int inverse_ccs[] = { /* If this is a an IF, ELIF, ELSE or ENDIF keyword */ static int is_condition(enum preproc_token arg) { - return IS_PP_IF(arg) || IS_PP_ELIF(arg) || - (arg == PP_ELSE) || (arg == PP_ENDIF); + return PP_IS_COND(arg) || (arg == PP_ELSE) || (arg == PP_ENDIF); } /* For TASM compatibility we need to be able to recognise TASM compatible @@ -383,7 +384,7 @@ static void make_tok_num(Token * tok, int32_t val); static void error(int severity, const char *fmt, ...); static void *new_Block(size_t size); static void delete_Blocks(void); -static Token *new_Token(Token * next, int type, char *text, int txtlen); +static Token *new_Token(Token * next, enum pp_token_type type, char *text, int txtlen); static Token *delete_Token(Token * t); /* @@ -683,7 +684,7 @@ static char *read_line(void) static Token *tokenize(char *line) { char *p = line; - int type; + enum pp_token_type type; Token *list = NULL; Token *t, **tail = &list; @@ -862,7 +863,7 @@ static void delete_Blocks(void) * back to the caller. It sets the type and text elements, and * also the mac and next elements to NULL. */ -static Token *new_Token(Token * next, int type, char *text, int txtlen) +static Token *new_Token(Token * next, enum pp_token_type type, char *text, int txtlen) { Token *t; int i; @@ -1269,26 +1270,25 @@ static void count_mmac_params(Token * t, int *nparam, Token *** params) * * We must free the tline we get passed. */ -static int if_condition(Token * tline, int i) +static int if_condition(Token * tline, enum preproc_token ct) { - int j, casesense; + enum pp_conditional i = PP_COND(ct); + int j; Token *t, *tt, **tptr, *origline; struct tokenval tokval; expr *evalresult; + enum pp_token_type needtype; origline = tline; switch (i) { - case PP_IFCTX: - case PP_ELIFCTX: - case PP_IFNCTX: - case PP_ELIFNCTX: + case PPC_IFCTX: j = FALSE; /* have we matched yet? */ while (cstk && tline) { skip_white_(tline); if (!tline || tline->type != TOK_ID) { error(ERR_NONFATAL, - "`%s' expects context identifiers", pp_directives[i]); + "`%s' expects context identifiers", pp_directives[ct]); free_tlist(origline); return -1; } @@ -1296,15 +1296,9 @@ static int if_condition(Token * tline, int i) j = TRUE; tline = tline->next; } - if (i == PP_IFNCTX || i == PP_ELIFNCTX) - j = !j; - free_tlist(origline); - return j; + break; - case PP_IFDEF: - case PP_ELIFDEF: - case PP_IFNDEF: - case PP_ELIFNDEF: + case PPC_IFDEF: j = FALSE; /* have we matched yet? */ while (tline) { skip_white_(tline); @@ -1312,27 +1306,17 @@ static int if_condition(Token * tline, int i) (tline->type != TOK_PREPROC_ID || tline->text[1] != '$'))) { error(ERR_NONFATAL, - "`%s' expects macro identifiers", pp_directives[i]); - free_tlist(origline); - return -1; + "`%s' expects macro identifiers", pp_directives[ct]); + goto fail; } if (smacro_defined(NULL, tline->text, 0, NULL, 1)) j = TRUE; tline = tline->next; } - if (i == PP_IFNDEF || i == PP_ELIFNDEF) - j = !j; - free_tlist(origline); - return j; + break; - case PP_IFIDN: - case PP_ELIFIDN: - case PP_IFNIDN: - case PP_ELIFNIDN: - case PP_IFIDNI: - case PP_ELIFIDNI: - case PP_IFNIDNI: - case PP_ELIFNIDNI: + case PPC_IFIDN: + case PPC_IFIDNI: tline = expand_smacro(tline); t = tt = tline; while (tok_isnt_(tt, ",")) @@ -1340,20 +1324,16 @@ static int if_condition(Token * tline, int i) if (!tt) { error(ERR_NONFATAL, "`%s' expects two comma-separated arguments", - pp_directives[i]); - free_tlist(tline); - return -1; + pp_directives[ct]); + goto fail; } tt = tt->next; - casesense = (i == PP_IFIDN || i == PP_ELIFIDN || - i == PP_IFNIDN || i == PP_ELIFNIDN); j = TRUE; /* assume equality unless proved not */ while ((t->type != TOK_OTHER || strcmp(t->text, ",")) && tt) { if (tt->type == TOK_OTHER && !strcmp(tt->text, ",")) { error(ERR_NONFATAL, "`%s': more than one comma on line", - pp_directives[i]); - free_tlist(tline); - return -1; + pp_directives[ct]); + goto fail; } if (t->type == TOK_WHITESPACE) { t = t->next; @@ -1372,7 +1352,7 @@ static int if_condition(Token * tline, int i) tt->text[0] = t->text[0]; tt->text[strlen(tt->text) - 1] = t->text[0]; } - if (mstrcmp(tt->text, t->text, casesense) != 0) { + if (mstrcmp(tt->text, t->text, i == PPC_IFIDN) != 0) { j = FALSE; /* found mismatching tokens */ break; } @@ -1382,16 +1362,9 @@ static int if_condition(Token * tline, int i) } if ((t->type != TOK_OTHER || strcmp(t->text, ",")) || tt) j = FALSE; /* trailing gunk on one end or other */ - if (i == PP_IFNIDN || i == PP_ELIFNIDN || - i == PP_IFNIDNI || i == PP_ELIFNIDNI) - j = !j; - free_tlist(tline); - return j; + break; - case PP_IFMACRO: - case PP_ELIFMACRO: - case PP_IFNMACRO: - case PP_ELIFNMACRO: + case PPC_IFMACRO: { int found = 0; MMacro searching, *mmac; @@ -1401,8 +1374,8 @@ static int if_condition(Token * tline, int i) tline = expand_id(tline); if (!tok_type_(tline, TOK_ID)) { error(ERR_NONFATAL, - "`%s' expects a macro name", pp_directives[i]); - return -1; + "`%s' expects a macro name", pp_directives[ct]); + goto fail; } searching.name = nasm_strdup(tline->text); searching.casesense = (i == PP_MACRO); @@ -1418,7 +1391,7 @@ static int if_condition(Token * tline, int i) } else if (!tok_type_(tline, TOK_NUMBER)) { error(ERR_NONFATAL, "`%s' expects a parameter count or nothing", - pp_directives[i]); + pp_directives[ct]); } else { searching.nparam_min = searching.nparam_max = readnum(tline->text, &j); @@ -1434,7 +1407,7 @@ static int if_condition(Token * tline, int i) else if (!tok_type_(tline, TOK_NUMBER)) error(ERR_NONFATAL, "`%s' expects a parameter count after `-'", - pp_directives[i]); + pp_directives[ct]); else { searching.nparam_max = readnum(tline->text, &j); if (j) @@ -1463,67 +1436,36 @@ static int if_condition(Token * tline, int i) mmac = mmac->next; } nasm_free(searching.name); - free_tlist(origline); - if (i == PP_IFNMACRO || i == PP_ELIFNMACRO) - found = !found; - return found; + j = found; + break; } - case PP_IFID: - case PP_ELIFID: - case PP_IFNID: - case PP_ELIFNID: - case PP_IFNUM: - case PP_ELIFNUM: - case PP_IFNNUM: - case PP_ELIFNNUM: - case PP_IFSTR: - case PP_ELIFSTR: - case PP_IFNSTR: - case PP_ELIFNSTR: + case PPC_IFID: + needtype = TOK_ID; + goto iftype; + case PPC_IFNUM: + needtype = TOK_NUMBER; + goto iftype; + case PPC_IFSTR: + needtype = TOK_STRING; + goto iftype; + + iftype: tline = expand_smacro(tline); t = tline; while (tok_type_(t, TOK_WHITESPACE)) t = t->next; j = FALSE; /* placate optimiser */ if (t) - switch (i) { - case PP_IFID: - case PP_ELIFID: - case PP_IFNID: - case PP_ELIFNID: - j = (t->type == TOK_ID); - break; - case PP_IFNUM: - case PP_ELIFNUM: - case PP_IFNNUM: - case PP_ELIFNNUM: - j = (t->type == TOK_NUMBER); - break; - case PP_IFSTR: - case PP_ELIFSTR: - case PP_IFNSTR: - case PP_ELIFNSTR: - j = (t->type == TOK_STRING); - break; - } - if (i == PP_IFNID || i == PP_ELIFNID || - i == PP_IFNNUM || i == PP_ELIFNNUM || - i == PP_IFNSTR || i == PP_ELIFNSTR) - j = !j; - free_tlist(tline); - return j; + j = t->type == needtype; + break; - case PP_IF: - case PP_IFN: - case PP_ELIF: - case PP_ELIFN: + case PPC_IF: t = tline = expand_smacro(tline); tptr = &t; tokval.t_type = TOKEN_INVALID; evalresult = evaluate(ppscan, tptr, &tokval, NULL, pass | CRITICAL, error, NULL); - free_tlist(tline); if (!evalresult) return -1; if (tokval.t_type) @@ -1531,20 +1473,24 @@ static int if_condition(Token * tline, int i) "trailing garbage after expression ignored"); if (!is_simple(evalresult)) { error(ERR_NONFATAL, - "non-constant value given to `%s'", pp_directives[i]); - return -1; + "non-constant value given to `%s'", pp_directives[ct]); + goto fail; } j = reloc_value(evalresult) != 0; - if (i == PP_IFN || i == PP_ELIFN) - j = !j; return j; default: error(ERR_FATAL, "preprocessor directive `%s' not yet implemented", - pp_directives[i]); - free_tlist(origline); - return -1; /* yeah, right */ + pp_directives[ct]); + goto fail; } + + free_tlist(origline); + return j ^ PP_NEGATIVE(ct); + +fail: + free_tlist(origline); + return -1; } /* @@ -1957,24 +1903,7 @@ static int do_directive(Token * tline) free_tlist(origline); break; - case PP_IF: - case PP_IFCTX: - case PP_IFDEF: - case PP_IFID: - case PP_IFIDN: - case PP_IFIDNI: - case PP_IFMACRO: - case PP_IFN: - case PP_IFNCTX: - case PP_IFNDEF: - case PP_IFNID: - case PP_IFNIDN: - case PP_IFNIDNI: - case PP_IFNMACRO: - case PP_IFNNUM: - case PP_IFNSTR: - case PP_IFNUM: - case PP_IFSTR: + CASE_PP_IF: if (istk->conds && !emitting(istk->conds->state)) j = COND_NEVER; else { @@ -1989,24 +1918,7 @@ static int do_directive(Token * tline) istk->conds = cond; return DIRECTIVE_FOUND; - case PP_ELIF: - case PP_ELIFCTX: - case PP_ELIFDEF: - case PP_ELIFID: - case PP_ELIFIDN: - case PP_ELIFIDNI: - case PP_ELIFMACRO: - case PP_ELIFN: - case PP_ELIFNCTX: - case PP_ELIFNDEF: - case PP_ELIFNID: - case PP_ELIFNIDN: - case PP_ELIFNIDNI: - case PP_ELIFNMACRO: - case PP_ELIFNNUM: - case PP_ELIFNSTR: - case PP_ELIFNUM: - case PP_ELIFSTR: + CASE_PP_ELIF: if (!istk->conds) error(ERR_FATAL, "`%s': no matching `%%if'", pp_directives[i]); if (emitting(istk->conds->state) @@ -2961,6 +2873,8 @@ static Token *expand_mmac_params(Token * tline) t->next = delete_Token(tt); } break; + default: + break; } return thead; -- 2.7.4