diff options
author | john haque <j.eh@mchsi.com> | 2012-04-21 05:52:19 -0500 |
---|---|---|
committer | john haque <j.eh@mchsi.com> | 2012-04-21 05:52:19 -0500 |
commit | 1a4aaf18f5ec6149315aabc53dbe667f1abfdb62 (patch) | |
tree | 5c7ad893e1621b7006566f31d8d16707a0258436 | |
parent | 87dc23679566c5ad96f4869de6aec39c2a4c3aa7 (diff) | |
download | egawk-1a4aaf18f5ec6149315aabc53dbe667f1abfdb62.tar.gz egawk-1a4aaf18f5ec6149315aabc53dbe667f1abfdb62.tar.bz2 egawk-1a4aaf18f5ec6149315aabc53dbe667f1abfdb62.zip |
Add optional shutdown routine for an extension lib.
-rw-r--r-- | ChangeLog | 23 | ||||
-rw-r--r-- | awk.h | 13 | ||||
-rw-r--r-- | awkgram.c | 2 | ||||
-rw-r--r-- | awkgram.y | 2 | ||||
-rw-r--r-- | debug.c | 2 | ||||
-rw-r--r-- | ext.c | 75 | ||||
-rw-r--r-- | interpret.h | 11 | ||||
-rw-r--r-- | main.c | 2 | ||||
-rw-r--r-- | msg.c | 4 |
9 files changed, 100 insertions, 34 deletions
@@ -1,3 +1,26 @@ +2012-04-21 John Haque <j.eh@mchsi.com> + + Shutdown routine for a dynamic extension. + + * awk.h (SRCFILE): New field fini_func. + * ext.c (load_ext): Takes an additional argument to look up and + save the clean up routine in SRCFILE struct. + (INIT_FUNC, FINI_FUNC): Defines for default init and fini routine + names. + (do_ext): Use default for the name of the init or fini routine if + one is not supplied. Adjust call to load_ext(). + (close_extensions): Execute fini routines. + * interpret.h (Op_at_exit): Call close_extensions(). + * msg.c (gawk_exit): Ditto. + * debug.c (close_all): Ditto. + * main.c (main): Adjust call to load_ext(). + * awkgram.y (tokentab): Specify 2nd and 3rd optional arguments + for the extension() built-in. + + Unrelated: + + * interpret.h (Op_arrayfor_init): Use assoc_length for array size. + 2012-04-19 John Haque <j.eh@mchsi.com> Enhanced array interface to support transparent implementation @@ -953,6 +953,8 @@ typedef struct srcfile { int fd; int maxlen; /* size of the longest line */ + void (*fini_func)(); /* dynamic extension of type SRC_EXTLIB */ + char *lexptr; char *lexend; char *lexeme; @@ -1488,12 +1490,13 @@ extern STACK_ITEM *grow_stack(void); extern void dump_fcall_stack(FILE *fp); extern int register_exec_hook(Func_pre_exec preh, Func_post_exec posth); /* ext.c */ -NODE *do_ext(int nargs); -NODE *load_ext(const char *lib_name, const char *init_func, NODE *obj); +extern NODE *do_ext(int nargs); +extern NODE *load_ext(SRCFILE *s, const char *init_func, const char *fini_func, NODE *obj); +extern void close_extensions(void); #ifdef DYNAMIC -void make_builtin(const char *, NODE *(*)(int), int); -NODE *get_argument(int); -NODE *get_actual_argument(int, int, int); +extern void make_builtin(const char *, NODE *(*)(int), int); +extern NODE *get_argument(int); +extern NODE *get_actual_argument(int, int, int); #define get_scalar_argument(i, opt) get_actual_argument((i), (opt), FALSE) #define get_array_argument(i, opt) get_actual_argument((i), (opt), TRUE) #endif @@ -4519,7 +4519,7 @@ static const struct token tokentab[] = { {"eval", Op_symbol, LEX_EVAL, 0, 0, 0}, {"exit", Op_K_exit, LEX_EXIT, 0, 0, 0}, {"exp", Op_builtin, LEX_BUILTIN, A(1), do_exp, MPF(exp)}, -{"extension", Op_builtin, LEX_BUILTIN, GAWKX|A(2), do_ext, 0}, +{"extension", Op_builtin, LEX_BUILTIN, GAWKX|A(1)|A(2)|A(3), do_ext, 0}, {"fflush", Op_builtin, LEX_BUILTIN, RESX|A(0)|A(1), do_fflush, 0}, {"for", Op_K_for, LEX_FOR, BREAK|CONTINUE, 0, 0}, {"func", Op_func, LEX_FUNCTION, NOT_POSIX|NOT_OLD, 0, 0}, @@ -1822,7 +1822,7 @@ static const struct token tokentab[] = { {"eval", Op_symbol, LEX_EVAL, 0, 0, 0}, {"exit", Op_K_exit, LEX_EXIT, 0, 0, 0}, {"exp", Op_builtin, LEX_BUILTIN, A(1), do_exp, MPF(exp)}, -{"extension", Op_builtin, LEX_BUILTIN, GAWKX|A(2), do_ext, 0}, +{"extension", Op_builtin, LEX_BUILTIN, GAWKX|A(1)|A(2)|A(3), do_ext, 0}, {"fflush", Op_builtin, LEX_BUILTIN, RESX|A(0)|A(1), do_fflush, 0}, {"for", Op_K_for, LEX_FOR, BREAK|CONTINUE, 0, 0}, {"func", Op_func, LEX_FUNCTION, NOT_POSIX|NOT_OLD, 0, 0}, @@ -5344,6 +5344,8 @@ close_all() } } + close_extensions(); + set_gawk_output(NULL); /* closes output_fp if not stdout */ } @@ -28,28 +28,44 @@ */ #include "awk.h" +extern SRCFILE *srcfiles; #ifdef DYNAMIC +#define INIT_FUNC "dlload" +#define FINI_FUNC "dlunload" + #include <dlfcn.h> /* do_ext --- load an extension at run-time: interface to load_ext */ - + NODE * do_ext(int nargs) { - NODE *obj, *fun, *ret = NULL; + NODE *obj, *init = NULL, *fini = NULL, *ret = NULL; SRCFILE *s; - extern SRCFILE *srcfiles; + char *init_func = NULL; + char *fini_func = NULL; - fun = POP_STRING(); + if (nargs == 3) { + fini = POP_STRING(); + fini_func = fini->stptr; + } + if (nargs >= 2) { + init = POP_STRING(); + init_func = init->stptr; + } obj = POP_STRING(); s = add_srcfile(SRC_EXTLIB, obj->stptr, srcfiles, NULL, NULL); if (s != NULL) - ret = load_ext(s->fullpath, fun->stptr, obj); + ret = load_ext(s, init_func, fini_func, obj); + DEREF(obj); - DEREF(fun); + if (fini != NULL) + DEREF(fini); + if (init != NULL) + DEREF(init); if (ret == NULL) ret = dupnode(Nnull_string); return ret; @@ -58,13 +74,20 @@ do_ext(int nargs) /* load_ext --- load an external library */ NODE * -load_ext(const char *lib_name, const char *init_func, NODE *obj) +load_ext(SRCFILE *s, const char *init_func, const char *fini_func, NODE *obj) { NODE *tmp = NULL; NODE *(*func)(NODE *, void *); void *dl; int flags = RTLD_LAZY; int *gpl_compat; + const char *lib_name = s->fullpath; + + if (init_func == NULL || init_func[0] == '\0') + init_func = INIT_FUNC; + + if (fini_func == NULL || fini_func[0] == '\0') + fini_func = FINI_FUNC; if (do_sandbox) fatal(_("extensions are not allowed in sandbox mode")); @@ -76,18 +99,18 @@ load_ext(const char *lib_name, const char *init_func, NODE *obj) flags |= RTLD_GLOBAL; #endif - if ((dl = dlopen(lib_name, flags)) == NULL) - fatal(_("extension: cannot open library `%s' (%s)\n"), lib_name, + if ((dl = dlopen(s->fullpath, flags)) == NULL) + fatal(_("extension: cannot open library `%s' (%s)"), lib_name, dlerror()); /* Per the GNU Coding standards */ gpl_compat = (int *) dlsym(dl, "plugin_is_GPL_compatible"); if (gpl_compat == NULL) - fatal(_("extension: library `%s': does not define `plugin_is_GPL_compatible' (%s)\n"), + fatal(_("extension: library `%s': does not define `plugin_is_GPL_compatible' (%s)"), lib_name, dlerror()); func = (NODE *(*)(NODE *, void *)) dlsym(dl, init_func); if (func == NULL) - fatal(_("extension: library `%s': cannot call function `%s' (%s)\n"), + fatal(_("extension: library `%s': cannot call function `%s' (%s)"), lib_name, init_func, dlerror()); if (obj == NULL) { @@ -95,11 +118,12 @@ load_ext(const char *lib_name, const char *init_func, NODE *obj) tmp = (*func)(obj, dl); unref(tmp); unref(obj); - return NULL; - } + tmp = NULL; + } else + tmp = (*func)(obj, dl); - tmp = (*func)(obj, dl); - return tmp; + s->fini_func = (void (*)(void)) dlsym(dl, fini_func); + return tmp; } @@ -118,7 +142,7 @@ make_builtin(const char *name, NODE *(*func)(int), int count) fatal(_("extension: missing function name")); while ((c = *sp++) != '\0') { - if ((sp == &name[1] && c != '_' && ! isalpha((unsigned char) c)) + if ((sp == & name[1] && c != '_' && ! isalpha((unsigned char) c)) || (sp > &name[1] && ! is_identchar((unsigned char) c))) fatal(_("extension: illegal character `%c' in function name `%s'"), c, name); } @@ -184,9 +208,10 @@ get_argument(int i) } -/* get_actual_argument --- get the i'th scalar or array argument of a - dynamically linked function, allowed to be optional. -*/ +/* + * get_actual_argument --- get the i'th scalar or array argument of a + * dynamically linked function, allowed to be optional. + */ NODE * get_actual_argument(int i, int optional, int want_array) @@ -257,3 +282,15 @@ load_ext(const char *lib_name, const char *init_func, NODE *obj) return NULL; } #endif + +/* close_extensions --- execute extension cleanup routines */ + +void +close_extensions() +{ + SRCFILE *s; + + for (s = srcfiles->next; s != srcfiles; s = s->next) + if (s->stype == SRC_EXTLIB && s->fini_func) + (*s->fini_func)(); +} diff --git a/interpret.h b/interpret.h index 0b830010..2fed2243 100644 --- a/interpret.h +++ b/interpret.h @@ -106,6 +106,8 @@ top: */ if (stdio_problem && ! exiting && exit_val == 0) exit_val = 1; + + close_extensions(); } break; @@ -763,12 +765,6 @@ mod: /* get the array */ array = POP_ARRAY(); - /* sanity: check if empty */ - if (assoc_empty(array)) - goto arrayfor; - - num_elems = array->table_size; - if (sorted_in == NULL) /* do this once */ sorted_in = make_string("sorted_in", 9); @@ -788,7 +784,8 @@ mod: list = assoc_list(array, how_to_sort, SORTED_IN); -arrayfor: + num_elems = assoc_length(array); + getnode(r); r->type = Node_arrayfor; r->for_list = list; @@ -637,7 +637,7 @@ out: /* load extension libs */ for (s = srcfiles->next; s != srcfiles; s = s->next) { if (s->stype == SRC_EXTLIB) - (void) load_ext(s->fullpath, "dlload", NULL); + (void) load_ext(s, NULL, NULL, NULL); else have_srcfile++; } @@ -158,5 +158,9 @@ gawk_exit(int status) exit_val = status; longjmp(fatal_tag, 1); } + + /* we could close_io() here */ + close_extensions(); + exit(status); } |