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-2014 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
31 extern SRCFILE *srcfiles;
35 #define OLD_INIT_FUNC "dlload"
36 #define OLD_FINI_FUNC "dlunload"
41 * is_letter --- function to check letters
42 * isalpha() isn't good enough since it can look at the locale.
43 * Underscore counts as a letter in awk identifiers
47 is_letter(unsigned char c)
50 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
51 case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
52 case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
53 case 's': case 't': case 'u': case 'v': case 'w': case 'x':
55 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
56 case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
57 case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
58 case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
67 /* is_identifier_char --- return true if a character can be used in an identifier */
70 is_identifier_char(unsigned char c)
72 return (is_letter(c) || isdigit(c));
76 #define INIT_FUNC "dl_load"
78 /* load_ext --- load an external library */
81 load_ext(const char *lib_name)
83 int (*install_func)(const gawk_api_t *const, awk_ext_id_t);
85 int flags = RTLD_LAZY;
89 fatal(_("extensions are not allowed in sandbox mode"));
91 if (do_traditional || do_posix)
92 fatal(_("-l / @load are gawk extensions"));
95 fatal(_("load_ext: received NULL lib_name"));
97 if ((dl = dlopen(lib_name, flags)) == NULL)
98 fatal(_("load_ext: cannot open library `%s' (%s)\n"), lib_name,
101 /* Per the GNU Coding standards */
102 gpl_compat = (int *) dlsym(dl, "plugin_is_GPL_compatible");
103 if (gpl_compat == NULL)
104 fatal(_("load_ext: library `%s': does not define `plugin_is_GPL_compatible' (%s)\n"),
105 lib_name, dlerror());
107 install_func = (int (*)(const gawk_api_t *const, awk_ext_id_t))
108 dlsym(dl, INIT_FUNC);
109 if (install_func == NULL)
110 fatal(_("load_ext: library `%s': cannot call function `%s' (%s)\n"),
111 lib_name, INIT_FUNC, dlerror());
113 if (install_func(& api_impl, NULL /* ext_id */) == 0)
114 warning(_("load_ext: library `%s' initialization routine `%s' failed\n"),
115 lib_name, INIT_FUNC);
118 /* do_ext --- load an extension at run-time: interface to load_ext */
123 NODE *obj, *init = NULL, *fini = NULL, *ret = NULL;
125 char *init_func = NULL;
126 char *fini_func = NULL;
130 fini_func = fini->stptr;
134 init_func = init->stptr;
138 s = add_srcfile(SRC_EXTLIB, obj->stptr, srcfiles, NULL, NULL);
140 ret = load_old_ext(s, init_func, fini_func, obj);
148 ret = dupnode(Nnull_string);
152 /* load_old_ext --- load an external library */
155 load_old_ext(SRCFILE *s, const char *init_func, const char *fini_func, NODE *obj)
157 NODE *(*func)(NODE *, void *);
160 int flags = RTLD_LAZY;
162 const char *lib_name = s->fullpath;
164 if (init_func == NULL || init_func[0] == '\0')
165 init_func = OLD_INIT_FUNC;
167 if (fini_func == NULL || fini_func[0] == '\0')
168 fini_func = OLD_FINI_FUNC;
171 fatal(_("extensions are not allowed in sandbox mode"));
173 if (do_traditional || do_posix)
174 fatal(_("`extension' is a gawk extension"));
176 if (lib_name == NULL)
177 fatal(_("extension: received NULL lib_name"));
179 if ((dl = dlopen(lib_name, flags)) == NULL)
180 fatal(_("extension: cannot open library `%s' (%s)"), lib_name,
183 /* Per the GNU Coding standards */
184 gpl_compat = (int *) dlsym(dl, "plugin_is_GPL_compatible");
185 if (gpl_compat == NULL)
186 fatal(_("extension: library `%s': does not define `plugin_is_GPL_compatible' (%s)"),
187 lib_name, dlerror());
188 func = (NODE *(*)(NODE *, void *)) dlsym(dl, init_func);
190 fatal(_("extension: library `%s': cannot call function `%s' (%s)"),
191 lib_name, init_func, dlerror());
194 obj = make_string(lib_name, strlen(lib_name));
195 tmp = (*func)(obj, dl);
200 tmp = (*func)(obj, dl);
202 s->fini_func = (void (*)(void)) dlsym(dl, fini_func);
207 /* make_builtin --- register name to be called as func with a builtin body */
210 make_builtin(const awk_ext_func_t *funcinfo)
216 const char *name = funcinfo->name;
217 int count = funcinfo->num_expected_args;
220 if (sp == NULL || *sp == '\0')
221 fatal(_("make_builtin: missing function name"));
223 if (! is_letter(*sp))
226 for (sp++; (c = *sp++) != '\0';) {
227 if (! is_identifier_char(c))
234 if (f->type == Node_func) {
235 /* user-defined function */
236 fatal(_("make_builtin: can't redefine function `%s'"), name);
237 } else if (f->type == Node_ext_func) {
238 /* multiple extension() calls etc. */
240 lintwarn(_("make_builtin: function `%s' already defined"), name);
243 /* variable name etc. */
244 fatal(_("make_builtin: function name `%s' previously defined"), name);
245 } else if (check_special(name) >= 0)
246 fatal(_("make_builtin: can't use gawk built-in `%s' as function name"), name);
249 fatal(_("make_builtin: negative argument count for function `%s'"),
252 b = bcalloc(Op_symbol, 1, 0);
253 b->extfunc = funcinfo->function;
254 b->expr_count = count;
256 /* NB: extension sub must return something */
258 symbol = install_symbol(estrdup(name, strlen(name)), Node_ext_func);
259 symbol->code_ptr = b;
260 track_ext_func(name);
264 /* make_old_builtin --- register name to be called as func with a builtin body */
267 make_old_builtin(const char *name, NODE *(*func)(int), int count) /* temporary */
275 if (sp == NULL || *sp == '\0')
276 fatal(_("extension: missing function name"));
278 if (! is_letter(*sp))
279 fatal(_("extension: illegal character `%c' in function name `%s'"), *sp, name);
281 for (sp++; (c = *sp++) != '\0';) {
282 if (! is_identifier_char(c))
283 fatal(_("extension: illegal character `%c' in function name `%s'"), c, name);
289 if (f->type == Node_func) {
290 /* user-defined function */
291 fatal(_("extension: can't redefine function `%s'"), name);
292 } else if (f->type == Node_ext_func) {
293 /* multiple extension() calls etc. */
295 lintwarn(_("extension: function `%s' already defined"), name);
298 /* variable name etc. */
299 fatal(_("extension: function name `%s' previously defined"), name);
300 } else if (check_special(name) >= 0)
301 fatal(_("extension: can't use gawk built-in `%s' as function name"), name);
304 fatal(_("make_builtin: negative argument count for function `%s'"),
307 b = bcalloc(Op_symbol, 1, 0);
309 b->expr_count = count;
311 /* NB: extension sub must return something */
313 symbol = install_symbol(estrdup(name, strlen(name)), Node_old_ext_func);
314 symbol->code_ptr = b;
315 track_ext_func(name);
319 /* get_argument --- get the i'th argument of a dynamically linked function */
325 int arg_count, pcount;
328 pc = TOP()->code_ptr; /* Op_ext_builtin instruction */
329 pcount = (pc + 1)->expr_count; /* max # of arguments */
330 arg_count = pc->expr_count; /* # of arguments supplied */
332 if (i < 0 || i >= pcount || i >= arg_count)
335 t = PEEK(arg_count - i);
336 if (t->type == Node_param_list)
337 t = GET_PARAM(t->param_cnt);
339 if (t->type == Node_array_ref) {
340 if (t->orig_array->type == Node_var) {
341 /* already a scalar, can no longer use it as array */
343 t->var_value = Nnull_string;
346 return t->orig_array; /* Node_var_new or Node_var_array */
348 if (t->type == Node_var) /* See Case Node_var in setup_frame(), eval.c */
350 /* Node_var_new, Node_var_array or Node_val */
356 * get_actual_argument --- get the i'th scalar or array argument of a
357 * dynamically linked function, allowed to be optional.
361 get_actual_argument(int i, bool optional, bool want_array)
368 pc = TOP()->code_ptr; /* Op_ext_builtin instruction */
369 fname = (pc + 1)->func_name;
370 pcount = (pc + 1)->expr_count;
374 if (i >= pcount) /* must be fatal */
375 fatal(_("function `%s' defined to take no more than %d argument(s)"),
378 fatal(_("function `%s': missing argument #%d"),
383 if (t->type == Node_var_new) {
385 return force_array(t, false);
388 t->var_value = dupnode(Nnull_string);
394 if (t->type != Node_var_array)
395 fatal(_("function `%s': argument #%d: attempt to use scalar as an array"),
398 if (t->type != Node_val)
399 fatal(_("function `%s': argument #%d: attempt to use array as a scalar"),
402 assert(t->type == Node_var_array || t->type == Node_val);
408 /* load_ext --- dummy version if extensions not available */
411 load_ext(const char *lib_name)
413 fatal(_("dynamic loading of library not supported"));
417 /* close_extensions --- execute extension cleanup routines */
424 for (s = srcfiles->next; s != srcfiles; s = s->next)
425 if (s->stype == SRC_EXTLIB && s->fini_func)