summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog18
-rw-r--r--awk.h1
-rw-r--r--ext.c9
-rw-r--r--extension/ChangeLog10
-rw-r--r--extension/Makefile.am7
-rw-r--r--extension/Makefile.in22
-rw-r--r--extension/testext.c124
-rw-r--r--extension/time.c2
-rw-r--r--gawkapi.c109
-rw-r--r--main.c4
-rw-r--r--msg.c8
-rw-r--r--profile.c2
12 files changed, 258 insertions, 58 deletions
diff --git a/ChangeLog b/ChangeLog
index d6bad9ea..1b071e93 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,11 +1,12 @@
2012-06-12 Arnold D. Robbins <arnold@skeeve.com>
+ API Work:
+
* gawkapi.h (awk_value_t): Restore union.
(get_curfunc_param): Renamed to get_argument. Return type changed
to awk_bool_t. Semantics better thought out and documented.
(awk_atexit, get_array_element): Return type now void.
(sym_lookup): Return type now void. Argument order rationalized.
-
* gawkapi.c (node_to_awk_value): Return type is now awk_bool_t.
Semantics now match table in gawkawpi.h.
(api_awk_atexit): Return type now void.
@@ -13,6 +14,21 @@
order.
(api_get_array_element): Return type is now awk_bool_t.
+ Further API implementations and fixes for extension/testext.c:
+
+ * awk.h (final_exit): Add declaration.
+ * ext.c (load_ext): Change `func' to install_func.
+ * gawkapi.c: Add casts to void for id param in all functions.
+ (api_sym_update): Finish implementation.
+ (api_get_array_element): Start implementation.
+ (api_set_array_element): Add error checking.
+ (api_get_element_count): Add error checking, return the right value.
+ * main.c (main): Call final_exit instead of exit.
+ (arg_assign): Ditto.
+ * msg.c (final_exit): New routine to run the exit handlers and exit.
+ (gawk_exit): Call it.
+ * profile.c (dump_and_exit): Ditto.
+
2012-06-10 Andrew J. Schorr <aschorr@telemetry-investments.com>
* TODO.xgawk: Addition of time extension moved to "done" section.
diff --git a/awk.h b/awk.h
index d8aa238b..6c1e706a 100644
--- a/awk.h
+++ b/awk.h
@@ -1604,6 +1604,7 @@ extern int mpg_strtoui(mpz_ptr, char *, size_t, char **, int);
#endif
/* msg.c */
extern void gawk_exit(int status);
+extern void final_exit(int status) ATTRIBUTE_NORETURN;
extern void err(const char *s, const char *emsg, va_list argp) ATTRIBUTE_PRINTF(2, 0);
extern void msg (const char *mesg, ...) ATTRIBUTE_PRINTF_1;
extern void error (const char *mesg, ...) ATTRIBUTE_PRINTF_1;
diff --git a/ext.c b/ext.c
index 66ea7fbe..d0755ccd 100644
--- a/ext.c
+++ b/ext.c
@@ -60,7 +60,7 @@ do_ext(int nargs)
NODE *
load_ext(const char *lib_name, const char *init_func)
{
- int (*func)(const gawk_api_t *const, awk_ext_id_t);
+ int (*install_func)(const gawk_api_t *const, awk_ext_id_t);
void *dl;
int flags = RTLD_LAZY;
int *gpl_compat;
@@ -80,12 +80,13 @@ load_ext(const char *lib_name, const char *init_func)
if (gpl_compat == NULL)
fatal(_("load_ext: library `%s': does not define `plugin_is_GPL_compatible' (%s)\n"),
lib_name, dlerror());
- func = (int (*)(const gawk_api_t *const, awk_ext_id_t)) dlsym(dl, init_func);
- if (func == NULL)
+ install_func = (int (*)(const gawk_api_t *const, awk_ext_id_t))
+ dlsym(dl, init_func);
+ if (install_func == NULL)
fatal(_("load_ext: library `%s': cannot call function `%s' (%s)\n"),
lib_name, init_func, dlerror());
- if ((*func)(& api_impl, NULL /* ext_id */) == 0) {
+ 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);
diff --git a/extension/ChangeLog b/extension/ChangeLog
index 6c4ea84a..4d504fb1 100644
--- a/extension/ChangeLog
+++ b/extension/ChangeLog
@@ -1,5 +1,7 @@
2012-06-12 Arnold D. Robbins <arnold@skeeve.com>
+ Revise API:
+
* filefuncs.c (do_chdir): Replace get_curfunc_param with get_argument.
(format_mode): Use unsigned masks.
(do_stat): Replace get_curfunc_param with get_argument.
@@ -10,6 +12,14 @@
* time.c (do_sleep): Replace get_curfunc_param with get_argument.
Replace set_ERRNO with update_ERRNO_str for no way to sleep case.
+ Work on testext.c:
+
+ * Makefile.am: Add stuff to make testext. Remove doit and steps
+ from EXTRA_DIST.
+ * testext.c: Fill in many of the test routines. Still more to do.
+ Fix up test scripts for each routine.
+ * time.c (do_sleep): Fix use of get_argument to be boolean.
+
2012-06-10 Andrew J. Schorr <aschorr@telemetry-investments.com>
* Makefile.am: Add time extension.
diff --git a/extension/Makefile.am b/extension/Makefile.am
index f2b30ede..bdb1bd19 100644
--- a/extension/Makefile.am
+++ b/extension/Makefile.am
@@ -36,6 +36,7 @@ pkgextension_LTLIBRARIES = \
fork.la \
ordchr.la \
readfile.la \
+ testext.la \
time.la
MY_MODULE_FLAGS = -module -avoid-version -no-undefined
@@ -50,12 +51,12 @@ readfile_la_SOURCES = readfile.c
readfile_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 \
- *.awk \
- doit \
- steps
+ *.awk
diff --git a/extension/Makefile.in b/extension/Makefile.in
index 59528912..202989a9 100644
--- a/extension/Makefile.in
+++ b/extension/Makefile.in
@@ -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 $@
+testext_la_LIBADD =
+am_testext_la_OBJECTS = testext.lo
+testext_la_OBJECTS = $(am_testext_la_OBJECTS)
+testext_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(testext_la_LDFLAGS) $(LDFLAGS) -o $@
time_la_LIBADD =
am_time_la_OBJECTS = time.lo
time_la_OBJECTS = $(am_time_la_OBJECTS)
@@ -174,9 +180,11 @@ LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
SOURCES = $(filefuncs_la_SOURCES) $(fork_la_SOURCES) \
- $(ordchr_la_SOURCES) $(readfile_la_SOURCES) $(time_la_SOURCES)
+ $(ordchr_la_SOURCES) $(readfile_la_SOURCES) \
+ $(testext_la_SOURCES) $(time_la_SOURCES)
DIST_SOURCES = $(filefuncs_la_SOURCES) $(fork_la_SOURCES) \
- $(ordchr_la_SOURCES) $(readfile_la_SOURCES) $(time_la_SOURCES)
+ $(ordchr_la_SOURCES) $(readfile_la_SOURCES) \
+ $(testext_la_SOURCES) $(time_la_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
@@ -329,6 +337,7 @@ pkgextension_LTLIBRARIES = \
fork.la \
ordchr.la \
readfile.la \
+ testext.la \
time.la
MY_MODULE_FLAGS = -module -avoid-version -no-undefined
@@ -342,14 +351,14 @@ readfile_la_SOURCES = readfile.c
readfile_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 \
- *.awk \
- doit \
- steps
+ *.awk
all: config.h
$(MAKE) $(AM_MAKEFLAGS) all-am
@@ -447,6 +456,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)
+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)
$(time_la_LINK) -rpath $(pkgextensiondir) $(time_la_OBJECTS) $(time_la_LIBADD) $(LIBS)
@@ -460,6 +471,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)/testext.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/time.Plo@am__quote@
.c.o:
diff --git a/extension/testext.c b/extension/testext.c
index 5b171e84..fa8dbf64 100644
--- a/extension/testext.c
+++ b/extension/testext.c
@@ -50,18 +50,20 @@ int plugin_is_GPL_compatible;
*/
/*
-@load testext
-BEGIN {
- dump_procinfo()
-}
+#@load "testext"
+#BEGIN {
+# dump_procinfo()
+#}
*/
static awk_value_t *
dump_procinfo(int nargs, awk_value_t *result)
{
/* get PROCINFO as flat array and print it */
+ return result;
}
/*
+@load "testext"
BEGIN {
testvar = "One Adam Twelve"
ret = var_test("testvar")
@@ -72,19 +74,45 @@ BEGIN {
static awk_value_t *
var_test(int nargs, awk_value_t *result)
{
- awk_value_t value;
+ awk_value_t value, value2;
+ awk_value_t *valp;
- if (nargs != 1 || result == NULL)
+ if (nargs != 1 || result == NULL) {
+ printf("var_test: nargs not right (%d should be 1) or result == NULL\n", nargs);
return NULL;
+ }
/* look up a reserved variable - should fail */
- if (sym_lookup("ARGC", & value, AWK_NUMBER) != NULL)
+ if (sym_lookup("ARGC", AWK_NUMBER, & value))
printf("var_test: sym_lookup of ARGC failed - got a value!\n");
else
printf("var_test: sym_lookup of ARGC passed\n");
/* look up variable whose name is passed in, should pass */
- /* change the value, should be reflected in awk script */
+ if (get_argument(0, AWK_STRING, & value)) {
+ if (sym_lookup(value.str_value.str, AWK_STRING, & value2)) {
+ /* change the value, should be reflected in awk script */
+ valp = make_number(42.0, & value2);
+
+ if (sym_update(value.str_value.str, valp)) {
+ printf("var_test: sym_update(\"%s\") succeeded\n", value.str_value.str);
+ } else {
+ printf("var_test: sym_update(\"%s\") failed\n", value.str_value.str);
+ return NULL;
+ }
+ } else {
+ printf("var_test: sym_lookup(\"%s\") failed\n", value.str_value.str);
+ return NULL;
+ }
+ } else {
+ printf("var_test: get_argument() failed\n");
+ return NULL;
+ }
+
+ result->val_type = AWK_NUMBER;
+ result->num_value = 1.0;
+
+ return result;
}
/*
@@ -97,7 +125,17 @@ BEGIN {
static awk_value_t *
test_errno(int nargs, awk_value_t *result)
{
+ if (nargs != 0 || result == NULL) {
+ printf("test_errno: nargs not right (%d should be 0) or result == NULL\n", nargs);
+ return NULL;
+ }
+
update_ERRNO_int(ECHILD);
+
+ result->val_type = AWK_NUMBER;
+ result->num_value = 1.0;
+
+ return result;
}
/*
@@ -105,7 +143,7 @@ BEGIN {
for (i = 1; i <= 10; i++)
test_array[i] = i + 2
- printf ("length of test_array is %d, should be 10\n", length(test_array)
+ printf ("length of test_array is %d, should be 10\n", length(test_array))
ret = test_array_size(test_array);
printf "test_array_size() returned %d, length is now %d\n", ret, length(test_array)
}
@@ -114,24 +152,62 @@ BEGIN {
static awk_value_t *
test_array_size(int nargs, awk_value_t *result)
{
+ awk_value_t value;
+ size_t count = 0;
+
+ if (nargs != 1 || result == NULL) {
+ printf("test_array_size: nargs not right (%d should be 0) or result == NULL\n", nargs);
+ return NULL;
+ }
+
/* get element count and print it; should match length(array) from awk script */
+ if (! get_argument(0, AWK_ARRAY, & value)) {
+ printf("test_array_size: get_argument failed\n");
+ return NULL;
+ }
+
+ if (! get_element_count(value.array_cookie, & count)) {
+ printf("test_array_size: get_element_count failed\n");
+ return NULL;
+ }
+
+ printf("test_array_size: incoming size is %lu\n", (unsigned long) count);
+
/* clear array - length(array) should then go to zero in script */
+ if (! clear_array(value.array_cookie)) {
+ printf("test_array_size: clear_array failed\n");
+ return NULL;
+ }
+
+ result->val_type = AWK_NUMBER;
+ result->num_value = 1.0;
+
+ return result;
}
/*
-BEGIN {
- n = split("one two three four five six", test_array2)
- ret = test_array_elem(test_array2, "3")
- printf "test_array_elem() returned %d, test_array2[3] = %g\n", ret, test_array2[3]
-}
+#BEGIN {
+# n = split("one two three four five six", test_array2)
+# ret = test_array_elem(test_array2, "3")
+# printf "test_array_elem() returned %d, test_array2[3] = %g\n", ret, test_array2[3]
+# if ("5" in test_array2)
+# printf "error: test_array_elem did not remove element \"5\"\n"
+# else
+# printf "test_array_elem did remove element \"5\"\n"
+#}
*/
static awk_value_t *
test_array_elem(int nargs, awk_value_t *result)
{
+ if (nargs != 2 || result == NULL) {
+ printf("test_array_elem: nargs not right (%d should be 2) or result == NULL\n", nargs);
+ return NULL;
+ }
/* look up an array element and print the value */
- /* change the element */
- /* delete another element */
+ /* change the element - "3" */
+ /* delete another element - "5" */
/* change and deletion should be reflected in awk script */
+ return result;
}
/*
@@ -148,7 +224,17 @@ BEGIN {
static awk_value_t *
print_do_lint(int nargs, awk_value_t *result)
{
+ if (nargs != 0 || result == NULL) {
+ printf("print_do_lint: nargs not right (%d should be 0) or result == NULL\n", nargs);
+ return NULL;
+ }
+
printf("print_do_lint: lint = %d\n", do_lint);
+
+ result->val_type = AWK_NUMBER;
+ result->num_value = 1.0;
+
+ return result;
}
static void at_exit0(void *data, int exit_status)
@@ -157,7 +243,7 @@ static void at_exit0(void *data, int exit_status)
if (data)
printf(" data = %p,", data);
else
- printf(" data = <null>,");
+ printf(" data = NULL,");
printf(" exit_status = %d\n", exit_status);
}
@@ -173,7 +259,7 @@ static void at_exit1(void *data, int exit_status)
else
printf(" (data is NOT & data_for_1),");
} else
- printf(" data = <null>,");
+ printf(" data = NULL,");
printf(" exit_status = %d\n", exit_status);
}
@@ -183,7 +269,7 @@ static void at_exit2(void *data, int exit_status)
if (data)
printf(" data = %p,", data);
else
- printf(" data = <null>,");
+ printf(" data = NULL,");
printf(" exit_status = %d\n", exit_status);
}
diff --git a/extension/time.c b/extension/time.c
index 09e71d0e..a12a05d6 100644
--- a/extension/time.c
+++ b/extension/time.c
@@ -116,7 +116,7 @@ do_sleep(int nargs, awk_value_t *result)
if (do_lint && nargs > 1)
lintwarn(ext_id, "sleep: called with too many arguments");
- if (get_argument(0, AWK_NUMBER, &num) == NULL) {
+ if (! get_argument(0, AWK_NUMBER, &num)) {
update_ERRNO_string("sleep: missing required numeric argument", 1);
return make_number(-1, result);
}
diff --git a/gawkapi.c b/gawkapi.c
index 885d514f..3f9159d9 100644
--- a/gawkapi.c
+++ b/gawkapi.c
@@ -42,6 +42,8 @@ api_get_argument(awk_ext_id_t id, size_t count,
if (result == NULL)
return false;
+ (void) id;
+
arg = (wanted == AWK_ARRAY
? get_array_argument(count, false)
: get_scalar_argument(count, false) );
@@ -81,10 +83,16 @@ awk_value_to_node(const awk_value_t *retval)
/* Functions to print messages */
/* FIXME: Code duplicate from msg.c. Fix this. */
+
+/* api_fatal --- print a fatal message and exit */
+
static void
api_fatal(awk_ext_id_t id, const char *format, ...)
{
va_list args;
+
+ (void) id;
+
va_start(args, format);
err(_("fatal: "), format, args);
va_end(args);
@@ -94,19 +102,29 @@ api_fatal(awk_ext_id_t id, const char *format, ...)
gawk_exit(EXIT_FATAL);
}
+/* api_warning --- print a warning message and exit */
+
static void
api_warning(awk_ext_id_t id, const char *format, ...)
{
va_list args;
+
+ (void) id;
+
va_start(args, format);
err(_("warning: "), format, args);
va_end(args);
}
+/* api_lintwarn --- print a lint warning message and exit if appropriate */
+
static void
api_lintwarn(awk_ext_id_t id, const char *format, ...)
{
va_list args;
+
+ (void) id;
+
va_start(args, format);
if (lintwarn == r_fatal) {
err(_("fatal: "), format, args);
@@ -121,31 +139,47 @@ api_lintwarn(awk_ext_id_t id, const char *format, ...)
}
}
-/* Register an open hook; for opening files read-only */
+/* api_register_open_hook --- register an open hook; for opening files read-only */
static void
api_register_open_hook(awk_ext_id_t id, void* (*open_func)(IOBUF *))
{
+ (void) id;
+
register_open_hook(open_func);
}
/* Functions to update ERRNO */
+
+/* api_update_ERRNO_int --- update ERRNO with an integer value */
+
static void
api_update_ERRNO_int(awk_ext_id_t id, int errno_val)
{
+ (void) id;
+
update_ERRNO_int(errno_val);
}
+/* api_update_ERRNO_string --- update ERRNO with a string value */
+
static void
-api_update_ERRNO_string(awk_ext_id_t id, const char *string,
- awk_bool_t translate)
+api_update_ERRNO_string(awk_ext_id_t id,
+ const char *string,
+ awk_bool_t translate)
{
+ (void) id;
+
update_ERRNO_string(string, (translate ? TRANSLATE : DONT_TRANSLATE));
}
+/* api_unset_ERRNO --- unset ERRNO */
+
static void
api_unset_ERRNO(awk_ext_id_t id)
{
+ (void) id;
+
unset_ERRNO();
}
@@ -157,6 +191,9 @@ api_add_ext_func(awk_ext_id_t id,
const awk_ext_func_t *func,
const char *namespace)
{
+ (void) id;
+ (void) namespace;
+
return make_builtin(func);
}
@@ -193,6 +230,8 @@ api_awk_atexit(awk_ext_id_t id,
{
struct ext_exit_handler *p;
+ (void) id;
+
/* allocate memory */
emalloc(p, struct ext_exit_handler *, sizeof(struct ext_exit_handler), "api_awk_atexit");
@@ -300,6 +339,9 @@ node_to_awk_value(NODE *node, awk_value_t *val, awk_valtype_t wanted)
* In the latter case, fills in vaule->val_type with the real type.
* Built-in variables (except PROCINFO) may not be accessed by an extension.
*/
+
+/* api_sym_lookup --- look up a symbol */
+
static awk_bool_t
api_sym_lookup(awk_ext_id_t id,
const char *name,
@@ -318,27 +360,13 @@ api_sym_lookup(awk_ext_id_t id,
return node_to_awk_value(node, result, wanted);
}
-/* api_sym_update --- update a value, see gawkapi.h for semantics */
+/* api_sym_update --- update a symbol's value, see gawkapi.h for semantics */
static awk_bool_t
api_sym_update(awk_ext_id_t id, const char *name, awk_value_t *value)
{
NODE *node;
- if ( name == NULL
- || *name == '\0'
- || value == NULL
- || is_off_limits_var(name)) /* most built-in vars not allowed */
- return false;
-
- node = lookup(name);
-
- if (node == NULL) {
- /* new value to be installed */
- } else {
- /* existing value to be updated */
- }
-
switch (value->val_type) {
case AWK_NUMBER:
case AWK_STRING:
@@ -349,11 +377,27 @@ api_sym_update(awk_ext_id_t id, const char *name, awk_value_t *value)
return false;
default:
- fatal(_("api_sym_update: invalid value for type of new value (%d)"), value->val_type);
+ /* fatal(_("api_sym_update: invalid value for type of new value (%d)"), value->val_type); */
return false;
}
- return true; /* for now */
+ if ( name == NULL
+ || *name == '\0'
+ || is_off_limits_var(name) /* most built-in vars not allowed */
+ || value == NULL)
+ return false;
+
+ node = lookup(name);
+
+ if (node == NULL) {
+ /* new value to be installed */
+ node = install_symbol((char *) name, Node_var);
+ }
+ unref(node->var_value);
+
+ node->var_value = awk_value_to_node(value);
+
+ return true;
}
/* Array management */
@@ -366,6 +410,21 @@ api_get_array_element(awk_ext_id_t id,
awk_array_t a_cookie, const awk_value_t *const index,
awk_valtype_t wanted, awk_value_t *result)
{
+ NODE *array;
+ NODE *subscript;
+
+ /* don't check for index len zero, null str is ok as index */
+ if ( a_cookie == NULL
+ || result == NULL
+ || index == NULL
+ || index->val_type != AWK_STRING
+ || index->str_value.str == NULL)
+ return false;
+
+ array = (NODE *) a_cookie;
+ subscript = awk_value_to_node(index);
+ /* FIXME: write rest of code */
+
return true; /* for now */
}
@@ -381,6 +440,12 @@ api_set_array_element(awk_ext_id_t id, awk_array_t a_cookie,
NODE *tmp;
NODE **aptr;
+ /* don't check for index len zero, null str is ok as index */
+ if ( a_cookie == NULL
+ || element == NULL
+ || element->index.str == NULL)
+ return false;
+
tmp = make_string(element->index.str, element->index.len);
aptr = assoc_lookup(array, tmp);
unref(tmp);
@@ -410,10 +475,10 @@ api_get_element_count(awk_ext_id_t id,
{
NODE *node = (NODE *) a_cookie;
- if (node == NULL || node->type != Node_var_array)
+ if (count == NULL || node == NULL || node->type != Node_var_array)
return false;
- *count = node->array_size;
+ *count = node->table_size;
return true;
}
diff --git a/main.c b/main.c
index 91da77d7..b3f7f9ec 100644
--- a/main.c
+++ b/main.c
@@ -731,7 +731,7 @@ out:
if (extra_stack)
efree(extra_stack);
- exit(exit_val); /* more portable */
+ final_exit(exit_val);
return exit_val; /* to suppress warnings */
}
@@ -1318,7 +1318,7 @@ arg_assign(char *arg, bool initing)
var = variable(0, cp2, Node_var);
if (var == NULL) /* error */
- exit(EXIT_FATAL);
+ final_exit(EXIT_FATAL);
if (var->type == Node_var && var->var_update)
var->var_update();
lhs = get_lhs(var, false);
diff --git a/msg.c b/msg.c
index 22cf5562..b94e840b 100644
--- a/msg.c
+++ b/msg.c
@@ -159,6 +159,14 @@ gawk_exit(int status)
longjmp(fatal_tag, 1);
}
+ final_exit(status);
+}
+
+/* final_exit --- run extension exit handlers and exit */
+
+void
+final_exit(int status)
+{
/* run any extension exit handlers */
run_ext_exit_handlers(status);
diff --git a/profile.c b/profile.c
index 15c9879b..16aa1cdd 100644
--- a/profile.c
+++ b/profile.c
@@ -922,7 +922,7 @@ static RETSIGTYPE
dump_and_exit(int signum)
{
just_dump(signum);
- exit(EXIT_FAILURE);
+ final_exit(EXIT_FAILURE);
}