2022-09-09  Juan Manuel Guerrero  <juan.guerrero@gmx.de>

	* doc/m4.texi: Add DJGPP specific info about place where the tmp files
	are stored.
	Add (ENOENT) to error message.
	Add DJGPP specific info about supported M4PATH path separator characters.
	Adjust different tests to DJGPP peculiarities.

	* lib/cloexec.c (set_cloexec_flag) [!MSDOS]: On MSDOS/Windows
	systems always return success.

	* lib/djgpp-spawn.h: New file.  Provides dup_noinherit, djgpp_pipe,
	fd_safer_noinherit, dup_safer_noinherit and undup_safer_noinherit.
	(djgpp_pipe): Register file descriptor of the pipe end that has
	been open.
	(remove_tmp_file): Close the file corresponding to the pipe end
	before removing it.

	* lib/execute.c [__DJGPP__]: DJGPP specific implementation of execute.

	* lib/fatal-signal.c [__DJGPP__]: New macro SIGNAL_INDEX used to
	adjust the signal numbers used by DJGPP to fit into the range of
	saved_sigactions.
	(uninstall_handlers): Use SIGNAL_INDEX to access saved_sigactions.
	(install_handlers): Use SIGNAL_INDEX to access saved_sigactions.

	* lib/fflush.c (rpl_fflush) [__DJGPP__]: Call fflush directly and do
	not try to do any POSIX specific stuff especially do not seek STDIN
	if connected to a file.  This would make lose synchronization between
        buffer pointer of FILE structure and and DOS file pointer.

	* lib/fopen.c: If ISSLASH is not defined include dosname.h
	(rpl_fopen): Use ISSLASH to check for the OS dependent directory
	separator character.

	* lib/getprogname.c (getprogname) [__DJGPP__]:  Implementation of
	DJGPP support.

	* lib/open.c: If ISSLASH is not defined include dosname.h
	(open): Use ISSLASH to check for the OS dependent directory separator
	character.

	* lib/progname.c [MSDOS]: Define new macro GET_LAST_SLASH to find
	the last directory separator character.  On DOS-Like systems these
	are slash, backslash or colon.  For POSIX this is simple a slash.

	* lib/secure_getenv.c [HAVE_ISSETUGID, __DJGPP__]: DOS does not provide
	issetugid.  Call getenv always.

	* lib/spawn-pipe.c [__DJGPP__]: remove_tmp_files definition.
	Closes and unlinks the file corresponding to the pipe end that
	could not be closed and unlinked during normal operation.

	* lib/stdio-impl.h [__DJGPP__]: Include sys/file.h to provide _IOERR
	for fseterr function support.

	* lib/tempname.c [__DJGPP__]: New macros HAVE_DIFFERENT_TMPDIR and
	HAVE_LFN_SUPPORT.  Values depend on if the OS is posix or not.
	Include libc/unconst.h.
	(__path_search): Use HAVE_LFN_SUPPORT to limit the length of the prefix
	string used to create the temporary file name.
	(__path_search): Use ISSLASH to check for the OS dependent directory
	separator character.  Use HAVE_DIFFERENT_TMPDIR to check for TMP and
	TEMP too, if none of them are defined or do not point to an existing
	directory default to the current directory.

	* lib/tmpdir.c [__DJGPP__]: New macros HAVE_DIFFERENT_TMPDIR and
	HAVE_LFN_SUPPORT.  Values depend on if the OS is posix or not.
	Include libc/unconst.h.
	(path_search): Use ISSLASH to check for the OS dependent directory
	separator character.  Use HAVE_DIFFERENT_TMPDIR to check for TMP and
	TEMP too, if none of them are defined or do not point to an existing
	directory default to the current directory.
	(path_search): Use HAVE_LFN_SUPPORT to limit the length of the prefix
	string used to create the temporary file name.

	* lib/wait-process.c [__DJGPP__]: Include djgpp-spawn.h.
	DJGPP specific implementation of wait_subprocess.  Removes the tmp
	files used to implement the pipe.

	* src/builtin.c: Add MSDOS and DJGPP to the supported platform macros
	list.
	(m4_syscmd, m4_esyscmd): For MSDOS allow command.com as shell as well.

	* src/m4.c [__DJGPP__]: Declaration of remove_tmp_files added.
	(djgpp_m4_startup) [__DJGPP__]: Adds remove_tmp_files to destructor.
	(usage) [__DJGPP__]: Add DJGPP specific info about M4PATH.
	(main): Use STRIP_FULL_PATH_AND_EXTENSION to strip path and extension
	from argv[0].

	* src/m4.h: Added FILE_SYSTEM_ACCEPTS_DRIVE_LETTER_PREFIX. This macro
	is used to define a serie of macros to parametrize OS specific issues
	like path separators, directory separators, drive letters, etc.
	New macro DOSISH to define a canonical recognition macro for
	MSDOS and DJGPP.  For DJGPP also define UNIX.
	New macro STRIP_FULL_PATH_AND_EXTENSION defined.  For all other systems
	this macro is a no-op.
	[FILE_SYSTEM_ACCEPTS_DRIVE_LETTER_PREFIX]: New macro HAVE_LFN_SUPPORT
	defined.  For all other systems this macro is a no-op.

	* src/output.c (m4_tmpname): Use HAVE_LFN_SUPPORT to determinate a
	valid file name pattern.
	(make_room_for): Added SET_BINARY. On systems that distinguish between
	text and binary files, tmpfiles are opened in binary mode. For all
	others OS it is a no-op macro.  Now the SET_BINARY macro is defined by
	gnulib in /lib/binary-io.h and expects a file descriptor as argument.

	* src/path.c (include_env_init): If FILE_SYSTEM_ACCEPTS_DRIVE_LETTER_PREFIX
	is defined check the enironment variable PATH_SEPARATOR to determiante
	the path separator character to be used.  For posix systems the default
	is colon, for DOS/DJGPP the default is semi colon.
	Use CANONICALIZE_PATH to replace DOS-style backslash directory separator
	to unix-style slash directory separtor.











diff -aprNU5 m4-1.4.19.orig/doc/m4.texi m4-1.4.19/doc/m4.texi
--- m4-1.4.19.orig/doc/m4.texi	2021-05-28 14:41:46 +0000
+++ m4-1.4.19/doc/m4.texi	2022-09-10 10:58:20 +0000
@@ -5016,14 +5016,14 @@ parameters.
 @end deffn
 
 @comment status: 1
 @example
 include(`none')
-@error{}m4:stdin:1: cannot open `none': No such file or directory
+@error{}m4:stdin:1: cannot open `none': No such file or directory (ENOENT)
 @result{}
 include()
-@error{}m4:stdin:2: cannot open `': No such file or directory
+@error{}m4:stdin:2: cannot open `': No such file or directory (ENOENT)
 @result{}
 sinclude(`none')
 @result{}
 sinclude()
 @result{}
@@ -5142,10 +5142,19 @@ directory.  Next comes the directories s
 @option{--include} or @option{-I} option, in the order found on the
 command line.  Finally, if the @env{M4PATH} environment variable is set,
 it is expected to contain a colon-separated list of directories, which
 will be searched in order.
 
+For the @acronym{DJGPP} port of @code{m4} the @env{M4PATH} environment variable
+points to either a semicolon-separted (default) or colon-separated list of
+directories.  The character to be used as path separator will be determinated
+by the value of the @env{PATH_SEPARATOR} environment variable.  If the variable
+is not set or set to @samp{;}, then the directory list must be a semicolon-separted
+list; if @env{PATH_SEPARATOR} is set to @samp{:}, then the directory list must be a
+colon-separted list.  In both cases the @acronym{DJGPP} specific syntax for drive
+letter prefix, e.g.: @samp{c:} is equivalent to @samp{/dev/c}, is supported.
+
 If the automatic search for include-files causes trouble, the @samp{p}
 debug flag (@pxref{Debug Levels}) can help isolate the problem.
 
 @node Diversions
 @chapter Diverting and undiverting output
@@ -5164,10 +5173,15 @@ limit to the overall memory usable by al
 (512K, currently).  When this maximum is about to be exceeded,
 a temporary file is opened to receive the contents of the biggest
 diversion still in memory, freeing this memory for other diversions.
 When creating the temporary file, @code{m4} honors the value of the
 environment variable @env{TMPDIR}, and falls back to @file{/tmp}.
+The @acronym{DJGPP} port of @acronym{GNU} @code{m4} also honors the
+value of the environment variables @env{TMP} and @env{TEMP}, in that
+order, if @env{TMPDIR} is not defined or points to a not existing
+directory, and falls back to the value of @code{P_tmpdir}.  If this also
+fails then it falls back to @file{./}.
 Thus, the amount of available disk space provides the only real limit on
 the number and aggregate size of diversions.
 
 @ignore
 @comment We need to test spilled diversions, but don't need to expose
@@ -6494,10 +6508,14 @@ Sometimes it is desirable for an input f
 @code{m4} is running on.  GNU @code{m4} provides several
 macros that are predefined to expand to the empty string; checking for
 their existence will confirm platform details.
 
 @deffn {Optional builtin} __gnu__
+@deffnx {Optional builtin} __djgpp__
+@deffnx {Optional builtin} djgpp
+@deffnx {Optional builtin} __msdos__
+@deffnx {Optional builtin} msdos
 @deffnx {Optional builtin} __os2__
 @deffnx {Optional builtin} os2
 @deffnx {Optional builtin} __unix__
 @deffnx {Optional builtin} unix
 @deffnx {Optional builtin} __windows__
@@ -6542,10 +6560,14 @@ On native Windows systems, GNU @code{m4}
 @option{-G} option is specified.
 
 On OS/2 systems, GNU @code{m4} will define @code{@w{__os2__}}
 by default, or @code{os2} when the @option{-G} option is specified.
 
+On MSDOS/DJGPP systems, @acronym{GNU} @code{m4} will define @code{@w{__djgpp__}},
+@code{@w{__msdos__}} and @code{@w{__unix__}} by default, or @code{djgpp}, @code{msdos}
+and @code{unix} when the @option{-G} option is specified.
+
 If GNU @code{m4} does not provide a platform macro for your system,
 please report that as a bug.
 
 @example
 define(`provided', `0')
@@ -6554,12 +6576,16 @@ ifdef(`__unix__', `define(`provided', in
 @result{}
 ifdef(`__windows__', `define(`provided', incr(provided))')
 @result{}
 ifdef(`__os2__', `define(`provided', incr(provided))')
 @result{}
+ifdef(`__djgpp__', `define(`provided', incr(provided))')
+@result{}
+ifdef(`__msdos__', `define(`provided', incr(provided))')
+@result{}
 provided
-@result{}1
+@result{}3
 @end example
 
 @node Syscmd
 @section Executing simple commands
 
@@ -6882,12 +6908,12 @@ sysval
 @example
 syscmd(`rm -rf foodir')sysval
 @result{}0
 syscmd(`mkdir foodir')sysval
 @result{}0
-len(mkstemp(`foodir/fooXXXXX'))
-@result{}16
+len(mkstemp(`foodir/foXXXXX'))
+@result{}15
 syscmd(`rm -r foodir')sysval
 @result{}0
 @end example
 
 @c Likewise, and ensure that traditional mode leaves the result unquoted
@@ -7256,11 +7282,11 @@ syscmd([echo 'changequote([,])pushdef([d
 @comment xerr: ignore
 @comment status: 1
 @example
 $ @kbd{m4 -F /none/such}
 ^D
-@error{}m4: cannot open `/none/such': No such file or directory
+@error{}m4: cannot open `/none/such': No such file or directory (ENOENT)
 @end example
 @end ignore
 
 When an @code{m4} run is to be frozen, the automatic undiversion
 which takes place at end of execution is inhibited.  Instead, all
diff -aprNU5 m4-1.4.19.orig/lib/cloexec.c m4-1.4.19/lib/cloexec.c
--- m4-1.4.19.orig/lib/cloexec.c	2021-04-22 20:28:46 +0000
+++ m4-1.4.19/lib/cloexec.c	2022-09-10 10:58:20 +0000
@@ -36,11 +36,19 @@
    non-inheritable in the first place.  */
 
 int
 set_cloexec_flag (int desc, bool value)
 {
-#ifdef F_SETFD
+#if defined F_SETFD && !defined MSDOS
+/*
+ *  On MSDOS/Windows DJGPP 2.03 always returns 0 for the handles
+ *  below 18 and FD_CLOEXEC for 19 and 20.
+ *  To avoid error messages like:
+ *    Warning: cannot protect input file across forks: Function not implemented (ENOSYS)
+ *  this function call returns always success.  This will not hurd because MSDOS/Windows
+ *  has no fork functionality at all.
+ */
 
   int flags = fcntl (desc, F_GETFD, 0);
 
   if (0 <= flags)
     {
diff -aprNU5 m4-1.4.19.orig/lib/djgpp-spawn.h m4-1.4.19/lib/djgpp-spawn.h
--- m4-1.4.19.orig/lib/djgpp-spawn.h	1970-01-01 00:00:00 +0000
+++ m4-1.4.19/lib/djgpp-spawn.h	2022-09-10 11:03:48 +0000
@@ -0,0 +1,165 @@
+#include <config.h>
+#include <stdio.h>
+#include "cloexec.h"
+#include "xalloc.h"
+
+
+#define PROGRAM_NAME_TEMPLATE  "m4XXXXXX"
+
+#define prepare_spawn(argv)                                                  \
+(__gnuc_extension__                                                          \
+  ({                                                                         \
+     size_t _argc;                                                           \
+     char **_new_argv;                                                       \
+                                                                             \
+     for (_argc = 0; (argv)[_argc]; _argc++)                                 \
+       ;                                                                     \
+                                                                             \
+     _new_argv = xmalloc((1 + _argc + 1) * sizeof(_new_argv[0]));            \
+     /*                                                                      \
+      *  Do not use neither an absolute path to the bash program             \
+      *  nor the environment variable /dev/env/DJDIR.  It can never          \
+      *  be assumed that they are setup correctly.  Let the system           \
+      *  search along the PATH and hope for the best.                        \
+      */                                                                     \
+     *_new_argv++ = "bash.exe";                                              \
+                                                                             \
+     for (_argc = 0; (_new_argv[_argc] = argv[_argc]); _argc++)              \
+       ;                                                                     \
+                                                                             \
+     _new_argv;                                                              \
+  })                                                                         \
+)
+
+
+#define PIPE_STDIN   0
+#define PIPE_STDOUT  1
+
+
+char tmp_file_name[2][L_tmpnam];         /*  0: pipe stdin, 1: pipe stdout.  */
+static int tmp_file_desc[2] = {-1, -1};  /*  0: pipe stdin, 1: pipe stdout.  */
+
+#define remove_tmp_file(name)                                                \
+(__gnuc_extension__                                                          \
+  ({                                                                         \
+     if ((name))                                                             \
+       unlink((name));                                                       \
+     else                                                                    \
+     {                                                                       \
+       if (tmp_file_name[PIPE_STDIN][0])                                     \
+       {                                                                     \
+         if (tmp_file_desc[PIPE_STDIN] > -1)                                 \
+           close(tmp_file_desc[PIPE_STDIN]);                                 \
+         unlink(tmp_file_name[PIPE_STDIN]);                                  \
+         tmp_file_name[PIPE_STDIN][0] = '\0';                                \
+         tmp_file_desc[PIPE_STDIN] = -1;                                     \
+       }                                                                     \
+       if (tmp_file_name[PIPE_STDOUT][0])                                    \
+       {                                                                     \
+         if (tmp_file_desc[PIPE_STDOUT] > -1)                                \
+         {                                                                   \
+           fsync(tmp_file_desc[PIPE_STDOUT]);                                \
+           close(tmp_file_desc[PIPE_STDOUT]);                                \
+         }                                                                   \
+         unlink(tmp_file_name[PIPE_STDOUT]);                                 \
+         tmp_file_name[PIPE_STDOUT][0] = '\0';                               \
+         tmp_file_desc[PIPE_STDOUT] = -1;                                    \
+       }                                                                     \
+     }                                                                       \
+  })                                                                         \
+)
+
+
+/* Duplicates a file handle, making the copy uninheritable.
+   Returns -1 for a file handle that is equivalent to closed.  */
+static int
+dup_noinherit(int fd)
+{
+  fd = dup_cloexec(fd);
+  if (fd < 0 && errno == EMFILE)
+    error(EXIT_FAILURE, errno, _("fcntl failed"));
+
+  return fd;
+}
+
+/* Returns a file descriptor equivalent to FD, except that the resulting file
+   descriptor is none of STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO.
+   FD must be open and non-inheritable.  The result will be non-inheritable as
+   well.
+   If FD < 0, FD itself is returned.  */
+static int
+fd_safer_noinherit(int fd)
+{
+  if (STDIN_FILENO <= fd && fd <= STDERR_FILENO)
+  {
+    /* The recursion depth is at most 3.  */
+    int nfd = fd_safer_noinherit(dup_noinherit(fd));
+    int saved_errno = errno;
+    close(fd);
+    errno = saved_errno;
+    return nfd;
+  }
+  return fd;
+}
+
+/* Duplicates a file handle, making the copy uninheritable and ensuring the
+   result is none of STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO.
+   Returns -1 for a file handle that is equivalent to closed.  */
+static int
+dup_safer_noinherit(int fd)
+{
+  return fd_safer_noinherit(dup_noinherit(fd));
+}
+
+/* Undoes the effect of TEMPFD = dup_safer_noinherit (ORIGFD);  */
+static void
+undup_safer_noinherit(int tempfd, int origfd)
+{
+  if (tempfd >= 0)
+  {
+    if (dup2(tempfd, origfd) < 0)
+      error(EXIT_FAILURE, errno, _("cannot restore fd %d: dup2 failed"), origfd);
+    close(tempfd);
+  }
+  else
+  {
+    /* origfd was closed or open to no handle at all.  Set it to a closed
+       state.  This is (nearly) equivalent to the original state.  */
+    close(origfd);
+  }
+}
+
+#ifdef _SPAWN_PIPE_H
+static int
+djgpp_pipe(int pipe_fd[2], int pipe_end)
+{
+  int fd;
+
+  strcpy(tmp_file_name[pipe_end], "/dev/env/TMPDIR/"PROGRAM_NAME_TEMPLATE);
+  if ((fd = mkstemp(tmp_file_name[pipe_end])) < 0)
+  {
+    strcpy(tmp_file_name[pipe_end], "/dev/env/TMP/"PROGRAM_NAME_TEMPLATE);
+    if ((fd = mkstemp(tmp_file_name[pipe_end])) < 0)
+    {
+      strcpy(tmp_file_name[pipe_end], "/dev/env/TEMP/"PROGRAM_NAME_TEMPLATE);
+      if ((fd = mkstemp(tmp_file_name[pipe_end])) < 0)
+        return -1;
+    }
+  }
+
+  if (pipe_end == PIPE_STDIN)
+  {
+    pipe_fd[PIPE_STDIN] = tmp_file_desc[PIPE_STDIN] = fd;
+    pipe_fd[PIPE_STDOUT] = -1;
+    tmp_file_name[PIPE_STDOUT][0] = '\0';
+  }
+  else if (pipe_end == PIPE_STDOUT)
+  {
+    pipe_fd[PIPE_STDOUT] = tmp_file_desc[PIPE_STDOUT] = fd;
+    pipe_fd[PIPE_STDIN] = -1;
+    tmp_file_name[PIPE_STDIN][0] = '\0';
+  }
+
+  return 0;
+}
+#endif
diff -aprNU5 m4-1.4.19.orig/lib/execute.c m4-1.4.19/lib/execute.c
--- m4-1.4.19.orig/lib/execute.c	2021-04-22 20:28:46 +0000
+++ m4-1.4.19/lib/execute.c	2022-09-10 10:58:20 +0000
@@ -64,10 +64,16 @@
 #  include <io.h>
 # endif
 # include <process.h>
 # include "windows-spawn.h"
 
+#elif defined __DJGPP__
+
+/* DJGPP API.  */
+# include <process.h>
+# include "djgpp-spawn.h"
+
 #else
 
 /* Unix API.  */
 # include <spawn.h>
 
@@ -245,10 +251,102 @@ execute (const char *progname,
       goto fail_with_saved_errno;
     }
 
   return exitcode;
 
+#elif defined __DJGPP__
+
+  int orig_stdin = -1;
+  int orig_stdout = -1;
+  int orig_stderr = -1;
+  int exitcode;
+  int nullinfd;
+  int nulloutfd;
+
+  /* Add an element upfront that can be used when argv[0] turns out to be a
+     script, not a program.  */
+  char **new_prog_argv = prepare_spawn (prog_argv);
+
+  /* Save standard file handles of parent process.  */
+  if (null_stdin)
+    orig_stdin = dup_safer_noinherit (STDIN_FILENO);
+  if (null_stdout)
+    orig_stdout = dup_safer_noinherit (STDOUT_FILENO);
+  if (null_stderr)
+    orig_stderr = dup_safer_noinherit (STDERR_FILENO);
+  exitcode = -1;
+
+  /* Create standard file handles of child process.  */
+  nullinfd = -1;
+  nulloutfd = -1;
+  if ((!null_stdin
+       || ((nullinfd = open ("/dev/null", O_RDONLY | O_BINARY, 0)) >= 0
+           && (nullinfd == STDIN_FILENO
+               || (dup2 (nullinfd, STDIN_FILENO) >= 0
+                   && close (nullinfd) >= 0))))
+      && (!(null_stdout || null_stderr)
+          || ((nulloutfd = open ("/dev/null", O_RDWR | O_BINARY, 0)) >= 0
+              && (!null_stdout
+                  || nulloutfd == STDOUT_FILENO
+                  || dup2 (nulloutfd, STDOUT_FILENO) >= 0)
+              && (!null_stderr
+                  || nulloutfd == STDERR_FILENO
+                  || dup2 (nulloutfd, STDERR_FILENO) >= 0)
+              && ((null_stdout && nulloutfd == STDOUT_FILENO)
+                  || (null_stderr && nulloutfd == STDERR_FILENO)
+                  || close (nulloutfd) >= 0))))
+    /* Use spawnvpe and pass the environment explicitly.  This is needed if
+       the program has modified the environment using putenv() or [un]setenv().
+       On Windows, programs have two environments, one in the "environment
+       block" of the process and managed through SetEnvironmentVariable(), and
+       one inside the process, in the location retrieved by the 'environ'
+       macro.  When using spawnvp() without 'e', the child process inherits a
+       copy of the environment block - ignoring the effects of putenv() and
+       [un]setenv().  */
+    {
+#if 0
+      exitcode = spawnvpe (P_WAIT, prog_path, new_prog_argv, environ);
+#else
+      /* Ignore prog_path.  It is an absolute path that will reflect
+         the constellation of the system used to build the m4 program.  */
+      exitcode = spawnvpe (P_WAIT, new_prog_argv[-1], new_prog_argv, environ);
+#endif
+      if (--new_prog_argv, exitcode < 0 && errno == ENOEXEC)
+        {
+          /* prog is not an native executable.  Try to execute it as a
+             shell script.  Note that prepare_spawn() has already prepended
+             a hidden element "bash.exe" to new_prog_argv.  */
+          exitcode = spawnvpe (P_WAIT, new_prog_argv[0], new_prog_argv, environ);
+        }
+      free (new_prog_argv);
+    }
+  if (nulloutfd >= 0)
+    close (nulloutfd);
+  if (nullinfd >= 0)
+    close (nullinfd);
+
+  /* Restore standard file handles of parent process.  */
+  if (null_stderr)
+    undup_safer_noinherit (orig_stderr, STDERR_FILENO);
+  if (null_stdout)
+    undup_safer_noinherit (orig_stdout, STDOUT_FILENO);
+  if (null_stdin)
+    undup_safer_noinherit (orig_stdin, STDIN_FILENO);
+
+  if (termsigp != NULL)
+    *termsigp = 0;
+
+  if (exitcode == -1)
+    {
+      if (exit_on_error || !null_stderr)
+        error (exit_on_error ? EXIT_FAILURE : 0, errno,
+               _("%s subprocess failed"), progname);
+      return 127;
+    }
+
+  return exitcode;
+
 #else
 
   /* Unix API.  */
   /* Note about 127: Some errors during posix_spawnp() cause the function
      posix_spawnp() to return an error code; some other errors cause the
diff -aprNU5 m4-1.4.19.orig/lib/fatal-signal.c m4-1.4.19/lib/fatal-signal.c
--- m4-1.4.19.orig/lib/fatal-signal.c	2021-04-22 20:28:46 +0000
+++ m4-1.4.19/lib/fatal-signal.c	2022-09-10 10:58:20 +0000
@@ -128,10 +128,18 @@ static actions_entry_t static_actions[32
 static actions_entry_t * volatile actions = static_actions;
 static sig_atomic_t volatile actions_count = 0;
 static size_t actions_allocated = SIZEOF (static_actions);
 
 
+#if __DJGPP__
+/* The saved signal handlers.
+   Size 32 would not be sufficient: On DJGPP, signals start at SIGABRT = 288 and go until SIGUSR2 = 300.
+   Make it fit into the given size of 64  */
+# define SIGNAL_INDEX(signal)  ((signal) % 288)
+#else
+# define SIGNAL_INDEX(signal)  (signal)
+#endif
 /* The saved signal handlers.
    Size 32 would not be sufficient: On HP-UX, SIGXCPU = 33, SIGXFSZ = 34.  */
 static struct sigaction saved_sigactions[64];
 
 
@@ -143,13 +151,13 @@ uninstall_handlers (void)
 
   for (i = 0; i < num_fatal_signals; i++)
     if (fatal_signals[i] >= 0)
       {
         int sig = fatal_signals[i];
-        if (saved_sigactions[sig].sa_handler == SIG_IGN)
-          saved_sigactions[sig].sa_handler = SIG_DFL;
-        sigaction (sig, &saved_sigactions[sig], NULL);
+        if (saved_sigactions[SIGNAL_INDEX(sig)].sa_handler == SIG_IGN)
+          saved_sigactions[SIGNAL_INDEX(sig)].sa_handler = SIG_DFL;
+        sigaction (sig, &saved_sigactions[SIGNAL_INDEX(sig)], NULL);
       }
 }
 
 
 /* The signal handler.  It gets called asynchronously.  */
@@ -196,13 +204,13 @@ install_handlers (void)
   for (i = 0; i < num_fatal_signals; i++)
     if (fatal_signals[i] >= 0)
       {
         int sig = fatal_signals[i];
 
-        if (!(sig < sizeof (saved_sigactions) / sizeof (saved_sigactions[0])))
+        if (!(SIGNAL_INDEX(sig) < sizeof (saved_sigactions) / sizeof (saved_sigactions[0])))
           abort ();
-        sigaction (sig, &action, &saved_sigactions[sig]);
+        sigaction (sig, &action, &saved_sigactions[SIGNAL_INDEX(sig)]);
       }
 }
 
 
 /* Lock that makes at_fatal_signal multi-thread safe.  */
diff -aprNU5 m4-1.4.19.orig/lib/fflush.c m4-1.4.19/lib/fflush.c
--- m4-1.4.19.orig/lib/fflush.c	2021-04-22 20:28:46 +0000
+++ m4-1.4.19/lib/fflush.c	2022-09-10 10:58:20 +0000
@@ -126,10 +126,14 @@ update_fpos_cache (FILE *fp _GL_UNUSED_P
 /* Flush all pending data on STREAM according to POSIX rules.  Both
    output and seekable input streams are supported.  */
 int
 rpl_fflush (FILE *stream)
 {
+#ifdef __DJGPP__
+  return fflush (stream);
+#endif
+
   /* When stream is NULL, POSIX and C99 only require flushing of "output
      streams and update streams in which the most recent operation was not
      input", and all implementations do this.
 
      When stream is "an output stream or an update stream in which the most
diff -aprNU5 m4-1.4.19.orig/lib/fopen.c m4-1.4.19/lib/fopen.c
--- m4-1.4.19.orig/lib/fopen.c	2021-04-22 20:28:46 +0000
+++ m4-1.4.19/lib/fopen.c	2022-09-10 10:58:20 +0000
@@ -19,10 +19,13 @@
 /* If the user's config.h happens to include <stdio.h>, let it include only
    the system's <stdio.h> here, so that orig_fopen doesn't recurse to
    rpl_fopen.  */
 #define _GL_ALREADY_INCLUDING_STDIO_H
 #include <config.h>
+#ifndef ISSLASH
+# include "filename.h"
+#endif
 
 /* Get the original definition of fopen.  It might be defined as a macro.  */
 #include <stdio.h>
 #undef _GL_ALREADY_INCLUDING_STDIO_H
 
@@ -162,11 +165,11 @@ rpl_fopen (const char *filename, const c
      says that it fails with errno = EISDIR in this case.
      If the named file does not exist or does not name a directory, then
      fopen() must fail since the file does not contain a '.' directory.  */
   {
     size_t len = strlen (filename);
-    if (len > 0 && filename[len - 1] == '/')
+    if (len > 0 && ISSLASH (filename[len - 1]))
       {
         int fd;
         struct stat statbuf;
         FILE *fp;
 
diff -aprNU5 m4-1.4.19.orig/lib/getprogname.c m4-1.4.19/lib/getprogname.c
--- m4-1.4.19.orig/lib/getprogname.c	2021-05-26 13:37:26 +0000
+++ m4-1.4.19/lib/getprogname.c	2022-09-10 10:58:20 +0000
@@ -55,10 +55,14 @@
 # include <fcntl.h>
 # include <stdlib.h>
 # include <string.h>
 #endif
 
+#ifdef __DJGPP__
+# include <crt0.h>
+#endif
+
 #include "basename-lgpl.h"
 
 #ifndef HAVE_GETPROGNAME             /* not Mac OS X, FreeBSD, NetBSD, OpenBSD >= 5.4, Cygwin */
 char const *
 getprogname (void)
@@ -285,10 +289,12 @@ getprogname (void)
             }
         }
       close (fd);
     }
   return "?";
+# elif __DJGPP__
+  return last_component (__crt0_argv ? __crt0_argv[0] : __dos_argv0);
 # else
 #  error "getprogname module not ported to this OS"
 # endif
 }
 
diff -aprNU5 m4-1.4.19.orig/lib/open.c m4-1.4.19/lib/open.c
--- m4-1.4.19.orig/lib/open.c	2021-04-22 20:28:46 +0000
+++ m4-1.4.19/lib/open.c	2022-09-10 10:58:20 +0000
@@ -19,10 +19,13 @@
 /* If the user's config.h happens to include <fcntl.h>, let it include only
    the system's <fcntl.h> here, so that orig_open doesn't recurse to
    rpl_open.  */
 #define __need_system_fcntl_h
 #include <config.h>
+#ifndef ISSLASH
+# include "filename.h"
+#endif
 
 /* Get the original definition of open.  It might be defined as a macro.  */
 #include <fcntl.h>
 #include <sys/types.h>
 #undef __need_system_fcntl_h
@@ -117,11 +120,11 @@ open (const char *filename, int flags, .
   if ((flags & O_CREAT)
       || (flags & O_ACCMODE) == O_RDWR
       || (flags & O_ACCMODE) == O_WRONLY)
     {
       size_t len = strlen (filename);
-      if (len > 0 && filename[len - 1] == '/')
+      if (len > 0 && ISSLASH (filename[len - 1]))
         {
           errno = EISDIR;
           return -1;
         }
     }
@@ -184,11 +187,11 @@ open (const char *filename, int flags, .
      with ENOTDIR.  */
   if (fd >= 0)
     {
       /* We know len is positive, since open did not fail with ENOENT.  */
       size_t len = strlen (filename);
-      if (filename[len - 1] == '/')
+      if (ISSLASH (filename[len - 1]))
         {
           struct stat statbuf;
 
           if (fstat (fd, &statbuf) >= 0 && !S_ISDIR (statbuf.st_mode))
             {
diff -aprNU5 m4-1.4.19.orig/lib/progname.c m4-1.4.19/lib/progname.c
--- m4-1.4.19.orig/lib/progname.c	2021-04-22 20:28:46 +0000
+++ m4-1.4.19/lib/progname.c	2022-09-10 10:58:20 +0000
@@ -25,10 +25,39 @@
 #include <errno.h> /* get program_invocation_name declaration */
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
+/* MS-DOS and similar non-Posix systems have some peculiarities:
+    - they use both `/' and `\\' as directory separator in file names;
+    - they can have a drive letter X: prepended to a file name;
+   These are all parameterized here.  */
+
+#ifdef MSDOS
+# include <libc/unconst.h>
+# undef  IS_SLASH
+# define IS_SLASH(c)  ((c) == '/' || (c) == '\\' || (c) == ':')
+# define GET_LAST_SLASH(filename)              \
+  (__gnuc_extension__                          \
+    ({                                         \
+      char *_slash = NULL;                     \
+      if ((filename))                          \
+      {                                        \
+        _slash = unconst((filename), char *);  \
+        while (*_slash++)                      \
+          ;                                    \
+        while ((--_slash - (filename)))        \
+          if (IS_SLASH(*_slash))               \
+            break;                             \
+      }                                        \
+      _slash;                                  \
+    })                                         \
+  )
+#else
+# define GET_LAST_SLASH(filename)  (strrchr((filename), '/'))
+#endif
+
 
 /* String containing name the program is called with.
    To be initialized by main().  */
 const char *program_name = NULL;
 
@@ -54,13 +83,21 @@ set_program_name (const char *argv0)
       fputs ("A NULL argv[0] was passed through an exec system call.\n",
              stderr);
       abort ();
     }
 
-  slash = strrchr (argv0, '/');
+  slash = GET_LAST_SLASH (argv0);
   base = (slash != NULL ? slash + 1 : argv0);
-  if (base - argv0 >= 7 && strncmp (base - 7, "/.libs/", 7) == 0)
+  if (base - argv0 >= 7 && (strncmp (base - 7, "/.libs/", 7) == 0
+#ifdef MSDOS
+     || strncmp (base - 7, "\\.libs/", 7) == 0
+     || strncmp (base - 7, "\\.libs\\", 7) == 0
+     || strncmp (base - 7, "/_libs/", 7) == 0
+     || strncmp (base - 7, "\\_libs/", 7) == 0
+     || strncmp (base - 7, "\\_libs\\", 7) == 0
+#endif
+     ))
     {
       argv0 = base;
       if (strncmp (base, "lt-", 3) == 0)
         {
           argv0 = base + 3;
diff -aprNU5 m4-1.4.19.orig/lib/secure_getenv.c m4-1.4.19/lib/secure_getenv.c
--- m4-1.4.19.orig/lib/secure_getenv.c	2021-04-01 20:30:12 +0000
+++ m4-1.4.19/lib/secure_getenv.c	2022-09-10 10:58:20 +0000
@@ -20,10 +20,15 @@
 #include <stdlib.h>
 
 #if !HAVE___SECURE_GETENV
 # if HAVE_ISSETUGID || (HAVE_GETUID && HAVE_GETEUID && HAVE_GETGID && HAVE_GETEGID)
 #  include <unistd.h>
+# else
+#  ifdef __DJGPP__
+#   undef issetugid
+#   define issetugid() 0
+#  endif
 # endif
 #endif
 
 char *
 secure_getenv (char const *name)
diff -aprNU5 m4-1.4.19.orig/lib/spawn-pipe.c m4-1.4.19/lib/spawn-pipe.c
--- m4-1.4.19.orig/lib/spawn-pipe.c	2021-04-22 20:28:46 +0000
+++ m4-1.4.19/lib/spawn-pipe.c	2022-09-10 10:58:20 +0000
@@ -72,10 +72,16 @@
 
 /* OS/2 kLIBC API.  */
 # include <process.h>
 # include "os2-spawn.h"
 
+#elif defined __DJGPP__
+
+/* DJGPP API.  */
+# include <process.h>
+# include "djgpp-spawn.h"
+
 #else
 
 /* Unix API.  */
 # include <spawn.h>
 
@@ -439,10 +445,149 @@ create_pipe (const char *progname,
     fd[0] = ifd[0];
   if (pipe_stdin)
     fd[1] = ofd[1];
   return child;
 
+#elif defined  __DJGPP__
+
+  /* DJGPP API.  */
+  int ifd[2];
+  int ofd[2];
+  int orig_stdin = -1;
+  int orig_stdout = -1;
+  int orig_stderr = -1;
+  int child;
+  int nulloutfd;
+  int stdinfd;
+  int stdoutfd;
+  saved_errno = 0;
+
+  /* Add an element upfront that can be used when argv[0] turns out to be a
+     script, not a program.  */
+  char **new_prog_argv = prepare_spawn (prog_argv);
+
+  if (pipe_stdout)
+    if (djgpp_pipe (ifd, PIPE_STDOUT) < 0)
+      error (EXIT_FAILURE, errno, _("cannot create pipe"));
+  if (pipe_stdin)
+    if (djgpp_pipe (ofd, PIPE_STDIN) < 0)
+      error (EXIT_FAILURE, errno, _("cannot create pipe"));
+/* Data flow diagram:
+ *
+ *           write        system         read
+ *    parent  ->   ofd[1]   ->   ofd[0]   ->   child       if pipe_stdin
+ *    parent  <-   ifd[0]   <-   ifd[1]   <-   child       if pipe_stdout
+ *           read         system         write
+ *
+ */
+
+  /* Save standard file handles of parent process.  */
+  if (pipe_stdin || prog_stdin != NULL)
+    orig_stdin = dup_safer_noinherit (STDIN_FILENO);
+  if (pipe_stdout || prog_stdout != NULL)
+    orig_stdout = dup_safer_noinherit (STDOUT_FILENO);
+  if (null_stderr)
+    orig_stderr = dup_safer_noinherit (STDERR_FILENO);
+  child = -1;
+
+  /* Create standard file handles of child process.  */
+  nulloutfd = -1;
+  stdinfd = -1;
+  stdoutfd = -1;
+  if ((!pipe_stdin || dup2 (ofd[0], STDIN_FILENO) >= 0)
+      && (!pipe_stdout || dup2 (ifd[1], STDOUT_FILENO) >= 0)
+      && (!null_stderr
+	  || ((nulloutfd = open ("/dev/null", O_RDWR, 0)) >= 0
+	      && (nulloutfd == STDERR_FILENO
+		  || (dup2 (nulloutfd, STDERR_FILENO) >= 0
+		      && close (nulloutfd) >= 0))))
+      && (pipe_stdin
+	  || prog_stdin == NULL
+	  || ((stdinfd = open (prog_stdin, O_RDONLY, 0)) >= 0
+	      && (stdinfd == STDIN_FILENO
+		  || (dup2 (stdinfd, STDIN_FILENO) >= 0
+		      && close (stdinfd) >= 0))))
+      && (pipe_stdout
+	  || prog_stdout == NULL
+	  || ((stdoutfd = open (prog_stdout, O_WRONLY, 0)) >= 0
+	      && (stdoutfd == STDOUT_FILENO
+		  || (dup2 (stdoutfd, STDOUT_FILENO) >= 0
+		      && close (stdoutfd) >= 0)))))
+    /* The child process doesn't inherit ifd[0], ifd[1], ofd[0], ofd[1],
+       but it inherits all open()ed or dup2()ed file handles (which is what
+       we want in the case of STD*_FILENO) and also orig_stdin,
+       orig_stdout, orig_stderr (which is not explicitly wanted but
+       harmless).  */
+    /* Use spawnvpe and pass the environment explicitly.  This is needed if
+       the program has modified the environment using putenv() or [un]setenv().
+       On Windows, programs have two environments, one in the "environment
+       block" of the process and managed through SetEnvironmentVariable(), and
+       one inside the process, in the location retrieved by the 'environ'
+       macro.  When using spawnvp() without 'e', the child process inherits a
+       copy of the environment block - ignoring the effects of putenv() and
+       [un]setenv().  */
+    {
+#if 0
+      child = spawnvpe (P_WAIT, prog_path, (char * const *) prog_argv, environ);
+      if (child < 0 && errno == ENOEXEC)
+	{
+	  /* prog is not an native executable.  Try to execute it as a
+	     shell script.  Note that prepare_spawn() has already prepended
+	     a hidden element "sh.exe" to prog_argv.  */
+	  --prog_argv;
+	  child = spawnvpe (P_WAIT, prog_argv[0], (char * const *) prog_argv, environ);
+	}
+#else
+      /* Ignore prog_path.  It is an absolute path that will reflect
+         the constellation of the system used to build the m4 program.  */
+      child = spawnvpe (P_WAIT, new_prog_argv[-1], new_prog_argv, environ);
+      if (--new_prog_argv, child < 0 && errno == ENOEXEC)
+	{
+	  /* prog is not an native executable.  Try to execute it as a
+	     shell script.  Note that prepare_spawn() has already prepended
+	     a hidden element "bash.exe" to new_prog_argv.  */
+          child = spawnvpe (P_WAIT, new_prog_argv[0], new_prog_argv, environ);
+	}
+#endif
+      free (new_prog_argv);
+    }
+  if (child == -1)
+    saved_errno = errno;
+  if (stdinfd >= 0)
+    close (stdinfd);
+  if (stdoutfd >= 0)
+    close (stdoutfd);
+  if (nulloutfd >= 0)
+    close (nulloutfd);
+
+  /* Restore standard file handles of parent process.  */
+  if (null_stderr)
+    dup2 (orig_stderr, STDERR_FILENO), close (orig_stderr);
+  if (pipe_stdout || prog_stdout != NULL)
+    dup2 (orig_stdout, STDOUT_FILENO), close (orig_stdout);
+  if (pipe_stdin || prog_stdin != NULL)
+    dup2 (orig_stdin, STDIN_FILENO), close (orig_stdin);
+
+  if (pipe_stdin)
+    close (ofd[0]);
+  if (pipe_stdout)
+    close (ifd[1]);
+  if (child == -1)
+    {
+      if (exit_on_error || !null_stderr)
+	error (exit_on_error ? EXIT_FAILURE : 0, errno,
+	       _("%s subprocess failed"), progname);
+      errno = saved_errno;
+      return -1;
+    }
+
+  if (pipe_stdout)
+    fd[0] = tmp_file_desc[PIPE_STDOUT] = open (tmp_file_name[PIPE_STDOUT], O_RDONLY, S_IRUSR);
+  if (pipe_stdin)
+    fd[1] = tmp_file_desc[PIPE_STDIN] = open (tmp_file_name[PIPE_STDIN], O_WRONLY | O_CREAT | O_TRUNC, S_IWUSR);
+  return child;
+
 #else
 
   /* Unix API.  */
   int ifd[2];
   int ofd[2];
diff -aprNU5 m4-1.4.19.orig/lib/spawni.c m4-1.4.19/lib/spawni.c
--- m4-1.4.19.orig/lib/spawni.c	2021-04-22 20:28:46 +0000
+++ m4-1.4.19/lib/spawni.c	2022-09-10 10:58:20 +0000
@@ -713,10 +713,23 @@ __spawni (pid_t *pid, const char *prog_f
   free (command);
   free (argv_mem_to_free);
   return errno;
 }
 
+#elif defined __DJGPP__
+
+/* MSDOS/DJGPP API.  */
+int
+__spawni (pid_t *pid, const char *file,
+	  const posix_spawn_file_actions_t *file_actions,
+	  const posix_spawnattr_t *attrp, const char *const argv[],
+	  const char *const envp[], int use_path)
+{
+  /* Not yet implemented.  */
+  return ENOSYS;
+}
+
 #else
 
 
 /* Spawn a new process executing PATH with the attributes describes in *ATTRP.
    Before running the process perform the actions described in FILE-ACTIONS. */
diff -aprNU5 m4-1.4.19.orig/lib/stdio-impl.h m4-1.4.19/lib/stdio-impl.h
--- m4-1.4.19.orig/lib/stdio-impl.h	2021-04-22 20:28:46 +0000
+++ m4-1.4.19/lib/stdio-impl.h	2022-09-10 10:58:20 +0000
@@ -33,10 +33,12 @@
 /* BSD stdio derived implementations.  */
 
 #if defined __NetBSD__                         /* NetBSD */
 /* Get __NetBSD_Version__.  */
 # include <sys/param.h>
+#elif defined __DJGPP__
+# include <libc/file.h>
 #endif
 
 #include <errno.h>                             /* For detecting Plan9.  */
 
 #if defined __sferror || defined __DragonFly__ || defined __ANDROID__
diff -aprNU5 m4-1.4.19.orig/lib/tempname.c m4-1.4.19/lib/tempname.c
--- m4-1.4.19.orig/lib/tempname.c	2021-04-01 20:30:12 +0000
+++ m4-1.4.19/lib/tempname.c	2022-09-10 10:58:20 +0000
@@ -52,10 +52,25 @@
 #include <stdint.h>
 #include <sys/random.h>
 #include <sys/stat.h>
 #include <time.h>
 
+#ifdef MSDOS
+# define HAVE_DIFFERENT_TMPDIR    1
+# if HAVE_UNISTD_H
+#  define HAVE_LFN_SUPPORT(name)  ((pathconf((name), _PC_NAME_MAX) > 12) ? true : false)
+# else
+#  define HAVE_LFN_SUPPORT(name)  (false)
+# endif
+# ifdef __DJGPP__
+#  include <libc/unconst.h>
+# endif
+#else
+# define HAVE_DIFFERENT_TMPDIR    0
+# define HAVE_LFN_SUPPORT(name)   (true)
+#endif
+
 #if _LIBC
 # define struct_stat64 struct stat64
 # define __secure_getenv __libc_secure_getenv
 #else
 # define struct_stat64 struct stat
@@ -130,39 +145,57 @@ __path_search (char *tmpl, size_t tmpl_l
   if (try_tmpdir)
     {
       d = __secure_getenv ("TMPDIR");
       if (d != NULL && direxists (d))
         dir = d;
+#if HAVE_DIFFERENT_TMPDIR
+      else if ((d = __secure_getenv ("TMP")) && direxists (d))
+	dir = d;
+      else if ((d = __secure_getenv ("TEMP")) && direxists (d))
+	dir = d;
+#endif
       else if (dir != NULL && direxists (dir))
         /* nothing */ ;
       else
         dir = NULL;
     }
   if (dir == NULL)
     {
       if (direxists (P_tmpdir))
         dir = P_tmpdir;
+#if HAVE_DIFFERENT_TMPDIR
+      else if (strcmp (P_tmpdir, ".") != 0 && direxists ("."))
+	dir = "./";
+#else
       else if (strcmp (P_tmpdir, "/tmp") != 0 && direxists ("/tmp"))
         dir = "/tmp";
+#endif
       else
         {
           __set_errno (ENOENT);
           return -1;
         }
     }
 
   dlen = strlen (dir);
-  while (dlen > 1 && dir[dlen - 1] == '/')
+  while (dlen > 1 && ISSLASH (dir[dlen - 1]))
     dlen--;                     /* remove trailing slashes */
 
   /* check we have room for "${dir}/${pfx}XXXXXX\0" */
   if (tmpl_len < dlen + 1 + plen + 6 + 1)
     {
       __set_errno (EINVAL);
       return -1;
     }
 
+  if (!HAVE_LFN_SUPPORT(dir))
+  {
+#ifdef __DJGPP__
+    char *prefix = unconst(pfx, char *);
+    prefix[2] = '\0';
+#endif
+  }
   sprintf (tmpl, "%.*s/%.*sXXXXXX", (int) dlen, dir, (int) plen, pfx);
   return 0;
 }
 #endif /* _LIBC */
 
diff -aprNU5 m4-1.4.19.orig/lib/tmpdir.c m4-1.4.19/lib/tmpdir.c
--- m4-1.4.19.orig/lib/tmpdir.c	2021-04-22 20:28:46 +0000
+++ m4-1.4.19/lib/tmpdir.c	2022-09-10 10:58:20 +0000
@@ -67,13 +67,24 @@
    ISSLASH(C)           tests whether C is a directory separator character.
  */
 #if defined _WIN32 || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__
   /* Native Windows, Cygwin, OS/2, DOS */
 # define ISSLASH(C) ((C) == '/' || (C) == '\\')
+# define HAVE_DIFFERENT_TMPDIR    1
+# if HAVE_UNISTD_H
+#  define HAVE_LFN_SUPPORT(name)  ((pathconf((name), _PC_NAME_MAX) > 12) ? true : false)
+# else
+#  define HAVE_LFN_SUPPORT(name)  (false)
+# endif
+# ifdef __DJGPP__
+#  include <libc/unconst.h>
+# endif
 #else
   /* Unix */
 # define ISSLASH(C) ((C) == '/')
+# define HAVE_DIFFERENT_TMPDIR    0
+# define HAVE_LFN_SUPPORT(name)   (true)
 #endif
 
 
 /* Return nonzero if DIR is an existent directory.  */
 static bool
@@ -112,10 +123,16 @@ path_search (char *tmpl, size_t tmpl_len
   if (try_tmpdir)
     {
       d = __libc_secure_getenv ("TMPDIR");
       if (d != NULL && direxists (d))
         dir = d;
+#if HAVE_DIFFERENT_TMPDIR
+      else if ((d = __libc_secure_getenv ("TMP")) && direxists (d))
+	dir = d;
+      else if ((d = __libc_secure_getenv ("TEMP")) && direxists (d))
+	dir = d;
+#endif
       else if (dir != NULL && direxists (dir))
         /* nothing */ ;
       else
         dir = NULL;
     }
@@ -134,12 +151,17 @@ path_search (char *tmpl, size_t tmpl_len
         dir = dirbuf;
       else
 #endif
       if (direxists (P_tmpdir))
         dir = P_tmpdir;
+#if HAVE_DIFFERENT_TMPDIR
+      else if (strcmp (P_tmpdir, ".") != 0 && direxists ("."))
+	dir = "./";
+#else
       else if (strcmp (P_tmpdir, "/tmp") != 0 && direxists ("/tmp"))
         dir = "/tmp";
+#endif
       else
         {
           __set_errno (ENOENT);
           return -1;
         }
@@ -157,9 +179,16 @@ path_search (char *tmpl, size_t tmpl_len
     {
       __set_errno (EINVAL);
       return -1;
     }
 
+  if (!HAVE_LFN_SUPPORT(dir))
+  {
+#ifdef __DJGPP__
+    char *prefix = unconst(pfx, char *);
+    prefix[2] = '\0';
+#endif
+  }
   memcpy (tmpl, dir, dlen);
   sprintf (tmpl + dlen, &"/%.*sXXXXXX"[!add_slash], (int) plen, pfx);
   return 0;
 }
diff -aprNU5 m4-1.4.19.orig/lib/wait-process.c m4-1.4.19/lib/wait-process.c
--- m4-1.4.19.orig/lib/wait-process.c	2021-04-22 20:28:46 +0000
+++ m4-1.4.19/lib/wait-process.c	2022-09-10 10:58:20 +0000
@@ -46,10 +46,14 @@
 
 /* The return value of _spawnvp() is really a process handle as returned
    by CreateProcess().  Therefore we can kill it using TerminateProcess.  */
 # define kill(pid,sig) TerminateProcess ((HANDLE) (pid), sig)
 
+#elif defined __DJGPP__
+
+# include "djgpp-spawn.h"
+
 #endif
 
 
 /* Type of an entry in the slaves array.
    The 'used' bit determines whether this entry is currently in use.
@@ -300,10 +304,25 @@ wait_subprocess (pid_t child, const char
   int status;
 
   if (termsigp != NULL)
     *termsigp = 0;
   status = 0;
+# ifdef __DJGPP__
+  /* Child process already finished.  */
+
+  remove_tmp_file(NULL);
+  if (child == -1)
+    {
+      if (exit_on_error || !null_stderr)
+        error (exit_on_error ? EXIT_FAILURE : 0, errno,
+               _("%s subprocess failed"), progname);
+      return 127;
+    }
+
+  return WEXITSTATUS (child);
+
+# else
   for (;;)
     {
       int result = waitpid (child, &status, 0);
 
       if (result != child)
@@ -364,7 +383,8 @@ wait_subprocess (pid_t child, const char
         error (exit_on_error ? EXIT_FAILURE : 0, 0,
                _("%s subprocess failed"), progname);
       return 127;
     }
   return WEXITSTATUS (status);
+# endif
 #endif
 }
diff -aprNU5 m4-1.4.19.orig/src/builtin.c m4-1.4.19/src/builtin.c
--- m4-1.4.19.orig/src/builtin.c	2021-05-10 21:33:22 +0000
+++ m4-1.4.19/src/builtin.c	2022-09-10 10:58:20 +0000
@@ -160,11 +160,17 @@ static predefined const predefined_tab[]
   { "windows",  "__windows__",  "" },
 #endif
 #if OS2
   { "os2",      "__os2__",      "" },
 #endif
-#if !UNIX && !W32_NATIVE && !OS2
+#if DOSISH
+  { "msdos",	"__msdos__",	"" },
+#if __DJGPP__
+  { "djgpp",	"__djgpp__",	"" },
+#endif
+#endif
+#if !UNIX && !W32_NATIVE && !OS2 && !DOSISH
 # warning Platform macro not provided
 #endif
   { NULL,       "__gnu__",      "" },
 
   { NULL,       NULL,           NULL },
@@ -961,10 +967,26 @@ m4_syscmd (struct obstack *obs MAYBE_UNU
     {
       prog_args[0] = "cmd";
       prog_args[1] = "/c";
     }
 #endif
+#if DOSISH
+# if 0  //__DJGPP__
+  /* prepare_spawn() prepends bash.exe anyway.  */
+  if (strstr (SYSCMD_SHELL, "bash"))
+    {
+      prog_args[0] = "bash";
+      prog_args[1] = "-c";
+    }
+  else
+# endif /* !__DJGPP__ */
+  if (strstr (SYSCMD_SHELL, "command"))
+    {
+      prog_args[0] = "command";
+      prog_args[1] = "/c";
+    }
+#endif
   prog_args[2] = cmd;
   errno = 0;
   status = execute (ARG (0), SYSCMD_SHELL, prog_args, NULL, false,
                     false, false, false, true, false, &sig_status);
   if (sig_status)
@@ -1004,10 +1026,26 @@ m4_esyscmd (struct obstack *obs, int arg
     {
       prog_args[0] = "cmd";
       prog_args[1] = "/c";
     }
 #endif
+#if DOSISH
+# if 0  //__DJGPP__
+  /* prepare_spawn() prepends bash.exe anyway.  */
+  if (strstr (SYSCMD_SHELL, "bash"))
+    {
+      prog_args[0] = "bash";
+      prog_args[1] = "-c";
+    }
+  else
+# endif /* __DJGPP__ */
+  if (strstr (SYSCMD_SHELL, "command"))
+    {
+      prog_args[0] = "command";
+      prog_args[1] = "/c";
+    }
+#endif
   prog_args[2] = cmd;
   errno = 0;
   child = create_pipe_in (ARG (0), SYSCMD_SHELL, prog_args, NULL,
                           NULL, false, true, false, &fd);
   if (child == -1)
diff -aprNU5 m4-1.4.19.orig/src/m4.c m4-1.4.19/src/m4.c
--- m4-1.4.19.orig/src/m4.c	2021-05-12 14:01:58 +0000
+++ m4-1.4.19/src/m4.c	2022-09-10 10:58:20 +0000
@@ -289,15 +289,26 @@ FLAGS is any of:\n\
   q   quote values as necessary, with a or e flag\n\
   t   trace for all macro calls, not only traceon'ed\n\
   x   add a unique macro call id, useful with c flag\n\
   V   shorthand for all of the above flags\n\
 "), stdout);
+#if __DJGPP__
+      puts ("");
+      fputs ("\
+\n\
+If defined, the environment variable `M4PATH' is either a colon-separated\n\
+or semicolon-separated (default) list of directories included after any\n\
+specified by `-I'.  The value of the environment variable `PATH_SEPARATOR'\n\
+determinates which one of the characters will be used.\n\
+", stdout);
+#else
       puts ("");
       fputs (_("\
 If defined, the environment variable `M4PATH' is a colon-separated list\n\
 of directories included after any specified by `-I'.\n\
 "), stdout);
+#endif
       puts ("");
       fputs (_("\
 Exit status is 0 for success, 1 for failure, 63 for frozen file version\n\
 mismatch, or whatever value was passed to the m4exit macro.\n\
 "), stdout);
@@ -415,10 +426,11 @@ main (int argc, char *const *argv)
   const char *frozen_file_to_read = NULL;
   const char *frozen_file_to_write = NULL;
   const char *macro_sequence = "";
 
   set_program_name (argv[0]);
+  STRIP_FULL_PATH_AND_EXTENSION (argv[0]);
   retcode = EXIT_SUCCESS;
   setlocale (LC_ALL, "");
   bindtextdomain (PACKAGE, LOCALEDIR);
   textdomain (PACKAGE);
   atexit (close_stdin);
diff -aprNU5 m4-1.4.19.orig/src/m4.h m4-1.4.19/src/m4.h
--- m4-1.4.19.orig/src/m4.h	2021-05-07 21:42:02 +0000
+++ m4-1.4.19/src/m4.h	2022-09-10 10:58:20 +0000
@@ -73,10 +73,71 @@
 #ifdef __EMX__
 # define OS2 1
 # undef UNIX
 #endif
 
+/* Canonicalize MSDOS/DJGPP recognition macro.  */
+#ifdef MSDOS
+# define DOSISH 1
+# ifdef __DJGPP__
+#  undef UNIX
+#  define UNIX 1
+#  define FILE_SYSTEM_ACCEPTS_DRIVE_LETTER_PREFIX
+# endif
+#endif
+
+/* MS-DOS and similar non-Posix systems have some peculiarities:
+    - directories in environment variables (like PATH) are separated
+        by `;' rather than `:';
+   This is parameterized here.  */
+
+#ifdef FILE_SYSTEM_ACCEPTS_DRIVE_LETTER_PREFIX
+
+# include <libc/unconst.h>
+# undef  IS_SLASH
+# define IS_SLASH(c)             ((c) == '/' || (c) == '\\' || (c) == ':')
+# undef  IS_DIR_SEPARATOR
+# define IS_DIR_SEPARATOR(c)     (IS_SLASH(c) || (c) == ':')
+# define HAVE_LFN_SUPPORT(name)  ((pathconf((name), _PC_NAME_MAX) > 12) ? true : false)
+
+# define STRIP_FULL_PATH_AND_EXTENSION(file_name)     \
+  (__gnuc_extension__                                 \
+    ({                                                \
+       char *_dst, *_src;                             \
+       _dst = _src = unconst((file_name), char *);    \
+       while (*_src++)                                \
+         ;                                            \
+       while ((_src - _dst) && (*--_src != '.'))      \
+         ;                                            \
+       for (*_src = '\0'; (_src - _dst); _src--)      \
+         if (IS_DIR_SEPARATOR(*_src))                 \
+           break;                                     \
+       if (_src - _dst)                               \
+         while ((*_dst++ = *++_src))                  \
+           ;                                          \
+       (file_name);                                   \
+    })                                                \
+  )
+# define CANONICALIZE_PATH(path)                      \
+  (__gnuc_extension__                                 \
+    ({                                                \
+       if ((path))                                    \
+       {                                              \
+         char *_p = unconst((path), char *);          \
+         for (; *_p; _p++)                            \
+           if (*_p == '\\')                           \
+             *_p = '/';                               \
+       }                                              \
+       (path);                                        \
+    })                                                \
+  )
+#else  /* not DOS/Windows like, i.e., Unix */
+# define HAVE_LFN_SUPPORT(name)                    (true)      /* NO OP */
+# define STRIP_FULL_PATH_AND_EXTENSION(filename)   (filename)  /* NO OP */
+# define CANONICALIZE_PATH(path)                               /* NO OP */
+#endif /* not FILE_SYSTEM_ACCEPTS_DRIVE_LETTER_PREFIX */
+
 /* Used if any programmer error is detected (not possible, right?)  */
 #define EXIT_INTERNAL_ERROR 2
 
 /* Used for version mismatch, when -R detects a frozen file it can't parse.  */
 #define EXIT_MISMATCH 63
diff -aprNU5 m4-1.4.19.orig/src/output.c m4-1.4.19/src/output.c
--- m4-1.4.19.orig/src/output.c	2021-05-10 21:30:00 +0000
+++ m4-1.4.19/src/output.c	2022-09-10 10:58:20 +0000
@@ -189,11 +189,11 @@ m4_tmpname (int divnum)
 {
   static char *buffer;
   static char *tail;
   if (buffer == NULL)
     {
-      tail = xasprintf ("%s/m4-%d", output_temp_dir->dir_name, INT_MAX);
+      tail = xasprintf (HAVE_LFN_SUPPORT(output_temp_dir->dir_name) ? "%s/m4-%d" : "%s/%d.m4", output_temp_dir->dir_name, INT_MAX);
       buffer = (char *) obstack_copy0 (&diversion_storage, tail,
                                        strlen (tail));
       free (tail);
       tail = strrchr (buffer, '-') + 1;
     }
@@ -462,10 +462,11 @@ make_room_for (int length)
       selected_buffer = selected_diversion->u.buffer;
       total_buffer_size -= selected_diversion->size;
       selected_diversion->size = 0;
       selected_diversion->u.file = NULL;
       selected_diversion->u.file = m4_tmpfile (selected_diversion->divnum);
+      SET_BINARY (fileno (selected_diversion->u.file));
 
       if (selected_diversion->used > 0)
         {
           count = fwrite (selected_buffer, (size_t) selected_diversion->used,
                           1, selected_diversion->u.file);
diff -aprNU5 m4-1.4.19.orig/src/path.c m4-1.4.19/src/path.c
--- m4-1.4.19.orig/src/path.c	2021-05-07 21:42:02 +0000
+++ m4-1.4.19/src/path.c	2022-09-10 10:58:20 +0000
@@ -50,10 +50,16 @@ void
 include_env_init (void)
 {
   char *path;
   char *path_end;
   char *env_path;
+  char path_sep = ':';
+#ifdef FILE_SYSTEM_ACCEPTS_DRIVE_LETTER_PREFIX
+  char *sep_char = getenv ("PATH_SEPARATOR");
+
+  path_sep = sep_char ? *sep_char :  ';';
+#endif
 
   if (no_gnu_extensions)
     return;
 
   env_path = getenv ("M4PATH");
@@ -63,13 +69,14 @@ include_env_init (void)
   env_path = xstrdup (env_path);
   path = env_path;
 
   do
     {
-      path_end = strchr (path, ':');
+      path_end = strchr (path, path_sep);
       if (path_end)
         *path_end = '\0';
+      CANONICALIZE_PATH (path);
       add_include_directory (path);
       path = path_end + 1;
     }
   while (path_end);
   free (env_path);






2022-09-03  Juan Manuel Guerrero  <juan.guerrero@gmx.de>

	* tests/inet_pton.c (inet_pton): Perform check only if AF_INET is defined.

	* tests/test-accept.c (main): Perform check only if AF_INET is defined.

	* tests/test-bind.c (main): Perform check only if AF_INET is defined.

	* tests/test-connect.c (main): Perform check only if AF_INET is defined.

	* tests/test-listen.c (main): Perform check only if AF_INET is defined.

	* tests/test-setsockopt.c (main): Perform check only if SOL_SOCKET and
	SO_REUSEADDR are defined.

	* tests/test-sys_stat.c (main): Exclude S_ISUID, S_ISGID and S_ISWID.

	* tests/test-sys_socket.c (main): Perform check only if HAVE_SHUTDOWN is
	defined.

	* tests/zerosize-ptr.h [__DJGPP__]: DJGPP does not provide neither mmap()
	nor mprotect().

	* tests/test-select.h [AF_INET]: Perform check only if AF_INET is defined.











diff -aprNU5 m4-1.4.19.orig/tests/inet_pton.c m4-1.4.19/tests/inet_pton.c
--- m4-1.4.19.orig/tests/inet_pton.c	2021-04-22 20:28:46 +0000
+++ m4-1.4.19/tests/inet_pton.c	2022-09-04 03:04:18 +0000
@@ -81,12 +81,14 @@ static int inet_pton6 (const char *src,
 int
 inet_pton (int af, const char *restrict src, void *restrict dst)
 {
   switch (af)
     {
+# if defined(AF_INET)
     case AF_INET:
       return (inet_pton4 (src, dst));
+# endif
 
 # if HAVE_IPV6
     case AF_INET6:
       return (inet_pton6 (src, dst));
 # endif
diff -aprNU5 m4-1.4.19.orig/tests/test-accept.c m4-1.4.19/tests/test-accept.c
--- m4-1.4.19.orig/tests/test-accept.c	2021-04-22 20:28:46 +0000
+++ m4-1.4.19/tests/test-accept.c	2022-09-04 03:04:18 +0000
@@ -17,12 +17,13 @@
 #include <config.h>
 
 #include <sys/socket.h>
 
 #include "signature.h"
+#if defined(AF_INET)
 SIGNATURE_CHECK (accept, int, (int, struct sockaddr *, socklen_t *));
-
+#endif
 #include <errno.h>
 #include <netinet/in.h>
 #include <unistd.h>
 
 #include "sockets.h"
@@ -31,10 +32,11 @@ SIGNATURE_CHECK (accept, int, (int, stru
 int
 main (void)
 {
   (void) gl_sockets_startup (SOCKETS_1_1);
 
+#if defined(AF_INET)
   /* Test behaviour for invalid file descriptors.  */
   {
     struct sockaddr_in addr;
     socklen_t addrlen = sizeof (addr);
 
@@ -49,8 +51,8 @@ main (void)
     close (99);
     errno = 0;
     ASSERT (accept (99, (struct sockaddr *) &addr, &addrlen) == -1);
     ASSERT (errno == EBADF);
   }
-
+#endif
   return 0;
 }
diff -aprNU5 m4-1.4.19.orig/tests/test-bind.c m4-1.4.19/tests/test-bind.c
--- m4-1.4.19.orig/tests/test-bind.c	2021-04-22 20:28:46 +0000
+++ m4-1.4.19/tests/test-bind.c	2022-09-04 03:04:18 +0000
@@ -17,11 +17,13 @@
 #include <config.h>
 
 #include <sys/socket.h>
 
 #include "signature.h"
+#if defined(AF_INET)
 SIGNATURE_CHECK (bind, int, (int, const struct sockaddr *, socklen_t));
+#endif
 
 #include <errno.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <unistd.h>
@@ -31,11 +33,11 @@ SIGNATURE_CHECK (bind, int, (int, const
 
 int
 main (void)
 {
   (void) gl_sockets_startup (SOCKETS_1_1);
-
+#if defined(AF_INET)
   /* Test behaviour for invalid file descriptors.  */
   {
     struct sockaddr_in addr;
 
     addr.sin_family = AF_INET;
@@ -51,8 +53,8 @@ main (void)
       errno = 0;
       ASSERT (bind (99, (const struct sockaddr *) &addr, sizeof (addr)) == -1);
       ASSERT (errno == EBADF);
     }
   }
-
+#endif
   return 0;
 }
diff -aprNU5 m4-1.4.19.orig/tests/test-connect.c m4-1.4.19/tests/test-connect.c
--- m4-1.4.19.orig/tests/test-connect.c	2021-04-22 20:28:46 +0000
+++ m4-1.4.19/tests/test-connect.c	2022-09-04 03:04:18 +0000
@@ -17,12 +17,13 @@
 #include <config.h>
 
 #include <sys/socket.h>
 
 #include "signature.h"
+#if defined(AF_INET)
 SIGNATURE_CHECK (connect, int, (int, const struct sockaddr *, socklen_t));
-
+#endif
 #include <errno.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <unistd.h>
 
@@ -31,11 +32,11 @@ SIGNATURE_CHECK (connect, int, (int, con
 
 int
 main (void)
 {
   (void) gl_sockets_startup (SOCKETS_1_1);
-
+#if defined(AF_INET)
   /* Test behaviour for invalid file descriptors.  */
   {
     struct sockaddr_in addr;
 
     addr.sin_family = AF_INET;
@@ -53,8 +54,8 @@ main (void)
       ASSERT (connect (99, (const struct sockaddr *) &addr, sizeof (addr))
               == -1);
       ASSERT (errno == EBADF);
     }
   }
-
+#endif
   return 0;
 }
diff -aprNU5 m4-1.4.19.orig/tests/test-listen.c m4-1.4.19/tests/test-listen.c
--- m4-1.4.19.orig/tests/test-listen.c	2021-04-22 20:28:46 +0000
+++ m4-1.4.19/tests/test-listen.c	2022-09-04 03:04:18 +0000
@@ -17,23 +17,24 @@
 #include <config.h>
 
 #include <sys/socket.h>
 
 #include "signature.h"
+#if 0
 SIGNATURE_CHECK (listen, int, (int, int));
-
+#endif
 #include <errno.h>
 #include <unistd.h>
 
 #include "sockets.h"
 #include "macros.h"
 
 int
 main (void)
 {
   (void) gl_sockets_startup (SOCKETS_1_1);
-
+#if 0
   /* Test behaviour for invalid file descriptors.  */
   {
     errno = 0;
     ASSERT (listen (-1, 1) == -1);
     ASSERT (errno == EBADF);
@@ -42,8 +43,8 @@ main (void)
     close (99);
     errno = 0;
     ASSERT (listen (99 ,1) == -1);
     ASSERT (errno == EBADF);
   }
-
+#endif
   return 0;
 }
diff -aprNU5 m4-1.4.19.orig/tests/test-nanosleep.c m4-1.4.19/tests/test-nanosleep.c
--- m4-1.4.19.orig/tests/test-nanosleep.c	2021-04-22 20:28:46 +0000
+++ m4-1.4.19/tests/test-nanosleep.c	2022-09-04 03:05:34 +0000
@@ -40,11 +40,11 @@ handle_alarm (int sig)
 
 int
 main (void)
 {
   struct timespec ts;
-
+#if !defined(__DJGPP__)
   ts.tv_sec = 1000;
   ts.tv_nsec = -1;
   errno = 0;
   ASSERT (nanosleep (&ts, NULL) == -1);
   ASSERT (errno == EINVAL);
@@ -76,8 +76,9 @@ main (void)
     ASSERT (errno == EINTR);
     ASSERT (pentecost - 10 < ts.tv_sec && ts.tv_sec <= pentecost);
     ASSERT (0 <= ts.tv_nsec && ts.tv_nsec <= 999999999);
   }
 #endif
+#endif
 
   return 0;
 }
diff -aprNU5 m4-1.4.19.orig/tests/test-select.h m4-1.4.19/tests/test-select.h
--- m4-1.4.19.orig/tests/test-select.h	2021-04-22 20:28:46 +0000
+++ m4-1.4.19/tests/test-select.h	2022-09-04 03:04:18 +0000
@@ -74,10 +74,11 @@ test (void (*fn) (select_fn), select_fn
 /* Funny socket code.  */
 
 static int
 open_server_socket (void)
 {
+#if defined(AF_INET)
   int s, x;
   struct sockaddr_in ia;
 
   s = socket (AF_INET, SOCK_STREAM, 0);
 
@@ -99,15 +100,19 @@ open_server_socket (void)
       perror ("listen");
       exit (77);
     }
 
   return s;
+#else
+  return 0;
+#endif
 }
 
 static int
 connect_to_socket (bool blocking)
 {
+#if defined(AF_INET)
   int s;
   struct sockaddr_in ia;
 
   s = socket (AF_INET, SOCK_STREAM, 0);
 
@@ -136,10 +141,13 @@ connect_to_socket (bool blocking)
       perror ("connect");
       exit (77);
     }
 
   return s;
+#else
+  return 0;
+#endif
 }
 
 
 /* A slightly more convenient interface to select(2).
    Waits until a specific event occurs on a file descriptor FD.
@@ -316,10 +324,11 @@ test_bad_fd (select_fn my_select)
 /* Test select(2) for unconnected nonblocking sockets.  */
 
 static void
 test_connect_first (select_fn my_select)
 {
+#if defined(AF_INET)
   int s = open_server_socket ();
   struct sockaddr_in ia;
   socklen_t addrlen;
 
   int c1, c2;
@@ -337,19 +346,21 @@ test_connect_first (select_fn my_select)
   addrlen = sizeof (ia);
   c2 = accept (s, (struct sockaddr *) &ia, &addrlen);
   ASSERT (close (s) == 0);
   ASSERT (close (c1) == 0);
   ASSERT (close (c2) == 0);
+#endif
 }
 
 
 /* Test select(2) for unconnected blocking sockets.  */
 
 static void
 test_accept_first (select_fn my_select)
 {
 #ifndef WINDOWS_NATIVE
+#if defined(AF_INET)
   int s = open_server_socket ();
   struct sockaddr_in ia;
   socklen_t addrlen;
   char buf[3];
   int c, pid;
@@ -382,10 +393,11 @@ test_accept_first (select_fn my_select)
       ASSERT (read (c, buf, 3) == 3);
       ASSERT (write (c, "foo", 3) == 3);
       (void) close (c); /* may fail with errno = ECONNRESET */
     }
 #endif
+#endif
 }
 
 
 /* Common code for pipes and connected sockets.  */
 
@@ -411,10 +423,11 @@ test_pair (int rd, int wd, select_fn my_
 /* Test select(2) on connected sockets.  */
 
 static void
 test_socket_pair (select_fn my_select)
 {
+#if defined(AF_INET)
   struct sockaddr_in ia;
 
   socklen_t addrlen = sizeof (ia);
   int s = open_server_socket ();
   int c1 = connect_to_socket (false);
@@ -424,10 +437,11 @@ test_socket_pair (select_fn my_select)
 
   test_pair (c1, c2, my_select);
   ASSERT (close (c1) == 0);
   ASSERT (write (c2, "foo", 3) == 3);
   (void) close (c2); /* may fail with errno = ECONNRESET */
+#endif
 }
 
 
 /* Test select(2) on pipes.  */
 
diff -aprNU5 m4-1.4.19.orig/tests/test-setsockopt.c m4-1.4.19/tests/test-setsockopt.c
--- m4-1.4.19.orig/tests/test-setsockopt.c	2021-04-22 20:28:46 +0000
+++ m4-1.4.19/tests/test-setsockopt.c	2022-09-04 03:04:18 +0000
@@ -17,23 +17,24 @@
 #include <config.h>
 
 #include <sys/socket.h>
 
 #include "signature.h"
+#if defined(SOL_SOCKET) && defined(SO_REUSEADDR)
 SIGNATURE_CHECK (setsockopt, int, (int, int, int, const void *, socklen_t));
-
+#endif
 #include <errno.h>
 #include <unistd.h>
 
 #include "sockets.h"
 #include "macros.h"
 
 int
 main (void)
 {
   (void) gl_sockets_startup (SOCKETS_1_1);
-
+#if defined(SOL_SOCKET) && defined(SO_REUSEADDR)
   /* Test behaviour for invalid file descriptors.  */
   {
     int value = 1;
 
     errno = 0;
@@ -48,8 +49,8 @@ main (void)
     errno = 0;
     ASSERT (setsockopt (99, SOL_SOCKET, SO_REUSEADDR, &value, sizeof (value))
             == -1);
     ASSERT (errno == EBADF);
   }
-
+#endif
   return 0;
 }
diff -aprNU5 m4-1.4.19.orig/tests/test-sys_socket.c m4-1.4.19/tests/test-sys_socket.c
--- m4-1.4.19.orig/tests/test-sys_socket.c	2021-04-22 20:28:46 +0000
+++ m4-1.4.19/tests/test-sys_socket.c	2022-09-04 03:04:18 +0000
@@ -25,10 +25,11 @@
 #if HAVE_SHUTDOWN
 /* Check some integer constant expressions.  */
 int a[] = { SHUT_RD, SHUT_WR, SHUT_RDWR };
 #endif
 
+#if HAVE_SHUTDOWN
 /* Check that the 'socklen_t' type is defined.  */
 socklen_t t1;
 
 /* Check that the 'size_t' and 'ssize_t' types are defined.  */
 size_t t2;
@@ -37,14 +38,16 @@ ssize_t t3;
 /* Check that 'struct iovec' is defined.  */
 struct iovec io;
 
 /* Check that a minimal set of 'struct msghdr' is defined.  */
 struct msghdr msg;
+#endif
 
 int
 main (void)
 {
+#if HAVE_SHUTDOWN
   struct sockaddr_storage x;
   sa_family_t i;
 
   /* Check some errno values.  */
   switch (ENOTSOCK)
@@ -63,6 +66,9 @@ main (void)
   i = 42;
   msg.msg_iov = &io;
 
   return (x.ss_family - i + msg.msg_namelen + msg.msg_iov->iov_len
           + msg.msg_iovlen);
+#else
+  return 0;
+#endif
 }
diff -aprNU5 m4-1.4.19.orig/tests/test-sys_stat.c m4-1.4.19/tests/test-sys_stat.c
--- m4-1.4.19.orig/tests/test-sys_stat.c	2021-04-22 20:28:46 +0000
+++ m4-1.4.19/tests/test-sys_stat.c	2022-09-04 03:04:18 +0000
@@ -314,14 +314,15 @@ verify (S_IWGRP == 00020);
 verify (S_IXGRP == 00010);
 verify (S_IRWXO == 00007);
 verify (S_IROTH == 00004);
 verify (S_IWOTH == 00002);
 verify (S_IXOTH == 00001);
+#if 0
 verify (S_ISUID == 04000);
 verify (S_ISGID == 02000);
 verify (S_ISVTX == 01000);
-
+#endif
 #if ((0 <= UTIME_NOW && UTIME_NOW < 1000000000)           \
      || (0 <= UTIME_OMIT && UTIME_OMIT < 1000000000)      \
      || UTIME_NOW == UTIME_OMIT)
 invalid UTIME macros
 #endif
diff -aprNU5 m4-1.4.19.orig/tests/zerosize-ptr.h m4-1.4.19/tests/zerosize-ptr.h
--- m4-1.4.19.orig/tests/zerosize-ptr.h	2021-04-22 20:28:46 +0000
+++ m4-1.4.19/tests/zerosize-ptr.h	2022-09-04 03:04:18 +0000
@@ -36,11 +36,11 @@
 /* Test whether mmap() and mprotect() are available.
    We don't use HAVE_MMAP, because AC_FUNC_MMAP would not define it on HP-UX.
    HAVE_MPROTECT is not enough, because mingw does not have mmap() but has an
    mprotect() function in libgcc.a.
    And OS/2 kLIBC has <sys/mman.h> and mprotect(), but not mmap().  */
-#if HAVE_SYS_MMAN_H && HAVE_MPROTECT && !defined __KLIBC__
+#if HAVE_SYS_MMAN_H && HAVE_MPROTECT && !defined __KLIBC__ && !defined __DJGPP__
 # include <fcntl.h>
 # include <unistd.h>
 # include <sys/types.h>
 # include <sys/mman.h>
 /* Define MAP_FILE when it isn't otherwise.  */
@@ -57,11 +57,11 @@
 static void *
 zerosize_ptr (void)
 {
 /* Use mmap and mprotect when they exist.  Don't test HAVE_MMAP, because it is
    not defined on HP-UX 11 (since it does not support MAP_FIXED).  */
-#if HAVE_SYS_MMAN_H && HAVE_MPROTECT && !defined __KLIBC__
+#if HAVE_SYS_MMAN_H && HAVE_MPROTECT && !defined __KLIBC__ && !defined __DJGPP__
 # if HAVE_MAP_ANONYMOUS
   const int flags = MAP_ANONYMOUS | MAP_PRIVATE;
   const int fd = -1;
 # else /* !HAVE_MAP_ANONYMOUS */
   const int flags = MAP_FILE | MAP_PRIVATE;




2023-01-26  Juan Manuel Guerrero  <juan.guerrero@gmx.de>

	* src/m4.h [FILE_SYSTEM_ACCEPTS_DRIVE_LETTER_PREFIX]: Macro
	CANONICALIZE_PATH replaces c: by /dev/c.

	* src/path.c (include_env_init): CANONICALIZE_PATH removed.
	(add_include_directory): If FILE_SYSTEM_ACCEPTS_DRIVE_LETTER_PREFIX is
	defined use CANONICALIZE_PATH to replace DOS-style backslash directory
	separator to unix-style slash directory separtor and replace "c:" by
	"/dev/c".












diff -aprNU5 m4-1.4.19.orig/src/m4.h m4-1.4.19/src/m4.h
--- m4-1.4.19.orig/src/m4.h	2023-01-26 21:48:50 +0000
+++ m4-1.4.19/src/m4.h	2023-01-26 22:05:24 +0000
@@ -92,14 +92,15 @@
 
 #ifdef FILE_SYSTEM_ACCEPTS_DRIVE_LETTER_PREFIX
 
 # include <libc/unconst.h>
 # undef  IS_SLASH
-# define IS_SLASH(c)             ((c) == '/' || (c) == '\\' || (c) == ':')
+# define IS_SLASH(c)                 ((c) == '/' || (c) == '\\' || (c) == ':')
 # undef  IS_DIR_SEPARATOR
-# define IS_DIR_SEPARATOR(c)     (IS_SLASH(c) || (c) == ':')
-# define HAVE_LFN_SUPPORT(name)  ((pathconf((name), _PC_NAME_MAX) > 12) ? true : false)
+# define IS_DIR_SEPARATOR(c)         (IS_SLASH(c) || (c) == ':')
+# define HAVE_LFN_SUPPORT(name)      ((pathconf((name), _PC_NAME_MAX) > 12) ? true : false)
+# define IS_DOS_ABSOLUTE_PATH(name)  ((name)[1] == ':' && IS_SLASH((name)[2]))
 
 # define STRIP_FULL_PATH_AND_EXTENSION(file_name)     \
   (__gnuc_extension__                                 \
     ({                                                \
        char *_dst, *_src;                             \
@@ -118,18 +119,42 @@
     })                                                \
   )
 # define CANONICALIZE_PATH(path)                      \
   (__gnuc_extension__                                 \
     ({                                                \
+       char *_path = unconst((path), char *);         \
        if ((path))                                    \
        {                                              \
-         char *_p = unconst((path), char *);          \
-         for (; *_p; _p++)                            \
-           if (*_p == '\\')                           \
-             *_p = '/';                               \
+         size_t _l_src = strlen((path));              \
+         size_t _l_dst = _l_src;                      \
+         if (!IS_DOS_ABSOLUTE_PATH((path)))           \
+           _path = xmalloc(_l_dst);                   \
+         else                                         \
+         {                                            \
+           _l_dst += 4;                               \
+           _path = xmalloc(_l_dst + 1);               \
+         }                                            \
+         for (; _l_src; _l_src--, _l_dst--)           \
+         {                                            \
+           if ((path)[_l_src] == '\\')                \
+             _path[_l_dst] = '/';                     \
+           else                                       \
+             _path[_l_dst] = (path)[_l_src];          \
+         }                                            \
+         if (!IS_DOS_ABSOLUTE_PATH((path)))           \
+           _path[_l_dst] = (path)[_l_src];            \
+         else                                         \
+         {                                            \
+           _path[5] = (path)[0];                      \
+           _path[4] = '/';                            \
+           _path[3] = 'v';                            \
+           _path[2] = 'e';                            \
+           _path[1] = 'd';                            \
+           _path[0] = '/';                            \
+         }                                            \
        }                                              \
-       (path);                                        \
+       (_path);                                       \
     })                                                \
   )
 #else  /* not DOS/Windows like, i.e., Unix */
 # define HAVE_LFN_SUPPORT(name)                    (true)      /* NO OP */
 # define STRIP_FULL_PATH_AND_EXTENSION(filename)   (filename)  /* NO OP */
diff -aprNU5 m4-1.4.19.orig/src/path.c m4-1.4.19/src/path.c
--- m4-1.4.19.orig/src/path.c	2023-01-26 21:48:50 +0000
+++ m4-1.4.19/src/path.c	2023-01-26 21:48:02 +0000
@@ -52,13 +52,13 @@ include_env_init (void)
   char *path;
   char *path_end;
   char *env_path;
   char path_sep = ':';
 #ifdef FILE_SYSTEM_ACCEPTS_DRIVE_LETTER_PREFIX
-  char *sep_char = getenv ("PATH_SEPARATOR");
+  char *sep_symbol = getenv ("PATH_SEPARATOR");
 
-  path_sep = sep_char ? *sep_char :  ';';
+  path_sep = sep_symbol ? *sep_symbol :  ';';
 #endif
 
   if (no_gnu_extensions)
     return;
 
@@ -72,11 +72,10 @@ include_env_init (void)
   do
     {
       path_end = strchr (path, path_sep);
       if (path_end)
         *path_end = '\0';
-      CANONICALIZE_PATH (path);
       add_include_directory (path);
       path = path_end + 1;
     }
   while (path_end);
   free (env_path);
@@ -93,12 +92,20 @@ add_include_directory (const char *dir)
   if (*dir == '\0')
     dir = ".";
 
   incl = (includes *) xmalloc (sizeof (struct includes));
   incl->next = NULL;
+#ifdef FILE_SYSTEM_ACCEPTS_DRIVE_LETTER_PREFIX
+  {
+    char *unixyfied_dir = CANONICALIZE_PATH (dir);
+    incl->len = strlen (unixyfied_dir);
+    incl->dir = unixyfied_dir;
+  }
+#else
   incl->len = strlen (dir);
   incl->dir = xstrdup (dir);
+#endif
 
   if (incl->len > dir_max_length) /* remember len of longest directory */
     dir_max_length = incl->len;
 
   if (dir_list_end == NULL)




2023-01-28  Juan Manuel Guerrero  <juan.guerrero@gmx.de>

	* src/freeze.c (reload_frozen_state): For systems that distinguish
	between text and binary I/O the reloading of frozen files must be
	done in O_BINARY mode if it has been created in O_BINARY mode.
	Bug reported to the m4 maintainers but still not found its way
	upstream.













diff -aprNU5 m4-1.4.19.orig/src/freeze.c m4-1.4.19/src/freeze.c
--- m4-1.4.19.orig/src/freeze.c	2021-05-10 21:33:08 +0000
+++ m4-1.4.19/src/freeze.c	2023-01-28 16:14:08 +0000
@@ -266,10 +266,11 @@ reload_frozen_state (const char *name)
   while (0)
 
   file = m4_path_search (name, NULL);
   if (file == NULL)
     m4_failure (errno, _("cannot open %s"), name);
+  SET_BINARY (fileno (file));
   current_file = name;
 
   allocated[0] = 100;
   string[0] = xcharalloc ((size_t) allocated[0]);
   allocated[1] = 100;
