diff options
Diffstat (limited to 'eval.c')
-rw-r--r-- | eval.c | 222 |
1 files changed, 139 insertions, 83 deletions
@@ -36,9 +36,11 @@ IOBUF *curfile = NULL; /* current data file */ int exiting = FALSE; int (*interpret)(INSTRUCTION *); +#define MAX_EXEC_HOOKS 10 +static int num_exec_hook = 0; +static Func_pre_exec pre_execute[MAX_EXEC_HOOKS]; +static Func_post_exec post_execute = NULL; -extern int pre_execute(INSTRUCTION **); -extern void post_execute(INSTRUCTION *); extern void frame_popped(); #if __GNUC__ < 2 @@ -437,6 +439,8 @@ flags2str(int flagval) { NUMINT, "NUMINT" }, { INTIND, "INTIND" }, { WSTRCUR, "WSTRCUR" }, + { MPFN, "MPFN" }, + { MPZN, "MPZN" }, { ARRAYMAXED, "ARRAYMAXED" }, { HALFHAT, "HALFHAT" }, { XARRAY, "XARRAY" }, @@ -563,6 +567,7 @@ posix_compare(NODE *s1, NODE *s2) return ret; } + /* cmp_nodes --- compare two nodes, returning negative, 0, positive */ int @@ -582,21 +587,13 @@ cmp_nodes(NODE *t1, NODE *t2) if (t1->flags & INTIND) t1 = force_string(t1); if (t2->flags & INTIND) - t2 = force_string(t2); - - if ((t1->flags & NUMBER) && (t2->flags & NUMBER)) { - if (t1->numbr == t2->numbr) - ret = 0; - /* don't subtract, in case one or both are infinite */ - else if (t1->numbr < t2->numbr) - ret = -1; - else - ret = 1; - return ret; - } + t2 = force_string(t2); - t1 = force_string(t1); - t2 = force_string(t2); + if ((t1->flags & NUMBER) && (t2->flags & NUMBER)) + return cmp_numbers(t1, t2); + + (void) force_string(t1); + (void) force_string(t2); len1 = t1->stlen; len2 = t2->stlen; ldiff = len1 - len2; @@ -700,6 +697,7 @@ void set_IGNORECASE() { static short warned = FALSE; + NODE *n = IGNORECASE_node->var_value; if ((do_lint || do_traditional) && ! warned) { warned = TRUE; @@ -708,17 +706,19 @@ set_IGNORECASE() load_casetable(); if (do_traditional) IGNORECASE = FALSE; - else if ((IGNORECASE_node->var_value->flags & (STRING|STRCUR)) != 0) { - if ((IGNORECASE_node->var_value->flags & MAYBE_NUM) == 0) { - IGNORECASE_node->var_value = force_string(IGNORECASE_node->var_value); - IGNORECASE = (IGNORECASE_node->var_value->stlen > 0); - } else - IGNORECASE = (force_number(IGNORECASE_node->var_value) != 0.0); - } else if ((IGNORECASE_node->var_value->flags & (NUMCUR|NUMBER)) != 0) - IGNORECASE = (force_number(IGNORECASE_node->var_value) != 0.0); + else if ((n->flags & (STRING|STRCUR)) != 0) { + if ((n->flags & MAYBE_NUM) == 0) { + (void) force_string(n); + IGNORECASE = (n->stlen > 0); + } else { + (void) force_number(n); + IGNORECASE = ! iszero(n); + } + } else if ((n->flags & (NUMCUR|NUMBER)) != 0) + IGNORECASE = ! iszero(n); else IGNORECASE = FALSE; /* shouldn't happen */ - + set_RS(); /* set_RS() calls set_FS() if need be, for us */ } @@ -729,7 +729,7 @@ set_BINMODE() { static short warned = FALSE; char *p; - NODE *v; + NODE *v = BINMODE_node->var_value; if ((do_lint || do_traditional) && ! warned) { warned = TRUE; @@ -737,16 +737,15 @@ set_BINMODE() } if (do_traditional) BINMODE = 0; - else if ((BINMODE_node->var_value->flags & NUMBER) != 0) { - BINMODE = (int) force_number(BINMODE_node->var_value); + else if ((v->flags & NUMBER) != 0) { + (void) force_number(v); + BINMODE = get_number_si(v); /* Make sure the value is rational. */ if (BINMODE < 0) BINMODE = 0; else if (BINMODE > 3) BINMODE = 3; - } - else if ((BINMODE_node->var_value->flags & STRING) != 0) { - v = BINMODE_node->var_value; + } else if ((v->flags & STRING) != 0) { p = v->stptr; /* @@ -795,8 +794,7 @@ set_BINMODE() break; } } - } - else + } else BINMODE = 3; /* shouldn't happen */ } @@ -922,16 +920,16 @@ set_LINT() { #ifndef NO_LINT int old_lint = do_lint; + NODE *n = LINT_node->var_value; - if ((LINT_node->var_value->flags & (STRING|STRCUR)) != 0) { - if ((LINT_node->var_value->flags & MAYBE_NUM) == 0) { + if ((n->flags & (STRING|STRCUR)) != 0) { + if ((n->flags & MAYBE_NUM) == 0) { const char *lintval; size_t lintlen; - NODE *tmp; - tmp = LINT_node->var_value = force_string(LINT_node->var_value); - lintval = tmp->stptr; - lintlen = tmp->stlen; + n = force_string(LINT_node->var_value); + lintval = n->stptr; + lintlen = n->stlen; if (lintlen > 0) { do_flags |= DO_LINT_ALL; if (lintlen == 5 && strncmp(lintval, "fatal", 5) == 0) @@ -946,14 +944,16 @@ set_LINT() lintfunc = warning; } } else { - if (force_number(LINT_node->var_value) != 0.0) + (void) force_number(n); + if (! iszero(n)) do_flags |= DO_LINT_ALL; else do_flags &= ~(DO_LINT_ALL|DO_LINT_INVALID); lintfunc = warning; } - } else if ((LINT_node->var_value->flags & (NUMCUR|NUMBER)) != 0) { - if (force_number(LINT_node->var_value) != 0.0) + } else if ((n->flags & (NUMCUR|NUMBER)) != 0) { + (void) force_number(n); + if (! iszero(n)) do_flags |= DO_LINT_ALL; else do_flags &= ~(DO_LINT_ALL|DO_LINT_INVALID); @@ -1029,9 +1029,14 @@ unset_ERRNO(void) void update_NR() { +#ifdef HAVE_MPFR + if (is_mpg_number(NR_node->var_value)) + (void) mpg_update_var(NR_node); + else +#endif if (NR_node->var_value->numbr != NR) { unref(NR_node->var_value); - NR_node->var_value = make_number((AWKNUM) NR); + NR_node->var_value = make_number(NR); } } @@ -1040,11 +1045,14 @@ update_NR() void update_NF() { - if (NF == -1 || NF_node->var_value->numbr != NF) { + long l; + + l = get_number_si(NF_node->var_value); + if (NF == -1 || l != NF) { if (NF == -1) (void) get_field(UNLIMITED - 1, NULL); /* parse record */ unref(NF_node->var_value); - NF_node->var_value = make_number((AWKNUM) NF); + NF_node->var_value = make_number(NF); } } @@ -1053,9 +1061,14 @@ update_NF() void update_FNR() { +#ifdef HAVE_MPFR + if (is_mpg_number(FNR_node->var_value)) + (void) mpg_update_var(FNR_node); + else +#endif if (FNR_node->var_value->numbr != FNR) { unref(FNR_node->var_value); - FNR_node->var_value = make_number((AWKNUM) FNR); + FNR_node->var_value = make_number(FNR); } } @@ -1153,7 +1166,9 @@ r_get_field(NODE *n, Func_ptr *assign, int reference) } } - field_num = (long) force_number(n); + (void) force_number(n); + field_num = get_number_si(n); + if (field_num < 0) fatal(_("attempt to access field %ld"), field_num); @@ -1410,7 +1425,8 @@ free_arrayfor(NODE *r) } -/* unwind_stack --- pop items off the run-time stack; +/* + * unwind_stack --- pop items off the run-time stack; * 'n' is the # of items left in the stack. */ @@ -1471,14 +1487,6 @@ unwind_stack(long n) #define pop_stack() (void) unwind_stack(0) -/* - * This generated compiler warnings from GCC 4.4. Who knows why. - * -#define eval_condition(t) (((t)->flags & MAYBE_NUM) && force_number(t), \ - ((t)->flags & NUMBER) ? ((t)->numbr != 0.0) : ((t)->stlen != 0)) -*/ - - static inline int eval_condition(NODE *t) { @@ -1492,15 +1500,15 @@ eval_condition(NODE *t) force_number(t); if ((t->flags & NUMBER) != 0) - return (t->numbr != 0.0); + return ! iszero(t); return (t->stlen != 0); } -/* cmp_scalar -- compare two nodes on the stack */ +/* cmp_scalars -- compare two nodes on the stack */ static inline int -cmp_scalar() +cmp_scalars() { NODE *t1, *t2; int di; @@ -1517,20 +1525,22 @@ cmp_scalar() return di; } - /* op_assign --- assignment operators excluding = */ static void op_assign(OPCODE op) { NODE **lhs; - NODE *t1; + NODE *t1, *t2; AWKNUM x = 0.0, x1, x2; lhs = POP_ADDRESS(); t1 = *lhs; - x1 = force_number(t1); - TOP_NUMBER(x2); + x1 = force_number(t1)->numbr; + + t2 = TOP_SCALAR(); + x2 = force_number(t2)->numbr; + DEREF(t2); switch (op) { case Op_assign_plus: @@ -1580,7 +1590,6 @@ op_assign(OPCODE op) REPLACE(t1); } - /* PUSH_CODE --- push a code onto the runtime stack */ void @@ -1607,7 +1616,8 @@ POP_CODE() } -/* Implementation of BEGINFILE and ENDFILE requires saving an execution +/* + * Implementation of BEGINFILE and ENDFILE requires saving an execution * state and the ability to return to that state. The state is * defined by the instruction triggering the BEGINFILE/ENDFILE rule, the * run-time stack, the rule and the source file. The source line is available in @@ -1675,6 +1685,56 @@ pop_exec_state(int *rule, char **src, long *sz) return cp; } + +/* register_exec_hook --- add exec hooks in the interpreter. */ + +int +register_exec_hook(Func_pre_exec preh, Func_post_exec posth) +{ + int pos = 0; + + /* + * multiple post-exec hooks aren't supported. post-exec hook is mainly + * for use by the debugger. + */ + + if (! preh || (post_execute && posth)) + return FALSE; + + if (num_exec_hook == MAX_EXEC_HOOKS) + return FALSE; + + /* + * Add to the beginning of the array but do not displace the + * debugger hook if it exists. + */ + if (num_exec_hook > 0) { + pos = !! do_debug; + if (num_exec_hook > pos) + memmove(pre_execute + pos + 1, pre_execute + pos, + (num_exec_hook - pos) * sizeof (preh)); + } + pre_execute[pos] = preh; + num_exec_hook++; + + if (posth) + post_execute = posth; + + return TRUE; +} + + +/* interpreter routine when not debugging */ +#include "interpret.h" + +/* interpreter routine with exec hook(s). Used when debugging and/or with MPFR. */ +#define r_interpret h_interpret +#define EXEC_HOOK 1 +#include "interpret.h" +#undef EXEC_HOOK +#undef r_interpret + + void init_interpret() { @@ -1696,26 +1756,22 @@ init_interpret() frame_ptr->vname = NULL; /* initialize TRUE and FALSE nodes */ - node_Boolean[FALSE] = make_number(0); - node_Boolean[FALSE]->flags |= NUMINT; + node_Boolean[FALSE] = make_number(0.0); node_Boolean[TRUE] = make_number(1.0); - node_Boolean[TRUE]->flags |= NUMINT; + if (! is_mpg_number(node_Boolean[FALSE])) { + node_Boolean[FALSE]->flags |= NUMINT; + node_Boolean[TRUE]->flags |= NUMINT; + } - /* select the interpreter routine */ - if (do_debug) - interpret = debug_interpret; + /* + * Select the interpreter routine. The version without + * any exec hook support (r_interpret) is faster by about + * 5%, or more depending on the opcodes. + */ + + if (num_exec_hook > 0) + interpret = h_interpret; else - interpret = r_interpret; + interpret = r_interpret; } - -/* interpreter routine when not debugging */ -#include "interpret.h" - -/* interpreter routine when deubugging with gawk --debug */ -#define r_interpret debug_interpret -#define DEBUGGING 1 -#include "interpret.h" -#undef DEBUGGING -#undef r_interpret - |