Initial revision
[bpt/guile.git] / libguile / dynl-dl.c
CommitLineData
1edae076
MV
1/* dynl-dl.c - dynamic linking for dlopen/dlsym
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
48#include "_scm.h"
49#include "genio.h"
50#include "smob.h"
51
52#include <dlfcn.h>
53
54#define SHL(obj) ((void*)SCM_CDR(obj))
55
56#ifdef RTLD_LAZY /* Solaris 2. */
57# define DLOPEN_MODE RTLD_LAZY
58#else
59# define DLOPEN_MODE 1 /* Thats what it says in the man page. */
60#endif
61
62static scm_sizet frshl SCM_P ((SCM ptr));
63
64static scm_sizet
65frshl (ptr)
66 SCM ptr;
67{
68#if 0
69 /* Should freeing a shl close and possibly unmap the object file it */
70 /* refers to? */
71 if (SHL(ptr))
72 dlclose (SHL(ptr));
73#endif
74 return 0;
75}
76
77static int prinshl SCM_P ((SCM exp, SCM port, scm_print_state *pstate));
78
79static int
80prinshl (exp, port, pstate)
81 SCM exp;
82 SCM port;
83 scm_print_state *pstate;
84{
85 scm_gen_puts (scm_regular_string, "#<dynamic-linked ", port);
86 scm_intprint (SCM_CDR (exp), 16, port);
87 scm_gen_putc ('>', port);
88 return 1;
89}
90
91int scm_tc16_shl;
92static scm_smobfuns shlsmob = { scm_mark0, frshl, prinshl };
93
94SCM_PROC (s_dynamic_link, "dynamic-link", 1, 0, 0, scm_dynamic_link);
95
96SCM
97scm_dynamic_link (fname)
98 SCM fname;
99{
100 SCM z;
101 void *handle;
102
103 /* if FALSEP(fname) return fname; XXX - ? */
104
105 fname = scm_coerce_rostring (fname, s_dynamic_link, SCM_ARG1);
106
107 SCM_DEFER_INTS;
108 handle = dlopen (SCM_CHARS (fname), DLOPEN_MODE);
109 if (NULL == handle)
110 scm_misc_error (s_dynamic_link, (char *)dlerror (), SCM_EOL);
111 SCM_NEWCELL (z);
112 SCM_SETCHARS (z, handle);
113 SCM_SETCAR (z, scm_tc16_shl);
114 SCM_ALLOW_INTS;
115
116 return z;
117}
118
119static void *get_func SCM_P ((void *handle, char *func, char *subr));
120
121static void *
122get_func (handle, func, subr)
123 void *handle;
124 char *func;
125 char *subr;
126{
127 void *fptr;
128 char *err;
129
130 fptr = dlsym (handle, func);
131 err = (char *)dlerror ();
132 if (!fptr)
133 scm_misc_error (subr, err? err : "symbol has NULL address", SCM_EOL);
134 return fptr;
135}
136
137SCM_PROC (s_dynamic_call, "dynamic-call", 2, 0, 0, scm_dynamic_call);
138
139SCM
140scm_dynamic_call (symb, shl)
141 SCM symb, shl;
142{
143 void (*func) SCM_P ((void)) = 0;
144
145 symb = scm_coerce_rostring (symb, s_dynamic_call, SCM_ARG1);
146 SCM_ASSERT (SCM_NIMP (shl) && SCM_CAR (shl) == scm_tc16_shl, shl,
147 SCM_ARG2, s_dynamic_call);
148
149 SCM_DEFER_INTS;
150 func = get_func (SHL(shl), SCM_CHARS (symb), s_dynamic_call);
151 SCM_ALLOW_INTS;
152
153 (*func) ();
154
155 return SCM_BOOL_T;
156}
157
158SCM_PROC (s_dynamic_args_call, "dynamic-args-call", 3, 0, 0, scm_dynamic_args_call);
159
160SCM
161scm_dynamic_args_call (symb, shl, args)
162 SCM symb, shl, args;
163{
164 int i, argc;
165 char **argv;
166 int (*func) SCM_P ((int argc, char **argv)) = 0;
167
168 symb = scm_coerce_rostring (symb, s_dynamic_args_call, SCM_ARG1);
169 SCM_ASSERT (SCM_NIMP (shl) && SCM_CAR (shl) == scm_tc16_shl, shl,
170 SCM_ARG2, s_dynamic_args_call);
171
172 SCM_DEFER_INTS;
173 func = get_func (SHL(shl), SCM_CHARS (symb), s_dynamic_args_call);
174 argv = scm_make_argv_from_stringlist (args, &argc, s_dynamic_args_call,
175 SCM_ARG3);
176 SCM_ALLOW_INTS;
177
178 i = (*func) (argc, argv);
179
180 SCM_DEFER_INTS;
181 scm_must_free_argv(argv);
182 SCM_ALLOW_INTS;
183 return SCM_MAKINUM(0L+i);
184}
185
186SCM_PROC (s_dynamic_unlink, "dynamic-unlink", 1, 0, 0, scm_dynamic_unlink);
187
188SCM
189scm_dynamic_unlink (shl)
190 SCM shl;
191{
192 int status;
193
194 SCM_ASSERT (SCM_NIMP (shl) && SCM_CAR (shl) == scm_tc16_shl, shl,
195 SCM_ARG1, s_dynamic_unlink);
196
197 SCM_DEFER_INTS;
198 status = dlclose (SHL(shl));
199 SCM_SETCHARS (shl, NULL);
200 SCM_ALLOW_INTS;
201
202 if (status)
203 scm_misc_error (s_dynamic_unlink, (char *)dlerror (), SCM_EOL);
204 return SCM_BOOL_T;
205}
206
207void
208scm_init_dynamic_linking ()
209{
210 scm_tc16_shl = scm_newsmob (&shlsmob);
211#include "dynl.x"
212}