From: Florian Krohm Subject: new readpipe patch (corrected) To: address@hidden Cc: address@hidden X-Sent: 22 weeks, 13 hours, 10 minutes, 12 seconds ago Please disregard the patch I sent earlier. I used an account that you cannot reply to. Sorry for that. Here it goes again. Florian ============================================================= Here is the new readpipe patch. It incorporates Paul's suggestions and eliminates the temporary file by running m4 as a filter. I will be ging on vacation this Friday and will be out of touch for three weeks. If the patch needs adjustment, please let me know soon so I can fix it before I leave. Otherwise, it will have to wait until I'm back. Florian ================= begin new file readpipe.h ======================= /* Copyright (C) 2002 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef READPIPE_H # define READPIPE_H 1 # if HAVE_CONFIG_H # include # endif # if HAVE_UNISTD_H # include # include # else # define pid_t int # endif # ifndef PARAMS # if defined PROTOTYPES || (defined __STDC__ && __STDC__) # define PARAMS(proto) proto # else # define PARAMS(proto) () # endif # endif pid_t open_filter PARAMS ((const char **argv, int *from, int *to)); #endif /* !READPIPE_H */ ================= end new file readpipe.h ======================= Index: bison/ChangeLog =================================================================== RCS file: /cvsroot/bison/bison/ChangeLog,v retrieving revision 1.677 diff -u -r1.677 ChangeLog --- bison/ChangeLog 7 May 2002 08:13:00 -0000 1.677 +++ bison/ChangeLog 12 May 2002 17:11:01 -0000 @@ -1,3 +1,14 @@ +2002-05-12 Florian Krohm + + * configure.in (AC_FUNC_FORK, AC_TYPE_PID): Added + * lib/readpipe.c (open_filter): New function + * lib/readpipe.h: New + * src/muscle_tab.c (muscles_m4_output): Use obstack not FILE. + * src/muscle_tab.h (muscles_m4_output): Use obstack not FILE. + * src/output.h (actions_output, token_definitions_output): Remove + * src/output.c (output_skeleton): Adapted to use open_filter. + Eliminated temporary file. Use obstacks. More trace output. + 2002-05-07 Akim Demaille * tests/synclines.at: Be sure to prototype yylex and yyerror to Index: bison/configure.in =================================================================== RCS file: /cvsroot/bison/bison/configure.in,v retrieving revision 1.64 diff -u -r1.64 configure.in --- bison/configure.in 3 May 2002 15:52:53 -0000 1.64 +++ bison/configure.in 12 May 2002 17:11:03 -0000 @@ -91,6 +91,7 @@ AC_FUNC_OBSTACK AC_FUNC_ERROR_AT_LINE AC_FUNC_STRNLEN +AC_FUNC_FORK UTILS_FUNC_MKSTEMP AC_CHECK_FUNCS(setlocale) AC_CHECK_DECLS([free, stpcpy, strchr, strspn, strnlen, @@ -101,6 +102,9 @@ jm_PREREQ_QUOTEARG jm_PREREQ_ERROR AM_WITH_DMALLOC + +# Checks for types. +AC_TYPE_PID_T # Gettext. GETTEXT_VERSION=0.11.2 Index: bison/lib/readpipe.c =================================================================== RCS file: /cvsroot/bison/bison/lib/readpipe.c,v retrieving revision 1.1 diff -u -r1.1 readpipe.c --- bison/lib/readpipe.c 5 Feb 2002 10:14:20 -0000 1.1 +++ bison/lib/readpipe.c 12 May 2002 17:11:05 -0000 @@ -1,5 +1,5 @@ -/* Open a pipe to read from a program without intermediary sh. - Copyright (C) 1992, 1997 Free Software Foundation, Inc. +/* Create a subprocess as a filter. + Copyright (C) 1992, 1997, 2002 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -15,82 +15,79 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* Written by David MacKenzie. */ - #if HAVE_CONFIG_H # include #endif -#include - -#if __STDC__ -#include -#else -#include -#endif - #if HAVE_UNISTD_H +# include # include #endif -/* Open a pipe to read from a program without intermediary sh. Checks - PATH. Sample use: +#ifndef _POSIX_VERSION +# ifndef STDIN_FILENO +# define STDIN_FILENO 0 +# endif +# ifndef STDOUT_FILENO +# define STDOUT_FILENO 1 +# endif +#endif + +#include +#include "readpipe.h" + +/* Creates a subprocess which is run as a filter. ARGV is the NULL-terminated + argument buffer for the subprocess. Upon success, the function returns the + id of the subprocess. The arguments FROM and TO will contain file handles + for communication with the subprocess. Otherwise, the function returns -1 + and errno is set appropriately. */ +pid_t +open_filter(const char **argv, int *from, int *to) +{ + int fds1[2], fds2[2]; + pid_t pid; - stream = readpipe ("progname", "arg1", "arg2", (char *) 0); +#if HAVE_WORKING_FORK || HAVE_WORKING_VFORK - Return 0 on error. */ + if (pipe (fds1) < 0 || pipe (fds2) < 0) + return -1; + + if ((pid = fork ()) < 0) + return -1; + + if (pid > 0) { + /* parent */ + close (fds1[0]); + close (fds2[1]); + + *from = fds2[0]; + *to = fds1[1]; + } else { + /* child */ + close(fds1[1]); + close(fds2[0]); + + if (fds1[0] != STDIN_FILENO) { + if (dup2(fds1[0], STDIN_FILENO) != STDIN_FILENO) + return -1; + close (fds1[0]); + } + if (fds2[1] != STDOUT_FILENO) { + if (dup2(fds2[1], STDOUT_FILENO) != STDOUT_FILENO) + return -1; + close (fds2[1]); + } + + /* The cast to (char **) is needed for portability to older + hosts with a nonstandard prototype for execvp. */ + execvp (argv[0], (char **)argv); + + _exit (errno == ENOEXEC ? 126 : 127); + } + + return pid; -#if __STDC__ -FILE * -readpipe (char *progname, ...) -#else -FILE * -readpipe (va_alist) -#endif -{ -#if ! __STDC__ - char *progname; -#endif - int fds[2]; - va_list ap; - char *args[100]; - int argno = 0; - - /* Copy arguments into `args'. */ -#if __STDC__ - va_start (ap, progname); #else - va_start (ap); - progname = va_arg (ap, char *); +#error Bison requires working fork #endif - args[argno++] = progname; - while ((args[argno++] = va_arg (ap, char *)) != NULL) - ; - va_end (ap); - - if (pipe (fds) == -1) - return 0; - - switch (fork ()) - { - case 0: /* Child. Write to pipe. */ - close (fds[0]); /* Not needed. */ - if (fds[1] != 1) /* Redirect 1 (stdout) only if needed. */ - { - close (1); /* We don't want the old stdout. */ - if (dup (fds[1]) == 0)/* Maybe stdin was closed. */ - { - dup (fds[1]); /* Guaranteed to dup to 1 (stdout). */ - close (0); - } - close (fds[1]); /* No longer needed. */ - } - execvp (args[0], args); - _exit (2); /* 2 for `cmp'. */ - case -1: /* Error. */ - return 0; - default: /* Parent. Read from pipe. */ - close (fds[1]); /* Not needed. */ - return fdopen (fds[0], "r"); - } } Index: bison/src/muscle_tab.c =================================================================== RCS file: /cvsroot/bison/bison/src/muscle_tab.c,v retrieving revision 1.16 diff -u -r1.16 muscle_tab.c --- bison/src/muscle_tab.c 6 May 2002 08:23:54 -0000 1.16 +++ bison/src/muscle_tab.c 12 May 2002 17:11:08 -0000 @@ -98,10 +98,15 @@ m4_defines. */ static int -muscle_m4_output (muscle_entry_t *entry, FILE *out) +muscle_m4_output (muscle_entry_t *entry, struct obstack *out) { - fprintf (out, "m4_define([b4_%s],\n", entry->key); - fprintf (out, " [[%s]])\n\n\n", entry->value); + obstack_fgrow1 (out, "m4_define([b4_%s],\n", entry->key); + + /* Cannot use obstack_fgrow1 here because of buffer overflow */ + obstack_sgrow (out, " [["); + obstack_sgrow (out, entry->value); + obstack_sgrow (out, "]])\n\n\n"); + return 1; } @@ -110,7 +115,7 @@ m4_defines. */ void -muscles_m4_output (FILE *out) +muscles_m4_output (struct obstack *out) { hash_do_for_each (muscle_table, (Hash_processor) muscle_m4_output, Index: bison/src/muscle_tab.h =================================================================== RCS file: /cvsroot/bison/bison/src/muscle_tab.h,v retrieving revision 1.4 diff -u -r1.4 muscle_tab.h --- bison/src/muscle_tab.h 7 Apr 2002 17:44:59 -0000 1.4 +++ bison/src/muscle_tab.h 12 May 2002 17:11:08 -0000 @@ -19,7 +19,7 @@ Boston, MA 02111-1307, USA. */ #ifndef MUSCLE_TAB_H_ -# define MUSCLE_TAB_H +# define MUSCLE_TAB_H_ # define MTABSIZE 101 @@ -63,6 +63,6 @@ } -void muscles_m4_output PARAMS ((FILE *out)); +void muscles_m4_output PARAMS ((struct obstack *out)); #endif /* not MUSCLE_TAB_H_ */ Index: bison/src/output.c =================================================================== RCS file: /cvsroot/bison/bison/src/output.c,v retrieving revision 1.154 diff -u -r1.154 output.c --- bison/src/output.c 7 May 2002 08:07:32 -0000 1.154 +++ bison/src/output.c 12 May 2002 17:11:19 -0000 @@ -103,9 +103,7 @@ #include "symtab.h" #include "conflicts.h" #include "muscle_tab.h" - -/* From lib/readpipe.h. */ -FILE *readpipe PARAMS ((const char *, ...)); +#include "readpipe.h" /* From src/scan-skel.l. */ int skel_lex PARAMS ((void)); @@ -132,6 +130,9 @@ static int lowzero; static int high; +static void actions_output (struct obstack *out); +static void token_definitions_output (struct obstack *out); + struct obstack muscle_obstack; static struct obstack format_obstack; @@ -534,26 +535,26 @@ | Output the actions to OOUT. | `-----------------------------*/ -void -actions_output (FILE *out) +static void +actions_output (struct obstack *out) { int rule; for (rule = 1; rule < nrules + 1; ++rule) if (rules[rule].action) { - fprintf (out, " case %d:\n", rule); + obstack_fgrow1 (out, " case %d:\n", rule); if (!no_lines_flag) - fprintf (out, muscle_find ("linef"), + obstack_fgrow2 (out, muscle_find ("linef"), rules[rule].action_line, quotearg_style (c_quoting_style, muscle_find ("filename"))); /* As a Bison extension, add the ending semicolon. Since some Yacc don't do that, help people using bison as a Yacc finding their missing semicolons. */ - fprintf (out, "{ %s%s }\n break;\n\n", - rules[rule].action, - yacc_flag ? ";" : ""); + obstack_fgrow2 (out, "{ %s%s }\n break;\n\n", + rules[rule].action, + yacc_flag ? ";" : ""); } } @@ -562,8 +563,8 @@ | Output the tokens definition to OOUT. | `---------------------------------------*/ -void -token_definitions_output (FILE *out) +static void +token_definitions_output (struct obstack *out) { int i; int first = 1; @@ -597,8 +598,8 @@ if (strchr (symbol->tag, '.') || strchr (symbol->tag, '$')) continue; - fprintf (out, "%s[[[%s]], [%d]]", - first ? "" : ",\n", symbol->tag, number); + obstack_fgrow3 (out, "%s[[[%s]], [%d]]", + first ? "" : ",\n", symbol->tag, number); first = 0; } @@ -949,73 +950,90 @@ /*---------------------------. | Call the skeleton parser. | `---------------------------*/ - static void output_skeleton (void) { /* Store the definition of all the muscles. */ - const char *tempdir = getenv ("TMPDIR"); - char *tempfile = NULL; - FILE *out = NULL; - int fd; - - if (tempdir == NULL) - tempdir = DEFAULT_TMPDIR; - tempfile = xmalloc (strlen (tempdir) + 11); - sprintf (tempfile, "%s/bsnXXXXXX", tempdir); - fd = mkstemp (tempfile); - if (fd == -1) - error (EXIT_FAILURE, errno, "%s", tempfile); - - out = fdopen (fd, "w"); - if (out == NULL) - error (EXIT_FAILURE, errno, "%s", tempfile); + struct obstack m4_obstack, *out = &m4_obstack; + const char *m4_buffer; + + obstack_init (out); /* There are no comments, especially not `#': we do want M4 expansion after `#': think of CPP macros! */ - fputs ("m4_changecom()\n", out); - fputs ("m4_init()\n", out); + obstack_sgrow (out, "m4_changecom()\n"); + obstack_sgrow (out, "m4_init()\n"); - fputs ("m4_define([b4_actions], \n[[", out); + obstack_sgrow (out, "m4_define([b4_actions], \n[["); actions_output (out); - fputs ("]])\n\n", out); + obstack_sgrow (out, "]])\n\n"); - fputs ("m4_define([b4_tokens], \n[", out); + obstack_sgrow (out, "m4_define([b4_tokens], \n["); token_definitions_output (out); - fputs ("])\n\n", out); + obstack_sgrow (out, "])\n\n"); muscles_m4_output (out); - fputs ("m4_wrap([m4_divert_pop(0)])\n", out); - fputs ("m4_divert_push(0)dnl\n", out); - xfclose (out); + obstack_sgrow (out, "m4_wrap([m4_divert_pop(0)])\n"); + obstack_sgrow (out, "m4_divert_push(0)dnl\n"); + obstack_1grow(out, '\0'); + + m4_buffer = obstack_finish (out); /* Invoke m4 on the definition of the muscles, and the skeleton. */ { + const char *argv[8]; + int from, to; + size_t len; + pid_t pid; const char *bison_pkgdatadir = getenv ("BISON_PKGDATADIR"); const char *m4 = getenv ("M4"); + if (!m4) m4 = M4; if (!bison_pkgdatadir) bison_pkgdatadir = PKGDATADIR; + + argv[0] = m4; + argv[1] = "-e"; /* input and output are unbuffered */ + argv[2] = "-I"; + argv[3] = bison_pkgdatadir; + argv[4] = "m4sugar/m4sugar.m4"; + argv[5] = "-"; + argv[6] = skeleton; + argv[7] = NULL; + if (trace_flag) - fprintf (stderr, - "running: %s -I %s m4sugar/m4sugar.m4 %s %s\n", - m4, bison_pkgdatadir, tempfile, skeleton); - skel_in = readpipe (m4, - "-I", bison_pkgdatadir, - "m4sugar/m4sugar.m4", - tempfile, - skeleton, - NULL); - if (!skel_in) + { + const char **p; + + fprintf (stderr, "running the following shell command:\n"); + for (p = argv; *p; ++p) { + fprintf (stderr, "%s ", *p); + } + fprintf (stderr, "<<'m4_EOF'\n"); + fprintf (stderr, "%s", m4_buffer); + fprintf (stderr, "m4_EOF\n\n"); + } + + pid = open_filter(argv, &from, &to); + if (pid < 0) error (EXIT_FAILURE, errno, "cannot run m4"); - skel_lex (); - /* If `debugging', keep this file alive. */ - if (!trace_flag) - unlink (tempfile); + len = strlen (m4_buffer); + if (write (to, m4_buffer, len) != len) + error (EXIT_FAILURE, errno, "write"); + close(to); + + skel_in = fdopen (from, "r"); + if (skel_in == NULL) + error (EXIT_FAILURE, errno, "fdopen"); + skel_lex (); + + close(from); } + + obstack_free (out, NULL); } static void @@ -1087,3 +1105,4 @@ obstack_free (&pre_prologue_obstack, NULL); obstack_free (&post_prologue_obstack, NULL); } + Index: bison/src/output.h =================================================================== RCS file: /cvsroot/bison/bison/src/output.h,v retrieving revision 1.9 diff -u -r1.9 output.h --- bison/src/output.h 2 May 2002 15:06:46 -0000 1.9 +++ bison/src/output.h 12 May 2002 17:11:19 -0000 @@ -26,9 +26,6 @@ /* Output the parsing tables and the parser code to FTABLE. */ void output PARAMS ((void)); -void actions_output PARAMS ((FILE *out)); -void token_definitions_output PARAMS ((FILE *out)); - extern struct obstack muscle_obstack; #endif /* !OUTPUT_H_ */