diff options
-rw-r--r-- | ChangeLog | 17 | ||||
-rw-r--r-- | array.c | 155 | ||||
-rw-r--r-- | awk.h | 1 | ||||
-rw-r--r-- | debug.c | 6 | ||||
-rw-r--r-- | eval.c | 27 | ||||
-rw-r--r-- | test/ChangeLog | 4 | ||||
-rw-r--r-- | test/arraysort.ok | 6 | ||||
-rw-r--r-- | test/sort1.ok | 16 |
8 files changed, 145 insertions, 87 deletions
@@ -1,3 +1,20 @@ +Sun May 8 20:38:03 2011 John Haque <j.eh@mchsi.com> + + * eval.c (r_interpret): In case Op_sub_array, store only the + subarray index as 'vname'. + * array.c (make_aname): Redone for dynamic computation of + a subarray actual 'vname'. + (array_vname): Use make_aname() for (sub)array name. + (asort_actual): Performance optimization for asort(a). + +Sun May 8 20:29:17 2011 Arnold D. Robbins <arnold@skeeve.com> + + * debug.c (print_array): Sort in order of string indices, per + request from John Haque. + * array.c (sort_up_value_number): Use string value to provide + ordering when numeric values are equal. Ensures that tests come + out OK on different systems. + Sun May 8 20:27:27 2011 Arnold D. Robbins <arnold@skeeve.com> * dfa.c: Sync with GNU grep. @@ -85,6 +85,41 @@ array_init() hash = gst_hash_string; } +/* make_aname --- construct a 'vname' for a (sub)array */ + +static char * +make_aname(const NODE *symbol) +{ + static char *aname = NULL; + static size_t alen; + static size_t max_alen; +#define SLEN 256 + + if (symbol->parent_array != NULL) { + size_t slen; + + (void) make_aname(symbol->parent_array); + slen = strlen(symbol->vname); /* subscript in parent array */ + if (alen + slen + 4 > max_alen) { /* sizeof("[\"\"]") = 4 */ + max_alen = alen + slen + 4 + SLEN; + erealloc(aname, char *, (max_alen + 1) * sizeof(char *), "make_aname"); + } + alen += sprintf(aname + alen, "[\"%s\"]", symbol->vname); + } else { + alen = strlen(symbol->vname); + if (aname == NULL) { + max_alen = alen + SLEN; + emalloc(aname, char *, (max_alen + 1) * sizeof(char *), "make_aname"); + } else if (alen > max_alen) { + max_alen = alen + SLEN; + erealloc(aname, char *, (max_alen + 1) * sizeof(char *), "make_aname"); + } + memcpy(aname, symbol->vname, alen + 1); + } + return aname; +#undef SLEN +} + /* * array_vname --- print the name of the array * @@ -103,18 +138,33 @@ array_vname(const NODE *symbol) int n; const NODE *save_symbol = symbol; const char *from = _("from %s"); + const char *aname; - if (symbol->type != Node_array_ref || symbol->orig_array->type != Node_var_array) - return symbol->vname; + if (symbol->type != Node_array_ref + || symbol->orig_array->type != Node_var_array + ) { + if (symbol->type != Node_var_array || symbol->parent_array == NULL) + return symbol->vname; + return make_aname(symbol); + } /* First, we have to compute the length of the string: */ - len = strlen(symbol->vname) + 2; /* "%s (" */ + + len = 2; /* " (" */ n = 0; - do { - symbol = symbol->prev_array; + while (symbol->type == Node_array_ref) { len += strlen(symbol->vname); n++; - } while (symbol->type == Node_array_ref); + symbol = symbol->prev_array; + } + + /* Get the (sub)array name */ + if (symbol->parent_array == NULL) + aname = symbol->vname; + else + aname = make_aname(symbol); + len += strlen(aname); + /* * Each node contributes by strlen(from) minus the length * of "%s" in the translation (which is at least 2) @@ -139,42 +189,21 @@ array_vname(const NODE *symbol) * Ancient systems have sprintf() returning char *, not int. * If you have one of those, use sprintf(..); s += strlen(s) instead. */ + s += sprintf(s, "%s (", symbol->vname); for (;;) { symbol = symbol->prev_array; - sprintf(s, from, symbol->vname); - s += strlen(s); if (symbol->type != Node_array_ref) break; - sprintf(s, ", "); - s += strlen(s); + s += sprintf(s, from, symbol->vname); + s += sprintf(s, ", "); } + s += sprintf(s, from, aname); strcpy(s, ")"); return message; } -/* make_aname --- construct a sub-array name for multi-dimensional array */ - -char * -make_aname(NODE *array, NODE *subs) -{ - static char *aname = NULL; - static size_t aname_len; - size_t slen; - - slen = strlen(array->vname) + subs->stlen + 6; - if (aname == NULL) { - emalloc(aname, char *, slen, "make_aname"); - aname_len = slen; - } else if (slen > aname_len) { - erealloc(aname, char *, slen, "make_aname"); - aname_len = slen; - } - sprintf(aname, "%s[\"%.*s\"]", array->vname, (int) subs->stlen, subs->stptr); - return aname; -} - /* * get_array --- proceed to the actual Node_var_array, @@ -702,7 +731,7 @@ do { \ /* e.g.: a[1] = 1; delete a[1][1] */ free_subs(i); fatal(_("attempt to use scalar `%s[\"%.*s\"]' as an array"), - symbol->vname, + array_vname(symbol), (int) bucket->ahname_len, bucket->ahname_str); } @@ -994,14 +1023,9 @@ dup_table(NODE *symbol, NODE *newsymb) if (chain->ahvalue->type == Node_var_array) { NODE *r; - char *aname; - size_t aname_len; getnode(r); r->type = Node_var_array; - aname_len = strlen(newsymb->vname) + chain->ahname_len + 4; - emalloc(aname, char *, aname_len + 2, "dup_table"); - sprintf(aname, "%s[\"%.*s\"]", newsymb->vname, (int) chain->ahname_len, chain->ahname_str); - r->vname = aname; + r->vname = estrdup(chain->ahname_str, chain->ahname_len); r->parent_array = newsymb; bucket->ahvalue = dup_table(chain->ahvalue, r); } else @@ -1136,23 +1160,34 @@ asort_actual(int nargs, SORT_CTXT ctxt) /* We want the values of the source array. */ val = r->ahvalue; - if (val->type == Node_val) - *assoc_lookup(result, subs, FALSE) = dupnode(val); - else { - const char *arr_name = make_aname(result, subs); - NODE *arr; - - /* - * There isn't any reference counting for - * subarrays, so recursively copy subarrays - * using dup_table(). - */ - getnode(arr); - arr->type = Node_var_array; - arr->var_array = NULL; - arr->vname = estrdup(arr_name, strlen(arr_name)); - arr->parent_array = array; /* actual parent, not the temporary one. */ - *assoc_lookup(result, subs, FALSE) = dup_table(val, arr); + if (result != dest) { + /* optimization for dest = NULL or dest = array */ + + if (val->type == Node_var_array) { + /* update subarray index in parent array */ + efree(val->vname); + val->vname = estrdup(subs->stptr, subs->stlen); + } + *assoc_lookup(result, subs, FALSE) = val; + r->ahvalue = Nnull_string; + } else { + if (val->type == Node_val) + *assoc_lookup(result, subs, FALSE) = dupnode(val); + else { + NODE *arr; + + /* + * There isn't any reference counting for + * subarrays, so recursively copy subarrays + * using dup_table(). + */ + getnode(arr); + arr->type = Node_var_array; + arr->var_array = NULL; + arr->vname = estrdup(subs->stptr, subs->stlen); + arr->parent_array = array; /* actual parent, not the temporary one. */ + *assoc_lookup(result, subs, FALSE) = dup_table(val, arr); + } } } @@ -1383,6 +1418,16 @@ sort_up_value_number(const void *p1, const void *p2) else ret = (n1->numbr > n2->numbr); + if (ret == 0) { + /* + * Use string value to guarantee same sort order on all + * versions of qsort(). + */ + n1 = force_string(n1); + n2 = force_string(n2); + ret = cmp_string(n1, n2); + } + return ret; } @@ -1113,7 +1113,6 @@ typedef enum sort_context { SORTED_IN = 1, ASORT, ASORTI } SORT_CTXT; extern NODE **assoc_list(NODE *array, const char *sort_str, SORT_CTXT sort_ctxt); extern NODE *get_array(NODE *symbol, int canfatal); extern char *array_vname(const NODE *symbol); -extern char *make_aname(NODE *array, NODE *subs); extern void array_init(void); extern void set_SUBSEP(void); extern NODE *concat_exp(int nargs, int do_subsep); @@ -1074,7 +1074,7 @@ print_array(volatile NODE *arr, char *arr_name) num_elems = arr->table_size; /* sort indices, sub_arrays are also sorted! */ - list = assoc_list((NODE *) arr, "@unsorted", SORTED_IN); + list = assoc_list((NODE *) arr, "@ind_str_asc", SORTED_IN); PUSH_BINDING(pager_quit_tag_stack, pager_quit_tag, pager_quit_tag_valid); if (setjmp(pager_quit_tag) == 0) { @@ -1262,12 +1262,12 @@ do_set_var(CMDARG *arg, int cmd ATTRIBUTE_UNUSED) } } else { if (value == NULL) { - const char *aname = make_aname(r, subs); NODE *array; + getnode(array); array->type = Node_var_array; array->var_array = NULL; - array->vname = estrdup(aname, strlen(aname)); + array->vname = estrdup(subs->stptr, subs->stlen); *assoc_lookup(r, subs, FALSE) = array; r = array; } else if (value->type != Node_var_array) { @@ -1763,18 +1763,15 @@ top: t1 = POP_ARRAY(); r = in_array(t1, t2); if (r == NULL) { - const char *arr_name = make_aname(t1, t2); getnode(r); r->type = Node_var_array; r->var_array = NULL; - r->vname = estrdup(arr_name, strlen(arr_name)); + r->vname = estrdup(t2->stptr, t2->stlen); /* the subscript in parent array */ r->parent_array = t1; *assoc_lookup(t1, t2, FALSE) = r; - } else if (r->type != Node_var_array) { - const char *arr_name = make_aname(t1, t2); - DEREF(t2); - fatal(_("attempt to use scalar `%s' as an array"), arr_name); - } + } else if (r->type != Node_var_array) + fatal(_("attempt to use scalar `%s[\"%.*s\"]' as an array"), + array_vname(t1), (int) t2->stlen, t2->stptr); DEREF(t2); PUSH(r); break; @@ -1783,11 +1780,9 @@ top: t2 = mk_sub(pc->sub_count); t1 = POP_ARRAY(); lhs = assoc_lookup(t1, t2, pc->do_reference); - if ((*lhs)->type == Node_var_array) { - const char *arr_name = make_aname(t1, t2); - DEREF(t2); - fatal(_("attempt to use array `%s' in a scalar context"), arr_name); - } + if ((*lhs)->type == Node_var_array) + 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; @@ -2031,11 +2026,9 @@ 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) { - const char *arr_name = make_aname(t1, t2); - DEREF(t2); - fatal(_("attempt to use array `%s' in a scalar context"), arr_name); - } + if ((*lhs)->type == Node_var_array) + 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(); diff --git a/test/ChangeLog b/test/ChangeLog index 03c93594..c7a01ccc 100644 --- a/test/ChangeLog +++ b/test/ChangeLog @@ -1,3 +1,7 @@ +Sun May 8 20:32:59 2011 Arnold D. Robbins <arnold@skeeve.com> + + * arraysort.ok, sort1.ok: Updated. + Wed May 4 23:37:27 2011 Arnold D. Robbins <arnold@skeeve.com> Revise tests for array sorting. diff --git a/test/arraysort.ok b/test/arraysort.ok index 454badf0..d2d8ca70 100644 --- a/test/arraysort.ok +++ b/test/arraysort.ok @@ -71,13 +71,13 @@ y 1 |4|4| |5|5| --asc val num-- -|D3|D3| |0|0| +|D3|D3| |1|1| |2|2| -|3D|3D| | 3| 3| |3|3| -|4|4| +|3D|3D| | 4 | 4 | +|4|4| |5|5| diff --git a/test/sort1.ok b/test/sort1.ok index 2d43e31a..00ed661a 100644 --- a/test/sort1.ok +++ b/test/sort1.ok @@ -58,14 +58,14 @@ [6][3]: tttalb [6][4]: zrab ---end PROCINFO["sorted_in"] = "@val_str_asc", IGNORECASE = 0--- + [3]: Zebra [1]: barz [2]: blattt - [3]: Zebra [5]: 234 [4]: 1234 - [6][4]: zrab [6][2]: arbeZ [6][3]: tttalb + [6][4]: zrab [6][1]: 4321 ---end PROCINFO["sorted_in"] = "@val_num_asc", IGNORECASE = 0--- [6][4]: zrab @@ -80,12 +80,12 @@ ---end PROCINFO["sorted_in"] = "@val_str_desc", IGNORECASE = 0--- [6][1]: 4321 [6][4]: zrab - [6][2]: arbeZ [6][3]: tttalb + [6][2]: arbeZ [4]: 1234 [5]: 234 - [1]: barz [2]: blattt + [1]: barz [3]: Zebra ---end PROCINFO["sorted_in"] = "@val_num_desc", IGNORECASE = 0--- [5]: 234 @@ -173,9 +173,9 @@ [3]: Zebra [5]: 234 [4]: 1234 - [6][4]: zrab [6][2]: arbeZ [6][3]: tttalb + [6][4]: zrab [6][1]: 4321 ---end PROCINFO["sorted_in"] = "@val_num_asc", IGNORECASE = 1--- [6][4]: zrab @@ -190,13 +190,13 @@ ---end PROCINFO["sorted_in"] = "@val_str_desc", IGNORECASE = 1--- [6][1]: 4321 [6][4]: zrab - [6][2]: arbeZ [6][3]: tttalb + [6][2]: arbeZ [4]: 1234 [5]: 234 - [1]: barz - [2]: blattt [3]: Zebra + [2]: blattt + [1]: barz ---end PROCINFO["sorted_in"] = "@val_num_desc", IGNORECASE = 1--- [5]: 234 [4]: 1234 |