diff options
-rw-r--r-- | ChangeLog | 18 | ||||
-rw-r--r-- | awk.h | 1 | ||||
-rw-r--r-- | ext.c | 9 | ||||
-rw-r--r-- | extension/ChangeLog | 10 | ||||
-rw-r--r-- | extension/Makefile.am | 7 | ||||
-rw-r--r-- | extension/Makefile.in | 22 | ||||
-rw-r--r-- | extension/testext.c | 124 | ||||
-rw-r--r-- | extension/time.c | 2 | ||||
-rw-r--r-- | gawkapi.c | 109 | ||||
-rw-r--r-- | main.c | 4 | ||||
-rw-r--r-- | msg.c | 8 | ||||
-rw-r--r-- | profile.c | 2 |
12 files changed, 258 insertions, 58 deletions
@@ -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. @@ -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; @@ -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); } @@ -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; } @@ -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); @@ -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); @@ -922,7 +922,7 @@ static RETSIGTYPE dump_and_exit(int signum) { just_dump(signum); - exit(EXIT_FAILURE); + final_exit(EXIT_FAILURE); } |