emacs-diffs
[Top][All Lists]
Advanced

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

[Emacs-diffs] /srv/bzr/emacs/trunk r104064: Extend `call-process' to tak


From: Lars Magne Ingebrigtsen
Subject: [Emacs-diffs] /srv/bzr/emacs/trunk r104064: Extend `call-process' to take the `(:file "file")' syntax to redirect
Date: Sun, 01 May 2011 02:04:17 +0200
User-agent: Bazaar (2.3.1)

------------------------------------------------------------
revno: 104064
committer: Lars Magne Ingebrigtsen <address@hidden>
branch nick: trunk
timestamp: Sun 2011-05-01 02:04:17 +0200
message:
  Extend `call-process' to take the `(:file "file")' syntax to redirect
  STDOUT to a file.
modified:
  doc/lispref/ChangeLog
  doc/lispref/processes.texi
  src/ChangeLog
  src/callproc.c
  src/lisp.h
  src/sysdep.c
=== modified file 'doc/lispref/ChangeLog'
--- a/doc/lispref/ChangeLog     2011-04-23 03:07:16 +0000
+++ b/doc/lispref/ChangeLog     2011-05-01 00:04:17 +0000
@@ -1,3 +1,8 @@
+2011-04-30  Lars Magne Ingebrigtsen  <address@hidden>
+
+       * processes.texi (Synchronous Processes): Document the (:file
+       "/file-name") syntax for `call-process'.
+
 2011-04-23  Juanma Barranquero  <address@hidden>
 
        * windows.texi (Choosing Window): Fix typo.

=== modified file 'doc/lispref/processes.texi'
--- a/doc/lispref/processes.texi        2011-03-05 20:45:09 +0000
+++ b/doc/lispref/processes.texi        2011-05-01 00:04:17 +0000
@@ -299,6 +299,9 @@
 MS-DOS doesn't support asynchronous subprocesses, so this option doesn't
 work there.
 
address@hidden @code{(:file @var{file-name})}
+Send the output to the file name specified.
+
 @item @code{(@var{real-destination} @var{error-destination})}
 Keep the standard output stream separate from the standard error stream;
 deal with the ordinary output as specified by @var{real-destination},

=== modified file 'src/ChangeLog'
--- a/src/ChangeLog     2011-04-30 10:31:17 +0000
+++ b/src/ChangeLog     2011-05-01 00:04:17 +0000
@@ -1,3 +1,13 @@
+2011-05-01  Lars Magne Ingebrigtsen  <address@hidden>
+
+       * sysdep.c (interruptible_wait_for_termination): New function
+       which is like wait_for_termination, but allows keyboard
+       interruptions.
+
+       * callproc.c (Fcall_process): Add (:file "file") as an option for
+       the STDOUT buffer.
+       (Fcall_process_region): Ditto.
+
 2011-04-30  Eli Zaretskii  <address@hidden>
 
        * dosfns.c (Fint86, Fdos_memget, Fdos_memput): Use `ASIZE (FOO)'

=== modified file 'src/callproc.c'
--- a/src/callproc.c    2011-04-14 19:34:42 +0000
+++ b/src/callproc.c    2011-05-01 00:04:17 +0000
@@ -156,8 +156,9 @@
        doc: /* Call PROGRAM synchronously in separate process.
 The remaining arguments are optional.
 The program's input comes from file INFILE (nil means `/dev/null').
-Insert output in BUFFER before point; t means current buffer;
- nil for BUFFER means discard it; 0 means discard and don't wait.
+Insert output in BUFFER before point; t means current buffer; nil for BUFFER
+ means discard it; 0 means discard and don't wait; and `(:file FILE)', where
+ FILE is a file name string, means that it should be written to that file.
 BUFFER can also have the form (REAL-BUFFER STDERR-FILE); in that case,
 REAL-BUFFER says what to do with standard output, as above,
 while STDERR-FILE says what to do with standard error in the child.
@@ -196,14 +197,17 @@
   /* File to use for stderr in the child.
      t means use same as standard output.  */
   Lisp_Object error_file;
+  Lisp_Object output_file = Qnil;
 #ifdef MSDOS   /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */
   char *outf, *tempfile;
   int outfilefd;
 #endif
+  int fd_output = -1;
   struct coding_system process_coding; /* coding-system of process output */
   struct coding_system argument_coding;        /* coding-system of arguments */
   /* Set to the return value of Ffind_operation_coding_system.  */
   Lisp_Object coding_systems;
+  int output_to_buffer = 1;
 
   /* Qt denotes that Ffind_operation_coding_system is not yet called.  */
   coding_systems = Qt;
@@ -273,9 +277,12 @@
     {
       buffer = args[2];
 
-      /* If BUFFER is a list, its meaning is
-        (BUFFER-FOR-STDOUT FILE-FOR-STDERR).  */
-      if (CONSP (buffer))
+      /* If BUFFER is a list, its meaning is (BUFFER-FOR-STDOUT
+        FILE-FOR-STDERR), unless the first element is :file, in which case see
+        the next paragraph. */
+      if (CONSP (buffer) &&
+         (! SYMBOLP (XCAR (buffer)) ||
+          strcmp (SSDATA (SYMBOL_NAME (XCAR (buffer))), ":file")))
        {
          if (CONSP (XCDR (buffer)))
            {
@@ -291,6 +298,17 @@
          buffer = XCAR (buffer);
        }
 
+      /* If the buffer is (still) a list, it might be a (:file "file") spec. */
+      if (CONSP (buffer) &&
+         SYMBOLP (XCAR (buffer)) &&
+         ! strcmp (SSDATA (SYMBOL_NAME (XCAR (buffer))), ":file"))
+       {
+         output_file = Fexpand_file_name (XCAR (XCDR (buffer)),
+                                          BVAR (current_buffer, directory));
+         CHECK_STRING (output_file);
+         buffer = Qnil;
+       }
+
       if (!(EQ (buffer, Qnil)
            || EQ (buffer, Qt)
            || INTEGERP (buffer)))
@@ -318,11 +336,11 @@
      protected by the caller, so all we really have to worry about is
      buffer.  */
   {
-    struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
+    struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
 
     current_dir = BVAR (current_buffer, directory);
 
-    GCPRO4 (infile, buffer, current_dir, error_file);
+    GCPRO5 (infile, buffer, current_dir, error_file, output_file);
 
     current_dir = Funhandled_file_name_directory (current_dir);
     if (NILP (current_dir))
@@ -342,6 +360,8 @@
       current_dir = ENCODE_FILE (current_dir);
     if (STRINGP (error_file) && STRING_MULTIBYTE (error_file))
       error_file = ENCODE_FILE (error_file);
+    if (STRINGP (output_file) && STRING_MULTIBYTE (output_file))
+      output_file = ENCODE_FILE (output_file);
     UNGCPRO;
   }
 
@@ -353,6 +373,26 @@
       infile = DECODE_FILE (infile);
       report_file_error ("Opening process input file", Fcons (infile, Qnil));
     }
+
+  if (STRINGP (output_file))
+    {
+#ifdef DOS_NT
+      fd_output = emacs_open (SSDATA (output_file),
+                             O_WRONLY | O_TRUNC | O_CREAT | O_TEXT,
+                             S_IREAD | S_IWRITE);
+#else  /* not DOS_NT */
+      fd_output = creat (SSDATA (output_file), 0666);
+#endif /* not DOS_NT */
+      if (fd_output < 0)
+       {
+         output_file = DECODE_FILE (output_file);
+         report_file_error ("Opening process output file",
+                            Fcons (output_file, Qnil));
+        }
+      if (STRINGP (error_file) || NILP (error_file))
+        output_to_buffer = 0;
+    }
+
   /* Search for program; barf if not found.  */
   {
     struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
@@ -413,13 +453,18 @@
   strcat (tempfile, "detmp.XXX");
   mktemp (tempfile);
 
-  outfilefd = creat (tempfile, S_IREAD | S_IWRITE);
-  if (outfilefd < 0)
+  /* If we're redirecting STDOUT to a file, this is already opened. */
+  if (fd_output < 0)
     {
-      emacs_close (filefd);
-      report_file_error ("Opening process output file",
-                        Fcons (build_string (tempfile), Qnil));
+      outfilefd = creat (tempfile, S_IREAD | S_IWRITE);
+      if (outfilefd < 0) {
+       emacs_close (filefd);
+       report_file_error ("Opening process output file",
+                          Fcons (build_string (tempfile), Qnil));
+      }
     }
+  else
+    outfilefd = fd_output;
   fd[0] = filefd;
   fd[1] = outfilefd;
 #endif /* MSDOS */
@@ -450,6 +495,8 @@
     struct sigaction sigpipe_action;
 #endif
 
+    if (fd_output >= 0)
+      fd1 = fd_output;
 #if 0  /* Some systems don't have sigblock.  */
     mask = sigblock (sigmask (SIGCHLD));
 #endif
@@ -591,6 +638,8 @@
     /* Close most of our fd's, but not fd[0]
        since we will use that to read input from.  */
     emacs_close (filefd);
+    if (fd_output >= 0)
+      emacs_close (fd_output);
     if (fd1 >= 0 && fd1 != fd_error)
       emacs_close (fd1);
   }
@@ -673,6 +722,7 @@
   immediate_quit = 1;
   QUIT;
 
+  if (output_to_buffer)
   {
     register EMACS_INT nread;
     int first = 1;
@@ -802,7 +852,10 @@
 
 #ifndef MSDOS
   /* Wait for it to terminate, unless it already has.  */
-  wait_for_termination (pid);
+  if (output_to_buffer)
+    wait_for_termination (pid);
+  else
+    interruptible_wait_for_termination (pid);
 #endif
 
   immediate_quit = 0;
@@ -850,8 +903,10 @@
 The remaining arguments are optional.
 Delete the text if fourth arg DELETE is non-nil.
 
-Insert output in BUFFER before point; t means current buffer;
- nil for BUFFER means discard it; 0 means discard and don't wait.
+Insert output in BUFFER before point; t means current buffer; nil for
+ BUFFER means discard it; 0 means discard and don't wait; and `(:file
+ FILE)', where FILE is a file name string, means that it should be
+ written to that file.
 BUFFER can also have the form (REAL-BUFFER STDERR-FILE); in that case,
 REAL-BUFFER says what to do with standard output, as above,
 while STDERR-FILE says what to do with standard error in the child.

=== modified file 'src/lisp.h'
--- a/src/lisp.h        2011-04-26 19:14:07 +0000
+++ b/src/lisp.h        2011-05-01 00:04:17 +0000
@@ -3349,6 +3349,7 @@
 extern void init_all_sys_modes (void);
 extern void reset_all_sys_modes (void);
 extern void wait_for_termination (int);
+extern void interruptible_wait_for_termination (int);
 extern void flush_pending_output (int);
 extern void child_setup_tty (int);
 extern void setup_pty (int);

=== modified file 'src/sysdep.c'
--- a/src/sysdep.c      2011-04-26 06:17:52 +0000
+++ b/src/sysdep.c      2011-05-01 00:04:17 +0000
@@ -302,6 +302,19 @@
 void
 wait_for_termination (int pid)
 {
+  wait_for_termination_1 (pid, 0);
+}
+
+/* Like the above, but allow keyboard interruption. */
+void
+interruptible_wait_for_termination (int pid)
+{
+  wait_for_termination_1 (pid, 1);
+}
+
+void
+wait_for_termination_1 (int pid, int interruptible)
+{
   while (1)
     {
 #if (defined (BSD_SYSTEM) || defined (HPUX)) && !defined(__GNU__)
@@ -339,6 +352,8 @@
       sigsuspend (&empty_mask);
 #endif /* not WINDOWSNT */
 #endif /* not BSD_SYSTEM, and not HPUX version >= 6 */
+      if (interruptible)
+       QUIT;
     }
 }
 


reply via email to

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