* fluids.c: Removed use of assert.h (in order to avoid
[bpt/guile.git] / libguile / dynl.c
CommitLineData
1edae076
MV
1/* dynl.c - dynamic linking
2 *
96599e6a 3 * Copyright (C) 1990-1997 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);
305 SCM_SETGC8MARK (ptr);
306 return d->filename;
307}
308
c487ad44
MV
309static scm_sizet free_dynl_obj SCM_P ((SCM ptr));
310static scm_sizet
311free_dynl_obj (ptr)
312 SCM ptr;
313{
314 scm_must_free ((char *)SCM_CDR (ptr));
315 return sizeof (struct dynl_obj);
316}
317
80bc7890
MV
318static int print_dynl_obj SCM_P ((SCM exp, SCM port, scm_print_state *pstate));
319static int
320print_dynl_obj (exp, port, pstate)
321 SCM exp;
322 SCM port;
323 scm_print_state *pstate;
324{
325 struct dynl_obj *d = (struct dynl_obj *)SCM_CDR (exp);
b7f3516f 326 scm_puts ("#<dynamic-object ", port);
80bc7890 327 scm_iprin1 (d->filename, port, pstate);
1fe1799f 328 if (d->handle == NULL)
b7f3516f
TT
329 scm_puts (" (unlinked)", port);
330 scm_putc ('>', port);
80bc7890
MV
331 return 1;
332}
333
334static scm_smobfuns dynl_obj_smob = {
335 mark_dynl_obj,
c487ad44 336 free_dynl_obj,
80bc7890
MV
337 print_dynl_obj
338};
339
340SCM_PROC (s_dynamic_link, "dynamic-link", 1, 0, 0, scm_dynamic_link);
341
342SCM
343scm_dynamic_link (fname)
344 SCM fname;
345{
346 SCM z;
c487ad44 347 void *handle;
80bc7890
MV
348 struct dynl_obj *d;
349
350 fname = scm_coerce_rostring (fname, s_dynamic_link, SCM_ARG1);
c487ad44
MV
351
352 SCM_DEFER_INTS;
353 handle = sysdep_dynl_link (SCM_CHARS (fname), s_dynamic_link);
354
80bc7890
MV
355 d = (struct dynl_obj *)scm_must_malloc (sizeof (struct dynl_obj),
356 s_dynamic_link);
357 d->filename = fname;
c487ad44 358 d->handle = handle;
80bc7890 359
80bc7890
MV
360 SCM_NEWCELL (z);
361 SCM_SETCHARS (z, d);
362 SCM_SETCAR (z, scm_tc16_dynamic_obj);
363 SCM_ALLOW_INTS;
364
365 return z;
366}
367
368static struct dynl_obj *get_dynl_obj SCM_P ((SCM obj, char *subr, int argn));
369static struct dynl_obj *
370get_dynl_obj (dobj, subr, argn)
371 SCM dobj;
372 char *subr;
373 int argn;
374{
375 struct dynl_obj *d;
376 SCM_ASSERT (SCM_NIMP (dobj) && SCM_CAR (dobj) == scm_tc16_dynamic_obj,
377 dobj, argn, subr);
378 d = (struct dynl_obj *)SCM_CDR (dobj);
379 SCM_ASSERT (d->handle != NULL, dobj, argn, subr);
380 return d;
381}
382
383SCM_PROC (s_dynamic_object_p, "dynamic-object?", 1, 0, 0, scm_dynamic_object_p);
384
385SCM
386scm_dynamic_object_p (SCM obj)
387{
388 return (SCM_NIMP (obj) && SCM_CAR (obj) == scm_tc16_dynamic_obj)?
389 SCM_BOOL_T : SCM_BOOL_F;
390}
391
392SCM_PROC (s_dynamic_unlink, "dynamic-unlink", 1, 0, 0, scm_dynamic_unlink);
393
394SCM
395scm_dynamic_unlink (dobj)
396 SCM dobj;
397{
398 struct dynl_obj *d = get_dynl_obj (dobj, s_dynamic_unlink, SCM_ARG1);
419e9e11 399 SCM_DEFER_INTS;
80bc7890
MV
400 sysdep_dynl_unlink (d->handle, s_dynamic_unlink);
401 d->handle = NULL;
419e9e11
MV
402 SCM_ALLOW_INTS;
403 return SCM_UNSPECIFIED;
80bc7890
MV
404}
405
406SCM_PROC (s_dynamic_func, "dynamic-func", 2, 0, 0, scm_dynamic_func);
407
408SCM
409scm_dynamic_func (SCM symb, SCM dobj)
410{
411 struct dynl_obj *d;
412 void (*func) ();
413
414 symb = scm_coerce_rostring (symb, s_dynamic_func, SCM_ARG1);
415 d = get_dynl_obj (dobj, s_dynamic_func, SCM_ARG2);
416
419e9e11 417 SCM_DEFER_INTS;
cdbadcac
JB
418 func = (void (*) ()) sysdep_dynl_func (SCM_CHARS (symb), d->handle,
419 s_dynamic_func);
419e9e11
MV
420 SCM_ALLOW_INTS;
421
80bc7890
MV
422 return scm_ulong2num ((unsigned long)func);
423}
424
425SCM_PROC (s_dynamic_call, "dynamic-call", 2, 0, 0, scm_dynamic_call);
426
427SCM
428scm_dynamic_call (SCM func, SCM dobj)
429{
430 void (*fptr)();
431
432 if (SCM_NIMP (func) && SCM_ROSTRINGP (func))
433 func = scm_dynamic_func (func, dobj);
434 fptr = (void (*)()) scm_num2ulong (func, (char *)SCM_ARG1, s_dynamic_call);
419e9e11 435 SCM_DEFER_INTS;
80bc7890 436 fptr ();
419e9e11
MV
437 SCM_ALLOW_INTS;
438 return SCM_UNSPECIFIED;
80bc7890
MV
439}
440
441SCM_PROC (s_dynamic_args_call, "dynamic-args-call", 3, 0, 0, scm_dynamic_args_call);
442
443SCM
444scm_dynamic_args_call (func, dobj, args)
445 SCM func, dobj, args;
446{
447 int (*fptr) (int argc, char **argv);
448 int result, argc;
449 char **argv;
450
451 if (SCM_NIMP (func) && SCM_ROSTRINGP (func))
452 func = scm_dynamic_func (func, dobj);
453
454 fptr = (int (*)(int, char **)) scm_num2ulong (func, (char *)SCM_ARG1,
455 s_dynamic_args_call);
419e9e11 456 SCM_DEFER_INTS;
80bc7890
MV
457 argv = scm_make_argv_from_stringlist (args, &argc, s_dynamic_args_call,
458 SCM_ARG3);
80bc7890 459 result = (*fptr) (argc, argv);
80bc7890 460 scm_must_free_argv (argv);
419e9e11
MV
461 SCM_ALLOW_INTS;
462
80bc7890
MV
463 return SCM_MAKINUM(0L+result);
464}
465
1edae076
MV
466void
467scm_init_dynamic_linking ()
468{
80bc7890
MV
469 scm_tc16_dynamic_obj = scm_newsmob (&dynl_obj_smob);
470 sysdep_dynl_init ();
471#include "dynl.x"
1edae076 472}