aboutsummaryrefslogtreecommitdiffstats
path: root/eval.c
diff options
context:
space:
mode:
Diffstat (limited to 'eval.c')
-rw-r--r--eval.c414
1 files changed, 239 insertions, 175 deletions
diff --git a/eval.c b/eval.c
index df9570e3..e5e07385 100644
--- a/eval.c
+++ b/eval.c
@@ -262,9 +262,12 @@ static const char *const nodetypes[] = {
"Node_var_new",
"Node_param_list",
"Node_func",
+ "Node_ext_func",
"Node_hashnode",
- "Node_ahash",
"Node_array_ref",
+ "Node_array_tree",
+ "Node_array_leaf",
+ "Node_dump_array",
"Node_arrayfor",
"Node_frame",
"Node_instruction",
@@ -349,6 +352,7 @@ static struct optypetab {
{ "Op_K_nextfile", "nextfile" },
{ "Op_builtin", NULL },
{ "Op_sub_builtin", NULL },
+ { "Op_ext_builtin", NULL },
{ "Op_in_array", " in " },
{ "Op_func_call", NULL },
{ "Op_indirect_func_call", NULL },
@@ -376,7 +380,6 @@ static struct optypetab {
{ "Op_field_assign", NULL },
{ "Op_after_beginfile", NULL },
{ "Op_after_endfile", NULL },
- { "Op_ext_func", NULL },
{ "Op_func", NULL },
{ "Op_exec_count", NULL },
{ "Op_breakpoint", NULL },
@@ -446,20 +449,19 @@ flags2str(int flagval)
{
static const struct flagtab values[] = {
{ MALLOC, "MALLOC" },
- { PERM, "PERM" },
{ STRING, "STRING" },
{ STRCUR, "STRCUR" },
{ NUMCUR, "NUMCUR" },
{ NUMBER, "NUMBER" },
{ MAYBE_NUM, "MAYBE_NUM" },
- { ARRAYMAXED, "ARRAYMAXED" },
- { FUNC, "FUNC" },
{ FIELD, "FIELD" },
{ INTLSTR, "INTLSTR" },
- { NUMIND, "NUMIND" },
-#ifdef WSTRCUR
+ { NUMINT, "NUMINT" },
+ { INTIND, "INTIND" },
{ WSTRCUR, "WSTRCUR" },
-#endif
+ { ARRAYMAXED, "ARRAYMAXED" },
+ { HALFHAT, "HALFHAT" },
+ { XARRAY, "XARRAY" },
{ 0, NULL },
};
@@ -484,7 +486,7 @@ genflags2str(int flagval, const struct flagtab *tab)
* the '|' character.
*/
space_needed = (strlen(tab[i].name) + (sp != buffer));
- if (space_left < space_needed)
+ if (space_left <= space_needed)
fatal(_("buffer overflow in genflags2str"));
if (sp != buffer) {
@@ -498,6 +500,7 @@ genflags2str(int flagval, const struct flagtab *tab)
}
}
+ *sp = '\0';
return buffer;
}
@@ -582,7 +585,6 @@ posix_compare(NODE *s1, NODE *s2)
return ret;
}
-
/* cmp_nodes --- compare two nodes, returning negative, 0, positive */
int
@@ -599,6 +601,11 @@ cmp_nodes(NODE *t1, NODE *t2)
(void) force_number(t1);
if (t2->flags & MAYBE_NUM)
(void) force_number(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;
@@ -610,8 +617,8 @@ cmp_nodes(NODE *t1, NODE *t2)
return ret;
}
- (void) force_string(t1);
- (void) force_string(t2);
+ t1 = force_string(t1);
+ t2 = force_string(t2);
len1 = t1->stlen;
len2 = t2->stlen;
ldiff = len1 - len2;
@@ -637,7 +644,9 @@ cmp_nodes(NODE *t1, NODE *t2)
ret = casetable[*cp1] - casetable[*cp2];
} else
ret = memcmp(t1->stptr, t2->stptr, l);
- return (ret == 0 ? ldiff : ret);
+
+ ret = ret == 0 ? ldiff : ret;
+ return ret;
}
@@ -728,9 +737,10 @@ set_IGNORECASE()
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 = (force_string(IGNORECASE_node->var_value)->stlen > 0);
- else
+ 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);
@@ -823,7 +833,8 @@ set_BINMODE()
void
set_OFS()
{
- OFS = force_string(OFS_node->var_value)->stptr;
+ OFS_node->var_value = force_string(OFS_node->var_value);
+ OFS = OFS_node->var_value->stptr;
OFSlen = OFS_node->var_value->stlen;
OFS[OFSlen] = '\0';
}
@@ -833,7 +844,8 @@ set_OFS()
void
set_ORS()
{
- ORS = force_string(ORS_node->var_value)->stptr;
+ ORS_node->var_value = force_string(ORS_node->var_value);
+ ORS = ORS_node->var_value->stptr;
ORSlen = ORS_node->var_value->stlen;
ORS[ORSlen] = '\0';
}
@@ -849,6 +861,7 @@ fmt_ok(NODE *n)
{
NODE *tmp = force_string(n);
const char *p = tmp->stptr;
+
#if ! defined(PRINTF_HAS_F_FORMAT) || PRINTF_HAS_F_FORMAT != 1
static const char float_formats[] = "efgEG";
#else
@@ -890,7 +903,7 @@ fmt_index(NODE *n)
if (fmt_list == NULL)
emalloc(fmt_list, NODE **, fmt_num*sizeof(*fmt_list), "fmt_index");
- (void) force_string(n);
+ n = force_string(n);
while (ix < fmt_hiwater) {
if (cmp_nodes(fmt_list[ix], n) == 0)
return ix;
@@ -942,41 +955,45 @@ set_LINT()
if ((LINT_node->var_value->flags & MAYBE_NUM) == 0) {
const char *lintval;
size_t lintlen;
+ NODE *tmp;
- do_lint = (force_string(LINT_node->var_value)->stlen > 0);
- lintval = LINT_node->var_value->stptr;
- lintlen = LINT_node->var_value->stlen;
- if (do_lint) {
- do_lint = LINT_ALL;
+ tmp = LINT_node->var_value = force_string(LINT_node->var_value);
+ lintval = tmp->stptr;
+ lintlen = tmp->stlen;
+ if (lintlen > 0) {
+ do_flags |= DO_LINT_ALL;
if (lintlen == 5 && strncmp(lintval, "fatal", 5) == 0)
lintfunc = r_fatal;
- else if (lintlen == 7 && strncmp(lintval, "invalid", 7) == 0)
- do_lint = LINT_INVALID;
- else
+ else if (lintlen == 7 && strncmp(lintval, "invalid", 7) == 0) {
+ do_flags &= ~ DO_LINT_ALL;
+ do_flags |= DO_LINT_INVALID;
+ } else
lintfunc = warning;
- } else
+ } else {
+ do_flags &= ~(DO_LINT_ALL|DO_LINT_INVALID);
lintfunc = warning;
+ }
} else {
if (force_number(LINT_node->var_value) != 0.0)
- do_lint = LINT_ALL;
+ do_flags |= DO_LINT_ALL;
else
- do_lint = FALSE;
+ 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)
- do_lint = LINT_ALL;
+ do_flags |= DO_LINT_ALL;
else
- do_lint = FALSE;
+ do_flags &= ~(DO_LINT_ALL|DO_LINT_INVALID);
lintfunc = warning;
} else
- do_lint = FALSE; /* shouldn't happen */
+ do_flags &= ~(DO_LINT_ALL|DO_LINT_INVALID); /* shouldn't happen */
if (! do_lint)
lintfunc = warning;
/* explicitly use warning() here, in case lintfunc == r_fatal */
- if (old_lint != do_lint && old_lint && do_lint == FALSE)
+ if (old_lint != do_lint && old_lint && ! do_lint)
warning(_("turning off `--lint' due to assignment to `LINT'"));
#endif /* ! NO_LINT */
}
@@ -987,9 +1004,11 @@ void
set_TEXTDOMAIN()
{
int len;
+ NODE *tmp;
- TEXTDOMAIN = force_string(TEXTDOMAIN_node->var_value)->stptr;
- len = TEXTDOMAIN_node->var_value->stlen;
+ tmp = TEXTDOMAIN_node->var_value = force_string(TEXTDOMAIN_node->var_value);
+ TEXTDOMAIN = tmp->stptr;
+ len = tmp->stlen;
TEXTDOMAIN[len] = '\0';
/*
* Note: don't call textdomain(); this value is for
@@ -1057,7 +1076,6 @@ update_FNR()
}
-
NODE *frame_ptr; /* current frame */
STACK_ITEM *stack_ptr = NULL;
STACK_ITEM *stack_bottom;
@@ -1079,17 +1097,10 @@ STACK_ITEM *
grow_stack()
{
if (stack_ptr == NULL) {
- char *val;
-
- if ((val = getenv("GAWK_STACKSIZE")) != NULL) {
- if (isdigit((unsigned char) *val)) {
- unsigned long n = 0;
- for (; *val && isdigit((unsigned char) *val); val++)
- n = (n * 10) + *val - '0';
- if (n >= 1)
- STACK_SIZE = n;
- }
- }
+ long newval;
+
+ if ((newval = getenv_long("GAWK_STACKSIZE")) > 0)
+ STACK_SIZE = newval;
emalloc(stack_bottom, STACK_ITEM *, STACK_SIZE * sizeof(STACK_ITEM), "grow_stack");
stack_ptr = stack_bottom - 1;
@@ -1123,9 +1134,6 @@ r_get_lhs(NODE *n, int reference)
int isparam = FALSE;
if (n->type == Node_param_list) {
- if ((n->flags & FUNC) != 0)
- fatal(_("can't use function name `%s' as variable or array"),
- n->vname);
isparam = TRUE;
n = GET_PARAM(n->param_cnt);
}
@@ -1139,11 +1147,11 @@ r_get_lhs(NODE *n, int reference)
fatal(_("attempt to use array `%s' in a scalar context"),
array_vname(n));
n->orig_array->type = Node_var;
- n->orig_array->var_value = Nnull_string;
+ n->orig_array->var_value = dupnode(Nnull_string);
/* fall through */
case Node_var_new:
n->type = Node_var;
- n->var_value = Nnull_string;
+ n->var_value = dupnode(Nnull_string);
break;
case Node_var:
@@ -1158,7 +1166,7 @@ r_get_lhs(NODE *n, int reference)
_("reference to uninitialized argument `%s'") :
_("reference to uninitialized variable `%s'")),
n->vname);
- return &n->var_value;
+ return & n->var_value;
}
@@ -1239,15 +1247,13 @@ static INSTRUCTION *
setup_frame(INSTRUCTION *pc)
{
NODE *r = NULL;
- NODE *m;
- NODE *f;
+ NODE *m, *f, *fp;
NODE **sp = NULL;
- char **varnames;
int pcount, arg_count, i;
f = pc->func_body;
- pcount = f->lnode->param_cnt;
- varnames = f->parmlist;
+ pcount = f->param_cnt;
+ fp = f->fparms;
arg_count = (pc + 1)->expr_count;
/* check for extra args */
@@ -1274,7 +1280,7 @@ setup_frame(INSTRUCTION *pc)
if (i >= arg_count) {
/* local variable */
r->type = Node_var_new;
- r->vname = varnames[i];
+ r->vname = fp[i].param;
continue;
}
@@ -1301,8 +1307,9 @@ setup_frame(INSTRUCTION *pc)
* scalar during evaluation of expression for a
* subsequent param.
*/
+ /* fall through */
r->type = Node_var;
- r->var_value = Nnull_string;
+ r->var_value = dupnode(Nnull_string);
break;
case Node_val:
@@ -1313,7 +1320,7 @@ setup_frame(INSTRUCTION *pc)
default:
cant_happen();
}
- r->vname = varnames[i];
+ r->vname = fp[i].param;
}
stack_adj(-arg_count); /* adjust stack pointer */
@@ -1354,7 +1361,7 @@ restore_frame(NODE *fp)
INSTRUCTION *ri;
func = frame_ptr->func_node;
- n = func->lnode->param_cnt;
+ n = func->param_cnt;
sp = frame_ptr->stack;
for (; n > 0; n--) {
@@ -1388,11 +1395,14 @@ restore_frame(NODE *fp)
static inline void
free_arrayfor(NODE *r)
{
- if (r->var_array != NULL) {
- size_t num_elems = r->table_size;
- NODE **list = r->var_array;
- while (num_elems > 0)
- unref(list[--num_elems]);
+ if (r->for_list != NULL) {
+ NODE *n;
+ size_t num_elems = r->for_list_size;
+ NODE **list = r->for_list;
+ while (num_elems > 0) {
+ n = list[--num_elems];
+ unref(n);
+ }
efree(list);
}
freenode(r);
@@ -1661,12 +1671,10 @@ pop_exec_state(int *rule, char **src, long *sz)
/* N.B.:
* 1) reference counting done for both number and string values.
- * 2) TEMP flag no longer needed (consequence of the above; valref = 0
- * is the replacement).
- * 3) Stack operations:
+ * 2) Stack operations:
* Use REPLACE[_XX] if last stack operation was TOP[_XX],
* PUSH[_XX] if last operation was POP[_XX] instead.
- * 4) UPREF and DREF -- see awk.h
+ * 3) UPREF and DREF -- see awk.h
*/
@@ -1681,11 +1689,8 @@ r_interpret(INSTRUCTION *code)
NODE *f; /* function definition */
NODE **lhs;
AWKNUM x, x1, x2;
- int di, pre = FALSE;
+ int di;
Regexp *rp;
-#if defined(GAWKDEBUG) || defined(ARRAYDEBUG)
- int last_was_stopme = FALSE; /* builtin stopme() called ? */
-#endif
int stdio_problem = FALSE;
@@ -1695,7 +1700,7 @@ r_interpret(INSTRUCTION *code)
erealloc(args_array, NODE **, (max_args + 2)*sizeof(NODE *), "r_interpret");
/* array subscript */
-#define mk_sub(n) (n == 1 ? POP_STRING() : concat_exp(n, TRUE))
+#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)
@@ -1728,7 +1733,6 @@ top:
currule = pc->in_rule; /* for sole use in Op_K_next, Op_K_nextfile, Op_K_getline* */
/* fall through */
case Op_func:
- case Op_ext_func:
source = pc->source_file;
break;
@@ -1762,7 +1766,18 @@ top:
case Op_push_i:
m = pc->memory;
- PUSH((m->flags & INTLSTR) != 0 ? format_val(CONVFMT, CONVFMTidx, m): m);
+ if (! do_traditional && (m->flags & INTLSTR) != 0) {
+ char *orig, *trans, save;
+
+ save = m->stptr[m->stlen];
+ m->stptr[m->stlen] = '\0';
+ orig = m->stptr;
+ trans = dgettext(TEXTDOMAIN, orig);
+ m->stptr[m->stlen] = save;
+ m = make_string(trans, strlen(trans));
+ } else
+ UPREF(m);
+ PUSH(m);
break;
case Op_push:
@@ -1773,9 +1788,6 @@ top:
save_symbol = m = pc->memory;
if (m->type == Node_param_list) {
- if ((m->flags & FUNC) != 0)
- fatal(_("can't use function name `%s' as variable or array"),
- m->vname);
isparam = TRUE;
save_symbol = m = GET_PARAM(m->param_cnt);
if (m->type == Node_array_ref)
@@ -1796,13 +1808,14 @@ top:
case Node_var_new:
m->type = Node_var;
- m->var_value = Nnull_string;
+ m->var_value = dupnode(Nnull_string);
if (do_lint)
lintwarn(isparam ?
_("reference to uninitialized argument `%s'") :
_("reference to uninitialized variable `%s'"),
save_symbol->vname);
- PUSH(Nnull_string);
+ m = dupnode(Nnull_string);
+ PUSH(m);
break;
case Node_var_array:
@@ -1843,7 +1856,16 @@ top:
case Op_subscript:
t2 = mk_sub(pc->sub_count);
t1 = POP_ARRAY();
- r = *assoc_lookup(t1, t2, TRUE);
+
+ if (do_lint && in_array(t1, t2) == NULL) {
+ t2 = force_string(t2);
+ lintwarn(_("reference to uninitialized element `%s[\"%.*s\"]'"),
+ array_vname(t1), (int) t2->stlen, t2->stptr);
+ if (t2->stlen == 0)
+ lintwarn(_("subscript of array `%s' is null string"), array_vname(t1));
+ }
+
+ r = *assoc_lookup(t1, t2);
DEREF(t2);
if (r->type == Node_val)
UPREF(r);
@@ -1855,15 +1877,17 @@ top:
t1 = POP_ARRAY();
r = in_array(t1, t2);
if (r == NULL) {
- getnode(r);
- r->type = Node_var_array;
- r->var_array = NULL;
- r->vname = estrdup(t2->stptr, t2->stlen); /* the subscript in parent array */
+ r = make_array();
r->parent_array = t1;
- *assoc_lookup(t1, t2, FALSE) = r;
- } else if (r->type != Node_var_array)
+ *assoc_lookup(t1, t2) = r;
+ t2 = force_string(t2);
+ r->vname = estrdup(t2->stptr, t2->stlen); /* the subscript in parent array */
+ } else if (r->type != Node_var_array) {
+ t2 = force_string(t2);
fatal(_("attempt to use scalar `%s[\"%.*s\"]' as an array"),
array_vname(t1), (int) t2->stlen, t2->stptr);
+ }
+
DEREF(t2);
PUSH(r);
break;
@@ -1871,10 +1895,22 @@ top:
case Op_subscript_lhs:
t2 = mk_sub(pc->sub_count);
t1 = POP_ARRAY();
- lhs = assoc_lookup(t1, t2, pc->do_reference);
- if ((*lhs)->type == Node_var_array)
+ if (do_lint && in_array(t1, t2) == NULL) {
+ t2 = force_string(t2);
+ if (pc->do_reference)
+ lintwarn(_("reference to uninitialized element `%s[\"%.*s\"]'"),
+ array_vname(t1), (int) t2->stlen, t2->stptr);
+ if (t2->stlen == 0)
+ lintwarn(_("subscript of array `%s' is null string"), array_vname(t1));
+ }
+
+ lhs = assoc_lookup(t1, t2);
+ if ((*lhs)->type == Node_var_array) {
+ t2 = force_string(t2);
fatal(_("attempt to use array `%s[\"%.*s\"]' in a scalar context"),
array_vname(t1), (int) t2->stlen, t2->stptr);
+ }
+
DEREF(t2);
PUSH_ADDRESS(lhs);
break;
@@ -1884,10 +1920,6 @@ top:
lhs = r_get_field(t1, (Func_ptr *) 0, TRUE);
decr_sp();
DEREF(t1);
- /* This used to look like this:
- PUSH(dupnode(*lhs));
- but was changed to bypass an apparent bug in the z/OS C compiler.
- Please do not remerge. */
r = dupnode(*lhs); /* can't use UPREF here */
PUSH(r);
break;
@@ -1960,39 +1992,39 @@ top:
break;
case Op_not:
- t1 = TOP_SCALAR();
+ t1 = TOP_SCALAR();
r = make_number((AWKNUM) ! eval_condition(t1));
DEREF(t1);
REPLACE(r);
break;
case Op_equal:
- r = make_number((AWKNUM) (cmp_scalar() == 0));
+ r = make_number((AWKNUM) cmp_scalar() == 0);
REPLACE(r);
break;
case Op_notequal:
- r = make_number((AWKNUM) (cmp_scalar() != 0));
+ r = make_number((AWKNUM) cmp_scalar() != 0);
REPLACE(r);
break;
case Op_less:
- r = make_number((AWKNUM) (cmp_scalar() < 0));
+ r = make_number((AWKNUM) cmp_scalar() < 0);
REPLACE(r);
break;
case Op_greater:
- r = make_number((AWKNUM) (cmp_scalar() > 0));
+ r = make_number((AWKNUM) cmp_scalar() > 0);
REPLACE(r);
break;
case Op_leq:
- r = make_number((AWKNUM) (cmp_scalar() <= 0));
+ r = make_number((AWKNUM) cmp_scalar() <= 0);
REPLACE(r);
break;
case Op_geq:
- r = make_number((AWKNUM) (cmp_scalar() >= 0));
+ r = make_number((AWKNUM) cmp_scalar() >= 0);
REPLACE(r);
break;
@@ -2083,27 +2115,30 @@ mod:
break;
case Op_preincrement:
- pre = TRUE;
- case Op_postincrement:
- x2 = 1.0;
-post:
+ case Op_predecrement:
+ x2 = pc->opcode == Op_preincrement ? 1.0 : -1.0;
lhs = TOP_ADDRESS();
x1 = force_number(*lhs);
+ x = x1 + x2;
+ r = make_number(x);
unref(*lhs);
- r = *lhs = make_number(x1 + x2);
- if (pre)
- UPREF(r);
- else
- r = make_number(x1);
+ *lhs = r;
+ UPREF(r);
REPLACE(r);
- pre = FALSE;
- break;
+ break;
- case Op_predecrement:
- pre = TRUE;
+ case Op_postincrement:
case Op_postdecrement:
- x2 = -1.0;
- goto post;
+ x2 = pc->opcode == Op_postincrement ? 1.0 : -1.0;
+ lhs = TOP_ADDRESS();
+ x1 = force_number(*lhs);
+ x = x1 + x2;
+ t1 = make_number(x);
+ r = make_number(x1);
+ unref(*lhs);
+ *lhs = t1;
+ REPLACE(r);
+ break;
case Op_unary_minus:
TOP_NUMBER(x1);
@@ -2117,10 +2152,12 @@ post:
*/
t1 = get_array(pc->memory, TRUE); /* array */
t2 = mk_sub(pc->expr_count); /* subscript */
- lhs = assoc_lookup(t1, t2, FALSE);
- if ((*lhs)->type == Node_var_array)
+ lhs = assoc_lookup(t1, t2);
+ if ((*lhs)->type == Node_var_array) {
+ t2 = force_string(t2);
fatal(_("attempt to use array `%s[\"%.*s\"]' in a scalar context"),
array_vname(t1), (int) t2->stlen, t2->stptr);
+ }
DEREF(t2);
unref(*lhs);
*lhs = POP_SCALAR();
@@ -2133,7 +2170,13 @@ post:
lhs = get_lhs(pc->memory, FALSE);
unref(*lhs);
- *lhs = POP_SCALAR();
+ r = pc->initval;
+ if (r == NULL)
+ *lhs = POP_SCALAR();
+ else {
+ UPREF(r);
+ *lhs = r;
+ }
break;
case Op_store_field:
@@ -2162,12 +2205,19 @@ post:
free_wstr(*lhs);
- if (t1 != t2 && t1->valref == 1 && (t1->flags & PERM) == 0) {
+ if (t1 != *lhs) {
+ unref(*lhs);
+ *lhs = dupnode(t1);
+ }
+
+ if (t1 != t2 && t1->valref == 1) {
size_t nlen = t1->stlen + t2->stlen;
+
erealloc(t1->stptr, char *, nlen + 2, "r_interpret");
memcpy(t1->stptr + t1->stlen, t2->stptr, t2->stlen);
t1->stlen = nlen;
t1->stptr[nlen] = '\0';
+ t1->flags &= ~(NUMCUR|NUMBER|NUMINT);
} else {
size_t nlen = t1->stlen + t2->stlen;
char *p;
@@ -2176,9 +2226,8 @@ post:
memcpy(p, t1->stptr, t1->stlen);
memcpy(p + t1->stlen, t2->stptr, t2->stlen);
unref(*lhs);
- t1 = *lhs = make_str_node(p, nlen, ALREADY_MALLOCED);
+ t1 = *lhs = make_str_node(p, nlen);
}
- t1->flags &= ~(NUMCUR|NUMBER);
DEREF(t2);
break;
@@ -2239,9 +2288,10 @@ post:
case Op_K_case:
if ((pc + 1)->match_exp) {
/* match a constant regex against switch expression instead of $0. */
+
m = POP(); /* regex */
t2 = TOP_SCALAR(); /* switch expression */
- (void) force_string(t2);
+ t2 = force_string(t2);
rp = re_update(m);
di = (research(rp, t2->stptr, 0, t2->stlen,
avoid_dfa(m, t2->stptr, t2->stlen)) >= 0);
@@ -2252,8 +2302,10 @@ post:
DEREF(t1);
}
- if (di) { /* match found */
- decr_sp();
+ if (di) {
+ /* match found */
+
+ t2 = POP_SCALAR();
DEREF(t2);
JUMPTO(pc->target_jmp);
}
@@ -2280,6 +2332,11 @@ post:
break;
case Op_arrayfor_init:
+#define idx_list sub.nodep.r.av
+#define num_idx sub.nodep.reflags
+#define cur_idx sub.nodep.l.ll
+#define for_array sub.nodep.rn
+
{
NODE **list = NULL;
NODE *array, *sort_str;
@@ -2291,7 +2348,7 @@ post:
array = POP_ARRAY();
/* sanity: check if empty */
- if (array->var_array == NULL || array->table_size == 0)
+ if (array_empty(array))
goto arrayfor;
num_elems = array->table_size;
@@ -2315,18 +2372,13 @@ post:
list = assoc_list(array, how_to_sort, SORTED_IN);
- /*
- * Actual array for use in lint warning
- * in Op_arrayfor_incr
- */
- list[num_elems] = array;
-
arrayfor:
getnode(r);
r->type = Node_arrayfor;
- r->var_array = list;
- r->table_size = num_elems; /* # of elements in list */
- r->array_size = -1; /* current index */
+ r->for_list = list;
+ r->for_list_size = num_elems; /* # of elements in list */
+ r->cur_idx = -1; /* current index */
+ r->for_array = array; /* array */
PUSH(r);
if (num_elems == 0)
@@ -2336,20 +2388,20 @@ arrayfor:
case Op_arrayfor_incr:
r = TOP(); /* Node_arrayfor */
- if (++r->array_size == r->table_size) {
+ if (++r->cur_idx == r->for_list_size) {
NODE *array;
- array = r->var_array[r->table_size]; /* actual array */
- if (do_lint && array->table_size != r->table_size)
+ array = r->for_array; /* actual array */
+ if (do_lint && array->table_size != r->for_list_size)
lintwarn(_("for loop: array `%s' changed size from %ld to %ld during loop execution"),
- array_vname(array), (long) r->table_size, (long) array->table_size);
+ array_vname(array), (long) r->for_list_size, (long) array->table_size);
JUMPTO(pc->target_jmp); /* Op_arrayfor_final */
}
- t1 = r->var_array[r->array_size];
+ t1 = r->for_list[r->cur_idx];
lhs = get_lhs(pc->array_var, FALSE);
unref(*lhs);
- *lhs = make_string(t1->ahname_str, t1->ahname_len);
- break;
+ *lhs = dupnode(t1);
+ break;
case Op_arrayfor_final:
r = POP();
@@ -2359,12 +2411,23 @@ arrayfor:
case Op_builtin:
r = pc->builtin(pc->expr_count);
-#if defined(GAWKDEBUG) || defined(ARRAYDEBUG)
- if (! r)
- last_was_stopme = TRUE;
- else
-#endif
- PUSH(r);
+ PUSH(r);
+ break;
+
+ case Op_ext_builtin:
+ {
+ int arg_count = pc->expr_count;
+
+ PUSH_CODE(pc);
+ r = pc->builtin(arg_count);
+ (void) POP_CODE();
+ while (arg_count-- > 0) {
+ t1 = POP();
+ if (t1->type == Node_val)
+ DEREF(t1);
+ }
+ PUSH(r);
+ }
break;
case Op_sub_builtin: /* sub, gsub and gensub */
@@ -2444,18 +2507,20 @@ match_re:
arg_count = (pc + 1)->expr_count;
t1 = PEEK(arg_count); /* indirect var */
assert(t1->type == Node_val); /* @a[1](p) not allowed in grammar */
- (void) force_string(t1);
+ t1 = force_string(t1);
if (t1->stlen > 0) {
/* retrieve function definition node */
f = pc->func_body;
- if (f != NULL && STREQ(f->vname, t1->stptr))
+ if (f != NULL && STREQ(f->vname, t1->stptr)) {
/* indirect var hasn't been reassigned */
goto func_call;
+ }
f = lookup(t1->stptr);
}
if (f == NULL || f->type != Node_func)
- fatal(_("function called indirectly through `%s' does not exist"), pc->func_name);
+ fatal(_("function called indirectly through `%s' does not exist"),
+ pc->func_name);
pc->func_body = f; /* save for next call */
goto func_call;
@@ -2466,26 +2531,32 @@ match_re:
f = pc->func_body;
if (f == NULL) {
f = lookup(pc->func_name);
- if (f == NULL || f->type != Node_func)
+ if (f == NULL || (f->type != Node_func && f->type != Node_ext_func))
fatal(_("function `%s' not defined"), pc->func_name);
pc->func_body = f; /* save for next call */
}
- /* save current frame along with source */
+ if (f->type == Node_ext_func) {
+ INSTRUCTION *bc;
+ char *fname = pc->func_name;
+ int arg_count = (pc + 1)->expr_count;
+
+ bc = f->code_ptr;
+ assert(bc->opcode == Op_symbol);
+ pc->opcode = Op_ext_builtin; /* self modifying code */
+ pc->builtin = bc->builtin;
+ pc->expr_count = arg_count; /* actual argument count */
+ (pc + 1)->func_name = fname; /* name of the builtin */
+ (pc + 1)->expr_count = bc->expr_count; /* defined max # of arguments */
+ ni = pc;
+ JUMPTO(ni);
+ }
func_call:
ni = setup_frame(pc);
- if (ni->opcode == Op_ext_func) {
- /* dynamically set source and line numbers for an extension builtin. */
- ni->source_file = source;
- ni->source_line = sourceline;
- ni->nexti->source_line = sourceline; /* Op_builtin */
- ni->nexti->nexti->source_line = sourceline; /* Op_K_return */
- }
-
/* run the function instructions */
- JUMPTO(ni); /* Op_func or Op_ext_func */
+ JUMPTO(ni); /* Op_func */
case Op_K_return:
m = POP_SCALAR(); /* return value */
@@ -2697,15 +2768,8 @@ func_call:
JUMPTO(pc->target_jmp); /* Op_get_record, read next record */
case Op_pop:
-#if defined(GAWKDEBUG) || defined(ARRAYDEBUG)
- if (last_was_stopme)
- last_was_stopme = FALSE;
- else
-#endif
- {
- r = POP_SCALAR();
- DEREF(r);
- }
+ r = POP_SCALAR();
+ DEREF(r);
break;
case Op_line_range:
@@ -2734,7 +2798,7 @@ func_call:
}
result = ip->triggered || di;
- ip->triggered ^= di; /* update triggered flag */
+ ip->triggered ^= di; /* update triggered flag */
r = make_number((AWKNUM) result); /* final value of condition pair */
REPLACE(r);
JUMPTO(pc->target_jmp);