[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
DJGPP specific patch for bison-1.875d
From: |
Juan Manuel Guerrero |
Subject: |
DJGPP specific patch for bison-1.875d |
Date: |
Tue, 07 Dec 2004 17:07:58 +0200 |
This is a proposition to port bison to non posix systems like djgpp/msdos.
There are two issues to be treated:
1) output file names
2) fork() to run m4
The first issue is handled in system.h. Using djgpp's pathconf(), the binary
will detect at runtime if long file name support is available (some sort of
win32 OS) or not (msdos/freedos, etc). Depending on the OS used, the posix
extensions (.tab and .output) will be used or the non posix ones (_tab and
.out) will be used. To achive this goal the TAB_EXT and OUTPUT_EXT have been
redefined.
The second issue can only be solved using temporary files. First bison's stdout
is redirected to a temp. file which will gather all output. This file is closed
and reopened as m4 stdin. A second temp file is opened and assigned to m4's
stdout to gather all its output. Then m4 is spawned() and after successfull
return the second temp. file is closed and reopened as bison's stdin.
This is implemented in subpipe.c. The design goal is to have as less as possible
impact in the existing code. subpipe.c has been modified in the following way:
#if HAVE_WORKING_VFORK || HAVE_WORKING_FORK
/*
* Here are all the *original* and *unaltered* posix functions:
*
* init_subpipe()
* create_subpipe()
* reap_subpipe()
*/
#else /* !HAVE_WORKING_VFORK && !HAVE_WORKING_FORK */
# if __DJGPP__
/*
* Here are all the djgpp specific versions of the posix functions:
*
* init_subpipe()
* create_subpipe()
* reap_subpipe()
*/
# else /* !__DJGPP__ */
# error "vfork, fork or an emulation is required."
# endif /* !__DJGPP__ */
#endif /* !HAVE_WORKING_VFORK and !HAVE_WORKING_FORK */
The djgpp specific versions of the posix functions: init_subpipe(),
create_subpipe() and reap_subpipe() use exactly the same arguments
and return types as the posix ones. This is to keep the impact on other
code as minimal possible. To start m4 on non posix systems the output.c
file needs the following adjustment:
#if !HAVE_WORKING_VFORK && !HAVE_WORKING_FORK
run_m4 (filter_fd);
#endif
in function output_skeleton().
The proposed patch has been tested with bison-1.875 and bison-1.875d on linux
and different types of win32 and plain dos. Because I do not know which the
appropriate cvs trunk is, I have made the patch against 1.875d. The patch is
intended for inspection. Comments, objections, suggestions are welcome.
Regards,
Juan M. Guerrero
2004-12-07 Guerrero, Juan Manuel <address@hidden>
* src/system.h [MSDOS]: __DJGPP__ conditional added. Use pathconf
to choose POSIX or DOS file extensions at run time.
* lib/subpipe.c: Use conditionals HAVE_WORKING_VFORK and
HAVE_WORKING_FORK to select the appropriate versions of the functions
init_subpipe, create_subpipe and reap_subpipe.
[HAVE_WORKING_VFORK, HAVE_WORKING_FORK] [__DJGPP__]: implementation
of DJGPP specific versions of init_subpipe, create_subpipe,
reap_subpipe and run_m4 to emulate the missing fork/pipe
functionality on MSDOS.
* src/output.c (output_skeleton) [HAVE_WORKING_VFORK,
HAVE_WORKING_FORK]: Call function run_m4 to generate parser output
file on non posix systems.
* lib/subpipe.h [HAVE_WORKING_VFORK, HAVE_WORKING_FORK]: Add run_m4
declaration on non posix systems.
diff -apruNU5 bison-1.875d.orig/lib/subpipe.c bison-1.875d/lib/subpipe.c
--- bison-1.875d.orig/lib/subpipe.c 2004-04-28 06:30:04.000000000 +0000
+++ bison-1.875d/lib/subpipe.c 2004-12-07 15:42:00.000000000 +0000
@@ -71,10 +71,12 @@
#include "gettext.h"
#define _(Msgid) gettext (Msgid)
+#if HAVE_WORKING_VFORK || HAVE_WORKING_FORK
+
/* Initialize this module. */
void
init_subpipe (void)
{
@@ -176,5 +178,250 @@ reap_subpipe (pid_t pid, char const *pro
: "subsidiary program `%s' failed (exit status %d)"),
program, status);
}
#endif
}
+#else /* !HAVE_WORKING_VFORK and !HAVE_WORKING_FORK */
+# if __DJGPP__
+/* Initialize this module. */
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <process.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include "xalloc.h"
+
+static int old_stdin;
+static int old_stdout;
+static char **arguments;
+static char tmp_file_name[2][L_tmpnam];
+
+#define remove_tmp_file(fd, name) \
+ do { \
+ close ((fd)); \
+ if (unlink ((name))) \
+ error (EXIT_FAILURE, 0, _("removing of `%s' failed"), (name)); \
+ } while (0)
+
+
+void
+init_subpipe (void)
+{
+ int fd;
+
+ strcpy (tmp_file_name[0], "/dev/env/TMPDIR/bnXXXXXX");
+ fd = mkstemp (tmp_file_name[0]);
+ if (fd < 0)
+ error (EXIT_FAILURE, 0, _("creation of tmpfile failed"));
+ close (fd);
+
+ strcpy (tmp_file_name[1], "/dev/env/TMPDIR/bnXXXXXX");
+ fd = mkstemp (tmp_file_name[1]);
+ if (fd < 0)
+ error (EXIT_FAILURE, 0, _("creation of tmpfile failed"));
+ close (fd);
+}
+
+
+/* Create a subprocess that is run as a filter. ARGV is the
+ NULL-terminated argument vector for the subprocess. Store read and
+ write file descriptors for communication with the subprocess into
+ FD[0] and FD[1]: input meant for the process can be written into
+ FD[0], and output from the process can be read from FD[1]. Return
+ the subprocess id.
+
+ Because DOS has neither fork nor pipe functionality to run the subprocess
+ as a filter, the filter is reproduced using temporary files. First bison's
+ stdout is redirected to a temp. file. After bison has produced all of is
+ output, this file is closed and connected to m4's stdin. All m4's output
+ is redirected from m4's stdout to a second temp. file and reopened as
+ bison's stdin. */
+
+pid_t
+create_subpipe (char const * const *argv, int fd[2])
+{
+ int argc;
+ int from_in_fd; /* pipe from bison to m4. */
+ pid_t pid;
+
+
+ pid = getpid ();
+
+ /*
+ * Save original stdin and stdout
+ * for later restauration.
+ */
+ old_stdin = dup (STDIN_FILENO);
+ if (old_stdin < 0)
+ error (EXIT_FAILURE, 0, _("saving stdin failed"));
+
+ old_stdout = dup (STDOUT_FILENO);
+ if (old_stdout < 0)
+ error (EXIT_FAILURE, 0, _("saving stdout failed"));
+
+ /*
+ * Save argv for later use.
+ */
+ for (argc = 0; argv[argc]; argc++)
+ ;
+ argc++;
+ arguments = xmalloc (argc * sizeof(arguments[0]));
+ for (argc = 0; argv[argc]; argc++)
+ {
+ arguments[argc] = xmalloc ((strlen (argv[argc]) + 1) *
sizeof(arguments[0][0]));
+ strcpy (arguments[argc], argv[argc]);
+ }
+ arguments[argc] = NULL;
+
+ /*
+ * All bison's output will be gathered in this temp. file
+ * and will be redirected to m4's stdin later.
+ */
+ from_in_fd = open (tmp_file_name[0], O_WRONLY | O_CREAT | O_TRUNC, S_IWUSR);
+ if (from_in_fd < 0)
+ error (EXIT_FAILURE, 0, _("opening of tmpfile failed"));
+ if (dup2 (from_in_fd, STDOUT_FILENO) < 0)
+ {
+ remove_tmp_file (from_in_fd, tmp_file_name[0]);
+ error (EXIT_FAILURE, 0, _("redirecting bison's stdout to tmpfile failed"));
+ }
+ close (from_in_fd);
+
+
+ fd[0] = STDOUT_FILENO;
+ return pid;
+}
+
+
+/* A signal handler that just records that a signal has happened. */
+static int child_interrupted;
+
+static void
+signal_catcher (int signo)
+{
+ child_interrupted++;
+}
+
+
+void
+run_m4 (int fd[2])
+{
+ char *program;
+ int from_out_fd = open (tmp_file_name[0], O_RDONLY, S_IRUSR);
/* pipe from bison to m4. */
+ int to_in_fd = open (tmp_file_name[1], O_WRONLY | O_CREAT | O_TRUNC,
S_IWUSR); /* pipe from m4 to bison. */
+ int status;
+ void (*previous_handler)(int);
+
+
+ program = strrchr (arguments[0], '/');
+ if (program)
+ program++;
+ else
+ program = arguments[0];
+
+ /*
+ * Redirect bison's output to m4's stdin.
+ */
+ if (from_out_fd < 0)
+ error (EXIT_FAILURE, 0, _("opening of tmpfile failed"));
+ if (dup2 (from_out_fd, STDIN_FILENO) < 0)
+ {
+ remove_tmp_file (from_out_fd, tmp_file_name[0]);
+ error (EXIT_FAILURE, 0, _("redirecting m4's stdin from tmpfile failed"));
+ }
+ close (from_out_fd);
+
+ /*
+ * All m4's output will be gathered in this temp. file
+ * and will be redirected to bison's stdin later.
+ */
+ if (to_in_fd < 0)
+ {
+ remove_tmp_file (STDIN_FILENO, tmp_file_name[0]);
+ error (EXIT_FAILURE, 0, _("opening of tmpfile failed"));
+ }
+ if (dup2 (to_in_fd, STDOUT_FILENO) < 0)
+ {
+ remove_tmp_file (STDIN_FILENO, tmp_file_name[0]);
+ remove_tmp_file (to_in_fd, tmp_file_name[1]);
+ error (EXIT_FAILURE, 0, _("redirecting m4's stdout to tmpfile failed"));
+ }
+ close (to_in_fd);
+
+ /*
+ * Run m4.
+ */
+ child_interrupted = 0;
+ errno = 0;
+ previous_handler = signal (SIGINT, signal_catcher);
+ status = spawnvp (P_WAIT, program, arguments);
+ signal (SIGINT, previous_handler);
+ if (child_interrupted)
+ {
+ remove_tmp_file (STDIN_FILENO, tmp_file_name[0]);
+ remove_tmp_file (STDOUT_FILENO, tmp_file_name[1]);
+ error (EXIT_FAILURE, 0, _("subsidiary program `%s' interrupted"), program);
+ }
+ if (status)
+ {
+ remove_tmp_file (STDIN_FILENO, tmp_file_name[0]);
+ remove_tmp_file (STDOUT_FILENO, tmp_file_name[1]);
+ error (EXIT_FAILURE, 0, _(errno == ENOENT
+ ? "subsidiary program `%s' not found"
+ : status < 1
+ ? "subsidiary program `%s' failed"
+ : "subsidiary program `%s' failed (status=%i,
errno=%i)"), program, status, errno);
+ }
+
+
+ /*
+ * Redirect m4's output to bison's stdin.
+ */
+ if (dup2 (old_stdout, STDOUT_FILENO) < 0)
+ error (EXIT_FAILURE, 0, "restore of bison's stdout failed");
+ close (old_stdout);
+ to_in_fd = open (tmp_file_name[1], O_RDONLY, S_IRUSR); /* pipe from m4 to
bison. */
+ if (to_in_fd < 0)
+ {
+ remove_tmp_file (STDIN_FILENO, tmp_file_name[0]);
+ error (EXIT_FAILURE, 0, _("opening of tmpfile failed"));
+ }
+ if (dup2 (to_in_fd, STDIN_FILENO) < 0)
+ {
+ remove_tmp_file (STDIN_FILENO, tmp_file_name[0]);
+ remove_tmp_file (to_in_fd, tmp_file_name[1]);
+ error (EXIT_FAILURE, -1, "dup2");
+ error (EXIT_FAILURE, 0, _("redirecting bison's stdin from tmpfile
failed"));
+ }
+ close (to_in_fd);
+
+
+ fd[1] = STDIN_FILENO;
+}
+
+
+/* Free resources, unlink temporary files and restore stdin and stdout. */
+
+void
+reap_subpipe (pid_t pid, char const *program)
+{
+ int argc;
+
+ for (argc = 0; arguments[argc]; argc++)
+ free (arguments[argc]);
+ free (arguments);
+
+ if (unlink (tmp_file_name[0]))
+ error (EXIT_FAILURE, 0, _("removing of `%s' failed"), tmp_file_name[0]);
+ if (unlink (tmp_file_name[1]))
+ error (EXIT_FAILURE, 0, _("removing of `%s' failed"), tmp_file_name[1]);
+
+ if (dup2 (old_stdin, STDIN_FILENO) < 0)
+ error (EXIT_FAILURE, 0, "restore of bison's stdin failed");
+ close (old_stdin);
+}
+# else /* !__DJGPP__ */
+# error "vfork, fork or an emulation is required."
+# endif /* !__DJGPP__ */
+#endif /* !HAVE_WORKING_VFORK and !HAVE_WORKING_FORK */
diff -apruNU5 bison-1.875d.orig/lib/subpipe.h bison-1.875d/lib/subpipe.h
--- bison-1.875d.orig/lib/subpipe.h 2004-04-28 06:30:04.000000000 +0000
+++ bison-1.875d/lib/subpipe.h 2004-12-07 14:58:34.000000000 +0000
@@ -26,5 +26,8 @@
#endif
void init_subpipe (void);
pid_t create_subpipe (char const * const *, int[2]);
void reap_subpipe (pid_t, char const *);
+#if !HAVE_WORKING_VFORK && !HAVE_WORKING_FORK
+void run_m4 (int[2]);
+#endif
diff -apruNU5 bison-1.875d.orig/src/output.c bison-1.875d/src/output.c
--- bison-1.875d.orig/src/output.c 2004-03-31 00:37:20.000000000 +0000
+++ bison-1.875d/src/output.c 2004-12-07 14:58:34.000000000 +0000
@@ -576,10 +576,15 @@ output_skeleton (void)
fputs ("m4_divert_push(0)dnl\n", out);
xfclose (out);
/* Read and process m4's output. */
timevar_push (TV_M4);
+#if !HAVE_WORKING_VFORK && !HAVE_WORKING_FORK
+ /* On non posix systems that lack vfork and fork
+ m4 must be explicitly spawned to process bison output. */
+ run_m4 (filter_fd);
+#endif
in = fdopen (filter_fd[1], "r");
if (! in)
error (EXIT_FAILURE, get_errno (), "fdopen");
scan_skel (in);
xfclose (in);
diff -apruNU5 bison-1.875d.orig/src/system.h bison-1.875d/src/system.h
--- bison-1.875d.orig/src/system.h 2004-04-28 20:00:56.000000000 +0000
+++ bison-1.875d/src/system.h 2004-12-07 14:58:34.000000000 +0000
@@ -178,12 +178,19 @@ do {
\
# define TAB_EXT "_tab"
# define OUTPUT_EXT ".output"
#else /* ! VMS */
# ifdef MSDOS
/* MS DOS. */
-# define TAB_EXT "_tab"
-# define OUTPUT_EXT ".out"
+# ifdef __DJGPP__
+ /* DJGPP. */
+# include <unistd.h>
+# define TAB_EXT ((pathconf(NULL, _PC_NAME_MAX) > 12) ? ".tab" : "_tab")
+# define OUTPUT_EXT ((pathconf(NULL, _PC_NAME_MAX) > 12) ? ".output" :
".out")
+# else /* ! __DJGPP__ */
+# define TAB_EXT "_tab"
+# define OUTPUT_EXT ".out"
+# endif /* ! __DJGPP__ */
# else /* ! MSDOS */
/* Standard. */
# define TAB_EXT ".tab"
# define OUTPUT_EXT ".output"
# endif /* ! MSDOS */
- DJGPP specific patch for bison-1.875d,
Juan Manuel Guerrero <=