aboutsummaryrefslogtreecommitdiffstats
path: root/ext.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext.c')
-rw-r--r--ext.c249
1 files changed, 85 insertions, 164 deletions
diff --git a/ext.c b/ext.c
index f3e783da..5fc16afe 100644
--- a/ext.c
+++ b/ext.c
@@ -33,229 +33,153 @@
#include <dlfcn.h>
-/* do_ext --- load an extension */
+#define INIT_FUNC "dl_load"
-NODE *
-do_ext(int nargs)
+/* load_ext --- load an external library */
+
+void
+load_ext(const char *lib_name)
{
- NODE *obj;
- NODE *fun;
- NODE *tmp = NULL;
- NODE *(*func)(NODE *, void *);
+ int (*install_func)(const gawk_api_t *const, awk_ext_id_t);
void *dl;
int flags = RTLD_LAZY;
- int fatal_error = FALSE;
int *gpl_compat;
-#if 0
- static short warned = FALSE;
-#endif
if (do_sandbox)
fatal(_("extensions are not allowed in sandbox mode"));
-#if 0
- /* already done in parser */
- if (do_lint && ! warned) {
- warned = TRUE;
- lintwarn(_("`extension' is a gawk extension"));
- }
-#endif
-
if (do_traditional || do_posix)
- error(_("`extension' is a gawk extension"));
+ fatal(_("-l / @load are gawk extensions"));
- fun = POP_STRING();
- obj = POP_STRING();
+ if (lib_name == NULL)
+ fatal(_("load_ext: received NULL lib_name"));
-#ifdef RTLD_GLOBAL
- flags |= RTLD_GLOBAL;
-#endif
- if ((dl = dlopen(obj->stptr, flags)) == NULL) {
- /* fatal needs `obj', and we need to deallocate it! */
- msg(_("fatal: extension: cannot open `%s' (%s)\n"), obj->stptr,
+ if ((dl = dlopen(lib_name, flags)) == NULL)
+ fatal(_("load_ext: cannot open library `%s' (%s)\n"), lib_name,
dlerror());
- fatal_error = TRUE;
- goto done;
- }
/* Per the GNU Coding standards */
gpl_compat = (int *) dlsym(dl, "plugin_is_GPL_compatible");
- if (gpl_compat == NULL) {
- msg(_("fatal: extension: library `%s': does not define `plugin_is_GPL_compatible' (%s)\n"),
- obj->stptr, dlerror());
- fatal_error = TRUE;
- goto done;
- }
-
-
- func = (NODE *(*)(NODE *, void *)) dlsym(dl, fun->stptr);
- if (func == NULL) {
- msg(_("fatal: extension: library `%s': cannot call function `%s' (%s)\n"),
- obj->stptr, fun->stptr, dlerror());
- fatal_error = TRUE;
- goto done;
- }
-
- tmp = (*func)(obj, dl);
- if (tmp == NULL)
- tmp = Nnull_string;
-done:
- DEREF(obj);
- DEREF(fun);
- if (fatal_error)
- gawk_exit(EXIT_FATAL);
- return tmp;
+ 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);
}
/* 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 *p, *symbol, *f;
- INSTRUCTION *b, *r;
+ NODE *symbol, *f;
+ INSTRUCTION *b;
const char *sp;
- char *pname;
- char **vnames = NULL;
- char c, buf[200];
- size_t space_needed;
- int i;
+ 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))
|| (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);
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;
- }
+ /* user-defined function */
+ fatal(_("make_builtin: can't redefine function `%s'"), name);
+ } else if (f->type == Node_ext_func) {
+ /* multiple extension() calls etc. */
+ if (do_lint)
+ 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);
- /* count parameters, create artificial list of param names */
+ 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);
-
- 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;
- }
- }
-
+ name);
- 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 = bcalloc(Op_symbol, 1, 0);
+ b->extfunc = funcinfo->function;
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);
+ symbol = install_symbol(estrdup(name, strlen(name)), Node_ext_func);
+ symbol->code_ptr = b;
+ track_ext_func(name);
+ return true;
}
-/* get_curfunc_arg_count --- return number actual parameters */
-
-size_t
-get_curfunc_arg_count()
-{
- size_t argc;
- INSTRUCTION *pc;
-
- pc = (INSTRUCTION *) frame_ptr->reti; /* Op_func_call instruction */
- argc = (pc + 1)->expr_count; /* # of arguments supplied */
- return argc;
-}
-
-
-/* get_argument --- get the n'th argument of a dynamically linked function */
+/* get_argument --- get the i'th argument of a dynamically linked function */
NODE *
get_argument(int i)
{
- int pcount;
- NODE *t, *f;
- int actual_args;
+ NODE *t;
+ int arg_count, pcount;
INSTRUCTION *pc;
- f = frame_ptr->func_node;
- pcount = f->lnode->param_cnt;
+ pc = TOP()->code_ptr; /* Op_ext_builtin instruction */
+ pcount = (pc + 1)->expr_count; /* max # of arguments */
+ arg_count = pc->expr_count; /* # of arguments supplied */
- pc = (INSTRUCTION *) frame_ptr->reti; /* Op_func_call instruction */
- actual_args = (pc + 1)->expr_count; /* # of arguments supplied */
-
- if (i < 0 || i >= pcount || i >= actual_args)
+ if (i < 0 || i >= pcount || i >= arg_count)
return NULL;
- t = GET_PARAM(i);
+ t = PEEK(arg_count - i);
+ if (t->type == Node_param_list)
+ t = GET_PARAM(t->param_cnt);
if (t->type == Node_array_ref)
- return t->orig_array; /* Node_var_new or Node_var_array */
- if (t->type == Node_var_new || t->type == Node_var_array)
- return t;
- return t->var_value;
+ t = t->orig_array;
+ if (t->type == Node_var) /* See Case Node_var in setup_frame(), eval.c */
+ return Nnull_string;
+ /* Node_var_new, Node_var_array or Node_val */
+ return t;
}
-/* get_actual_argument --- get a scalar or array, 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)
+get_actual_argument(int i, bool optional, bool want_array)
{
- /* optional : if TRUE and i th argument not present return NULL, else fatal. */
-
- NODE *t, *f;
- int pcount;
+ NODE *t;
char *fname;
-
+ int pcount;
+ INSTRUCTION *pc;
+
+ pc = TOP()->code_ptr; /* Op_ext_builtin instruction */
+ fname = (pc + 1)->func_name;
+ pcount = (pc + 1)->expr_count;
+
t = get_argument(i);
-
- f = frame_ptr->func_node;
- pcount = f->lnode->param_cnt;
- fname = f->lnode->param;
-
if (t == NULL) {
- if (i >= pcount) /* must be fatal */
+ if (i >= pcount) /* must be fatal */
fatal(_("function `%s' defined to take no more than %d argument(s)"),
fname, pcount);
if (! optional)
@@ -266,11 +190,11 @@ get_actual_argument(int i, int optional, int want_array)
if (t->type == Node_var_new) {
if (want_array)
- return get_array(t, FALSE);
+ return get_array(t, false);
else {
t->type = Node_var;
- t->var_value = Nnull_string;
- return Nnull_string;
+ t->var_value = dupnode(Nnull_string);
+ return t->var_value;
}
}
@@ -283,20 +207,17 @@ get_actual_argument(int i, int optional, int want_array)
fatal(_("function `%s': argument #%d: attempt to use array as a scalar"),
fname, i + 1);
}
+ assert(t->type == Node_var_array || t->type == Node_val);
return t;
}
#else
-/* do_ext --- dummy version if extensions not available */
+/* load_ext --- dummy version if extensions not available */
-NODE *
-do_ext(int nargs)
+void
+load_ext(const char *lib_name)
{
- 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);
+ fatal(_("dynamic loading of library not supported"));
}
#endif