Use INTERNAL_FIELD for processes.
[bpt/emacs.git] / src / process.c
index 4d59ff0..47f1081 100644 (file)
@@ -93,8 +93,8 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "systty.h"
 
 #include "window.h"
-#include "buffer.h"
 #include "character.h"
+#include "buffer.h"
 #include "coding.h"
 #include "process.h"
 #include "frame.h"
@@ -172,10 +172,10 @@ extern Lisp_Object QCfamily;
 /* QCfilter is defined in keyboard.c.  */
 extern Lisp_Object QCfilter;
 
-#define NETCONN_P(p) (EQ (XPROCESS (p)->type, Qnetwork))
-#define NETCONN1_P(p) (EQ ((p)->type, Qnetwork))
-#define SERIALCONN_P(p) (EQ (XPROCESS (p)->type, Qserial))
-#define SERIALCONN1_P(p) (EQ ((p)->type, Qserial))
+#define NETCONN_P(p) (EQ (PVAR (XPROCESS (p), type), Qnetwork))
+#define NETCONN1_P(p) (EQ (PVAR (p, type), Qnetwork))
+#define SERIALCONN_P(p) (EQ (PVAR (XPROCESS (p), type), Qserial))
+#define SERIALCONN1_P(p) (EQ (PVAR (p, type), Qserial))
 
 #ifndef HAVE_H_ERRNO
 extern int h_errno;
@@ -228,13 +228,11 @@ static EMACS_INT update_tick;
 #endif
 
 #if !defined (ADAPTIVE_READ_BUFFERING) && !defined (NO_ADAPTIVE_READ_BUFFERING)
-#ifdef EMACS_HAS_USECS
 #define ADAPTIVE_READ_BUFFERING
 #endif
-#endif
 
 #ifdef ADAPTIVE_READ_BUFFERING
-#define READ_OUTPUT_DELAY_INCREMENT 10000
+#define READ_OUTPUT_DELAY_INCREMENT (EMACS_TIME_RESOLUTION / 100)
 #define READ_OUTPUT_DELAY_MAX       (READ_OUTPUT_DELAY_INCREMENT * 5)
 #define READ_OUTPUT_DELAY_MAX_MAX   (READ_OUTPUT_DELAY_INCREMENT * 7)
 
@@ -251,7 +249,6 @@ static int process_output_skip;
 #define process_output_delay_count 0
 #endif
 
-static Lisp_Object Fget_process (Lisp_Object);
 static void create_process (Lisp_Object, char **, Lisp_Object);
 #ifdef SIGIO
 static int keyboard_bit_set (SELECT_TYPE *);
@@ -355,7 +352,7 @@ static struct fd_callback_data
 void
 add_read_fd (int fd, fd_callback func, void *data)
 {
-  xassert (fd < MAXDESC);
+  eassert (fd < MAXDESC);
   add_keyboard_wait_descriptor (fd);
 
   fd_callback_info[fd].func = func;
@@ -368,7 +365,7 @@ add_read_fd (int fd, fd_callback func, void *data)
 void
 delete_read_fd (int fd)
 {
-  xassert (fd < MAXDESC);
+  eassert (fd < MAXDESC);
   delete_keyboard_wait_descriptor (fd);
 
   fd_callback_info[fd].condition &= ~FOR_READ;
@@ -385,7 +382,7 @@ delete_read_fd (int fd)
 void
 add_write_fd (int fd, fd_callback func, void *data)
 {
-  xassert (fd < MAXDESC);
+  eassert (fd < MAXDESC);
   FD_SET (fd, &write_mask);
   if (fd > max_input_desc)
     max_input_desc = fd;
@@ -402,7 +399,7 @@ delete_write_fd (int fd)
 {
   int lim = max_input_desc;
 
-  xassert (fd < MAXDESC);
+  eassert (fd < MAXDESC);
   FD_CLR (fd, &write_mask);
   fd_callback_info[fd].condition &= ~FOR_WRITE;
   if (fd_callback_info[fd].condition == 0)
@@ -431,7 +428,7 @@ static void
 update_status (struct Lisp_Process *p)
 {
   eassert (p->raw_status_new);
-  p->status = status_convert (p->raw_status);
+  PVAR (p, status) = status_convert (p->raw_status);
   p->raw_status_new = 0;
 }
 
@@ -482,7 +479,7 @@ decode_status (Lisp_Object l, Lisp_Object *symbol, int *code, int *coredump)
 static Lisp_Object
 status_message (struct Lisp_Process *p)
 {
-  Lisp_Object status = p->status;
+  Lisp_Object status = PVAR (p, status);
   Lisp_Object symbol;
   int code, coredump;
   Lisp_Object string, string2;
@@ -500,7 +497,7 @@ status_message (struct Lisp_Process *p)
        {
          int c1, c2;
 
-         string = make_unibyte_string (signame, strlen (signame));
+         string = build_unibyte_string (signame);
          if (! NILP (Vlocale_coding_system))
            string = (code_convert_string_norecord
                      (string, Vlocale_coding_system, 0));
@@ -627,34 +624,18 @@ make_process (Lisp_Object name)
   printmax_t i;
 
   p = allocate_process ();
+  /* Initialize Lisp data.  Note that allocate_process initializes all
+     Lisp data to nil, so do it only for slots which should not be nil.  */
+  PVAR (p, status) = Qrun;
+  PVAR (p, mark) = Fmake_marker ();
 
+  /* Initialize non-Lisp data.  Note that allocate_process zeroes out all
+     non-Lisp data, so do it only for slots which should not be zero.  */
   p->infd = -1;
   p->outfd = -1;
-  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 ();
-  p->kill_without_query = 0;
-
-#ifdef ADAPTIVE_READ_BUFFERING
-  p->adaptive_read_buffering = 0;
-  p->read_output_delay = 0;
-  p->read_output_skip = 0;
-#endif
 
 #ifdef HAVE_GNUTLS
   p->gnutls_initstage = GNUTLS_STAGE_EMPTY;
-  /* Default log level.  */
-  p->gnutls_log_level = 0;
-  /* GnuTLS handshakes attempted for this connection.  */
-  p->gnutls_handshakes_tried = 0;
-  p->gnutls_p = 0;
-  p->gnutls_state = NULL;
-  p->gnutls_x509_cred = NULL;
-  p->gnutls_anon_cred = NULL;
 #endif
 
   /* If name is already in use, modify it until it is unused.  */
@@ -664,11 +645,10 @@ make_process (Lisp_Object name)
     {
       tem = Fget_process (name1);
       if (NILP (tem)) break;
-      sprintf (suffix, "<%"pMd">", i);
-      name1 = concat2 (name, build_string (suffix));
+      name1 = concat2 (name, make_formatted_string (suffix, "<%"pMd">", i));
     }
   name = name1;
-  p->name = name;
+  PVAR (p, name) = name;
   XSETPROCESS (val, p);
   Vprocess_alist = Fcons (Fcons (name, val), Vprocess_alist);
   return val;
@@ -765,7 +745,7 @@ nil, indicating the current buffer's process.  */)
   p->raw_status_new = 0;
   if (NETCONN1_P (p) || SERIALCONN1_P (p))
     {
-      p->status = Fcons (Qexit, Fcons (make_number (0), Qnil));
+      PVAR (p, status) = Fcons (Qexit, Fcons (make_number (0), Qnil));
       p->tick = ++process_tick;
       status_notify (p);
       redisplay_preserve_echo_area (13);
@@ -783,9 +763,9 @@ nil, indicating the current buffer's process.  */)
       /* If the process has already signaled, remove it from the list.  */
       if (p->raw_status_new)
        update_status (p);
-      symbol = p->status;
-      if (CONSP (p->status))
-       symbol = XCAR (p->status);
+      symbol = PVAR (p, status);
+      if (CONSP (PVAR (p, status)))
+       symbol = XCAR (PVAR (p, status));
       if (EQ (symbol, Qsignal) || EQ (symbol, Qexit))
        deleted_pid_list
          = Fdelete (make_fixnum_or_float (pid), deleted_pid_list);
@@ -794,7 +774,7 @@ nil, indicating the current buffer's process.  */)
        {
          Fkill_process (process, Qnil);
          /* Do this now, since remove_process will make sigchld_handler do nothing.  */
-         p->status
+         PVAR (p, status)
            = Fcons (Qsignal, Fcons (make_number (SIGKILL), Qnil));
          p->tick = ++process_tick;
          status_notify (p);
@@ -836,14 +816,14 @@ nil, indicating the current buffer's process.  */)
   p = XPROCESS (process);
   if (p->raw_status_new)
     update_status (p);
-  status = p->status;
+  status = PVAR (p, status);
   if (CONSP (status))
     status = XCAR (status);
   if (NETCONN1_P (p) || SERIALCONN1_P (p))
     {
       if (EQ (status, Qexit))
        status = Qclosed;
-      else if (EQ (p->command, Qt))
+      else if (EQ (PVAR (p, command), Qt))
        status = Qstop;
       else if (EQ (status, Qrun))
        status = Qopen;
@@ -860,8 +840,8 @@ If PROCESS has not yet exited or died, return 0.  */)
   CHECK_PROCESS (process);
   if (XPROCESS (process)->raw_status_new)
     update_status (XPROCESS (process));
-  if (CONSP (XPROCESS (process)->status))
-    return XCAR (XCDR (XPROCESS (process)->status));
+  if (CONSP (PVAR (XPROCESS (process), status)))
+    return XCAR (XCDR (PVAR (XPROCESS (process), status)));
   return make_number (0);
 }
 
@@ -885,7 +865,7 @@ possibly modified to make it unique among process names.  */)
   (register Lisp_Object process)
 {
   CHECK_PROCESS (process);
-  return XPROCESS (process)->name;
+  return PVAR (XPROCESS (process), name);
 }
 
 DEFUN ("process-command", Fprocess_command, Sprocess_command, 1, 1, 0,
@@ -897,7 +877,7 @@ For a network or serial process, this is nil (process is running) or t
   (register Lisp_Object process)
 {
   CHECK_PROCESS (process);
-  return XPROCESS (process)->command;
+  return PVAR (XPROCESS (process), command);
 }
 
 DEFUN ("process-tty-name", Fprocess_tty_name, Sprocess_tty_name, 1, 1, 0,
@@ -907,7 +887,7 @@ not the name of the pty that Emacs uses to talk with that terminal.  */)
   (register Lisp_Object process)
 {
   CHECK_PROCESS (process);
-  return XPROCESS (process)->tty_name;
+  return PVAR (XPROCESS (process), tty_name);
 }
 
 DEFUN ("set-process-buffer", Fset_process_buffer, Sset_process_buffer,
@@ -922,9 +902,9 @@ Return BUFFER.  */)
   if (!NILP (buffer))
     CHECK_BUFFER (buffer);
   p = XPROCESS (process);
-  p->buffer = buffer;
+  PVAR (p, buffer) = buffer;
   if (NETCONN1_P (p) || SERIALCONN1_P (p))
-    p->childp = Fplist_put (p->childp, QCbuffer, buffer);
+    PVAR (p, childp) = Fplist_put (PVAR (p, childp), QCbuffer, buffer);
   setup_process_coding_systems (process);
   return buffer;
 }
@@ -936,7 +916,7 @@ Output from PROCESS is inserted in this buffer unless PROCESS has a filter.  */)
   (register Lisp_Object process)
 {
   CHECK_PROCESS (process);
-  return XPROCESS (process)->buffer;
+  return PVAR (XPROCESS (process), buffer);
 }
 
 DEFUN ("process-mark", Fprocess_mark, Sprocess_mark,
@@ -945,7 +925,7 @@ DEFUN ("process-mark", Fprocess_mark, Sprocess_mark,
   (register Lisp_Object process)
 {
   CHECK_PROCESS (process);
-  return XPROCESS (process)->mark;
+  return PVAR (XPROCESS (process), mark);
 }
 
 DEFUN ("set-process-filter", Fset_process_filter, Sset_process_filter,
@@ -981,23 +961,23 @@ The string argument is normally a multibyte string, except:
 
   if (p->infd >= 0)
     {
-      if (EQ (filter, Qt) && !EQ (p->status, Qlisten))
+      if (EQ (filter, Qt) && !EQ (PVAR (p, status), Qlisten))
        {
          FD_CLR (p->infd, &input_wait_mask);
          FD_CLR (p->infd, &non_keyboard_wait_mask);
        }
-      else if (EQ (p->filter, Qt)
+      else if (EQ (PVAR (p, filter), Qt)
               /* Network or serial process not stopped:  */
-              && !EQ (p->command, Qt))
+              && !EQ (PVAR (p, command), Qt))
        {
          FD_SET (p->infd, &input_wait_mask);
          FD_SET (p->infd, &non_keyboard_wait_mask);
        }
     }
 
-  p->filter = filter;
+  PVAR (p, filter) = filter;
   if (NETCONN1_P (p) || SERIALCONN1_P (p))
-    p->childp = Fplist_put (p->childp, QCfilter, filter);
+    PVAR (p, childp) = Fplist_put (PVAR (p, childp), QCfilter, filter);
   setup_process_coding_systems (process);
   return filter;
 }
@@ -1009,7 +989,7 @@ See `set-process-filter' for more info on filter functions.  */)
   (register Lisp_Object process)
 {
   CHECK_PROCESS (process);
-  return XPROCESS (process)->filter;
+  return PVAR (XPROCESS (process), filter);
 }
 
 DEFUN ("set-process-sentinel", Fset_process_sentinel, Sset_process_sentinel,
@@ -1024,9 +1004,9 @@ It gets two arguments: the process, and a string describing the change.  */)
   CHECK_PROCESS (process);
   p = XPROCESS (process);
 
-  p->sentinel = sentinel;
+  PVAR (p, sentinel) = sentinel;
   if (NETCONN1_P (p) || SERIALCONN1_P (p))
-    p->childp = Fplist_put (p->childp, QCsentinel, sentinel);
+    PVAR (p, childp) = Fplist_put (PVAR (p, childp), QCsentinel, sentinel);
   return sentinel;
 }
 
@@ -1037,7 +1017,7 @@ See `set-process-sentinel' for more info on sentinels.  */)
   (register Lisp_Object process)
 {
   CHECK_PROCESS (process);
-  return XPROCESS (process)->sentinel;
+  return PVAR (XPROCESS (process), sentinel);
 }
 
 DEFUN ("set-process-window-size", Fset_process_window_size,
@@ -1046,8 +1026,8 @@ DEFUN ("set-process-window-size", Fset_process_window_size,
   (register Lisp_Object process, Lisp_Object height, Lisp_Object width)
 {
   CHECK_PROCESS (process);
-  CHECK_RANGED_INTEGER (0, height, INT_MAX);
-  CHECK_RANGED_INTEGER (0, width, INT_MAX);
+  CHECK_RANGED_INTEGER (height, 0, INT_MAX);
+  CHECK_RANGED_INTEGER (width, 0, INT_MAX);
 
   if (XPROCESS (process)->infd < 0
       || set_window_size (XPROCESS (process)->infd,
@@ -1107,10 +1087,6 @@ DEFUN ("process-query-on-exit-flag",
   return (XPROCESS (process)->kill_without_query ? Qnil : Qt);
 }
 
-#ifdef DATAGRAM_SOCKETS
-static Lisp_Object Fprocess_datagram_address (Lisp_Object);
-#endif
-
 DEFUN ("process-contact", Fprocess_contact, Sprocess_contact,
        1, 2, 0,
        doc: /* Return the contact info of PROCESS; t for a real child.
@@ -1126,7 +1102,7 @@ list of keywords.  */)
   Lisp_Object contact;
 
   CHECK_PROCESS (process);
-  contact = XPROCESS (process)->childp;
+  contact = PVAR (XPROCESS (process), childp);
 
 #ifdef DATAGRAM_SOCKETS
   if (DATAGRAM_CONN_P (process)
@@ -1152,7 +1128,7 @@ DEFUN ("process-plist", Fprocess_plist, Sprocess_plist,
   (register Lisp_Object process)
 {
   CHECK_PROCESS (process);
-  return XPROCESS (process)->plist;
+  return PVAR (XPROCESS (process), plist);
 }
 
 DEFUN ("set-process-plist", Fset_process_plist, Sset_process_plist,
@@ -1163,7 +1139,7 @@ DEFUN ("set-process-plist", Fset_process_plist, Sset_process_plist,
   CHECK_PROCESS (process);
   CHECK_LIST (plist);
 
-  XPROCESS (process)->plist = plist;
+  PVAR (XPROCESS (process), plist) = plist;
   return plist;
 }
 
@@ -1175,7 +1151,7 @@ The value is nil for a pipe, t or `pty' for a pty, or `stream' for
 a socket connection.  */)
   (Lisp_Object process)
 {
-  return XPROCESS (process)->type;
+  return PVAR (XPROCESS (process), type);
 }
 #endif
 
@@ -1188,7 +1164,7 @@ nil, indicating the current buffer's process.  */)
 {
   Lisp_Object proc;
   proc = get_process (process);
-  return XPROCESS (proc)->type;
+  return PVAR (XPROCESS (proc), type);
 }
 
 DEFUN ("format-network-address", Fformat_network_address, Sformat_network_address,
@@ -1349,13 +1325,13 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)  */)
      itself; it's all taken care of here.  */
   record_unwind_protect (start_process_unwind, proc);
 
-  XPROCESS (proc)->childp = Qt;
-  XPROCESS (proc)->plist = Qnil;
-  XPROCESS (proc)->type = Qreal;
-  XPROCESS (proc)->buffer = buffer;
-  XPROCESS (proc)->sentinel = Qnil;
-  XPROCESS (proc)->filter = Qnil;
-  XPROCESS (proc)->command = Flist (nargs - 2, args + 2);
+  PVAR (XPROCESS (proc), childp) = Qt;
+  PVAR (XPROCESS (proc), plist) = Qnil;
+  PVAR (XPROCESS (proc), type) = Qreal;
+  PVAR (XPROCESS (proc), buffer) = buffer;
+  PVAR (XPROCESS (proc), sentinel) = Qnil;
+  PVAR (XPROCESS (proc), filter) = Qnil;
+  PVAR (XPROCESS (proc), command) = Flist (nargs - 2, args + 2);
 
 #ifdef HAVE_GNUTLS
   /* AKA GNUTLS_INITSTAGE(proc).  */
@@ -1371,7 +1347,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)  */)
 
   /* Make the process marker point into the process buffer (if any).  */
   if (BUFFERP (buffer))
-    set_marker_both (XPROCESS (proc)->mark, buffer,
+    set_marker_both (PVAR (XPROCESS (proc), mark), buffer,
                     BUF_ZV (XBUFFER (buffer)),
                     BUF_ZV_BYTE (XBUFFER (buffer)));
 
@@ -1388,7 +1364,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)  */)
     val = Vcoding_system_for_read;
     if (NILP (val))
       {
-       args2 = (Lisp_Object *) alloca ((nargs + 1) * sizeof *args2);
+       args2 = alloca ((nargs + 1) * sizeof *args2);
        args2[0] = Qstart_process;
        for (i = 0; i < nargs; i++) args2[i + 1] = args[i];
        GCPRO2 (proc, current_dir);
@@ -1400,14 +1376,14 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)  */)
        else if (CONSP (Vdefault_process_coding_system))
          val = XCAR (Vdefault_process_coding_system);
       }
-    XPROCESS (proc)->decode_coding_system = val;
+    PVAR (XPROCESS (proc), decode_coding_system) = val;
 
     val = Vcoding_system_for_write;
     if (NILP (val))
       {
        if (EQ (coding_systems, Qt))
          {
-           args2 = (Lisp_Object *) alloca ((nargs + 1) * sizeof *args2);
+           args2 = alloca ((nargs + 1) * sizeof *args2);
            args2[0] = Qstart_process;
            for (i = 0; i < nargs; i++) args2[i + 1] = args[i];
            GCPRO2 (proc, current_dir);
@@ -1420,7 +1396,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)  */)
        else if (CONSP (Vdefault_process_coding_system))
          val = XCDR (Vdefault_process_coding_system);
       }
-    XPROCESS (proc)->encode_coding_system = val;
+    PVAR (XPROCESS (proc), encode_coding_system) = val;
     /* Note: At this moment, the above coding system may leave
        text-conversion or eol-conversion unspecified.  They will be
        decided after we read output from the process and decode it by
@@ -1429,9 +1405,9 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)  */)
   }
 
 
-  XPROCESS (proc)->decoding_buf = empty_unibyte_string;
+  PVAR (XPROCESS (proc), decoding_buf) = empty_unibyte_string;
   XPROCESS (proc)->decoding_carryover = 0;
-  XPROCESS (proc)->encoding_buf = empty_unibyte_string;
+  PVAR (XPROCESS (proc), encoding_buf) = empty_unibyte_string;
 
   XPROCESS (proc)->inherit_coding_system_flag
     = !(NILP (buffer) || !inherit_process_coding_system);
@@ -1489,7 +1465,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)  */)
              {
                if (NILP (arg_encoding))
                  arg_encoding = (complement_process_encoding_system
-                                 (XPROCESS (proc)->encode_coding_system));
+                                 (PVAR (XPROCESS (proc), encode_coding_system)));
                XSETCAR (tem,
                         code_convert_string_norecord
                         (XCAR (tem), arg_encoding, 1));
@@ -1501,7 +1477,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)  */)
 
       /* Now that everything is encoded we can collect the strings into
         NEW_ARGV.  */
-      new_argv = (unsigned char **) alloca ((nargs - 1) * sizeof (char *));
+      new_argv = alloca ((nargs - 1) * sizeof *new_argv);
       new_argv[nargs - 2] = 0;
 
       for (i = nargs - 2; i-- != 0; )
@@ -1653,7 +1629,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
      more portable (see USG_SUBTTY_WORKS above).  */
 
   XPROCESS (process)->pty_flag = pty_flag;
-  XPROCESS (process)->status = Qrun;
+  PVAR (XPROCESS (process), status) = Qrun;
 
   /* Delay interrupts until we have a chance to store
      the new fork's pid in its process structure */
@@ -1875,10 +1851,9 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
         So have an interrupt jar it loose.  */
       {
        struct atimer *timer;
-       EMACS_TIME offset;
+       EMACS_TIME offset = make_emacs_time (1, 0);
 
        stop_polling ();
-       EMACS_SET_SECS_USECS (offset, 1, 0);
        timer = start_atimer (ATIMER_RELATIVE, offset, create_process_1, 0);
 
        if (forkin >= 0)
@@ -1893,10 +1868,10 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
 
 #ifdef HAVE_PTYS
       if (pty_flag)
-       XPROCESS (process)->tty_name = build_string (pty_name);
+       PVAR (XPROCESS (process), tty_name) = build_string (pty_name);
       else
 #endif
-       XPROCESS (process)->tty_name = Qnil;
+       PVAR (XPROCESS (process), tty_name) = Qnil;
 
 #if !defined (WINDOWSNT) && defined (FD_CLOEXEC)
       /* Wait for child_setup to complete in case that vfork is
@@ -1991,7 +1966,7 @@ create_pty (Lisp_Object process)
      more portable (see USG_SUBTTY_WORKS above).  */
 
   XPROCESS (process)->pty_flag = pty_flag;
-  XPROCESS (process)->status = Qrun;
+  PVAR (XPROCESS (process), status) = Qrun;
   setup_process_coding_systems (process);
 
   FD_SET (inchannel, &input_wait_mask);
@@ -2002,10 +1977,10 @@ create_pty (Lisp_Object process)
   XPROCESS (process)->pid = -2;
 #ifdef HAVE_PTYS
   if (pty_flag)
-    XPROCESS (process)->tty_name = build_string (pty_name);
+    PVAR (XPROCESS (process), tty_name) = build_string (pty_name);
   else
 #endif
-    XPROCESS (process)->tty_name = Qnil;
+    PVAR (XPROCESS (process), tty_name) = Qnil;
 }
 
 \f
@@ -2394,7 +2369,7 @@ OPTION is not a supported option, return nil instead; otherwise return t.  */)
 
   if (set_socket_option (s, option, value))
     {
-      p->childp = Fplist_put (p->childp, option, value);
+      PVAR (p, childp) = Fplist_put (PVAR (p, childp), option, value);
       return Qt;
     }
 
@@ -2483,10 +2458,10 @@ usage: (serial-process-configure &rest ARGS)  */)
     proc = Fplist_get (contact, QCport);
   proc = get_process (proc);
   p = XPROCESS (proc);
-  if (!EQ (p->type, Qserial))
+  if (!EQ (PVAR (p, type), Qserial))
     error ("Not a serial process");
 
-  if (NILP (Fplist_get (p->childp, QCspeed)))
+  if (NILP (Fplist_get (PVAR (p, childp), QCspeed)))
     {
       UNGCPRO;
       return Qnil;
@@ -2627,21 +2602,21 @@ usage:  (make-serial-process &rest ARGS)  */)
   if (NILP (buffer))
     buffer = name;
   buffer = Fget_buffer_create (buffer);
-  p->buffer = buffer;
-
-  p->childp = contact;
-  p->plist = Fcopy_sequence (Fplist_get (contact, QCplist));
-  p->type = Qserial;
-  p->sentinel = Fplist_get (contact, QCsentinel);
-  p->filter = Fplist_get (contact, QCfilter);
-  p->log = Qnil;
+  PVAR (p, buffer) = buffer;
+
+  PVAR (p, childp) = contact;
+  PVAR (p, plist) = Fcopy_sequence (Fplist_get (contact, QCplist));
+  PVAR (p, type) = Qserial;
+  PVAR (p, sentinel) = Fplist_get (contact, QCsentinel);
+  PVAR (p, filter) = Fplist_get (contact, QCfilter);
+  PVAR (p, log) = Qnil;
   if (tem = Fplist_get (contact, QCnoquery), !NILP (tem))
     p->kill_without_query = 1;
   if (tem = Fplist_get (contact, QCstop), !NILP (tem))
-    p->command = Qt;
+    PVAR (p, command) = Qt;
   p->pty_flag = 0;
 
-  if (!EQ (p->command, Qt))
+  if (!EQ (PVAR (p, command), Qt))
     {
       FD_SET (fd, &input_wait_mask);
       FD_SET (fd, &non_keyboard_wait_mask);
@@ -2649,7 +2624,7 @@ usage:  (make-serial-process &rest ARGS)  */)
 
   if (BUFFERP (buffer))
     {
-      set_marker_both (p->mark, buffer,
+      set_marker_both (PVAR (p, mark), buffer,
                       BUF_ZV (XBUFFER (buffer)),
                       BUF_ZV_BYTE (XBUFFER (buffer)));
     }
@@ -2670,7 +2645,7 @@ usage:  (make-serial-process &rest ARGS)  */)
   else if ((!NILP (buffer) && NILP (BVAR (XBUFFER (buffer), enable_multibyte_characters)))
           || (NILP (buffer) && NILP (BVAR (&buffer_defaults, enable_multibyte_characters))))
     val = Qnil;
-  p->decode_coding_system = val;
+  PVAR (p, decode_coding_system) = val;
 
   val = Qnil;
   if (!NILP (tem))
@@ -2684,12 +2659,12 @@ usage:  (make-serial-process &rest ARGS)  */)
   else if ((!NILP (buffer) && NILP (BVAR (XBUFFER (buffer), enable_multibyte_characters)))
           || (NILP (buffer) && NILP (BVAR (&buffer_defaults, enable_multibyte_characters))))
     val = Qnil;
-  p->encode_coding_system = val;
+  PVAR (p, encode_coding_system) = val;
 
   setup_process_coding_systems (proc);
-  p->decoding_buf = empty_unibyte_string;
+  PVAR (p, decoding_buf) = empty_unibyte_string;
   p->decoding_carryover = 0;
-  p->encoding_buf = empty_unibyte_string;
+  PVAR (p, encoding_buf) = empty_unibyte_string;
   p->inherit_coding_system_flag
     = !(!NILP (tem) || NILP (buffer) || !inherit_process_coding_system);
 
@@ -3037,7 +3012,9 @@ usage: (make-network-process &rest ARGS)  */)
       CHECK_STRING (service);
       memset (&address_un, 0, sizeof address_un);
       address_un.sun_family = AF_LOCAL;
-      strncpy (address_un.sun_path, SSDATA (service), sizeof address_un.sun_path);
+      if (sizeof address_un.sun_path <= SBYTES (service))
+       error ("Service name too long");
+      strcpy (address_un.sun_path, SSDATA (service));
       ai.ai_addr = (struct sockaddr *) &address_un;
       ai.ai_addrlen = sizeof address_un;
       goto open_socket;
@@ -3290,7 +3267,7 @@ usage: (make-network-process &rest ARGS)  */)
        {
          /* Unlike most other syscalls connect() cannot be called
             again.  (That would return EALREADY.)  The proper way to
-            wait for completion is select(). */
+            wait for completion is pselect(). */
          int sc;
          socklen_t len;
          SELECT_TYPE fdset;
@@ -3298,8 +3275,7 @@ usage: (make-network-process &rest ARGS)  */)
          FD_ZERO (&fdset);
          FD_SET (s, &fdset);
          QUIT;
-         sc = select (s + 1, (SELECT_TYPE *)0, &fdset, (SELECT_TYPE *)0,
-                      (EMACS_TIME *)0);
+         sc = pselect (s + 1, NULL, &fdset, NULL, NULL, NULL);
          if (sc == -1)
            {
              if (errno == EINTR)
@@ -3340,7 +3316,7 @@ usage: (make-network-process &rest ARGS)  */)
        {
          if (datagram_address[s].sa)
            abort ();
-         datagram_address[s].sa = (struct sockaddr *) xmalloc (lres->ai_addrlen);
+         datagram_address[s].sa = xmalloc (lres->ai_addrlen);
          datagram_address[s].len = lres->ai_addrlen;
          if (is_server)
            {
@@ -3425,27 +3401,27 @@ usage: (make-network-process &rest ARGS)  */)
 
   p = XPROCESS (proc);
 
-  p->childp = contact;
-  p->plist = Fcopy_sequence (Fplist_get (contact, QCplist));
-  p->type = Qnetwork;
+  PVAR (p, childp) = contact;
+  PVAR (p, plist) = Fcopy_sequence (Fplist_get (contact, QCplist));
+  PVAR (p, type) = Qnetwork;
 
-  p->buffer = buffer;
-  p->sentinel = sentinel;
-  p->filter = filter;
-  p->log = Fplist_get (contact, QClog);
+  PVAR (p, buffer) = buffer;
+  PVAR (p, sentinel) = sentinel;
+  PVAR (p, filter) = filter;
+  PVAR (p, log) = Fplist_get (contact, QClog);
   if (tem = Fplist_get (contact, QCnoquery), !NILP (tem))
     p->kill_without_query = 1;
   if ((tem = Fplist_get (contact, QCstop), !NILP (tem)))
-    p->command = Qt;
+    PVAR (p, command) = Qt;
   p->pid = 0;
   p->infd  = inch;
   p->outfd = outch;
   if (is_server && socktype != SOCK_DGRAM)
-    p->status = Qlisten;
+    PVAR (p, status) = Qlisten;
 
   /* Make the process marker point into the process buffer (if any).  */
   if (BUFFERP (buffer))
-    set_marker_both (p->mark, buffer,
+    set_marker_both (PVAR (p, mark), buffer,
                     BUF_ZV (XBUFFER (buffer)),
                     BUF_ZV_BYTE (XBUFFER (buffer)));
 
@@ -3455,7 +3431,7 @@ usage: (make-network-process &rest ARGS)  */)
       /* We may get here if connect did succeed immediately.  However,
         in that case, we still need to signal this like a non-blocking
         connection.  */
-      p->status = Qconnect;
+      PVAR (p, status) = Qconnect;
       if (!FD_ISSET (inch, &connect_wait_mask))
        {
          FD_SET (inch, &connect_wait_mask);
@@ -3467,8 +3443,8 @@ usage: (make-network-process &rest ARGS)  */)
 #endif
     /* A server may have a client filter setting of Qt, but it must
        still listen for incoming connects unless it is stopped.  */
-    if ((!EQ (p->filter, Qt) && !EQ (p->command, Qt))
-       || (EQ (p->status, Qlisten) && NILP (p->command)))
+    if ((!EQ (PVAR (p, filter), Qt) && !EQ (PVAR (p, command), Qt))
+       || (EQ (PVAR (p, status), Qlisten) && NILP (PVAR (p, command))))
       {
        FD_SET (inch, &input_wait_mask);
        FD_SET (inch, &non_keyboard_wait_mask);
@@ -3522,7 +3498,7 @@ usage: (make-network-process &rest ARGS)  */)
        else
          val = Qnil;
       }
-    p->decode_coding_system = val;
+    PVAR (p, decode_coding_system) = val;
 
     if (!NILP (tem))
       {
@@ -3556,13 +3532,13 @@ usage: (make-network-process &rest ARGS)  */)
        else
          val = Qnil;
       }
-    p->encode_coding_system = val;
+    PVAR (p, encode_coding_system) = val;
   }
   setup_process_coding_systems (proc);
 
-  p->decoding_buf = empty_unibyte_string;
+  PVAR (p, decoding_buf) = empty_unibyte_string;
   p->decoding_carryover = 0;
-  p->encoding_buf = empty_unibyte_string;
+  PVAR (p, encoding_buf) = empty_unibyte_string;
 
   p->inherit_coding_system_flag
     = !(!NILP (tem) || NILP (buffer) || !inherit_process_coding_system);
@@ -3742,8 +3718,9 @@ FLAGS is the current flags of the interface.  */)
 
   CHECK_STRING (ifname);
 
-  memset (rq.ifr_name, 0, sizeof rq.ifr_name);
-  strncpy (rq.ifr_name, SSDATA (ifname), sizeof (rq.ifr_name));
+  if (sizeof rq.ifr_name <= SBYTES (ifname))
+    error ("interface name too long");
+  strcpy (rq.ifr_name, SSDATA (ifname));
 
   s = socket (AF_INET, SOCK_STREAM, 0);
   if (s < 0)
@@ -3960,7 +3937,8 @@ If JUST-THIS-ONE is an integer, don't run any timers either.
 Return non-nil if we received any output before the timeout expired.  */)
   (register Lisp_Object process, Lisp_Object seconds, Lisp_Object millisec, Lisp_Object just_this_one)
 {
-  int secs = -1, usecs = 0;
+  intmax_t secs;
+  int nsecs;
 
   if (! NILP (process))
     CHECK_PROCESS (process);
@@ -3979,17 +3957,36 @@ Return non-nil if we received any output before the timeout expired.  */)
        }
     }
 
+  secs = 0;
+  nsecs = -1;
+
   if (!NILP (seconds))
     {
-      double duration = extract_float (seconds);
-      if (0 < duration)
-       duration_to_sec_usec (duration, &secs, &usecs);
+      if (INTEGERP (seconds))
+       {
+         if (0 < XINT (seconds))
+           {
+             secs = XINT (seconds);
+             nsecs = 0;
+           }
+       }
+      else if (FLOATP (seconds))
+       {
+         if (0 < XFLOAT_DATA (seconds))
+           {
+             EMACS_TIME t = EMACS_TIME_FROM_DOUBLE (XFLOAT_DATA (seconds));
+             secs = min (EMACS_SECS (t), WAIT_READING_MAX);
+             nsecs = EMACS_NSECS (t);
+           }
+       }
+      else
+       wrong_type_argument (Qnumberp, seconds);
     }
-  else if (!NILP (process))
-    secs = 0;
+  else if (! NILP (process))
+    nsecs = 0;
 
   return
-    (wait_reading_process_output (secs, usecs, 0, 0,
+    (wait_reading_process_output (secs, nsecs, 0, 0,
                                  Qnil,
                                  !NILP (process) ? XPROCESS (process) : NULL,
                                  NILP (just_this_one) ? 0 :
@@ -4034,8 +4031,8 @@ server_accept_connection (Lisp_Object server, int channel)
        return;
 #endif
 
-      if (!NILP (ps->log))
-       call3 (ps->log, server, Qnil,
+      if (!NILP (PVAR (ps, log)))
+       call3 (PVAR (ps, log), server, Qnil,
               concat3 (build_string ("accept failed with code"),
                        Fnumber_to_string (make_number (code)),
                        build_string ("\n")));
@@ -4105,15 +4102,15 @@ server_accept_connection (Lisp_Object server, int channel)
      process name of the server process concatenated with the caller
      identification.  */
 
-  if (!NILP (ps->filter) && !EQ (ps->filter, Qt))
+  if (!NILP (PVAR (ps, filter)) && !EQ (PVAR (ps, filter), Qt))
     buffer = Qnil;
   else
     {
-      buffer = ps->buffer;
+      buffer = PVAR (ps, buffer);
       if (!NILP (buffer))
        buffer = Fbuffer_name (buffer);
       else
-       buffer = ps->name;
+       buffer = PVAR (ps, name);
       if (!NILP (buffer))
        {
          buffer = concat2 (buffer, caller);
@@ -4124,7 +4121,7 @@ server_accept_connection (Lisp_Object server, int channel)
   /* Generate a unique name for the new server process.  Combine the
      server process name with the caller identification.  */
 
-  name = concat2 (ps->name, caller);
+  name = concat2 (PVAR (ps, name), caller);
   proc = make_process (name);
 
   chan_process[s] = proc;
@@ -4140,7 +4137,7 @@ server_accept_connection (Lisp_Object server, int channel)
   p = XPROCESS (proc);
 
   /* Build new contact information for this setup.  */
-  contact = Fcopy_sequence (ps->childp);
+  contact = Fcopy_sequence (PVAR (ps, childp));
   contact = Fplist_put (contact, QCserver, Qnil);
   contact = Fplist_put (contact, QChost, host);
   if (!NILP (service))
@@ -4154,21 +4151,21 @@ server_accept_connection (Lisp_Object server, int channel)
                          conv_sockaddr_to_lisp (&saddr.sa, len));
 #endif
 
-  p->childp = contact;
-  p->plist = Fcopy_sequence (ps->plist);
-  p->type = Qnetwork;
+  PVAR (p, childp) = contact;
+  PVAR (p, plist) = Fcopy_sequence (PVAR (ps, plist));
+  PVAR (p, type) = Qnetwork;
 
-  p->buffer = buffer;
-  p->sentinel = ps->sentinel;
-  p->filter = ps->filter;
-  p->command = Qnil;
+  PVAR (p, buffer) = buffer;
+  PVAR (p, sentinel) = PVAR (ps, sentinel);
+  PVAR (p, filter) = PVAR (ps, filter);
+  PVAR (p, command) = Qnil;
   p->pid = 0;
   p->infd  = s;
   p->outfd = s;
-  p->status = Qrun;
+  PVAR (p, status) = Qrun;
 
   /* Client processes for accepted connections are not stopped initially.  */
-  if (!EQ (p->filter, Qt))
+  if (!EQ (PVAR (p, filter), Qt))
     {
       FD_SET (s, &input_wait_mask);
       FD_SET (s, &non_keyboard_wait_mask);
@@ -4182,24 +4179,24 @@ server_accept_connection (Lisp_Object server, int channel)
      of the new process should reflect the settings at the time the
      server socket was opened; not the current settings. */
 
-  p->decode_coding_system = ps->decode_coding_system;
-  p->encode_coding_system = ps->encode_coding_system;
+  PVAR (p, decode_coding_system) = PVAR (ps, decode_coding_system);
+  PVAR (p, encode_coding_system) = PVAR (ps, encode_coding_system);
   setup_process_coding_systems (proc);
 
-  p->decoding_buf = empty_unibyte_string;
+  PVAR (p, decoding_buf) = empty_unibyte_string;
   p->decoding_carryover = 0;
-  p->encoding_buf = empty_unibyte_string;
+  PVAR (p, encoding_buf) = empty_unibyte_string;
 
   p->inherit_coding_system_flag
     = (NILP (buffer) ? 0 : ps->inherit_coding_system_flag);
 
-  if (!NILP (ps->log))
-      call3 (ps->log, server, proc,
+  if (!NILP (PVAR (ps, log)))
+      call3 (PVAR (ps, log), server, proc,
             concat3 (build_string ("accept from "),
                      (STRINGP (host) ? host : build_string ("-")),
                      build_string ("\n")));
 
-  if (!NILP (p->sentinel))
+  if (!NILP (PVAR (p, sentinel)))
     exec_sentinel (proc,
                   concat3 (build_string ("open from "),
                            (STRINGP (host) ? host : build_string ("-")),
@@ -4230,36 +4227,21 @@ wait_reading_process_output_1 (void)
 {
 }
 
-/* Use a wrapper around select to work around a bug in gdb 5.3.
-   Normally, the wrapper is optimized away by inlining.
-
-   If emacs is stopped inside select, the gdb backtrace doesn't
-   show the function which called select, so it is practically
-   impossible to step through wait_reading_process_output.  */
-
-#ifndef select
-static inline int
-select_wrapper (int n, fd_set *rfd, fd_set *wfd, fd_set *xfd, struct timeval *tmo)
-{
-  return select (n, rfd, wfd, xfd, tmo);
-}
-#define select select_wrapper
-#endif
-
 /* Read and dispose of subprocess output while waiting for timeout to
    elapse and/or keyboard input to be available.
 
    TIME_LIMIT is:
-     timeout in seconds, or
-     zero for no limit, or
-     -1 means gobble data immediately available but don't wait for any.
+     timeout in seconds
+     If negative, gobble data immediately available but don't wait for any.
 
-   MICROSECS is:
-     an additional duration to wait, measured in microseconds.
-     If this is nonzero and time_limit is 0, then the timeout
-     consists of MICROSECS only.
+   NSECS is:
+     an additional duration to wait, measured in nanoseconds
+     If TIME_LIMIT is zero, then:
+       If NSECS == 0, there is no limit.
+       If NSECS > 0, the timeout consists of NSECS only.
+       If NSECS < 0, gobble data immediately, as if TIME_LIMIT were negative.
 
-   READ_KBD is a lisp value:
+   READ_KBD is:
      0 to ignore keyboard input, or
      1 to return when input is available, or
      -1 meaning caller will actually read the input, so don't throw to
@@ -4284,7 +4266,7 @@ select_wrapper (int n, fd_set *rfd, fd_set *wfd, fd_set *xfd, struct timeval *tm
    Otherwise, return true if we received input from any process.  */
 
 int
-wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
+wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
                             int do_display,
                             Lisp_Object wait_for_cell,
                             struct Lisp_Process *wait_proc, int just_wait_proc)
@@ -4304,8 +4286,9 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
   FD_ZERO (&Available);
   FD_ZERO (&Writeok);
 
-  if (time_limit == 0 && microsecs == 0 && wait_proc && !NILP (Vinhibit_quit)
-      && !(CONSP (wait_proc->status) && EQ (XCAR (wait_proc->status), Qexit)))
+  if (time_limit == 0 && nsecs == 0 && wait_proc && !NILP (Vinhibit_quit)
+      && !(CONSP (PVAR (wait_proc, status)) 
+          && EQ (XCAR (PVAR (wait_proc, status)), Qexit)))
     message ("Blocking call to accept-process-output with quit inhibited!!");
 
   /* If wait_proc is a process to watch, set wait_channel accordingly.  */
@@ -4316,13 +4299,20 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
                         make_number (waiting_for_user_input_p));
   waiting_for_user_input_p = read_kbd;
 
+  if (time_limit < 0)
+    {
+      time_limit = 0;
+      nsecs = -1;
+    }
+  else if (TYPE_MAXIMUM (time_t) < time_limit)
+    time_limit = TYPE_MAXIMUM (time_t);
+
   /* Since we may need to wait several times,
      compute the absolute time to return at.  */
-  if (time_limit || microsecs)
+  if (time_limit || 0 < nsecs)
     {
-      EMACS_GET_TIME (end_time);
-      EMACS_SET_SECS_USECS (timeout, time_limit, microsecs);
-      EMACS_ADD_TIME (end_time, end_time, timeout);
+      timeout = make_emacs_time (time_limit, nsecs);
+      end_time = add_emacs_time (current_emacs_time (), timeout);
     }
 
   while (1)
@@ -4345,24 +4335,24 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
 
       /* Compute time from now till when time limit is up */
       /* Exit if already run out */
-      if (time_limit == -1)
+      if (nsecs < 0)
        {
-         /* -1 specified for timeout means
+         /* A negative timeout means
             gobble output available now
             but don't wait at all. */
 
-         EMACS_SET_SECS_USECS (timeout, 0, 0);
+         timeout = make_emacs_time (0, 0);
        }
-      else if (time_limit || microsecs)
+      else if (time_limit || 0 < nsecs)
        {
-         EMACS_GET_TIME (timeout);
-         EMACS_SUB_TIME (timeout, end_time, timeout);
-         if (EMACS_TIME_NEG_P (timeout))
+         EMACS_TIME now = current_emacs_time ();
+         if (EMACS_TIME_LE (end_time, now))
            break;
+         timeout = sub_emacs_time (end_time, now);
        }
       else
        {
-         EMACS_SET_SECS_USECS (timeout, 100000, 0);
+         timeout = make_emacs_time (100000, 0);
        }
 
       /* Normally we run timers here.
@@ -4404,21 +4394,22 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
              && requeued_events_pending_p ())
            break;
 
-         if (! EMACS_TIME_NEG_P (timer_delay) && time_limit != -1)
+         /* A negative timeout means do not wait at all.  */
+         if (0 <= nsecs)
            {
-             EMACS_TIME difference;
-             EMACS_SUB_TIME (difference, timer_delay, timeout);
-             if (EMACS_TIME_NEG_P (difference))
+             if (EMACS_TIME_VALID_P (timer_delay))
                {
-                 timeout = timer_delay;
-                 timeout_reduced_for_timers = 1;
+                 if (EMACS_TIME_LT (timer_delay, timeout))
+                   {
+                     timeout = timer_delay;
+                     timeout_reduced_for_timers = 1;
+                   }
+               }
+             else
+               {
+                 /* This is so a breakpoint can be put here.  */
+                 wait_reading_process_output_1 ();
                }
-           }
-         /* If time_limit is -1, we are not going to wait at all.  */
-         else if (time_limit != -1)
-           {
-             /* This is so a breakpoint can be put here.  */
-             wait_reading_process_output_1 ();
            }
        }
 
@@ -4446,15 +4437,15 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
             Atemp = input_wait_mask;
          Ctemp = write_mask;
 
-         EMACS_SET_SECS_USECS (timeout, 0, 0);
-         if ((select (max (max_process_desc, max_input_desc) + 1,
-                      &Atemp,
+         timeout = make_emacs_time (0, 0);
+         if ((pselect (max (max_process_desc, max_input_desc) + 1,
+                       &Atemp,
 #ifdef NON_BLOCKING_CONNECT
-                      (num_pending_connects > 0 ? &Ctemp : (SELECT_TYPE *)0),
+                       (num_pending_connects > 0 ? &Ctemp : NULL),
 #else
-                      (SELECT_TYPE *)0,
+                       NULL,
 #endif
-                      (SELECT_TYPE *)0, &timeout)
+                       NULL, &timeout, NULL)
               <= 0))
            {
              /* It's okay for us to do this and then continue with
@@ -4470,8 +4461,8 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
       if (wait_proc && wait_proc->raw_status_new)
        update_status (wait_proc);
       if (wait_proc
-         && ! EQ (wait_proc->status, Qrun)
-         && ! EQ (wait_proc->status, Qconnect))
+         && ! EQ (PVAR (wait_proc, status), Qrun)
+         && ! EQ (PVAR (wait_proc, status), Qconnect))
        {
          int nread, total_nread = 0;
 
@@ -4577,9 +4568,9 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
             Vprocess_adaptive_read_buffering is nil.  */
          if (process_output_skip && check_delay > 0)
            {
-             int usecs = EMACS_USECS (timeout);
-             if (EMACS_SECS (timeout) > 0 || usecs > READ_OUTPUT_DELAY_MAX)
-               usecs = READ_OUTPUT_DELAY_MAX;
+             int nsecs = EMACS_NSECS (timeout);
+             if (EMACS_SECS (timeout) > 0 || nsecs > READ_OUTPUT_DELAY_MAX)
+               nsecs = READ_OUTPUT_DELAY_MAX;
              for (channel = 0; check_delay > 0 && channel <= max_process_desc; channel++)
                {
                  proc = chan_process[channel];
@@ -4594,11 +4585,11 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
                        continue;
                      FD_CLR (channel, &Available);
                      XPROCESS (proc)->read_output_skip = 0;
-                     if (XPROCESS (proc)->read_output_delay < usecs)
-                       usecs = XPROCESS (proc)->read_output_delay;
+                     if (XPROCESS (proc)->read_output_delay < nsecs)
+                       nsecs = XPROCESS (proc)->read_output_delay;
                    }
                }
-             EMACS_SET_SECS_USECS (timeout, 0, usecs);
+             timeout = make_emacs_time (0, nsecs);
              process_output_skip = 0;
            }
 #endif
@@ -4607,12 +4598,12 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
 #elif defined (HAVE_NS)
          nfds = ns_select
 #else
-         nfds = select
+         nfds = pselect
 #endif
             (max (max_process_desc, max_input_desc) + 1,
              &Available,
              (check_write ? &Writeok : (SELECT_TYPE *)0),
-             (SELECT_TYPE *)0, &timeout);
+             NULL, &timeout, NULL);
 
 #ifdef HAVE_GNUTLS
           /* GnuTLS buffers data internally.  In lowat mode it leaves
@@ -4670,8 +4661,8 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
       /*  If we woke up due to SIGWINCH, actually change size now.  */
       do_pending_window_change (0);
 
-      if (time_limit && nfds == 0 && ! timeout_reduced_for_timers)
-       /* We wanted the full specified time, so return now.  */
+      if ((time_limit || nsecs) && nfds == 0 && ! timeout_reduced_for_timers)
+       /* We waited the full specified time, so return now.  */
        break;
       if (nfds < 0)
        {
@@ -4822,7 +4813,7 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
              if (wait_channel == channel)
                {
                  wait_channel = -1;
-                 time_limit = -1;
+                 nsecs = -1;
                  got_some_input = 1;
                }
              proc = chan_process[channel];
@@ -4830,7 +4821,7 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
                continue;
 
              /* If this is a server stream socket, accept connection.  */
-             if (EQ (XPROCESS (proc)->status, Qlisten))
+             if (EQ (PVAR (XPROCESS (proc), status), Qlisten))
                {
                  server_accept_connection (proc, channel);
                  continue;
@@ -4899,7 +4890,7 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
                         wait3() will not find the process object to
                         delete.  Do it here.  */
                      p->tick = ++process_tick;
-                     p->status = Qfailed;
+                     PVAR (p, status) = Qfailed;
                    }
                   else
                    kill (getpid (), SIGCHLD);
@@ -4918,8 +4909,8 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
                  deactivate_process (proc);
                  if (XPROCESS (proc)->raw_status_new)
                    update_status (XPROCESS (proc));
-                 if (EQ (XPROCESS (proc)->status, Qrun))
-                   XPROCESS (proc)->status
+                 if (EQ (PVAR (XPROCESS (proc), status), Qrun))
+                   PVAR (XPROCESS (proc), status)
                      = Fcons (Qexit, Fcons (make_number (256), Qnil));
                }
            }
@@ -4968,17 +4959,18 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
              if (xerrno)
                {
                  p->tick = ++process_tick;
-                 p->status = Fcons (Qfailed, Fcons (make_number (xerrno), Qnil));
+                 PVAR (p, status) 
+                   = Fcons (Qfailed, Fcons (make_number (xerrno), Qnil));
                  deactivate_process (proc);
                }
              else
                {
-                 p->status = Qrun;
+                 PVAR (p, status) = Qrun;
                  /* Execute the sentinel here.  If we had relied on
                     status_notify to do it later, it will read input
                     from the process before calling the sentinel.  */
                  exec_sentinel (proc, build_string ("open\n"));
-                 if (!EQ (p->filter, Qt) && !EQ (p->command, Qt))
+                 if (!EQ (PVAR (p, filter), Qt) && !EQ (PVAR (p, command), Qt))
                    {
                      FD_SET (p->infd, &input_wait_mask);
                      FD_SET (p->infd, &non_keyboard_wait_mask);
@@ -5047,10 +5039,10 @@ read_process_output (Lisp_Object proc, register int channel)
   ptrdiff_t count = SPECPDL_INDEX ();
   Lisp_Object odeactivate;
 
-  chars = (char *) alloca (carryover + readmax);
+  chars = alloca (carryover + readmax);
   if (carryover)
     /* See the comment above.  */
-    memcpy (chars, SDATA (p->decoding_buf), carryover);
+    memcpy (chars, SDATA (PVAR (p, decoding_buf)), carryover);
 
 #ifdef DATAGRAM_SOCKETS
   /* We have a working select, so proc_buffered_char is always -1.  */
@@ -5129,7 +5121,7 @@ read_process_output (Lisp_Object proc, register int channel)
   record_unwind_protect (set_buffer_if_live, Fcurrent_buffer ());
 
   /* Read and dispose of the process output.  */
-  outstream = p->filter;
+  outstream = PVAR (p, filter);
   if (!NILP (outstream))
     {
       Lisp_Object text;
@@ -5171,9 +5163,9 @@ read_process_output (Lisp_Object proc, register int channel)
       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, Vlast_coding_system_used))
+      if (!EQ (PVAR (p, decode_coding_system), Vlast_coding_system_used))
        {
-         p->decode_coding_system = Vlast_coding_system_used;
+         PVAR (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
@@ -5186,21 +5178,21 @@ read_process_output (Lisp_Object proc, register int channel)
             proc_encode_coding_system[p->outfd] surely points to a
             valid memory because p->outfd will be changed once EOF is
             sent to the process.  */
-         if (NILP (p->encode_coding_system)
+         if (NILP (PVAR (p, encode_coding_system))
              && proc_encode_coding_system[p->outfd])
            {
-             p->encode_coding_system
+             PVAR (p, encode_coding_system)
                = coding_inherit_eol_type (Vlast_coding_system_used, Qnil);
-             setup_coding_system (p->encode_coding_system,
+             setup_coding_system (PVAR (p, encode_coding_system),
                                   proc_encode_coding_system[p->outfd]);
            }
        }
 
       if (coding->carryover_bytes > 0)
        {
-         if (SCHARS (p->decoding_buf) < coding->carryover_bytes)
-           p->decoding_buf = make_uninit_string (coding->carryover_bytes);
-         memcpy (SDATA (p->decoding_buf), coding->carryover,
+         if (SCHARS (PVAR (p, decoding_buf)) < coding->carryover_bytes)
+           PVAR (p, decoding_buf) = make_uninit_string (coding->carryover_bytes);
+         memcpy (SDATA (PVAR (p, decoding_buf)), coding->carryover,
                  coding->carryover_bytes);
          p->decoding_carryover = coding->carryover_bytes;
        }
@@ -5236,7 +5228,7 @@ read_process_output (Lisp_Object proc, register int channel)
     }
 
   /* If no filter, write into buffer if it isn't dead.  */
-  else if (!NILP (p->buffer) && !NILP (BVAR (XBUFFER (p->buffer), name)))
+  else if (!NILP (PVAR (p, buffer)) && !NILP (BVAR (XBUFFER (PVAR (p, buffer)), name)))
     {
       Lisp_Object old_read_only;
       ptrdiff_t old_begv, old_zv;
@@ -5246,7 +5238,7 @@ read_process_output (Lisp_Object proc, register int channel)
       Lisp_Object text;
       struct buffer *b;
 
-      Fset_buffer (p->buffer);
+      Fset_buffer (PVAR (p, buffer));
       opoint = PT;
       opoint_byte = PT_BYTE;
       old_read_only = BVAR (current_buffer, read_only);
@@ -5260,9 +5252,11 @@ read_process_output (Lisp_Object proc, register int channel)
       /* Insert new output into buffer
         at the current end-of-output marker,
         thus preserving logical ordering of input and output.  */
-      if (XMARKER (p->mark)->buffer)
-       SET_PT_BOTH (clip_to_bounds (BEGV, marker_position (p->mark), ZV),
-                    clip_to_bounds (BEGV_BYTE, marker_byte_position (p->mark),
+      if (XMARKER (PVAR (p, mark))->buffer)
+       SET_PT_BOTH (clip_to_bounds (BEGV,
+                                    marker_position (PVAR (p, mark)), ZV),
+                    clip_to_bounds (BEGV_BYTE,
+                                    marker_byte_position (PVAR (p, mark)),
                                     ZV_BYTE));
       else
        SET_PT_BOTH (ZV, ZV_BYTE);
@@ -5279,23 +5273,23 @@ read_process_output (Lisp_Object proc, register int channel)
       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, Vlast_coding_system_used))
+      if (!EQ (PVAR (p, decode_coding_system), Vlast_coding_system_used))
        {
-         p->decode_coding_system = Vlast_coding_system_used;
-         if (NILP (p->encode_coding_system)
+         PVAR (p, decode_coding_system) = Vlast_coding_system_used;
+         if (NILP (PVAR (p, encode_coding_system))
              && proc_encode_coding_system[p->outfd])
            {
-             p->encode_coding_system
+             PVAR (p, encode_coding_system)
                = coding_inherit_eol_type (Vlast_coding_system_used, Qnil);
-             setup_coding_system (p->encode_coding_system,
+             setup_coding_system (PVAR (p, encode_coding_system),
                                   proc_encode_coding_system[p->outfd]);
            }
        }
       if (coding->carryover_bytes > 0)
        {
-         if (SCHARS (p->decoding_buf) < coding->carryover_bytes)
-           p->decoding_buf = make_uninit_string (coding->carryover_bytes);
-         memcpy (SDATA (p->decoding_buf), coding->carryover,
+         if (SCHARS (PVAR (p, decoding_buf)) < coding->carryover_bytes)
+           PVAR (p, decoding_buf) = make_uninit_string (coding->carryover_bytes);
+         memcpy (SDATA (PVAR (p, decoding_buf)), coding->carryover,
                  coding->carryover_bytes);
          p->decoding_carryover = coding->carryover_bytes;
        }
@@ -5313,11 +5307,11 @@ read_process_output (Lisp_Object proc, register int channel)
       /* Make sure the process marker's position is valid when the
         process buffer is changed in the signal_after_change above.
         W3 is known to do that.  */
-      if (BUFFERP (p->buffer)
-         && (b = XBUFFER (p->buffer), b != current_buffer))
-       set_marker_both (p->mark, p->buffer, BUF_PT (b), BUF_PT_BYTE (b));
+      if (BUFFERP (PVAR (p, buffer))
+         && (b = XBUFFER (PVAR (p, buffer)), b != current_buffer))
+       set_marker_both (PVAR (p, mark), PVAR (p, buffer), BUF_PT (b), BUF_PT_BYTE (b));
       else
-       set_marker_both (p->mark, p->buffer, PT, PT_BYTE);
+       set_marker_both (PVAR (p, mark), PVAR (p, buffer), PT, PT_BYTE);
 
       update_mode_lines++;
 
@@ -5360,7 +5354,7 @@ static jmp_buf send_process_frame;
 static Lisp_Object process_sent_to;
 
 #ifndef FORWARD_SIGNAL_TO_MAIN_THREAD
-static void send_process_trap (int) NO_RETURN;
+static _Noreturn void send_process_trap (int);
 #endif
 
 static void
@@ -5371,6 +5365,78 @@ send_process_trap (int ignore)
   longjmp (send_process_frame, 1);
 }
 
+/* In send_process, when a write fails temporarily,
+   wait_reading_process_output is called.  It may execute user code,
+   e.g. timers, that attempts to write new data to the same process.
+   We must ensure that data is sent in the right order, and not
+   interspersed half-completed with other writes (Bug#10815).  This is
+   handled by the write_queue element of struct process.  It is a list
+   with each entry having the form
+
+   (string . (offset . length))
+
+   where STRING is a lisp string, OFFSET is the offset into the
+   string's byte sequence from which we should begin to send, and
+   LENGTH is the number of bytes left to send.  */
+
+/* Create a new entry in write_queue.
+   INPUT_OBJ should be a buffer, string Qt, or Qnil.
+   BUF is a pointer to the string sequence of the input_obj or a C
+   string in case of Qt or Qnil.  */
+
+static void
+write_queue_push (struct Lisp_Process *p, Lisp_Object input_obj,
+                  const char *buf, ptrdiff_t len, int front)
+{
+  ptrdiff_t offset;
+  Lisp_Object entry, obj;
+
+  if (STRINGP (input_obj))
+    {
+      offset = buf - SSDATA (input_obj);
+      obj = input_obj;
+    }
+  else
+    {
+      offset = 0;
+      obj = make_unibyte_string (buf, len);
+    }
+
+  entry = Fcons (obj, Fcons (make_number (offset), make_number (len)));
+
+  if (front)
+    PVAR (p, write_queue) = Fcons (entry, PVAR (p, write_queue));
+  else
+    PVAR (p, write_queue) = nconc2 (PVAR (p, write_queue), Fcons (entry, Qnil));
+}
+
+/* Remove the first element in the write_queue of process P, put its
+   contents in OBJ, BUF and LEN, and return non-zero.  If the
+   write_queue is empty, return zero.  */
+
+static int
+write_queue_pop (struct Lisp_Process *p, Lisp_Object *obj,
+                const char **buf, ptrdiff_t *len)
+{
+  Lisp_Object entry, offset_length;
+  ptrdiff_t offset;
+
+  if (NILP (PVAR (p, write_queue)))
+    return 0;
+
+  entry = XCAR (PVAR (p, write_queue));
+  PVAR (p, write_queue) = XCDR (PVAR (p, write_queue));
+
+  *obj = XCAR (entry);
+  offset_length = XCDR (entry);
+
+  *len = XINT (XCDR (offset_length));
+  offset = XINT (XCAR (offset_length));
+  *buf = SSDATA (*obj) + offset;
+
+  return 1;
+}
+
 /* Send some data to process PROC.
    BUF is the beginning of the data; LEN is the number of characters.
    OBJECT is the Lisp object that the data comes from.  If OBJECT is
@@ -5389,17 +5455,14 @@ send_process (volatile Lisp_Object proc, const char *volatile buf,
   struct Lisp_Process *p = XPROCESS (proc);
   ssize_t rv;
   struct coding_system *coding;
-  struct gcpro gcpro1;
   void (*volatile old_sigpipe) (int);
 
-  GCPRO1 (object);
-
   if (p->raw_status_new)
     update_status (p);
-  if (! EQ (p->status, Qrun))
-    error ("Process %s not running", SDATA (p->name));
+  if (! EQ (PVAR (p, status), Qrun))
+    error ("Process %s not running", SDATA (PVAR (p, name)));
   if (p->outfd < 0)
-    error ("Output file descriptor of %s is closed", SDATA (p->name));
+    error ("Output file descriptor of %s is closed", SDATA (PVAR (p, name)));
 
   coding = proc_encode_coding_system[p->outfd];
   Vlast_coding_system_used = CODING_ID_NAME (coding->id);
@@ -5409,9 +5472,9 @@ send_process (volatile Lisp_Object proc, const char *volatile buf,
          && !NILP (BVAR (XBUFFER (object), enable_multibyte_characters)))
       || EQ (object, Qt))
     {
-      p->encode_coding_system
-       = complement_process_encoding_system (p->encode_coding_system);
-      if (!EQ (Vlast_coding_system_used, p->encode_coding_system))
+      PVAR (p, encode_coding_system)
+       = complement_process_encoding_system (PVAR (p, encode_coding_system));
+      if (!EQ (Vlast_coding_system_used, PVAR (p, encode_coding_system)))
        {
          /* The coding system for encoding was changed to raw-text
             because we sent a unibyte text previously.  Now we are
@@ -5421,8 +5484,8 @@ send_process (volatile Lisp_Object proc, const char *volatile buf,
             Another reason we come here is that the coding system
             was just complemented and a new one was returned by
             complement_process_encoding_system.  */
-         setup_coding_system (p->encode_coding_system, coding);
-         Vlast_coding_system_used = p->encode_coding_system;
+         setup_coding_system (PVAR (p, encode_coding_system), coding);
+         Vlast_coding_system_used = PVAR (p, encode_coding_system);
        }
       coding->src_multibyte = 1;
     }
@@ -5505,22 +5568,37 @@ send_process (volatile Lisp_Object proc, const char *volatile buf,
   if (!setjmp (send_process_frame))
     {
       p = XPROCESS (proc);  /* Repair any setjmp clobbering.  */
-
       process_sent_to = proc;
-      while (len > 0)
+
+      /* If there is already data in the write_queue, put the new data
+         in the back of queue.  Otherwise, ignore it.  */
+      if (!NILP (PVAR (p, write_queue)))
+        write_queue_push (p, object, buf, len, 0);
+
+      do   /* while !NILP (p->write_queue) */
        {
-         ptrdiff_t this = len;
+         ptrdiff_t cur_len = -1;
+         const char *cur_buf;
+         Lisp_Object cur_object;
 
-         /* Send this batch, using one or more write calls.  */
-         while (this > 0)
+         /* If write_queue is empty, ignore it.  */
+         if (!write_queue_pop (p, &cur_object, &cur_buf, &cur_len))
            {
+             cur_len = len;
+             cur_buf = buf;
+             cur_object = object;
+           }
+
+         while (cur_len > 0)
+           {
+             /* Send this batch, using one or more write calls.  */
              ptrdiff_t written = 0;
              int outfd = p->outfd;
              old_sigpipe = (void (*) (int)) signal (SIGPIPE, send_process_trap);
 #ifdef DATAGRAM_SOCKETS
              if (DATAGRAM_CHAN_P (outfd))
                {
-                 rv = sendto (outfd, buf, this,
+                 rv = sendto (outfd, cur_buf, cur_len,
                               0, datagram_address[outfd].sa,
                               datagram_address[outfd].len);
                  if (0 <= rv)
@@ -5537,10 +5615,10 @@ send_process (volatile Lisp_Object proc, const char *volatile buf,
                {
 #ifdef HAVE_GNUTLS
                  if (p->gnutls_p)
-                   written = emacs_gnutls_write (p, buf, this);
+                   written = emacs_gnutls_write (p, cur_buf, cur_len);
                  else
 #endif
-                   written = emacs_write (outfd, buf, this);
+                   written = emacs_write (outfd, cur_buf, cur_len);
                  rv = (written ? 0 : -1);
 #ifdef ADAPTIVE_READ_BUFFERING
                  if (p->read_output_delay > 0
@@ -5568,8 +5646,6 @@ send_process (volatile Lisp_Object proc, const char *volatile buf,
                       that may allow the program
                       to finish doing output and read more.  */
                    {
-                     ptrdiff_t offset = 0;
-
 #ifdef BROKEN_PTY_READ_AFTER_EAGAIN
                      /* A gross hack to work around a bug in FreeBSD.
                         In the following sequence, read(2) returns
@@ -5595,35 +5671,22 @@ send_process (volatile Lisp_Object proc, const char *volatile buf,
                        }
 #endif /* BROKEN_PTY_READ_AFTER_EAGAIN */
 
-                     /* Running filters might relocate buffers or strings.
-                        Arrange to relocate BUF.  */
-                     if (BUFFERP (object))
-                       offset = BUF_PTR_BYTE_POS (XBUFFER (object),
-                                                  (unsigned char *) buf);
-                     else if (STRINGP (object))
-                       offset = buf - SSDATA (object);
-
-#ifdef EMACS_HAS_USECS
-                     wait_reading_process_output (0, 20000, 0, 0, Qnil, NULL, 0);
-#else
-                     wait_reading_process_output (1, 0, 0, 0, Qnil, NULL, 0);
-#endif
-
-                     if (BUFFERP (object))
-                       buf = (char *) BUF_BYTE_ADDRESS (XBUFFER (object),
-                                                        offset);
-                     else if (STRINGP (object))
-                       buf = offset + SSDATA (object);
+                     /* Put what we should have written in wait_queue.  */
+                     write_queue_push (p, cur_object, cur_buf, cur_len, 1);
+                     wait_reading_process_output (0, 20 * 1000 * 1000,
+                                                  0, 0, Qnil, NULL, 0);
+                     /* Reread queue, to see what is left.  */
+                     break;
                    }
                  else
                    /* This is a real error.  */
                    report_file_error ("writing to process", Fcons (proc, Qnil));
                }
-             buf += written;
-             len -= written;
-             this -= written;
+             cur_buf += written;
+             cur_len -= written;
            }
        }
+      while (!NILP (PVAR (p, write_queue)));
     }
   else
     {
@@ -5631,13 +5694,11 @@ send_process (volatile Lisp_Object proc, const char *volatile buf,
       proc = process_sent_to;
       p = XPROCESS (proc);
       p->raw_status_new = 0;
-      p->status = Fcons (Qexit, Fcons (make_number (256), Qnil));
+      PVAR (p, status) = Fcons (Qexit, Fcons (make_number (256), Qnil));
       p->tick = ++process_tick;
       deactivate_process (proc);
-      error ("SIGPIPE raised on process %s; closed it", SDATA (p->name));
+      error ("SIGPIPE raised on process %s; closed it", SDATA (PVAR (p, name)));
     }
-
-  UNGCPRO;
 }
 
 DEFUN ("process-send-region", Fprocess_send_region, Sprocess_send_region,
@@ -5694,12 +5755,12 @@ emacs_get_tty_pgrp (struct Lisp_Process *p)
   pid_t gid = -1;
 
 #ifdef TIOCGPGRP
-  if (ioctl (p->infd, TIOCGPGRP, &gid) == -1 && ! NILP (p->tty_name))
+  if (ioctl (p->infd, TIOCGPGRP, &gid) == -1 && ! NILP (PVAR (p, tty_name)))
     {
       int fd;
       /* Some OS:es (Solaris 8/9) does not allow TIOCGPGRP from the
         master side.  Try the slave side.  */
-      fd = emacs_open (SSDATA (p->tty_name), O_RDONLY, 0);
+      fd = emacs_open (SSDATA (PVAR (p, tty_name)), O_RDONLY, 0);
 
       if (fd != -1)
        {
@@ -5728,12 +5789,12 @@ return t unconditionally.  */)
   proc = get_process (process);
   p = XPROCESS (proc);
 
-  if (!EQ (p->type, Qreal))
+  if (!EQ (PVAR (p, type), Qreal))
     error ("Process %s is not a subprocess",
-          SDATA (p->name));
+          SDATA (PVAR (p, name)));
   if (p->infd < 0)
     error ("Process %s is not active",
-          SDATA (p->name));
+          SDATA (PVAR (p, name)));
 
   gid = emacs_get_tty_pgrp (p);
 
@@ -5768,12 +5829,12 @@ process_send_signal (Lisp_Object process, int signo, Lisp_Object current_group,
   proc = get_process (process);
   p = XPROCESS (proc);
 
-  if (!EQ (p->type, Qreal))
+  if (!EQ (PVAR (p, type), Qreal))
     error ("Process %s is not a subprocess",
-          SDATA (p->name));
+          SDATA (PVAR (p, name)));
   if (p->infd < 0)
     error ("Process %s is not active",
-          SDATA (p->name));
+          SDATA (PVAR (p, name)));
 
   if (!p->pty_flag)
     current_group = Qnil;
@@ -5862,7 +5923,7 @@ process_send_signal (Lisp_Object process, int signo, Lisp_Object current_group,
 #ifdef SIGCONT
     case SIGCONT:
       p->raw_status_new = 0;
-      p->status = Qrun;
+      PVAR (p, status) = Qrun;
       p->tick = ++process_tick;
       if (!nomsg)
        {
@@ -5952,13 +6013,13 @@ traffic.  */)
       struct Lisp_Process *p;
 
       p = XPROCESS (process);
-      if (NILP (p->command)
+      if (NILP (PVAR (p, command))
          && p->infd >= 0)
        {
          FD_CLR (p->infd, &input_wait_mask);
          FD_CLR (p->infd, &non_keyboard_wait_mask);
        }
-      p->command = Qt;
+      PVAR (p, command) = Qt;
       return process;
     }
 #ifndef SIGTSTP
@@ -5981,9 +6042,9 @@ traffic.  */)
       struct Lisp_Process *p;
 
       p = XPROCESS (process);
-      if (EQ (p->command, Qt)
+      if (EQ (PVAR (p, command), Qt)
          && p->infd >= 0
-         && (!EQ (p->filter, Qt) || EQ (p->status, Qlisten)))
+         && (!EQ (PVAR (p, filter), Qt) || EQ (PVAR (p, status), Qlisten)))
        {
          FD_SET (p->infd, &input_wait_mask);
          FD_SET (p->infd, &non_keyboard_wait_mask);
@@ -5994,7 +6055,7 @@ traffic.  */)
          tcflush (p->infd, TCIFLUSH);
 #endif /* not WINDOWSNT */
        }
-      p->command = Qnil;
+      PVAR (p, command) = Qnil;
       return process;
     }
 #ifdef SIGCONT
@@ -6041,7 +6102,8 @@ SIGCODE may be an integer, or a symbol whose name is a signal name.  */)
       CHECK_PROCESS (process);
       pid = XPROCESS (process)->pid;
       if (pid <= 0)
-       error ("Cannot signal process %s", SDATA (XPROCESS (process)->name));
+       error ("Cannot signal process %s",
+              SDATA (PVAR (XPROCESS (process), name)));
     }
 
 #define parse_signal(NAME, VALUE)              \
@@ -6185,8 +6247,8 @@ process has been transmitted to the serial port.  */)
   /* Make sure the process is really alive.  */
   if (XPROCESS (proc)->raw_status_new)
     update_status (XPROCESS (proc));
-  if (! EQ (XPROCESS (proc)->status, Qrun))
-    error ("Process %s not running", SDATA (XPROCESS (proc)->name));
+  if (! EQ (PVAR (XPROCESS (proc), status), Qrun))
+    error ("Process %s not running", SDATA (PVAR (XPROCESS (proc), name)));
 
   if (CODING_REQUIRE_FLUSHING (coding))
     {
@@ -6196,7 +6258,7 @@ process has been transmitted to the serial port.  */)
 
   if (XPROCESS (proc)->pty_flag)
     send_process (proc, "\004", 1, Qnil);
-  else if (EQ (XPROCESS (proc)->type, Qserial))
+  else if (EQ (PVAR (XPROCESS (proc), type), Qserial))
     {
 #ifndef WINDOWSNT
       if (tcdrain (XPROCESS (proc)->outfd) != 0)
@@ -6213,7 +6275,7 @@ process has been transmitted to the serial port.  */)
         for communication with the subprocess, call shutdown to cause EOF.
         (In some old system, shutdown to socketpair doesn't work.
         Then we just can't win.)  */
-      if (EQ (XPROCESS (proc)->type, Qnetwork)
+      if (EQ (PVAR (XPROCESS (proc), type), Qnetwork)
          || XPROCESS (proc)->outfd == XPROCESS (proc)->infd)
        shutdown (XPROCESS (proc)->outfd, 1);
       /* In case of socketpair, outfd == infd, so don't close it.  */
@@ -6229,7 +6291,7 @@ process has been transmitted to the serial port.  */)
 
       if (!proc_encode_coding_system[new_outfd])
        proc_encode_coding_system[new_outfd]
-         = (struct coding_system *) xmalloc (sizeof (struct coding_system));
+         = xmalloc (sizeof (struct coding_system));
       memcpy (proc_encode_coding_system[new_outfd],
              proc_encode_coding_system[old_outfd],
              sizeof (struct coding_system));
@@ -6326,7 +6388,7 @@ sigchld_handler (int signo)
        {
          proc = XCDR (XCAR (tail));
          p = XPROCESS (proc);
-         if (EQ (p->type, Qreal) && p->pid == pid)
+         if (EQ (PVAR (p, type), Qreal) && p->pid == pid)
            break;
          p = 0;
        }
@@ -6367,7 +6429,7 @@ sigchld_handler (int signo)
          /* Tell wait_reading_process_output that it needs to wake up and
             look around.  */
          if (input_available_clear_time)
-           EMACS_SET_SECS_USECS (*input_available_clear_time, 0, 0);
+           *input_available_clear_time = make_emacs_time (0, 0);
        }
 
       /* There was no asynchronous process found for that pid: we have
@@ -6385,7 +6447,7 @@ sigchld_handler (int signo)
          /* Tell wait_reading_process_output that it needs to wake up and
             look around.  */
          if (input_available_clear_time)
-           EMACS_SET_SECS_USECS (*input_available_clear_time, 0, 0);
+           *input_available_clear_time = make_emacs_time (0, 0);
        }
 
     sigchld_end_of_loop:
@@ -6410,7 +6472,7 @@ sigchld_handler (int signo)
 static Lisp_Object
 exec_sentinel_unwind (Lisp_Object data)
 {
-  XPROCESS (XCAR (data))->sentinel = XCDR (data);
+  PVAR (XPROCESS (XCAR (data)), sentinel) = XCDR (data);
   return Qnil;
 }
 
@@ -6450,13 +6512,13 @@ exec_sentinel (Lisp_Object proc, Lisp_Object reason)
      friends don't expect current-buffer to be changed from under them.  */
   record_unwind_protect (set_buffer_if_live, Fcurrent_buffer ());
 
-  sentinel = p->sentinel;
+  sentinel = PVAR (p, sentinel);
   if (NILP (sentinel))
     return;
 
   /* Zilch the sentinel while it's running, to avoid recursive invocations;
      assure that it gets restored no matter how the sentinel exits.  */
-  p->sentinel = Qnil;
+  PVAR (p, sentinel) = Qnil;
   record_unwind_protect (exec_sentinel_unwind, Fcons (proc, sentinel));
   /* Inhibit quit so that random quits don't screw up a running filter.  */
   specbind (Qinhibit_quit, Qt);
@@ -6544,16 +6606,16 @@ status_notify (struct Lisp_Process *deleting_process)
          p->update_tick = p->tick;
 
          /* If process is still active, read any output that remains.  */
-         while (! EQ (p->filter, Qt)
-                && ! EQ (p->status, Qconnect)
-                && ! EQ (p->status, Qlisten)
+         while (! EQ (PVAR (p, filter), Qt)
+                && ! EQ (PVAR (p, status), Qconnect)
+                && ! EQ (PVAR (p, status), Qlisten)
                 /* Network or serial process not stopped:  */
-                && ! EQ (p->command, Qt)
+                && ! EQ (PVAR (p, command), Qt)
                 && p->infd >= 0
                 && p != deleting_process
                 && read_process_output (proc, p->infd) > 0);
 
-         buffer = p->buffer;
+         buffer = PVAR (p, buffer);
 
          /* Get the text to use for the message.  */
          if (p->raw_status_new)
@@ -6561,9 +6623,9 @@ status_notify (struct Lisp_Process *deleting_process)
          msg = status_message (p);
 
          /* If process is terminated, deactivate it or delete it.  */
-         symbol = p->status;
-         if (CONSP (p->status))
-           symbol = XCAR (p->status);
+         symbol = PVAR (p, status);
+         if (CONSP (PVAR (p, status)))
+           symbol = XCAR (PVAR (p, status));
 
          if (EQ (symbol, Qsignal) || EQ (symbol, Qexit)
              || EQ (symbol, Qclosed))
@@ -6580,7 +6642,7 @@ status_notify (struct Lisp_Process *deleting_process)
             this code to be run again.  */
          p->update_tick = p->tick;
          /* Now output the message suitably.  */
-         if (!NILP (p->sentinel))
+         if (!NILP (PVAR (p, sentinel)))
            exec_sentinel (proc, msg);
          /* Don't bother with a message in the buffer
             when a process becomes runnable.  */
@@ -6602,8 +6664,8 @@ status_notify (struct Lisp_Process *deleting_process)
              /* Insert new output into buffer
                 at the current end-of-output marker,
                 thus preserving logical ordering of input and output.  */
-             if (XMARKER (p->mark)->buffer)
-               Fgoto_char (p->mark);
+             if (XMARKER (PVAR (p, mark))->buffer)
+               Fgoto_char (PVAR (p, mark));
              else
                SET_PT_BOTH (ZV, ZV_BYTE);
 
@@ -6613,11 +6675,11 @@ status_notify (struct Lisp_Process *deleting_process)
              tem = BVAR (current_buffer, read_only);
              BVAR (current_buffer, read_only) = Qnil;
              insert_string ("\nProcess ");
-             Finsert (1, &p->name);
+             Finsert (1, &PVAR (p, name));
              insert_string (" ");
              Finsert (1, &msg);
              BVAR (current_buffer, read_only) = tem;
-             set_marker_both (p->mark, p->buffer, PT, PT_BYTE);
+             set_marker_both (PVAR (p, mark), PVAR (p, buffer), PT, PT_BYTE);
 
              if (opoint >= before)
                SET_PT_BOTH (opoint + (PT - before),
@@ -6647,14 +6709,14 @@ encode subprocess input.  */)
   CHECK_PROCESS (process);
   p = XPROCESS (process);
   if (p->infd < 0)
-    error ("Input file descriptor of %s closed", SDATA (p->name));
+    error ("Input file descriptor of %s closed", SDATA (PVAR (p, name)));
   if (p->outfd < 0)
-    error ("Output file descriptor of %s closed", SDATA (p->name));
+    error ("Output file descriptor of %s closed", SDATA (PVAR (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;
+  PVAR (p, decode_coding_system) = decoding;
+  PVAR (p, encode_coding_system) = encoding;
   setup_process_coding_systems (process);
 
   return Qnil;
@@ -6666,8 +6728,8 @@ DEFUN ("process-coding-system",
   (register Lisp_Object process)
 {
   CHECK_PROCESS (process);
-  return Fcons (XPROCESS (process)->decode_coding_system,
-               XPROCESS (process)->encode_coding_system);
+  return Fcons (PVAR (XPROCESS (process), decode_coding_system),
+               PVAR (XPROCESS (process), encode_coding_system));
 }
 
 DEFUN ("set-process-filter-multibyte", Fset_process_filter_multibyte,
@@ -6684,7 +6746,8 @@ suppressed.  */)
   CHECK_PROCESS (process);
   p = XPROCESS (process);
   if (NILP (flag))
-    p->decode_coding_system = raw_text_coding_system (p->decode_coding_system);
+    PVAR (p, decode_coding_system) 
+      = raw_text_coding_system (PVAR (p, decode_coding_system));
   setup_process_coding_systems (process);
 
   return Qnil;
@@ -6746,19 +6809,25 @@ keyboard_bit_set (fd_set *mask)
 
 /* Defined on msdos.c.  */
 extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *,
-                      EMACS_TIME *);
+                      EMACS_TIME *, void *);
 
 /* Implementation of wait_reading_process_output, assuming that there
    are no subprocesses.  Used only by the MS-DOS build.
 
    Wait for timeout to elapse and/or keyboard input to be available.
 
-   time_limit is:
-     timeout in seconds, or
-     zero for no limit, or
-     -1 means gobble data immediately available but don't wait for any.
+   TIME_LIMIT is:
+     timeout in seconds
+     If negative, gobble data immediately available but don't wait for any.
+
+   NSECS is:
+     an additional duration to wait, measured in nanoseconds
+     If TIME_LIMIT is zero, then:
+       If NSECS == 0, there is no limit.
+       If NSECS > 0, the timeout consists of NSECS only.
+       If NSECS < 0, gobble data immediately, as if TIME_LIMIT were negative.
 
-   read_kbd is a Lisp_Object:
+   READ_KBD is:
      0 to ignore keyboard input, or
      1 to return when input is available, or
      -1 means caller will actually read the input, so don't throw to
@@ -6767,28 +6836,33 @@ extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *,
    see full version for other parameters. We know that wait_proc will
      always be NULL, since `subprocesses' isn't defined.
 
-   do_display != 0 means redisplay should be done to show subprocess
+   DO_DISPLAY != 0 means redisplay should be done to show subprocess
    output that arrives.
 
    Return true if we received input from any process.  */
 
 int
-wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
+wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
                             int do_display,
                             Lisp_Object wait_for_cell,
                             struct Lisp_Process *wait_proc, int just_wait_proc)
 {
   register int nfds;
   EMACS_TIME end_time, timeout;
-  SELECT_TYPE waitchannels;
-  int xerrno;
+
+  if (time_limit < 0)
+    {
+      time_limit = 0;
+      nsecs = -1;
+    }
+  else if (TYPE_MAXIMUM (time_t) < time_limit)
+    time_limit = TYPE_MAXIMUM (time_t);
 
   /* What does time_limit really mean?  */
-  if (time_limit || microsecs)
+  if (time_limit || 0 < nsecs)
     {
-      EMACS_GET_TIME (end_time);
-      EMACS_SET_SECS_USECS (timeout, time_limit, microsecs);
-      EMACS_ADD_TIME (end_time, end_time, timeout);
+      timeout = make_emacs_time (time_limit, nsecs);
+      end_time = add_emacs_time (current_emacs_time (), timeout);
     }
 
   /* Turn off periodic alarms (in case they are in use)
@@ -6800,6 +6874,8 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
   while (1)
     {
       int timeout_reduced_for_timers = 0;
+      SELECT_TYPE waitchannels;
+      int xerrno;
 
       /* If calling from keyboard input, do not quit
         since we want to return C-g as an input character.
@@ -6813,24 +6889,24 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
 
       /* Compute time from now till when time limit is up */
       /* Exit if already run out */
-      if (time_limit == -1)
+      if (nsecs < 0)
        {
-         /* -1 specified for timeout means
+         /* A negative timeout means
             gobble output available now
             but don't wait at all. */
 
-         EMACS_SET_SECS_USECS (timeout, 0, 0);
+         timeout = make_emacs_time (0, 0);
        }
-      else if (time_limit || microsecs)
+      else if (time_limit || 0 < nsecs)
        {
-         EMACS_GET_TIME (timeout);
-         EMACS_SUB_TIME (timeout, end_time, timeout);
-         if (EMACS_TIME_NEG_P (timeout))
+         EMACS_TIME now = current_emacs_time ();
+         if (EMACS_TIME_LE (end_time, now))
            break;
+         timeout = sub_emacs_time (end_time, now);
        }
       else
        {
-         EMACS_SET_SECS_USECS (timeout, 100000, 0);
+         timeout = make_emacs_time (100000, 0);
        }
 
       /* If our caller will not immediately handle keyboard events,
@@ -6859,11 +6935,9 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
              && requeued_events_pending_p ())
            break;
 
-         if (! EMACS_TIME_NEG_P (timer_delay) && time_limit != -1)
+         if (EMACS_TIME_VALID_P (timer_delay) && 0 <= nsecs)
            {
-             EMACS_TIME difference;
-             EMACS_SUB_TIME (difference, timer_delay, timeout);
-             if (EMACS_TIME_NEG_P (difference))
+             if (EMACS_TIME_LT (timer_delay, timeout))
                {
                  timeout = timer_delay;
                  timeout_reduced_for_timers = 1;
@@ -6876,13 +6950,6 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
       if (read_kbd < 0)
        set_waiting_for_input (&timeout);
 
-      /* Wait till there is something to do.  */
-
-      if (! read_kbd && NILP (wait_for_cell))
-       FD_ZERO (&waitchannels);
-      else
-       FD_SET (0, &waitchannels);
-
       /* If a frame has been newly mapped and needs updating,
         reprocess its display stuff.  */
       if (frame_garbaged && do_display)
@@ -6893,14 +6960,16 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
            set_waiting_for_input (&timeout);
        }
 
+      /* Wait till there is something to do.  */
+      FD_ZERO (&waitchannels);
       if (read_kbd && detect_input_pending ())
+       nfds = 0;
+      else
        {
-         nfds = 0;
-         FD_ZERO (&waitchannels);
+         if (read_kbd || !NILP (wait_for_cell))
+           FD_SET (0, &waitchannels);
+         nfds = pselect (1, &waitchannels, NULL, NULL, &timeout, NULL);
        }
-      else
-       nfds = select (1, &waitchannels, (SELECT_TYPE *)0, (SELECT_TYPE *)0,
-                      &timeout);
 
       xerrno = errno;
 
@@ -6910,7 +6979,7 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
       /*  If we woke up due to SIGWINCH, actually change size now.  */
       do_pending_window_change (0);
 
-      if (time_limit && nfds == 0 && ! timeout_reduced_for_timers)
+      if ((time_limit || nsecs) && nfds == 0 && ! timeout_reduced_for_timers)
        /* We waited the full specified time, so return now.  */
        break;
 
@@ -7015,22 +7084,20 @@ setup_process_coding_systems (Lisp_Object process)
     return;
 
   if (!proc_decode_coding_system[inch])
-    proc_decode_coding_system[inch]
-      = (struct coding_system *) xmalloc (sizeof (struct coding_system));
-  coding_system = p->decode_coding_system;
-  if (! NILP (p->filter))
+    proc_decode_coding_system[inch] = xmalloc (sizeof (struct coding_system));
+  coding_system = PVAR (p, decode_coding_system);
+  if (! NILP (PVAR (p, filter)))
     ;
-  else if (BUFFERP (p->buffer))
+  else if (BUFFERP (PVAR (p, buffer)))
     {
-      if (NILP (BVAR (XBUFFER (p->buffer), enable_multibyte_characters)))
+      if (NILP (BVAR (XBUFFER (PVAR (p, buffer)), enable_multibyte_characters)))
        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] = xmalloc (sizeof (struct coding_system));
+  setup_coding_system (PVAR (p, encode_coding_system),
                       proc_encode_coding_system[outch]);
 #endif
 }
@@ -7076,7 +7143,7 @@ BUFFER may be a buffer or the name of one.  */)
   for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail))
     {
       proc = Fcdr (XCAR (tail));
-      if (PROCESSP (proc) && EQ (XPROCESS (proc)->buffer, buf))
+      if (PROCESSP (proc) && EQ (PVAR (XPROCESS (proc), buffer), buf))
        return proc;
     }
 #endif /* subprocesses */
@@ -7115,7 +7182,7 @@ kill_buffer_processes (Lisp_Object buffer)
     {
       proc = XCDR (XCAR (tail));
       if (PROCESSP (proc)
-         && (NILP (buffer) || EQ (XPROCESS (proc)->buffer, buffer)))
+         && (NILP (buffer) || EQ (PVAR (XPROCESS (proc), buffer), buffer)))
        {
          if (NETCONN_P (proc) || SERIALCONN_P (proc))
            Fdelete_process (proc);
@@ -7213,19 +7280,20 @@ integer or floating point values.
  majflt  -- number of major page faults (number)
  cminflt -- cumulative number of minor page faults (number)
  cmajflt -- cumulative number of major page faults (number)
- utime   -- user time used by the process, in the (HIGH LOW USEC) format
- stime   -- system time used by the process, in the (HIGH LOW USEC) format
- time    -- sum of utime and stime, in the (HIGH LOW USEC) format
- cutime  -- user time used by the process and its children, (HIGH LOW USEC)
- cstime  -- system time used by the process and its children, (HIGH LOW USEC)
- ctime   -- sum of cutime and cstime, in the (HIGH LOW USEC) format
+ utime   -- user time used by the process, in (current-time) format,
+              which is a list of integers (HIGH LOW USEC PSEC)
+ stime   -- system time used by the process (current-time)
+ time    -- sum of utime and stime (current-time)
+ cutime  -- user time used by the process and its children (current-time)
+ cstime  -- system time used by the process and its children (current-time)
+ ctime   -- sum of cutime and cstime (current-time)
  pri     -- priority of the process (number)
  nice    -- nice value of the process (number)
  thcount -- process thread count (number)
- start   -- time the process started, in the (HIGH LOW USEC) format
+ start   -- time the process started (current-time)
  vsize   -- virtual memory size of the process in KB's (number)
  rss     -- resident set size of the process in KB's (number)
- etime   -- elapsed time the process is running, in (HIGH LOW USEC) format
+ etime   -- elapsed time the process is running, in (HIGH LOW USEC PSEC) format
  pcpu    -- percents of CPU time used by the process (floating-point number)
  pmem    -- percents of total physical memory used by process's resident set
               (floating-point number)
@@ -7236,8 +7304,10 @@ integer or floating point values.
 }
 
 \f
+/* This is not called "init_process" because that is the name of a
+   Mach system call, so it would cause problems on Darwin systems.  */
 void
-init_process (void)
+init_process_emacs (void)
 {
 #ifdef subprocesses
   register int i;
@@ -7334,8 +7404,7 @@ init_process (void)
     char const *release = (STRINGP (Voperating_system_release)
                           ? SSDATA (Voperating_system_release)
                           : 0);
-    if (!release || !release[0] || (release[0] < MIN_PTY_KERNEL_VERSION
-                                   && release[1] == '.')) {
+    if (!release || !release[0] || (release[0] < '7' && release[1] == '.')) {
       Vprocess_connection_type = Qnil;
     }
   }