source: vendor/gawk/3.1.5/ext.c@ 3513

Last change on this file since 3513 was 3076, checked in by bird, 18 years ago

gawk 3.1.5

File size: 6.0 KB
Line 
1/*
2 * ext.c - Builtin function that links external gawk functions and related
3 * utilities.
4 *
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
7 */
8
9/*
10 * Copyright (C) 1995 - 2001, 2003-2005 the Free Software Foundation, Inc.
11 *
12 * This file is part of GAWK, the GNU implementation of the
13 * AWK Programming Language.
14 *
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 2 of the License, or
18 * (at your option) any later version.
19 *
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.
24 *
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
28 */
29
30#include "awk.h"
31
32#ifdef DYNAMIC
33
34#include <dlfcn.h>
35
36#ifdef __GNUC__
37static unsigned long long dummy; /* fake out gcc for dynamic loading? */
38#endif
39
40extern int errcount;
41
42/* do_ext --- load an extension */
43
44NODE *
45do_ext(NODE *tree)
46{
47 NODE *obj;
48 NODE *fun;
49 NODE *(*func) P((NODE *, void *));
50 void *dl;
51 int flags = RTLD_LAZY;
52
53#ifdef __GNUC__
54 AWKNUM junk;
55
56 junk = (AWKNUM) dummy;
57#endif
58
59 if (do_lint)
60 lintwarn(_("`extension' is a gawk extension"));
61
62 if (do_traditional || do_posix) {
63 errcount++;
64 error(_("`extension' is a gawk extension"));
65 }
66
67 obj = tree_eval(tree->lnode);
68 force_string(obj);
69
70#ifdef RTLD_GLOBAL
71 flags |= RTLD_GLOBAL;
72#endif
73 if ((dl = dlopen(obj->stptr, flags)) == NULL)
74 fatal(_("extension: cannot open `%s' (%s)\n"), obj->stptr,
75 dlerror());
76
77 fun = tree_eval(tree->rnode->lnode);
78 force_string(fun);
79
80 func = (NODE *(*) P((NODE *, void *))) dlsym(dl, fun->stptr);
81 if (func == NULL)
82 fatal(_("extension: library `%s': cannot call function `%s' (%s)\n"),
83 obj->stptr, fun->stptr, dlerror());
84 free_temp(obj);
85 free_temp(fun);
86
87 return (*func)(tree, dl);
88}
89
90/* make_builtin --- register name to be called as func with a builtin body */
91
92void
93make_builtin(char *name, NODE *(*func) P((NODE *)), int count)
94{
95 NODE *p, *b, *f;
96 char **vnames, *parm_names, *sp;
97 char c, buf[200];
98 int space_needed, i;
99
100 sp = name;
101 if (sp == NULL || *sp == '\0')
102 fatal(_("extension: missing function name"));
103
104 while ((c = *sp++) != '\0')
105 if ((sp == &name[1] && c != '_' && ! ISALPHA(c))
106 || (sp > &name[1] && ! is_identchar(c)))
107 fatal(_("extension: illegal character `%c' in function name `%s'"), c, name);
108
109 f = lookup(name);
110 if (f != NULL) {
111 if (f->type == Node_func) {
112 if (f->rnode->type != Node_builtin) /* user-defined function */
113 fatal(_("extension: can't redefine function `%s'"), name);
114 else {
115 /* multiple extension() calls etc. */
116 if (do_lint)
117 lintwarn(_("extension: function `%s' already defined"), name);
118 return;
119 }
120 } else {
121 if (check_special(name) >= 0)
122 fatal(_("extension: can't use gawk built-in `%s' as function name"), name);
123 /* variable name etc. */
124 fatal(_("extension: function name `%s' previously defined"), name);
125 }
126 }
127
128 /* count parameters, create artificial list of param names */
129 space_needed = 0;
130 for (i = 0; i < count; i++) {
131 sprintf(buf, "p%d", i);
132 space_needed += strlen(buf) + 1;
133 }
134 emalloc(parm_names, char *, space_needed, "make_builtin");
135 emalloc(vnames, char **, count * sizeof(char *), "make_builtin");
136 sp = parm_names;
137 for (i = 0; i < count; i++) {
138 sprintf(sp, "p%d",i);
139 vnames[i] = sp;
140 sp += strlen(sp) + 1;
141 }
142
143 getnode(p);
144 p->type = Node_param_list;
145 p->flags |= FUNC;
146 p->rnode = NULL;
147 p->param = name;
148 p->param_cnt = count;
149#if 0
150 /* setting these blows away the param_cnt. dang unions! */
151 p->source_line = __LINE__;
152 p->source_file = __FILE__;
153#endif
154
155 getnode(b);
156 b->type = Node_builtin;
157 b->builtin = func;
158 b->subnode = p;
159 b->source_line = __LINE__;
160 b->source_file = __FILE__;
161
162 f = node(p, Node_func, b);
163 f->parmlist = vnames;
164 install(name, f);
165}
166
167/* get_argument --- Get the n'th argument of a dynamically linked function */
168
169NODE *
170get_argument(NODE *tree, int i)
171{
172 extern NODE **stack_ptr;
173 int actual_args;
174
175 actual_args = get_curfunc_arg_count();
176 if (i < 0 || i >= tree->param_cnt || i >= actual_args)
177 return NULL;
178
179 tree = stack_ptr[i];
180 if (tree->type == Node_array_ref)
181 tree = tree->orig_array;
182 if (tree->type == Node_var_new || tree->type == Node_var_array)
183 return tree;
184
185 return tree->lnode;
186}
187
188/* get_actual_argument --- get a scalar or array, allowed to be optional */
189
190NODE *
191get_actual_argument(NODE *tree, unsigned int i, int optional, int want_array)
192{
193 /* optional : if TRUE and i th argument not present return NULL, else fatal. */
194
195 NODE *t;
196
197 t = get_argument(tree, i);
198
199 if (t == NULL) {
200 if (i >= tree->param_cnt) /* must be fatal */
201 fatal(_("function `%s' defined to take no more than %d argument(s)"),
202 tree->param, tree->param_cnt);
203 if (! optional)
204 fatal(_("function `%s': missing argument #%d"),
205 tree->param, i + 1);
206 return NULL;
207 }
208
209 if (t->type == Node_var_new)
210 return (want_array ? get_array(t) : tree_eval(t));
211
212 if (want_array) {
213 if (t->type != Node_var_array)
214 fatal(_("function `%s': argument #%d: attempt to use scalar as an array"),
215 tree->param, i + 1);
216 } else {
217 if (t->type != Node_val)
218 fatal(_("function `%s': argument #%d: attempt to use array as a scalar"),
219 tree->param, i + 1);
220 }
221 return t;
222}
223
224/* set_value --- set the return value of a dynamically linked function */
225
226void
227set_value(NODE *tree)
228{
229 extern NODE *ret_node;
230
231 if (tree)
232 ret_node = tree;
233 else
234 ret_node = Nnull_string;
235}
236#else
237
238/* do_ext --- dummy version if extensions not available */
239
240NODE *
241do_ext(NODE *tree)
242{
243 const char *emsg = _("Operation Not Supported");
244
245 unref(ERRNO_node->var_value);
246 ERRNO_node->var_value = make_string((char *) emsg, strlen(emsg));
247 return tmp_number((AWKNUM) -1);
248}
249#endif
Note: See TracBrowser for help on using the repository browser.