diff --git a/configure.ac b/configure.ac index 04c75e3..2614f46 100644 --- a/configure.ac +++ b/configure.ac @@ -323,6 +323,8 @@ OPTION_DEFAULT_ON([gsettings],[don't compile with GSettings support]) OPTION_DEFAULT_ON([selinux],[don't compile with SELinux support]) OPTION_DEFAULT_ON([gnutls],[don't use -lgnutls for SSL/TLS support]) OPTION_DEFAULT_ON([zlib],[don't compile with zlib decompression support]) +OPTION_DEFAULT_ON([ltdl], [don't compile with dynamic module loading support]) + AC_ARG_WITH([file-notification],[AS_HELP_STRING([--with-file-notification=LIB], [use a file notification library (LIB one of: yes, gfile, inotify, w32, no)])], @@ -3126,6 +3128,18 @@ if test "${HAVE_ZLIB}" = "yes"; then fi AC_SUBST(LIBZ) +HAVE_LTDL=no +LIBLTDL= +if test "${with_ltdl}" != "no"; then + AC_CHECK_HEADER(ltdl.h, HAVE_LTDL=yes, HAVE_LTDL=no) + AC_CHECK_LIB(ltdl, lt_dlopen, HAVE_LTDL=yes, HAVE_LTDL=no) +fi +if test "${HAVE_LTDL}" = "yes"; then + AC_DEFINE(HAVE_LTDL, 1, [Define to 1 if you have the ltdl library (-lltdl).]) + LIBLTDL="-lltdl -Wl,--export-dynamic" +fi +AC_SUBST(LIBLTDL) + ### Use -lpng if available, unless `--with-png=no'. HAVE_PNG=no LIBPNG= @@ -4989,7 +5003,7 @@ optsep= emacs_config_features= for opt in XAW3D XPM JPEG TIFF GIF PNG RSVG IMAGEMAGICK SOUND GPM DBUS \ GCONF GSETTINGS NOTIFY ACL LIBSELINUX GNUTLS LIBXML2 FREETYPE M17N_FLT \ - LIBOTF XFT ZLIB; do + LIBOTF XFT ZLIB LTDL; do case $opt in NOTIFY|ACL) eval val=\${${opt}_SUMMARY} ;; @@ -5028,6 +5042,7 @@ echo " Does Emacs use -lm17n-flt? ${HAVE_M17N_FLT} echo " Does Emacs use -lotf? ${HAVE_LIBOTF}" echo " Does Emacs use -lxft? ${HAVE_XFT}" echo " Does Emacs directly use zlib? ${HAVE_ZLIB}" +echo " Does Emacs use -lltdl? ${HAVE_LTDL}" echo " Does Emacs use toolkit scroll bars? ${USE_TOOLKIT_SCROLL_BARS}" echo diff --git a/modules/Makefile b/modules/Makefile new file mode 100644 index 0000000..52fb876 --- /dev/null +++ b/modules/Makefile @@ -0,0 +1,8 @@ + +all: fmod.so + +%.so: %.o + gcc -shared -o $@ $< + +%.o: %.c + gcc -ggdb3 -Wall -I../src -I../lib -fPIC -c $< diff --git a/modules/fmod.c b/modules/fmod.c new file mode 100644 index 0000000..2fdd01e --- /dev/null +++ b/modules/fmod.c @@ -0,0 +1,25 @@ +#include +#include + +#include + +/* emacs checks for this symbol before running the module */ + +int plugin_is_GPL_compatible; + +/* define a new lisp function */ + +EXFUN (Ffmod, 2); +DEFUN ("fmod", Ffmod, Sfmod, 2, 2, 0, + doc: "Returns the floating-point remainder of NUMER/DENOM") + (Lisp_Object numer, Lisp_Object denom) +{ + return make_float (fmod (extract_float (numer), extract_float (denom))); +} + +/* entry point of the module */ + +void init () +{ + defsubr (&Sfmod); +} diff --git a/src/Makefile.in b/src/Makefile.in index a13f7b8..780245a 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -225,6 +225,8 @@ LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ LIBZ = @LIBZ@ +LIBLTDL = @LIBLTDL@ + XRANDR_LIBS = @XRANDR_LIBS@ XRANDR_CFLAGS = @XRANDR_CFLAGS@ @@ -408,7 +410,7 @@ LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(LIBX_BASE) $(LIBIMAGE) \ $(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \ $(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(LIBOTF_LIBS) $(M17N_FLT_LIBS) \ $(LIBGNUTLS_LIBS) $(LIB_PTHREAD) \ - $(GFILENOTIFY_LIBS) $(LIB_MATH) $(LIBZ) + $(GFILENOTIFY_LIBS) $(LIB_MATH) $(LIBZ) $(LIBLTDL) all: emacs$(EXEEXT) $(OTHER_FILES) .PHONY: all diff --git a/src/lread.c b/src/lread.c index f252993..e431be6 100644 --- a/src/lread.c +++ b/src/lread.c @@ -1,3 +1,4 @@ + /* Lisp parsing and input streams. Copyright (C) 1985-1989, 1993-1995, 1997-2014 Free Software Foundation, @@ -64,6 +65,10 @@ along with GNU Emacs. If not, see . */ #define file_tell ftell #endif +#ifdef HAVE_LTDL +#include +#endif + /* Hash table read constants. */ static Lisp_Object Qhash_table, Qdata; static Lisp_Object Qtest, Qsize; @@ -999,6 +1004,49 @@ This uses the variables `load-suffixes' and `load-file-rep-suffixes'. */) return Fnreverse (lst); } +DEFUN ("load-module", Fload_module, Sload_module, 1, 1, 0, + doc: /* Dymamically load a compiled module. */) + (Lisp_Object file) +{ +#ifdef HAVE_LTDL + static int lt_init_done = 0; + lt_dlhandle handle; + void (*module_init) (); + void *gpl_sym; + + if (!lt_init_done) + { + int ret = lt_dlinit (); + if (ret) + { + const char* s = lt_dlerror (); + error ("ltdl init fail: %s", s); + } + lt_init_done = 1; + } + + CHECK_STRING (file); + + handle = lt_dlopen (SDATA (file)); + if (!handle) + error ("Cannot load file %s", SDATA (file)); + + gpl_sym = lt_dlsym (handle, "plugin_is_GPL_compatible"); + if (!gpl_sym) + error ("Module %s is not GPL compatible", SDATA (file)); + + module_init = (void (*) ()) lt_dlsym (handle, "init"); + if (!module_init) + error ("Module %s does not have an init function.", SDATA (file)); + + module_init (); + + return Qt; +#else + return Qnil; +#endif +} + DEFUN ("load", Fload, Sload, 1, 5, 0, doc: /* Execute a file of Lisp code named FILE. First try FILE with `.elc' appended, then try with `.el', @@ -3805,10 +3853,7 @@ intern_c_string_1 (const char *str, ptrdiff_t len) return tem; if (NILP (Vpurify_flag)) - /* Creating a non-pure string from a string literal not - implemented yet. We could just use make_string here and live - with the extra copy. */ - emacs_abort (); + return Fintern (make_string (str, len), obarray); return Fintern (make_pure_c_string (str, len), obarray); } @@ -4486,6 +4531,7 @@ syms_of_lread (void) defsubr (&Sget_file_char); defsubr (&Smapatoms); defsubr (&Slocate_file_internal); + defsubr (&Sload_module); DEFVAR_LISP ("obarray", Vobarray, doc: /* Symbol table for use by `intern' and `read'.