aboutsummaryrefslogtreecommitdiffstats
path: root/extension/rwarray.c
diff options
context:
space:
mode:
Diffstat (limited to 'extension/rwarray.c')
-rw-r--r--extension/rwarray.c181
1 files changed, 108 insertions, 73 deletions
diff --git a/extension/rwarray.c b/extension/rwarray.c
index 72a331c3..ace5c84e 100644
--- a/extension/rwarray.c
+++ b/extension/rwarray.c
@@ -37,11 +37,13 @@
#define MAJOR 1
#define MINOR 0
+static int write_array(int fd, NODE *array);
static int write_elem(int fd, int index, NODE *item);
static int write_chain(int fd, int index, NODE *item);
static int write_value(int fd, NODE *val);
-static NODE *read_elem(int fd, int *index, int *eof);
+static int read_array(int fd, NODE *array);
+static NODE *read_elem(int fd, int *index, NODE *array);
static NODE *read_value(int fd);
/*
@@ -59,7 +61,7 @@ static NODE *read_value(int fd);
* Hash of index val: 4 bytes - network order
* Length of index val: 4 bytes - network order
* Index val as characters (N bytes)
- * Value type 1 byte (0 = string, 1 = number)
+ * Value type 1 byte (0 = string, 1 = number, 2 = array)
* IF string:
* Length of value 4 bytes
* Value as characters (N bytes)
@@ -70,24 +72,20 @@ static NODE *read_value(int fd);
/* do_writea --- write an array */
static NODE *
-do_writea(tree)
-NODE *tree;
+do_writea(int nargs)
{
NODE *file, *array;
int ret;
int fd;
uint32_t major = MAJOR;
uint32_t minor = MINOR;
- uint32_t count;
- uint32_t array_sz;
- int i;
if (do_lint && get_curfunc_arg_count() > 2)
lintwarn("writea: called with too many arguments");
/* directory is first arg, array to dump is second */
- file = get_scalar_argument(tree, 0, FALSE);
- array = get_array_argument(tree, 1, TRUE);
+ file = get_scalar_argument(0, FALSE);
+ array = get_array_argument(1, FALSE);
/* open the file, if error, set ERRNO and return */
(void) force_string(file);
@@ -107,20 +105,9 @@ NODE *tree;
if (write(fd, & minor, sizeof(minor)) != sizeof(minor))
goto done1;
- count = htonl(array->table_size);
- if (write(fd, & count, sizeof(count)) != sizeof(count))
- goto done1;
-
- array_sz = htonl(array->array_size);
- if (write(fd, & array_sz, sizeof(array_sz)) != sizeof(array_sz))
+ ret = write_array(fd, array);
+ if (ret != 0)
goto done1;
-
- for (i = 0; i < array->array_size; i++) {
- ret = write_chain(fd, i, array->var_array[i]);
- if (ret != 0)
- goto done1;
- }
-
ret = 0;
goto done0;
@@ -130,16 +117,40 @@ done1:
unlink(file->stptr);
done0:
- free_temp(file);
close(fd);
/* Set the return value */
- set_value(tmp_number((AWKNUM) ret));
+ return make_number((AWKNUM) ret);
+}
+
+
+/* write_array --- write out an array or a sub-array */
+
+static int
+write_array(int fd, NODE *array)
+{
+ int ret;
+ uint32_t count;
+ uint32_t array_sz;
+ int i;
+
+ count = htonl(array->table_size);
+ if (write(fd, & count, sizeof(count)) != sizeof(count))
+ return -1;
+
+ array_sz = htonl(array->array_size);
+ if (write(fd, & array_sz, sizeof(array_sz)) != sizeof(array_sz))
+ return -1;
- /* Just to make the interpreter happy */
- return tmp_number((AWKNUM) 0);
+ for (i = 0; i < array->array_size; i++) {
+ ret = write_chain(fd, i, array->var_array[i]);
+ if (ret != 0)
+ return ret;
+ }
+ return 0;
}
+
/* write_chain --- write out a whole hash chain */
/*
@@ -188,13 +199,20 @@ write_elem(int fd, int index, NODE *item)
return write_value(fd, item->ahvalue);
}
-/* write_value --- write a number or a string */
+/* write_value --- write a number or a string or a array */
static int
write_value(int fd, NODE *val)
{
int code, len;
+ if (val->type == Node_var_array) {
+ code = htonl(2);
+ if (write(fd, & code, sizeof(code)) != sizeof(code))
+ return -1;
+ return write_array(fd, val);
+ }
+
if ((val->flags & NUMBER) != 0) {
code = htonl(1);
if (write(fd, & code, sizeof(code)) != sizeof(code))
@@ -221,27 +239,21 @@ write_value(int fd, NODE *val)
/* do_reada --- read an array */
static NODE *
-do_reada(tree)
-NODE *tree;
+do_reada(int nargs)
{
NODE *file, *array;
int ret;
int fd;
uint32_t major;
uint32_t minor;
- uint32_t count;
- uint32_t array_sz;
char magic_buf[30];
- int index;
- NODE *new_elem;
- int eof;
if (do_lint && get_curfunc_arg_count() > 2)
lintwarn("reada: called with too many arguments");
/* directory is first arg, array to dump is second */
- file = get_scalar_argument(tree, 0, FALSE);
- array = get_array_argument(tree, 1, TRUE);
+ file = get_scalar_argument(0, FALSE);
+ array = get_array_argument(1, FALSE);
(void) force_string(file);
fd = open(file->stptr, O_RDONLY);
@@ -277,13 +289,40 @@ NODE *tree;
assoc_clear(array);
+ ret = read_array(fd, array);
+ if (ret == 0)
+ goto done0;
+
+done1:
+ ret = -1;
+ update_ERRNO();
+
+done0:
+ close(fd);
+
+ /* Set the return value */
+ return make_number((AWKNUM) ret);
+}
+
+
+/* read_array --- read in an array or sub-array */
+
+static int
+read_array(int fd, NODE *array)
+{
+ int i;
+ uint32_t count;
+ uint32_t array_sz;
+ int index;
+ NODE *new_elem;
+
if (read(fd, & count, sizeof(count)) != sizeof(count)) {
- goto done1;
+ return -1;
}
array->table_size = ntohl(count);
if (read(fd, & array_sz, sizeof(array_sz)) != sizeof(array_sz)) {
- goto done1;
+ return -1;
}
array->array_size = ntohl(array_sz);
@@ -291,47 +330,32 @@ NODE *tree;
array->var_array = (NODE **) malloc(array->array_size * sizeof(NODE *));
memset(array->var_array, '\0', array->array_size * sizeof(NODE *));
- while ((new_elem = read_elem(fd, & index, & eof)) != NULL) {
- new_elem->ahnext = array->var_array[index];
- array->var_array[index] = new_elem;
- }
-
- if (eof) {
- ret = 0;
- goto done0;
+ for (i = 0; i < array->table_size; i++) {
+ if ((new_elem = read_elem(fd, & index, array)) != NULL) {
+ new_elem->ahnext = array->var_array[index];
+ array->var_array[index] = new_elem;
+ } else
+ break;
}
-
-done1:
- ret = -1;
- update_ERRNO();
-
-done0:
- free_temp(file);
- close(fd);
-
- /* Set the return value */
- set_value(tmp_number((AWKNUM) ret));
-
- /* Just to make the interpreter happy */
- return tmp_number((AWKNUM) 0);
+ if (i != array->table_size)
+ return -1;
+ return 0;
}
+
/* read_elem --- read in a single element */
static NODE *
-read_elem(int fd, int *the_index, int *eof)
+read_elem(int fd, int *the_index, NODE *array)
{
uint32_t hashval, indexval_len, index;
NODE *item;
+ NODE *val;
int ret;
*the_index = 0;
- *eof = FALSE;
if ((ret = read(fd, & index, sizeof(index))) != sizeof(index)) {
- if (ret == 0) {
- *eof = TRUE;
- }
return NULL;
}
*the_index = index = ntohl(index);
@@ -359,10 +383,20 @@ read_elem(int fd, int *the_index, int *eof)
item->ahname_str[item->ahname_len] = '\0';
item->ahname_ref = 1;
- item->ahvalue = read_value(fd);
- if (item->ahvalue == NULL) {
+ item->ahvalue = val = read_value(fd);
+ if (val == NULL) {
return NULL;
}
+ if (val->type == Node_var_array) {
+ char *aname;
+ size_t aname_len;
+
+ /* construct the sub-array name */
+ aname_len = strlen(array->vname) + item->ahname_len + 4;
+ emalloc(aname, char *, aname_len + 2, "read_elem");
+ sprintf(aname, "%s[\"%.*s\"]", array->vname, (int) item->ahname_len, item->ahname_str);
+ val->vname = aname;
+ }
return item;
}
@@ -384,14 +418,15 @@ read_value(int fd)
}
code = ntohl(code);
- /*
- * Very very early versions of this did not write out the code using htonl.
- * Thus this check for `!= 0' instead of '== 1'.
- */
- if (code != 0) {
+ if (code == 2) {
+ val->type = Node_var_array;
+ if (read_array(fd, val) != 0)
+ return NULL;
+ } else if (code == 1) {
if (read(fd, & val->numbr, sizeof(val->numbr)) != sizeof(val->numbr)) {
return NULL;
}
+
val->flags = NUMBER|NUMCUR|MALLOC;
} else {
if (read(fd, & len, sizeof(len)) != sizeof(len)) {
@@ -421,5 +456,5 @@ void *dl;
make_builtin("writea", do_writea, 2);
make_builtin("reada", do_reada, 2);
- return tmp_number((AWKNUM) 0);
+ return make_number((AWKNUM) 0);
}