* init.scm (index, rindex): replace versions in utilities.scm with
[bpt/guile.git] / libguile / dynl.c
CommitLineData
1edae076
MV
1/* dynl.c - dynamic linking
2 *
3 * Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this software; see the file COPYING. If not, write to
17 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 * As a special exception, the Free Software Foundation gives permission
20 * for additional uses of the text contained in its release of GUILE.
21 *
22 * The exception is that, if you link the GUILE library with other files
23 * to produce an executable, this does not by itself cause the
24 * resulting executable to be covered by the GNU General Public License.
25 * Your use of that executable is in no way restricted on account of
26 * linking the GUILE library code into it.
27 *
28 * This exception does not however invalidate any other reasons why
29 * the executable file might be covered by the GNU General Public License.
30 *
31 * This exception applies only to the code released by the
32 * Free Software Foundation under the name GUILE. If you copy
33 * code from other Free Software Foundation releases into a copy of
34 * GUILE, as the General Public License permits, the exception does
35 * not apply to the code that you add in this way. To avoid misleading
36 * anyone as to the status of such modified files, you must delete
37 * this exception notice from them.
38 *
39 * If you write modifications of your own for GUILE, it is your choice
40 * whether to permit this exception to apply to your modifications.
41 * If you do not wish that, delete this exception notice.
42 */
43
44/* "dynl.c" dynamically link&load object files.
45 Author: Aubrey Jaffer
46 Modified for libguile by Marius Vollmer */
47
80bc7890
MV
48/* XXX - This is only here to drag in a definition of __eprintf. This
49 is needed for proper operation of dynamic linking. The real
50 solution would probably be a shared libgcc. */
51
52#undef NDEBUG
53#include <assert.h>
54
55static void
56maybe_drag_in_eprintf ()
57{
58 assert (!maybe_drag_in_eprintf);
59}
60
1edae076 61#include "_scm.h"
80bc7890
MV
62#include "dynl.h"
63#include "genio.h"
64#include "smob.h"
65
66#ifdef DYNAMIC_LINKING
1edae076
MV
67
68/* Converting a list of SCM strings into a argv-style array. You must
69 have ints disabled for the whole lifetime of the created argv (from
70 before MAKE_ARGV_FROM_STRINGLIST until after
71 MUST_FREE_ARGV). Atleast this is was the documentation for
72 MAKARGVFROMSTRS says, it isn't really used that way.
73
74 This code probably belongs into strings.c */
75
76static char **scm_make_argv_from_stringlist SCM_P ((SCM args, int *argcp,
77 char *subr, int argn));
78
79static char **
80scm_make_argv_from_stringlist (args, argcp, subr, argn)
81 SCM args;
82 int *argcp;
83 char *subr;
84 int argn;
85{
86 char **argv;
87 int argc, i;
88
89 argc = scm_ilength(args);
90 argv = (char **) scm_must_malloc ((1L+argc)*sizeof(char *), subr);
91 for(i = 0; SCM_NNULLP (args); args = SCM_CDR (args), i++) {
92 size_t len;
93 char *dst, *src;
94 SCM str = SCM_CAR (args);
95
96 SCM_ASSERT (SCM_NIMP (str) && SCM_ROSTRINGP (str), str, argn, subr);
97 len = 1 + SCM_ROLENGTH (str);
98 dst = (char *) scm_must_malloc ((long)len, subr);
99 src = SCM_ROCHARS (str);
100 while (len--)
101 dst[len] = src[len];
102 argv[i] = dst;
103 }
104
105 if (argcp)
106 *argcp = argc;
107 argv[argc] = 0;
108 return argv;
109}
110
111static void scm_must_free_argv SCM_P ((char **argv));
112
113static void
114scm_must_free_argv(argv)
115 char **argv;
116{
117 char **av = argv;
118 while(!(*av))
119 free(*(av++));
120 free(argv);
121}
122
123/* Coerce an arbitrary readonly-string into a zero-terminated string.
124 */
125
126static SCM scm_coerce_rostring SCM_P ((SCM rostr, char *subr, int argn));
127
128static SCM
129scm_coerce_rostring (rostr, subr, argn)
130 SCM rostr;
131 char *subr;
132 int argn;
133{
134 SCM_ASSERT (SCM_NIMP (rostr) && SCM_ROSTRINGP (rostr), rostr, argn, subr);
135 if (SCM_SUBSTRP (rostr))
136 rostr = scm_makfromstr (SCM_ROCHARS (rostr), SCM_ROLENGTH (rostr), 0);
137 return rostr;
138}
139
80bc7890
MV
140/* Module registry
141 */
142
143/* We can't use SCM objects here. One should be able to call
144 SCM_REGISTER_MODULE from a C++ constructor for a static
145 object. This happens before main and thus before libguile is
146 initialized. */
147
148struct moddata {
149 struct moddata *link;
150 char *module_name;
151 void *init_func;
152};
153
154static struct moddata *registered_mods = NULL;
155
156void
157scm_register_module_xxx (module_name, init_func)
158 char *module_name;
159 void *init_func;
160{
161 struct moddata *md;
162
163 /* XXX - should we (and can we) DEFER_INTS here? */
164
165 for (md = registered_mods; md; md = md->link)
166 if (!strcmp (md->module_name, module_name)) {
167 md->init_func = init_func;
168 return;
169 }
170
171 md = (struct moddata *)malloc (sizeof (struct moddata));
172 if (md == NULL)
173 return;
174
175 md->module_name = module_name;
176 md->init_func = init_func;
177 md->link = registered_mods;
178 registered_mods = md;
179}
180
181SCM_PROC (s_registered_modules, "c-registered-modules", 0, 0, 0, scm_registered_modules);
182
183SCM
184scm_registered_modules ()
185{
186 SCM res;
187 struct moddata *md;
188
189 res = SCM_EOL;
190 for (md = registered_mods; md; md = md->link)
191 res = scm_cons (scm_cons (scm_makfrom0str (md->module_name),
192 scm_ulong2num ((unsigned long) md->init_func)),
193 res);
194 return res;
195}
196
197SCM_PROC (s_clear_registered_modules, "c-clear-registered-modules", 0, 0, 0, scm_clear_registered_modules);
198
199SCM
200scm_clear_registered_modules ()
201{
202 struct moddata *md1, *md2;
203
204 SCM_DEFER_INTS;
205
206 for (md1 = registered_mods; md1; md1 = md2) {
207 md2 = md1->link;
208 free (md1);
209 }
210 registered_mods = NULL;
211
212 SCM_ALLOW_INTS;
213 return SCM_UNSPECIFIED;
214}
215
1edae076 216/* Dispatch to the system dependent files
80bc7890
MV
217 *
218 * They define these static functions:
1edae076
MV
219 */
220
80bc7890
MV
221static void sysdep_dynl_init SCM_P ((void));
222static void *sysdep_dynl_link SCM_P ((char *filename, char *subr));
223static void sysdep_dynl_unlink SCM_P ((void *handle, char *subr));
224static void *sysdep_dynl_func SCM_P ((char *symbol, void *handle, char *subr));
225
1edae076
MV
226#ifdef HAVE_LIBDL
227#include "dynl-dl.c"
228#else
229#ifdef HAVE_SHL_LOAD
230#include "dynl-shl.c"
231#else
232#ifdef HAVE_DLD
233#include "dynl-dld.c"
234#else /* no dynamic linking available */
80bc7890
MV
235/* configure should not have defined DYNAMIC_LINKING in this case */
236#error Dynamic linking not implemented for your system.
237#endif
238#endif
239#endif
240
241int scm_tc16_dynamic_obj;
242
243struct dynl_obj {
244 SCM filename;
245 void *handle;
246};
247
248static SCM mark_dynl_obj SCM_P ((SCM ptr));
249static SCM
250mark_dynl_obj (ptr)
251 SCM ptr;
252{
253 struct dynl_obj *d = (struct dynl_obj *)SCM_CDR (ptr);
254 SCM_SETGC8MARK (ptr);
255 return d->filename;
256}
257
258static int print_dynl_obj SCM_P ((SCM exp, SCM port, scm_print_state *pstate));
259static int
260print_dynl_obj (exp, port, pstate)
261 SCM exp;
262 SCM port;
263 scm_print_state *pstate;
264{
265 struct dynl_obj *d = (struct dynl_obj *)SCM_CDR (exp);
266 scm_gen_puts (scm_regular_string, "#<dynamic-object ", port);
267 scm_iprin1 (d->filename, port, pstate);
268 scm_gen_putc ('>', port);
269 return 1;
270}
271
272static scm_smobfuns dynl_obj_smob = {
273 mark_dynl_obj,
274 scm_free0,
275 print_dynl_obj
276};
277
278SCM_PROC (s_dynamic_link, "dynamic-link", 1, 0, 0, scm_dynamic_link);
279
280SCM
281scm_dynamic_link (fname)
282 SCM fname;
283{
284 SCM z;
285 struct dynl_obj *d;
286
287 fname = scm_coerce_rostring (fname, s_dynamic_link, SCM_ARG1);
288 d = (struct dynl_obj *)scm_must_malloc (sizeof (struct dynl_obj),
289 s_dynamic_link);
290 d->filename = fname;
291
292 SCM_DEFER_INTS;
293 d->handle = sysdep_dynl_link (SCM_CHARS (fname), s_dynamic_link);
294 SCM_NEWCELL (z);
295 SCM_SETCHARS (z, d);
296 SCM_SETCAR (z, scm_tc16_dynamic_obj);
297 SCM_ALLOW_INTS;
298
299 return z;
300}
301
302static struct dynl_obj *get_dynl_obj SCM_P ((SCM obj, char *subr, int argn));
303static struct dynl_obj *
304get_dynl_obj (dobj, subr, argn)
305 SCM dobj;
306 char *subr;
307 int argn;
308{
309 struct dynl_obj *d;
310 SCM_ASSERT (SCM_NIMP (dobj) && SCM_CAR (dobj) == scm_tc16_dynamic_obj,
311 dobj, argn, subr);
312 d = (struct dynl_obj *)SCM_CDR (dobj);
313 SCM_ASSERT (d->handle != NULL, dobj, argn, subr);
314 return d;
315}
316
317SCM_PROC (s_dynamic_object_p, "dynamic-object?", 1, 0, 0, scm_dynamic_object_p);
318
319SCM
320scm_dynamic_object_p (SCM obj)
321{
322 return (SCM_NIMP (obj) && SCM_CAR (obj) == scm_tc16_dynamic_obj)?
323 SCM_BOOL_T : SCM_BOOL_F;
324}
325
326SCM_PROC (s_dynamic_unlink, "dynamic-unlink", 1, 0, 0, scm_dynamic_unlink);
327
328SCM
329scm_dynamic_unlink (dobj)
330 SCM dobj;
331{
332 struct dynl_obj *d = get_dynl_obj (dobj, s_dynamic_unlink, SCM_ARG1);
333 sysdep_dynl_unlink (d->handle, s_dynamic_unlink);
334 d->handle = NULL;
335 return SCM_BOOL_T;
336}
337
338SCM_PROC (s_dynamic_func, "dynamic-func", 2, 0, 0, scm_dynamic_func);
339
340SCM
341scm_dynamic_func (SCM symb, SCM dobj)
342{
343 struct dynl_obj *d;
344 void (*func) ();
345
346 symb = scm_coerce_rostring (symb, s_dynamic_func, SCM_ARG1);
347 d = get_dynl_obj (dobj, s_dynamic_func, SCM_ARG2);
348
349 func = sysdep_dynl_func (d->handle, SCM_CHARS (symb), s_dynamic_func);
350 return scm_ulong2num ((unsigned long)func);
351}
352
353SCM_PROC (s_dynamic_call, "dynamic-call", 2, 0, 0, scm_dynamic_call);
354
355SCM
356scm_dynamic_call (SCM func, SCM dobj)
357{
358 void (*fptr)();
359
360 if (SCM_NIMP (func) && SCM_ROSTRINGP (func))
361 func = scm_dynamic_func (func, dobj);
362 fptr = (void (*)()) scm_num2ulong (func, (char *)SCM_ARG1, s_dynamic_call);
363 fptr ();
364 return SCM_BOOL_T;
365}
366
367SCM_PROC (s_dynamic_args_call, "dynamic-args-call", 3, 0, 0, scm_dynamic_args_call);
368
369SCM
370scm_dynamic_args_call (func, dobj, args)
371 SCM func, dobj, args;
372{
373 int (*fptr) (int argc, char **argv);
374 int result, argc;
375 char **argv;
376
377 if (SCM_NIMP (func) && SCM_ROSTRINGP (func))
378 func = scm_dynamic_func (func, dobj);
379
380 fptr = (int (*)(int, char **)) scm_num2ulong (func, (char *)SCM_ARG1,
381 s_dynamic_args_call);
382 argv = scm_make_argv_from_stringlist (args, &argc, s_dynamic_args_call,
383 SCM_ARG3);
384
385 result = (*fptr) (argc, argv);
386
387 scm_must_free_argv (argv);
388 return SCM_MAKINUM(0L+result);
389}
390
1edae076
MV
391void
392scm_init_dynamic_linking ()
393{
80bc7890
MV
394 scm_tc16_dynamic_obj = scm_newsmob (&dynl_obj_smob);
395 sysdep_dynl_init ();
396#include "dynl.x"
1edae076 397}
80bc7890
MV
398
399#else /* not DYNAMIC_LINKING */
400
1edae076
MV
401void
402scm_init_dynamic_linking ()
403{
80bc7890 404#include "dynl.x"
1edae076 405}
80bc7890
MV
406
407#endif /* not DYNAMIC_LINKING */