aboutsummaryrefslogtreecommitdiffstats
path: root/interpret.h
diff options
context:
space:
mode:
Diffstat (limited to 'interpret.h')
-rw-r--r--interpret.h237
1 files changed, 134 insertions, 103 deletions
diff --git a/interpret.h b/interpret.h
index 67a702e3..009e6e10 100644
--- a/interpret.h
+++ b/interpret.h
@@ -1,37 +1,48 @@
/*
- * interpret:
- * code is a list of instructions to run. returns the exit value
- * from the awk code.
+ * interpret.h --- run a list of instructions.
*/
-
- /* N.B.:
- * 1) reference counting done for both number and string values.
- * 2) Stack operations:
- * Use REPLACE[_XX] if last stack operation was TOP[_XX],
- * PUSH[_XX] if last operation was POP[_XX] instead.
- * 3) UPREF and DREF -- see awk.h
+
+/*
+ * Copyright (C) 1986, 1988, 1989, 1991-2012 the Free Software Foundation, Inc.
+ *
+ * This file is part of GAWK, the GNU implementation of the
+ * AWK Programming Language.
+ *
+ * GAWK is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GAWK is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
+
int
r_interpret(INSTRUCTION *code)
{
INSTRUCTION *pc; /* current instruction */
+ OPCODE op; /* current opcode */
NODE *r = NULL;
NODE *m;
INSTRUCTION *ni;
NODE *t1, *t2;
- NODE *f; /* function definition */
NODE **lhs;
- AWKNUM x, x1, x2;
+ AWKNUM x, x2;
int di;
Regexp *rp;
- int stdio_problem = FALSE;
/* array subscript */
#define mk_sub(n) (n == 1 ? POP_SCALAR() : concat_exp(n, TRUE))
-#ifdef DEBUGGING
-#define JUMPTO(x) do { post_execute(pc); pc = (x); goto top; } while (FALSE)
+#ifdef EXEC_HOOK
+#define JUMPTO(x) do { if (post_execute) post_execute(pc); pc = (x); goto top; } while (FALSE)
#else
#define JUMPTO(x) do { pc = (x); goto top; } while (FALSE)
#endif
@@ -51,12 +62,14 @@ top:
if (pc->source_line > 0)
sourceline = pc->source_line;
-#ifdef DEBUGGING
- if (! pre_execute(&pc))
- goto top;
+#ifdef EXEC_HOOK
+ for (di = 0; di < num_exec_hook; di++) {
+ if (! pre_execute[di](& pc))
+ goto top;
+ }
#endif
- switch (pc->opcode) {
+ switch ((op = pc->opcode)) {
case Op_rule:
currule = pc->in_rule; /* for sole use in Op_K_next, Op_K_nextfile, Op_K_getline */
/* fall through */
@@ -65,6 +78,9 @@ top:
break;
case Op_atexit:
+ {
+ int stdio_problem = FALSE;
+
/* avoid false source indications */
source = NULL;
sourceline = 0;
@@ -87,6 +103,7 @@ top:
*/
if (stdio_problem && ! exiting && exit_val == 0)
exit_val = 1;
+ }
break;
case Op_stop:
@@ -147,7 +164,7 @@ top:
break;
case Node_var_array:
- if (pc->opcode == Op_push_arg)
+ if (op == Op_push_arg)
PUSH(m);
else
fatal(_("attempt to use array `%s' in a scalar context"),
@@ -303,8 +320,7 @@ top:
t1 = POP_SCALAR();
di = eval_condition(t1);
DEREF(t1);
- if ((pc->opcode == Op_and && di)
- || (pc->opcode == Op_or && ! di))
+ if ((op == Op_and && di) || (op == Op_or && ! di))
break;
r = node_Boolean[di];
UPREF(r);
@@ -330,164 +346,175 @@ top:
break;
case Op_equal:
- r = node_Boolean[cmp_scalar() == 0];
+ r = node_Boolean[cmp_scalars() == 0];
UPREF(r);
REPLACE(r);
break;
case Op_notequal:
- r = node_Boolean[cmp_scalar() != 0];
+ r = node_Boolean[cmp_scalars() != 0];
UPREF(r);
REPLACE(r);
break;
case Op_less:
- r = node_Boolean[cmp_scalar() < 0];
+ r = node_Boolean[cmp_scalars() < 0];
UPREF(r);
REPLACE(r);
break;
case Op_greater:
- r = node_Boolean[cmp_scalar() > 0];
+ r = node_Boolean[cmp_scalars() > 0];
UPREF(r);
REPLACE(r);
break;
case Op_leq:
- r = node_Boolean[cmp_scalar() <= 0];
+ r = node_Boolean[cmp_scalars() <= 0];
UPREF(r);
REPLACE(r);
break;
case Op_geq:
- r = node_Boolean[cmp_scalar() >= 0];
+ r = node_Boolean[cmp_scalars() >= 0];
UPREF(r);
REPLACE(r);
break;
case Op_plus_i:
- x2 = force_number(pc->memory);
+ x2 = force_number(pc->memory)->numbr;
goto plus;
-
case Op_plus:
- POP_NUMBER(x2);
+ t2 = POP_NUMBER();
+ x2 = t2->numbr;
+ DEREF(t2);
plus:
- TOP_NUMBER(x1);
- r = make_number(x1 + x2);
+ t1 = TOP_NUMBER();
+ r = make_number(t1->numbr + x2);
+ DEREF(t1);
REPLACE(r);
break;
case Op_minus_i:
- x2 = force_number(pc->memory);
+ x2 = force_number(pc->memory)->numbr;
goto minus;
-
case Op_minus:
- POP_NUMBER(x2);
+ t2 = POP_NUMBER();
+ x2 = t2->numbr;
+ DEREF(t2);
minus:
- TOP_NUMBER(x1);
- r = make_number(x1 - x2);
+ t1 = TOP_NUMBER();
+ r = make_number(t1->numbr - x2);
+ DEREF(t1);
REPLACE(r);
break;
case Op_times_i:
- x2 = force_number(pc->memory);
+ x2 = force_number(pc->memory)->numbr;
goto times;
-
case Op_times:
- POP_NUMBER(x2);
+ t2 = POP_NUMBER();
+ x2 = t2->numbr;
+ DEREF(t2);
times:
- TOP_NUMBER(x1);
- r = make_number(x1 * x2);
+ t1 = TOP_NUMBER();
+ r = make_number(t1->numbr * x2);
+ DEREF(t1);
REPLACE(r);
break;
case Op_exp_i:
- x2 = force_number(pc->memory);
- goto exponent;
-
+ x2 = force_number(pc->memory)->numbr;
+ goto exp;
case Op_exp:
- POP_NUMBER(x2);
-exponent:
- TOP_NUMBER(x1);
- x = calc_exp(x1, x2);
- r = make_number(x);
+ t2 = POP_NUMBER();
+ x2 = t2->numbr;
+ DEREF(t2);
+exp:
+ t1 = TOP_NUMBER();
+ r = make_number(calc_exp(t1->numbr, x2));
+ DEREF(t1);
REPLACE(r);
break;
case Op_quotient_i:
- x2 = force_number(pc->memory);
+ x2 = force_number(pc->memory)->numbr;
goto quotient;
-
case Op_quotient:
- POP_NUMBER(x2);
+ t2 = POP_NUMBER();
+ x2 = t2->numbr;
+ DEREF(t2);
quotient:
+ t1 = TOP_NUMBER();
if (x2 == 0)
fatal(_("division by zero attempted"));
-
- TOP_NUMBER(x1);
- x = x1 / x2;
- r = make_number(x);
+ r = make_number(t1->numbr / x2);
+ DEREF(t1);
REPLACE(r);
break;
case Op_mod_i:
- x2 = force_number(pc->memory);
+ x2 = force_number(pc->memory)->numbr;
goto mod;
-
case Op_mod:
- POP_NUMBER(x2);
+ t2 = POP_NUMBER();
+ x2 = t2->numbr;
+ DEREF(t2);
mod:
+ t1 = TOP_NUMBER();
if (x2 == 0)
fatal(_("division by zero attempted in `%%'"));
-
- TOP_NUMBER(x1);
#ifdef HAVE_FMOD
- x = fmod(x1, x2);
+ x = fmod(t1->numbr, x2);
#else /* ! HAVE_FMOD */
- (void) modf(x1 / x2, &x);
- x = x1 - x * x2;
+ (void) modf(t1->numbr / x2, &x);
+ x = t1->numbr - x * x2;
#endif /* ! HAVE_FMOD */
r = make_number(x);
+
+ DEREF(t1);
REPLACE(r);
- break;
+ break;
case Op_preincrement:
case Op_predecrement:
- x2 = pc->opcode == Op_preincrement ? 1.0 : -1.0;
+ x = op == Op_preincrement ? 1.0 : -1.0;
lhs = TOP_ADDRESS();
t1 = *lhs;
- x1 = force_number(t1);
+ force_number(t1);
if (t1->valref == 1 && t1->flags == (MALLOC|NUMCUR|NUMBER)) {
/* optimization */
- t1->numbr = x1 + x2;
+ t1->numbr += x;
+ r = t1;
} else {
+ r = *lhs = make_number(t1->numbr + x);
unref(t1);
- t1 = *lhs = make_number(x1 + x2);
}
- UPREF(t1);
- REPLACE(t1);
+ UPREF(r);
+ REPLACE(r);
break;
case Op_postincrement:
case Op_postdecrement:
- x2 = pc->opcode == Op_postincrement ? 1.0 : -1.0;
+ x = op == Op_postincrement ? 1.0 : -1.0;
lhs = TOP_ADDRESS();
t1 = *lhs;
- x1 = force_number(t1);
+ force_number(t1);
+ r = make_number(t1->numbr);
if (t1->valref == 1 && t1->flags == (MALLOC|NUMCUR|NUMBER)) {
- /* optimization */
- t1->numbr = x1 + x2;
+ /* optimization */
+ t1->numbr += x;
} else {
+ *lhs = make_number(t1->numbr + x);
unref(t1);
- *lhs = make_number(x1 + x2);
}
- r = make_number(x1);
REPLACE(r);
break;
case Op_unary_minus:
- TOP_NUMBER(x1);
- r = make_number(-x1);
+ t1 = TOP_NUMBER();
+ r = make_number(-t1->numbr);
+ DEREF(t1);
REPLACE(r);
break;
@@ -532,7 +559,7 @@ mod:
Func_ptr assign;
t1 = TOP_SCALAR();
- lhs = r_get_field(t1, &assign, FALSE);
+ lhs = r_get_field(t1, & assign, FALSE);
decr_sp();
DEREF(t1);
unref(*lhs);
@@ -555,7 +582,7 @@ mod:
*lhs = dupnode(t1);
}
- if (t1 != t2 && t1->valref == 1) {
+ if (t1 != t2 && t1->valref == 1 && (t1->flags & MPFN) == 0) {
size_t nlen = t1->stlen + t2->stlen;
erealloc(t1->stptr, char *, nlen + 2, "r_interpret");
@@ -592,7 +619,7 @@ mod:
case Op_assign_quotient:
case Op_assign_mod:
case Op_assign_exp:
- op_assign(pc->opcode);
+ op_assign(op);
break;
case Op_var_update: /* update value of NR, FNR or NF */
@@ -601,8 +628,9 @@ mod:
case Op_var_assign:
case Op_field_assign:
+ r = TOP();
if (pc->assign_ctxt == Op_sub_builtin
- && TOP()->numbr == 0.0 /* top of stack has a number == 0 */
+ && get_number_si(r) == 0 /* top of stack has a number == 0 */
) {
/* There wasn't any substitutions. If the target is a FIELD,
* this means no field re-splitting or $0 reconstruction.
@@ -612,14 +640,14 @@ mod:
break;
} else if ((pc->assign_ctxt == Op_K_getline
|| pc->assign_ctxt == Op_K_getline_redir)
- && TOP()->numbr <= 0.0 /* top of stack has a number <= 0 */
+ && get_number_si(r) <= 0 /* top of stack has a number <= 0 */
) {
/* getline returned EOF or error */
break;
}
- if (pc->opcode == Op_var_assign)
+ if (op == Op_var_assign)
pc->assign_var();
else
pc->field_assign();
@@ -649,7 +677,6 @@ mod:
if (di) {
/* match found */
-
t2 = POP_SCALAR();
DEREF(t2);
JUMPTO(pc->target_jmp);
@@ -671,9 +698,10 @@ mod:
case Op_in_array:
t1 = POP_ARRAY();
t2 = mk_sub(pc->expr_count);
- di = (in_array(t1, t2) != NULL);
+ r = node_Boolean[(in_array(t1, t2) != NULL)];
DEREF(t2);
- PUSH(make_number((AWKNUM) di));
+ UPREF(r);
+ PUSH(r);
break;
case Op_arrayfor_init:
@@ -816,8 +844,8 @@ match_re:
di = research(rp, t1->stptr, 0, t1->stlen,
avoid_dfa(m, t1->stptr, t1->stlen));
- di = (di == -1) ^ (pc->opcode != Op_nomatch);
- if(pc->opcode != Op_match_rec) {
+ di = (di == -1) ^ (op != Op_nomatch);
+ if (op != Op_match_rec) {
decr_sp();
DEREF(t1);
}
@@ -842,9 +870,9 @@ match_re:
case Op_indirect_func_call:
{
+ NODE *f = NULL;
int arg_count;
- f = NULL;
arg_count = (pc + 1)->expr_count;
t1 = PEEK(arg_count); /* indirect var */
assert(t1->type == Node_val); /* @a[1](p) not allowed in grammar */
@@ -855,7 +883,8 @@ match_re:
if (f != NULL && strcmp(f->vname, t1->stptr) == 0) {
/* indirect var hasn't been reassigned */
- goto func_call;
+ ni = setup_frame(pc);
+ JUMPTO(ni); /* Op_func */
}
f = lookup(t1->stptr);
}
@@ -865,10 +894,14 @@ match_re:
pc->func_name);
pc->func_body = f; /* save for next call */
- goto func_call;
+ ni = setup_frame(pc);
+ JUMPTO(ni); /* Op_func */
}
case Op_func_call:
+ {
+ NODE *f;
+
/* retrieve function definition node */
f = pc->func_body;
if (f == NULL) {
@@ -894,11 +927,9 @@ match_re:
JUMPTO(ni);
}
-func_call:
ni = setup_frame(pc);
-
- /* run the function instructions */
- JUMPTO(ni); /* Op_func */
+ JUMPTO(ni); /* Op_func */
+ }
case Op_K_return:
m = POP_SCALAR(); /* return value */
@@ -1074,8 +1105,9 @@ func_call:
fatal(_("`exit' cannot be called in the current context"));
exiting = TRUE;
- POP_NUMBER(x1);
- exit_val = (int) x1;
+ t1 = POP_NUMBER();
+ exit_val = (int) get_number_si(t1);
+ DEREF(t1);
#ifdef VMS
if (exit_val == 0)
exit_val = EXIT_SUCCESS;
@@ -1171,7 +1203,7 @@ func_call:
break;
default:
- fatal(_("Sorry, don't know how to interpret `%s'"), opcode2str(pc->opcode));
+ fatal(_("Sorry, don't know how to interpret `%s'"), opcode2str(op));
}
JUMPTO(pc->nexti);
@@ -1184,4 +1216,3 @@ func_call:
#undef mk_sub
#undef JUMPTO
}
-