about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2000-08-02 18:01:51 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2000-08-02 18:01:51 +0000
commit4f1aa826f5fb4d7f8dd9d76ab5c3f83934b148de (patch)
tree24d61adf721e320b6a7de68f010071c656648c93
parentde7b6730bcebf08368e7531b68c6a2598166eb86 (diff)
downloadzsh-4f1aa826f5fb4d7f8dd9d76ab5c3f83934b148de.tar.gz
zsh-4f1aa826f5fb4d7f8dd9d76ab5c3f83934b148de.tar.xz
zsh-4f1aa826f5fb4d7f8dd9d76ab5c3f83934b148de.zip
Andrej: Dynamic loading on cygwin
-rw-r--r--ChangeLog7
-rw-r--r--Etc/MACHINES11
-rw-r--r--Src/Makefile.in18
-rw-r--r--Src/Zle/zle_utils.c2
-rw-r--r--Src/init.c94
-rw-r--r--Src/main.c84
-rw-r--r--Src/makepro.awk63
-rw-r--r--Src/mkmakemod.sh350
-rw-r--r--Src/parse.c3
-rw-r--r--Src/zsh.h8
-rw-r--r--configure.in22
11 files changed, 452 insertions, 210 deletions
diff --git a/ChangeLog b/ChangeLog
index d4901814f..7651f0ca2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2000-08-02  Peter Stephenson  <pws@csr.com>
+
+	* Andrej: 12487: configure.in, Etc/MACHINES, Src/Makefile.in,
+	Src/init.c, Src/main.c, Src/makepro.awk, Src/mkmakemod.sh,
+	Src/parse.c, Src/zsh.h, Src/Zle/zle_utils.c: Dynamic loading
+	on cygwin.
+
 2000-08-02  Clint Adams  <schizo@debian.org>
 
         * 12489: Src/Modules/files.c, Src/Modules/parameter.c: check
diff --git a/Etc/MACHINES b/Etc/MACHINES
index dafb5cb30..a2f6e595a 100644
--- a/Etc/MACHINES
+++ b/Etc/MACHINES
@@ -30,14 +30,19 @@ Cygnus Solutions: Cygwin on Intel
 	be on a file system mounted as binary (the mount command shows
 	`binmode').
 
-	Dynamic loading does not work (this is automatically detected),
-	though libraries not compiled by default will work (see the file
-	INSTALL for how to add these to the base executable).  In
+	Dynamic loading works as of cygwin-1.1.3 and binutils-20000722-1.
+	It was not tested for earlier versions. This does not imply
+	that every module will work. New completion and in
 	particular zsh/zftp and zsh/mathfunc are known to work.
 
 	Some of the tests in the Test subdirectory are known to fail:
 	this is because the UNIX environment is not completely implemented.
 
+	Cygwin allows mount without existing mount point (e.g.
+	"mount //server/path /usr/src" where /usr/src does not exist).
+	Path completion will fail inside these mounts; make sure that
+	every mount point really exists.
+
 Data General: DG/UX 5.4R3.10 MU01 (various AViiONs)
 	Should build `out-of-the-box'.
 
diff --git a/Src/Makefile.in b/Src/Makefile.in
index e11440cd4..7ddddeb9b 100644
--- a/Src/Makefile.in
+++ b/Src/Makefile.in
@@ -58,6 +58,8 @@ modules: headers
 
 MAIN_OBJS = main.o
 
+L = @L@
+
 LSTMP =
 LLIST =
 NSTMP = stamp-modobjs
@@ -65,6 +67,8 @@ NLIST = `cat stamp-modobjs`
 
 LIBZSH = libzsh-$(VERSION).$(DL_EXT)
 NIBZSH =
+INSTLIB = @INSTLIB@
+UNINSTLIB = @UNINSTLIB@
 
 ZSH_EXPORT = $(EXPOPT)zsh.export
 ZSH_NXPORT =
@@ -80,7 +84,7 @@ zsh$(EXEEXT): $(@L@IBZSH) $(@L@STMP) $(MAIN_OBJS) zsh.export
 
 $(LIBZSH): $(LIBOBJS) $(NSTMP)
 	rm -f $@
-	$(DLLINK) $(LIBOBJS) $(NLIST)
+	$(DLLINK) $(LIBOBJS) $(NLIST) $(LIBS)
 
 stamp-modobjs: modobjs
 	@if cmp -s stamp-modobjs.tmp stamp-modobjs; then \
@@ -176,7 +180,7 @@ uninstall.bin: uninstall.bin-here
 .PHONY: install.bin uninstall.bin
 
 # install binary, creating install directory if necessary
-install.bin-here: zsh$(EXEEXT) install.bin-@L@
+install.bin-here: zsh$(EXEEXT) $(INSTLIB)
 	$(sdir_top)/mkinstalldirs $(DESTDIR)$(bindir)
 	$(INSTALL_PROGRAM) $(STRIPFLAGS) zsh$(EXEEXT) $(DESTDIR)$(bindir)/$(tzsh)-$(VERSION)$(EXEEXT)
 	if test -f $(DESTDIR)$(bindir)/$(tzsh)$(EXEEXT); then \
@@ -192,17 +196,21 @@ install.bin-N:
 install.bin-L: $(LIBZSH)
 	$(sdir_top)/mkinstalldirs $(DESTDIR)$(libdir)/$(tzsh)
 	$(INSTALL_PROGRAM) $(LIBZSH) $(DESTDIR)$(libdir)/$(tzsh)/$(LIBZSH)
-.PHONY: install.bin-N install.bin-L
+install.cygwin-lib: $(LIBZSH)
+	$(INSTALL_PROGRAM) $(LIBZSH) $(DESTDIR)$(bindir)/$(LIBZSH)
+.PHONY: install.bin-N install.bin-L install.cygwin-lib
 
 # uninstall binary
-uninstall.bin-here: uninstall.bin-@L@
+uninstall.bin-here: $(UNINSTLIB)
 	rm -f $(DESTDIR)$(bindir)/$(tzsh)-$(VERSION) $(DESTDIR)$(bindir)/$(tzsh)$(EXEEXT)
 .PHONY: uninstall.bin-here uninstall.bin-@L@
 
 uninstall.bin-N:
 uninstall.bin-L:
 	rm -f $(DESTDIR)$(libdir)/$(tzsh)/$(LIBZSH)
-.PHONY: uninstall.bin-N uninstall.bin-L
+uninstall.cygwin-lib:
+	rm -f $(DESTDIR)$(bindir)/$(LIBZSH)
+.PHONY: uninstall.bin-N uninstall.bin-L uninstall.cygwin-lib
 
 # ========== DEPENDENCIES FOR CLEANUP ==========
 
diff --git a/Src/Zle/zle_utils.c b/Src/Zle/zle_utils.c
index dc48c835c..5de9b331d 100644
--- a/Src/Zle/zle_utils.c
+++ b/Src/Zle/zle_utils.c
@@ -379,7 +379,7 @@ printbind(char *str, FILE *stream)
  * The message must be metafied.                              */
 
 /**/
-void
+void mod_export
 showmsg(char const *msg)
 {
     char const *p;
diff --git a/Src/init.c b/Src/init.c
index d0140a525..131cc855c 100644
--- a/Src/init.c
+++ b/Src/init.c
@@ -1123,3 +1123,97 @@ fallback_compctlread(char *name, char **args, char *ops, char *reply)
 	    NULL, 0);
     return 1;
 }
+
+/*
+ * This is real main entry point. This has to be mod_export'ed
+ * so zsh.exe can found it on Cygwin
+ */
+
+/**/
+mod_export int
+zsh_main(int argc, char **argv)
+{
+    char **t;
+    int t0;
+#ifdef USE_LOCALE
+    setlocale(LC_ALL, "");
+#endif
+
+    init_hackzero(argv, environ);
+
+    /*
+     * Provisionally set up the type table to allow metafication.
+     * This will be done properly when we have decided if we are
+     * interactive
+     */
+    typtab['\0'] |= IMETA;
+    typtab[STOUC(Meta)  ] |= IMETA;
+    typtab[STOUC(Marker)] |= IMETA;
+    for (t0 = (int)STOUC(Pound); t0 <= (int)STOUC(Nularg); t0++)
+	typtab[t0] |= ITOK | IMETA;
+
+    for (t = argv; *t; *t = metafy(*t, -1, META_ALLOC), t++);
+
+    zsh_name = argv[0];
+    do {
+      char *arg0 = zsh_name;
+      if (!(zsh_name = strrchr(arg0, '/')))
+	  zsh_name = arg0;
+      else
+	  zsh_name++;
+      if (*zsh_name == '-')
+	  zsh_name++;
+      if (strcmp(zsh_name, "su") == 0) {
+	  char *sh = zgetenv("SHELL");
+	  if (sh && *sh && arg0 != sh)
+	      zsh_name = sh;
+	  else
+	      break;
+      } else
+	  break;
+    } while (zsh_name);
+
+    fdtable_size = OPEN_MAX;
+    fdtable = zcalloc(fdtable_size);
+
+    createoptiontable();
+    emulate(zsh_name, 1);   /* initialises most options */
+    opts[LOGINSHELL] = (**argv == '-');
+    opts[MONITOR] = 1;   /* may be unset in init_io() */
+    opts[PRIVILEGED] = (getuid() != geteuid() || getgid() != getegid());
+    opts[USEZLE] = 1;   /* may be unset in init_io() */
+    parseargs(argv);   /* sets INTERACTIVE, SHINSTDIN and SINGLECOMMAND */
+
+    SHTTY = -1;
+    init_io();
+    setupvals();
+    init_signals();
+    init_bltinmods();
+    run_init_scripts();
+    init_misc();
+
+    for (;;) {
+	do
+	    loop(1,0);
+	while (tok != ENDINPUT && (tok != LEXERR || isset(SHINSTDIN)));
+	if (tok == LEXERR) {
+	    stopmsg = 1;
+	    zexit(lastval, 0);
+	}
+	if (!(isset(IGNOREEOF) && interact)) {
+#if 0
+	    if (interact)
+		fputs(islogin ? "logout\n" : "exit\n", shout);
+#endif
+	    zexit(lastval, 0);
+	    continue;
+	}
+	noexitct++;
+	if (noexitct >= 10) {
+	    stopmsg = 1;
+	    zexit(lastval, 0);
+	}
+	zerrnam("zsh", (!islogin) ? "use 'exit' to exit."
+		: "use 'logout' to logout.", NULL, 0);
+    }
+}
diff --git a/Src/main.c b/Src/main.c
index dbf1addc5..c9c5fa867 100644
--- a/Src/main.c
+++ b/Src/main.c
@@ -34,87 +34,5 @@
 int
 main(int argc, char **argv)
 {
-    char **t;
-    int t0;
-#ifdef USE_LOCALE
-    setlocale(LC_ALL, "");
-#endif
-
-    init_hackzero(argv, environ);
-
-    /*
-     * Provisionally set up the type table to allow metafication.
-     * This will be done properly when we have decided if we are
-     * interactive
-     */
-    typtab['\0'] |= IMETA;
-    typtab[STOUC(Meta)  ] |= IMETA;
-    typtab[STOUC(Marker)] |= IMETA;
-    for (t0 = (int)STOUC(Pound); t0 <= (int)STOUC(Nularg); t0++)
-	typtab[t0] |= ITOK | IMETA;
-
-    for (t = argv; *t; *t = metafy(*t, -1, META_ALLOC), t++);
-
-    zsh_name = argv[0];
-    do {
-      char *arg0 = zsh_name;
-      if (!(zsh_name = strrchr(arg0, '/')))
-	  zsh_name = arg0;
-      else
-	  zsh_name++;
-      if (*zsh_name == '-')
-	  zsh_name++;
-      if (strcmp(zsh_name, "su") == 0) {
-	  char *sh = zgetenv("SHELL");
-	  if (sh && *sh && arg0 != sh)
-	      zsh_name = sh;
-	  else
-	      break;
-      } else
-	  break;
-    } while (zsh_name);
-
-    fdtable_size = OPEN_MAX;
-    fdtable = zcalloc(fdtable_size);
-
-    createoptiontable();
-    emulate(zsh_name, 1);   /* initialises most options */
-    opts[LOGINSHELL] = (**argv == '-');
-    opts[MONITOR] = 1;   /* may be unset in init_io() */
-    opts[PRIVILEGED] = (getuid() != geteuid() || getgid() != getegid());
-    opts[USEZLE] = 1;   /* may be unset in init_io() */
-    parseargs(argv);   /* sets INTERACTIVE, SHINSTDIN and SINGLECOMMAND */
-
-    SHTTY = -1;
-    init_io();
-    setupvals();
-    init_signals();
-    init_bltinmods();
-    run_init_scripts();
-    init_misc();
-
-    for (;;) {
-	do
-	    loop(1,0);
-	while (tok != ENDINPUT && (tok != LEXERR || isset(SHINSTDIN)));
-	if (tok == LEXERR) {
-	    stopmsg = 1;
-	    zexit(lastval, 0);
-	}
-	if (!(isset(IGNOREEOF) && interact)) {
-#if 0
-	    if (interact)
-		fputs(islogin ? "logout\n" : "exit\n", shout);
-#endif
-	    zexit(lastval, 0);
-	    continue;
-	}
-	noexitct++;
-	if (noexitct >= 10) {
-	    stopmsg = 1;
-	    zexit(lastval, 0);
-	}
-	zerrnam("zsh", (!islogin) ? "use 'exit' to exit."
-		: "use 'logout' to logout.", NULL, 0);
-    }
+    return (zsh_main(argc, argv));
 }
diff --git a/Src/makepro.awk b/Src/makepro.awk
index b5d2f3dc4..158510d33 100644
--- a/Src/makepro.awk
+++ b/Src/makepro.awk
@@ -18,13 +18,9 @@ BEGIN {
     gsub(/\//, "_", name)
     ARGC--
 
-    # `locals' is a list of local declarations, built up while global
-    # declarations are output.
-    locals = ""
-
-    printf "#ifndef have_%s_globals\n", name
-    printf "#define have_%s_globals\n", name
-    printf "\n"
+    printf "E#ifndef have_%s_globals\n", name
+    printf "E#define have_%s_globals\n", name
+    printf "E\n"
 }
 
 # all relevant declarations are preceded by "/**/" on a line by itself
@@ -40,6 +36,13 @@ BEGIN {
 	    aborting = 1
 	    exit 1
 	}
+	if (line == "" && $0 ~ /^[ \t]*#/) {
+            # Directly after the /**/ was a preprocessor line.
+            # Spit it out and re-start the outer loop.
+	    printf "E%s\n", $0
+	    printf "L%s\n", $0
+	    next
+	}
 	gsub(/\t/, " ")
 	line = line " " $0
 	gsub(/\/\*([^*]|\*+[^*\/])*\*+\//, " ", line)
@@ -74,13 +77,16 @@ BEGIN {
 	    break
     }
     sub(/^ */, "", line)
-    match(line, /^((const|enum|static|struct|union) +)*([_0-9A-Za-z]+ +|((char|double|float|int|long|short|unsigned|void) +)+)((const|static) +)*/)
+    match(line, /^((const|enum|mod_export|static|struct|union) +)*([_0-9A-Za-z]+ +|((char|double|float|int|long|short|unsigned|void) +)+)((const|static) +)*/)
     dtype = substr(line, 1, RLENGTH)
     sub(/ *$/, "", dtype)
-    islocal = " " dtype " " ~ / static /
+    if(" " dtype " " ~ / static /)
+	locality = "L"
+    else
+	locality = "E"
+    exported = " " dtype " " ~ / mod_export /
     line = substr(line, RLENGTH+1) ","
     # Handle each declarator.
-    output = ""
     while(match(line, /^[^,]*,/)) {
 	# Separate out the name from the declarator.  Use "@+" and "@-"
 	# to bracket the name within the declarator.  Strip off any
@@ -103,44 +109,29 @@ BEGIN {
 	gsub(/@>/, ")", dcltor)
 	gsub(/@!/, ",", dcltor)
 
-	# If this is a module boot/cleanup function, conditionally rename it.
-	if(" " dtype " " ~ / int / && dcltor ~ / *@\+(boot|cleanup)_[_0-9A-Za-z]+@- *_\(\( *Module +[_0-9A-Za-z]+ *\)\) */) {
-	    modtype = dnam
-	    sub(/_.*$/, "", modtype)
-	    output = output "# if defined(DYNAMIC_NAME_CLASH_OK) && defined(MODULE)\n"
-	    output = output "#  define " dnam " " modtype "_\n"
-	    output = output "# endif\n"
-	}
+	# If this is exported, add it to the exported symbol list.
+	if(exported)
+	    printf "X%s\n", dnam
 
 	# Format the declaration for output
 	dcl = dtype " " dcltor ";"
-	if(!islocal)
+	if(locality ~ /E/)
 	    dcl = "extern " dcl
+	if(isfunc)
+	    gsub(/ mod_export /, " mod_import_function ", dcl)
+	else
+	    gsub(/ mod_export /, " mod_import_variable ", dcl)
 	gsub(/@[+-]/, "", dcl)
 	gsub(/ +/, " ", dcl)
 	while(match(dcl, /[^_0-9A-Za-z] ./) || match(dcl, /. [^_0-9A-Za-z]/))
 	    dcl = substr(dcl, 1, RSTART) substr(dcl, RSTART+2)
-	output = output dcl "\n"
+	printf "%s%s\n", locality, dcl
     }
-
-    # Output global declarations now, but save up locals until the end.
-    if(islocal)
-	locals = locals output
-    else
-	printf "%s", output
 }
 
 END {
     if(aborting)
 	exit 1
-    printf "\n"
-    printf "#endif /* !have_%s_globals */\n", name
-    if(locals != "") {
-	printf "\n"
-	printf "#ifndef GLOBAL_PROTOTYPES\n"
-	printf "\n"
-	printf locals
-	printf "\n"
-	printf "#endif /* !GLOBAL_PROTOTYPES */\n"
-    }
+    printf "E\n"
+    printf "E#endif /* !have_%s_globals */\n", name
 }
diff --git a/Src/mkmakemod.sh b/Src/mkmakemod.sh
index b088929fa..6c9e8bcf1 100644
--- a/Src/mkmakemod.sh
+++ b/Src/mkmakemod.sh
@@ -17,15 +17,21 @@
 # defines one module.  The .mdd file is actually a shell script, which will
 # be sourced.  It may define the following shell variables:
 #
-#   moddeps       modules on which this module depends (default none)
-#   nozshdep      non-empty indicates no dependence on the `zsh' pseudo-module
-#   alwayslink    if non-empty, always link the module into the executable
-#   autobins      builtins defined by the module, for autoloading
-#   objects       .o files making up this module (*must* be defined)
-#   proto         .pro files for this module (default generated from $objects)
-#   headers       extra headers for this module (default none)
-#   hdrdeps       extra headers on which the .mdh depends (default none)
-#   otherincs     extra headers that are included indirectly (default none)
+#   name            name of this module
+#   moddeps         modules on which this module depends (default none)
+#   nozshdep        non-empty indicates no dependence on the `zsh/main' pseudo-module
+#   alwayslink      if non-empty, always link the module into the executable
+#   autobins        builtins defined by the module, for autoloading
+#   autoinfixconds  infix condition codes defined by the module, for
+#                   autoloading (without the leading `-')
+#   autoprefixconds like autoinfixconds, but for prefix condition codes
+#   autoparams      parameters defined by the module, for autoloading
+#   automathfuncs   math functions defined by the module, for autoloading
+#   objects         .o files making up this module (*must* be defined)
+#   proto           .syms files for this module (default generated from $objects)
+#   headers         extra headers for this module (default none)
+#   hdrdeps         extra headers on which the .mdh depends (default none)
+#   otherincs       extra headers that are included indirectly (default none)
 #
 # The .mdd file may also include a Makefile.in fragment between lines
 # `:<<\Make' and `Make' -- this will be copied into Makemod.in.
@@ -34,9 +40,9 @@
 # For each module in also knows how to build a .mdh file.  Each source file
 # should #include the .mdh file for the module it is a part of.  The .mdh
 # file #includes the .mdh files for any module dependencies, then each of
-# $headers, and then each of $proto (for global declarations).  It will
+# $headers, and then each .epro (for global declarations).  It will
 # be recreated if any of the dependency .mdh files changes, or if any of
-# $headers or $hdrdeps changes.  When anything depends on it, all of $proto
+# $headers or $hdrdeps changes.  When anything depends on it, all the .epros
 # and $otherincs will be made up to date, but the .mdh file won't actually
 # be rebuilt if those files change.
 #
@@ -67,6 +73,15 @@ sed_normalise='
     s,\(.\)/$,\1,
 '
 
+CYGWIN=no
+if uname -s > /dev/null 2>&1; then
+    case `uname -s` in
+	CYGWIN* )
+	    CYGWIN=yes
+	;;
+    esac
+fi
+
 # decide which stages to process
 first_stage=true
 second_stage=true
@@ -98,14 +113,14 @@ if $first_stage; then
     echo
 
     . Src/modules.index
-    bin_mods=" zsh "`sed 's/^/ /;s/$/ /' Src/modules-bltin`
+    bin_mods=" zsh/main "`sed 's/^/ /;s/$/ /' Src/modules-bltin`
     if grep '%@D@%D%' config.status >/dev/null; then
 	is_dynamic=true
     else
 	is_dynamic=false
     fi
 
-    here_modules=
+    here_mddnames=
     all_subdirs=
     all_modobjs=
     all_modules=
@@ -114,30 +129,31 @@ if $first_stage; then
     all_proto=
     lastsub=//
     for module in $module_list; do
-	eval "loc=\$loc_$module"
-	case $loc in
-	    $the_subdir)
-		here_modules="$here_modules $module"
+	q_module=`echo $module | sed 's,Q,Qq,g;s,_,Qu,g;s,/,Qs,g'`
+	eval "modfile=\$modfile_$q_module"
+	case $modfile in
+	    $the_subdir/$lastsub/*) ;;
+	    $the_subdir/*/*)
+		lastsub=`echo $modfile | sed 's,^'$the_subdir'/,,;s,/[^/]*$,,'`
+		all_subdirs="$all_subdirs $lastsub"
+		;;
+	    $the_subdir/*)
+		mddname=`echo $modfile | sed 's,^.*/,,;s,\.mdd$,,'`
+		here_mddnames="$here_mddnames $mddname"
 		build=$is_dynamic
 		case $is_dynamic@$bin_mods in
 		    *" $module "*)
 			build=true
-			all_modobjs="$all_modobjs modobjs.${module}" ;;
+			all_modobjs="$all_modobjs modobjs.${mddname}" ;;
 		    true@*)
-			all_modules="$all_modules ${module}.\$(DL_EXT)" ;;
+			all_modules="$all_modules ${mddname}.\$(DL_EXT)" ;;
 		esac
-		all_mdds="$all_mdds ${module}.mdd"
-		$build && all_mdhs="$all_mdhs ${module}.mdh"
-		$build && all_proto="$all_proto proto.${module}"
-		;;
-	    $lastsub | $lastsub/*) ;;
-	    $the_subdir/*)
-		all_subdirs="$all_subdirs $loc"
-		lastsub=$loc
+		all_mdds="$all_mdds ${mddname}.mdd"
+		$build && all_mdhs="$all_mdhs ${mddname}.mdh"
+		$build && all_proto="$all_proto proto.${mddname}"
 		;;
 	esac
     done
-    all_subdirs=`echo "$all_subdirs" | sed "s' $the_subdir/' 'g"`
     echo "MODOBJS =$all_modobjs"
     echo "MODULES =$all_modules"
     echo "MDDS    =$all_mdds"
@@ -145,6 +161,11 @@ if $first_stage; then
     echo "PROTOS  =$all_proto"
     echo "SUBDIRS =$all_subdirs"
     echo
+    echo "ENTRYOBJ = \$(dir_src)/modentry..o"
+    echo "NNTRYOBJ ="
+    echo "ENTRYOPT = -emodentry"
+    echo "NNTRYOPT ="
+    echo
 
     echo "##### ===== INCLUDING Makemod.in.in ===== #####"
     echo
@@ -159,95 +180,230 @@ if $first_stage; then
 
     other_mdhs=
     remote_mdhs=
-    for module in $here_modules; do
+    other_exports=
+    remote_exports=
+    other_modules=
+    remote_modules=
+    for mddname in $here_mddnames; do
 
-	unset moddeps nozshdep alwayslink
-	unset autobins
+	unset name moddeps nozshdep alwayslink hasexport
+	unset autobins autoinfixconds autoprefixconds autoparams automathfuncs
 	unset objects proto headers hdrdeps otherincs
-	. $top_srcdir/$the_subdir/${module}.mdd
+	. $top_srcdir/$the_subdir/${mddname}.mdd
+	q_name=`echo $name | sed 's,Q,Qq,g;s,_,Qu,g;s,/,Qs,g'`
 	test -n "${moddeps+set}" || moddeps=
-	test -n "$nozshdep" || moddeps="$moddeps zsh"
+	test -n "$nozshdep" || moddeps="$moddeps zsh/main"
 	test -n "${proto+set}" ||
-	    proto=`echo $objects '' | sed 's,\.o ,.pro ,g'`
+	    proto=`echo $objects '' | sed 's,\.o ,.syms ,g'`
 
 	dobjects=`echo $objects '' | sed 's,\.o ,..o ,g'`
 	modhdeps=
+	mododeps=
+	exportdeps=
+	imports=
+	q_moddeps=
+	dllname=
 	for dep in $moddeps; do
-	    eval "loc=\$loc_$dep"
+	    q_dep=`echo $dep | sed 's,Q,Qq,g;s,_,Qu,g;s,/,Qs,g'`
+	    q_moddeps="$q_moddeps $q_dep"
+	    eval "depfile=\$modfile_$q_dep"
+	    eval `echo $depfile | sed 's,/\([^/]*\)\.mdd$,;depbase=\1,;s,^,loc=,'`
+	    case "$binmod" in
+		*" $dep "* )
+		    dep=zsh/main
+		;;
+	    esac
+
 	    case $the_subdir in
 		$loc)
-		    mdh="${dep}.mdh"
+		    mdh="${depbase}.mdh"
+		    export="${depbase}.export"
+		    case "$dep" in
+			zsh/main )
+			    mdll="\$(dir_top)/Src/libzsh-\$(VERSION).\$(DL_EXT) "
+			;;
+			zsh/$mddname )
+			    mdll=
+			;;
+			* )
+			    mdll="${depbase}.\$(DL_EXT) "
+			;;
+		    esac
 		    ;;
 		$loc/*)
-		    mdh="\$(dir_top)/$loc/${dep}.mdh"
+		    mdh="\$(dir_top)/$loc/${depbase}.mdh"
 		    case "$other_mdhs " in
 			*" $mdh "*) ;;
 			*) other_mdhs="$other_mdhs $mdh" ;;
 		    esac
+		    export="\$(dir_top)/$loc/${depbase}.export"
+		    case "$other_exports " in
+			*" $export "*) ;;
+			*) other_exports="$other_exports $export" ;;
+		    esac
+		    case "$dep" in
+			zsh/main )
+			    mdll="\$(dir_top)/Src/libzsh-\$(VERSION).\$(DL_EXT) "
+			;;
+			zsh/$mddname )
+			    mdll=
+			;;
+			* )
+			    mdll="\$(dir_top)/$loc/${depbase}.\$(DL_EXT) "
+			;;
+		    esac
+		    case "$other_modules " in
+			*" $mdll "*) ;;
+			*) other_modules="$other_modules $mdll" ;;
+		    esac
 		    ;;
 		*)
-		    mdh="\$(dir_top)/$loc/${dep}.mdh"
+		    mdh="\$(dir_top)/$loc/${depbase}.mdh"
 		    case "$remote_mdhs " in
 			*" $mdh "*) ;;
 			*) remote_mdhs="$remote_mdhs $mdh" ;;
 		    esac
+		    export="\$(dir_top)/$loc/${depbase}.export"
+		    case "$remote_exports " in
+			*" $export "*) ;;
+			*) remote_exports="$remote_exports $export" ;;
+		    esac
+		    case "$dep" in
+			zsh/main )
+			    mdll="\$(dir_top)/Src/libzsh-\$(VERSION).\$(DL_EXT) "
+			;;
+			zsh/$mddname )
+			    mdll=
+			;;
+			* )
+			    mdll="\$(dir_top)/$loc/${depbase}.\$(DL_EXT) "
+			;;
+		    esac
+		    case "$remote_modules " in
+			*" $mdll "*) ;;
+			*) remote_modules="$remote_modules $mdll" ;;
+		    esac
 		    ;;
 	    esac
 	    modhdeps="$modhdeps $mdh"
+	    exportdeps="$exportdeps $export"
+	    imports="$imports \$(IMPOPT)$export"
+	    if test $CYGWIN = yes -a -n "$mdll"; then
+		case "$mododeps" in
+		    *" $mdll "* )
+			:
+		    ;;
+		    * )
+			mododeps="$mododeps $mdll"
+		    ;;
+		esac
+	    fi
 	done
+	if test $CYGWIN = yes; then
+		dllname="--dllname $q_name"
+	fi
 
-	echo "##### ===== DEPENDENCIES GENERATED FROM ${module}.mdd ===== #####"
+	echo "##### ===== DEPENDENCIES GENERATED FROM ${mddname}.mdd ===== #####"
+	echo
+	echo "MODOBJS_${mddname} = $objects"
+	echo "MODDOBJS_${mddname} = $dobjects \$(@E@NTRYOBJ)"
+	echo "SYMS_${mddname} = $proto"
+	echo "EPRO_${mddname} = "`echo $proto '' | sed 's,\.syms ,.epro ,g'`
+	echo "INCS_${mddname} = \$(EPRO_${mddname}) $otherincs"
+	echo "EXPIMP_${mddname} = $imports \$(EXPOPT)$mddname.export"
+	echo "NXPIMP_${mddname} ="
+	echo "DEPMODS_${mddname} = $mododeps"
+	echo "DLLNAME_${mddname} = $dllname"
 	echo
-	echo "MODOBJS_${module} = $objects"
-	echo "MODDOBJS_${module} = $dobjects"
-	echo "PROTO_${module} = $proto"
-	echo "INCS_${module} = \$(PROTO_${module}) $otherincs"
+	echo "proto.${mddname}: \$(EPRO_${mddname})"
+	echo "\$(SYMS_${mddname}): \$(PROTODEPS)"
 	echo
-	echo "proto.${module}: \$(PROTO_${module})"
-	echo "\$(PROTO_${module}): \$(PROTODEPS)"
+	echo "${mddname}.export: \$(SYMS_${mddname})"
+	echo "	( echo '#!'; cat \$(SYMS_${mddname}) | sed -n '/^X/{s/^X//;p;}' | sort -u ) > \$@"
 	echo
-	echo "modobjs.${module}: \$(MODOBJS_${module})"
-	echo "	echo '' \$(MODOBJS_${module}) $modobjs_sed>> \$(dir_src)/stamp-modobjs.tmp"
+	echo "modobjs.${mddname}: \$(MODOBJS_${mddname})"
+	echo "	echo '' \$(MODOBJS_${mddname}) $modobjs_sed>> \$(dir_src)/stamp-modobjs.tmp"
 	echo
 	if test -z "$alwayslink"; then
-	    echo "${module}.\$(DL_EXT): \$(MODDOBJS_${module})"
+	    case " $all_modules" in *" ${mddname}."*)
+		echo "install.modules-here: install.modules.${mddname}"
+		echo "uninstall.modules-here: uninstall.modules.${mddname}"
+		echo
+	    ;; esac
+	    instsubdir=`echo $name | sed 's,^,/,;s,/[^/]*$,,'`
+	    echo "install.modules.${mddname}: ${mddname}.\$(DL_EXT)"
+	    echo "	\$(sdir_top)/mkinstalldirs \$(DESTDIR)\$(MODDIR)${instsubdir}"
+	    echo "	\$(INSTALL_PROGRAM) ${mddname}.\$(DL_EXT) \$(DESTDIR)\$(MODDIR)/${name}.\$(DL_EXT)"
+	    echo
+	    echo "uninstall.modules.${mddname}:"
+	    echo "	rm -f \$(DESTDIR)\$(MODDIR)/${name}.\$(DL_EXT)"
+	    echo
+	    echo "${mddname}.\$(DL_EXT): \$(MODDOBJS_${mddname}) ${mddname}.export $exportdeps \$(DEPMODS_${mddname})"
 	    echo '	rm -f $@'
-	    echo "	\$(DLLINK) \$(MODDOBJS_${module}) \$(LIBS)"
+	    echo "	\$(DLLINK) \$(@E@XPIMP_$mddname) \$(@E@NTRYOPT) \$(DLLNAME_${mddname}) \$(MODDOBJS_${mddname}) \$(DEPMODS_${mddname}) \$(LIBS) "
 	    echo
 	fi
-	echo "${module}.mdhi: ${module}.mdhs \$(INCS_${module})"
+	echo "${mddname}.mdhi: ${mddname}.mdhs \$(INCS_${mddname})"
 	echo "	@test -f \$@ || echo 'do not delete this file' > \$@"
 	echo
-	echo "${module}.mdhs: ${module}.mdd"
-	echo "	@\$(MAKE) -f \$(makefile) \$(MAKEDEFS) ${module}.mdh.tmp"
-	echo "	@if cmp -s ${module}.mdh ${module}.mdh.tmp; then \\"
-	echo "	    rm -f ${module}.mdh.tmp; \\"
-	echo "	    echo \"\\\`${module}.mdh' is up to date.\"; \\"
+	echo "${mddname}.mdhs: ${mddname}.mdd"
+	echo "	@\$(MAKE) -f \$(makefile) \$(MAKEDEFS) ${mddname}.mdh.tmp"
+	echo "	@if cmp -s ${mddname}.mdh ${mddname}.mdh.tmp; then \\"
+	echo "	    rm -f ${mddname}.mdh.tmp; \\"
+	echo "	    echo \"\\\`${mddname}.mdh' is up to date.\"; \\"
 	echo "	else \\"
-	echo "	    mv -f ${module}.mdh.tmp ${module}.mdh; \\"
-	echo "	    echo \"Updated \\\`${module}.mdh'.\"; \\"
+	echo "	    mv -f ${mddname}.mdh.tmp ${mddname}.mdh; \\"
+	echo "	    echo \"Updated \\\`${mddname}.mdh'.\"; \\"
 	echo "	fi"
-	echo "	echo 'timestamp for ${module}.mdh against ${module}.mdd' > \$@"
+	echo "	echo 'timestamp for ${mddname}.mdh against ${mddname}.mdd' > \$@"
 	echo
-	echo "${module}.mdh: ${modhdeps} ${headers} ${hdrdeps} ${module}.mdhi"
-	echo "	@\$(MAKE) -f \$(makefile) \$(MAKEDEFS) ${module}.mdh.tmp"
-	echo "	@mv -f ${module}.mdh.tmp ${module}.mdh"
-	echo "	@echo \"Updated \\\`${module}.mdh'.\""
+	echo "${mddname}.mdh: ${modhdeps} ${headers} ${hdrdeps} ${mddname}.mdhi"
+	echo "	@\$(MAKE) -f \$(makefile) \$(MAKEDEFS) ${mddname}.mdh.tmp"
+	echo "	@mv -f ${mddname}.mdh.tmp ${mddname}.mdh"
+	echo "	@echo \"Updated \\\`${mddname}.mdh'.\""
 	echo
-	echo "${module}.mdh.tmp:"
+	echo "${mddname}.mdh.tmp:"
 	echo "	@( \\"
-	echo "	    echo '#ifndef have_${module}_module'; \\"
-	echo "	    echo '#define have_${module}_module'; \\"
+	echo "	    echo '#ifndef have_${q_name}_module'; \\"
+	echo "	    echo '#define have_${q_name}_module'; \\"
+	echo "	    echo; \\"
+	echo "	    echo '# ifndef IMPORTING_MODULE_${q_name}'; \\"
+	if test $CYGWIN = yes; then
+	    echo "	    echo '#  ifdef MODULE'; \\"
+	    echo "	    echo '#   define boot_ __attribute__((__dllexport__)) boot_${q_name}'; \\"
+	    echo "	    echo '#   define cleanup_ __attribute__((__dllexport__)) cleanup_${q_name}'; \\"
+	    echo "	    echo '#   define setup_ __attribute__((__dllexport__)) setup_${q_name}'; \\"
+	    echo "	    echo '#   define finish_ __attribute__((__dllexport__)) finish_${q_name}'; \\"
+	    echo "	    echo '#  else /* MODULE */'; \\"
+	    echo "	    echo '#   define boot_ boot_${q_name}'; \\"
+	    echo "	    echo '#   define cleanup_ cleanup_${q_name}'; \\"
+	    echo "	    echo '#   define setup_ setup_${q_name}'; \\"
+	    echo "	    echo '#   define finish_ finish_${q_name}'; \\"
+	    echo "	    echo '#  endif /* MODULE */'; \\"
+	else
+	    echo "	    if test @SHORTBOOTNAMES@ = yes; then \\"
+	    echo "		echo '#  ifndef MODULE'; \\"
+	    echo "	    fi; \\"
+	    echo "	    echo '#   define boot_ boot_${q_name}'; \\"
+	    echo "	    echo '#   define cleanup_ cleanup_${q_name}'; \\"
+	    echo "	    echo '#   define setup_ setup_${q_name}'; \\"
+	    echo "	    echo '#   define finish_ finish_${q_name}'; \\"
+	    echo "	    if test @SHORTBOOTNAMES@ = yes; then \\"
+	    echo "		echo '#  endif /* !MODULE */'; \\"
+	    echo "	    fi; \\"
+	fi
+	echo "	    echo '# endif /* !IMPORTING_MODULE_${q_name} */'; \\"
 	echo "	    echo; \\"
-	if test -n "$moddeps"; then
+	if test -n "$moddeps"; then (
+	    set x $q_moddeps
 	    echo "	    echo '/* Module dependencies */'; \\"
-	    echo "	    for mod in $modhdeps; do \\"
-	    echo "		echo '# define USING_MODULE'; \\"
-	    echo "		echo '# include \"'\$\$mod'\"'; \\"
-	    echo "	    done; \\"
-	    echo "	    echo '# undef USING_MODULE'; \\"
+	    for hdep in $modhdeps; do
+		shift
+		echo "	    echo '# define IMPORTING_MODULE_${1} 1'; \\"
+		echo "	    echo '# include \"${hdep}\"'; \\"
+	    done
 	    echo "	    echo; \\"
-	fi
+	) fi
 	if test -n "$headers"; then
 	    echo "	    echo '/* Extra headers for this module */'; \\"
 	    echo "	    for hdr in $headers; do \\"
@@ -260,25 +416,35 @@ if $first_stage; then
 	    echo "	    echo; \\"
 	fi
 	if test -n "$proto"; then
-	    echo "	    echo '# define GLOBAL_PROTOTYPES'; \\"
-	    echo "	    for pro in \$(PROTO_${module}); do \\"
-	    echo "		echo '# include \"'\$\$pro'\"'; \\"
+	    if test "$CYGWIN" = yes; then
+		echo "	    echo '# ifndef IMPORTING_MODULE_${q_name} '; \\"
+		echo "	    echo '#  undef mod_import_variable'; \\"
+		echo "	    echo '#  define mod_import_variable'; \\"
+		echo "	    echo '# endif /* IMPORTING_MODULE_${q_name} */'; \\"
+	    fi
+	    echo "	    for epro in \$(EPRO_${mddname}); do \\"
+	    echo "		echo '# include \"'\$\$epro'\"'; \\"
 	    echo "	    done; \\"
-	    echo "	    echo '# undef GLOBAL_PROTOTYPES'; \\"
+	    if test "$CYGWIN" = yes; then
+		echo "	    echo '# ifndef IMPORTING_MODULE_${q_name} '; \\"
+		echo "	    echo '#  undef mod_import_variable'; \\"
+		echo "	    echo '#  define mod_import_variable __attribute__((__dllimport__))'; \\"
+		echo "	    echo '# endif /* IMPORTING_MODULE_${q_name} */'; \\"
+	    fi
 	    echo "	    echo; \\"
 	fi
-	echo "	    echo '#endif /* !have_${module}_module */'; \\"
+	echo "	    echo '#endif /* !have_${q_name}_module */'; \\"
 	echo "	) > \$@"
 	echo
-	echo "\$(MODOBJS_${module}) \$(MODDOBJS_${module}): ${module}.mdh"
+	echo "\$(MODOBJS_${mddname}) \$(MODDOBJS_${mddname}): ${mddname}.mdh"
 	sed -e '/^ *: *<< *\\Make *$/,/^Make$/!d' \
 	    -e 's/^ *: *<< *\\Make *$//; /^Make$/d' \
-	    < $top_srcdir/$the_subdir/${module}.mdd
+	    < $top_srcdir/$the_subdir/${mddname}.mdd
 	echo
 
     done
 
-    if test -n "$remote_mdhs$other_mdhs"; then
+    if test -n "$remote_mdhs$other_mdhs$remote_exports$other_exports$remote_modules$other_modules"; then
 	echo "##### ===== DEPENDENCIES FOR REMOTE MODULES ===== #####"
 	echo
 	for mdh in $remote_mdhs; do
@@ -287,10 +453,32 @@ if $first_stage; then
 	    echo
 	done | sed 's,^\(.*\)@%@\(.*\)@%@\(.*\)/\([^/]*\)$,\1\3\2\4,'
 	if test -n "$other_mdhs"; then
-	    echo "${other_mdhs}:"
+	    echo "${other_mdhs}:" | sed 's,^ ,,'
+	    echo "	false # should only happen with make -n"
+	    echo
+	fi
+	for export in $remote_exports; do
+	    echo "$export: FORCE"
+	    echo "	@cd @%@ && \$(MAKE) \$(MAKEDEFS) @%@$export"
+	    echo
+	done | sed 's,^\(.*\)@%@\(.*\)@%@\(.*\)/\([^/]*\)$,\1\3\2\4,'
+	if test -n "$other_exports"; then
+	    echo "${other_exports}:" | sed 's,^ ,,'
 	    echo "	false # should only happen with make -n"
 	    echo
 	fi
+	if test "$CYGWIN" = yes; then
+	    for mdll in $remote_modules; do
+		echo "$mdll: FORCE"
+		echo "	@cd @%@ && \$(MAKE) \$(MAKEDEFS) @%@$mdll"
+		echo
+	    done | sed 's,^\(.*\)@%@\(.*\)@%@\(.*\)/\([^/]*\)$,\1\3\2\4,'
+	    if test -n "$other_modules"; then
+		echo "${other_modules}:" | sed 's,^ ,,'
+		echo "	false # should only happen with make -n"
+		echo
+	    fi
+	fi
     fi
 
     echo "##### End of ${the_makefile}.in"
diff --git a/Src/parse.c b/Src/parse.c
index ddeb5e529..7ea6b28d3 100644
--- a/Src/parse.c
+++ b/Src/parse.c
@@ -3070,7 +3070,8 @@ decrdumpcount(FuncDump f)
 {
 }
 
-void
+/**/
+mod_export void
 closedumps(void)
 {
 }
diff --git a/Src/zsh.h b/Src/zsh.h
index a21fa16e6..dc24db2ed 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -1681,7 +1681,15 @@ typedef unsigned char * (*ZleReadFn) _((char *, char *, int));
 /* Pseudo-keyword to mark exportedness */
 /***************************************/
 
+#ifdef __CYGWIN__
+#define mod_export __attribute__((__dllexport__))
+#define mod_import_variable __attribute__((__dllimport__))
+#define mod_import_function
+#else
 #define mod_export
+#define mod_import_variable
+#define mod_import_function
+#endif
 
 /***************************************/
 /* Hooks in core.                      */
diff --git a/configure.in b/configure.in
index f6c80a2a3..6f813e0b0 100644
--- a/configure.in
+++ b/configure.in
@@ -1467,6 +1467,18 @@ if test "x$aixdynamic" = xyes; then
   zsh_cv_sys_dynamic_strip_exe="${zsh_cv_sys_dynamic_strip_exe=yes}"
   zsh_cv_sys_dynamic_strip_lib="${zsh_cv_sys_dynamic_strip_lib=yes}"
   zsh_cv_sys_dynamic_broken="${zsh_cv_sys_dynamic_broken=no}"
+elif test "x$ac_cv_cygwin" = xyes; then
+  DL_EXT="${DL_EXT=dll}"
+  DLLD="${DLLD=dllwrap}"
+  zsh_cv_func_dlsym_needs_underscore=no
+  DLLDFLAGS=${DLLDFLAGS=}
+  EXTRA_LDFLAGS=${EXTRA_LDFLAGS=}
+  zsh_cv_sys_dynamic_clash_ok="${zsh_cv_sys_dynamic_clash_ok=no}"
+  zsh_cv_sys_dynamic_rtld_global="${zsh_cv_sys_dynamic_rtld_global=yes}"
+  zsh_cv_sys_dynamic_execsyms="${zsh_cv_sys_dynamic_execsyms=no}"
+  zsh_cv_sys_dynamic_strip_exe="${zsh_cv_sys_dynamic_strip_exe=yes}"
+  zsh_cv_sys_dynamic_strip_lib="${zsh_cv_sys_dynamic_strip_lib=yes}"
+  zsh_cv_sys_dynamic_broken="${zsh_cv_sys_dynamic_broken=no}"
 elif test "x$dynamic" = xyes; then
   AC_CACHE_CHECK(if your system use ELF binaries,
    zsh_cv_sys_elf,
@@ -1654,6 +1666,16 @@ else
 fi
 AC_SUBST(SHORTBOOTNAMES)
 
+if test "x$ac_cv_cygwin" = xyes; then
+  INSTLIB="install.cygwin-lib"
+  UNINSTLIB="uninstall.cygwin-lib"
+else
+  INSTLIB="install.bin-\$(L)"
+  UNINSTLIB="uninstall.bin-\$(L)"
+fi
+AC_SUBST(INSTLIB)dnl
+AC_SUBST(UNINSTLIB)dnl
+
 AC_DEFINE_UNQUOTED(DL_EXT, "$DL_EXT")dnl
 AC_SUBST(D)dnl
 AC_SUBST(DL_EXT)dnl