use dynwind_begin and dynwind_end
[bpt/emacs.git] / src / callproc.c
index 98ffc2f..56bdc7d 100644 (file)
@@ -82,12 +82,7 @@ static Lisp_Object Vtemp_file_name_pattern;
 /* If nonzero, a process-ID that has not been reaped.  */
 static pid_t synch_process_pid;
 
-/* If a string, the name of a temp file that has not been removed.  */
-#ifdef MSDOS
 static Lisp_Object synch_process_tempfile;
-#else
-# define synch_process_tempfile make_number (0)
-#endif
 
 /* Indexes of file descriptors that need closing on call_process_kill.  */
 enum
@@ -103,7 +98,7 @@ enum
     CALLPROC_FDS
   };
 
-static Lisp_Object call_process (ptrdiff_t, Lisp_Object *, int, ptrdiff_t);
+static Lisp_Object call_process (ptrdiff_t, Lisp_Object *, int *, Lisp_Object *);
 \f
 /* Return the current buffer's working directory, or the home
    directory if it's unreachable, as a string suitable for a system call.
@@ -133,7 +128,7 @@ encode_current_directory (void)
     report_file_error ("Setting current directory",
                       BVAR (current_buffer, directory));
 
-  RETURN_UNGCPRO (dir);
+  return dir;
 }
 
 /* If P is reapable, record it as a deleted process and kill it.
@@ -161,9 +156,11 @@ record_kill_process (struct Lisp_Process *p, Lisp_Object tempfile)
 /* Clean up files, file descriptors and processes created by Fcall_process.  */
 
 static void
-delete_temp_file (Lisp_Object name)
+delete_temp_file_ptr (Lisp_Object *name_ptr)
 {
-  unlink (SSDATA (name));
+  Lisp_Object name = *name_ptr;
+  if (! NILP (name))
+    unlink (SSDATA (name));
 }
 
 static void
@@ -184,7 +181,7 @@ call_process_kill (void *ptr)
       synch_process_pid = 0;
     }
   else if (STRINGP (synch_process_tempfile))
-    delete_temp_file (synch_process_tempfile);
+    delete_temp_file_ptr (&synch_process_tempfile);
 }
 
 /* Clean up when exiting Fcall_process: restore the buffer, and
@@ -248,7 +245,7 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS)  *
   Lisp_Object infile, encoded_infile;
   int filefd;
   struct gcpro gcpro1;
-  ptrdiff_t count = SPECPDL_INDEX ();
+  dynwind_begin ();
 
   if (nargs >= 2 && ! NILP (args[1]))
     {
@@ -264,9 +261,11 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS)  *
   filefd = emacs_open (SSDATA (encoded_infile), O_RDONLY, 0);
   if (filefd < 0)
     report_file_error ("Opening process input file", infile);
-  record_unwind_protect_int (close_file_unwind, filefd);
+  record_unwind_protect_ptr (close_file_ptr_unwind, &filefd);
   UNGCPRO;
-  return unbind_to (count, call_process (nargs, args, filefd, -1));
+  Lisp_Object tem0 = call_process (nargs, args, &filefd, NULL);
+  dynwind_end ();
+  return tem0;
 }
 
 /* Like Fcall_process (NARGS, ARGS), except use FILEFD as the input file.
@@ -278,8 +277,7 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS)  *
    At entry, the specpdl stack top entry must be close_file_unwind (FILEFD).  */
 
 static Lisp_Object
-call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
-             ptrdiff_t tempfile_index)
+call_process (ptrdiff_t nargs, Lisp_Object *args, int *filefd, Lisp_Object *tempfile_ptr)
 {
   Lisp_Object buffer, current_dir, path;
   bool display_p;
@@ -287,7 +285,6 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
   int callproc_fd[CALLPROC_FDS];
   int status;
   ptrdiff_t i;
-  ptrdiff_t count = SPECPDL_INDEX ();
   USE_SAFE_ALLOCA;
 
   char **new_argv;
@@ -310,6 +307,8 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
   Lisp_Object coding_systems;
   bool discard_output;
 
+  dynwind_begin ();
+
   if (synch_process_pid)
     error ("call-process invoked recursively");
 
@@ -570,12 +569,12 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
 #ifdef MSDOS /* MW, July 1993 */
   /* Note that on MSDOS `child_setup' actually returns the child process
      exit status, not its PID, so assign it to status below.  */
-  pid = child_setup (filefd, fd_output, fd_error, new_argv, 0, current_dir);
+  pid = child_setup (*filefd, fd_output, fd_error, new_argv, 0, current_dir);
 
   if (pid < 0)
     {
       child_errno = errno;
-      unbind_to (count, Qnil);
+      dynwind_end ();
       synchronize_system_messages_locale ();
       return
        code_convert_string_norecord (build_string (strerror (child_errno)),
@@ -589,8 +588,8 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
        emacs_close (callproc_fd[i]);
        callproc_fd[i] = -1;
       }
-  emacs_close (filefd);
-  clear_unwind_protect (count - 1);
+  emacs_close (*filefd);
+  *filefd = -1;
 
   if (tempfile)
     {
@@ -619,7 +618,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
   block_child_signal (&oldset);
 
 #ifdef WINDOWSNT
-  pid = child_setup (filefd, fd_output, fd_error, new_argv, 0, current_dir);
+  pid = child_setup (*filefd, fd_output, fd_error, new_argv, 0, current_dir);
 #else  /* not WINDOWSNT */
 
   /* vfork, and prevent local vars from being clobbered by the vfork.  */
@@ -628,11 +627,8 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
     Lisp_Object volatile coding_systems_volatile = coding_systems;
     Lisp_Object volatile current_dir_volatile = current_dir;
     bool volatile display_p_volatile = display_p;
-    bool volatile sa_must_free_volatile = sa_must_free;
     int volatile fd_error_volatile = fd_error;
-    int volatile filefd_volatile = filefd;
-    ptrdiff_t volatile count_volatile = count;
-    ptrdiff_t volatile sa_count_volatile = sa_count;
+    int *volatile filefd_volatile = filefd;
     char **volatile new_argv_volatile = new_argv;
     int volatile callproc_fd_volatile[CALLPROC_FDS];
     for (i = 0; i < CALLPROC_FDS; i++)
@@ -644,11 +640,8 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
     coding_systems = coding_systems_volatile;
     current_dir = current_dir_volatile;
     display_p = display_p_volatile;
-    sa_must_free = sa_must_free_volatile;
     fd_error = fd_error_volatile;
     filefd = filefd_volatile;
-    count = count_volatile;
-    sa_count = sa_count_volatile;
     new_argv = new_argv_volatile;
 
     for (i = 0; i < CALLPROC_FDS; i++)
@@ -669,7 +662,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
       signal (SIGPROF, SIG_DFL);
 #endif
 
-      child_setup (filefd, fd_output, fd_error, new_argv, 0, current_dir);
+      child_setup (*filefd, fd_output, fd_error, new_argv, 0, current_dir);
     }
 
 #endif /* not WINDOWSNT */
@@ -682,14 +675,15 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
 
       if (INTEGERP (buffer))
        {
-         if (tempfile_index < 0)
-           record_deleted_pid (pid, Qnil);
-         else
-           {
-             eassert (1 < nargs);
-             record_deleted_pid (pid, args[1]);
-             clear_unwind_protect (tempfile_index);
-           }
+          if (tempfile_ptr)
+            {
+              record_deleted_pid (pid, *tempfile_ptr);
+              *tempfile_ptr = Qnil;
+            }
+          else
+            {
+              record_deleted_pid (pid, Qnil);
+            }
          synch_process_pid = 0;
        }
     }
@@ -708,13 +702,16 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
        emacs_close (callproc_fd[i]);
        callproc_fd[i] = -1;
       }
-  emacs_close (filefd);
-  clear_unwind_protect (count - 1);
+  emacs_close (*filefd);
+  *filefd = -1;
 
 #endif /* not MSDOS */
 
   if (INTEGERP (buffer))
-    return unbind_to (count, Qnil);
+    {
+      dynwind_end ();
+      return Qnil;
+    }
 
   if (BUFFERP (buffer))
     Fset_buffer (buffer);
@@ -813,8 +810,8 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
          else
            {                   /* We have to decode the input.  */
              Lisp_Object curbuf;
-             ptrdiff_t count1 = SPECPDL_INDEX ();
 
+              dynwind_begin ();
              XSETBUFFER (curbuf, current_buffer);
              /* FIXME: Call signal_after_change!  */
              prepare_to_modify_buffer (PT, PT, NULL);
@@ -826,7 +823,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
              specbind (Qinhibit_modification_hooks, Qt);
              decode_coding_c_string (&process_coding,
                                      (unsigned char *) buf, nread, curbuf);
-             unbind_to (count1, Qnil);
+              dynwind_end ();
              if (display_on_the_fly
                  && CODING_REQUIRE_DETECTION (&saved_coding)
                  && ! CODING_REQUIRE_DETECTION (&process_coding))
@@ -901,7 +898,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
   synch_process_pid = 0;
 
   SAFE_FREE ();
-  unbind_to (count, Qnil);
+  dynwind_end ();
 
   if (WIFSIGNALED (status))
     {
@@ -928,9 +925,9 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
    Unwind-protect the file, so that the file descriptor will be closed
    and the file removed when the caller unwinds the specpdl stack.  */
 
-static int
+static void
 create_temp_file (ptrdiff_t nargs, Lisp_Object *args,
-                 Lisp_Object *filename_string_ptr)
+                 Lisp_Object *filename_string_ptr, int *fdp)
 {
   int fd;
   struct gcpro gcpro1;
@@ -980,14 +977,14 @@ create_temp_file (ptrdiff_t nargs, Lisp_Object *args,
     GCPRO1 (filename_string);
     tempfile = SSDATA (filename_string);
 
-    count = SPECPDL_INDEX ();
-    record_unwind_protect_nothing ();
     fd = mkostemp (tempfile, O_CLOEXEC);
     if (fd < 0)
       report_file_error ("Failed to open temporary file using pattern",
                         pattern);
-    set_unwind_protect (count, delete_temp_file, filename_string);
-    record_unwind_protect_int (close_file_unwind, fd);
+    *fdp = fd;
+    *filename_string_ptr = filename_string;
+    record_unwind_protect (delete_temp_file_ptr, filename_string_ptr);
+    record_unwind_protect_ptr (close_file_ptr_unwind, fdp);
   }
 
   start = args[0];
@@ -1012,7 +1009,7 @@ create_temp_file (ptrdiff_t nargs, Lisp_Object *args,
   val = complement_process_encoding_system (val);
 
   {
-    ptrdiff_t count1 = SPECPDL_INDEX ();
+    dynwind_begin ();
 
     specbind (intern ("coding-system-for-write"), val);
     /* POSIX lets mk[s]temp use "."; don't invoke jka-compr if we
@@ -1020,7 +1017,7 @@ create_temp_file (ptrdiff_t nargs, Lisp_Object *args,
     specbind (intern ("file-name-handler-alist"), Qnil);
     write_region (start, end, filename_string, Qnil, Qlambda, Qnil, Qnil, fd);
 
-    unbind_to (count1, Qnil);
+    dynwind_end ();
   }
 
   if (lseek (fd, 0, SEEK_SET) < 0)
@@ -1029,9 +1026,7 @@ create_temp_file (ptrdiff_t nargs, Lisp_Object *args,
   /* Note that Fcall_process takes care of binding
      coding-system-for-read.  */
 
-  *filename_string_ptr = filename_string;
   UNGCPRO;
-  return fd;
 }
 
 DEFUN ("call-process-region", Fcall_process_region, Scall_process_region,
@@ -1063,7 +1058,7 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r
 {
   struct gcpro gcpro1;
   Lisp_Object infile, val;
-  ptrdiff_t count = SPECPDL_INDEX ();
+  dynwind_begin ();
   Lisp_Object start = args[0];
   Lisp_Object end = args[1];
   bool empty_input;
@@ -1082,14 +1077,14 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r
     }
 
   if (!empty_input)
-    fd = create_temp_file (nargs, args, &infile);
+    create_temp_file (nargs, args, &infile, &fd);
   else
     {
       infile = Qnil;
       fd = emacs_open (NULL_DEVICE, O_RDONLY, 0);
       if (fd < 0)
        report_file_error ("Opening null device", Qnil);
-      record_unwind_protect_int (close_file_unwind, fd);
+      record_unwind_protect_ptr (close_file_ptr_unwind, &fd);
     }
 
   GCPRO1 (infile);
@@ -1109,8 +1104,9 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r
     }
   args[1] = infile;
 
-  val = call_process (nargs, args, fd, empty_input ? -1 : count);
-  RETURN_UNGCPRO (unbind_to (count, val));
+  val = call_process (nargs, args, &fd, &infile);
+  dynwind_end ();
+  return val;
 }
 \f
 #ifndef WINDOWSNT
@@ -1669,10 +1665,8 @@ syms_of_callproc (void)
 #endif
   staticpro (&Vtemp_file_name_pattern);
 
-#ifdef MSDOS
   synch_process_tempfile = make_number (0);
   staticpro (&synch_process_tempfile);
-#endif
 
   DEFVAR_LISP ("shell-file-name", Vshell_file_name,
               doc: /* File name to load inferior shells from.