aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--ext.c4
-rw-r--r--extension/ChangeLog6
-rw-r--r--extension/Makefile.am11
-rw-r--r--extension/Makefile.in20
-rw-r--r--extension/rwarray.awk25
-rw-r--r--extension/rwarray.c469
-rw-r--r--gawkapi.c11
8 files changed, 293 insertions, 258 deletions
diff --git a/ChangeLog b/ChangeLog
index dbfc8efb..9f6cad4d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2012-06-24 Arnold D. Robbins <arnold@skeeve.com>
+
+ * ext.c (load_ext): Don't retun a value from a void function.
+ * gawkapi.c (api_set_array_element): Set up vname and parent_array.
+
2012-06-21 Arnold D. Robbins <arnold@skeeve.com>
More API and cleanup:
diff --git a/ext.c b/ext.c
index 911754bf..0b87def9 100644
--- a/ext.c
+++ b/ext.c
@@ -69,9 +69,9 @@ load_ext(const char *lib_name)
if (install_func(& api_impl, NULL /* ext_id */) == 0) {
warning(_("load_ext: library `%s' initialization routine `%s' failed\n"),
lib_name, INIT_FUNC);
- return make_number(-1);
+ return;
}
- return make_number(0);
+ return;
}
diff --git a/extension/ChangeLog b/extension/ChangeLog
index b482d6f1..9d4305c1 100644
--- a/extension/ChangeLog
+++ b/extension/ChangeLog
@@ -1,3 +1,9 @@
+2012-06-24 Arnold D. Robbins <arnold@skeeve.com>
+
+ * Makefile.am: Enable rwarray extension.
+ * rwarray.c: Redone to use new API.
+ * rwarray.awk: Revamped for new version.
+
2012-06-21 Arnold D. Robbins <arnold@skeeve.com>
* testext.c (test_array_elem): Add a subarray.
diff --git a/extension/Makefile.am b/extension/Makefile.am
index bdb1bd19..767c2abd 100644
--- a/extension/Makefile.am
+++ b/extension/Makefile.am
@@ -1,7 +1,7 @@
#
# extension/Makefile.am --- automake input file for gawk
#
-# Copyright (C) 1995-2006 the Free Software Foundation, Inc.
+# Copyright (C) 1995-2006, 2012 the Free Software Foundation, Inc.
#
# This file is part of GAWK, the GNU implementation of the
# AWK Programming Language.
@@ -36,6 +36,7 @@ pkgextension_LTLIBRARIES = \
fork.la \
ordchr.la \
readfile.la \
+ rwarray.la \
testext.la \
time.la
@@ -49,12 +50,12 @@ ordchr_la_SOURCES = ordchr.c
ordchr_la_LDFLAGS = $(MY_MODULE_FLAGS)
readfile_la_SOURCES = readfile.c
readfile_la_LDFLAGS = $(MY_MODULE_FLAGS)
+rwarray_la_SOURCES = rwarray.c
+rwarray_la_LDFLAGS = $(MY_MODULE_FLAGS)
time_la_SOURCES = time.c
time_la_LDFLAGS = $(MY_MODULE_FLAGS)
-testext_la_SOURCES = testext.c
-testext_la_LDFLAGS = $(MY_MODULE_FLAGS)
-#rwarray_la_SOURCES = rwarray.c
-#rwarray_la_LDFLAGS = $(MY_MODULE_FLAGS)
+testext_la_SOURCES = testext.c
+testext_la_LDFLAGS = $(MY_MODULE_FLAGS)
EXTRA_DIST = \
ChangeLog \
diff --git a/extension/Makefile.in b/extension/Makefile.in
index 202989a9..5666c9d4 100644
--- a/extension/Makefile.in
+++ b/extension/Makefile.in
@@ -18,7 +18,7 @@
#
# extension/Makefile.am --- automake input file for gawk
#
-# Copyright (C) 1995-2006 the Free Software Foundation, Inc.
+# Copyright (C) 1995-2006, 2012 the Free Software Foundation, Inc.
#
# This file is part of GAWK, the GNU implementation of the
# AWK Programming Language.
@@ -154,6 +154,12 @@ readfile_la_OBJECTS = $(am_readfile_la_OBJECTS)
readfile_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(readfile_la_LDFLAGS) $(LDFLAGS) -o $@
+rwarray_la_LIBADD =
+am_rwarray_la_OBJECTS = rwarray.lo
+rwarray_la_OBJECTS = $(am_rwarray_la_OBJECTS)
+rwarray_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(rwarray_la_LDFLAGS) $(LDFLAGS) -o $@
testext_la_LIBADD =
am_testext_la_OBJECTS = testext.lo
testext_la_OBJECTS = $(am_testext_la_OBJECTS)
@@ -181,10 +187,10 @@ LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
$(LDFLAGS) -o $@
SOURCES = $(filefuncs_la_SOURCES) $(fork_la_SOURCES) \
$(ordchr_la_SOURCES) $(readfile_la_SOURCES) \
- $(testext_la_SOURCES) $(time_la_SOURCES)
+ $(rwarray_la_SOURCES) $(testext_la_SOURCES) $(time_la_SOURCES)
DIST_SOURCES = $(filefuncs_la_SOURCES) $(fork_la_SOURCES) \
$(ordchr_la_SOURCES) $(readfile_la_SOURCES) \
- $(testext_la_SOURCES) $(time_la_SOURCES)
+ $(rwarray_la_SOURCES) $(testext_la_SOURCES) $(time_la_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
@@ -337,6 +343,7 @@ pkgextension_LTLIBRARIES = \
fork.la \
ordchr.la \
readfile.la \
+ rwarray.la \
testext.la \
time.la
@@ -349,12 +356,12 @@ ordchr_la_SOURCES = ordchr.c
ordchr_la_LDFLAGS = $(MY_MODULE_FLAGS)
readfile_la_SOURCES = readfile.c
readfile_la_LDFLAGS = $(MY_MODULE_FLAGS)
+rwarray_la_SOURCES = rwarray.c
+rwarray_la_LDFLAGS = $(MY_MODULE_FLAGS)
time_la_SOURCES = time.c
time_la_LDFLAGS = $(MY_MODULE_FLAGS)
testext_la_SOURCES = testext.c
testext_la_LDFLAGS = $(MY_MODULE_FLAGS)
-#rwarray_la_SOURCES = rwarray.c
-#rwarray_la_LDFLAGS = $(MY_MODULE_FLAGS)
EXTRA_DIST = \
ChangeLog \
ChangeLog.0 \
@@ -456,6 +463,8 @@ ordchr.la: $(ordchr_la_OBJECTS) $(ordchr_la_DEPENDENCIES) $(EXTRA_ordchr_la_DEPE
$(ordchr_la_LINK) -rpath $(pkgextensiondir) $(ordchr_la_OBJECTS) $(ordchr_la_LIBADD) $(LIBS)
readfile.la: $(readfile_la_OBJECTS) $(readfile_la_DEPENDENCIES) $(EXTRA_readfile_la_DEPENDENCIES)
$(readfile_la_LINK) -rpath $(pkgextensiondir) $(readfile_la_OBJECTS) $(readfile_la_LIBADD) $(LIBS)
+rwarray.la: $(rwarray_la_OBJECTS) $(rwarray_la_DEPENDENCIES) $(EXTRA_rwarray_la_DEPENDENCIES)
+ $(rwarray_la_LINK) -rpath $(pkgextensiondir) $(rwarray_la_OBJECTS) $(rwarray_la_LIBADD) $(LIBS)
testext.la: $(testext_la_OBJECTS) $(testext_la_DEPENDENCIES) $(EXTRA_testext_la_DEPENDENCIES)
$(testext_la_LINK) -rpath $(pkgextensiondir) $(testext_la_OBJECTS) $(testext_la_LIBADD) $(LIBS)
time.la: $(time_la_OBJECTS) $(time_la_DEPENDENCIES) $(EXTRA_time_la_DEPENDENCIES)
@@ -471,6 +480,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fork.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ordchr.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/readfile.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rwarray.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testext.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/time.Plo@am__quote@
diff --git a/extension/rwarray.awk b/extension/rwarray.awk
index 1057b396..b34a42a7 100644
--- a/extension/rwarray.awk
+++ b/extension/rwarray.awk
@@ -1,19 +1,24 @@
-BEGIN {
- extension("./rwarray.so","dlload")
+@load "rwarray"
+BEGIN {
while ((getline word < "/usr/share/dict/words") > 0)
dict[word] = word word
- for (i in dict)
- printf("dict[%s] = %s\n", i, dict[i]) > "orig.out"
+ n = asorti(dict, dictindices)
+ for (i = 1; i <= n; i++)
+ printf("dict[%s] = %s\n", dictindices[i], dict[dictindices[i]]) > "orig.out"
close("orig.out");
- writea("orig.bin", dict)
+ ret = writea("orig.bin", dict)
+ printf "writea() returned %d, expecting 1\n", ret
- reada("orig.bin", dict)
+
+ ret = reada("orig.bin", dict)
+ printf "reada() returned %d, expecting 1\n", ret
- for (i in dict)
- printf("dict[%s] = %s\n", i, dict[i]) > "new.out"
+ n = asorti(dict, dictindices)
+ for (i = 1; i <= n; i++)
+ printf("dict[%s] = %s\n", dictindices[i], dict[dictindices[i]]) > "new.out"
close("new.out");
ret = system("cmp orig.out new.out")
@@ -23,6 +28,6 @@ BEGIN {
else
print "old and new are not equal - BAD"
- if (ret == 0 && !("keepit" in ENVIRON))
- system("rm orig.bin orig.out new.out")
+ if (ret == 0 && !("KEEPIT" in ENVIRON))
+ system("rm -f orig.bin orig.out new.out")
}
diff --git a/extension/rwarray.c b/extension/rwarray.c
index fed040fc..e4ddde3b 100644
--- a/extension/rwarray.c
+++ b/extension/rwarray.c
@@ -3,10 +3,11 @@
*
* Arnold Robbins
* May 2009
+ * Redone June 2012
*/
/*
- * Copyright (C) 2009, 2010, 2011 the Free Software Foundation, Inc.
+ * Copyright (C) 2009, 2010, 2011, 2012 the Free Software Foundation, Inc.
*
* This file is part of GAWK, the GNU implementation of the
* AWK Programming Language.
@@ -26,76 +27,98 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
-#include "awk.h"
+#include <stdio.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/stat.h>
-#include <fcntl.h>
+#include "gawkapi.h"
#define MAGIC "awkrulz\n"
-#define MAJOR 1
+#define MAJOR 3
#define MINOR 0
+static const gawk_api_t *api; /* for convenience macros to work */
+static awk_ext_id_t *ext_id;
+
int plugin_is_GPL_compatible;
-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 awk_bool_t write_array(int fd, awk_array_t array);
+static awk_bool_t write_elem(int fd, awk_element_t *element);
+static awk_bool_t write_value(int fd, awk_value_t *val);
-static int read_array(int fd, NODE *array);
-static NODE *read_elem(int fd, int *index, NODE *array);
-static NODE *read_value(int fd);
+static awk_bool_t read_array(int fd, awk_array_t array);
+static awk_bool_t read_elem(int fd, awk_element_t *element);
+static awk_bool_t read_value(int fd, awk_value_t *value);
/*
* Format of array info:
*
- * MAGIC 8 bytes
+ * MAGIC 8 bytes
* Major version 4 bytes - network order
* Minor version 4 bytes - network order
* Element count 4 bytes - network order
- * Array size 4 bytes - network order
* Elements
*
* For each element:
- * Bucket number: 4 bytes - network order
- * 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, 2 = array)
+ * Value type 4 bytes (0 = string, 1 = number, 2 = array)
* IF string:
* Length of value 4 bytes
* Value as characters (N bytes)
- * ELSE
+ * ELSE IF number:
* 8 bytes as native double
+ * ELSE
+ * Element count
+ * Elements
+ * END IF
*/
/* do_writea --- write an array */
-static NODE *
-do_writea(int nargs)
+static awk_value_t *
+do_writea(int nargs, awk_value_t *result)
{
- NODE *file, *array;
- int ret;
- int fd;
+ awk_value_t filename, array;
+ int fd = -1;
uint32_t major = MAJOR;
uint32_t minor = MINOR;
+ assert(result != NULL);
+ make_number(0.0, result);
+
if (do_lint && nargs > 2)
- lintwarn("writea: called with too many arguments");
+ lintwarn(ext_id, "writea: called with too many arguments");
+
+ if (nargs < 2)
+ goto out;
/* directory is first arg, array to dump is second */
- file = get_scalar_argument(0, false);
- array = get_array_argument(1, false);
+ if (! get_argument(0, AWK_STRING, & filename)) {
+ fprintf(stderr, "do_writea: argument 0 is not a string\n");
+ errno = EINVAL;
+ goto done1;
+ }
- /* open the file, if error, set ERRNO and return */
- (void) force_string(file);
- fd = creat(file->stptr, 0600);
- if (fd < 0) {
+ if (! get_argument(1, AWK_ARRAY, & array)) {
+ fprintf(stderr, "do_writea: argument 1 is not an array\n");
+ errno = EINVAL;
goto done1;
}
+ /* open the file, if error, set ERRNO and return */
+ fd = creat(filename.str_value.str, 0600);
+ if (fd < 0)
+ goto done1;
+
if (write(fd, MAGIC, strlen(MAGIC)) != strlen(MAGIC))
goto done1;
@@ -107,356 +130,336 @@ do_writea(int nargs)
if (write(fd, & minor, sizeof(minor)) != sizeof(minor))
goto done1;
- ret = write_array(fd, array);
- if (ret != 0)
- goto done1;
- ret = 0;
- goto done0;
+ if (write_array(fd, array.array_cookie)) {
+ make_number(1.0, result);
+ goto done0;
+ }
done1:
- ret = -1;
update_ERRNO_int(errno);
- unlink(file->stptr);
+ unlink(filename.str_value.str);
done0:
close(fd);
-
- /* Set the return value */
- return make_number((AWKNUM) ret);
+out:
+ return result;
}
/* write_array --- write out an array or a sub-array */
-static int
-write_array(int fd, NODE *array)
+static awk_bool_t
+write_array(int fd, awk_array_t array)
{
- int ret;
+ uint32_t i;
uint32_t count;
- uint32_t array_sz;
- int i;
-
- count = htonl(array->table_size);
- if (write(fd, & count, sizeof(count)) != sizeof(count))
- return -1;
+ awk_flat_array_t *flat_array;
- array_sz = htonl(array->array_size);
- if (write(fd, & array_sz, sizeof(array_sz)) != sizeof(array_sz))
- return -1;
-
- for (i = 0; i < array->array_size; i++) {
- ret = write_chain(fd, i, array->var_array[i]);
- if (ret != 0)
- return ret;
+ if (! flatten_array(array, & flat_array)) {
+ printf("write_array: could not flatten array\n");
+ return 0;
}
- return 0;
-}
+ count = htonl(flat_array->count);
+ if (write(fd, & count, sizeof(count)) != sizeof(count))
+ return 0;
-/* write_chain --- write out a whole hash chain */
-
-/*
- * Write elements in the chain in reverse order so that
- * when we read the elements back in we can just push them
- * onto the front and thus recreate the array as it was.
- */
-
-static int
-write_chain(int fd, int index, NODE *bucket)
-{
- int ret;
+ for (i = 0; i < flat_array->count; i++) {
+ if (! write_elem(fd, & flat_array->elements[i]))
+ return 0;
+ }
- if (bucket == NULL)
+ if (! release_flattened_array(array, flat_array)) {
+ printf("write_array: could not release flattened array\n");
return 0;
+ }
- ret = write_chain(fd, index, bucket->ahnext);
- if (ret != 0)
- return ret;
-
- return write_elem(fd, index, bucket);
+ return 1;
}
/* write_elem --- write out a single element */
-static int
-write_elem(int fd, int index, NODE *item)
+static awk_bool_t
+write_elem(int fd, awk_element_t *element)
{
- uint32_t hashval, indexval_len;
-
- index = htonl(index);
- if (write(fd, & index, sizeof(index)) != sizeof(index))
- return -1;
+ uint32_t indexval_len;
+ ssize_t write_count;
- hashval = htonl(item->ahcode);
- if (write(fd, & hashval, sizeof(hashval)) != sizeof(hashval))
- return -1;
-
- indexval_len = htonl(item->ahname_len);
+ indexval_len = htonl(element->index.str_value.len);
if (write(fd, & indexval_len, sizeof(indexval_len)) != sizeof(indexval_len))
- return -1;
+ return 0;
- if (write(fd, item->ahname_str, item->ahname_len) != item->ahname_len)
- return -1;
+ if (element->index.str_value.len > 0) {
+ write_count = write(fd, element->index.str_value.str,
+ element->index.str_value.len);
+ if (write_count != (ssize_t) element->index.str_value.len)
+ return 0;
+ }
- return write_value(fd, item->ahvalue);
+ return write_value(fd, & element->value);
}
/* write_value --- write a number or a string or a array */
static int
-write_value(int fd, NODE *val)
+write_value(int fd, awk_value_t *val)
{
- int code, len;
+ uint32_t code, len;
- if (val->type == Node_var_array) {
+ if (val->val_type == AWK_ARRAY) {
code = htonl(2);
if (write(fd, & code, sizeof(code)) != sizeof(code))
- return -1;
- return write_array(fd, val);
+ return 0;
+ return write_array(fd, val->array_cookie);
}
- if ((val->flags & NUMBER) != 0) {
+ if (val->val_type == AWK_NUMBER) {
code = htonl(1);
if (write(fd, & code, sizeof(code)) != sizeof(code))
- return -1;
+ return 0;
- if (write(fd, & val->numbr, sizeof(val->numbr)) != sizeof(val->numbr))
- return -1;
+ if (write(fd, & val->num_value, sizeof(val->num_value)) != sizeof(val->num_value))
+ return 0;
} else {
code = 0;
if (write(fd, & code, sizeof(code)) != sizeof(code))
- return -1;
+ return 0;
- len = htonl(val->stlen);
+ len = htonl(val->str_value.len);
if (write(fd, & len, sizeof(len)) != sizeof(len))
- return -1;
+ return 0;
- if (write(fd, val->stptr, val->stlen) != val->stlen)
- return -1;
+ if (write(fd, val->str_value.str, val->str_value.len)
+ != (ssize_t) val->str_value.len)
+ return 0;
}
- return 0;
+ return 1;
}
/* do_reada --- read an array */
-static NODE *
-do_reada(int nargs)
+static awk_value_t *
+do_reada(int nargs, awk_value_t *result)
{
- NODE *file, *array;
- int ret;
- int fd;
+ awk_value_t filename, array;
+ int fd = -1;
uint32_t major;
uint32_t minor;
char magic_buf[30];
+ assert(result != NULL);
+ make_number(0.0, result);
+
if (do_lint && nargs > 2)
- lintwarn("reada: called with too many arguments");
+ lintwarn(ext_id, "reada: called with too many arguments");
- /* directory is first arg, array to dump is second */
- file = get_scalar_argument(0, false);
- array = get_array_argument(1, false);
+ if (nargs < 2)
+ goto out;
- (void) force_string(file);
- fd = open(file->stptr, O_RDONLY);
- if (fd < 0) {
+ /* directory is first arg, array to read is second */
+ if (! get_argument(0, AWK_STRING, & filename)) {
+ fprintf(stderr, "do_reada: argument 0 is not a string\n");
+ errno = EINVAL;
goto done1;
}
+ if (! get_argument(1, AWK_ARRAY, & array)) {
+ fprintf(stderr, "do_reada: argument 1 is not an array\n");
+ errno = EINVAL;
+ goto done1;
+ }
+
+ fd = open(filename.str_value.str, O_RDONLY);
+ if (fd < 0)
+ goto done1;
+
memset(magic_buf, '\0', sizeof(magic_buf));
if (read(fd, magic_buf, strlen(MAGIC)) != strlen(MAGIC)) {
+ errno = EBADF;
goto done1;
}
if (strcmp(magic_buf, MAGIC) != 0) {
+ errno = EBADF;
goto done1;
}
if (read(fd, & major, sizeof(major)) != sizeof(major)) {
+ errno = EBADF;
goto done1;
}
major = ntohl(major);
if (major != MAJOR) {
+ errno = EBADF;
goto done1;
}
if (read(fd, & minor, sizeof(minor)) != sizeof(minor)) {
+ /* read() sets errno */
goto done1;
}
+
minor = ntohl(minor);
if (minor != MINOR) {
+ errno = EBADF;
goto done1;
}
- assoc_clear(array, NULL);
+ if (! clear_array(array.array_cookie)) {
+ errno = ENOMEM;
+ printf("do_reada: clear_array failed\n");
+ goto done1;
+ }
- ret = read_array(fd, array);
- if (ret == 0)
+ if (read_array(fd, array.array_cookie)) {
+ make_number(1.0, result);
goto done0;
+ }
done1:
- ret = -1;
update_ERRNO_int(errno);
-
done0:
close(fd);
-
- /* Set the return value */
- return make_number((AWKNUM) ret);
+out:
+ return result;
}
/* read_array --- read in an array or sub-array */
-static int
-read_array(int fd, NODE *array)
+static awk_bool_t
+read_array(int fd, awk_array_t array)
{
- int i;
+ uint32_t i;
uint32_t count;
- uint32_t array_sz;
- int index;
- NODE *new_elem;
+ awk_element_t new_elem;
if (read(fd, & count, sizeof(count)) != sizeof(count)) {
- return -1;
- }
- array->table_size = ntohl(count);
-
- if (read(fd, & array_sz, sizeof(array_sz)) != sizeof(array_sz)) {
- return -1;
+ return 0;
}
- array->array_size = ntohl(array_sz);
-
- /* malloc var_array */
- array->var_array = (NODE **) malloc(array->array_size * sizeof(NODE *));
- memset(array->var_array, '\0', array->array_size * sizeof(NODE *));
-
- 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;
+ count = ntohl(count);
+
+ for (i = 0; i < count; i++) {
+ if (read_elem(fd, & new_elem)) {
+ /* add to array */
+ if (! set_array_element(array, & new_elem)) {
+ printf("read_array: set_array_element failed\n");
+ return 0;
+ }
} else
break;
}
- if (i != array->table_size)
- return -1;
- return 0;
-}
+ if (i != count)
+ return 0;
+
+ return 1;
+}
/* read_elem --- read in a single element */
-static NODE *
-read_elem(int fd, int *the_index, NODE *array)
+static awk_bool_t
+read_elem(int fd, awk_element_t *element)
{
- uint32_t hashval, indexval_len, index;
- NODE *item;
- NODE *val;
- int ret;
+ uint32_t index_len;
+ static char *buffer;
+ static uint32_t buflen;
+ ssize_t ret;
- *the_index = 0;
-
- if ((ret = read(fd, & index, sizeof(index))) != sizeof(index)) {
- return NULL;
+ if ((ret = read(fd, & index_len, sizeof(index_len))) != sizeof(index_len)) {
+ return 0;
}
- *the_index = index = ntohl(index);
+ index_len = ntohl(index_len);
- getnode(item);
- memset(item, 0, sizeof(*item));
- item->type = Node_ahash;
- item->flags = MALLOC;
+ memset(element, 0, sizeof(*element));
- if (read(fd, & hashval, sizeof(hashval)) != sizeof(hashval)) {
- return NULL;
- }
+ if (index_len > 0) {
+ if (buffer == NULL) {
+ // allocate buffer
+ emalloc(buffer, char *, index_len, "read_elem");
+ buflen = index_len;
+ } else if (buflen < index_len) {
+ // reallocate buffer
+ char *cp = realloc(buffer, index_len);
- item->ahcode = ntohl(hashval);
+ if (cp == NULL)
+ return 0;
- if (read(fd, & indexval_len, sizeof(indexval_len)) != sizeof(indexval_len)) {
- return NULL;
- }
- item->ahname_len = ntohl(indexval_len);
+ buffer = cp;
+ buflen = index_len;
+ }
- item->ahname_str = malloc(item->ahname_len + 2);
- if (read(fd, item->ahname_str, item->ahname_len) != item->ahname_len) {
- return NULL;
+ if (read(fd, buffer, index_len) != (ssize_t) index_len) {
+ return 0;
+ }
+ make_string(buffer, index_len, & element->index);
+ } else {
+ make_string("", 0, & element->index);
}
- item->ahname_str[item->ahname_len] = '\0';
- item->ahname_ref = 1;
- 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;
- }
+ if (! read_value(fd, & element->value))
+ return 0;
- return item;
+ return 1;
}
/* read_value --- read a number or a string */
-static NODE *
-read_value(int fd)
+static awk_bool_t
+read_value(int fd, awk_value_t *value)
{
- NODE *val;
- int code, len;
+ uint32_t code, len;
- getnode(val);
- memset(val, 0, sizeof(*val));
- val->type = Node_val;
+ if (read(fd, & code, sizeof(code)) != sizeof(code))
+ return 0;
- if (read(fd, & code, sizeof(code)) != sizeof(code)) {
- return NULL;
- }
code = ntohl(code);
if (code == 2) {
- val->type = Node_var_array;
- if (read_array(fd, val) != 0)
- return NULL;
+ awk_array_t array = create_array();
+
+ if (read_array(fd, array) != 0)
+ return 0;
+
+ /* hook into value */
+ value->val_type = AWK_ARRAY;
+ value->array_cookie = array;
} else if (code == 1) {
- if (read(fd, & val->numbr, sizeof(val->numbr)) != sizeof(val->numbr)) {
- return NULL;
- }
+ double d;
+
+ if (read(fd, & d, sizeof(d)) != sizeof(d))
+ return 0;
- val->flags = NUMBER|NUMCUR|MALLOC;
+ /* hook into value */
+ value->val_type = AWK_NUMBER;
+ value->num_value = d;
} else {
if (read(fd, & len, sizeof(len)) != sizeof(len)) {
- return NULL;
+ return 0;
}
- val->stlen = ntohl(len);
- val->stptr = malloc(val->stlen + 2);
- memset(val->stptr, '\0', val->stlen + 2);
-
- if (read(fd, val->stptr, val->stlen) != val->stlen) {
- return NULL;
+ len = ntohl(len);
+ value->val_type = AWK_STRING;
+ value->str_value.len = len;
+ value->str_value.str = malloc(len + 2);
+ memset(value->str_value.str, '\0', len + 2);
+
+ if (read(fd, value->str_value.str, len) != len) {
+ free(value->str_value.str);
+ return 0;
}
-
- val->flags = STRING|STRCUR|MALLOC;
}
- return val;
+ return 1;
}
-/* dlload --- load new builtins in this library */
+static awk_ext_func_t func_table[] = {
+ { "writea", do_writea, 2 },
+ { "reada", do_reada, 2 },
+};
-NODE *
-dlload(tree, dl)
-NODE *tree;
-void *dl;
-{
- make_builtin("writea", do_writea, 2);
- make_builtin("reada", do_reada, 2);
- return make_number((AWKNUM) 0);
-}
+/* define the dl_load function using the boilerplate macro */
+
+dl_load_func(func_table, rwarray, "")
diff --git a/gawkapi.c b/gawkapi.c
index 139d77b8..f87c7759 100644
--- a/gawkapi.c
+++ b/gawkapi.c
@@ -528,6 +528,7 @@ api_set_array_element(awk_ext_id_t id, awk_array_t a_cookie,
{
NODE *array = (NODE *)a_cookie;
NODE *tmp;
+ NODE *elem;
NODE **aptr;
/* don't check for index len zero, null str is ok as index */
@@ -542,9 +543,13 @@ api_set_array_element(awk_ext_id_t id, awk_array_t a_cookie,
aptr = assoc_lookup(array, tmp);
unref(tmp);
unref(*aptr);
- *aptr = awk_value_to_node(& element->value);
- if ((*aptr)->type == Node_var_array)
- (*aptr)->parent_array = array;
+ elem = *aptr = awk_value_to_node(& element->value);
+ if (elem->type == Node_var_array) {
+ elem->parent_array = array;
+ elem->vname = estrdup(element->index.str_value.str,
+ element->index.str_value.len);
+ make_aname(elem);
+ }
return true;
}