2 * ext.c - Builtin function that links external gawk functions and related
5 * Christos Zoulas, Thu Jun 29 17:40:41 EDT 1995
6 * Arnold Robbins, update for 3.1, Mon Nov 23 12:53:39 EST 1998
10 * Copyright (C) 1995 - 2001, 2003-2012 the Free Software Foundation, Inc.
12 * This file is part of GAWK, the GNU implementation of the
13 * AWK Programming Language.
15 * GAWK is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 3 of the License, or
18 * (at your option) any later version.
20 * GAWK is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
36 /* do_ext --- load an extension */
44 NODE *(*func)(NODE *, void *);
46 int flags = RTLD_LAZY;
47 int fatal_error = FALSE;
50 static short warned = FALSE;
54 fatal(_("extensions are not allowed in sandbox mode"));
57 /* already done in parser */
58 if (do_lint && ! warned) {
60 lintwarn(_("`extension' is a gawk extension"));
64 if (do_traditional || do_posix)
65 error(_("`extension' is a gawk extension"));
73 if ((dl = dlopen(obj->stptr, flags)) == NULL) {
74 /* fatal needs `obj', and we need to deallocate it! */
75 msg(_("fatal: extension: cannot open `%s' (%s)\n"), obj->stptr,
81 /* Per the GNU Coding standards */
82 gpl_compat = (int *) dlsym(dl, "plugin_is_GPL_compatible");
83 if (gpl_compat == NULL) {
84 msg(_("fatal: extension: library `%s': does not define `plugin_is_GPL_compatible' (%s)\n"),
85 obj->stptr, dlerror());
91 func = (NODE *(*)(NODE *, void *)) dlsym(dl, fun->stptr);
93 msg(_("fatal: extension: library `%s': cannot call function `%s' (%s)\n"),
94 obj->stptr, fun->stptr, dlerror());
99 tmp = (*func)(obj, dl);
106 gawk_exit(EXIT_FATAL);
111 /* make_builtin --- register name to be called as func with a builtin body */
114 make_builtin(const char *name, NODE *(*func)(int), int count)
116 NODE *p, *symbol, *f;
120 char **vnames = NULL;
126 if (sp == NULL || *sp == '\0')
127 fatal(_("extension: missing function name"));
129 while ((c = *sp++) != '\0') {
130 if ((sp == &name[1] && c != '_' && ! isalpha((unsigned char) c))
131 || (sp > &name[1] && ! is_identchar((unsigned char) c)))
132 fatal(_("extension: illegal character `%c' in function name `%s'"), c, name);
138 if (f->type == Node_func) {
139 INSTRUCTION *pc = f->code_ptr;
140 if (pc->opcode != Op_ext_func) /* user-defined function */
141 fatal(_("extension: can't redefine function `%s'"), name);
143 /* multiple extension() calls etc. */
145 lintwarn(_("extension: function `%s' already defined"), name);
149 /* variable name etc. */
150 fatal(_("extension: function name `%s' previously defined"), name);
151 } else if (check_special(name) >= 0)
152 fatal(_("extension: can't use gawk built-in `%s' as function name"), name);
153 /* count parameters, create artificial list of param names */
156 fatal(_("make_builtin: negative argument count for function `%s'"),
160 sprintf(buf, "p%d", count);
161 space_needed = strlen(buf) + 1;
162 emalloc(vnames, char **, count * sizeof(char *), "make_builtin");
163 for (i = 0; i < count; i++) {
164 emalloc(pname, char *, space_needed, "make_builtin");
165 sprintf(pname, "p%d", i);
172 p->type = Node_param_list;
174 /* get our own copy for name */
175 p->param = estrdup(name, strlen(name));
176 p->param_cnt = count;
178 /* actual source and line numbers set at runtime for these instructions */
179 b = bcalloc(Op_builtin, 1, __LINE__);
181 b->expr_count = count;
182 b->nexti = bcalloc(Op_K_return, 1, __LINE__);
183 r = bcalloc(Op_ext_func, 1, __LINE__);
184 r->source_file = __FILE__;
187 /* NB: extension sub must return something */
189 symbol = mk_symbol(Node_func, p);
190 symbol->parmlist = vnames;
191 symbol->code_ptr = r;
192 r->func_body = symbol;
193 (void) install_symbol(p->param, symbol);
197 /* get_curfunc_arg_count --- return number actual parameters */
200 get_curfunc_arg_count()
205 pc = (INSTRUCTION *) frame_ptr->reti; /* Op_func_call instruction */
206 argc = (pc + 1)->expr_count; /* # of arguments supplied */
211 /* get_argument --- get the n'th argument of a dynamically linked function */
221 f = frame_ptr->func_node;
222 pcount = f->lnode->param_cnt;
224 pc = (INSTRUCTION *) frame_ptr->reti; /* Op_func_call instruction */
225 actual_args = (pc + 1)->expr_count; /* # of arguments supplied */
227 if (i < 0 || i >= pcount || i >= actual_args)
232 if (t->type == Node_array_ref)
233 return t->orig_array; /* Node_var_new or Node_var_array */
234 if (t->type == Node_var_new || t->type == Node_var_array)
240 /* get_actual_argument --- get a scalar or array, allowed to be optional */
243 get_actual_argument(int i, int optional, int want_array)
245 /* optional : if TRUE and i th argument not present return NULL, else fatal. */
253 f = frame_ptr->func_node;
254 pcount = f->lnode->param_cnt;
255 fname = f->lnode->param;
258 if (i >= pcount) /* must be fatal */
259 fatal(_("function `%s' defined to take no more than %d argument(s)"),
262 fatal(_("function `%s': missing argument #%d"),
267 if (t->type == Node_var_new) {
269 return get_array(t, FALSE);
272 t->var_value = Nnull_string;
278 if (t->type != Node_var_array)
279 fatal(_("function `%s': argument #%d: attempt to use scalar as an array"),
282 if (t->type != Node_val)
283 fatal(_("function `%s': argument #%d: attempt to use array as a scalar"),
291 /* do_ext --- dummy version if extensions not available */
296 const char *emsg = _("Operation Not Supported");
298 unref(ERRNO_node->var_value);
299 ERRNO_node->var_value = make_string(emsg, strlen(emsg));
300 return make_number((AWKNUM) -1);