Initial revision
authorMarius Vollmer <mvo@zagadka.de>
Sun, 8 Dec 1996 16:52:38 +0000 (16:52 +0000)
committerMarius Vollmer <mvo@zagadka.de>
Sun, 8 Dec 1996 16:52:38 +0000 (16:52 +0000)
libguile/DYNAMIC-LINKING [new file with mode: 0644]
libguile/dynl-dl.c [new file with mode: 0644]
libguile/dynl-dld.c [new file with mode: 0644]
libguile/dynl-shl.c [new file with mode: 0644]
libguile/dynl-vms.c [new file with mode: 0644]
libguile/dynl.c [new file with mode: 0644]
libguile/dynl.h [new file with mode: 0644]

diff --git a/libguile/DYNAMIC-LINKING b/libguile/DYNAMIC-LINKING
new file mode 100644 (file)
index 0000000..5a5be2a
--- /dev/null
@@ -0,0 +1,94 @@
+Random notes about dynamic linking for Guile. I will update this file
+as I go along. Comments are very welcome.
+
+The dynamic linking support is mostly untested. I can't test it
+because I don't have all the different platforms, of course. Please
+try it out.
+
+To enable support for dynamic linking in libguile, give the
+
+    --enable-dynamic-linking
+
+option to configure. It is disabled by default because it will
+probably cause lots of problems in its present state. Currently there
+is support for -ldld, -ldl, HP-UX (and VMS, but not really).
+
+Files affected:
+
+ dynl*           new
+ configure.in    add --enable-dynamic-linking option and checking for
+                 system dependencies
+ Makefile.am     include dynl* in build and dist.
+ init.c          initialize dynamic linking support
+
+Here is my plan with indications of progress.
+
+- port "dynl.c" and maybe some parts of "Link.scm" from SCM to
+  Guile. This should not be difficult, maybe I can even squeeze the
+  VMS code into the "dynl:link", "dyn:call" interface.
+
+* Mostly done, except VMS, and almost completely untested. The -dl
+  support should work, but the rest has not even been compiled.
+
+  The code is in the "dynl*" files. "dynl.c" is the system independent
+  portion and includes the appropriate system dependent file, either
+  "dynl-dld.c", "dynl-dl.c" or "dynl-shl.c".
+
+  I have renamed the SCM names of the functions, because they didnn't
+  fit very well into Guile, the semantics are the same:
+
+    SCM name       Guile name
+
+    dynl:link      dynamic-link
+    dynl:call      dynamic-call
+    dynl:main-call dynamic-args-call
+    dynl:unlink    dynamic-unlink
+
+  I plan to generalise dynamic-call and dynamic-args-call to work with
+  arbitrary arguments, so these names are likely to change.
+
+  PROBLEMS:
+
+  When including dynlink support in libguile you need to link your
+  applications with additional libraries (-ldl or -ldld). How do you
+  communicate this to "guile" and "gh_test" for example? Some PLUGIN
+  magic?
+
+  You may need to link your application in a special way to make
+  dynamic linking work. For example, on Linux and a statically linked
+  libguile.a, you need -rdynamic to make the libguile symbols
+  available for dynamic linking. The solution is probably to build
+  libguile as a shared library on the systems that support it. Does
+  libtool help here? Where can I find it?
+
+
+- see how to couple dynamic linking with the module system. Dynamic
+  objects should have a way to specify the module they want to add
+  their bindings to. Extend this to statically linked parts of
+  guile. (i.e. posix could be put into a module and initialized on
+  demand)
+
+* Maybe it will suffice to have scm_make_gsubr, etc to honor the
+  current scm_top_level_lookup_closure and do all the module switching
+  from Scheme.
+
+
+- use gtcltk as a test case for the above, so that TCL/Tk capabilities
+  can be added to guile at runtime.
+
+- see how G-Wrap and libffi can work together and extend dyn:call to
+  functions taking arbitrary arguments. Something along the lines
+
+    (define XOpenDisplay (make-foreign-function X11-lib 'XOpenDisplay
+                                               .. whatever args ..))
+
+
+I have no ideas how to support the development of packages for Guile
+that can be dynamically linked into a running application.  Maybe
+automake can be used to automate most of the issues.
+
+One nice thing is, however, that developers and users of Guile
+packages have already installed Guile. So we might able to use Scheme
+to describe and handle the build process. I would like that much more
+than the arcane shell based implementations of autoconf, automake,
+etc.
diff --git a/libguile/dynl-dl.c b/libguile/dynl-dl.c
new file mode 100644 (file)
index 0000000..7899b32
--- /dev/null
@@ -0,0 +1,212 @@
+/* dynl-dl.c - dynamic linking for dlopen/dlsym
+ *
+ * Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * As a special exception, the Free Software Foundation gives permission
+ * for additional uses of the text contained in its release of GUILE.
+ *
+ * The exception is that, if you link the GUILE library with other files
+ * to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the GUILE library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by the
+ * Free Software Foundation under the name GUILE.  If you copy
+ * code from other Free Software Foundation releases into a copy of
+ * GUILE, as the General Public License permits, the exception does
+ * not apply to the code that you add in this way.  To avoid misleading
+ * anyone as to the status of such modified files, you must delete
+ * this exception notice from them.
+ *
+ * If you write modifications of your own for GUILE, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.  
+ */
+
+/* "dynl.c" dynamically link&load object files.
+   Author: Aubrey Jaffer
+   Modified for libguile by Marius Vollmer */
+
+#include "_scm.h"
+#include "genio.h"
+#include "smob.h"
+
+#include <dlfcn.h>
+
+#define SHL(obj) ((void*)SCM_CDR(obj))
+
+#ifdef RTLD_LAZY       /* Solaris 2. */
+#  define DLOPEN_MODE  RTLD_LAZY
+#else
+#  define DLOPEN_MODE  1       /* Thats what it says in the man page. */
+#endif
+
+static scm_sizet frshl SCM_P ((SCM ptr));
+
+static scm_sizet
+frshl (ptr)
+     SCM ptr;
+{
+#if 0
+    /* Should freeing a shl close and possibly unmap the object file it */
+    /* refers to? */
+    if (SHL(ptr))
+       dlclose (SHL(ptr));
+#endif
+    return 0;
+}
+
+static int prinshl SCM_P ((SCM exp, SCM port, scm_print_state *pstate));
+
+static int
+prinshl (exp, port, pstate)
+     SCM exp;
+     SCM port;
+     scm_print_state *pstate;
+{
+    scm_gen_puts (scm_regular_string, "#<dynamic-linked ", port);
+    scm_intprint (SCM_CDR (exp), 16, port);
+    scm_gen_putc ('>', port);
+    return 1;
+}
+
+int scm_tc16_shl;
+static scm_smobfuns shlsmob = { scm_mark0, frshl, prinshl };
+
+SCM_PROC (s_dynamic_link, "dynamic-link", 1, 0, 0, scm_dynamic_link);
+
+SCM
+scm_dynamic_link (fname)
+     SCM fname;
+{
+    SCM z;
+    void *handle;
+
+    /* if FALSEP(fname) return fname; XXX - ? */
+
+    fname = scm_coerce_rostring (fname, s_dynamic_link, SCM_ARG1);
+
+    SCM_DEFER_INTS;
+    handle = dlopen (SCM_CHARS (fname), DLOPEN_MODE);
+    if (NULL == handle)
+       scm_misc_error (s_dynamic_link, (char *)dlerror (), SCM_EOL);
+    SCM_NEWCELL (z);
+    SCM_SETCHARS (z, handle);
+    SCM_SETCAR (z, scm_tc16_shl);
+    SCM_ALLOW_INTS;
+
+    return z;
+}
+
+static void *get_func SCM_P ((void *handle, char *func, char *subr));
+
+static void *
+get_func (handle, func, subr)
+     void *handle;
+     char *func;
+     char *subr;
+{
+    void *fptr;
+    char *err;
+
+    fptr = dlsym (handle, func);
+    err = (char *)dlerror ();
+    if (!fptr)
+       scm_misc_error (subr, err? err : "symbol has NULL address", SCM_EOL);
+    return fptr;
+}
+
+SCM_PROC (s_dynamic_call, "dynamic-call", 2, 0, 0, scm_dynamic_call);
+
+SCM
+scm_dynamic_call (symb, shl)
+     SCM symb, shl;
+{
+    void (*func) SCM_P ((void)) = 0;
+
+    symb = scm_coerce_rostring (symb, s_dynamic_call, SCM_ARG1);
+    SCM_ASSERT (SCM_NIMP (shl) && SCM_CAR (shl) == scm_tc16_shl, shl,
+               SCM_ARG2, s_dynamic_call);
+
+    SCM_DEFER_INTS;
+    func = get_func (SHL(shl), SCM_CHARS (symb), s_dynamic_call);
+    SCM_ALLOW_INTS;
+
+    (*func) ();
+
+    return SCM_BOOL_T;
+}
+
+SCM_PROC (s_dynamic_args_call, "dynamic-args-call", 3, 0, 0, scm_dynamic_args_call);
+
+SCM
+scm_dynamic_args_call (symb, shl, args)
+     SCM symb, shl, args;
+{
+    int i, argc;
+    char **argv;
+    int (*func) SCM_P ((int argc, char **argv)) = 0;
+
+    symb = scm_coerce_rostring (symb, s_dynamic_args_call, SCM_ARG1);
+    SCM_ASSERT (SCM_NIMP (shl) && SCM_CAR (shl) == scm_tc16_shl, shl,
+               SCM_ARG2, s_dynamic_args_call);
+
+    SCM_DEFER_INTS;
+    func = get_func (SHL(shl), SCM_CHARS (symb), s_dynamic_args_call);
+    argv = scm_make_argv_from_stringlist (args, &argc, s_dynamic_args_call,
+                                     SCM_ARG3);
+    SCM_ALLOW_INTS;
+
+    i = (*func) (argc, argv);
+
+    SCM_DEFER_INTS;
+    scm_must_free_argv(argv);
+    SCM_ALLOW_INTS;
+    return SCM_MAKINUM(0L+i);
+}
+
+SCM_PROC (s_dynamic_unlink, "dynamic-unlink", 1, 0, 0, scm_dynamic_unlink);
+
+SCM
+scm_dynamic_unlink (shl)
+     SCM shl;
+{
+    int status;
+
+    SCM_ASSERT (SCM_NIMP (shl) && SCM_CAR (shl) == scm_tc16_shl, shl,
+               SCM_ARG1, s_dynamic_unlink);
+
+    SCM_DEFER_INTS;
+    status = dlclose (SHL(shl));
+    SCM_SETCHARS (shl, NULL);
+    SCM_ALLOW_INTS;
+
+    if (status)
+       scm_misc_error (s_dynamic_unlink, (char *)dlerror (), SCM_EOL);
+    return SCM_BOOL_T;
+}
+
+void
+scm_init_dynamic_linking ()
+{
+    scm_tc16_shl = scm_newsmob (&shlsmob);
+#include "dynl.x"
+}
diff --git a/libguile/dynl-dld.c b/libguile/dynl-dld.c
new file mode 100644 (file)
index 0000000..aba8b93
--- /dev/null
@@ -0,0 +1,187 @@
+/* dynl-dld.c - dynamic linking with dld
+ *
+ * Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * As a special exception, the Free Software Foundation gives permission
+ * for additional uses of the text contained in its release of GUILE.
+ *
+ * The exception is that, if you link the GUILE library with other files
+ * to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the GUILE library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by the
+ * Free Software Foundation under the name GUILE.  If you copy
+ * code from other Free Software Foundation releases into a copy of
+ * GUILE, as the General Public License permits, the exception does
+ * not apply to the code that you add in this way.  To avoid misleading
+ * anyone as to the status of such modified files, you must delete
+ * this exception notice from them.
+ *
+ * If you write modifications of your own for GUILE, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.  
+ */
+
+/* "dynl.c" dynamically link&load object files.
+   Author: Aubrey Jaffer
+   Modified for libguile by Marius Vollmer */
+
+#include "_scm.h"
+#include "genio.h"
+#include "smob.h"
+
+#include "dld.h"
+
+static void listundef SCM_P ((void));
+
+static void
+listundefs ()
+{
+    int i;
+    char **undefs = dld_list_undefined_sym();
+    puts("   undefs:");
+    for(i = dld_undefined_sym_count;i--;) {
+       putc('"', stdout);
+       fputs(undefs[i], stdout);
+       puts("\"");
+    }
+    free(undefs);
+}
+
+SCM_PROC (s_dynamic_link, "dynamic-link", 1, 0, 0, scm_dynamic_link);
+
+SCM
+scm_dynamic_link (fname)
+     SCM fname;
+{
+    int status;
+    
+    fname = scm_coerce_rostring (fname, s_dynamic_link, SCM_ARG1);
+
+    SCM_DEFER_INTS;
+    status = dld_link (SCM_CHARS (fname));
+    SCM_ALLOW_INTS;
+    if (status)
+       scm_misc_error (s_dynamic_link, dld_strerror (status), SCM_EOL);
+    return fname;
+}
+
+static void *get_func SCM_P ((char *subr, char *fname));
+
+static void *
+get_func (subr, fname)
+     char *subr;
+     char *fname;
+{
+    void *func;
+
+    if (!dld_function_executable_p (func)) {
+       listundefs ();
+       scm_misc_error (subr, "unresolved symbols remain", SCM_EOL);
+    }
+    func = (void *) dld_get_func (func);
+    if (func == 0)
+       scm_misc_error (subr, dld_strerror (dld_errno), SCM_EOL);
+    return func;
+}
+
+SCM_PROC (s_dynamic_call, "dynamic-call", 2, 0, 0, scm_dynamic_call);
+
+SCM
+scm_dynamic_call (symb, shl)
+     SCM symb;
+     SCM shl;
+{
+    void (*func)() = 0;
+
+    symb = scm_coerce_rostring (symb, s_dynamic_call, SCM_ARG1);
+
+    SCM_DEFER_INTS;
+    func = get_func (s_dynamic_call, SCM_CHARS (symb));
+    SCM_ALLOW_INST;
+    (*func) ();
+    return SCM_BOOL_T;
+}
+
+SCM_PROC (s_dynamic_args_call, "dynamic-args-call", 3, 0, 0, scm_dynamic_args_call);
+
+SCM
+scm_dynamic_args_call (symb, shl, args)
+     SCM symb, shl, args;
+{
+    int i, argc;
+    char **argv;
+    int (*func) SCM_P ((int argc, char **argv)) = 0;
+
+    symb = scm_coerce_rostring (symb, s_dynamic_args_call, SCM_ARG1);
+
+    SCM_DEFER_INTS;
+    func = get_func (SCM_CHARS (symb), s_dynamic_args_call);
+    argv = scm_make_argv_from_stringlist (args, &argc, s_dynamic_args_call,
+                                     SCM_ARG3);
+    SCM_ALLOW_INTS;
+
+    i = (*func) (argc, argv);
+
+    SCM_DEFER_INTS;
+    scm_must_free_argv(argv);
+    SCM_ALLOW_INTS;
+    return SCM_MAKINUM(0L+i);
+}
+
+SCM_PROC (s_dynamic_unlink, "dynamic-unlink", 1, 0, 0, scm_dynamic_unlink);
+
+SCM
+scm_dynamic_unlink(fname)
+     SCM fname;
+{
+    int status;
+
+    fname = scm_coerce_rostring (fname, s_dynamic_unlink, SCM_ARG1);
+
+    SCM_DEFER_INTS;
+    status = dld_unlink_by_file (SCM_CHARS (fname), 1);
+    SCM_ALLOW_INTS;
+
+    if (status)
+       scm_misc_error (s_dynamic_unlink, dld_strerror (status), SCM_EOL);
+    return SCM_BOOL_T;
+}
+
+void
+scm_init_dynamic_linking ()
+{
+#ifndef RTL
+    if (!execpath)
+       execpath = dld_find_executable (SCM_CHARS (SCM_CAR (progargs)));
+    if (dld_init (SCM_CHARS (SCM_CAR (progargs)))) {
+       dld_perror("DLD");
+       return;
+    }
+#endif
+
+#include "dynl.x"
+
+#ifdef DLD_DYNCM /* XXX - what's this? */
+    add_feature("dld:dyncm");
+#endif
+}
diff --git a/libguile/dynl-shl.c b/libguile/dynl-shl.c
new file mode 100644 (file)
index 0000000..b8e4744
--- /dev/null
@@ -0,0 +1,172 @@
+/* dynl-shl.c - dynamic linking with shl_load (HP-UX)
+ *
+ * Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * As a special exception, the Free Software Foundation gives permission
+ * for additional uses of the text contained in its release of GUILE.
+ *
+ * The exception is that, if you link the GUILE library with other files
+ * to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the GUILE library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by the
+ * Free Software Foundation under the name GUILE.  If you copy
+ * code from other Free Software Foundation releases into a copy of
+ * GUILE, as the General Public License permits, the exception does
+ * not apply to the code that you add in this way.  To avoid misleading
+ * anyone as to the status of such modified files, you must delete
+ * this exception notice from them.
+ *
+ * If you write modifications of your own for GUILE, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.  
+ */
+
+/* "dynl.c" dynamically link&load object files.
+   Author: Aubrey Jaffer
+   Modified for libguile by Marius Vollmer */
+
+#include "_scm.h"
+#include "genio.h"
+#include "smob.h"
+
+#include "dl.h"
+
+#define SHL(obj) ((shl_t*)SCM_CDR(obj))
+
+static int printshl SCM_P ((SCM exp, SCM port, scm_printstate *pstate));
+
+static int
+prinshl (exp, port, pstate)
+     SCM exp;
+     SCM port;
+     scm_printstate *pstate;
+{
+    scm_gen_puts (scm_regular_string, "#<dynamic-linked ", port);
+    scm_intprint (SCM_CDR (exp), 16, port);
+    scm_gen_putc ('>', port);
+    return 1;
+}
+
+int scm_tc16_shl;
+static scm_smobfuns shlsmob = { scm_mark0, scm_free0, prinshl };
+
+SCM_PROC (s_dynamic_link, "dynamic-link", 1, 0, 0, scm_dynamic_link);
+
+SCM
+scm_dynamic_link (fname)
+     SCM fname;
+{
+    SCM z;
+    shl_t shl;
+    
+    fname = scm_coerce_rostring (fname, s_dynamic_link, SCM_ARG1);
+
+    SCM_DEFER_INTS;
+    shl = shl_load (SCM_CHARS (fname), BIND_DEFERRED , 0L);
+    if (NULL==shl)
+       scm_misc_error (s_dynamic_link, "dynamic linking failed", SCM_EOL);
+    SCM_NEWCELL (z);
+    SCM_SETCHARS (z, shl);
+    SCM_SETCAR (z, scm_tc16_shl);
+    SCM_ALLOW_INTS;
+
+    return z;
+}
+
+SCM_PROC (s_dynamic_call, "dynamic-call", 2, 0, 0, scm_dynamic_call);
+
+SCM
+scm_dynamic_call (symb, shl)
+     SCM symb, shl;
+{
+    void (*func)() = 0;
+    int i;
+
+    symb = scm_coerce_rostring (symb, s_dynamic_call, SCM_ARG1);
+    SCM_ASSERT (SCM_NIMP (shl) && SCM_CAR (shl) == scm_tc16_shl, shl, SCM_ARG2,
+               s_dynamic_call);
+
+    SCM_DEFER_INTS;
+    if (shl_findsym (&SHL(shl), SCM_CHARS(symb), TYPE_PROCEDURE, &func))
+       scm_misc_error (s_dynamic_call, "undefined function",
+                       scm_cons (symb, SCM_EOL));
+    SCM_ALLOW_INTS;
+
+    (*func) ();
+    return SCM_BOOL_T;
+}
+
+SCM_PROC (s_dynamic_args_call, "dynamic-args-call", 3, 0, 0, scm_dynamic_args_call);
+
+SCM
+scm_dynamic_args_call (symb, shl, args)
+     SCM symb, shl, args;
+{
+    int i, argc;
+    char **argv;
+    int (*func) SCM_P ((int argc, char **argv)) = 0; 
+
+    symb = scm_coerce_rostring (symb, s_dynamic_args_call, SCM_ARG1);
+    SCM_ASSERT (SCM_NIMP (shl) && SCM_CAR(shl) == scm_tc16_shl, shl, SCM_ARG2,
+               s_dynamic_args_call);
+
+    SCM_DEFER_INTS;
+    if (shl_findsym(&SHL(shl), SCM_CHARS(symb), TYPE_PROCEDURE, &func)) 
+       scm_misc_error (s_dynamic_call, "undefined function: %s",
+                       scm_cons (symb, SCM_EOL));
+    argv = scm_make_argv_from_stringlist (args, &argc, s_dynamic_args_call,
+                                     SCM_ARG3);
+    SCM_ALLOW_INTS;
+
+    i = (*func) (argc, argv);
+
+    SCM_DEFER_INTS;
+    scm_must_free_argv (argv);
+    SCM_ALLOW_INTS;
+    return SCM_MAKINUM (0L+i);
+}
+
+SCM_PROC (s_dynamic_unlink, "dynamic-unlink", 1, 0, 0, scm_dynamic_unlink);
+
+SCM
+scm_dynamic_unlink (shl)
+     SCM shl;
+{
+    int status;
+    SCM_ASSERT (SCM_NIMP (shl) && SCM_CAR (shl) == scm_tc16_shl, shl,
+               SCM_ARG1, s_dynamic_unlink);
+
+    SCM_DEFER_INTS;
+    status = shl_unload (SHL (shl));
+    SCM_ALLOW_INTS;
+    if (!status)
+       return SCM_BOOL_T;
+    return SCM_BOOL_F;
+}
+
+void
+scm_init_dynamic_linking ()
+{
+    scm_tc16_shl = scm_newsmob (&shlsmob);
+#include "dynl.x"
+}
diff --git a/libguile/dynl-vms.c b/libguile/dynl-vms.c
new file mode 100644 (file)
index 0000000..322839c
--- /dev/null
@@ -0,0 +1,106 @@
+/* dynl-vms.c - dynamic linking for VMS, not yet ported
+ *
+ * Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * As a special exception, the Free Software Foundation gives permission
+ * for additional uses of the text contained in its release of GUILE.
+ *
+ * The exception is that, if you link the GUILE library with other files
+ * to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the GUILE library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by the
+ * Free Software Foundation under the name GUILE.  If you copy
+ * code from other Free Software Foundation releases into a copy of
+ * GUILE, as the General Public License permits, the exception does
+ * not apply to the code that you add in this way.  To avoid misleading
+ * anyone as to the status of such modified files, you must delete
+ * this exception notice from them.
+ *
+ * If you write modifications of your own for GUILE, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.  
+ */
+
+/* "dynl.c" dynamically link&load object files.
+   Author: Aubrey Jaffer
+   (Not yet) modified for libguile by Marius Vollmer */
+
+/* We should try to implement dynamic-link/dynamic-call for VMS,
+   too. */
+
+#include "_scm.h"
+
+/* This permits dynamic linking. For example, the procedure of 0 arguments
+   from a file could be the initialization procedure.
+   (vms:dynamic-link-call "MYDISK:[MYDIR].EXE" "foo" "INIT_FOO")
+   The first argument specifies the directory where the file specified
+   by the second argument resides.  The current directory would be
+   "SYS$DISK:[].EXE".
+   The second argument cannot contain any punctuation.
+   The third argument probably needs to be uppercased to mimic the VMS linker.
+   */
+
+# include <descrip.h>
+# include <ssdef.h>
+# include <rmsdef.h>
+
+struct dsc$descriptor *descriptorize(x, buff)
+     struct dsc$descriptor *x;
+     SCM buff;
+{(*x).dsc$w_length = LENGTH(buff);
+ (*x).dsc$a_pointer = CHARS(buff);
+ (*x).dsc$b_class = DSC$K_CLASS_S;
+ (*x).dsc$b_dtype = DSC$K_DTYPE_T;
+ return(x);}
+
+static char s_dynl[] = "vms:dynamic-link-call";
+SCM dynl(dir, symbol, fname)
+     SCM dir, symbol, fname;
+{
+  struct dsc$descriptor fnamed, symbold, dird;
+  void (*fcn)();
+  long retval;
+  ASSERT(IMP(dir) || STRINGP(dir), dir, ARG1, s_dynl);
+  ASSERT(NIMP(fname) && STRINGP(fname), fname, ARG2, s_dynl);
+  ASSERT(NIMP(symbol) && STRINGP(symbol), symbol, ARG3, s_dynl);
+  descriptorize(&fnamed, fname);
+  descriptorize(&symbold, symbol);
+  DEFER_INTS;
+  retval = lib$find_image_symbol(&fnamed, &symbold, &fcn,
+                                IMP(dir) ? 0 : descriptorize(&dird, dir));
+  if (SS$_NORMAL != retval) {
+    /* wta(MAKINUM(retval), "vms error", s_dynl); */
+    ALLOW_INTS;
+    return BOOL_F;
+  }
+  ALLOW_INTS;
+/*  *loc_loadpath = dir; */
+  (*fcn)();
+/*  *loc_loadpath = oloadpath; */
+  return BOOL_T;
+}
+
+void init_dynl()
+{
+  make_subr(s_dynl, tc7_subr_3, dynl);
+}
diff --git a/libguile/dynl.c b/libguile/dynl.c
new file mode 100644 (file)
index 0000000..800de3d
--- /dev/null
@@ -0,0 +1,147 @@
+/* dynl.c - dynamic linking
+ *
+ * Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * As a special exception, the Free Software Foundation gives permission
+ * for additional uses of the text contained in its release of GUILE.
+ *
+ * The exception is that, if you link the GUILE library with other files
+ * to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the GUILE library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by the
+ * Free Software Foundation under the name GUILE.  If you copy
+ * code from other Free Software Foundation releases into a copy of
+ * GUILE, as the General Public License permits, the exception does
+ * not apply to the code that you add in this way.  To avoid misleading
+ * anyone as to the status of such modified files, you must delete
+ * this exception notice from them.
+ *
+ * If you write modifications of your own for GUILE, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.  
+ */
+
+/* "dynl.c" dynamically link&load object files.
+   Author: Aubrey Jaffer
+   Modified for libguile by Marius Vollmer */
+
+#include "_scm.h"
+
+/* Converting a list of SCM strings into a argv-style array.  You must
+   have ints disabled for the whole lifetime of the created argv (from
+   before MAKE_ARGV_FROM_STRINGLIST until after
+   MUST_FREE_ARGV). Atleast this is was the documentation for
+   MAKARGVFROMSTRS says, it isn't really used that way.
+
+   This code probably belongs into strings.c */
+
+static char **scm_make_argv_from_stringlist SCM_P ((SCM args, int *argcp,
+                                                   char *subr, int argn));
+
+static char **
+scm_make_argv_from_stringlist (args, argcp, subr, argn)
+     SCM args;
+     int *argcp;
+     char *subr;
+     int argn;
+{
+    char **argv;
+    int argc, i;
+
+    argc = scm_ilength(args);
+    argv = (char **) scm_must_malloc ((1L+argc)*sizeof(char *), subr);
+    for(i = 0; SCM_NNULLP (args); args = SCM_CDR (args), i++) {
+       size_t len;
+       char *dst, *src;
+       SCM str = SCM_CAR (args);
+
+       SCM_ASSERT (SCM_NIMP (str) && SCM_ROSTRINGP (str), str, argn, subr);
+       len = 1 + SCM_ROLENGTH (str);
+       dst = (char *) scm_must_malloc ((long)len, subr);
+       src = SCM_ROCHARS (str);
+       while (len--)
+           dst[len] = src[len];
+       argv[i] = dst;
+    }
+
+    if (argcp)
+       *argcp = argc;
+    argv[argc] = 0;
+    return argv;
+}
+
+static void scm_must_free_argv SCM_P ((char **argv));
+
+static void
+scm_must_free_argv(argv)
+     char **argv;
+{
+    char **av = argv;
+    while(!(*av))
+       free(*(av++));
+    free(argv);
+}
+
+/* Coerce an arbitrary readonly-string into a zero-terminated string.
+ */
+
+static SCM scm_coerce_rostring SCM_P ((SCM rostr, char *subr, int argn));
+
+static SCM
+scm_coerce_rostring (rostr, subr, argn)
+     SCM rostr;
+     char *subr;
+     int argn;
+{
+    SCM_ASSERT (SCM_NIMP (rostr) && SCM_ROSTRINGP (rostr), rostr, argn, subr);
+    if (SCM_SUBSTRP (rostr))
+       rostr = scm_makfromstr (SCM_ROCHARS (rostr), SCM_ROLENGTH (rostr), 0);
+    return rostr;
+}
+
+/* Dispatch to the system dependent files
+ */
+
+#ifdef DYNAMIC_LINKING
+#ifdef HAVE_LIBDL
+#include "dynl-dl.c"
+#else
+#ifdef HAVE_SHL_LOAD
+#include "dynl-shl.c"
+#else
+#ifdef HAVE_DLD
+#include "dynl-dld.c"
+#else /* no dynamic linking available */
+void
+scm_init_dynamic_linking ()
+{
+}
+#endif
+#endif
+#endif
+#else /* dynamic linking disabled */
+void
+scm_init_dynamic_linking ()
+{
+}
+#endif
diff --git a/libguile/dynl.h b/libguile/dynl.h
new file mode 100644 (file)
index 0000000..723d2e9
--- /dev/null
@@ -0,0 +1,57 @@
+/*     Copyright (C) 1996 Free Software Foundation, Inc.
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * As a special exception, the Free Software Foundation gives permission
+ * for additional uses of the text contained in its release of GUILE.
+ *
+ * The exception is that, if you link the GUILE library with other files
+ * to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the GUILE library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by the
+ * Free Software Foundation under the name GUILE.  If you copy
+ * code from other Free Software Foundation releases into a copy of
+ * GUILE, as the General Public License permits, the exception does
+ * not apply to the code that you add in this way.  To avoid misleading
+ * anyone as to the status of such modified files, you must delete
+ * this exception notice from them.
+ *
+ * If you write modifications of your own for GUILE, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.  
+ */
+\f
+
+#ifndef LIBGUILE_DYNL_H
+#define LIBGUILE_DYNL_H
+
+#include "libguile/__scm.h"
+
+\f
+
+SCM scm_dynamic_link SCM_P ((SCM fname));
+SCM scm_dynamic_call SCM_P ((SCM symb, SCM shl));
+SCM scm_dynamic_args_call SCM_P ((SCM symb, SCM shl, SCM args));
+SCM scm_dynamic_unlink SCM_P ((SCM shl));
+
+void scm_init_dynamic_linking SCM_P ((void));
+
+#endif  /* LIBGUILE_DYNL_H */