changeset 8063:30861f2f4f84

(send_process): Major rewrite. Don't put in a C-d unless a single line is too long. Read process input whenever output gets stuck. Relocate BUF if we read input. New arg OBJECT. Fprocess_send_region, Fprocess_send_string, process_send_signal) (Fprocess_send_eof): Pass new arg OBJECT.
author Richard M. Stallman <rms@gnu.org>
date Sat, 25 Jun 1994 22:35:28 +0000
parents ad595e4e165c
children d04a39ce4f1d
files src/process.c
diffstat 1 files changed, 114 insertions(+), 70 deletions(-) [+]
line wrap: on
line diff
--- a/src/process.c	Sat Jun 25 22:34:52 1994 +0000
+++ b/src/process.c	Sat Jun 25 22:35:28 1994 +0000
@@ -2337,16 +2337,20 @@
   longjmp (send_process_frame, 1);
 }
 
-send_process (proc, buf, len)
+/* 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.  */
+
+send_process (proc, buf, len, object)
      Lisp_Object proc;
      char *buf;
      int len;
+     Lisp_Object object;
 {
   /* Don't use register vars; longjmp can lose them.  */
   int rv;
   unsigned char *procname = XSTRING (XPROCESS (proc)->name)->data;
 
-
 #ifdef VMS
   struct Lisp_Process *p = XPROCESS (proc);
   VMS_PROC_STUFF *vs, *get_vms_process_pointer();
@@ -2364,6 +2368,21 @@
   else if (write_to_vms_process (vs, buf, len))
     ;
 #else
+
+  if (pty_max_bytes == 0)
+    {
+#if defined (HAVE_FPATHCONF) && defined (_PC_MAX_CANON)
+      pty_max_bytes = fpathconf (XFASTINT (XPROCESS (proc)->outfd),
+				 _PC_MAX_CANON);
+      if (pty_max_bytes < 0)
+	pty_max_bytes = 250;
+#else
+      pty_max_bytes = 250;
+#endif
+      /* Deduct one, to leave space for the eof.  */
+      pty_max_bytes--;
+    }
+
   if (!setjmp (send_process_frame))
     while (len > 0)
       {
@@ -2371,65 +2390,89 @@
 	SIGTYPE (*old_sigpipe)();
 	int flush_pty = 0;
 
-	if (pty_max_bytes == 0)
+	/* Decide how much data we can send in one batch.
+	   Long lines need to be split into multiple batches.  */
+	if (!NILP (XPROCESS (proc)->pty_flag))
 	  {
-#if defined (HAVE_FPATHCONF) && defined (_PC_MAX_CANON)
-	    pty_max_bytes = fpathconf (XFASTINT (XPROCESS (proc)->outfd),
-				       _PC_MAX_CANON);
-	    if (pty_max_bytes < 0)
-	      pty_max_bytes = 250;
-#else
-	    pty_max_bytes = 250;
+	    /* Starting this at zero is always correct when not the first iteration
+	       because the previous iteration ended by sending C-d.
+	       It may not be correct for the first iteration
+	       if a partial line was sent in a separate send_process call.
+	       If that proves worth handling, we need to save linepos
+	       in the process object.  */
+	    int linepos = 0;
+	    char *ptr = buf;
+	    char *end = buf + len;
+
+	    /* Scan through this text for a line that is too long.  */
+	    while (ptr != end && linepos < pty_max_bytes)
+	      {
+		if (*ptr == '\n')
+		  linepos = 0;
+		else
+		  linepos++;
+		ptr++;
+	      }
+	    /* If we found one, break the line there
+	       and put in a C-d to force the buffer through.  */
+	    this = ptr - buf;
+	  }
+
+	/* Send this batch, using one or more write calls.  */
+	while (this > 0)
+	  {
+	    old_sigpipe = (SIGTYPE (*) ()) signal (SIGPIPE, send_process_trap);
+	    rv = write (XINT (XPROCESS (proc)->outfd), buf, this);
+	    signal (SIGPIPE, old_sigpipe);
+
+	    if (rv < 0)
+	      {
+		if (0
+#ifdef EWOULDBLOCK
+		    || errno == EWOULDBLOCK
 #endif
+#ifdef EAGAIN
+		    || errno == EAGAIN
+#endif
+		    )
+		  /* Buffer is full.  Wait, accepting input; 
+		     that may allow the program
+		     to finish doing output and read more.  */
+		  {
+		    Lisp_Object zero;
+		    int offset;
+
+		    /* Running filters might relocate buffers or strings.
+		       Arrange to relocate BUF.  */
+		    if (BUFFERP (object))
+		      offset = BUF_PTR_CHAR_POS (XBUFFER (object),
+						 (unsigned char *) buf);
+		    else if (STRINGP (object))
+		      offset = buf - (char *) XSTRING (object)->data;
+
+		    XFASTINT (zero) = 0;
+		    wait_reading_process_input (1, 0, zero, 0);
+
+		    if (BUFFERP (object))
+		      buf = (char *) BUF_CHAR_ADDRESS (XBUFFER (object), offset);
+		    else if (STRINGP (object))
+		      buf = offset + (char *) XSTRING (object)->data;
+
+		    rv = 0;
+		  }
+		else
+		  /* This is a real error.  */
+		  report_file_error ("writing to process", Fcons (proc, Qnil));
+	      }
+	    buf += rv;
+	    len -= rv;
+	    this -= rv;
 	  }
 
-	/* Don't send more than pty_max_bytes bytes at a time.  */
-	/* Subtract 1 to leave room for the EOF.  */
-	if (this >= pty_max_bytes && !NILP (XPROCESS (proc)->pty_flag))
-	  this = pty_max_bytes - 1;
-
-	old_sigpipe = (SIGTYPE (*) ()) signal (SIGPIPE, send_process_trap);
-	rv = write (XINT (XPROCESS (proc)->outfd), buf, this);
-
 	/* If we sent just part of the string, put in an EOF
 	   to force it through, before we send the rest.  */
-	if (this < len)
+	if (len > 0)
 	  Fprocess_send_eof (proc);
-
-	signal (SIGPIPE, old_sigpipe);
-	if (rv < 0)
-	  {
-	    if (0
-#ifdef EWOULDBLOCK
-		|| errno == EWOULDBLOCK
-#endif
-#ifdef EAGAIN
-		|| errno == EAGAIN
-#endif
-		)
-	      {
-		/* It would be nice to accept process output here,
-		   but that is difficult.  For example, it could
-		   garbage what we are sending if that is from a buffer.  */
-		immediate_quit = 1;
-		QUIT;
-		sleep (1);
-		immediate_quit = 0;
-		continue;
-	      }
-	    report_file_error ("writing to process", Fcons (proc, Qnil));
-	  }
-	buf += rv;
-	len -= rv;
-	/* Allow input from processes between bursts of sending.
-	   Otherwise things may get stopped up.  */
-	if (len > 0)
-	  {
-	    Lisp_Object zero;
-
-	    XFASTINT (zero) = 0;
-	    wait_reading_process_input (-1, 0, zero, 0);
-	  }
       }
 #endif
   else
@@ -2469,7 +2512,8 @@
     move_gap (start);
 
   start1 = XINT (start);
-  send_process (proc, &FETCH_CHAR (start1), XINT (end) - XINT (start));
+  send_process (proc, &FETCH_CHAR (start1), XINT (end) - XINT (start),
+		Fcurrent_buffer ());
 
   return Qnil;
 }
@@ -2488,7 +2532,7 @@
   Lisp_Object proc;
   CHECK_STRING (string, 1);
   proc = get_process (process);
-  send_process (proc, XSTRING (string)->data, XSTRING (string)->size);
+  send_process (proc, XSTRING (string)->data, XSTRING (string)->size, string);
   return Qnil;
 }
 
@@ -2544,20 +2588,20 @@
 	{
 	case SIGINT:
 	  tcgetattr (XINT (p->infd), &t);
-	  send_process (proc, &t.c_cc[VINTR], 1);
+	  send_process (proc, &t.c_cc[VINTR], 1, Qnil);
 	  return;
 
 	case SIGQUIT:
 	  tcgetattr (XINT (p->infd), &t);
-  	  send_process (proc, &t.c_cc[VQUIT], 1);
+  	  send_process (proc, &t.c_cc[VQUIT], 1, Qnil);
   	  return;
 
   	case SIGTSTP:
 	  tcgetattr (XINT (p->infd), &t);
 #if defined (VSWTCH) && !defined (PREFER_VSUSP)
-  	  send_process (proc, &t.c_cc[VSWTCH], 1);
+  	  send_process (proc, &t.c_cc[VSWTCH], 1, Qnil);
 #else
-	  send_process (proc, &t.c_cc[VSUSP], 1);
+	  send_process (proc, &t.c_cc[VSUSP], 1, Qnil);
 #endif
   	  return;
 	}
@@ -2575,16 +2619,16 @@
 	{
 	case SIGINT:
 	  ioctl (XINT (p->infd), TIOCGETC, &c);
-	  send_process (proc, &c.t_intrc, 1);
+	  send_process (proc, &c.t_intrc, 1, Qnil);
 	  return;
 	case SIGQUIT:
 	  ioctl (XINT (p->infd), TIOCGETC, &c);
-	  send_process (proc, &c.t_quitc, 1);
+	  send_process (proc, &c.t_quitc, 1, Qnil);
 	  return;
 #ifdef SIGTSTP
 	case SIGTSTP:
 	  ioctl (XINT (p->infd), TIOCGLTC, &lc);
-	  send_process (proc, &lc.t_suspc, 1);
+	  send_process (proc, &lc.t_suspc, 1, Qnil);
 	  return;
 #endif /* ! defined (SIGTSTP) */
 	}
@@ -2599,16 +2643,16 @@
 	{
 	case SIGINT:
 	  ioctl (XINT (p->infd), TCGETA, &t);
-	  send_process (proc, &t.c_cc[VINTR], 1);
+	  send_process (proc, &t.c_cc[VINTR], 1, Qnil);
 	  return;
 	case SIGQUIT:
 	  ioctl (XINT (p->infd), TCGETA, &t);
-	  send_process (proc, &t.c_cc[VQUIT], 1);
+	  send_process (proc, &t.c_cc[VQUIT], 1, Qnil);
 	  return;
 #ifdef SIGTSTP
 	case SIGTSTP:
 	  ioctl (XINT (p->infd), TCGETA, &t);
-	  send_process (proc, &t.c_cc[VSWTCH], 1);
+	  send_process (proc, &t.c_cc[VSWTCH], 1, Qnil);
 	  return;
 #endif /* ! defined (SIGTSTP) */
 	}
@@ -2669,12 +2713,12 @@
 #endif /* ! defined (SIGCONT) */
     case SIGINT:
 #ifdef VMS
-      send_process (proc, "\003", 1);	/* ^C */
+      send_process (proc, "\003", 1, Qnil);	/* ^C */
       goto whoosh;
 #endif
     case SIGQUIT:
 #ifdef VMS
-      send_process (proc, "\031", 1);	/* ^Y */
+      send_process (proc, "\031", 1, Qnil);	/* ^Y */
       goto whoosh;
 #endif
     case SIGKILL:
@@ -2815,10 +2859,10 @@
   }
 #else /* did not do TOICREMOTE */
 #ifdef VMS
-  send_process (proc, "\032", 1); 	/* ^z */
+  send_process (proc, "\032", 1, Qnil); 	/* ^z */
 #else
   if (!NILP (XPROCESS (proc)->pty_flag))
-    send_process (proc, "\004", 1);
+    send_process (proc, "\004", 1, Qnil);
   else
     {
       close (XINT (XPROCESS (proc)->outfd));