diff options
author | Arnold D. Robbins <arnold@skeeve.com> | 2010-07-16 12:27:41 +0300 |
---|---|---|
committer | Arnold D. Robbins <arnold@skeeve.com> | 2010-07-16 12:27:41 +0300 |
commit | 61bb57af53ebe916d2db6e3585d4fc7ac1d99b92 (patch) | |
tree | 2bfc4e5b127618d286f57a87d416702131b1b01d /eval.c | |
parent | 0a9ae0c89481db540e1b817a63cc6c793a62c90d (diff) | |
download | egawk-61bb57af53ebe916d2db6e3585d4fc7ac1d99b92.tar.gz egawk-61bb57af53ebe916d2db6e3585d4fc7ac1d99b92.tar.bz2 egawk-61bb57af53ebe916d2db6e3585d4fc7ac1d99b92.zip |
Move to gawk-2.15.3.
Diffstat (limited to 'eval.c')
-rw-r--r-- | eval.c | 65 |
1 files changed, 42 insertions, 23 deletions
@@ -386,11 +386,11 @@ 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; } if (tree->type == Node_param_list) { @@ -489,32 +489,51 @@ 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"); 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; @@ -696,7 +715,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; @@ -985,7 +1004,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; { @@ -998,7 +1017,7 @@ Func_ptr *assign; 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; |