aboutsummaryrefslogtreecommitdiffstats
path: root/ext.c
diff options
context:
space:
mode:
authorArnold D. Robbins <arnold@skeeve.com>2012-11-25 21:54:48 +0200
committerArnold D. Robbins <arnold@skeeve.com>2012-11-25 21:54:48 +0200
commit9a9ff61bbd952c1263b55f82a269da5b09289a6b (patch)
tree4bc31b31d0bec6d27f77e55f1a88f50534fa6ed4 /ext.c
parentdbabe5a569ad82a9faeb2f121e387ec6399f9dcb (diff)
parent7af1da783175273a26609911c3a95975ed0f5c13 (diff)
downloadegawk-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.c195
1 files changed, 157 insertions, 38 deletions
diff --git a/ext.c b/ext.c
index dc312cce..d861b82a 100644
--- a/ext.c
+++ b/ext.c
@@ -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