aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog17
-rw-r--r--array.c155
-rw-r--r--awk.h1
-rw-r--r--debug.c6
-rw-r--r--eval.c27
-rw-r--r--test/ChangeLog4
-rw-r--r--test/arraysort.ok6
-rw-r--r--test/sort1.ok16
8 files changed, 145 insertions, 87 deletions
diff --git a/ChangeLog b/ChangeLog
index fde2cc68..fcc5f719 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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.
diff --git a/array.c b/array.c
index b6e72c8d..5cf75d27 100644
--- a/array.c
+++ b/array.c
@@ -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;
}
diff --git a/awk.h b/awk.h
index a14f20a0..d05e07c1 100644
--- a/awk.h
+++ b/awk.h
@@ -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);
diff --git a/debug.c b/debug.c
index 1543a46a..9b9db345 100644
--- a/debug.c
+++ b/debug.c
@@ -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) {
diff --git a/eval.c b/eval.c
index 02ca13e3..4132474a 100644
--- a/eval.c
+++ b/eval.c
@@ -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