Greg's smob patch
[bpt/guile.git] / libguile / dynl.c
CommitLineData
1edae076
MV
1/* dynl.c - dynamic linking
2 *
a80a90e9 3 * Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999 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"
8e3ab003 68#include "keywords.h"
80bc7890 69
1edae076
MV
70/* Converting a list of SCM strings into a argv-style array. You must
71 have ints disabled for the whole lifetime of the created argv (from
72 before MAKE_ARGV_FROM_STRINGLIST until after
73 MUST_FREE_ARGV). Atleast this is was the documentation for
74 MAKARGVFROMSTRS says, it isn't really used that way.
75
76 This code probably belongs into strings.c */
77
78static char **scm_make_argv_from_stringlist SCM_P ((SCM args, int *argcp,
3eeba8d4 79 const char *subr, int argn));
1edae076
MV
80
81static char **
82scm_make_argv_from_stringlist (args, argcp, subr, argn)
83 SCM args;
84 int *argcp;
3eeba8d4 85 const char *subr;
1edae076
MV
86 int argn;
87{
88 char **argv;
89 int argc, i;
90
91 argc = scm_ilength(args);
92 argv = (char **) scm_must_malloc ((1L+argc)*sizeof(char *), subr);
93 for(i = 0; SCM_NNULLP (args); args = SCM_CDR (args), i++) {
94 size_t len;
95 char *dst, *src;
96 SCM str = SCM_CAR (args);
97
98 SCM_ASSERT (SCM_NIMP (str) && SCM_ROSTRINGP (str), str, argn, subr);
99 len = 1 + SCM_ROLENGTH (str);
100 dst = (char *) scm_must_malloc ((long)len, subr);
101 src = SCM_ROCHARS (str);
102 while (len--)
103 dst[len] = src[len];
104 argv[i] = dst;
105 }
106
107 if (argcp)
108 *argcp = argc;
109 argv[argc] = 0;
110 return argv;
111}
112
113static void scm_must_free_argv SCM_P ((char **argv));
114
115static void
116scm_must_free_argv(argv)
117 char **argv;
118{
119 char **av = argv;
c3e09ef9
MD
120 while (*av)
121 free(*(av++));
1edae076
MV
122 free(argv);
123}
124
125/* Coerce an arbitrary readonly-string into a zero-terminated string.
126 */
127
3eeba8d4 128static SCM scm_coerce_rostring SCM_P ((SCM rostr, const char *subr, int argn));
1edae076
MV
129
130static SCM
131scm_coerce_rostring (rostr, subr, argn)
132 SCM rostr;
3eeba8d4 133 const char *subr;
1edae076
MV
134 int argn;
135{
136 SCM_ASSERT (SCM_NIMP (rostr) && SCM_ROSTRINGP (rostr), rostr, argn, subr);
137 if (SCM_SUBSTRP (rostr))
138 rostr = scm_makfromstr (SCM_ROCHARS (rostr), SCM_ROLENGTH (rostr), 0);
139 return rostr;
140}
141
80bc7890
MV
142/* Module registry
143 */
144
145/* We can't use SCM objects here. One should be able to call
146 SCM_REGISTER_MODULE from a C++ constructor for a static
147 object. This happens before main and thus before libguile is
148 initialized. */
149
150struct moddata {
151 struct moddata *link;
152 char *module_name;
153 void *init_func;
154};
155
156static struct moddata *registered_mods = NULL;
157
158void
159scm_register_module_xxx (module_name, init_func)
160 char *module_name;
161 void *init_func;
162{
163 struct moddata *md;
164
165 /* XXX - should we (and can we) DEFER_INTS here? */
166
167 for (md = registered_mods; md; md = md->link)
168 if (!strcmp (md->module_name, module_name)) {
169 md->init_func = init_func;
170 return;
171 }
172
173 md = (struct moddata *)malloc (sizeof (struct moddata));
96599e6a
MV
174 if (md == NULL) {
175 fprintf (stderr,
176 "guile: can't register module (%s): not enough memory",
177 module_name);
80bc7890 178 return;
96599e6a 179 }
80bc7890
MV
180
181 md->module_name = module_name;
182 md->init_func = init_func;
183 md->link = registered_mods;
184 registered_mods = md;
185}
186
187SCM_PROC (s_registered_modules, "c-registered-modules", 0, 0, 0, scm_registered_modules);
188
189SCM
190scm_registered_modules ()
191{
192 SCM res;
193 struct moddata *md;
194
195 res = SCM_EOL;
196 for (md = registered_mods; md; md = md->link)
197 res = scm_cons (scm_cons (scm_makfrom0str (md->module_name),
198 scm_ulong2num ((unsigned long) md->init_func)),
199 res);
200 return res;
201}
202
203SCM_PROC (s_clear_registered_modules, "c-clear-registered-modules", 0, 0, 0, scm_clear_registered_modules);
204
205SCM
206scm_clear_registered_modules ()
207{
208 struct moddata *md1, *md2;
209
210 SCM_DEFER_INTS;
211
212 for (md1 = registered_mods; md1; md1 = md2) {
213 md2 = md1->link;
214 free (md1);
215 }
216 registered_mods = NULL;
217
218 SCM_ALLOW_INTS;
219 return SCM_UNSPECIFIED;
220}
221
1edae076 222/* Dispatch to the system dependent files
80bc7890 223 *
419e9e11
MV
224 * They define some static functions. These functions are called with
225 * deferred interrupts. When they want to throw errors, they are
226 * expected to insert a SCM_ALLOW_INTS before doing the throw. It
227 * might work to throw an error while interrupts are deferred (because
228 * they will be unconditionally allowed the next time a SCM_ALLOW_INTS
229 * is executed, SCM_DEFER_INTS and SCM_ALLOW_INTS do not nest).
1edae076
MV
230 */
231
8e3ab003
MV
232#define DYNL_GLOBAL 0x0001
233
80bc7890 234static void sysdep_dynl_init SCM_P ((void));
8e3ab003
MV
235static void *sysdep_dynl_link SCM_P ((const char *filename, int flags,
236 const char *subr));
3eeba8d4
JB
237static void sysdep_dynl_unlink SCM_P ((void *handle, const char *subr));
238static void *sysdep_dynl_func SCM_P ((const char *symbol, void *handle,
239 const char *subr));
80bc7890 240
26c41b99 241#ifdef HAVE_DLOPEN
1edae076
MV
242#include "dynl-dl.c"
243#else
244#ifdef HAVE_SHL_LOAD
245#include "dynl-shl.c"
246#else
26c41b99 247#ifdef HAVE_LIBDLD
1edae076 248#include "dynl-dld.c"
96599e6a
MV
249#else
250
251/* no dynamic linking available, throw errors. */
252
253static void
254sysdep_dynl_init ()
255{
256}
257
258static void
a80a90e9 259no_dynl_error (const char *subr)
96599e6a 260{
419e9e11
MV
261 SCM_ALLOW_INTS;
262 scm_misc_error (subr, "dynamic linking not available", SCM_EOL);
96599e6a
MV
263}
264
265static void *
8e3ab003
MV
266sysdep_dynl_link (const char *filename,
267 int flags,
a80a90e9 268 const char *subr)
96599e6a
MV
269{
270 no_dynl_error (subr);
271 return NULL;
272}
273
274static void
a80a90e9
JB
275sysdep_dynl_unlink (void *handle,
276 const char *subr)
96599e6a
MV
277{
278 no_dynl_error (subr);
279}
280
281static void *
a80a90e9
JB
282sysdep_dynl_func (const char *symbol,
283 void *handle,
284 const char *subr)
96599e6a
MV
285{
286 no_dynl_error (subr);
287 return NULL;
288}
289
80bc7890
MV
290#endif
291#endif
292#endif
293
294int scm_tc16_dynamic_obj;
295
296struct dynl_obj {
297 SCM filename;
298 void *handle;
299};
300
301static SCM mark_dynl_obj SCM_P ((SCM ptr));
302static SCM
303mark_dynl_obj (ptr)
304 SCM ptr;
305{
306 struct dynl_obj *d = (struct dynl_obj *)SCM_CDR (ptr);
80bc7890
MV
307 return d->filename;
308}
309
c487ad44
MV
310static scm_sizet free_dynl_obj SCM_P ((SCM ptr));
311static scm_sizet
312free_dynl_obj (ptr)
313 SCM ptr;
314{
315 scm_must_free ((char *)SCM_CDR (ptr));
316 return sizeof (struct dynl_obj);
317}
318
80bc7890
MV
319static int print_dynl_obj SCM_P ((SCM exp, SCM port, scm_print_state *pstate));
320static int
321print_dynl_obj (exp, port, pstate)
322 SCM exp;
323 SCM port;
324 scm_print_state *pstate;
325{
326 struct dynl_obj *d = (struct dynl_obj *)SCM_CDR (exp);
b7f3516f 327 scm_puts ("#<dynamic-object ", port);
80bc7890 328 scm_iprin1 (d->filename, port, pstate);
1fe1799f 329 if (d->handle == NULL)
b7f3516f
TT
330 scm_puts (" (unlinked)", port);
331 scm_putc ('>', port);
80bc7890
MV
332 return 1;
333}
334
8e3ab003
MV
335static SCM kw_global;
336SCM_SYMBOL (sym_global, "-global");
337
338SCM_PROC (s_dynamic_link, "dynamic-link", 1, 0, 1, scm_dynamic_link);
80bc7890
MV
339
340SCM
8e3ab003 341scm_dynamic_link (fname, rest)
80bc7890 342 SCM fname;
8e3ab003 343 SCM rest;
80bc7890
MV
344{
345 SCM z;
c487ad44 346 void *handle;
80bc7890 347 struct dynl_obj *d;
8e3ab003 348 int flags = DYNL_GLOBAL;
80bc7890
MV
349
350 fname = scm_coerce_rostring (fname, s_dynamic_link, SCM_ARG1);
c487ad44 351
8e3ab003
MV
352 /* collect flags */
353 while (SCM_NIMP (rest) && SCM_CONSP (rest))
354 {
355 SCM kw, val;
356
357 kw = SCM_CAR (rest);
358 rest = SCM_CDR (rest);
359
360 if (!(SCM_NIMP (rest) && SCM_CONSP (rest)))
361 scm_misc_error (s_dynamic_link, "keyword without value", SCM_EOL);
362
363 val = SCM_CAR (rest);
364 rest = SCM_CDR (rest);
365
366 if (kw == kw_global)
367 {
368 if (SCM_FALSEP (val))
369 flags &= ~DYNL_GLOBAL;
370 }
371 else
372 scm_misc_error (s_dynamic_link, "unknown keyword argument: %s",
373 scm_cons (kw, SCM_EOL));
374 }
375
c487ad44 376 SCM_DEFER_INTS;
8e3ab003 377 handle = sysdep_dynl_link (SCM_CHARS (fname), flags, s_dynamic_link);
c487ad44 378
80bc7890
MV
379 d = (struct dynl_obj *)scm_must_malloc (sizeof (struct dynl_obj),
380 s_dynamic_link);
381 d->filename = fname;
c487ad44 382 d->handle = handle;
80bc7890 383
80bc7890
MV
384 SCM_NEWCELL (z);
385 SCM_SETCHARS (z, d);
386 SCM_SETCAR (z, scm_tc16_dynamic_obj);
387 SCM_ALLOW_INTS;
388
389 return z;
390}
391
3eeba8d4 392static struct dynl_obj *get_dynl_obj SCM_P ((SCM obj, const char *subr, int argn));
80bc7890
MV
393static struct dynl_obj *
394get_dynl_obj (dobj, subr, argn)
395 SCM dobj;
3eeba8d4 396 const char *subr;
80bc7890
MV
397 int argn;
398{
399 struct dynl_obj *d;
400 SCM_ASSERT (SCM_NIMP (dobj) && SCM_CAR (dobj) == scm_tc16_dynamic_obj,
401 dobj, argn, subr);
402 d = (struct dynl_obj *)SCM_CDR (dobj);
403 SCM_ASSERT (d->handle != NULL, dobj, argn, subr);
404 return d;
405}
406
407SCM_PROC (s_dynamic_object_p, "dynamic-object?", 1, 0, 0, scm_dynamic_object_p);
408
409SCM
410scm_dynamic_object_p (SCM obj)
411{
412 return (SCM_NIMP (obj) && SCM_CAR (obj) == scm_tc16_dynamic_obj)?
413 SCM_BOOL_T : SCM_BOOL_F;
414}
415
416SCM_PROC (s_dynamic_unlink, "dynamic-unlink", 1, 0, 0, scm_dynamic_unlink);
417
418SCM
419scm_dynamic_unlink (dobj)
420 SCM dobj;
421{
422 struct dynl_obj *d = get_dynl_obj (dobj, s_dynamic_unlink, SCM_ARG1);
419e9e11 423 SCM_DEFER_INTS;
80bc7890
MV
424 sysdep_dynl_unlink (d->handle, s_dynamic_unlink);
425 d->handle = NULL;
419e9e11
MV
426 SCM_ALLOW_INTS;
427 return SCM_UNSPECIFIED;
80bc7890
MV
428}
429
430SCM_PROC (s_dynamic_func, "dynamic-func", 2, 0, 0, scm_dynamic_func);
431
432SCM
433scm_dynamic_func (SCM symb, SCM dobj)
434{
435 struct dynl_obj *d;
436 void (*func) ();
437
438 symb = scm_coerce_rostring (symb, s_dynamic_func, SCM_ARG1);
439 d = get_dynl_obj (dobj, s_dynamic_func, SCM_ARG2);
440
419e9e11 441 SCM_DEFER_INTS;
cdbadcac
JB
442 func = (void (*) ()) sysdep_dynl_func (SCM_CHARS (symb), d->handle,
443 s_dynamic_func);
419e9e11
MV
444 SCM_ALLOW_INTS;
445
80bc7890
MV
446 return scm_ulong2num ((unsigned long)func);
447}
448
449SCM_PROC (s_dynamic_call, "dynamic-call", 2, 0, 0, scm_dynamic_call);
450
451SCM
452scm_dynamic_call (SCM func, SCM dobj)
453{
454 void (*fptr)();
455
456 if (SCM_NIMP (func) && SCM_ROSTRINGP (func))
457 func = scm_dynamic_func (func, dobj);
458 fptr = (void (*)()) scm_num2ulong (func, (char *)SCM_ARG1, s_dynamic_call);
419e9e11 459 SCM_DEFER_INTS;
80bc7890 460 fptr ();
419e9e11
MV
461 SCM_ALLOW_INTS;
462 return SCM_UNSPECIFIED;
80bc7890
MV
463}
464
465SCM_PROC (s_dynamic_args_call, "dynamic-args-call", 3, 0, 0, scm_dynamic_args_call);
466
467SCM
468scm_dynamic_args_call (func, dobj, args)
469 SCM func, dobj, args;
470{
471 int (*fptr) (int argc, char **argv);
472 int result, argc;
473 char **argv;
474
475 if (SCM_NIMP (func) && SCM_ROSTRINGP (func))
476 func = scm_dynamic_func (func, dobj);
477
478 fptr = (int (*)(int, char **)) scm_num2ulong (func, (char *)SCM_ARG1,
479 s_dynamic_args_call);
419e9e11 480 SCM_DEFER_INTS;
80bc7890
MV
481 argv = scm_make_argv_from_stringlist (args, &argc, s_dynamic_args_call,
482 SCM_ARG3);
80bc7890 483 result = (*fptr) (argc, argv);
80bc7890 484 scm_must_free_argv (argv);
419e9e11
MV
485 SCM_ALLOW_INTS;
486
80bc7890
MV
487 return SCM_MAKINUM(0L+result);
488}
489
1edae076
MV
490void
491scm_init_dynamic_linking ()
492{
23a62151
MD
493 scm_tc16_dynamic_obj = scm_make_smob_type_mfpe ("dynamic-object", sizeof (struct dynl_obj),
494 mark_dynl_obj, free_dynl_obj,
495 print_dynl_obj, NULL);
80bc7890
MV
496 sysdep_dynl_init ();
497#include "dynl.x"
8e3ab003 498 kw_global = scm_make_keyword_from_dash_symbol (sym_global);
1edae076 499}