(wait_reading_process_output): Check for window changes caused by timers.
[bpt/emacs.git] / src / process.c
index 4360926..e959dea 100644 (file)
@@ -1,7 +1,7 @@
 /* Asynchronous subprocess control for GNU Emacs.
    Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995,
                  1996, 1998, 1999, 2001, 2002, 2003, 2004,
-                 2005, 2006, 2007 Free Software Foundation, Inc.
+                 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -57,12 +57,9 @@ Boston, MA 02110-1301, USA.  */
 #include <netdb.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
-#ifdef NEED_NET_ERRNO_H
-#include <net/errno.h>
-#endif /* NEED_NET_ERRNO_H */
 
 /* Are local (unix) sockets supported?  */
-#if defined (HAVE_SYS_UN_H) && !defined (NO_SOCKETS_IN_FILE_SYSTEM)
+#if defined (HAVE_SYS_UN_H)
 #if !defined (AF_LOCAL) && defined (AF_UNIX)
 #define AF_LOCAL AF_UNIX
 #endif
@@ -78,21 +75,12 @@ Boston, MA 02110-1301, USA.  */
 #include <client.h>
 #endif
 
-/* On some systems, e.g. DGUX, inet_addr returns a 'struct in_addr'. */
-#ifdef HAVE_BROKEN_INET_ADDR
-#define IN_ADDR struct in_addr
-#define NUMERIC_ADDR_ERROR (numeric_addr.s_addr == -1)
-#else
-#define IN_ADDR unsigned long
-#define NUMERIC_ADDR_ERROR (numeric_addr == -1)
-#endif
-
-#if defined(BSD_SYSTEM) || defined(STRIDE)
+#if defined(BSD_SYSTEM)
 #include <sys/ioctl.h>
 #if !defined (O_NDELAY) && defined (HAVE_PTYS) && !defined(USG5)
 #include <fcntl.h>
 #endif /* HAVE_PTYS and no O_NDELAY */
-#endif /* BSD_SYSTEM || STRIDE */
+#endif /* BSD_SYSTEM */
 
 #ifdef BROKEN_O_NONBLOCK
 #undef O_NONBLOCK
@@ -121,13 +109,19 @@ Boston, MA 02110-1301, USA.  */
 #include <sys/wait.h>
 #endif
 
+#ifdef HAVE_RES_INIT
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#endif
+
 #include "lisp.h"
 #include "systime.h"
 #include "systty.h"
 
 #include "window.h"
 #include "buffer.h"
-#include "charset.h"
+#include "character.h"
 #include "coding.h"
 #include "process.h"
 #include "frame.h"
@@ -168,8 +162,8 @@ extern Lisp_Object QCfilter;
    Qt nor Qnil but is instead a property list (KEY VAL ...).  */
 
 #ifdef HAVE_SOCKETS
-#define NETCONN_P(p) (GC_CONSP (XPROCESS (p)->childp))
-#define NETCONN1_P(p) (GC_CONSP ((p)->childp))
+#define NETCONN_P(p) (CONSP (XPROCESS (p)->childp))
+#define NETCONN1_P(p) (CONSP ((p)->childp))
 #else
 #define NETCONN_P(p) 0
 #define NETCONN1_P(p) 0
@@ -210,12 +204,6 @@ extern int h_errno;
    maybe other values to come.  */
 static Lisp_Object Vprocess_connection_type;
 
-#ifdef SKTPAIR
-#ifndef HAVE_SOCKETS
-#include <sys/socket.h>
-#endif
-#endif /* SKTPAIR */
-
 /* These next two vars are non-static since sysdep.c uses them in the
    emulation of `select'.  */
 /* Number of events of change of status of a process.  */
@@ -590,7 +578,6 @@ allocate_pty ()
 #else
             sprintf (pty_name, "/dev/tty%c%x", c, i);
 #endif /* no PTY_TTY_NAME_SPRINTF */
-#ifndef UNIPLUS
            if (access (pty_name, 6) != 0)
              {
                emacs_close (fd);
@@ -600,7 +587,6 @@ allocate_pty ()
                return -1;
 # endif /* IRIS */
              }
-#endif /* not UNIPLUS */
            setup_pty (fd);
            return fd;
          }
@@ -625,6 +611,7 @@ make_process (name)
   p->tick = 0;
   p->update_tick = 0;
   p->pid = 0;
+  p->pty_flag = 0;
   p->raw_status_new = 0;
   p->status = Qrun;
   p->mark = Fmake_marker ();
@@ -673,6 +660,7 @@ setup_process_coding_systems (process)
   struct Lisp_Process *p = XPROCESS (process);
   int inch = p->infd;
   int outch = p->outfd;
+  Lisp_Object coding_system;
 
   if (inch < 0 || outch < 0)
     return;
@@ -680,26 +668,24 @@ setup_process_coding_systems (process)
   if (!proc_decode_coding_system[inch])
     proc_decode_coding_system[inch]
       = (struct coding_system *) xmalloc (sizeof (struct coding_system));
-  setup_coding_system (p->decode_coding_system,
-                      proc_decode_coding_system[inch]);
+  coding_system = p->decode_coding_system;
   if (! NILP (p->filter))
     {
       if (!p->filter_multibyte)
-       setup_raw_text_coding_system (proc_decode_coding_system[inch]);
+       coding_system = raw_text_coding_system (coding_system);
     }
   else if (BUFFERP (p->buffer))
     {
       if (NILP (XBUFFER (p->buffer)->enable_multibyte_characters))
-       setup_raw_text_coding_system (proc_decode_coding_system[inch]);
+       coding_system = raw_text_coding_system (coding_system);
     }
+  setup_coding_system (coding_system, proc_decode_coding_system[inch]);
 
   if (!proc_encode_coding_system[outch])
     proc_encode_coding_system[outch]
       = (struct coding_system *) xmalloc (sizeof (struct coding_system));
   setup_coding_system (p->encode_coding_system,
                       proc_encode_coding_system[outch]);
-  if (proc_encode_coding_system[outch]->eol_type == CODING_EOL_UNDECIDED)
-    proc_encode_coding_system[outch]->eol_type = system_eol_type;
 }
 \f
 DEFUN ("processp", Fprocessp, Sprocessp, 1, 1, 0,
@@ -733,9 +719,9 @@ BUFFER may be a buffer or the name of one.  */)
   buf = Fget_buffer (buffer);
   if (NILP (buf)) return Qnil;
 
-  for (tail = Vprocess_alist; !NILP (tail); tail = Fcdr (tail))
+  for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail))
     {
-      proc = Fcdr (Fcar (tail));
+      proc = Fcdr (XCAR (tail));
       if (PROCESSP (proc) && EQ (XPROCESS (proc)->buffer, buf))
        return proc;
     }
@@ -1001,7 +987,7 @@ DEFUN ("process-mark", Fprocess_mark, Sprocess_mark,
 DEFUN ("set-process-filter", Fset_process_filter, Sset_process_filter,
        2, 2, 0,
        doc: /* Give PROCESS the filter function FILTER; nil means no filter.
-t means stop accepting output from the process.
+A value of t means stop accepting output from the process.
 
 When a process has a filter, its buffer is not used for output.
 Instead, each time it does output, the entire string of output is
@@ -1339,11 +1325,11 @@ list_processes_1 (query_only)
   w_buffer = 6;  /* Buffer */
   w_tty = 0;     /* Omit if no ttys */
 
-  for (tail = Vprocess_alist; !NILP (tail); tail = Fcdr (tail))
+  for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail))
     {
       int i;
 
-      proc = Fcdr (Fcar (tail));
+      proc = Fcdr (XCAR (tail));
       p = XPROCESS (proc);
       if (NILP (p->childp))
        continue;
@@ -1354,8 +1340,11 @@ list_processes_1 (query_only)
        w_proc = i;
       if (!NILP (p->buffer))
        {
-         if (NILP (XBUFFER (p->buffer)->name) && w_buffer < 8)
-           w_buffer = 8;  /* (Killed) */
+         if (NILP (XBUFFER (p->buffer)->name))
+           {
+             if (w_buffer < 8)
+               w_buffer = 8;  /* (Killed) */
+           }
          else if ((i = SCHARS (XBUFFER (p->buffer)->name), (i > w_buffer)))
            w_buffer = i;
        }
@@ -1369,8 +1358,10 @@ list_processes_1 (query_only)
   if (w_tty)
     {
       XSETFASTINT (i_tty, XFASTINT (i_buffer) + w_buffer + 1);
-      XSETFASTINT (i_command, XFASTINT (i_buffer) + w_tty + 1);
-    } else {
+      XSETFASTINT (i_command, XFASTINT (i_tty) + w_tty + 1);
+    }
+  else
+    {
       i_tty = Qnil;
       XSETFASTINT (i_command, XFASTINT (i_buffer) + w_buffer + 1);
     }
@@ -1402,11 +1393,11 @@ list_processes_1 (query_only)
   Findent_to (i_command, minspace); write_string ("-------", -1);
   write_string ("\n", -1);
 
-  for (tail = Vprocess_alist; !NILP (tail); tail = Fcdr (tail))
+  for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail))
     {
       Lisp_Object symbol;
 
-      proc = Fcdr (Fcar (tail));
+      proc = Fcdr (XCAR (tail));
       p = XPROCESS (proc);
       if (NILP (p->childp))
        continue;
@@ -1605,9 +1596,12 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)  */)
 
     GCPRO2 (buffer, current_dir);
 
-    current_dir
-      = expand_and_dir_to_file (Funhandled_file_name_directory (current_dir),
-                               Qnil);
+    current_dir = Funhandled_file_name_directory (current_dir);
+    if (NILP (current_dir))
+      /* If the file name handler says that current_dir is unreachable, use
+        a sensible default. */
+      current_dir = build_string ("~/");
+    current_dir = expand_and_dir_to_file (current_dir, Qnil);
     if (NILP (Ffile_accessible_directory_p (current_dir)))
       report_file_error ("Setting current directory",
                         Fcons (current_buffer->directory, Qnil));
@@ -1880,12 +1874,12 @@ create_process (process, new_argv, current_dir)
 #endif
       if (forkin < 0)
        report_file_error ("Opening pty", Qnil);
-#if defined (RTU) || defined (UNIPLUS) || defined (DONT_REOPEN_PTY)
+#if defined (DONT_REOPEN_PTY)
       /* In the case that vfork is defined as fork, the parent process
         (Emacs) may send some data before the child process completes
         tty options setup.  So we setup tty before forking.  */
       child_setup_tty (forkout);
-#endif /* RTU or UNIPLUS or DONT_REOPEN_PTY */
+#endif /* DONT_REOPEN_PTY */
 #else
       forkin = forkout = -1;
 #endif /* not USG, or USG_SUBTTY_WORKS */
@@ -1893,14 +1887,6 @@ create_process (process, new_argv, current_dir)
     }
   else
 #endif /* HAVE_PTYS */
-#ifdef SKTPAIR
-    {
-      if (socketpair (AF_UNIX, SOCK_STREAM, 0, sv) < 0)
-       report_file_error ("Opening socketpair", Qnil);
-      outchannel = inchannel = sv[0];
-      forkout = forkin = sv[1];
-    }
-#else /* not SKTPAIR */
     {
       int tem;
       tem = pipe (sv);
@@ -1918,7 +1904,6 @@ create_process (process, new_argv, current_dir)
       outchannel = sv[1];
       forkin = sv[0];
     }
-#endif /* not SKTPAIR */
 
 #if 0
   /* Replaced by close_process_descs */
@@ -1926,15 +1911,6 @@ create_process (process, new_argv, current_dir)
   set_exclusive_use (outchannel);
 #endif
 
-/* Stride people say it's a mystery why this is needed
-   as well as the O_NDELAY, but that it fails without this.  */
-#if defined (STRIDE) || (defined (pfa) && defined (HAVE_PTYS))
-  {
-    int one = 1;
-    ioctl (inchannel, FIONBIO, &one);
-  }
-#endif
-
 #ifdef O_NONBLOCK
   fcntl (inchannel, F_SETFL, O_NONBLOCK);
   fcntl (outchannel, F_SETFL, O_NONBLOCK);
@@ -1984,7 +1960,7 @@ create_process (process, new_argv, current_dir)
 #ifdef BSD4_1
   sighold (SIGCHLD);
 #else /* not BSD4_1 */
-#if defined (BSD_SYSTEM) || defined (UNIPLUS) || defined (HPUX)
+#if defined (BSD_SYSTEM) || defined (HPUX)
   sigsetmask (sigmask (SIGCHLD));
 #else /* ordinary USG */
 #if 0
@@ -2098,7 +2074,7 @@ create_process (process, new_argv, current_dir)
          }
 #endif /* TIOCNOTTY */
 
-#if !defined (RTU) && !defined (UNIPLUS) && !defined (DONT_REOPEN_PTY)
+#if !defined (DONT_REOPEN_PTY)
 /*** There is a suggestion that this ought to be a
      conditional on TIOCSPGRP,
      or !(defined (HAVE_SETSID) && defined (TIOCSCTTY)).
@@ -2132,7 +2108,7 @@ create_process (process, new_argv, current_dir)
            ioctl (xforkout, TIOCSPGRP, &pgrp);
 #endif
          }
-#endif /* not UNIPLUS and not RTU and not DONT_REOPEN_PTY */
+#endif /* not DONT_REOPEN_PTY */
 
 #ifdef SETUP_SLAVE_PTY
        if (pty_flag)
@@ -2159,7 +2135,7 @@ create_process (process, new_argv, current_dir)
 #ifdef BSD4_1
        sigrelse (SIGCHLD);
 #else /* not BSD4_1 */
-#if defined (BSD_SYSTEM) || defined (UNIPLUS) || defined (HPUX)
+#if defined (BSD_SYSTEM) || defined (HPUX)
        sigsetmask (SIGEMPTYMASK);
 #else /* ordinary USG */
 #if 0
@@ -2170,10 +2146,10 @@ create_process (process, new_argv, current_dir)
 #endif /* SIGCHLD */
 #endif /* !POSIX_SIGNALS */
 
-#if !defined (RTU) && !defined (UNIPLUS) && !defined (DONT_REOPEN_PTY)
+#if !defined (DONT_REOPEN_PTY)
        if (pty_flag)
          child_setup_tty (xforkout);
-#endif /* not RTU and not UNIPLUS and not DONT_REOPEN_PTY */
+#endif /* not DONT_REOPEN_PTY */
 #ifdef WINDOWSNT
        pid = child_setup (xforkin, xforkout, xforkout,
                           new_argv, 1, current_dir);
@@ -2251,7 +2227,7 @@ create_process (process, new_argv, current_dir)
 #ifdef BSD4_1
   sigrelse (SIGCHLD);
 #else /* not BSD4_1 */
-#if defined (BSD_SYSTEM) || defined (UNIPLUS) || defined (HPUX)
+#if defined (BSD_SYSTEM) || defined (HPUX)
   sigsetmask (SIGEMPTYMASK);
 #else /* ordinary USG */
 #if 0
@@ -2677,6 +2653,7 @@ OPTION is not a supported option, return nil instead; otherwise return t.  */)
 \f
 /* A version of request_sigio suitable for a record_unwind_protect.  */
 
+#ifdef __ultrix__
 static Lisp_Object
 unwind_request_sigio (dummy)
      Lisp_Object dummy;
@@ -2685,6 +2662,7 @@ unwind_request_sigio (dummy)
     request_sigio ();
   return Qnil;
 }
+#endif
 
 /* Create a network stream/datagram client/server process.  Treated
    exactly like a normal process when reading and writing.  Primary
@@ -2721,7 +2699,9 @@ host, and only clients connecting to that address will be accepted.
 
 :service SERVICE -- SERVICE is name of the service desired, or an
 integer specifying a port number to connect to.  If SERVICE is t,
-a random port number is selected for the server.
+a random port number is selected for the server.  (If Emacs was
+compiled with getaddrinfo, a port number can also be specified as a
+string, e.g. "80", as well as an integer.  This is not portable.)
 
 :type TYPE -- TYPE is the type of connection.  The default (nil) is a
 stream type connection, `datagram' creates a datagram type connection.
@@ -2780,7 +2760,7 @@ The stopped state is cleared by `continue-process' and set by
 
 :filter-multibyte BOOL -- If BOOL is non-nil, strings given to the
 process filter are multibyte, otherwise they are unibyte.
-If this keyword is not specified, the strings are multibyte iff
+If this keyword is not specified, the strings are multibyte if
 `default-enable-multibyte-characters' is non-nil.
 
 :sentinel SENTINEL -- Install SENTINEL as the process sentinel.
@@ -3081,6 +3061,11 @@ usage: (make-network-process &rest ARGS)  */)
       hints.ai_family = family;
       hints.ai_socktype = socktype;
       hints.ai_protocol = 0;
+
+#ifdef HAVE_RES_INIT
+      res_init ();
+#endif
+
       ret = getaddrinfo (SDATA (host), portstring, &hints, &res);
       if (ret)
 #ifdef HAVE_GAI_STRERROR
@@ -3126,6 +3111,11 @@ usage: (make-network-process &rest ARGS)  */)
         as it may `hang' Emacs for a very long time.  */
       immediate_quit = 1;
       QUIT;
+
+#ifdef HAVE_RES_INIT
+      res_init ();
+#endif
+
       host_info_ptr = gethostbyname (SDATA (host));
       immediate_quit = 0;
 
@@ -3139,9 +3129,9 @@ usage: (make-network-process &rest ARGS)  */)
       else
        /* Attempt to interpret host as numeric inet address */
        {
-         IN_ADDR numeric_addr;
+         unsigned long numeric_addr;
          numeric_addr = inet_addr ((char *) SDATA (host));
-         if (NUMERIC_ADDR_ERROR)
+         if (numeric_addr == -1)
            error ("Unknown host \"%s\"", SDATA (host));
 
          bcopy ((char *)&numeric_addr, (char *) &address_in.sin_addr,
@@ -3922,7 +3912,7 @@ it specifies a fractional number of seconds to wait.
 If optional fourth arg JUST-THIS-ONE is non-nil, only accept output
 from PROCESS, suspending reading output from other processes.
 If JUST-THIS-ONE is an integer, don't run any timers either.
-Return non-nil iff we received any output before the timeout expired.  */)
+Return non-nil if we received any output before the timeout expired.  */)
      (process, seconds, millisec, just_this_one)
      register Lisp_Object process, seconds, millisec, just_this_one;
 {
@@ -4254,16 +4244,16 @@ select_wrapper (n, rfd, wfd, xfd, tmo)
      (and gobble terminal input into the buffer if any arrives).
 
    If WAIT_PROC is specified, wait until something arrives from that
-     process.  The return value is true iff we read some input from
+     process.  The return value is true if we read some input from
      that process.
 
    If JUST_WAIT_PROC is non-nil, handle only output from WAIT_PROC
      (suspending output from other processes).  A negative value
      means don't run any timers either.
 
-   If WAIT_PROC is specified, then the function returns true iff we
+   If WAIT_PROC is specified, then the function returns true if we
      received input from that process before the timeout elapsed.
-   Otherwise, return true iff we received input from any process.  */
+   Otherwise, return true if we received input from any process.  */
 
 int
 wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
@@ -4372,13 +4362,15 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
            {
              int old_timers_run = timers_run;
              struct buffer *old_buffer = current_buffer;
+             Lisp_Object old_window = selected_window;
 
              timer_delay = timer_check (1);
 
              /* If a timer has run, this might have changed buffers
                 an alike.  Make read_key_sequence aware of that.  */
              if (timers_run != old_timers_run
-                 && old_buffer != current_buffer
+                 && (old_buffer != current_buffer
+                     || !EQ (old_window, selected_window))
                  && waiting_for_user_input_p == -1)
                record_asynch_buffer_change ();
 
@@ -4627,12 +4619,6 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
             not by DEC's bundled CC.  -JimB  */
          else if (xerrno == ENOMEM)
            no_avail = 1;
-#endif
-#ifdef ALLIANT
-         /* This happens for no known reason on ALLIANT.
-            I am guessing that this is the right response. -- RMS.  */
-         else if (xerrno == EFAULT)
-           no_avail = 1;
 #endif
          else if (xerrno == EBADF)
            {
@@ -4695,6 +4681,7 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
        {
          int old_timers_run = timers_run;
          struct buffer *old_buffer = current_buffer;
+         Lisp_Object old_window = selected_window;
          int leave = 0;
 
          if (detect_input_pending_run_timers (do_display))
@@ -4708,7 +4695,8 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
             an alike.  Make read_key_sequence aware of that.  */
          if (timers_run != old_timers_run
              && waiting_for_user_input_p == -1
-             && old_buffer != current_buffer)
+             && (old_buffer != current_buffer
+             || !EQ (old_window, selected_window)))
            record_asynch_buffer_change ();
 
          if (leave)
@@ -5144,13 +5132,13 @@ read_process_output (proc, channel)
         save the match data in a special nonrecursive fashion.  */
       running_asynch_code = 1;
 
-      text = decode_coding_string (make_unibyte_string (chars, nbytes),
-                                  coding, 0);
-      Vlast_coding_system_used = coding->symbol;
+      decode_coding_c_string (coding, chars, nbytes, Qt);
+      text = coding->dst_object;
+      Vlast_coding_system_used = CODING_ID_NAME (coding->id);
       /* A new coding system might be found.  */
-      if (!EQ (p->decode_coding_system, coding->symbol))
+      if (!EQ (p->decode_coding_system, Vlast_coding_system_used))
        {
-         p->decode_coding_system = coding->symbol;
+         p->decode_coding_system = Vlast_coding_system_used;
 
          /* Don't call setup_coding_system for
             proc_decode_coding_system[channel] here.  It is done in
@@ -5166,25 +5154,21 @@ read_process_output (proc, channel)
          if (NILP (p->encode_coding_system)
              && proc_encode_coding_system[p->outfd])
            {
-             p->encode_coding_system = coding->symbol;
-             setup_coding_system (coding->symbol,
+             p->encode_coding_system
+               = coding_inherit_eol_type (Vlast_coding_system_used, Qnil);
+             setup_coding_system (p->encode_coding_system,
                                   proc_encode_coding_system[p->outfd]);
-             if (proc_encode_coding_system[p->outfd]->eol_type
-                 == CODING_EOL_UNDECIDED)
-               proc_encode_coding_system[p->outfd]->eol_type
-                 = system_eol_type;
            }
        }
 
-      carryover = nbytes - coding->consumed;
-      if (carryover < 0)
-       abort ();
-
-      if (SCHARS (p->decoding_buf) < carryover)
-       p->decoding_buf = make_uninit_string (carryover);
-      bcopy (chars + coding->consumed, SDATA (p->decoding_buf),
-            carryover);
-      p->decoding_carryover = carryover;
+      if (coding->carryover_bytes > 0)
+       {
+         if (SCHARS (p->decoding_buf) < coding->carryover_bytes)
+           p->decoding_buf = make_uninit_string (coding->carryover_bytes);
+         bcopy (coding->carryover, SDATA (p->decoding_buf),
+                coding->carryover_bytes);
+         p->decoding_carryover = coding->carryover_bytes;
+       }
       /* Adjust the multibyteness of TEXT to that of the filter.  */
       if (!p->filter_multibyte != !STRING_MULTIBYTE (text))
        text = (STRING_MULTIBYTE (text)
@@ -5269,36 +5253,31 @@ read_process_output (proc, channel)
       if (! (BEGV <= PT && PT <= ZV))
        Fwiden ();
 
-      text = decode_coding_string (make_unibyte_string (chars, nbytes),
-                                  coding, 0);
-      Vlast_coding_system_used = coding->symbol;
+      decode_coding_c_string (coding, chars, nbytes, Qt);
+      text = coding->dst_object;
+      Vlast_coding_system_used = CODING_ID_NAME (coding->id);
       /* A new coding system might be found.  See the comment in the
         similar code in the previous `if' block.  */
-      if (!EQ (p->decode_coding_system, coding->symbol))
+      if (!EQ (p->decode_coding_system, Vlast_coding_system_used))
        {
-         p->decode_coding_system = coding->symbol;
+         p->decode_coding_system = Vlast_coding_system_used;
          if (NILP (p->encode_coding_system)
              && proc_encode_coding_system[p->outfd])
            {
-             p->encode_coding_system = coding->symbol;
-             setup_coding_system (coding->symbol,
+             p->encode_coding_system
+               = coding_inherit_eol_type (Vlast_coding_system_used, Qnil);
+             setup_coding_system (p->encode_coding_system,
                                   proc_encode_coding_system[p->outfd]);
-             if (proc_encode_coding_system[p->outfd]->eol_type
-                 == CODING_EOL_UNDECIDED)
-               proc_encode_coding_system[p->outfd]->eol_type
-                 = system_eol_type;
            }
        }
-      carryover = nbytes - coding->consumed;
-      if (carryover < 0)
-       abort ();
-
-      if (SCHARS (p->decoding_buf) < carryover)
-       p->decoding_buf = make_uninit_string (carryover);
-      bcopy (chars + coding->consumed, SDATA (p->decoding_buf),
-            carryover);
-      p->decoding_carryover = carryover;
-
+      if (coding->carryover_bytes > 0)
+       {
+         if (SCHARS (p->decoding_buf) < coding->carryover_bytes)
+           p->decoding_buf = make_uninit_string (coding->carryover_bytes);
+         bcopy (coding->carryover, SDATA (p->decoding_buf),
+                coding->carryover_bytes);
+         p->decoding_carryover = coding->carryover_bytes;
+       }
       /* Adjust the multibyteness of TEXT to that of the buffer.  */
       if (NILP (current_buffer->enable_multibyte_characters)
          != ! STRING_MULTIBYTE (text))
@@ -5420,24 +5399,19 @@ send_process (proc, buf, len, object)
     error ("Output file descriptor of %s is closed", SDATA (p->name));
 
   coding = proc_encode_coding_system[p->outfd];
-  Vlast_coding_system_used = coding->symbol;
+  Vlast_coding_system_used = CODING_ID_NAME (coding->id);
 
   if ((STRINGP (object) && STRING_MULTIBYTE (object))
       || (BUFFERP (object)
          && !NILP (XBUFFER (object)->enable_multibyte_characters))
       || EQ (object, Qt))
     {
-      if (!EQ (coding->symbol, p->encode_coding_system))
+      if (!EQ (Vlast_coding_system_used, p->encode_coding_system))
        /* The coding system for encoding was changed to raw-text
           because we sent a unibyte text previously.  Now we are
           sending a multibyte text, thus we must encode it by the
           original coding system specified for the current process.  */
        setup_coding_system (p->encode_coding_system, coding);
-      if (coding->eol_type == CODING_EOL_UNDECIDED)
-       coding->eol_type = system_eol_type;
-      /* src_multibyte should be set to 1 _after_ a call to
-        setup_coding_system, since it resets src_multibyte to
-        zero.  */
       coding->src_multibyte = 1;
     }
   else
@@ -5445,60 +5419,56 @@ send_process (proc, buf, len, object)
       /* For sending a unibyte text, character code conversion should
         not take place but EOL conversion should.  So, setup raw-text
         or one of the subsidiary if we have not yet done it.  */
-      if (coding->type != coding_type_raw_text)
+      if (CODING_REQUIRE_ENCODING (coding))
        {
          if (CODING_REQUIRE_FLUSHING (coding))
            {
              /* But, before changing the coding, we must flush out data.  */
              coding->mode |= CODING_MODE_LAST_BLOCK;
              send_process (proc, "", 0, Qt);
+             coding->mode &= CODING_MODE_LAST_BLOCK;
            }
+         setup_coding_system (raw_text_coding_system
+                              (Vlast_coding_system_used),
+                              coding);
          coding->src_multibyte = 0;
-         setup_raw_text_coding_system (coding);
        }
     }
   coding->dst_multibyte = 0;
 
   if (CODING_REQUIRE_ENCODING (coding))
     {
-      int require = encoding_buffer_size (coding, len);
-      int from_byte = -1, from = -1, to = -1;
-
+      coding->dst_object = Qt;
       if (BUFFERP (object))
        {
-         from_byte = BUF_PTR_BYTE_POS (XBUFFER (object), buf);
-         from = buf_bytepos_to_charpos (XBUFFER (object), from_byte);
-         to = buf_bytepos_to_charpos (XBUFFER (object), from_byte + len);
+         int from_byte, from, to;
+         int save_pt, save_pt_byte;
+         struct buffer *cur = current_buffer;
+
+         set_buffer_internal (XBUFFER (object));
+         save_pt = PT, save_pt_byte = PT_BYTE;
+
+         from_byte = PTR_BYTE_POS (buf);
+         from = BYTE_TO_CHAR (from_byte);
+         to = BYTE_TO_CHAR (from_byte + len);
+         TEMP_SET_PT_BOTH (from, from_byte);
+         encode_coding_object (coding, object, from, from_byte,
+                               to, from_byte + len, Qt);
+         TEMP_SET_PT_BOTH (save_pt, save_pt_byte);
+         set_buffer_internal (cur);
        }
       else if (STRINGP (object))
        {
-         from_byte = buf - SDATA (object);
-         from = string_byte_to_char (object, from_byte);
-         to =  string_byte_to_char (object, from_byte + len);
+         encode_coding_string (coding, object, 1);
        }
-
-      if (coding->composing != COMPOSITION_DISABLED)
+      else
        {
-         if (from_byte >= 0)
-           coding_save_composition (coding, from, to, object);
-         else
-           coding->composing = COMPOSITION_DISABLED;
+         coding->dst_object = make_unibyte_string (buf, len);
+         coding->produced = len;
        }
 
-      if (SBYTES (p->encoding_buf) < require)
-       p->encoding_buf = make_uninit_string (require);
-
-      if (from_byte >= 0)
-       buf = (BUFFERP (object)
-              ? BUF_BYTE_ADDRESS (XBUFFER (object), from_byte)
-              : SDATA (object) + from_byte);
-
-      object = p->encoding_buf;
-      encode_coding (coding, (char *) buf, SDATA (object),
-                    len, SBYTES (object));
-      coding_free_composition_data (coding);
       len = coding->produced;
-      buf = SDATA (object);
+      buf = SDATA (coding->dst_object);
     }
 
 #ifdef VMS
@@ -5692,91 +5662,6 @@ send_process (proc, buf, len, object)
   UNGCPRO;
 }
 
-static Lisp_Object
-send_process_object_unwind (buf)
-     Lisp_Object buf;
-{
-  Lisp_Object tembuf;
-
-  if (XBUFFER (buf) == current_buffer)
-    return Qnil;
-  tembuf = Fcurrent_buffer ();
-  Fset_buffer (buf);
-  Fkill_buffer (tembuf);
-  return Qnil;
-}
-
-/* Send current contents of region between START and END to PROC.
-   If START is a string, send it instead.
-   This function can evaluate Lisp code and can garbage collect.  */
-
-static void
-send_process_object (proc, start, end)
-     Lisp_Object proc, start, end;
-{
-  int count = SPECPDL_INDEX ();
-  Lisp_Object object = STRINGP (start) ? start : Fcurrent_buffer ();
-  struct buffer *given_buffer = current_buffer;
-  unsigned char *buf;
-  int len;
-
-  record_unwind_protect (send_process_object_unwind, Fcurrent_buffer ());
-
-  if (STRINGP (object) ? STRING_MULTIBYTE (object)
-      : ! NILP (XBUFFER (object)->enable_multibyte_characters))
-    {
-      struct Lisp_Process *p = XPROCESS (proc);
-      struct coding_system *coding;
-
-      if (p->raw_status_new)
-       update_status (p);
-      if (! EQ (p->status, Qrun))
-       error ("Process %s not running", SDATA (p->name));
-      if (p->outfd < 0)
-       error ("Output file descriptor of %s is closed", SDATA (p->name));
-
-      coding = proc_encode_coding_system[p->outfd];
-      if (! EQ (coding->symbol, p->encode_coding_system))
-       /* The coding system for encoding was changed to raw-text
-          because we sent a unibyte text previously.  Now we are
-          sending a multibyte text, thus we must encode it by the
-          original coding system specified for the current process.  */
-       setup_coding_system (p->encode_coding_system, coding);
-      if (! NILP (coding->pre_write_conversion))
-       {
-         struct gcpro gcpro1, gcpro2;
-
-         GCPRO2 (proc, object);
-         call2 (coding->pre_write_conversion, start, end);
-         UNGCPRO;
-         if (given_buffer != current_buffer)
-           {
-             start = make_number (BEGV), end = make_number (ZV);
-             object = Fcurrent_buffer ();
-           }
-       }
-    }
-
-  if (BUFFERP (object))
-    {
-      EMACS_INT start_byte;
-
-      if (XINT (start) < GPT && XINT (end) > GPT)
-       move_gap (XINT (end));
-      start_byte = CHAR_TO_BYTE (XINT (start));
-      buf = BYTE_POS_ADDR (start_byte);
-      len = CHAR_TO_BYTE (XINT (end)) - start_byte;
-    }
-  else
-    {
-      buf = SDATA (object);
-      len = SBYTES (object);
-    }
-  send_process (proc, buf, len, object);
-
-  unbind_to (count, Qnil);
-}
-
 DEFUN ("process-send-region", Fprocess_send_region, Sprocess_send_region,
        3, 3, 0,
        doc: /* Send current contents of region as input to PROCESS.
@@ -5790,10 +5675,19 @@ Output from processes can arrive in between bunches.  */)
      Lisp_Object process, start, end;
 {
   Lisp_Object proc;
+  int start1, end1;
 
   proc = get_process (process);
   validate_region (&start, &end);
-  send_process_object (proc, start, end);
+
+  if (XINT (start) < GPT && XINT (end) > GPT)
+    move_gap (XINT (start));
+
+  start1 = CHAR_TO_BYTE (XINT (start));
+  end1 = CHAR_TO_BYTE (XINT (end));
+  send_process (proc, BYTE_POS_ADDR (start1), end1 - start1,
+               Fcurrent_buffer ());
+
   return Qnil;
 }
 
@@ -5811,7 +5705,8 @@ Output from processes can arrive in between bunches.  */)
   Lisp_Object proc;
   CHECK_STRING (string);
   proc = get_process (process);
-  send_process_object (proc, string, Qnil);
+  send_process (proc, SDATA (string),
+               SBYTES (string), string);
   return Qnil;
 }
 \f
@@ -6460,10 +6355,10 @@ kill_buffer_processes (buffer)
 {
   Lisp_Object tail, proc;
 
-  for (tail = Vprocess_alist; GC_CONSP (tail); tail = XCDR (tail))
+  for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail))
     {
       proc = XCDR (XCAR (tail));
-      if (GC_PROCESSP (proc)
+      if (PROCESSP (proc)
          && (NILP (buffer) || EQ (XPROCESS (proc)->buffer, buffer)))
        {
          if (NETCONN_P (proc))
@@ -6558,11 +6453,11 @@ sigchld_handler (signo)
       /* Find the process that signaled us, and record its status.  */
 
       /* The process can have been deleted by Fdelete_process.  */
-      for (tail = deleted_pid_list; GC_CONSP (tail); tail = XCDR (tail))
+      for (tail = deleted_pid_list; CONSP (tail); tail = XCDR (tail))
        {
          Lisp_Object xpid = XCAR (tail);
-         if ((GC_INTEGERP (xpid) && pid == (pid_t) XINT (xpid))
-             || (GC_FLOATP (xpid) && pid == (pid_t) XFLOAT_DATA (xpid)))
+         if ((INTEGERP (xpid) && pid == (pid_t) XINT (xpid))
+             || (FLOATP (xpid) && pid == (pid_t) XFLOAT_DATA (xpid)))
            {
              XSETCAR (tail, Qnil);
              goto sigchld_end_of_loop;
@@ -6571,11 +6466,11 @@ sigchld_handler (signo)
 
       /* Otherwise, if it is asynchronous, it is in Vprocess_alist.  */
       p = 0;
-      for (tail = Vprocess_alist; GC_CONSP (tail); tail = XCDR (tail))
+      for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail))
        {
          proc = XCDR (XCAR (tail));
          p = XPROCESS (proc);
-         if (GC_EQ (p->childp, Qt) && p->pid == pid)
+         if (EQ (p->childp, Qt) && p->pid == pid)
            break;
          p = 0;
        }
@@ -6583,7 +6478,7 @@ sigchld_handler (signo)
       /* Look for an asynchronous process whose pid hasn't been filled
         in yet.  */
       if (p == 0)
-       for (tail = Vprocess_alist; GC_CONSP (tail); tail = XCDR (tail))
+       for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail))
          {
            proc = XCDR (XCAR (tail));
            p = XPROCESS (proc);
@@ -6781,12 +6676,12 @@ status_notify (deleting_process)
      that we run, we get called again to handle their status changes.  */
   update_tick = process_tick;
 
-  for (tail = Vprocess_alist; !NILP (tail); tail = Fcdr (tail))
+  for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail))
     {
       Lisp_Object symbol;
       register struct Lisp_Process *p;
 
-      proc = Fcdr (Fcar (tail));
+      proc = Fcdr (XCAR (tail));
       p = XPROCESS (proc);
 
       if (p->tick != p->update_tick)
@@ -6906,7 +6801,7 @@ encode subprocess input.  */)
     error ("Output file descriptor of %s closed", SDATA (p->name));
   Fcheck_coding_system (decoding);
   Fcheck_coding_system (encoding);
-
+  encoding = coding_inherit_eol_type (encoding, Qnil);
   p->decode_coding_system = decoding;
   p->encode_coding_system = encoding;
   setup_process_coding_systems (process);
@@ -7325,7 +7220,7 @@ The variable takes effect when `start-process' is called.  */);
 
 #include "lisp.h"
 #include "systime.h"
-#include "charset.h"
+#include "character.h"
 #include "coding.h"
 #include "termopts.h"
 #include "sysselect.h"
@@ -7358,7 +7253,7 @@ Lisp_Object QCtype;
    do_display != 0 means redisplay should be done to show subprocess
    output that arrives.
 
-   Return true iff we received input from any process.  */
+   Return true if we received input from any process.  */
 
 int
 wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,