aboutsummaryrefslogtreecommitdiffstats
path: root/eval.c
diff options
context:
space:
mode:
Diffstat (limited to 'eval.c')
-rw-r--r--eval.c222
1 files changed, 139 insertions, 83 deletions
diff --git a/eval.c b/eval.c
index 78598b21..2305bbb3 100644
--- a/eval.c
+++ b/eval.c
@@ -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);
@@ -1017,9 +1017,14 @@ update_ERRNO()
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);
}
}
@@ -1028,11 +1033,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);
}
}
@@ -1041,9 +1049,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);
}
}
@@ -1141,7 +1154,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);
@@ -1398,7 +1413,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.
*/
@@ -1459,14 +1475,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)
{
@@ -1480,15 +1488,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;
@@ -1505,20 +1513,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:
@@ -1568,7 +1578,6 @@ op_assign(OPCODE op)
REPLACE(t1);
}
-
/* PUSH_CODE --- push a code onto the runtime stack */
void
@@ -1595,7 +1604,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
@@ -1663,6 +1673,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()
{
@@ -1684,26 +1744,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
-