diff options
author | Arnold D. Robbins <arnold@skeeve.com> | 2012-11-25 21:54:48 +0200 |
---|---|---|
committer | Arnold D. Robbins <arnold@skeeve.com> | 2012-11-25 21:54:48 +0200 |
commit | 9a9ff61bbd952c1263b55f82a269da5b09289a6b (patch) | |
tree | 4bc31b31d0bec6d27f77e55f1a88f50534fa6ed4 /ext.c | |
parent | dbabe5a569ad82a9faeb2f121e387ec6399f9dcb (diff) | |
parent | 7af1da783175273a26609911c3a95975ed0f5c13 (diff) | |
download | egawk-9a9ff61bbd952c1263b55f82a269da5b09289a6b.tar.gz egawk-9a9ff61bbd952c1263b55f82a269da5b09289a6b.tar.bz2 egawk-9a9ff61bbd952c1263b55f82a269da5b09289a6b.zip |
Merge branch 'master' into array-iface
Diffstat (limited to 'ext.c')
-rw-r--r-- | ext.c | 195 |
1 files changed, 157 insertions, 38 deletions
@@ -32,11 +32,53 @@ extern SRCFILE *srcfiles; #ifdef DYNAMIC -#define INIT_FUNC "dlload" -#define FINI_FUNC "dlunload" +#define OLD_INIT_FUNC "dlload" +#define OLD_FINI_FUNC "dlunload" #include <dlfcn.h> +#define INIT_FUNC "dl_load" + +/* load_ext --- load an external library */ + +void +load_ext(const char *lib_name) +{ + int (*install_func)(const gawk_api_t *const, awk_ext_id_t); + void *dl; + int flags = RTLD_LAZY; + int *gpl_compat; + + if (do_sandbox) + fatal(_("extensions are not allowed in sandbox mode")); + + if (do_traditional || do_posix) + fatal(_("-l / @load are gawk extensions")); + + if (lib_name == NULL) + fatal(_("load_ext: received NULL lib_name")); + + if ((dl = dlopen(lib_name, flags)) == NULL) + fatal(_("load_ext: cannot open library `%s' (%s)\n"), lib_name, + dlerror()); + + /* Per the GNU Coding standards */ + gpl_compat = (int *) dlsym(dl, "plugin_is_GPL_compatible"); + if (gpl_compat == NULL) + fatal(_("load_ext: library `%s': does not define `plugin_is_GPL_compatible' (%s)\n"), + lib_name, dlerror()); + + 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 (install_func(& api_impl, NULL /* ext_id */) == 0) + warning(_("load_ext: library `%s' initialization routine `%s' failed\n"), + lib_name, INIT_FUNC); +} + /* do_ext --- load an extension at run-time: interface to load_ext */ NODE * @@ -59,7 +101,7 @@ do_ext(int nargs) s = add_srcfile(SRC_EXTLIB, obj->stptr, srcfiles, NULL, NULL); if (s != NULL) - ret = load_ext(s, init_func, fini_func, obj); + ret = load_old_ext(s, init_func, fini_func, obj); DEREF(obj); if (fini != NULL) @@ -74,20 +116,20 @@ do_ext(int nargs) /* load_ext --- load an external library */ NODE * -load_ext(SRCFILE *s, const char *init_func, const char *fini_func, NODE *obj) +load_old_ext(SRCFILE *s, const char *init_func, const char *fini_func, NODE *obj) { - NODE *tmp = NULL; NODE *(*func)(NODE *, void *); + NODE *tmp; 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; + init_func = OLD_INIT_FUNC; if (fini_func == NULL || fini_func[0] == '\0') - fini_func = FINI_FUNC; + fini_func = OLD_FINI_FUNC; if (do_sandbox) fatal(_("extensions are not allowed in sandbox mode")); @@ -95,9 +137,8 @@ load_ext(SRCFILE *s, const char *init_func, const char *fini_func, NODE *obj) if (do_traditional || do_posix) fatal(_("`extension' is a gawk extension")); -#ifdef RTLD_GLOBAL - flags |= RTLD_GLOBAL; -#endif + if (lib_name == NULL) + fatal(_("load_ext: received NULL lib_name")); if ((dl = dlopen(s->fullpath, flags)) == NULL) fatal(_("extension: cannot open library `%s' (%s)"), lib_name, @@ -129,22 +170,24 @@ load_ext(SRCFILE *s, const char *init_func, const char *fini_func, NODE *obj) /* make_builtin --- register name to be called as func with a builtin body */ -void -make_builtin(const char *name, NODE *(*func)(int), int count) +awk_bool_t +make_builtin(const awk_ext_func_t *funcinfo) { NODE *symbol, *f; INSTRUCTION *b; const char *sp; char c; + const char *name = funcinfo->name; + int count = funcinfo->num_expected_args; sp = name; if (sp == NULL || *sp == '\0') - fatal(_("extension: missing function name")); + fatal(_("make_builtin: 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); + fatal(_("make_builtin: illegal character `%c' in function name `%s'"), c, name); } f = lookup(name); @@ -152,31 +195,120 @@ make_builtin(const char *name, NODE *(*func)(int), int count) if (f != NULL) { if (f->type == Node_func) { /* user-defined function */ - fatal(_("extension: can't redefine function `%s'"), name); + fatal(_("make_builtin: can't redefine function `%s'"), name); } else if (f->type == Node_ext_func) { /* multiple extension() calls etc. */ if (do_lint) - lintwarn(_("extension: function `%s' already defined"), name); - return; + lintwarn(_("make_builtin: function `%s' already defined"), name); + return false; } else /* variable name etc. */ - fatal(_("extension: function name `%s' previously defined"), name); + fatal(_("make_builtin: function name `%s' previously defined"), name); } else if (check_special(name) >= 0) - fatal(_("extension: can't use gawk built-in `%s' as function name"), name); + fatal(_("make_builtin: can't use gawk built-in `%s' as function name"), name); if (count < 0) fatal(_("make_builtin: negative argument count for function `%s'"), name); b = bcalloc(Op_symbol, 1, 0); - b->builtin = func; + b->extfunc = funcinfo->function; b->expr_count = count; /* NB: extension sub must return something */ symbol = install_symbol(estrdup(name, strlen(name)), Node_ext_func); symbol->code_ptr = b; + track_ext_func(name); + return true; +} + +#if 0 +/* make_old_builtin --- register name to be called as func with a builtin body */ + +void +make_old_builtin(const char *, NODE *(*)(int), int) /* temporary */ +{ + NODE *p, *symbol, *f; + INSTRUCTION *b, *r; + const char *sp; + char *pname; + char **vnames = NULL; + char c, buf[200]; + size_t space_needed; + int i; + + sp = name; + if (sp == NULL || *sp == '\0') + fatal(_("extension: missing function name")); + + while ((c = *sp++) != '\0') { + if ((sp == &name[1] && c != '_' && ! isalpha((unsigned char) c)) + || (sp > &name[1] && ! is_identchar((unsigned char) c))) + fatal(_("make_old_builtin: illegal character `%c' in function name `%s'"), c, name); + } + + f = lookup(name); + + if (f != NULL) { + if (f->type == Node_func) { + INSTRUCTION *pc = f->code_ptr; + if (pc->opcode != Op_ext_func) /* user-defined function */ + fatal(_("extension: can't redefine function `%s'"), name); + else { + /* multiple extension() calls etc. */ + if (do_lint) + lintwarn(_("extension: function `%s' already defined"), name); + return; + } + } else + /* variable name etc. */ + fatal(_("extension: function name `%s' previously defined"), name); + } else if (check_special(name) >= 0) + fatal(_("extension: can't use gawk built-in `%s' as function name"), name); + /* count parameters, create artificial list of param names */ + + if (count < 0) + fatal(_("make_builtin: negative argument count for function `%s'"), + name); + + if (count > 0) { + sprintf(buf, "p%d", count); + space_needed = strlen(buf) + 1; + emalloc(vnames, char **, count * sizeof(char *), "make_builtin"); + for (i = 0; i < count; i++) { + emalloc(pname, char *, space_needed, "make_builtin"); + sprintf(pname, "p%d", i); + vnames[i] = pname; + } + } + + + getnode(p); + p->type = Node_param_list; + p->flags |= FUNC; + /* get our own copy for name */ + p->param = estrdup(name, strlen(name)); + p->param_cnt = count; + + /* actual source and line numbers set at runtime for these instructions */ + b = bcalloc(Op_builtin, 1, __LINE__); + b->builtin = func; + b->expr_count = count; + b->nexti = bcalloc(Op_K_return, 1, __LINE__); + r = bcalloc(Op_ext_func, 1, __LINE__); + r->source_file = __FILE__; + r->nexti = b; + + /* NB: extension sub must return something */ + + symbol = mk_symbol(Node_func, p); + symbol->parmlist = vnames; + symbol->code_ptr = r; + r->func_body = symbol; + (void) install_symbol(p->param, symbol); } +#endif /* get_argument --- get the i'th argument of a dynamically linked function */ @@ -214,7 +346,7 @@ get_argument(int i) */ NODE * -get_actual_argument(int i, int optional, int want_array) +get_actual_argument(int i, bool optional, bool want_array) { NODE *t; char *fname; @@ -238,7 +370,7 @@ get_actual_argument(int i, int optional, int want_array) if (t->type == Node_var_new) { if (want_array) - return force_array(t, FALSE); + return force_array(t, false); else { t->type = Node_var; t->var_value = dupnode(Nnull_string); @@ -261,25 +393,12 @@ get_actual_argument(int i, int optional, int want_array) #else -/* do_ext --- dummy version if extensions not available */ - -NODE * -do_ext(int nargs) -{ - const char *emsg = _("Operation Not Supported"); - - unref(ERRNO_node->var_value); - ERRNO_node->var_value = make_string(emsg, strlen(emsg)); - return make_number((AWKNUM) -1); -} - /* load_ext --- dummy version if extensions not available */ -NODE * -load_ext(const char *lib_name, const char *init_func, NODE *obj) +void +load_ext(const char *lib_name) { fatal(_("dynamic loading of library not supported")); - return NULL; } #endif |