2002-02-27  Dave Love  <fx@gnu.org>

	* configure.in: Add libtool stuff.  Also define
	build_emacs_module, config_includes, and CAN_DLOPEN.  Output
	lib-src/build-emacs-module, libltdl/Makefile.

	* Makefile.in (SUBDIR, clean, mostlyclean, maintainer-clean)
	(distclean): Add libltdl.
	(SUBDIR_MAKEFILES): Add libltdl/Makefile.
	(libltdl/Makefile, install-module-stuff, libtool, LIBTOOL_DEPS)
	(top_builddir): New target.
	(install): Add install-module-stuff.
	(mkdir): Add ${archlibdir}/m ${archlibdir}/s.
	(uninstall): Add libtool, C headers.

	* aclocal.m4: Add libtool stuff.

	* ltdl: New directory.

	* ltconfig, ltmain.sh: New files.

[lib-src]
2002-02-27  Dave Love  <fx@gnu.org>

	* Makefile.in (INSTALLABLE_SCRIPTS): Maybe add build_emacs_module. 
	(UTILITIES): Add make-docfile.
	(DONT_INSTALL): Remove make-docfile.

	* build-emacs-module.in: New file.

[src]
2002-02-27  Dave Love  <fx@gnu.org>

	* Makefile.in (top_srcdir, top_builddir, INCLTDL, LIBLTDL)
	(LIBTOOL): New.
	(ALL_CFLAGS): Add INCLTDL.
	(LINKER, LD): Use LIBTOOL.
	(YMF_PASS_LDFLAGS): Always use trivial definition.
	(LIBES): Add LIBLTDL.

	* doc.c (Vfile_name_coding_system): Declare.
	(snarf_documentation): New function.

	* lread.c [CAN_DLOPEN]: Include ltdl.h.
	(command_loop_level, snarf_documentation, modules_list): Declare.
	(Fload): Support .la module files with lt_dlopen.  Recognize .bz2.
	(defsubr) [CAN_DLOPEN]: Copy sname if evalling.
	(Fdynamic_modules_p): New function.

	* mod-test.c: New file.

--- /dev/null	Thu Nov 30 15:25:58 2000
+++ lib-src/build-emacs-module.in	Tue Mar 19 23:54:53 2002
@@ -0,0 +1,105 @@
+#! /bin/sh
+
+# Build dynamically-loadable modules from source.
+
+# Copyright (C) 2002 Free Software Foundation Inc.
+
+# Author: Dave Love <fx@gnu.org>
+
+# This file 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 file 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 GNU Emacs; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+exec_prefix="@exec_prefix@"
+version=@version@
+configuration=@configuration@
+libexecdir="@libexecdir@"
+dest=`pwd`
+# Could set this in the environment to use uninstalled, assuming lisp.h,
+# cofig.h and make-docfile are all in the same place.
+archlibdir=${archlibdir:-@archlibdir@}
+
+while test $# -gt 0
+do
+  case "$1" in
+      --help)
+          echo "\
+Usage: build-emacs-module [--cflags CFLAGS] [--ldflags LDFLAGS] \\
+           [--dest DIRECTORY] FILE...
+
+Compile C module source FILEs into files for dynamically loading the
+module into Emacs.  CFLAGS and LDFLAGS (both single arguments) specify
+flags respectively for compiling and linking in addition to those used
+to build Emacs.  if the module needs to link against extra libraries,
+put the relevant -L and -l flags in LDFLAGS.  DEST is a directory into
+which to install the module (default current directory).  This must be
+in the Emacs load-path list when the module is loaded.  E.g.:
+  build-emacs-module --ldflags '-lfoo -L/usr/local/lib/foodir' foo.c
+
+Two module files are installed for each FILE with the same base name
+as FILE, one with extension .la and the other with extension
+appropriate for a shared library, e.g. .so on an ELF system.  A file
+of documentation strings with extension .doc is installed too.
+
+Dynamically-linked modules must comply ith the Emacs licence (the GNU GPL)
+just as if they were statically linked."
+          exit;;
+      --version)
+          echo "build-emacs-module Emacs @version@
+Copyright (C) Free Software Foundation, Inc.
+This program is distributed under the same terms as Emacs."
+          exit ;;
+      --cflags)
+          shift
+          cflags="$1"
+          shift ;;
+      --cflags=*)
+          cflags=`echo $1 | sed 's/--cflags=//'`
+          shift ;;
+      --ldflags)
+          shift
+          ldflags="$1"
+          shift ;;
+      --ldflags=*)
+          ldflags=`echo $1 | sed 's/--ldflags=//'`
+          shift ;;
+      --dest)
+          shift
+          dest="$1"
+          shift ;;
+      --dest=*)
+          dest=`echo $1 | sed 's/--dest=//'`
+          shift ;;
+      --)
+          shift
+          break ;;
+      *)
+          break ;;
+  esac
+done
+
+for file
+do
+  basename=`basename $file .c`
+  "$archlibdir/libtool" --mode=compile @CC@ @CFLAGS@ $cflags -I"$archlibdir" -c "$file" &&
+  "$archlibdir/libtool" --mode=link @CC@ @LDFLAGS@ $ldflags -module -avoid-version -rpath `pwd` -o "$basename.la" "$basename.lo" &&
+  echo "Installing in $dest" &&
+# Sink confusing output from this step (not suppressed by --quiet).
+  "$archlibdir/libtool" --quiet --mode=install @INSTALL@ "$basename.la" "$dest/$basename.la" 2>/dev/null >/dev/null &&
+  "$archlibdir/make-docfile" "$file" >"$dest/$basename.doc" &&
+# The archive isn't wanted.
+  rm -f "$dest/$basename.a" || exit 1
+  test "$dest" != `pwd` &&
+  "$archlibdir/libtool" --mode=clean rm -f "$basename.la" "$basename.lo" || exit 1
+done
--- /dev/null	Thu Nov 30 15:25:58 2000
+++ src/mod-test.c	Tue Mar 19 23:54:46 2002
@@ -0,0 +1,61 @@
+/* mod-test.c --- trivial test/demo of dynamic loading C modules
+
+   Copyright (C) 2002 Free Software Foundation Inc.
+
+   Author: Dave Love <fx@gnu.org>
+   
+   This file 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 file 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 GNU Emacs; see the file COPYING.  If not, write to
+   the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "config.h"
+#include "lisp.h"
+#include <math.h>
+#include <errno.h>
+
+Lisp_Object Vtest_var;		/* exported variable */
+int test_int = 69;		/* forwarded to Lisp */
+
+/* A function missing from the Emacs core (commented-out in
+   floatfns.c).  It needs -lm, which is automatically included by the
+   module builder.  */
+DEFUN ("Y1", Fy1, Sy1, 1, 1, 0,
+  "Return the order 1 Bessel function of the second kind of ARG.")
+  (arg)
+     Lisp_Object arg;
+{
+  double d = extract_float (arg);
+  errno = 0;
+  d = y1 (d);
+  switch (errno) {
+  case 0: break;
+  case EDOM:
+    Fsignal (Qdomain_error, Fcons (build_string ("Y1"), Fcons (arg, Qnil)));
+  case ERANGE:
+    Fsignal (Qrange_error, Fcons (build_string ("Y1"), Fcons (arg, Qnil)));
+  default:
+    Fsignal (Qarith_error, Fcons (build_string ("Y1"), Fcons (arg, Qnil)));
+  }  
+  return make_float (d);
+}
+
+/* Initialization for the module.  Must be called init_MODULE.  */
+void
+init_mod_test ()
+{
+  defsubr (&Sy1);
+  DEFVAR_LISP ("test-var", &Vtest_var, "A module variable.");
+  Vtest_var = make_number (69);
+  DEFVAR_INT ("test-int", &test_int, "A module defvar_int.");
+  Fprovide (intern ("mod-test"));
+}
Index: Makefile.in
===================================================================
RCS file: /cvs/emacs/Makefile.in,v
retrieving revision 1.232
diff -u -p -r1.232 Makefile.in
--- Makefile.in	25 Apr 2001 13:50:10 -0000	1.232
+++ Makefile.in	19 Mar 2002 23:55:58 -0000
@@ -3,7 +3,7 @@
 # DIST: that first.
 
 # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-#  2000, 2001 Free Software Foundation, Inc.
+#  2000, 2001, 2002 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
@@ -63,6 +63,8 @@ CPP=@CPP@
 C_SWITCH_SYSTEM=@c_switch_system@
 ALLOCA=@ALLOCA@
 LN_S=@LN_S@
+# The LTDL flags are only relevant in src, but the flags are explicitly
+# set for the sub-make for some reason.
 CFLAGS=@CFLAGS@
 LDFLAGS=@LDFLAGS@
 CPPFLAGS=@CPPFLAGS@
@@ -209,10 +211,10 @@ EMACS = emacs
 # because the compiled lisp files are part of the distribution
 # and you cannot remake them without installing Emacs first.
 # leim is not included because it needs special handling.
-SUBDIR = lib-src src
+SUBDIR = lib-src libltdl src
 
 # The makefiles of the directories in $SUBDIR.
-SUBDIR_MAKEFILES = lib-src/Makefile man/Makefile src/Makefile oldXMenu/Makefile lwlib/Makefile leim/Makefile
+SUBDIR_MAKEFILES = lib-src/Makefile man/Makefile src/Makefile oldXMenu/Makefile lwlib/Makefile leim/Makefile libltdl/Makefile
 
 # Subdirectories to install, and where they'll go.
 # lib-src's makefile knows how to install it, so we don't do that here.
@@ -223,7 +225,7 @@ SUBDIR_MAKEFILES = lib-src/Makefile man/
 COPYDIR = ${srcdir}/etc ${srcdir}/lisp
 COPYDESTS = ${etcdir} ${lispdir}
 
-all: ${SUBDIR} leim
+all: maybe_bootstrap ${SUBDIR} leim
 
 removenullpaths=sed -e 's/^://g' -e 's/:$$//g' -e 's/::/:/g'
 
@@ -298,6 +300,9 @@ lwlib/Makefile: $(srcdir)/lwlib/Makefile
 leim/Makefile: $(srcdir)/leim/Makefile.in config.status
 	./config.status
 
+libltdl/Makefile: $(srcdir)/libltdl/Makefile.in config.status
+	./config.status
+
 # ==================== Installation ====================
 
 ## If we let lib-src do its own installation, that means we
@@ -316,7 +321,8 @@ leim/Makefile: $(srcdir)/leim/Makefile.i
 ## source exists and is distinct from the destination.
 ### We do install-arch-indep first because
 ### the executable needs the Lisp files and DOC file to work properly.
-install: all install-arch-indep install-arch-dep install-leim blessmail
+install: all install-arch-indep install-arch-dep install-leim blessmail \
+         install-module-stuff
 	@true
 
 ### Install the executables that were compiled specifically for this machine.
@@ -464,6 +470,29 @@ install-leim: leim/Makefile mkdir
 install-strip:
 	$(MAKE) INSTALL_STRIP=-s install
 
+install-module-stuff: mkdir
+#ifdef CAN_DLOPEN
+# lisp.h actually isn't architecture-dependent, but we might as well
+# keep it with config.h, which is, so we only need one include directory
+# for building modules.
+	${INSTALL_DATA} ${srcdir}/src/lisp.h ${archlibdir}/lisp.h
+	${INSTALL_DATA} ${srcdir}/src/config.h ${archlibdir}/config.h
+	if test "@config_includes@"; then \
+	  for i in @config_includes@; do \
+	    case $$i in \
+	    /*) ;; \
+	    *) ${INSTALL_DATA} ${srcdir}/src/$$i ${archlibdir}/$$i;; \
+	    esac; \
+	  done; \
+	else \
+	  echo "*** Not using GCC, so can't check all dependents of config.h."; \
+	  echo "*** Check headers installed in $archlibdir."; \
+	  ${INSTALL_DATA} ${srcdir}/src/@machfile@ ${archlibdir}/@machfile@; \
+	  ${INSTALL_DATA} ${srcdir}/src/@opsysfile@ ${archlibdir}/@opsysfile@; \
+	fi
+	${INSTALL_PROGRAM} ${INSTALL_STRIP} libtool ${archlibdir}/libtool
+#endif
+
 ### Build all the directories we're going to install Emacs in.	Since
 ### we may be creating several layers of directories (for example,
 ### /usr/local/lib/emacs/19.0/mips-dec-ultrix4.2), we use mkinstalldirs
@@ -477,6 +506,7 @@ mkdir: FRC
 	  ${bindir} ${docdir} ${libexecdir} \
 	  ${datadir}/emacs/site-lisp \
 	  ${datadir}/emacs/${version}/site-lisp \
+	  ${archlibdir}/m ${archlibdir}/s \
 	  `echo ${locallisppath} | sed 's/:/ /g'`
 
 ### Delete all the installed files that the `install' target would
@@ -503,13 +533,12 @@ uninstall:
 	    esac ;					\
 	  fi ;						\
 	done
-	(cd ${archlibdir} && rm -f fns-*)
-	-rm -rf ${libexecdir}/emacs/${version}
+	(cd ${archlibdir} && rm -f fns-* lisp.h config.h libtool)
+	-rm -rf ${libexecdir}/emacs/${version} ${archlibdir}/m ${archlibdir}/s
 	(cd ${infodir} && rm -f cl* ada-mode* autotype* ccmode* ebrowse* efaq* eshell* eudc* idlwave* message* pcl-cvs* reftex* speedbar* widget* woman* dired-x* ediff* emacs* forms* gnus* info* mh-e* sc* vip*)
 	(cd ${man1dir}  && rm -f emacs.1 etags.1 ctags.1)
 	(cd ${bindir}  && rm -f emacs-${version} $(EMACS))
 
-
 FRC:
 
 # ==================== Cleaning up and miscellanea ====================
@@ -528,6 +557,7 @@ mostlyclean: FRC
 	(cd lib-src;  $(MAKE) $(MFLAGS) mostlyclean)
 	-(cd man &&   $(MAKE) $(MFLAGS) mostlyclean)
 	(cd leim;     $(MAKE) $(MFLAGS) mostlyclean)
+	(cd libltdl;  $(MAKE) $(MFLAGS) mostlyclean)
 
 ### `clean'
 ###      Delete all files from the current directory that are normally
@@ -544,6 +574,8 @@ clean: FRC
 	(cd lib-src;  $(MAKE) $(MFLAGS) clean)
 	-(cd man &&   $(MAKE) $(MFLAGS) clean)
 	(cd leim;     $(MAKE) $(MFLAGS) clean)
+	(cd libltdl;  $(MAKE) $(MFLAGS) clean)
+	rm -f libtool ltmain.sh ltconfig
 
 ### `distclean'
 ###      Delete all files from the current directory that are created by
@@ -552,7 +584,7 @@ clean: FRC
 ###      `make distclean' should leave only the files that were in the
 ###      distribution.
 top_distclean=\
-	rm -f config.status config.cache config.log ; \
+	rm -f config.status config.cache config.log libtool ; \
 	rm -f Makefile ${SUBDIR_MAKEFILES} ; \
 	if [ -d lock ] ; then (cd lock && (rm -f * || true)); else true; fi
 distclean: FRC
@@ -563,6 +595,7 @@ distclean: FRC
 	(cd man &&    $(MAKE) $(MFLAGS) distclean)
 	(cd leim;     $(MAKE) $(MFLAGS) distclean)
 	(cd lisp;     $(MAKE) $(MFLAGS) distclean)
+	(cd libltdl;  $(MAKE) $(MFLAGS) distclean)
 	${top_distclean}
 
 ### `maintainer-clean'
@@ -583,6 +616,7 @@ maintainer-clean: FRC
 	(cd lib-src;  $(MAKE) $(MFLAGS) maintainer-clean)
 	-(cd man &&   $(MAKE) $(MFLAGS) maintainer-clean)
 	(cd leim;     $(MAKE) $(MFLAGS) maintainer-clean)
+	(cd libltdl;  $(MAKE) $(MFLAGS) maintainer-clean)
 	${top_distclean}
 
 ### This doesn't actually appear in the coding standards, but Karl
@@ -677,3 +717,7 @@ bootstrap-src:
 
 bootstrap-clean:
 	(cd src; $(MAKE) $(MFLAGS) clean)
+
+LIBTOOL_DEPS = @LIBTOOL_DEPS@
+libtool: $(LIBTOOL_DEPS)
+	$(SHELL) ./config.status --recheck
Index: configure.in
===================================================================
RCS file: /cvs/emacs/configure.in,v
retrieving revision 1.267.4.2
diff -u -p -r1.267.4.2 configure.in
--- configure.in	19 Oct 2001 14:10:34 -0000	1.267.4.2
+++ configure.in	19 Mar 2002 23:55:59 -0000
@@ -3,7 +3,7 @@ dnl To rebuild the `configure' script fr
 dnl 	autoconf
 dnl in the directory containing this script.
 dnl
-dnl  Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001
+dnl  Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002
 dnl  Free Software Foundation, Inc.
 dnl
 dnl  This file is part of GNU Emacs.
@@ -1151,6 +1155,20 @@ then
   ac_link="$ac_link $NON_GCC_LINK_TEST_OPTIONS"
 fi
 
+if test "$GCC" = yes; then
+  cat >conftest.c <<+
+#include "$machfile"
+#include "$opsysfile"
++
+dnl Sample gcc o/p:
+dnl conftest.o: conftest.c s/irix6-5.h s/irix5-0.h s/usg5-4.h s/usg5-3.h \
+dnl  m/mips.h
+  cwd=`pwd`; export cwd
+  config_includes=`( cd "$srcdir/src"
+                     gcc -E -MM -I. "$cwd"/conftest.c 2>/dev/null |
+		     tr '\\\\\n' '  ' | sed -e 's/^.*conftest.c //' )`
+fi
+
 #### Some other nice autoconf tests.  If you add a test here which
 #### should make an entry in src/config.h, don't forget to add an
 #### #undef clause to src/config.h.in for autoconf to modify.
@@ -2131,6 +2161,23 @@ fi
 
 AC_FUNC_VFORK
 
+AC_LIBLTDL_CONVENIENCE
+AC_SUBST(INCLTDL)
+AC_SUBST(LIBLTDL)
+AC_LIBTOOL_DLOPEN
+AM_PROG_LIBTOOL
+case `./libtool --config | grep ^dlopen_support=` in
+dlopen_support=yes)
+   CAN_DLOPEN=yes;
+   AC_DEFINE(CAN_DLOPEN)
+   build_emacs_module=build-emacs-module ;;
+dlopen_support=no) ;;
+*)
+   AC_MSG_ERROR([Bad output from libtool --config.  Probably inappropriate version.]) ;;
+esac
+AC_SUBST(LIBTOOL_DEPS)
+AC_CONFIG_SUBDIRS(libltdl)
+
 # Fixme: This should be replaced when we have autoconf 2.14.
 AC_SIZE_T
 
@@ -2179,6 +2226,8 @@ AC_SUBST(X_TOOLKIT_TYPE)
 AC_SUBST(machfile)
 AC_SUBST(opsysfile)
 AC_SUBST(GETLOADAVG_LIBS)
+AC_SUBST(build_emacs_module)
+AC_SUBST(config_includes)
 
 AC_DEFINE_UNQUOTED(EMACS_CONFIGURATION,  "${canonical}")
 AC_DEFINE_UNQUOTED(EMACS_CONFIG_OPTIONS, "${ac_configure_args}")
@@ -2243,6 +2292,7 @@ echo "  Does Emacs use -ltiff?          
 echo "  Does Emacs use -lungif?                                 ${HAVE_GIF}"
 echo "  Does Emacs use -lpng?                                   ${HAVE_PNG}"
 echo "  Does Emacs use X toolkit scroll bars?                   ${USE_TOOLKIT_SCROLL_BARS}"
+echo "  Does Emacs support dynamic modues?                      ${CAN_DLOPEN:-no}"
 echo
 
 # Remove any trailing slashes in these variables.
@@ -2265,7 +2315,7 @@ AC_EGREP_CPP(yes..yes,
 
 AC_OUTPUT(Makefile lib-src/Makefile.c:lib-src/Makefile.in oldXMenu/Makefile \
 	man/Makefile lwlib/Makefile src/Makefile.c:src/Makefile.in \
-	lisp/Makefile leim/Makefile, [
+	lisp/Makefile leim/Makefile lib-src/build-emacs-module, [
 
 ### Make the necessary directories, if they don't exist.
 for dir in etc lisp ; do
@@ -2335,6 +2385,8 @@ if test ! -f src/.gdbinit && test -f $to
   echo creating src/.gdbinit
   echo source $top_srcdir/src/.gdbinit > src/.gdbinit
 fi
+
+chmod +x lib-src/build-emacs-module
 
 # This is how we know whether to re-run configure in certain cases.
 touch src/config.stamp
Index: lib-src/Makefile.in
===================================================================
RCS file: /cvs/emacs/lib-src/Makefile.in,v
retrieving revision 1.120.14.1
diff -u -p -r1.120.14.1 Makefile.in
--- lib-src/Makefile.in	19 Oct 2001 00:31:27 -0000	1.120.14.1
+++ lib-src/Makefile.in	19 Mar 2002 23:55:59 -0000
@@ -1,5 +1,5 @@
 # Makefile for lib-src subdirectory in GNU Emacs.
-# Copyright (C) 1985, 1987, 1988, 1993, 1994 Free Software Foundation, Inc.
+# Copyright (C) 1985, 1987, 1988, 1993, 1994, 2002 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
@@ -93,14 +93,14 @@ INSTALL_STRIP =
 # Things that a user might actually run,
 # which should be installed in bindir.
 INSTALLABLES = etags ctags emacsclient b2m ebrowse
-INSTALLABLE_SCRIPTS = rcs-checkin grep-changelog
+INSTALLABLE_SCRIPTS = rcs-checkin grep-changelog @build_emacs_module@
 
 # Things that Emacs runs internally, or during the build process,
 #  which should not be installed in bindir.
-UTILITIES=  profile digest-doc \
+UTILITIES=  profile digest-doc make-docfile \
 	sorted-doc movemail cvtmail fakemail yow emacsserver hexl
 
-DONT_INSTALL= test-distrib make-docfile
+DONT_INSTALL= test-distrib
 
 # Like UTILITIES, but they're not system-dependent, and should not be
 #  deleted by the distclean target.
Index: src/doc.c
===================================================================
RCS file: /cvs/emacs/src/doc.c,v
retrieving revision 1.79
diff -u -p -r1.79 doc.c
--- src/doc.c	2 Jan 2001 14:02:33 -0000	1.79
+++ src/doc.c	19 Mar 2002 23:55:59 -0000
@@ -1,5 +1,5 @@
 /* Record indices of function doc strings stored in a file.
-   Copyright (C) 1985, 86,93,94,95,97,98,99, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1985, 86,93,94,95,97,98,99, 2000, 2002 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -48,6 +48,7 @@ extern char *index P_ ((const char *, in
 Lisp_Object Vdoc_file_name, Vhelp_manyarg_func_alist;
 
 Lisp_Object Qfunction_documentation;
+extern Lisp_Object Vfile_name_coding_system;
 
 extern Lisp_Object Voverriding_local_map;
 
@@ -566,6 +567,77 @@ when doc strings are referred to later i
     }
   emacs_close (fd);
   return Qnil;
+}
+
+/* Used for dynamic modules to snarf from FILENAME (module.doc).  */
+void
+snarf_documentation (filename)
+     Lisp_Object filename;
+{
+  int fd;
+  char buf[1024 + 1];
+  register int filled;
+  register int pos;
+  register char *p, *end;
+  Lisp_Object sym, encoded_name;
+  char *name;
+
+  encoded_name = Fencode_coding_string (filename,
+					Vfile_name_coding_system, Qt);
+  name = XSTRING (encoded_name)->data;
+  fd = emacs_open (name, O_RDONLY, 0);
+  if (fd < 0) return;
+/*     report_file_error ("Opening doc string file", */
+/* 		       Fcons (build_string (name), Qnil)); */
+  filled = 0;
+  pos = 0;
+  while (1)
+    {
+      if (filled < 512)
+	filled += emacs_read (fd, &buf[filled], sizeof buf - 1 - filled);
+      if (!filled)
+	break;
+
+      buf[filled] = 0;
+      p = buf;
+      end = buf + (filled < 512 ? filled : filled - 128);
+      while (p != end && *p != '\037') p++;
+      /* p points to ^_Ffunctionname\n or ^_Vvarname\n.  */
+      if (p != end)
+	{
+	  end = (char *) index (p, '\n');
+	  sym = oblookup (Vobarray, p + 2,
+			  multibyte_chars_in_text (p + 2, end - p - 2),
+			  end - p - 2);
+	  if (SYMBOLP (sym))
+	    {
+	      /* Attach a docstring to a variable?  */
+	      if (p[1] == 'V')
+		{
+		  /* Install file-position as variable-documentation property
+		     and make it negative for a user-variable
+		     (doc starts with a `*').  */
+		  Fput (sym, Qvariable_documentation,
+			Fcons (filename,
+			       make_number ((pos + end + 1 - buf)
+					    * (end[1] == '*' ? -1 : 1))));
+		}
+
+	      /* Attach a docstring to a function?  */
+	      else if (p[1] == 'F')
+		  Fput (sym, Qfunction_documentation,
+			Fcons (filename,
+			       make_number ((pos + end + 1 - buf))));
+	      else
+		error ("DOC file invalid at position %d", pos);
+	    }
+	}
+      pos += end - buf;
+      filled -= end - buf;
+      bcopy (end, buf, filled);
+    }
+  emacs_close (fd);
+  return;
 }
 
 DEFUN ("substitute-command-keys", Fsubstitute_command_keys,
Index: src/lread.c
===================================================================
RCS file: /cvs/emacs/src/lread.c,v
retrieving revision 1.256
diff -u -p -r1.256 lread.c
--- src/lread.c	2 Jun 2001 06:09:41 -0000	1.256
+++ src/lread.c	19 Mar 2002 23:55:59 -0000
@@ -26,6 +26,9 @@ Boston, MA 02111-1307, USA.  */
 #include <sys/stat.h>
 #include <sys/file.h>
 #include <errno.h>
+#if CAN_DLOPEN
+#include <ltdl.h>
+#endif
 #include "lisp.h"
 #include "intervals.h"
 #include "buffer.h"
@@ -85,6 +88,9 @@ Lisp_Object Qinhibit_file_name_operation
 extern Lisp_Object Qevent_symbol_element_mask;
 extern Lisp_Object Qfile_exists_p;
 
+extern int command_loop_level;	/* keyboard.c */
+extern void snarf_documentation P_ ((Lisp_Object)); /* doc.c */
+
 /* non-zero if inside `load' */
 int load_in_progress;
 
@@ -193,6 +199,9 @@ int load_dangerous_libraries;
 
 static Lisp_Object Vbytecomp_version_regexp;
 
+/* List of dynamically loaded module nemas.  */
+static Lisp_Object modules_list;
+
 static void readevalloop P_ ((Lisp_Object, FILE*, Lisp_Object, 
 			      Lisp_Object (*) (), int,
 			      Lisp_Object, Lisp_Object));
@@ -672,6 +682,11 @@ Return t if file exists.")
 	  else if (size > 4
 		   && !strcmp (XSTRING (file)->data + size - 4, ".elc"))
 	    must_suffix = Qnil;
+#ifdef CAN_DLOPEN
+	  else if (size > 3
+		   && !strcmp (XSTRING (file)->data + size - 3, ".la"))
+	    must_suffix = Qnil;
+#endif
 	  /* Don't insist on adding a suffix
 	     if the argument includes a directory name.  */
 	  else if (! NILP (Ffile_name_directory (file)))
@@ -680,8 +695,13 @@ Return t if file exists.")
 
       fd = openp (Vload_path, file,
 		  (!NILP (nosuffix) ? ""
-		   : ! NILP (must_suffix) ? ".elc.gz:.elc:.el.gz:.el"
-		   : ".elc:.elc.gz:.el.gz:.el:"),
+#ifdef CAN_DLOPEN
+		   : ! NILP (must_suffix) ? ".la:.elc.bz2:.elc.gz:.elc:.el.bz2:.el.gz:.el"
+		   : ".la:.elc.gz:.elc:.el.gz:.el:"),
+#else
+		   : ! NILP (must_suffix) ? ".elc.bz2:.elc.gz:.elc:.el.bz2:.el.gz:.el"
+		   : ".elc.bz2:.elc.gz:.elc:.el.bz2:.el.gz:.el:"),
+#endif
 		  &found, 0);
       UNGCPRO;
     }
@@ -776,6 +796,78 @@ Return t if file exists.")
 	  XSTRING (found)->data[STRING_BYTES (XSTRING (found)) - 1] = 'c';
 	}
     }
+#if CAN_DLOPEN
+  else if (!bcmp (&(XSTRING (found)->data[STRING_BYTES (XSTRING (found)) - 3]),
+	     ".la", 3))
+     /* Load dynamic modules, but not when they are remote and have no
+	handler!  */
+     /* Fixme: what about fd == 2?  */
+    {
+      /* Fixme: will it actually work when dumping?  */
+      if (!NILP (Vpurify_flag))
+	error ("Can't dynamic-load modules when dumping");
+      if (fd != -2)
+	{
+	  lt_dlhandle handle;
+	  void (*init) () = 0;
+	  Lisp_Object module_name;
+	  Lisp_Object init_name;
+	  Lisp_Object args[2];
+	  struct gcpro gcpro2;
+	  int i;
+
+	  emacs_close (fd);
+	  if (NILP (nomessage))
+	    message_with_string ("Loading %s (module; subject to the GPL)...",
+				 file, 1);
+	  /* In case file-name-nondirectory GCs.  */
+	  GCPRO1 (found);
+	  module_name = Fsubstring (Ffile_name_nondirectory (found),
+				    make_number (0), make_number (-3));
+	  UNGCPRO;
+	  /* Fixme: Is it reasonable to dlopen twice?  */
+	  if (!NILP (Fmember (module_name, modules_list)))
+	    error ("Module %s already loaded", XSTRING (module_name)->data);
+	  handle = lt_dlopen (XSTRING (found)->data);
+	  if (!handle)
+	    error ("Can't load module %s: %s", XSTRING (module_name)->data,
+		   lt_dlerror ());
+	  modules_list = Fcons (module_name, modules_list);
+	  args[0] = build_string ("init_");
+	  args[1] = module_name;
+	  /* Convention: To form init function name, replace hyphens
+	     in module name with underscores. */
+	  for (i = 0; i < Flength (module_name); i++)
+	    if (!NILP (Feq (Faref (args[1], make_number (i)),
+			    make_number ('-'))))
+	      Faset (args[1], make_number (i), make_number ('_'));
+	  init_name = Fconcat (2, args);
+	  init = (void (*) ()) lt_dlsym (handle, XSTRING (init_name)->data);
+	  if (!init)
+	    error ("Init function not found in module %s",
+		   XSTRING (module_name)->data);
+	  GCPRO2 (found, file);
+	  (*init) ();
+	  UNGCPRO;
+	  {
+	    Lisp_Object doc_name;
+
+	    args[0] = Fsubstring (found, make_number (0), make_number (-3));
+	    args[1] = build_string (".doc");
+	    doc_name = Fconcat (2, args);
+	    snarf_documentation (doc_name);
+	  }
+	  /* Run any load-hooks for this file.  */
+	  temp = Fassoc (file, Vafter_load_alist);
+	  if (!NILP (temp))
+	    Fprogn (Fcdr (temp));
+	  if (!noninteractive && NILP (nomessage))
+	    message_with_string ("Loading %s (module subject to the GPL)...done",
+				 file, 1);
+	  return unbind_to (count, Qt);
+	}
+    }
+#endif
   else
     {
       /* We are loading a source file (*.el).  */
@@ -3167,8 +3295,21 @@ defsubr (sname)
      struct Lisp_Subr *sname;
 {
   Lisp_Object sym;
+#ifdef CAN_DLOPEN
+  struct Lisp_Subr *tmp;
+
   sym = intern (sname->symbol_name);
-  XSETSUBR (XSYMBOL (sym)->function, sname);
+  if (command_loop_level >= 0)	/* evaluating, so must be dynamic load */
+    {
+      /* We're dynamic loading and the subr needs copying to avoid a
+	 SEGV for reasons I don't understand.  Fixme.  */
+      tmp = xmalloc (sizeof (struct Lisp_Subr));
+      bcopy (sname, tmp, sizeof (struct Lisp_Subr));
+      XSETSUBR (XSYMBOL (sym)->function, tmp);
+    }
+  else
+#endif
+    XSETSUBR (XSYMBOL (sym)->function, sname);
 }
 
 #ifdef NOTDEF /* use fset in subr.el now */
@@ -3481,6 +3622,17 @@ dir_warning (format, dirname)
     message_dolog (buffer, strlen (buffer), 0, STRING_MULTIBYTE (dirname));
 }
 
+DEFUN ("dynamic-modules-p", Fdynamic_modules_p, Sdynamic_modules_p, 0, 0, 0,
+       "Return non-nil if this Emacs supports dynamic modules.")
+     ()
+{
+#if CAN_DLOPEN
+  return Qt;
+#else
+  return Qnil;
+#endif
+}
+
 void
 syms_of_lread ()
 {
@@ -3497,6 +3649,7 @@ syms_of_lread ()
   defsubr (&Sread_event);
   defsubr (&Sget_file_char);
   defsubr (&Smapatoms);
+  defsubr (&Sdynamic_modules_p);
 
   DEFVAR_LISP ("obarray", &Vobarray,
     "Symbol table for use by `intern' and `read'.\n\
@@ -3669,4 +3822,10 @@ no limit.");
   
   Vloads_in_progress = Qnil;
   staticpro (&Vloads_in_progress);
+
+#ifdef CAN_DLOPEN
+  staticpro (&modules_list);
+  modules_list = Qnil;
+  lt_dlinit ();
+#endif
 }
Index: help.el
===================================================================
RCS file: /cvs/emacs/lisp/help.el,v
retrieving revision 1.231
diff -u -p -r1.231 help.el
--- help.el	1 Oct 2001 07:01:24 -0000	1.231
+++ help.el	17 Mar 2002 18:36:35 -0000
@@ -1034,18 +1034,23 @@ and the file name is displayed in the ec
 	      '("")
 	    '(".elc" ".el" "")
 	    (let ((basic '(".elc" ".el" ""))
-		  (compressed '(".Z" ".gz" "")))
+		  (compressed '(".Z" ".gz" ".bz2" ""))
+		  result)
 	      ;; If autocompression mode is on,
 	      ;; consider all combinations of library suffixes
 	      ;; and compression suffixes.
-	      (if (rassq 'jka-compr-handler file-name-handler-alist)
-		  (apply 'nconc
-			 (mapcar (lambda (compelt)
-				   (mapcar (lambda (baselt)
-					     (concat baselt compelt))
-					   basic))
-				 compressed))
-		basic)))))
+	      (setq result
+		    (if (rassq 'jka-compr-handler file-name-handler-alist)
+			(apply 'nconc
+			       (mapcar (lambda (compelt)
+					 (mapcar (lambda (baselt)
+						   (concat baselt compelt))
+						 basic))
+				       compressed))
+		      basic))
+	      (if (dynamic-modules-p)
+		  (push ".la" result); can't be compressed
+		result)))))
        (or path load-path)))
     (and interactive-call
 	 (if result
