summaryrefslogtreecommitdiff
path: root/gnu/usr.bin/awk/eval.c
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/usr.bin/awk/eval.c')
-rw-r--r--gnu/usr.bin/awk/eval.c113
1 files changed, 74 insertions, 39 deletions
diff --git a/gnu/usr.bin/awk/eval.c b/gnu/usr.bin/awk/eval.c
index f640f3733ada..18f67fd2b592 100644
--- a/gnu/usr.bin/awk/eval.c
+++ b/gnu/usr.bin/awk/eval.c
@@ -3,7 +3,7 @@
*/
/*
- * Copyright (C) 1986, 1988, 1989, 1991, 1992 the Free Software Foundation, Inc.
+ * Copyright (C) 1986, 1988, 1989, 1991, 1992, 1993 the Free Software Foundation, Inc.
*
* This file is part of GAWK, the GNU implementation of the
* AWK Progamming Language.
@@ -137,6 +137,10 @@ register NODE *volatile tree;
NODE *volatile stable_tree;
int volatile traverse = 1; /* True => loop thru tree (Node_rule_list) */
+ /* avoid false source indications */
+ source = NULL;
+ sourceline = 0;
+
if (tree == NULL)
return 1;
sourceline = tree->source_line;
@@ -318,7 +322,10 @@ register NODE *volatile tree;
break;
case Node_K_delete:
- do_delete(tree->lnode, tree->rnode);
+ if (tree->rnode != NULL)
+ do_delete(tree->lnode, tree->rnode);
+ else
+ assoc_clear(tree->lnode);
break;
case Node_K_next:
@@ -378,7 +385,7 @@ register NODE *tree;
register int di;
AWKNUM x, x1, x2;
long lx;
-#ifdef CRAY
+#ifdef _CRAY
long lx2;
#endif
@@ -386,21 +393,25 @@ register NODE *tree;
if (tree == NULL)
return Nnull_string;
if (tree->type == Node_val) {
- if (tree->stref <= 0) cant_happen();
+ if ((char)tree->stref <= 0) cant_happen();
return tree;
}
if (tree->type == Node_var) {
- if (tree->var_value->stref <= 0) cant_happen();
+ if ((char)tree->var_value->stref <= 0) cant_happen();
return tree->var_value;
}
+#endif
+
if (tree->type == Node_param_list) {
- if (stack_ptr[tree->param_cnt] == NULL)
+ tree = stack_ptr[tree->param_cnt];
+ if (tree == NULL)
return Nnull_string;
- else
- return stack_ptr[tree->param_cnt]->var_value;
}
-#endif
+
switch (tree->type) {
+ case Node_var:
+ return tree->var_value;
+
case Node_and:
return tmp_number((AWKNUM) (eval_condition(tree->lnode)
&& eval_condition(tree->rnode)));
@@ -443,7 +454,7 @@ register NODE *tree;
return *lhs;
case Node_var_array:
- fatal("attempt to use an array in a scalar context");
+ fatal("attempt to use array `%s' in a scalar context", tree->vname);
case Node_unary_minus:
t1 = tree_eval(tree->subnode);
@@ -489,32 +500,52 @@ register NODE *tree;
case Node_concat:
{
#define STACKSIZE 10
- NODE *stack[STACKSIZE];
- register NODE **sp;
- register int len;
+ NODE *treelist[STACKSIZE+1];
+ NODE *strlist[STACKSIZE+1];
+ register NODE **treep;
+ register NODE **strp;
+ register size_t len;
char *str;
register char *dest;
- sp = stack;
- len = 0;
+ /*
+ * This is an efficiency hack for multiple adjacent string
+ * concatenations, to avoid recursion and string copies.
+ *
+ * Node_concat trees grow downward to the left, so
+ * descend to lowest (first) node, accumulating nodes
+ * to evaluate to strings as we go.
+ */
+ treep = treelist;
while (tree->type == Node_concat) {
- *sp = force_string(tree_eval(tree->lnode));
- tree = tree->rnode;
- len += (*sp)->stlen;
- if (++sp == &stack[STACKSIZE-2]) /* one more and NULL */
+ *treep++ = tree->rnode;
+ tree = tree->lnode;
+ if (treep == &treelist[STACKSIZE])
break;
}
- *sp = force_string(tree_eval(tree));
- len += (*sp)->stlen;
- *++sp = NULL;
+ *treep = tree;
+ /*
+ * Now, evaluate to strings in LIFO order, accumulating
+ * the string length, so we can do a single malloc at the
+ * end.
+ */
+ strp = strlist;
+ len = 0;
+ while (treep >= treelist) {
+ *strp = force_string(tree_eval(*treep--));
+ len += (*strp)->stlen;
+ strp++;
+ }
+ *strp = NULL;
emalloc(str, char *, len+2, "tree_eval");
+ str[len] = str[len+1] = '\0'; /* for good measure */
dest = str;
- sp = stack;
- while (*sp) {
- memcpy(dest, (*sp)->stptr, (*sp)->stlen);
- dest += (*sp)->stlen;
- free_temp(*sp);
- sp++;
+ strp = strlist;
+ while (*strp) {
+ memcpy(dest, (*strp)->stptr, (*strp)->stlen);
+ dest += (*strp)->stlen;
+ free_temp(*strp);
+ strp++;
}
r = make_str_node(str, len, ALREADY_MALLOCED);
r->flags |= TEMP;
@@ -629,7 +660,7 @@ register NODE *tree;
return tmp_number(x1 - x2);
case Node_var_array:
- fatal("attempt to use an array in a scalar context");
+ fatal("attempt to use array `%s' in a scalar context", tree->vname);
default:
fatal("illegal type (%d) in tree_eval", tree->type);
@@ -696,7 +727,7 @@ cmp_nodes(t1, t2)
register NODE *t1, *t2;
{
register int ret;
- register int len1, len2;
+ register size_t len1, len2;
if (t1 == t2)
return 0;
@@ -944,22 +975,26 @@ NODE *arg_list; /* Node_expression_list of calling args. */
if (arg->type == Node_param_list)
arg = stack_ptr[arg->param_cnt];
n = *sp++;
- if (arg->type == Node_var && n->type == Node_var_array) {
+ if ((arg->type == Node_var || arg->type == Node_var_array)
+ && n->type == Node_var_array) {
/* should we free arg->var_value ? */
arg->var_array = n->var_array;
arg->type = Node_var_array;
+ arg->array_size = n->array_size;
+ arg->table_size = n->table_size;
+ arg->flags = n->flags;
}
- unref(n->lnode);
+ /* n->lnode overlays the array size, don't unref it if array */
+ if (n->type != Node_var_array)
+ unref(n->lnode);
freenode(n);
count--;
}
while (count-- > 0) {
n = *sp++;
/* if n is an (local) array, all the elements should be freed */
- if (n->type == Node_var_array) {
+ if (n->type == Node_var_array)
assoc_clear(n);
- free(n->var_array);
- }
unref(n->lnode);
freenode(n);
}
@@ -985,7 +1020,7 @@ NODE *arg_list; /* Node_expression_list of calling args. */
*/
NODE **
-get_lhs(ptr, assign)
+r_get_lhs(ptr, assign)
register NODE *ptr;
Func_ptr *assign;
{
@@ -994,11 +1029,11 @@ Func_ptr *assign;
switch (ptr->type) {
case Node_var_array:
- fatal("attempt to use an array in a scalar context");
+ fatal("attempt to use array `%s' in a scalar context", ptr->vname);
case Node_var:
aptr = &(ptr->var_value);
#ifdef DEBUG
- if (ptr->var_value->stref <= 0)
+ if ((char)ptr->var_value->stref <= 0)
cant_happen();
#endif
break;
@@ -1170,7 +1205,7 @@ set_ORS()
ORS[ORSlen] = '\0';
}
-static NODE **fmt_list = NULL;
+NODE **fmt_list = NULL;
static int fmt_ok P((NODE *n));
static int fmt_index P((NODE *n));