* __scm.h, alist.c, async.c, async.h, backtrace.h, chars.c,
[bpt/guile.git] / libguile / dynl.c
CommitLineData
1edae076
MV
1/* dynl.c - dynamic linking
2 *
7dc6e754 3 * Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
1edae076
MV
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
82892bed
JB
17 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18 * Boston, MA 02111-1307 USA
1edae076
MV
19 *
20 * As a special exception, the Free Software Foundation gives permission
21 * for additional uses of the text contained in its release of GUILE.
22 *
23 * The exception is that, if you link the GUILE library with other files
24 * to produce an executable, this does not by itself cause the
25 * resulting executable to be covered by the GNU General Public License.
26 * Your use of that executable is in no way restricted on account of
27 * linking the GUILE library code into it.
28 *
29 * This exception does not however invalidate any other reasons why
30 * the executable file might be covered by the GNU General Public License.
31 *
32 * This exception applies only to the code released by the
33 * Free Software Foundation under the name GUILE. If you copy
34 * code from other Free Software Foundation releases into a copy of
35 * GUILE, as the General Public License permits, the exception does
36 * not apply to the code that you add in this way. To avoid misleading
37 * anyone as to the status of such modified files, you must delete
38 * this exception notice from them.
39 *
40 * If you write modifications of your own for GUILE, it is your choice
41 * whether to permit this exception to apply to your modifications.
82892bed 42 * If you do not wish that, delete this exception notice. */
1edae076
MV
43
44/* "dynl.c" dynamically link&load object files.
45 Author: Aubrey Jaffer
46 Modified for libguile by Marius Vollmer */
47
104d4533 48#if 0 /* Disabled until we know for sure that it isn't needed */
80bc7890
MV
49/* XXX - This is only here to drag in a definition of __eprintf. This
50 is needed for proper operation of dynamic linking. The real
51 solution would probably be a shared libgcc. */
52
53#undef NDEBUG
54#include <assert.h>
55
56static void
57maybe_drag_in_eprintf ()
58{
59 assert (!maybe_drag_in_eprintf);
60}
104d4533 61#endif
80bc7890 62
96599e6a 63#include <stdio.h>
1edae076 64#include "_scm.h"
80bc7890
MV
65#include "dynl.h"
66#include "genio.h"
67#include "smob.h"
68
1edae076
MV
69/* Converting a list of SCM strings into a argv-style array. You must
70 have ints disabled for the whole lifetime of the created argv (from
71 before MAKE_ARGV_FROM_STRINGLIST until after
72 MUST_FREE_ARGV). Atleast this is was the documentation for
73 MAKARGVFROMSTRS says, it isn't really used that way.
74
75 This code probably belongs into strings.c */
76
77static char **scm_make_argv_from_stringlist SCM_P ((SCM args, int *argcp,
78 char *subr, int argn));
79
80static char **
81scm_make_argv_from_stringlist (args, argcp, subr, argn)
82 SCM args;
83 int *argcp;
84 char *subr;
85 int argn;
86{
87 char **argv;
88 int argc, i;
89
90 argc = scm_ilength(args);
91 argv = (char **) scm_must_malloc ((1L+argc)*sizeof(char *), subr);
92 for(i = 0; SCM_NNULLP (args); args = SCM_CDR (args), i++) {
93 size_t len;
94 char *dst, *src;
95 SCM str = SCM_CAR (args);
96
97 SCM_ASSERT (SCM_NIMP (str) && SCM_ROSTRINGP (str), str, argn, subr);
98 len = 1 + SCM_ROLENGTH (str);
99 dst = (char *) scm_must_malloc ((long)len, subr);
100 src = SCM_ROCHARS (str);
101 while (len--)
102 dst[len] = src[len];
103 argv[i] = dst;
104 }
105
106 if (argcp)
107 *argcp = argc;
108 argv[argc] = 0;
109 return argv;
110}
111
112static void scm_must_free_argv SCM_P ((char **argv));
113
114static void
115scm_must_free_argv(argv)
116 char **argv;
117{
118 char **av = argv;
c3e09ef9
MD
119 while (*av)
120 free(*(av++));
1edae076
MV
121 free(argv);
122}
123
124/* Coerce an arbitrary readonly-string into a zero-terminated string.
125 */
126
127static SCM scm_coerce_rostring SCM_P ((SCM rostr, char *subr, int argn));
128
129static SCM
130scm_coerce_rostring (rostr, subr, argn)
131 SCM rostr;
132 char *subr;
133 int argn;
134{
135 SCM_ASSERT (SCM_NIMP (rostr) && SCM_ROSTRINGP (rostr), rostr, argn, subr);
136 if (SCM_SUBSTRP (rostr))
137 rostr = scm_makfromstr (SCM_ROCHARS (rostr), SCM_ROLENGTH (rostr), 0);
138 return rostr;
139}
140
80bc7890
MV
141/* Module registry
142 */
143
144/* We can't use SCM objects here. One should be able to call
145 SCM_REGISTER_MODULE from a C++ constructor for a static
146 object. This happens before main and thus before libguile is
147 initialized. */
148
149struct moddata {
150 struct moddata *link;
151 char *module_name;
152 void *init_func;
153};
154
155static struct moddata *registered_mods = NULL;
156
157void
158scm_register_module_xxx (module_name, init_func)
159 char *module_name;
160 void *init_func;
161{
162 struct moddata *md;
163
164 /* XXX - should we (and can we) DEFER_INTS here? */
165
166 for (md = registered_mods; md; md = md->link)
167 if (!strcmp (md->module_name, module_name)) {
168 md->init_func = init_func;
169 return;
170 }
171
172 md = (struct moddata *)malloc (sizeof (struct moddata));
96599e6a
MV
173 if (md == NULL) {
174 fprintf (stderr,
175 "guile: can't register module (%s): not enough memory",
176 module_name);
80bc7890 177 return;
96599e6a 178 }
80bc7890
MV
179
180 md->module_name = module_name;
181 md->init_func = init_func;
182 md->link = registered_mods;
183 registered_mods = md;
184}
185
186SCM_PROC (s_registered_modules, "c-registered-modules", 0, 0, 0, scm_registered_modules);
187
188SCM
189scm_registered_modules ()
190{
191 SCM res;
192 struct moddata *md;
193
194 res = SCM_EOL;
195 for (md = registered_mods; md; md = md->link)
196 res = scm_cons (scm_cons (scm_makfrom0str (md->module_name),
197 scm_ulong2num ((unsigned long) md->init_func)),
198 res);
199 return res;
200}
201
202SCM_PROC (s_clear_registered_modules, "c-clear-registered-modules", 0, 0, 0, scm_clear_registered_modules);
203
204SCM
205scm_clear_registered_modules ()
206{
207 struct moddata *md1, *md2;
208
209 SCM_DEFER_INTS;
210
211 for (md1 = registered_mods; md1; md1 = md2) {
212 md2 = md1->link;
213 free (md1);
214 }
215 registered_mods = NULL;
216
217 SCM_ALLOW_INTS;
218 return SCM_UNSPECIFIED;
219}
220
1edae076 221/* Dispatch to the system dependent files
80bc7890 222 *
419e9e11
MV
223 * They define some static functions. These functions are called with
224 * deferred interrupts. When they want to throw errors, they are
225 * expected to insert a SCM_ALLOW_INTS before doing the throw. It
226 * might work to throw an error while interrupts are deferred (because
227 * they will be unconditionally allowed the next time a SCM_ALLOW_INTS
228 * is executed, SCM_DEFER_INTS and SCM_ALLOW_INTS do not nest).
1edae076
MV
229 */
230
80bc7890
MV
231static void sysdep_dynl_init SCM_P ((void));
232static void *sysdep_dynl_link SCM_P ((char *filename, char *subr));
233static void sysdep_dynl_unlink SCM_P ((void *handle, char *subr));
234static void *sysdep_dynl_func SCM_P ((char *symbol, void *handle, char *subr));
235
26c41b99 236#ifdef HAVE_DLOPEN
1edae076
MV
237#include "dynl-dl.c"
238#else
239#ifdef HAVE_SHL_LOAD
240#include "dynl-shl.c"
241#else
26c41b99 242#ifdef HAVE_LIBDLD
1edae076 243#include "dynl-dld.c"
96599e6a
MV
244#else
245
246/* no dynamic linking available, throw errors. */
247
248static void
249sysdep_dynl_init ()
250{
251}
252
253static void
254no_dynl_error (subr)
255 char *subr;
256{
419e9e11
MV
257 SCM_ALLOW_INTS;
258 scm_misc_error (subr, "dynamic linking not available", SCM_EOL);
96599e6a
MV
259}
260
261static void *
262sysdep_dynl_link (filename, subr)
263 char *filename;
264 char *subr;
265{
266 no_dynl_error (subr);
267 return NULL;
268}
269
270static void
271sysdep_dynl_unlink (handle, subr)
272 void *handle;
273 char *subr;
274{
275 no_dynl_error (subr);
276}
277
278static void *
279sysdep_dynl_func (symbol, handle, subr)
280 char *symbol;
281 void *handle;
282 char *subr;
283{
284 no_dynl_error (subr);
285 return NULL;
286}
287
80bc7890
MV
288#endif
289#endif
290#endif
291
292int scm_tc16_dynamic_obj;
293
294struct dynl_obj {
295 SCM filename;
296 void *handle;
297};
298
299static SCM mark_dynl_obj SCM_P ((SCM ptr));
300static SCM
301mark_dynl_obj (ptr)
302 SCM ptr;
303{
304 struct dynl_obj *d = (struct dynl_obj *)SCM_CDR (ptr);
80bc7890
MV
305 return d->filename;
306}
307
c487ad44
MV
308static scm_sizet free_dynl_obj SCM_P ((SCM ptr));
309static scm_sizet
310free_dynl_obj (ptr)
311 SCM ptr;
312{
313 scm_must_free ((char *)SCM_CDR (ptr));
314 return sizeof (struct dynl_obj);
315}
316
80bc7890
MV
317static int print_dynl_obj SCM_P ((SCM exp, SCM port, scm_print_state *pstate));
318static int
319print_dynl_obj (exp, port, pstate)
320 SCM exp;
321 SCM port;
322 scm_print_state *pstate;
323{
324 struct dynl_obj *d = (struct dynl_obj *)SCM_CDR (exp);
b7f3516f 325 scm_puts ("#<dynamic-object ", port);
80bc7890 326 scm_iprin1 (d->filename, port, pstate);
1fe1799f 327 if (d->handle == NULL)
b7f3516f
TT
328 scm_puts (" (unlinked)", port);
329 scm_putc ('>', port);
80bc7890
MV
330 return 1;
331}
332
333static scm_smobfuns dynl_obj_smob = {
334 mark_dynl_obj,
c487ad44 335 free_dynl_obj,
80bc7890
MV
336 print_dynl_obj
337};
338
339SCM_PROC (s_dynamic_link, "dynamic-link", 1, 0, 0, scm_dynamic_link);
340
341SCM
342scm_dynamic_link (fname)
343 SCM fname;
344{
345 SCM z;
c487ad44 346 void *handle;
80bc7890
MV
347 struct dynl_obj *d;
348
349 fname = scm_coerce_rostring (fname, s_dynamic_link, SCM_ARG1);
c487ad44
MV
350
351 SCM_DEFER_INTS;
352 handle = sysdep_dynl_link (SCM_CHARS (fname), s_dynamic_link);
353
80bc7890
MV
354 d = (struct dynl_obj *)scm_must_malloc (sizeof (struct dynl_obj),
355 s_dynamic_link);
356 d->filename = fname;
c487ad44 357 d->handle = handle;
80bc7890 358
80bc7890
MV
359 SCM_NEWCELL (z);
360 SCM_SETCHARS (z, d);
361 SCM_SETCAR (z, scm_tc16_dynamic_obj);
362 SCM_ALLOW_INTS;
363
364 return z;
365}
366
367static struct dynl_obj *get_dynl_obj SCM_P ((SCM obj, char *subr, int argn));
368static struct dynl_obj *
369get_dynl_obj (dobj, subr, argn)
370 SCM dobj;
371 char *subr;
372 int argn;
373{
374 struct dynl_obj *d;
375 SCM_ASSERT (SCM_NIMP (dobj) && SCM_CAR (dobj) == scm_tc16_dynamic_obj,
376 dobj, argn, subr);
377 d = (struct dynl_obj *)SCM_CDR (dobj);
378 SCM_ASSERT (d->handle != NULL, dobj, argn, subr);
379 return d;
380}
381
382SCM_PROC (s_dynamic_object_p, "dynamic-object?", 1, 0, 0, scm_dynamic_object_p);
383
384SCM
385scm_dynamic_object_p (SCM obj)
386{
387 return (SCM_NIMP (obj) && SCM_CAR (obj) == scm_tc16_dynamic_obj)?
388 SCM_BOOL_T : SCM_BOOL_F;
389}
390
391SCM_PROC (s_dynamic_unlink, "dynamic-unlink", 1, 0, 0, scm_dynamic_unlink);
392
393SCM
394scm_dynamic_unlink (dobj)
395 SCM dobj;
396{
397 struct dynl_obj *d = get_dynl_obj (dobj, s_dynamic_unlink, SCM_ARG1);
419e9e11 398 SCM_DEFER_INTS;
80bc7890
MV
399 sysdep_dynl_unlink (d->handle, s_dynamic_unlink);
400 d->handle = NULL;
419e9e11
MV
401 SCM_ALLOW_INTS;
402 return SCM_UNSPECIFIED;
80bc7890
MV
403}
404
405SCM_PROC (s_dynamic_func, "dynamic-func", 2, 0, 0, scm_dynamic_func);
406
407SCM
408scm_dynamic_func (SCM symb, SCM dobj)
409{
410 struct dynl_obj *d;
411 void (*func) ();
412
413 symb = scm_coerce_rostring (symb, s_dynamic_func, SCM_ARG1);
414 d = get_dynl_obj (dobj, s_dynamic_func, SCM_ARG2);
415
419e9e11 416 SCM_DEFER_INTS;
cdbadcac
JB
417 func = (void (*) ()) sysdep_dynl_func (SCM_CHARS (symb), d->handle,
418 s_dynamic_func);
419e9e11
MV
419 SCM_ALLOW_INTS;
420
80bc7890
MV
421 return scm_ulong2num ((unsigned long)func);
422}
423
424SCM_PROC (s_dynamic_call, "dynamic-call", 2, 0, 0, scm_dynamic_call);
425
426SCM
427scm_dynamic_call (SCM func, SCM dobj)
428{
429 void (*fptr)();
430
431 if (SCM_NIMP (func) && SCM_ROSTRINGP (func))
432 func = scm_dynamic_func (func, dobj);
433 fptr = (void (*)()) scm_num2ulong (func, (char *)SCM_ARG1, s_dynamic_call);
419e9e11 434 SCM_DEFER_INTS;
80bc7890 435 fptr ();
419e9e11
MV
436 SCM_ALLOW_INTS;
437 return SCM_UNSPECIFIED;
80bc7890
MV
438}
439
440SCM_PROC (s_dynamic_args_call, "dynamic-args-call", 3, 0, 0, scm_dynamic_args_call);
441
442SCM
443scm_dynamic_args_call (func, dobj, args)
444 SCM func, dobj, args;
445{
446 int (*fptr) (int argc, char **argv);
447 int result, argc;
448 char **argv;
449
450 if (SCM_NIMP (func) && SCM_ROSTRINGP (func))
451 func = scm_dynamic_func (func, dobj);
452
453 fptr = (int (*)(int, char **)) scm_num2ulong (func, (char *)SCM_ARG1,
454 s_dynamic_args_call);
419e9e11 455 SCM_DEFER_INTS;
80bc7890
MV
456 argv = scm_make_argv_from_stringlist (args, &argc, s_dynamic_args_call,
457 SCM_ARG3);
80bc7890 458 result = (*fptr) (argc, argv);
80bc7890 459 scm_must_free_argv (argv);
419e9e11
MV
460 SCM_ALLOW_INTS;
461
80bc7890
MV
462 return SCM_MAKINUM(0L+result);
463}
464
1edae076
MV
465void
466scm_init_dynamic_linking ()
467{
80bc7890
MV
468 scm_tc16_dynamic_obj = scm_newsmob (&dynl_obj_smob);
469 sysdep_dynl_init ();
470#include "dynl.x"
1edae076 471}