|
Packit Service |
f629e6 |
/*
|
|
Packit Service |
f629e6 |
* interpret.h --- run a list of instructions.
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/*
|
|
Packit Service |
f629e6 |
* Copyright (C) 1986, 1988, 1989, 1991-2018 the Free Software Foundation, Inc.
|
|
Packit Service |
f629e6 |
*
|
|
Packit Service |
f629e6 |
* This file is part of GAWK, the GNU implementation of the
|
|
Packit Service |
f629e6 |
* AWK Programming Language.
|
|
Packit Service |
f629e6 |
*
|
|
Packit Service |
f629e6 |
* GAWK is free software; you can redistribute it and/or modify
|
|
Packit Service |
f629e6 |
* it under the terms of the GNU General Public License as published by
|
|
Packit Service |
f629e6 |
* the Free Software Foundation; either version 3 of the License, or
|
|
Packit Service |
f629e6 |
* (at your option) any later version.
|
|
Packit Service |
f629e6 |
*
|
|
Packit Service |
f629e6 |
* GAWK is distributed in the hope that it will be useful,
|
|
Packit Service |
f629e6 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
f629e6 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit Service |
f629e6 |
* GNU General Public License for more details.
|
|
Packit Service |
f629e6 |
*
|
|
Packit Service |
f629e6 |
* You should have received a copy of the GNU General Public License
|
|
Packit Service |
f629e6 |
* along with this program; if not, write to the Free Software
|
|
Packit Service |
f629e6 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/*
|
|
Packit Service |
f629e6 |
* If "r" is a field, valref should normally be > 1, because the field is
|
|
Packit Service |
f629e6 |
* created initially with valref 1, and valref should be bumped when it is
|
|
Packit Service |
f629e6 |
* pushed onto the stack by Op_field_spec. On the other hand, if we are
|
|
Packit Service |
f629e6 |
* assigning to $n, then Op_store_field calls unref(*lhs) before assigning
|
|
Packit Service |
f629e6 |
* the new value, so that decrements valref. So if the RHS is a field with
|
|
Packit Service |
f629e6 |
* valref 1, that effectively means that this is an assignment like "$n = $n",
|
|
Packit Service |
f629e6 |
* so a no-op, other than triggering $0 reconstitution.
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
#define UNFIELD(l, r) \
|
|
Packit Service |
f629e6 |
{ \
|
|
Packit Service |
f629e6 |
/* if was a field, turn it into a var */ \
|
|
Packit Service |
f629e6 |
if ((r->flags & MALLOC) != 0 || r->valref == 1) { \
|
|
Packit Service |
f629e6 |
l = r; \
|
|
Packit Service |
f629e6 |
} else { \
|
|
Packit Service |
f629e6 |
l = dupnode(r); \
|
|
Packit Service |
f629e6 |
DEREF(r); \
|
|
Packit Service |
f629e6 |
} \
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
int
|
|
Packit Service |
f629e6 |
r_interpret(INSTRUCTION *code)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
INSTRUCTION *pc; /* current instruction */
|
|
Packit Service |
f629e6 |
OPCODE op; /* current opcode */
|
|
Packit Service |
f629e6 |
NODE *r = NULL;
|
|
Packit Service |
f629e6 |
NODE *m;
|
|
Packit Service |
f629e6 |
INSTRUCTION *ni;
|
|
Packit Service |
f629e6 |
NODE *t1, *t2;
|
|
Packit Service |
f629e6 |
NODE **lhs;
|
|
Packit Service |
f629e6 |
AWKNUM x, x2;
|
|
Packit Service |
f629e6 |
int di;
|
|
Packit Service |
f629e6 |
Regexp *rp;
|
|
Packit Service |
f629e6 |
NODE *set_array = NULL; /* array with a post-assignment routine */
|
|
Packit Service |
f629e6 |
NODE *set_idx = NULL; /* the index of the array element */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* array subscript */
|
|
Packit Service |
f629e6 |
#define mk_sub(n) (n == 1 ? POP_SCALAR() : concat_exp(n, true))
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
#ifdef EXEC_HOOK
|
|
Packit Service |
f629e6 |
#define JUMPTO(x) do { if (post_execute) post_execute(pc); pc = (x); goto top; } while (false)
|
|
Packit Service |
f629e6 |
#else
|
|
Packit Service |
f629e6 |
#define JUMPTO(x) do { pc = (x); goto top; } while (false)
|
|
Packit Service |
f629e6 |
#endif
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
pc = code;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* N.B.: always use JUMPTO for next instruction, otherwise bad things
|
|
Packit Service |
f629e6 |
* may happen. DO NOT add a real loop (for/while) below to
|
|
Packit Service |
f629e6 |
* replace ' forever {'; this catches failure to use JUMPTO to execute
|
|
Packit Service |
f629e6 |
* next instruction (e.g. continue statement).
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* loop until hit Op_stop instruction */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* forever { */
|
|
Packit Service |
f629e6 |
top:
|
|
Packit Service |
f629e6 |
if (pc->source_line > 0)
|
|
Packit Service |
f629e6 |
sourceline = pc->source_line;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
#ifdef EXEC_HOOK
|
|
Packit Service |
f629e6 |
for (di = 0; di < num_exec_hook; di++) {
|
|
Packit Service |
f629e6 |
if (! pre_execute[di](& pc))
|
|
Packit Service |
f629e6 |
goto top;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
#endif
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
switch ((op = pc->opcode)) {
|
|
Packit Service |
f629e6 |
case Op_rule:
|
|
Packit Service |
f629e6 |
currule = pc->in_rule; /* for sole use in Op_K_next, Op_K_nextfile, Op_K_getline */
|
|
Packit Service |
f629e6 |
/* fall through */
|
|
Packit Service |
f629e6 |
case Op_func:
|
|
Packit Service |
f629e6 |
source = pc->source_file;
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_atexit:
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
bool stdio_problem = false;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* avoid false source indications */
|
|
Packit Service |
f629e6 |
source = NULL;
|
|
Packit Service |
f629e6 |
sourceline = 0;
|
|
Packit Service |
f629e6 |
(void) nextfile(& curfile, true); /* close input data file */
|
|
Packit Service |
f629e6 |
/*
|
|
Packit Service |
f629e6 |
* This used to be:
|
|
Packit Service |
f629e6 |
*
|
|
Packit Service |
f629e6 |
* if (close_io() != 0 && ! exiting && exit_val == 0)
|
|
Packit Service |
f629e6 |
* exit_val = 1;
|
|
Packit Service |
f629e6 |
*
|
|
Packit Service |
f629e6 |
* Other awks don't care about problems closing open files
|
|
Packit Service |
f629e6 |
* and pipes, in that it doesn't affect their exit status.
|
|
Packit Service |
f629e6 |
* So we no longer do either.
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
(void) close_io(& stdio_problem);
|
|
Packit Service |
f629e6 |
/*
|
|
Packit Service |
f629e6 |
* However, we do want to exit non-zero if there was a problem
|
|
Packit Service |
f629e6 |
* with stdout/stderr, so we reinstate a slightly different
|
|
Packit Service |
f629e6 |
* version of the above:
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
if (stdio_problem && ! exiting && exit_val == 0)
|
|
Packit Service |
f629e6 |
exit_val = 1;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
close_extensions();
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_stop:
|
|
Packit Service |
f629e6 |
return 0;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_push_i:
|
|
Packit Service |
f629e6 |
m = pc->memory;
|
|
Packit Service |
f629e6 |
if (! do_traditional && (m->flags & INTLSTR) != 0) {
|
|
Packit Service |
f629e6 |
char *orig, *trans, save;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
save = m->stptr[m->stlen];
|
|
Packit Service |
f629e6 |
m->stptr[m->stlen] = '\0';
|
|
Packit Service |
f629e6 |
orig = m->stptr;
|
|
Packit Service |
f629e6 |
trans = dgettext(TEXTDOMAIN, orig);
|
|
Packit Service |
f629e6 |
m->stptr[m->stlen] = save;
|
|
Packit Service |
f629e6 |
m = make_string(trans, strlen(trans));
|
|
Packit Service |
f629e6 |
} else
|
|
Packit Service |
f629e6 |
UPREF(m);
|
|
Packit Service |
f629e6 |
PUSH(m);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_push:
|
|
Packit Service |
f629e6 |
case Op_push_arg:
|
|
Packit Service |
f629e6 |
case Op_push_arg_untyped:
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
NODE *save_symbol;
|
|
Packit Service |
f629e6 |
bool isparam = false;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
save_symbol = m = pc->memory;
|
|
Packit Service |
f629e6 |
if (m->type == Node_param_list) {
|
|
Packit Service |
f629e6 |
isparam = true;
|
|
Packit Service |
f629e6 |
save_symbol = m = GET_PARAM(m->param_cnt);
|
|
Packit Service |
f629e6 |
if (m->type == Node_array_ref) {
|
|
Packit Service |
f629e6 |
if (m->orig_array->type == Node_var) {
|
|
Packit Service |
f629e6 |
/* gawk 'func f(x) { a = 10; print x; } BEGIN{ f(a) }' */
|
|
Packit Service |
f629e6 |
goto uninitialized_scalar;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
m = m->orig_array;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
switch (m->type) {
|
|
Packit Service |
f629e6 |
case Node_var:
|
|
Packit Service |
f629e6 |
if (do_lint && var_uninitialized(m))
|
|
Packit Service |
f629e6 |
lintwarn(isparam ?
|
|
Packit Service |
f629e6 |
_("reference to uninitialized argument `%s'") :
|
|
Packit Service |
f629e6 |
_("reference to uninitialized variable `%s'"),
|
|
Packit Service |
f629e6 |
save_symbol->vname);
|
|
Packit Service |
f629e6 |
m = m->var_value;
|
|
Packit Service |
f629e6 |
UPREF(m);
|
|
Packit Service |
f629e6 |
PUSH(m);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Node_var_new:
|
|
Packit Service |
f629e6 |
uninitialized_scalar:
|
|
Packit Service |
f629e6 |
if (op != Op_push_arg_untyped) {
|
|
Packit Service |
f629e6 |
/* convert untyped to scalar */
|
|
Packit Service |
f629e6 |
m->type = Node_var;
|
|
Packit Service |
f629e6 |
m->var_value = dupnode(Nnull_string);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
if (do_lint)
|
|
Packit Service |
f629e6 |
lintwarn(isparam ?
|
|
Packit Service |
f629e6 |
_("reference to uninitialized argument `%s'") :
|
|
Packit Service |
f629e6 |
_("reference to uninitialized variable `%s'"),
|
|
Packit Service |
f629e6 |
save_symbol->vname);
|
|
Packit Service |
f629e6 |
if (op != Op_push_arg_untyped)
|
|
Packit Service |
f629e6 |
m = dupnode(Nnull_string);
|
|
Packit Service |
f629e6 |
PUSH(m);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Node_var_array:
|
|
Packit Service |
f629e6 |
if (op == Op_push_arg || op == Op_push_arg_untyped)
|
|
Packit Service |
f629e6 |
PUSH(m);
|
|
Packit Service |
f629e6 |
else
|
|
Packit Service |
f629e6 |
fatal(_("attempt to use array `%s' in a scalar context"),
|
|
Packit Service |
f629e6 |
array_vname(save_symbol));
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
default:
|
|
Packit Service |
f629e6 |
cant_happen();
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_push_param: /* function argument */
|
|
Packit Service |
f629e6 |
m = pc->memory;
|
|
Packit Service |
f629e6 |
if (m->type == Node_param_list)
|
|
Packit Service |
f629e6 |
m = GET_PARAM(m->param_cnt);
|
|
Packit Service |
f629e6 |
if (m->type == Node_var) {
|
|
Packit Service |
f629e6 |
m = m->var_value;
|
|
Packit Service |
f629e6 |
UPREF(m);
|
|
Packit Service |
f629e6 |
PUSH(m);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
/* else
|
|
Packit Service |
f629e6 |
fall through */
|
|
Packit Service |
f629e6 |
case Op_push_array:
|
|
Packit Service |
f629e6 |
PUSH(pc->memory);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_push_lhs:
|
|
Packit Service |
f629e6 |
lhs = get_lhs(pc->memory, pc->do_reference);
|
|
Packit Service |
f629e6 |
PUSH_ADDRESS(lhs);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_subscript:
|
|
Packit Service |
f629e6 |
t2 = mk_sub(pc->sub_count);
|
|
Packit Service |
f629e6 |
t1 = POP_ARRAY();
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (do_lint && in_array(t1, t2) == NULL) {
|
|
Packit Service |
f629e6 |
t2 = force_string(t2);
|
|
Packit Service |
f629e6 |
lintwarn(_("reference to uninitialized element `%s[\"%.*s\"]'"),
|
|
Packit Service |
f629e6 |
array_vname(t1), (int) t2->stlen, t2->stptr);
|
|
Packit Service |
f629e6 |
if (t2->stlen == 0)
|
|
Packit Service |
f629e6 |
lintwarn(_("subscript of array `%s' is null string"), array_vname(t1));
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* for FUNCTAB, get the name as the element value */
|
|
Packit Service |
f629e6 |
if (t1 == func_table) {
|
|
Packit Service |
f629e6 |
static bool warned = false;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (do_lint && ! warned) {
|
|
Packit Service |
f629e6 |
warned = true;
|
|
Packit Service |
f629e6 |
lintwarn(_("FUNCTAB is a gawk extension"));
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
r = t2;
|
|
Packit Service |
f629e6 |
} else {
|
|
Packit Service |
f629e6 |
/* make sure stuff like NF, NR, are up to date */
|
|
Packit Service |
f629e6 |
if (t1 == symbol_table)
|
|
Packit Service |
f629e6 |
update_global_values();
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
r = *assoc_lookup(t1, t2);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
DEREF(t2);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* for SYMTAB, step through to the actual variable */
|
|
Packit Service |
f629e6 |
if (t1 == symbol_table) {
|
|
Packit Service |
f629e6 |
static bool warned = false;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (do_lint && ! warned) {
|
|
Packit Service |
f629e6 |
warned = true;
|
|
Packit Service |
f629e6 |
lintwarn(_("SYMTAB is a gawk extension"));
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
if (r->type == Node_var)
|
|
Packit Service |
f629e6 |
r = r->var_value;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (r->type == Node_val)
|
|
Packit Service |
f629e6 |
UPREF(r);
|
|
Packit Service |
f629e6 |
PUSH(r);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_sub_array:
|
|
Packit Service |
f629e6 |
t2 = mk_sub(pc->sub_count);
|
|
Packit Service |
f629e6 |
t1 = POP_ARRAY();
|
|
Packit Service |
f629e6 |
r = in_array(t1, t2);
|
|
Packit Service |
f629e6 |
if (r == NULL) {
|
|
Packit Service |
f629e6 |
r = make_array();
|
|
Packit Service |
f629e6 |
r->parent_array = t1;
|
|
Packit Service |
f629e6 |
lhs = assoc_lookup(t1, t2);
|
|
Packit Service |
f629e6 |
unref(*lhs);
|
|
Packit Service |
f629e6 |
*lhs = r;
|
|
Packit Service |
f629e6 |
t2 = force_string(t2);
|
|
Packit Service |
f629e6 |
r->vname = estrdup(t2->stptr, t2->stlen); /* the subscript in parent array */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* execute post-assignment routine if any */
|
|
Packit Service |
f629e6 |
if (t1->astore != NULL)
|
|
Packit Service |
f629e6 |
(*t1->astore)(t1, t2);
|
|
Packit Service |
f629e6 |
} else if (r->type != Node_var_array) {
|
|
Packit Service |
f629e6 |
t2 = force_string(t2);
|
|
Packit Service |
f629e6 |
fatal(_("attempt to use scalar `%s[\"%.*s\"]' as an array"),
|
|
Packit Service |
f629e6 |
array_vname(t1), (int) t2->stlen, t2->stptr);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
DEREF(t2);
|
|
Packit Service |
f629e6 |
PUSH(r);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_subscript_lhs:
|
|
Packit Service |
f629e6 |
t2 = mk_sub(pc->sub_count);
|
|
Packit Service |
f629e6 |
t1 = POP_ARRAY();
|
|
Packit Service |
f629e6 |
if (do_lint && in_array(t1, t2) == NULL) {
|
|
Packit Service |
f629e6 |
t2 = force_string(t2);
|
|
Packit Service |
f629e6 |
if (pc->do_reference)
|
|
Packit Service |
f629e6 |
lintwarn(_("reference to uninitialized element `%s[\"%.*s\"]'"),
|
|
Packit Service |
f629e6 |
array_vname(t1), (int) t2->stlen, t2->stptr);
|
|
Packit Service |
f629e6 |
if (t2->stlen == 0)
|
|
Packit Service |
f629e6 |
lintwarn(_("subscript of array `%s' is null string"), array_vname(t1));
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
lhs = assoc_lookup(t1, t2);
|
|
Packit Service |
f629e6 |
if ((*lhs)->type == Node_var_array) {
|
|
Packit Service |
f629e6 |
t2 = force_string(t2);
|
|
Packit Service |
f629e6 |
fatal(_("attempt to use array `%s[\"%.*s\"]' in a scalar context"),
|
|
Packit Service |
f629e6 |
array_vname(t1), (int) t2->stlen, t2->stptr);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/*
|
|
Packit Service |
f629e6 |
* Changing something in FUNCTAB is not allowed.
|
|
Packit Service |
f629e6 |
*
|
|
Packit Service |
f629e6 |
* SYMTAB is a little more messy. Three kinds of values may
|
|
Packit Service |
f629e6 |
* be stored in SYMTAB:
|
|
Packit Service |
f629e6 |
* 1. Variables that don"t yet have a value (Node_var_new)
|
|
Packit Service |
f629e6 |
* 2. Variables that have a value (Node_var)
|
|
Packit Service |
f629e6 |
* 3. Values that awk code stuck into SYMTAB not related to variables (Node_value)
|
|
Packit Service |
f629e6 |
* For 1, since we are giving it a value, we have to change the type to Node_var.
|
|
Packit Service |
f629e6 |
* For 1 and 2, we have to step through the Node_var to get to the value.
|
|
Packit Service |
f629e6 |
* For 3, we just us the value we got from assoc_lookup(), above.
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
if (t1 == func_table)
|
|
Packit Service |
f629e6 |
fatal(_("cannot assign to elements of FUNCTAB"));
|
|
Packit Service |
f629e6 |
else if ( t1 == symbol_table
|
|
Packit Service |
f629e6 |
&& ( (*lhs)->type == Node_var
|
|
Packit Service |
f629e6 |
|| (*lhs)->type == Node_var_new)) {
|
|
Packit Service |
f629e6 |
update_global_values(); /* make sure stuff like NF, NR, are up to date */
|
|
Packit Service |
f629e6 |
(*lhs)->type = Node_var; /* in case was Node_var_new */
|
|
Packit Service |
f629e6 |
lhs = & ((*lhs)->var_value); /* extra level of indirection */
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
assert(set_idx == NULL);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (t1->astore) {
|
|
Packit Service |
f629e6 |
/* array has post-assignment routine */
|
|
Packit Service |
f629e6 |
set_array = t1;
|
|
Packit Service |
f629e6 |
set_idx = t2;
|
|
Packit Service |
f629e6 |
} else
|
|
Packit Service |
f629e6 |
DEREF(t2);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
PUSH_ADDRESS(lhs);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_field_spec:
|
|
Packit Service |
f629e6 |
t1 = TOP_SCALAR();
|
|
Packit Service |
f629e6 |
lhs = r_get_field(t1, (Func_ptr *) 0, true);
|
|
Packit Service |
f629e6 |
decr_sp();
|
|
Packit Service |
f629e6 |
DEREF(t1);
|
|
Packit Service |
f629e6 |
r = *lhs;
|
|
Packit Service |
f629e6 |
UPREF(r);
|
|
Packit Service |
f629e6 |
PUSH(r);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_field_spec_lhs:
|
|
Packit Service |
f629e6 |
t1 = TOP_SCALAR();
|
|
Packit Service |
f629e6 |
lhs = r_get_field(t1, &pc->target_assign->field_assign, pc->do_reference);
|
|
Packit Service |
f629e6 |
decr_sp();
|
|
Packit Service |
f629e6 |
DEREF(t1);
|
|
Packit Service |
f629e6 |
PUSH_ADDRESS(lhs);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_lint:
|
|
Packit Service |
f629e6 |
if (do_lint) {
|
|
Packit Service |
f629e6 |
switch (pc->lint_type) {
|
|
Packit Service |
f629e6 |
case LINT_assign_in_cond:
|
|
Packit Service |
f629e6 |
lintwarn(_("assignment used in conditional context"));
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case LINT_no_effect:
|
|
Packit Service |
f629e6 |
lintwarn(_("statement has no effect"));
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
default:
|
|
Packit Service |
f629e6 |
cant_happen();
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_K_break:
|
|
Packit Service |
f629e6 |
case Op_K_continue:
|
|
Packit Service |
f629e6 |
case Op_jmp:
|
|
Packit Service |
f629e6 |
assert(pc->target_jmp != NULL);
|
|
Packit Service |
f629e6 |
JUMPTO(pc->target_jmp);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_jmp_false:
|
|
Packit Service |
f629e6 |
r = POP_SCALAR();
|
|
Packit Service |
f629e6 |
di = eval_condition(r);
|
|
Packit Service |
f629e6 |
DEREF(r);
|
|
Packit Service |
f629e6 |
if (! di)
|
|
Packit Service |
f629e6 |
JUMPTO(pc->target_jmp);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_jmp_true:
|
|
Packit Service |
f629e6 |
r = POP_SCALAR();
|
|
Packit Service |
f629e6 |
di = eval_condition(r);
|
|
Packit Service |
f629e6 |
DEREF(r);
|
|
Packit Service |
f629e6 |
if (di)
|
|
Packit Service |
f629e6 |
JUMPTO(pc->target_jmp);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_and:
|
|
Packit Service |
f629e6 |
case Op_or:
|
|
Packit Service |
f629e6 |
t1 = POP_SCALAR();
|
|
Packit Service |
f629e6 |
di = eval_condition(t1);
|
|
Packit Service |
f629e6 |
DEREF(t1);
|
|
Packit Service |
f629e6 |
if ((op == Op_and && di) || (op == Op_or && ! di))
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
r = node_Boolean[di];
|
|
Packit Service |
f629e6 |
UPREF(r);
|
|
Packit Service |
f629e6 |
PUSH(r);
|
|
Packit Service |
f629e6 |
ni = pc->target_jmp;
|
|
Packit Service |
f629e6 |
JUMPTO(ni->nexti);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_and_final:
|
|
Packit Service |
f629e6 |
case Op_or_final:
|
|
Packit Service |
f629e6 |
t1 = TOP_SCALAR();
|
|
Packit Service |
f629e6 |
r = node_Boolean[eval_condition(t1)];
|
|
Packit Service |
f629e6 |
DEREF(t1);
|
|
Packit Service |
f629e6 |
UPREF(r);
|
|
Packit Service |
f629e6 |
REPLACE(r);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_not:
|
|
Packit Service |
f629e6 |
t1 = TOP_SCALAR();
|
|
Packit Service |
f629e6 |
r = node_Boolean[! eval_condition(t1)];
|
|
Packit Service |
f629e6 |
DEREF(t1);
|
|
Packit Service |
f629e6 |
UPREF(r);
|
|
Packit Service |
f629e6 |
REPLACE(r);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_equal:
|
|
Packit Service |
f629e6 |
r = node_Boolean[cmp_scalars(SCALAR_EQ_NEQ) == 0];
|
|
Packit Service |
f629e6 |
UPREF(r);
|
|
Packit Service |
f629e6 |
REPLACE(r);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_notequal:
|
|
Packit Service |
f629e6 |
r = node_Boolean[cmp_scalars(SCALAR_EQ_NEQ) != 0];
|
|
Packit Service |
f629e6 |
UPREF(r);
|
|
Packit Service |
f629e6 |
REPLACE(r);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_less:
|
|
Packit Service |
f629e6 |
r = node_Boolean[cmp_scalars(SCALAR_RELATIONAL) < 0];
|
|
Packit Service |
f629e6 |
UPREF(r);
|
|
Packit Service |
f629e6 |
REPLACE(r);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_greater:
|
|
Packit Service |
f629e6 |
r = node_Boolean[cmp_scalars(SCALAR_RELATIONAL) > 0];
|
|
Packit Service |
f629e6 |
UPREF(r);
|
|
Packit Service |
f629e6 |
REPLACE(r);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_leq:
|
|
Packit Service |
f629e6 |
r = node_Boolean[cmp_scalars(SCALAR_RELATIONAL) <= 0];
|
|
Packit Service |
f629e6 |
UPREF(r);
|
|
Packit Service |
f629e6 |
REPLACE(r);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_geq:
|
|
Packit Service |
f629e6 |
r = node_Boolean[cmp_scalars(SCALAR_RELATIONAL) >= 0];
|
|
Packit Service |
f629e6 |
UPREF(r);
|
|
Packit Service |
f629e6 |
REPLACE(r);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_plus_i:
|
|
Packit Service |
f629e6 |
x2 = force_number(pc->memory)->numbr;
|
|
Packit Service |
f629e6 |
goto plus;
|
|
Packit Service |
f629e6 |
case Op_plus:
|
|
Packit Service |
f629e6 |
t2 = POP_NUMBER();
|
|
Packit Service |
f629e6 |
x2 = t2->numbr;
|
|
Packit Service |
f629e6 |
DEREF(t2);
|
|
Packit Service |
f629e6 |
plus:
|
|
Packit Service |
f629e6 |
t1 = TOP_NUMBER();
|
|
Packit Service |
f629e6 |
r = make_number(t1->numbr + x2);
|
|
Packit Service |
f629e6 |
DEREF(t1);
|
|
Packit Service |
f629e6 |
REPLACE(r);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_minus_i:
|
|
Packit Service |
f629e6 |
x2 = force_number(pc->memory)->numbr;
|
|
Packit Service |
f629e6 |
goto minus;
|
|
Packit Service |
f629e6 |
case Op_minus:
|
|
Packit Service |
f629e6 |
t2 = POP_NUMBER();
|
|
Packit Service |
f629e6 |
x2 = t2->numbr;
|
|
Packit Service |
f629e6 |
DEREF(t2);
|
|
Packit Service |
f629e6 |
minus:
|
|
Packit Service |
f629e6 |
t1 = TOP_NUMBER();
|
|
Packit Service |
f629e6 |
r = make_number(t1->numbr - x2);
|
|
Packit Service |
f629e6 |
DEREF(t1);
|
|
Packit Service |
f629e6 |
REPLACE(r);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_times_i:
|
|
Packit Service |
f629e6 |
x2 = force_number(pc->memory)->numbr;
|
|
Packit Service |
f629e6 |
goto times;
|
|
Packit Service |
f629e6 |
case Op_times:
|
|
Packit Service |
f629e6 |
t2 = POP_NUMBER();
|
|
Packit Service |
f629e6 |
x2 = t2->numbr;
|
|
Packit Service |
f629e6 |
DEREF(t2);
|
|
Packit Service |
f629e6 |
times:
|
|
Packit Service |
f629e6 |
t1 = TOP_NUMBER();
|
|
Packit Service |
f629e6 |
r = make_number(t1->numbr * x2);
|
|
Packit Service |
f629e6 |
DEREF(t1);
|
|
Packit Service |
f629e6 |
REPLACE(r);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_exp_i:
|
|
Packit Service |
f629e6 |
x2 = force_number(pc->memory)->numbr;
|
|
Packit Service |
f629e6 |
goto exp;
|
|
Packit Service |
f629e6 |
case Op_exp:
|
|
Packit Service |
f629e6 |
t2 = POP_NUMBER();
|
|
Packit Service |
f629e6 |
x2 = t2->numbr;
|
|
Packit Service |
f629e6 |
DEREF(t2);
|
|
Packit Service |
f629e6 |
exp:
|
|
Packit Service |
f629e6 |
t1 = TOP_NUMBER();
|
|
Packit Service |
f629e6 |
r = make_number(calc_exp(t1->numbr, x2));
|
|
Packit Service |
f629e6 |
DEREF(t1);
|
|
Packit Service |
f629e6 |
REPLACE(r);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_quotient_i:
|
|
Packit Service |
f629e6 |
x2 = force_number(pc->memory)->numbr;
|
|
Packit Service |
f629e6 |
goto quotient;
|
|
Packit Service |
f629e6 |
case Op_quotient:
|
|
Packit Service |
f629e6 |
t2 = POP_NUMBER();
|
|
Packit Service |
f629e6 |
x2 = t2->numbr;
|
|
Packit Service |
f629e6 |
DEREF(t2);
|
|
Packit Service |
f629e6 |
quotient:
|
|
Packit Service |
f629e6 |
t1 = TOP_NUMBER();
|
|
Packit Service |
f629e6 |
if (x2 == 0)
|
|
Packit Service |
f629e6 |
fatal(_("division by zero attempted"));
|
|
Packit Service |
f629e6 |
r = make_number(t1->numbr / x2);
|
|
Packit Service |
f629e6 |
DEREF(t1);
|
|
Packit Service |
f629e6 |
REPLACE(r);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_mod_i:
|
|
Packit Service |
f629e6 |
x2 = force_number(pc->memory)->numbr;
|
|
Packit Service |
f629e6 |
goto mod;
|
|
Packit Service |
f629e6 |
case Op_mod:
|
|
Packit Service |
f629e6 |
t2 = POP_NUMBER();
|
|
Packit Service |
f629e6 |
x2 = t2->numbr;
|
|
Packit Service |
f629e6 |
DEREF(t2);
|
|
Packit Service |
f629e6 |
mod:
|
|
Packit Service |
f629e6 |
t1 = TOP_NUMBER();
|
|
Packit Service |
f629e6 |
if (x2 == 0)
|
|
Packit Service |
f629e6 |
fatal(_("division by zero attempted in `%%'"));
|
|
Packit Service |
f629e6 |
#ifdef HAVE_FMOD
|
|
Packit Service |
f629e6 |
x = fmod(t1->numbr, x2);
|
|
Packit Service |
f629e6 |
#else /* ! HAVE_FMOD */
|
|
Packit Service |
f629e6 |
(void) modf(t1->numbr / x2, &x);
|
|
Packit Service |
f629e6 |
x = t1->numbr - x * x2;
|
|
Packit Service |
f629e6 |
#endif /* ! HAVE_FMOD */
|
|
Packit Service |
f629e6 |
r = make_number(x);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
DEREF(t1);
|
|
Packit Service |
f629e6 |
REPLACE(r);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_preincrement:
|
|
Packit Service |
f629e6 |
case Op_predecrement:
|
|
Packit Service |
f629e6 |
x = op == Op_preincrement ? 1.0 : -1.0;
|
|
Packit Service |
f629e6 |
lhs = TOP_ADDRESS();
|
|
Packit Service |
f629e6 |
t1 = *lhs;
|
|
Packit Service |
f629e6 |
force_number(t1);
|
|
Packit Service |
f629e6 |
if (t1->valref == 1 && t1->flags == (MALLOC|NUMCUR|NUMBER)) {
|
|
Packit Service |
f629e6 |
/* optimization */
|
|
Packit Service |
f629e6 |
t1->numbr += x;
|
|
Packit Service |
f629e6 |
r = t1;
|
|
Packit Service |
f629e6 |
} else {
|
|
Packit Service |
f629e6 |
r = *lhs = make_number(t1->numbr + x);
|
|
Packit Service |
f629e6 |
unref(t1);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
UPREF(r);
|
|
Packit Service |
f629e6 |
REPLACE(r);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_postincrement:
|
|
Packit Service |
f629e6 |
case Op_postdecrement:
|
|
Packit Service |
f629e6 |
x = op == Op_postincrement ? 1.0 : -1.0;
|
|
Packit Service |
f629e6 |
lhs = TOP_ADDRESS();
|
|
Packit Service |
f629e6 |
t1 = *lhs;
|
|
Packit Service |
f629e6 |
force_number(t1);
|
|
Packit Service |
f629e6 |
r = make_number(t1->numbr);
|
|
Packit Service |
f629e6 |
if (t1->valref == 1 && t1->flags == (MALLOC|NUMCUR|NUMBER)) {
|
|
Packit Service |
f629e6 |
/* optimization */
|
|
Packit Service |
f629e6 |
t1->numbr += x;
|
|
Packit Service |
f629e6 |
} else {
|
|
Packit Service |
f629e6 |
*lhs = make_number(t1->numbr + x);
|
|
Packit Service |
f629e6 |
unref(t1);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
REPLACE(r);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_unary_minus:
|
|
Packit Service |
f629e6 |
t1 = TOP_NUMBER();
|
|
Packit Service |
f629e6 |
r = make_number(-t1->numbr);
|
|
Packit Service |
f629e6 |
DEREF(t1);
|
|
Packit Service |
f629e6 |
REPLACE(r);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_unary_plus:
|
|
Packit Service |
f629e6 |
// Force argument to be numeric
|
|
Packit Service |
f629e6 |
t1 = TOP_NUMBER();
|
|
Packit Service |
f629e6 |
r = make_number(t1->numbr);
|
|
Packit Service |
f629e6 |
DEREF(t1);
|
|
Packit Service |
f629e6 |
REPLACE(r);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_store_sub:
|
|
Packit Service |
f629e6 |
/*
|
|
Packit Service |
f629e6 |
* array[sub] assignment optimization,
|
|
Packit Service |
f629e6 |
* see awkgram.y (optimize_assignment)
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
t1 = force_array(pc->memory, true); /* array */
|
|
Packit Service |
f629e6 |
t2 = mk_sub(pc->expr_count); /* subscript */
|
|
Packit Service |
f629e6 |
lhs = assoc_lookup(t1, t2);
|
|
Packit Service |
f629e6 |
if ((*lhs)->type == Node_var_array) {
|
|
Packit Service |
f629e6 |
t2 = force_string(t2);
|
|
Packit Service |
f629e6 |
fatal(_("attempt to use array `%s[\"%.*s\"]' in a scalar context"),
|
|
Packit Service |
f629e6 |
array_vname(t1), (int) t2->stlen, t2->stptr);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
DEREF(t2);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/*
|
|
Packit Service |
f629e6 |
* Changing something in FUNCTAB is not allowed.
|
|
Packit Service |
f629e6 |
*
|
|
Packit Service |
f629e6 |
* SYMTAB is a little more messy. Three kinds of values may
|
|
Packit Service |
f629e6 |
* be stored in SYMTAB:
|
|
Packit Service |
f629e6 |
* 1. Variables that don"t yet have a value (Node_var_new)
|
|
Packit Service |
f629e6 |
* 2. Variables that have a value (Node_var)
|
|
Packit Service |
f629e6 |
* 3. Values that awk code stuck into SYMTAB not related to variables (Node_value)
|
|
Packit Service |
f629e6 |
* For 1, since we are giving it a value, we have to change the type to Node_var.
|
|
Packit Service |
f629e6 |
* For 1 and 2, we have to step through the Node_var to get to the value.
|
|
Packit Service |
f629e6 |
* For 3, we just us the value we got from assoc_lookup(), above.
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
if (t1 == func_table)
|
|
Packit Service |
f629e6 |
fatal(_("cannot assign to elements of FUNCTAB"));
|
|
Packit Service |
f629e6 |
else if ( t1 == symbol_table
|
|
Packit Service |
f629e6 |
&& ( (*lhs)->type == Node_var
|
|
Packit Service |
f629e6 |
|| (*lhs)->type == Node_var_new)) {
|
|
Packit Service |
f629e6 |
(*lhs)->type = Node_var; /* in case was Node_var_new */
|
|
Packit Service |
f629e6 |
lhs = & ((*lhs)->var_value); /* extra level of indirection */
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
unref(*lhs);
|
|
Packit Service |
f629e6 |
r = POP_SCALAR();
|
|
Packit Service |
f629e6 |
UNFIELD(*lhs, r);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* execute post-assignment routine if any */
|
|
Packit Service |
f629e6 |
if (t1->astore != NULL)
|
|
Packit Service |
f629e6 |
(*t1->astore)(t1, t2);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
DEREF(t2);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_store_var:
|
|
Packit Service |
f629e6 |
/*
|
|
Packit Service |
f629e6 |
* simple variable assignment optimization,
|
|
Packit Service |
f629e6 |
* see awkgram.y (optimize_assignment)
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
lhs = get_lhs(pc->memory, false);
|
|
Packit Service |
f629e6 |
unref(*lhs);
|
|
Packit Service |
f629e6 |
r = pc->initval; /* constant initializer */
|
|
Packit Service |
f629e6 |
if (r != NULL) {
|
|
Packit Service |
f629e6 |
UPREF(r);
|
|
Packit Service |
f629e6 |
*lhs = r;
|
|
Packit Service |
f629e6 |
} else {
|
|
Packit Service |
f629e6 |
r = POP_SCALAR();
|
|
Packit Service |
f629e6 |
UNFIELD(*lhs, r);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_store_field:
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
/* field assignment optimization,
|
|
Packit Service |
f629e6 |
* see awkgram.y (optimize_assignment)
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
Func_ptr assign;
|
|
Packit Service |
f629e6 |
t1 = TOP_SCALAR();
|
|
Packit Service |
f629e6 |
lhs = r_get_field(t1, & assign, false);
|
|
Packit Service |
f629e6 |
decr_sp();
|
|
Packit Service |
f629e6 |
DEREF(t1);
|
|
Packit Service |
f629e6 |
/*
|
|
Packit Service |
f629e6 |
* N.B. We must call assign() before unref, since
|
|
Packit Service |
f629e6 |
* we may need to copy $n values before freeing the
|
|
Packit Service |
f629e6 |
* $0 buffer.
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
assert(assign != NULL);
|
|
Packit Service |
f629e6 |
assign();
|
|
Packit Service |
f629e6 |
unref(*lhs);
|
|
Packit Service |
f629e6 |
r = POP_SCALAR();
|
|
Packit Service |
f629e6 |
UNFIELD(*lhs, r);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_assign_concat:
|
|
Packit Service |
f629e6 |
/* x = x ... string concatenation optimization */
|
|
Packit Service |
f629e6 |
lhs = get_lhs(pc->memory, false);
|
|
Packit Service |
f629e6 |
t1 = force_string(*lhs);
|
|
Packit Service |
f629e6 |
t2 = POP_STRING();
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (t1 != *lhs) {
|
|
Packit Service |
f629e6 |
unref(*lhs);
|
|
Packit Service |
f629e6 |
*lhs = dupnode(t1);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (t1 != t2 && t1->valref == 1 && (t1->flags & (MALLOC|MPFN|MPZN)) == MALLOC) {
|
|
Packit Service |
f629e6 |
size_t nlen = t1->stlen + t2->stlen;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
erealloc(t1->stptr, char *, nlen + 1, "r_interpret");
|
|
Packit Service |
f629e6 |
memcpy(t1->stptr + t1->stlen, t2->stptr, t2->stlen);
|
|
Packit Service |
f629e6 |
t1->stlen = nlen;
|
|
Packit Service |
f629e6 |
t1->stptr[nlen] = '\0';
|
|
Packit Service |
f629e6 |
/* clear flags except WSTRCUR (used below) */
|
|
Packit Service |
f629e6 |
t1->flags &= WSTRCUR;
|
|
Packit Service |
f629e6 |
/* configure as a string as in make_str_node */
|
|
Packit Service |
f629e6 |
t1->flags |= (MALLOC|STRING|STRCUR);
|
|
Packit Service |
f629e6 |
t1->stfmt = STFMT_UNUSED;
|
|
Packit Service |
f629e6 |
#ifdef HAVE_MPFR
|
|
Packit Service |
f629e6 |
t1->strndmode = MPFR_round_mode;
|
|
Packit Service |
f629e6 |
#endif
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if ((t1->flags & WSTRCUR) != 0 && (t2->flags & WSTRCUR) != 0) {
|
|
Packit Service |
f629e6 |
size_t wlen = t1->wstlen + t2->wstlen;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
erealloc(t1->wstptr, wchar_t *,
|
|
Packit Service |
f629e6 |
sizeof(wchar_t) * (wlen + 1), "r_interpret");
|
|
Packit Service |
f629e6 |
memcpy(t1->wstptr + t1->wstlen, t2->wstptr, t2->wstlen * sizeof(wchar_t));
|
|
Packit Service |
f629e6 |
t1->wstlen = wlen;
|
|
Packit Service |
f629e6 |
t1->wstptr[wlen] = L'\0';
|
|
Packit Service |
f629e6 |
} else
|
|
Packit Service |
f629e6 |
free_wstr(*lhs);
|
|
Packit Service |
f629e6 |
} else {
|
|
Packit Service |
f629e6 |
size_t nlen = t1->stlen + t2->stlen;
|
|
Packit Service |
f629e6 |
char *p;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
emalloc(p, char *, nlen + 1, "r_interpret");
|
|
Packit Service |
f629e6 |
memcpy(p, t1->stptr, t1->stlen);
|
|
Packit Service |
f629e6 |
memcpy(p + t1->stlen, t2->stptr, t2->stlen);
|
|
Packit Service |
f629e6 |
/* N.B. No NUL-termination required, since make_str_node will do it. */
|
|
Packit Service |
f629e6 |
unref(*lhs);
|
|
Packit Service |
f629e6 |
t1 = *lhs = make_str_node(p, nlen, ALREADY_MALLOCED);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
DEREF(t2);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_assign:
|
|
Packit Service |
f629e6 |
lhs = POP_ADDRESS();
|
|
Packit Service |
f629e6 |
r = TOP_SCALAR();
|
|
Packit Service |
f629e6 |
unref(*lhs);
|
|
Packit Service |
f629e6 |
UPREF(r);
|
|
Packit Service |
f629e6 |
UNFIELD(*lhs, r);
|
|
Packit Service |
f629e6 |
REPLACE(r);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_subscript_assign:
|
|
Packit Service |
f629e6 |
/* conditionally execute post-assignment routine for an array element */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (set_idx != NULL) {
|
|
Packit Service |
f629e6 |
di = true;
|
|
Packit Service |
f629e6 |
if (pc->assign_ctxt == Op_sub_builtin
|
|
Packit Service |
f629e6 |
&& (r = TOP())
|
|
Packit Service |
f629e6 |
&& get_number_si(r) == 0 /* no substitution performed */
|
|
Packit Service |
f629e6 |
)
|
|
Packit Service |
f629e6 |
di = false;
|
|
Packit Service |
f629e6 |
else if ((pc->assign_ctxt == Op_K_getline
|
|
Packit Service |
f629e6 |
|| pc->assign_ctxt == Op_K_getline_redir)
|
|
Packit Service |
f629e6 |
&& (r = TOP())
|
|
Packit Service |
f629e6 |
&& get_number_si(r) <= 0 /* EOF or error */
|
|
Packit Service |
f629e6 |
)
|
|
Packit Service |
f629e6 |
di = false;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (di)
|
|
Packit Service |
f629e6 |
(*set_array->astore)(set_array, set_idx);
|
|
Packit Service |
f629e6 |
unref(set_idx);
|
|
Packit Service |
f629e6 |
set_idx = NULL;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* numeric assignments */
|
|
Packit Service |
f629e6 |
case Op_assign_plus:
|
|
Packit Service |
f629e6 |
case Op_assign_minus:
|
|
Packit Service |
f629e6 |
case Op_assign_times:
|
|
Packit Service |
f629e6 |
case Op_assign_quotient:
|
|
Packit Service |
f629e6 |
case Op_assign_mod:
|
|
Packit Service |
f629e6 |
case Op_assign_exp:
|
|
Packit Service |
f629e6 |
op_assign(op);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_var_update: /* update value of NR, FNR or NF */
|
|
Packit Service |
f629e6 |
pc->update_var();
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_var_assign:
|
|
Packit Service |
f629e6 |
case Op_field_assign:
|
|
Packit Service |
f629e6 |
r = TOP();
|
|
Packit Service |
f629e6 |
if (pc->assign_ctxt == Op_sub_builtin
|
|
Packit Service |
f629e6 |
&& get_number_si(r) == 0 /* top of stack has a number == 0 */
|
|
Packit Service |
f629e6 |
) {
|
|
Packit Service |
f629e6 |
/* There wasn't any substitutions. If the target is a FIELD,
|
|
Packit Service |
f629e6 |
* this means no field re-splitting or $0 reconstruction.
|
|
Packit Service |
f629e6 |
* Skip the set_FOO routine if the target is a special variable.
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
} else if ((pc->assign_ctxt == Op_K_getline
|
|
Packit Service |
f629e6 |
|| pc->assign_ctxt == Op_K_getline_redir)
|
|
Packit Service |
f629e6 |
&& get_number_si(r) <= 0 /* top of stack has a number <= 0 */
|
|
Packit Service |
f629e6 |
) {
|
|
Packit Service |
f629e6 |
/* getline returned EOF or error */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (op == Op_var_assign)
|
|
Packit Service |
f629e6 |
pc->assign_var();
|
|
Packit Service |
f629e6 |
else
|
|
Packit Service |
f629e6 |
pc->field_assign();
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_concat:
|
|
Packit Service |
f629e6 |
r = concat_exp(pc->expr_count, pc->concat_flag & CSUBSEP);
|
|
Packit Service |
f629e6 |
PUSH(r);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_K_case:
|
|
Packit Service |
f629e6 |
if ((pc + 1)->match_exp) {
|
|
Packit Service |
f629e6 |
/* match a constant regex against switch expression instead of $0. */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
m = POP(); /* regex */
|
|
Packit Service |
f629e6 |
t2 = TOP_SCALAR(); /* switch expression */
|
|
Packit Service |
f629e6 |
t2 = force_string(t2);
|
|
Packit Service |
f629e6 |
rp = re_update(m);
|
|
Packit Service |
f629e6 |
di = (research(rp, t2->stptr, 0, t2->stlen, RE_NO_FLAGS) >= 0);
|
|
Packit Service |
f629e6 |
} else {
|
|
Packit Service |
f629e6 |
t1 = POP_SCALAR(); /* case value */
|
|
Packit Service |
f629e6 |
t2 = TOP_SCALAR(); /* switch expression */
|
|
Packit Service |
f629e6 |
di = (cmp_nodes(t2, t1, true) == 0);
|
|
Packit Service |
f629e6 |
DEREF(t1);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (di) {
|
|
Packit Service |
f629e6 |
/* match found */
|
|
Packit Service |
f629e6 |
t2 = POP_SCALAR();
|
|
Packit Service |
f629e6 |
DEREF(t2);
|
|
Packit Service |
f629e6 |
JUMPTO(pc->target_jmp);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_K_delete:
|
|
Packit Service |
f629e6 |
t1 = POP_ARRAY();
|
|
Packit Service |
f629e6 |
do_delete(t1, pc->expr_count);
|
|
Packit Service |
f629e6 |
stack_adj(-pc->expr_count);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_K_delete_loop:
|
|
Packit Service |
f629e6 |
t1 = POP_ARRAY();
|
|
Packit Service |
f629e6 |
lhs = POP_ADDRESS(); /* item */
|
|
Packit Service |
f629e6 |
do_delete_loop(t1, lhs);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_in_array:
|
|
Packit Service |
f629e6 |
t1 = POP_ARRAY();
|
|
Packit Service |
f629e6 |
t2 = mk_sub(pc->expr_count);
|
|
Packit Service |
f629e6 |
r = node_Boolean[(in_array(t1, t2) != NULL)];
|
|
Packit Service |
f629e6 |
DEREF(t2);
|
|
Packit Service |
f629e6 |
UPREF(r);
|
|
Packit Service |
f629e6 |
PUSH(r);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_arrayfor_init:
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
NODE **list = NULL;
|
|
Packit Service |
f629e6 |
NODE *array, *sort_str;
|
|
Packit Service |
f629e6 |
size_t num_elems = 0;
|
|
Packit Service |
f629e6 |
static NODE *sorted_in = NULL;
|
|
Packit Service |
f629e6 |
const char *how_to_sort = "@unsorted";
|
|
Packit Service |
f629e6 |
char save;
|
|
Packit Service |
f629e6 |
bool saved_end = false;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* get the array */
|
|
Packit Service |
f629e6 |
array = POP_ARRAY();
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* sanity: check if empty */
|
|
Packit Service |
f629e6 |
num_elems = assoc_length(array);
|
|
Packit Service |
f629e6 |
if (num_elems == 0)
|
|
Packit Service |
f629e6 |
goto arrayfor;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (sorted_in == NULL) /* do this once */
|
|
Packit Service |
f629e6 |
sorted_in = make_string("sorted_in", 9);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
sort_str = NULL;
|
|
Packit Service |
f629e6 |
/*
|
|
Packit Service |
f629e6 |
* If posix, or if there's no PROCINFO[],
|
|
Packit Service |
f629e6 |
* there's no ["sorted_in"], so no sorting
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
if (! do_posix && PROCINFO_node != NULL)
|
|
Packit Service |
f629e6 |
sort_str = in_array(PROCINFO_node, sorted_in);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (sort_str != NULL) {
|
|
Packit Service |
f629e6 |
sort_str = force_string(sort_str);
|
|
Packit Service |
f629e6 |
if (sort_str->stlen > 0) {
|
|
Packit Service |
f629e6 |
how_to_sort = sort_str->stptr;
|
|
Packit Service |
f629e6 |
str_terminate(sort_str, save);
|
|
Packit Service |
f629e6 |
saved_end = true;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
list = assoc_list(array, how_to_sort, SORTED_IN);
|
|
Packit Service |
f629e6 |
if (saved_end)
|
|
Packit Service |
f629e6 |
str_restore(sort_str, save);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
arrayfor:
|
|
Packit Service |
f629e6 |
getnode(r);
|
|
Packit Service |
f629e6 |
r->type = Node_arrayfor;
|
|
Packit Service |
f629e6 |
r->for_list = list;
|
|
Packit Service |
f629e6 |
r->for_list_size = num_elems; /* # of elements in list */
|
|
Packit Service |
f629e6 |
r->cur_idx = -1; /* current index */
|
|
Packit Service |
f629e6 |
r->for_array = array; /* array */
|
|
Packit Service |
f629e6 |
PUSH(r);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (num_elems == 0)
|
|
Packit Service |
f629e6 |
JUMPTO(pc->target_jmp); /* Op_arrayfor_final */
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_arrayfor_incr:
|
|
Packit Service |
f629e6 |
r = TOP(); /* Node_arrayfor */
|
|
Packit Service |
f629e6 |
if (++r->cur_idx == r->for_list_size) {
|
|
Packit Service |
f629e6 |
NODE *array;
|
|
Packit Service |
f629e6 |
array = r->for_array; /* actual array */
|
|
Packit Service |
f629e6 |
if (do_lint && array->table_size != r->for_list_size)
|
|
Packit Service |
f629e6 |
lintwarn(_("for loop: array `%s' changed size from %ld to %ld during loop execution"),
|
|
Packit Service |
f629e6 |
array_vname(array), (long) r->for_list_size, (long) array->table_size);
|
|
Packit Service |
f629e6 |
JUMPTO(pc->target_jmp); /* Op_arrayfor_final */
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
t1 = r->for_list[r->cur_idx];
|
|
Packit Service |
f629e6 |
lhs = get_lhs(pc->array_var, false);
|
|
Packit Service |
f629e6 |
unref(*lhs);
|
|
Packit Service |
f629e6 |
*lhs = dupnode(t1);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_arrayfor_final:
|
|
Packit Service |
f629e6 |
r = POP();
|
|
Packit Service |
f629e6 |
assert(r->type == Node_arrayfor);
|
|
Packit Service |
f629e6 |
free_arrayfor(r);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_builtin:
|
|
Packit Service |
f629e6 |
r = pc->builtin(pc->expr_count);
|
|
Packit Service |
f629e6 |
PUSH(r);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_ext_builtin:
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
size_t arg_count = pc->expr_count;
|
|
Packit Service |
f629e6 |
awk_ext_func_t *f = pc[1].c_function;
|
|
Packit Service |
f629e6 |
size_t min_req = f->min_required_args;
|
|
Packit Service |
f629e6 |
size_t max_expect = f->max_expected_args;
|
|
Packit Service |
f629e6 |
awk_value_t result;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (arg_count < min_req)
|
|
Packit Service |
f629e6 |
fatal(_("%s: called with %lu arguments, expecting at least %lu"),
|
|
Packit Service |
f629e6 |
pc[1].func_name,
|
|
Packit Service |
f629e6 |
(unsigned long) arg_count,
|
|
Packit Service |
f629e6 |
(unsigned long) min_req);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (do_lint && ! f->suppress_lint && arg_count > max_expect)
|
|
Packit Service |
f629e6 |
lintwarn(_("%s: called with %lu arguments, expecting no more than %lu"),
|
|
Packit Service |
f629e6 |
pc[1].func_name,
|
|
Packit Service |
f629e6 |
(unsigned long) arg_count,
|
|
Packit Service |
f629e6 |
(unsigned long) max_expect);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
PUSH_CODE(pc);
|
|
Packit Service |
f629e6 |
r = awk_value_to_node(pc->extfunc(arg_count, & result, f));
|
|
Packit Service |
f629e6 |
(void) POP_CODE();
|
|
Packit Service |
f629e6 |
while (arg_count-- > 0) {
|
|
Packit Service |
f629e6 |
t1 = POP();
|
|
Packit Service |
f629e6 |
if (t1->type == Node_val)
|
|
Packit Service |
f629e6 |
DEREF(t1);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
free_api_string_copies();
|
|
Packit Service |
f629e6 |
PUSH(r);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_sub_builtin: /* sub, gsub and gensub */
|
|
Packit Service |
f629e6 |
r = do_sub(pc->expr_count, pc->sub_flags);
|
|
Packit Service |
f629e6 |
PUSH(r);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_K_print:
|
|
Packit Service |
f629e6 |
do_print(pc->expr_count, pc->redir_type);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_K_printf:
|
|
Packit Service |
f629e6 |
do_printf(pc->expr_count, pc->redir_type);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_K_print_rec:
|
|
Packit Service |
f629e6 |
do_print_rec(pc->expr_count, pc->redir_type);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_push_re:
|
|
Packit Service |
f629e6 |
m = pc->memory;
|
|
Packit Service |
f629e6 |
if (m->type == Node_dynregex) {
|
|
Packit Service |
f629e6 |
r = POP_STRING();
|
|
Packit Service |
f629e6 |
unref(m->re_exp);
|
|
Packit Service |
f629e6 |
m->re_exp = r;
|
|
Packit Service |
f629e6 |
} else if (m->type == Node_val) {
|
|
Packit Service |
f629e6 |
assert((m->flags & REGEX) != 0);
|
|
Packit Service |
f629e6 |
UPREF(m);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
PUSH(m);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_match_rec:
|
|
Packit Service |
f629e6 |
m = pc->memory;
|
|
Packit Service |
f629e6 |
t1 = *get_field(0, (Func_ptr *) 0);
|
|
Packit Service |
f629e6 |
match_re:
|
|
Packit Service |
f629e6 |
rp = re_update(m);
|
|
Packit Service |
f629e6 |
di = research(rp, t1->stptr, 0, t1->stlen, RE_NO_FLAGS);
|
|
Packit Service |
f629e6 |
di = (di == -1) ^ (op != Op_nomatch);
|
|
Packit Service |
f629e6 |
if (op != Op_match_rec) {
|
|
Packit Service |
f629e6 |
decr_sp();
|
|
Packit Service |
f629e6 |
DEREF(t1);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
r = node_Boolean[di];
|
|
Packit Service |
f629e6 |
UPREF(r);
|
|
Packit Service |
f629e6 |
PUSH(r);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_nomatch:
|
|
Packit Service |
f629e6 |
/* fall through */
|
|
Packit Service |
f629e6 |
case Op_match:
|
|
Packit Service |
f629e6 |
m = pc->memory;
|
|
Packit Service |
f629e6 |
t1 = TOP_STRING();
|
|
Packit Service |
f629e6 |
if (m->type == Node_dynregex) {
|
|
Packit Service |
f629e6 |
unref(m->re_exp);
|
|
Packit Service |
f629e6 |
m->re_exp = t1;
|
|
Packit Service |
f629e6 |
decr_sp();
|
|
Packit Service |
f629e6 |
t1 = TOP_STRING();
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
goto match_re;
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_indirect_func_call:
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
NODE *f = NULL;
|
|
Packit Service |
f629e6 |
int arg_count;
|
|
Packit Service |
f629e6 |
char save;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
arg_count = (pc + 1)->expr_count;
|
|
Packit Service |
f629e6 |
t1 = PEEK(arg_count); /* indirect var */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (t1->type != Node_val) /* @a[1](p) not allowed in grammar */
|
|
Packit Service |
f629e6 |
fatal(_("indirect function call requires a simple scalar value"));
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
t1 = force_string(t1);
|
|
Packit Service |
f629e6 |
str_terminate(t1, save);
|
|
Packit Service |
f629e6 |
if (t1->stlen > 0) {
|
|
Packit Service |
f629e6 |
/* retrieve function definition node */
|
|
Packit Service |
f629e6 |
f = pc->func_body;
|
|
Packit Service |
f629e6 |
if (f != NULL && strcmp(f->vname, t1->stptr) == 0) {
|
|
Packit Service |
f629e6 |
/* indirect var hasn't been reassigned */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
str_restore(t1, save);
|
|
Packit Service |
f629e6 |
ni = setup_frame(pc);
|
|
Packit Service |
f629e6 |
JUMPTO(ni); /* Op_func */
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
f = lookup(t1->stptr);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (f == NULL) {
|
|
Packit Service |
f629e6 |
fatal(_("`%s' is not a function, so it cannot be called indirectly"),
|
|
Packit Service |
f629e6 |
t1->stptr);
|
|
Packit Service |
f629e6 |
} else if (f->type == Node_builtin_func) {
|
|
Packit Service |
f629e6 |
int arg_count = (pc + 1)->expr_count;
|
|
Packit Service |
f629e6 |
builtin_func_t the_func = lookup_builtin(t1->stptr);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
assert(the_func != NULL);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* call it */
|
|
Packit Service |
f629e6 |
if (the_func == (builtin_func_t) do_sub)
|
|
Packit Service |
f629e6 |
r = call_sub(t1->stptr, arg_count);
|
|
Packit Service |
f629e6 |
else if (the_func == do_match)
|
|
Packit Service |
f629e6 |
r = call_match(arg_count);
|
|
Packit Service |
f629e6 |
else if (the_func == do_split || the_func == do_patsplit)
|
|
Packit Service |
f629e6 |
r = call_split_func(t1->stptr, arg_count);
|
|
Packit Service |
f629e6 |
else
|
|
Packit Service |
f629e6 |
r = the_func(arg_count);
|
|
Packit Service |
f629e6 |
str_restore(t1, save);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
PUSH(r);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
} else if (f->type != Node_func) {
|
|
Packit Service |
f629e6 |
str_restore(t1, save);
|
|
Packit Service |
f629e6 |
if (f->type == Node_ext_func) {
|
|
Packit Service |
f629e6 |
/* code copied from below, keep in sync */
|
|
Packit Service |
f629e6 |
INSTRUCTION *bc;
|
|
Packit Service |
f629e6 |
char *fname = pc->func_name;
|
|
Packit Service |
f629e6 |
int arg_count = (pc + 1)->expr_count;
|
|
Packit Service |
f629e6 |
static INSTRUCTION npc[2];
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
npc[0] = *pc;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
bc = f->code_ptr;
|
|
Packit Service |
f629e6 |
assert(bc->opcode == Op_symbol);
|
|
Packit Service |
f629e6 |
npc[0].opcode = Op_ext_builtin; /* self modifying code */
|
|
Packit Service |
f629e6 |
npc[0].extfunc = bc->extfunc;
|
|
Packit Service |
f629e6 |
npc[0].expr_count = arg_count; /* actual argument count */
|
|
Packit Service |
f629e6 |
npc[1] = pc[1];
|
|
Packit Service |
f629e6 |
npc[1].func_name = fname; /* name of the builtin */
|
|
Packit Service |
f629e6 |
npc[1].c_function = bc->c_function;
|
|
Packit Service |
f629e6 |
ni = npc;
|
|
Packit Service |
f629e6 |
JUMPTO(ni);
|
|
Packit Service |
f629e6 |
} else
|
|
Packit Service |
f629e6 |
fatal(_("function called indirectly through `%s' does not exist"),
|
|
Packit Service |
f629e6 |
pc->func_name);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
pc->func_body = f; /* save for next call */
|
|
Packit Service |
f629e6 |
str_restore(t1, save);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
ni = setup_frame(pc);
|
|
Packit Service |
f629e6 |
JUMPTO(ni); /* Op_func */
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_func_call:
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
NODE *f;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* retrieve function definition node */
|
|
Packit Service |
f629e6 |
f = pc->func_body;
|
|
Packit Service |
f629e6 |
if (f == NULL) {
|
|
Packit Service |
f629e6 |
f = lookup(pc->func_name);
|
|
Packit Service |
f629e6 |
if (f == NULL || (f->type != Node_func && f->type != Node_ext_func))
|
|
Packit Service |
f629e6 |
fatal(_("function `%s' not defined"), pc->func_name);
|
|
Packit Service |
f629e6 |
pc->func_body = f; /* save for next call */
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (f->type == Node_ext_func) {
|
|
Packit Service |
f629e6 |
/* keep in sync with indirect call code */
|
|
Packit Service |
f629e6 |
INSTRUCTION *bc;
|
|
Packit Service |
f629e6 |
char *fname = pc->func_name;
|
|
Packit Service |
f629e6 |
int arg_count = (pc + 1)->expr_count;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
bc = f->code_ptr;
|
|
Packit Service |
f629e6 |
assert(bc->opcode == Op_symbol);
|
|
Packit Service |
f629e6 |
pc->opcode = Op_ext_builtin; /* self modifying code */
|
|
Packit Service |
f629e6 |
pc->extfunc = bc->extfunc;
|
|
Packit Service |
f629e6 |
pc->expr_count = arg_count; /* actual argument count */
|
|
Packit Service |
f629e6 |
(pc + 1)->func_name = fname; /* name of the builtin */
|
|
Packit Service |
f629e6 |
(pc + 1)->c_function = bc->c_function; /* min and max args */
|
|
Packit Service |
f629e6 |
ni = pc;
|
|
Packit Service |
f629e6 |
JUMPTO(ni);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
ni = setup_frame(pc);
|
|
Packit Service |
f629e6 |
JUMPTO(ni); /* Op_func */
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_K_return:
|
|
Packit Service |
f629e6 |
m = POP_SCALAR(); /* return value */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
ni = pop_fcall();
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* put the return value back on stack */
|
|
Packit Service |
f629e6 |
PUSH(m);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
JUMPTO(ni);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_K_getline_redir:
|
|
Packit Service |
f629e6 |
r = do_getline_redir(pc->into_var, pc->redir_type);
|
|
Packit Service |
f629e6 |
PUSH(r);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_K_getline: /* no redirection */
|
|
Packit Service |
f629e6 |
if (! currule || currule == BEGINFILE || currule == ENDFILE)
|
|
Packit Service |
f629e6 |
fatal(_("non-redirected `getline' invalid inside `%s' rule"),
|
|
Packit Service |
f629e6 |
ruletab[currule]);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
do {
|
|
Packit Service |
f629e6 |
int ret;
|
|
Packit Service |
f629e6 |
ret = nextfile(& curfile, false);
|
|
Packit Service |
f629e6 |
if (ret <= 0)
|
|
Packit Service |
f629e6 |
r = do_getline(pc->into_var, curfile);
|
|
Packit Service |
f629e6 |
else {
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* Save execution state so that we can return to it
|
|
Packit Service |
f629e6 |
* from Op_after_beginfile or Op_after_endfile.
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
push_exec_state(pc, currule, source, stack_ptr);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (curfile == NULL)
|
|
Packit Service |
f629e6 |
JUMPTO((pc + 1)->target_endfile);
|
|
Packit Service |
f629e6 |
else
|
|
Packit Service |
f629e6 |
JUMPTO((pc + 1)->target_beginfile);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
} while (r == NULL); /* EOF */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
PUSH(r);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_after_endfile:
|
|
Packit Service |
f629e6 |
/* Find the execution state to return to */
|
|
Packit Service |
f629e6 |
ni = pop_exec_state(& currule, & source, NULL);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
assert(ni->opcode == Op_newfile || ni->opcode == Op_K_getline);
|
|
Packit Service |
f629e6 |
JUMPTO(ni);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_after_beginfile:
|
|
Packit Service |
f629e6 |
after_beginfile(& curfile);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* Find the execution state to return to */
|
|
Packit Service |
f629e6 |
ni = pop_exec_state(& currule, & source, NULL);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
assert(ni->opcode == Op_newfile || ni->opcode == Op_K_getline);
|
|
Packit Service |
f629e6 |
if (ni->opcode == Op_K_getline
|
|
Packit Service |
f629e6 |
|| curfile == NULL /* skipping directory argument */
|
|
Packit Service |
f629e6 |
)
|
|
Packit Service |
f629e6 |
JUMPTO(ni);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
break; /* read a record, Op_get_record */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_newfile:
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
int ret;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
ret = nextfile(& curfile, false);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (ret < 0) /* end of input */
|
|
Packit Service |
f629e6 |
JUMPTO(pc->target_jmp); /* end block or Op_atexit */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (ret == 0) /* read a record */
|
|
Packit Service |
f629e6 |
JUMPTO((pc + 1)->target_get_record);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* ret > 0 */
|
|
Packit Service |
f629e6 |
/* Save execution state for use in Op_after_beginfile or Op_after_endfile. */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
push_exec_state(pc, currule, source, stack_ptr);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (curfile == NULL) /* EOF */
|
|
Packit Service |
f629e6 |
JUMPTO(pc->target_endfile);
|
|
Packit Service |
f629e6 |
/* else
|
|
Packit Service |
f629e6 |
execute beginfile block */
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_get_record:
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
int errcode = 0;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
ni = pc->target_newfile;
|
|
Packit Service |
f629e6 |
if (curfile == NULL) {
|
|
Packit Service |
f629e6 |
/* from non-redirected getline, e.g.:
|
|
Packit Service |
f629e6 |
* {
|
|
Packit Service |
f629e6 |
* while (getline > 0) ;
|
|
Packit Service |
f629e6 |
* }
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
ni = ni->target_jmp; /* end_block or Op_atexit */
|
|
Packit Service |
f629e6 |
JUMPTO(ni);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (! inrec(curfile, & errcode)) {
|
|
Packit Service |
f629e6 |
if (errcode > 0) {
|
|
Packit Service |
f629e6 |
update_ERRNO_int(errcode);
|
|
Packit Service |
f629e6 |
if (do_traditional || ! pc->has_endfile)
|
|
Packit Service |
f629e6 |
fatal(_("error reading input file `%s': %s"),
|
|
Packit Service |
f629e6 |
curfile->public.name, strerror(errcode));
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
JUMPTO(ni);
|
|
Packit Service |
f629e6 |
} /* else
|
|
Packit Service |
f629e6 |
prog (rule) block */
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_K_nextfile:
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
int ret;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (currule != Rule && currule != BEGINFILE)
|
|
Packit Service |
f629e6 |
fatal(_("`nextfile' cannot be called from a `%s' rule"),
|
|
Packit Service |
f629e6 |
ruletab[currule]);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
ret = nextfile(& curfile, true); /* skip current file */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (currule == BEGINFILE) {
|
|
Packit Service |
f629e6 |
long stack_size = 0;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
ni = pop_exec_state(& currule, & source, & stack_size);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
assert(ni->opcode == Op_K_getline || ni->opcode == Op_newfile);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* pop stack returning to the state of Op_K_getline or Op_newfile. */
|
|
Packit Service |
f629e6 |
unwind_stack(stack_size);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (ret == 0) {
|
|
Packit Service |
f629e6 |
/* There was an error opening the file;
|
|
Packit Service |
f629e6 |
* don't run ENDFILE block(s).
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
JUMPTO(ni);
|
|
Packit Service |
f629e6 |
} else {
|
|
Packit Service |
f629e6 |
/* do run ENDFILE block(s) first. */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* Execution state to return to in Op_after_endfile. */
|
|
Packit Service |
f629e6 |
push_exec_state(ni, currule, source, stack_ptr);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
JUMPTO(pc->target_endfile);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
} /* else
|
|
Packit Service |
f629e6 |
Start over with the first rule. */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* empty the run-time stack to avoid memory leak */
|
|
Packit Service |
f629e6 |
pop_stack();
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* Push an execution state for Op_after_endfile to return to */
|
|
Packit Service |
f629e6 |
push_exec_state(pc->target_newfile, currule, source, stack_ptr);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
JUMPTO(pc->target_endfile);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_K_exit:
|
|
Packit Service |
f629e6 |
/* exit not allowed in user-defined comparison functions for "sorted_in";
|
|
Packit Service |
f629e6 |
* This is done so that END blocks aren't executed more than once.
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
if (! currule)
|
|
Packit Service |
f629e6 |
fatal(_("`exit' cannot be called in the current context"));
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
exiting = true;
|
|
Packit Service |
f629e6 |
if ((t1 = POP_NUMBER()) != Nnull_string) {
|
|
Packit Service |
f629e6 |
exit_val = (int) get_number_si(t1);
|
|
Packit Service |
f629e6 |
#ifdef VMS
|
|
Packit Service |
f629e6 |
if (exit_val == 0)
|
|
Packit Service |
f629e6 |
exit_val = EXIT_SUCCESS;
|
|
Packit Service |
f629e6 |
else if (exit_val == 1)
|
|
Packit Service |
f629e6 |
exit_val = EXIT_FAILURE;
|
|
Packit Service |
f629e6 |
/* else
|
|
Packit Service |
f629e6 |
just pass anything else on through */
|
|
Packit Service |
f629e6 |
#endif
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
DEREF(t1);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (currule == BEGINFILE || currule == ENDFILE) {
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* Find the rule of the saved execution state (Op_K_getline/Op_newfile).
|
|
Packit Service |
f629e6 |
* This is needed to prevent multiple execution of any END rules:
|
|
Packit Service |
f629e6 |
* gawk 'BEGINFILE { exit(1) } \
|
|
Packit Service |
f629e6 |
* END { while (getline > 0); }' in1 in2
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
(void) pop_exec_state(& currule, & source, NULL);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
pop_stack(); /* empty stack, don't leak memory */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* Jump to either the first END block instruction
|
|
Packit Service |
f629e6 |
* or to Op_atexit.
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (currule == END)
|
|
Packit Service |
f629e6 |
ni = pc->target_atexit;
|
|
Packit Service |
f629e6 |
else
|
|
Packit Service |
f629e6 |
ni = pc->target_end;
|
|
Packit Service |
f629e6 |
JUMPTO(ni);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_K_next:
|
|
Packit Service |
f629e6 |
if (currule != Rule)
|
|
Packit Service |
f629e6 |
fatal(_("`next' cannot be called from a `%s' rule"), ruletab[currule]);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
pop_stack();
|
|
Packit Service |
f629e6 |
JUMPTO(pc->target_jmp); /* Op_get_record, read next record */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_pop:
|
|
Packit Service |
f629e6 |
r = POP_SCALAR();
|
|
Packit Service |
f629e6 |
DEREF(r);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_line_range:
|
|
Packit Service |
f629e6 |
if (pc->triggered) /* evaluate right expression */
|
|
Packit Service |
f629e6 |
JUMPTO(pc->target_jmp);
|
|
Packit Service |
f629e6 |
/* else
|
|
Packit Service |
f629e6 |
evaluate left expression */
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_cond_pair:
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
int result;
|
|
Packit Service |
f629e6 |
INSTRUCTION *ip;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
t1 = TOP_SCALAR(); /* from right hand side expression */
|
|
Packit Service |
f629e6 |
di = (eval_condition(t1) != 0);
|
|
Packit Service |
f629e6 |
DEREF(t1);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
ip = pc->line_range; /* Op_line_range */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (! ip->triggered && di) {
|
|
Packit Service |
f629e6 |
/* not already triggered and left expression is true */
|
|
Packit Service |
f629e6 |
decr_sp();
|
|
Packit Service |
f629e6 |
ip->triggered = true;
|
|
Packit Service |
f629e6 |
JUMPTO(ip->target_jmp); /* evaluate right expression */
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
result = ip->triggered || di;
|
|
Packit Service |
f629e6 |
ip->triggered ^= di; /* update triggered flag */
|
|
Packit Service |
f629e6 |
r = node_Boolean[result]; /* final value of condition pair */
|
|
Packit Service |
f629e6 |
UPREF(r);
|
|
Packit Service |
f629e6 |
REPLACE(r);
|
|
Packit Service |
f629e6 |
JUMPTO(pc->target_jmp);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_exec_count:
|
|
Packit Service |
f629e6 |
if (do_profile)
|
|
Packit Service |
f629e6 |
pc->exec_count++;
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
case Op_no_op:
|
|
Packit Service |
f629e6 |
case Op_K_do:
|
|
Packit Service |
f629e6 |
case Op_K_while:
|
|
Packit Service |
f629e6 |
case Op_K_for:
|
|
Packit Service |
f629e6 |
case Op_K_arrayfor:
|
|
Packit Service |
f629e6 |
case Op_K_switch:
|
|
Packit Service |
f629e6 |
case Op_K_default:
|
|
Packit Service |
f629e6 |
case Op_K_if:
|
|
Packit Service |
f629e6 |
case Op_K_else:
|
|
Packit Service |
f629e6 |
case Op_cond_exp:
|
|
Packit Service |
f629e6 |
case Op_comment:
|
|
Packit Service |
f629e6 |
case Op_parens:
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
default:
|
|
Packit Service |
f629e6 |
fatal(_("Sorry, don't know how to interpret `%s'"), opcode2str(op));
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
JUMPTO(pc->nexti);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* } forever */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* not reached */
|
|
Packit Service |
f629e6 |
return 0;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
#undef mk_sub
|
|
Packit Service |
f629e6 |
#undef JUMPTO
|
|
Packit Service |
f629e6 |
}
|