m4-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: add some fd tests to head


From: Eric Blake
Subject: Re: add some fd tests to head
Date: Fri, 13 Oct 2006 22:25:10 +0000 (UTC)
User-agent: Loom/3.14 (http://gmane.org/)

Eric Blake <ebb9 <at> byu.net> writes:

> 
> 2006-10-06  Eric Blake  <ebb9 <at> byu.net>
> 
>       Replace uses of tmpfile with clean-temp, since tmpfile is
>       incompatible with closeout.

This was relatively easy to port to the branch (although it breaks mingw builds 
unless a pending patch of mine is accepted in gnulib).

2006-10-13  Eric Blake  <address@hidden>

        Backport head's usage of clean-temp module, as it is cleaner than
        using tmpfile-safer.
        * m4/gnulib-cache.m4: Augment with 'gnulib-tool --import
        clean-temp closeout', and remove tmpfile-safer.
        * src/m4.h (includes): Adjust.
        (m4_path_search): Rename from path_search, to avoid collision
        with gnulib.
        * src/m4.c (main): Install closeout handler.  Adjust caller.
        (usage): Now done by closeout module.
        * src/builtin.c (m4_m4exit): Likewise.
        (m4_undivert, include): Adjust callers.
        * src/freeze.c (reload_frozen_state): Likewise.
        * src/path.c (m4_path_search): Rename from path_search.
        * src/output.c (output_temp_dir): New variable.
        (cleanup_tmpfile, m4_tmpfile): New functions, from head.
        (insert_diversion, make_room_for): Use them.
        * doc/m4.texinfo (Diversions): Document this, and add a test.
        (Improved fatal_error): Fix typo.
        (Maketemp): Port test to mingw, and no longer hide from
        documentation.
        * NEWS: Document the change in TMPDIR behavior.


Index: NEWS
===================================================================
RCS file: /sources/m4/m4/NEWS,v
retrieving revision 1.1.1.1.2.71
diff -u -r1.1.1.1.2.71 NEWS
--- NEWS        13 Oct 2006 12:59:16 -0000      1.1.1.1.2.71
+++ NEWS        13 Oct 2006 22:20:55 -0000
@@ -22,6 +22,10 @@
   token in an included file.
 * The `builtin' and `indir' macros now transparently handle builtin
   tokens generated by `defn'.
+* When diversions created by the `divert' macro collect enough text that
+  M4 must use temporary files, the environment variable $TMPDIR is now
+  consulted, and a better effort is made to clean up those files in the
+  event of a fatal signal.
 
 Version 1.4.7 - 25 September 2006, by Eric Blake  (CVS version 1.4.6a)
 
Index: doc/m4.texinfo
===================================================================
RCS file: /sources/m4/m4/doc/m4.texinfo,v
retrieving revision 1.1.1.1.2.84
diff -u -r1.1.1.1.2.84 m4.texinfo
--- doc/m4.texinfo      13 Oct 2006 12:59:17 -0000      1.1.1.1.2.84
+++ doc/m4.texinfo      13 Oct 2006 22:20:55 -0000
@@ -3240,9 +3240,46 @@
 (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}.
 So, it is theoretically possible that the number of diversions be
 limited by the number of available file descriptors.
 
address@hidden
address@hidden We need to test spilled diversions, but don't need to expose
address@hidden this highly repetitive test in the manual.
+
address@hidden
+divert(`-1')define(`f', `.')
+define(`f', defn(`f')defn(`f'))
+define(`f', defn(`f')defn(`f'))
+define(`f', defn(`f')defn(`f'))
+define(`f', defn(`f')defn(`f'))
+define(`f', defn(`f')defn(`f'))
+define(`f', defn(`f')defn(`f'))
+define(`f', defn(`f')defn(`f'))
+define(`f', defn(`f')defn(`f'))
+define(`f', defn(`f')defn(`f'))
+define(`f', defn(`f')defn(`f'))
+define(`f', defn(`f')defn(`f'))
+define(`f', defn(`f')defn(`f'))
+define(`f', defn(`f')defn(`f'))
+define(`f', defn(`f')defn(`f'))
+define(`f', defn(`f')defn(`f'))
+define(`f', defn(`f')defn(`f'))
+define(`f', defn(`f')defn(`f'))
+define(`f', defn(`f')defn(`f'))
+define(`f', defn(`f')defn(`f'))
+define(`f', defn(`f')defn(`f'))
+divert`'dnl
+len(f)
address@hidden
+divert(`1')
+f
+divert(`-1')undivert
address@hidden example
address@hidden ignore
+
 @c FIXME: need some explanation here why this is a useful feature, not
 @c just how you use it.
 
@@ -4394,16 +4431,9 @@
 @code{maketemp}, so a future version of @acronym{GNU} M4 may have
 changes in this area.
 
address@hidden
address@hidden This test makes sure maketemp gets testsuite coverage, but is
address@hidden somewhat complex for use in the manual.
 @example
-dnl This test assumes /tmp is a valid directory name, which is not true
-dnl for native Windows.
-ifdef(`__unix__', , `errprint(` skipping: not sure /tmp exists
-')m4exit(`77')')dnl
-define(`file1', maketemp(`/tmp/fooXXXXXX'))dnl
-define(`file2', maketemp(`/tmp/fooXXXXXX'))dnl
+define(`file1', maketemp(`fooXXXXXX'))dnl
+define(`file2', maketemp(`fooXXXXXX'))dnl
 ifelse(file1, file2, `same', `different')
 @result{}different
 syscmd(`rm 'file1 file2)
@@ -4411,7 +4441,6 @@
 sysval
 @result{}0
 @end example
address@hidden ignore
 
 @node Miscellaneous
 @chapter Miscellaneous builtin macros
@@ -5189,7 +5218,7 @@
 
 @example
 define(`fatal_error',
-  `errprint(ifdef(`__program', `__program__', ``m4'')'dnl
+  `errprint(ifdef(`__program__', `__program__', ``m4'')'dnl
 `:ifelse(__line__, `0', `',
     `__file__:__line__:')` fatal error: $*
 ')m4exit(`1')')
Index: m4/gnulib-cache.m4
===================================================================
RCS file: /sources/m4/m4/m4/Attic/gnulib-cache.m4,v
retrieving revision 1.1.2.15
diff -u -r1.1.2.15 gnulib-cache.m4
--- m4/gnulib-cache.m4  7 Sep 2006 22:48:15 -0000       1.1.2.15
+++ m4/gnulib-cache.m4  13 Oct 2006 22:20:55 -0000
@@ -15,11 +15,11 @@
 
 
 # Specification in the form of a command-line invocation:
-#   gnulib-tool --import --dir=. --lib=libm4 --source-base=lib --m4-base=m4 --
doc-base=doc --aux-dir=. --no-libtool --macro-prefix=M4 binary-io cloexec close-
stream error fdl fopen-safer free gendocs getopt gnupload mkstemp obstack regex 
stdlib-safer strtol tmpfile-safer unlocked-io verror xalloc xvasprintf
+#   gnulib-tool --import --dir=. --lib=libm4 --source-base=lib --m4-base=m4 --
doc-base=doc --aux-dir=. --no-libtool --macro-prefix=M4 binary-io clean-temp 
cloexec close-stream closeout error fdl fopen-safer free gendocs getopt 
gnupload mkstemp obstack regex stdlib-safer strtol unlocked-io verror xalloc 
xvasprintf
 
 # Specification in the form of a few gnulib-tool.m4 macro invocations:
 gl_LOCAL_DIR([])
-gl_MODULES([binary-io cloexec close-stream error fdl fopen-safer free gendocs 
getopt gnupload mkstemp obstack regex stdlib-safer strtol tmpfile-safer 
unlocked-io verror xalloc xvasprintf])
+gl_MODULES([binary-io clean-temp cloexec close-stream closeout error fdl fopen-
safer free gendocs getopt gnupload mkstemp obstack regex stdlib-safer strtol 
unlocked-io verror xalloc xvasprintf])
 gl_AVOID([])
 gl_SOURCE_BASE([lib])
 gl_M4_BASE([m4])
Index: src/builtin.c
===================================================================
RCS file: /sources/m4/m4/src/Attic/builtin.c,v
retrieving revision 1.1.1.1.2.42
diff -u -r1.1.1.1.2.42 builtin.c
--- src/builtin.c       13 Oct 2006 12:59:17 -0000      1.1.1.1.2.42
+++ src/builtin.c       13 Oct 2006 22:20:55 -0000
@@ -1088,7 +1088,7 @@
                    "non-numeric argument to builtin `%s'", ARG (0)));
        else
          {
-           fp = path_search (ARG (i), NULL);
+           fp = m4_path_search (ARG (i), NULL);
            if (fp != NULL)
              {
                insert_file (fp);
@@ -1200,7 +1200,7 @@
   if (bad_argc (argv[0], argc, 2, 2))
     return;
 
-  fp = path_search (ARG (1), &name);
+  fp = m4_path_search (ARG (1), &name);
   if (fp == NULL)
     {
       if (!silent)
@@ -1329,16 +1329,11 @@
      detect any errors it might have encountered.  */
   debug_set_output (NULL);
   debug_flush_files ();
-  if (close_stream (stdout) != 0)
-    {
-      M4ERROR ((warning_status, errno, "write error"));
-      if (exit_code == 0)
-       exit_code = EXIT_FAILURE;
-    }
-  if (close_stream (stderr) != 0 && exit_code == 0)
-    exit_code = EXIT_FAILURE;
-  if (exit_code == 0 && retcode != 0)
+  if (exit_code == EXIT_SUCCESS && retcode != EXIT_SUCCESS)
     exit_code = retcode;
+  /* Propagate non-zero status to atexit handlers.  */
+  if (exit_code != EXIT_SUCCESS)
+    exit_failure = exit_code;
   exit (exit_code);
 }
 
Index: src/freeze.c
===================================================================
RCS file: /sources/m4/m4/src/freeze.c,v
retrieving revision 1.1.1.1.2.12
diff -u -r1.1.1.1.2.12 freeze.c
--- src/freeze.c        30 Jul 2006 03:18:12 -0000      1.1.1.1.2.12
+++ src/freeze.c        13 Oct 2006 22:20:55 -0000
@@ -222,7 +222,7 @@
     }                                                           \
   while (character == '\n')
 
-  file = path_search (name, NULL);
+  file = m4_path_search (name, NULL);
   if (file == NULL)
     M4ERROR ((EXIT_FAILURE, errno, "cannot open %s", name));
 
Index: src/m4.c
===================================================================
RCS file: /sources/m4/m4/src/Attic/m4.c,v
retrieving revision 1.1.1.1.2.33
diff -u -r1.1.1.1.2.33 m4.c
--- src/m4.c    10 Oct 2006 03:54:26 -0000      1.1.1.1.2.33
+++ src/m4.c    13 Oct 2006 22:20:55 -0000
@@ -204,11 +204,6 @@
 ", stdout);
       printf ("\nReport bugs to <%s>.\n", PACKAGE_BUGREPORT);
     }
-
-  if (close_stream (stdout) != 0)
-    M4ERROR ((EXIT_FAILURE, errno, "write error"));
-  if (close_stream (stderr) != 0)
-    exit (EXIT_FAILURE); /* Can't really do much else without stderr.  */
   exit (status);
 }
 
@@ -286,6 +281,7 @@
 
   program_name = argv[0];
   retcode = EXIT_SUCCESS;
+  atexit (close_stdout);
 
   include_init ();
   debug_init ();
@@ -421,20 +417,15 @@
        break;
 
       case VERSION_OPTION:
-        printf ("%s\n", PACKAGE_STRING);
-        fputs ("\
+       printf ("%s\n", PACKAGE_STRING);
+       fputs ("\
 Copyright (C) 2006 Free Software Foundation, Inc.\n\
 This is free software; see the source for copying conditions.  There is NO\n\
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
 \n\
 Written by Rene' Seindal.\n\
 ", stdout);
-
-        if (close_stream (stdout) != 0)
-          M4ERROR ((EXIT_FAILURE, errno, "write error"));
-        if (close_stream (stderr) != 0)
-          exit (EXIT_FAILURE);
-        exit (EXIT_SUCCESS);
+       exit (EXIT_SUCCESS);
        break;
 
       case HELP_OPTION:
@@ -532,7 +523,7 @@
        else
          {
            const char *name;
-           fp = path_search (argv[optind], &name);
+           fp = m4_path_search (argv[optind], &name);
            if (fp == NULL)
              {
                error (0, errno, "%s", argv[optind]);
@@ -570,10 +561,5 @@
       make_diversion (0);
       undivert_all ();
     }
-
-  if (close_stream (stdout) != 0)
-    M4ERROR ((EXIT_FAILURE, errno, "write error"));
-  if (close_stream (stderr) != 0)
-    exit (EXIT_FAILURE); /* Can't really do much else without stderr.  */
   exit (retcode);
 }
Index: src/m4.h
===================================================================
RCS file: /sources/m4/m4/src/m4.h,v
retrieving revision 1.1.1.1.2.29
diff -u -r1.1.1.1.2.29 m4.h
--- src/m4.h    7 Sep 2006 22:48:15 -0000       1.1.1.1.2.29
+++ src/m4.h    13 Oct 2006 22:20:55 -0000
@@ -49,16 +49,20 @@
 #include <sys/types.h>
 
 #include "binary-io.h"
+#include "clean-temp.h"
 #include "cloexec.h"
 #include "close-stream.h"
+#include "closeout.h"
 #include "error.h"
 #include "exit.h"
+#include "exitfail.h"
 #include "obstack.h"
 #include "stdio--.h"
 #include "stdlib--.h"
 #include "unistd--.h"
 #include "verror.h"
 #include "xalloc.h"
+#include "xvasprintf.h"
 
 /* If FALSE is defined, we presume TRUE is defined too.  In this case,
    merely typedef boolean as being int.  Or else, define these all.  */
@@ -418,7 +422,7 @@
 void include_init (void);
 void include_env_init (void);
 void add_include_directory (const char *);
-FILE *path_search (const char *, const char **);
+FILE *m4_path_search (const char *, const char **);
 
 /* File: eval.c  --- expression evaluation.  */
 
Index: src/output.c
===================================================================
RCS file: /sources/m4/m4/src/Attic/output.c,v
retrieving revision 1.1.1.1.2.10
diff -u -r1.1.1.1.2.10 output.c
--- src/output.c        18 Aug 2006 23:11:37 -0000      1.1.1.1.2.10
+++ src/output.c        13 Oct 2006 22:20:56 -0000
@@ -76,6 +76,13 @@
 
 /* Number of input line we are generating output for.  */
 int output_current_line;
+
+typedef struct temp_dir m4_temp_dir;
+
+/* Temporary directory holding all spilled diversion files.  */
+static m4_temp_dir *output_temp_dir;
+
+
 
 /*------------------------.
 | Output initialisation.  |
@@ -99,6 +106,48 @@
   output_unused = 0;
 }
 
+/* Clean up any temporary directory.  Designed for use as an atexit
+   handler, where it is not safe to call exit() recursively; so this
+   calls _exit if a problem is encountered.  */
+static void
+cleanup_tmpfile (void)
+{
+  if (cleanup_temp_dir (output_temp_dir) != 0)
+    _exit (exit_failure);
+}
+
+/* Create a temporary file open for reading and writing in a secure
+   temp directory.  The file will be automatically closed and deleted
+   on a fatal signal.  When done with the file, close it with
+   close_stream_temp.  Exits on failure, so the return value is always
+   an open file.  */
+static FILE *
+m4_tmpfile (void)
+{
+  static unsigned int count;
+  char *name;
+  FILE *file;
+
+  if (output_temp_dir == NULL)
+    {
+      errno = 0;
+      output_temp_dir = create_temp_dir ("m4-", NULL, true);
+      if (output_temp_dir == NULL)
+       M4ERROR ((EXIT_FAILURE, errno,
+                 "cannot create temporary file for diversion"));
+      atexit (cleanup_tmpfile);
+    }
+  name = xasprintf ("%s/m4-%d", output_temp_dir->dir_name, count++);
+  register_temp_file (output_temp_dir, name);
+  errno = 0;
+  file = fopen_temp (name, O_BINARY ? "wb+" : "w+");
+  if (file == NULL)
+    M4ERROR ((EXIT_FAILURE, errno,
+             "cannot create temporary file for diversion"));
+  free (name);
+  return file;
+}
+
 /*-----------------------------------------------------------------------.
 | Reorganize in-memory diversion buffers so the current diversion can   |
 | accomodate LENGTH more characters without further reorganization.  The |
@@ -154,10 +203,7 @@
       /* Create a temporary file, write the in-memory buffer of the
         diversion to this file, then release the buffer.  */
 
-      selected_diversion->file = tmpfile ();
-      if (selected_diversion->file == NULL)
-       M4ERROR ((EXIT_FAILURE, errno,
-                 "ERROR: cannot create temporary file for diversion"));
+      selected_diversion->file = m4_tmpfile ();
       if (set_cloexec_flag (fileno (selected_diversion->file), true) != 0)
        M4ERROR ((warning_status, errno,
                  "Warning: cannot protect diversion across forks"));
@@ -485,7 +531,7 @@
 
   if (diversion->file)
     {
-      fclose (diversion->file);
+      close_stream_temp (diversion->file);
       diversion->file = NULL;
     }
   else if (diversion->buffer)
Index: src/path.c
===================================================================
RCS file: /sources/m4/m4/src/Attic/path.c,v
retrieving revision 1.1.1.1.2.11
diff -u -r1.1.1.1.2.11 path.c
--- src/path.c  10 Oct 2006 11:36:40 -0000      1.1.1.1.2.11
+++ src/path.c  13 Oct 2006 22:20:56 -0000
@@ -111,7 +111,7 @@
    respect to the current working directory.  */
 
 FILE *
-path_search (const char *file, const char **result)
+m4_path_search (const char *file, const char **result)
 {
   FILE *fp;
   includes *incl;
@@ -154,7 +154,7 @@
       strcpy (name + incl->len + 1, file);
 
 #ifdef DEBUG_INCL
-      fprintf (stderr, "path_search (%s) -- trying %s\n", file, name);
+      fprintf (stderr, "m4_path_search (%s) -- trying %s\n", file, name);
 #endif
 
       fp = fopen (name, "r");






reply via email to

[Prev in Thread] Current Thread [Next in Thread]