diff src/callproc.c @ 17025:3c222a7edda1

Include charset.h and coding.h. (Fcall_process): Perform character code conversion of a process arguments and the process output. (Fcall_process_region): Encode coding of a text given to a process.
author Karl Heuer <kwzh@gnu.org>
date Thu, 20 Feb 1997 06:46:14 +0000
parents e7bf457086fb
children 19b17b4f765d
line wrap: on
line diff
--- a/src/callproc.c	Thu Feb 20 06:45:50 1997 +0000
+++ b/src/callproc.c	Thu Feb 20 06:46:14 1997 +0000
@@ -71,6 +71,8 @@
 #include "lisp.h"
 #include "commands.h"
 #include "buffer.h"
+#include "charset.h"
+#include "coding.h"
 #include <paths.h>
 #include "process.h"
 #include "syssignal.h"
@@ -219,6 +221,9 @@
 #if 0
   int mask;
 #endif
+  struct coding_system process_coding; /* coding-system of process output */
+  struct coding_system argument_coding;	/* coding-system of arguments */
+
   CHECK_STRING (args[0], 0);
 
   error_file = Qt;
@@ -229,6 +234,50 @@
     error ("Operating system cannot handle asynchronous subprocesses");
 #endif /* subprocesses */
 
+  /* Decide the coding-system for giving arguments and reading process
+     output.  */
+  {
+    Lisp_Object val, *args2;
+    /* Qt denotes that we have not yet called Ffind_coding_system.  */
+    Lisp_Object coding_systems = Qt;
+    int i;
+
+    /* If arguments are supplied, we may have to encode them.  */
+    if (nargs >= 5)
+      {
+	if (NILP (val = Vcoding_system_for_write))
+	  {
+	    args2 = (Lisp_Object *) alloca ((nargs + 1) * sizeof *args2);
+	    args2[0] = Qcall_process;
+	    for (i = 0; i < nargs; i++) args2[i + 1] = args[i];
+	    coding_systems = Ffind_coding_system (nargs + 1, args2);
+	    val = CONSP (coding_systems) ? XCONS (coding_systems)->cdr : Qnil;
+	  }
+	setup_coding_system (Fcheck_coding_system (val), &argument_coding);
+      }
+
+    /* If BUFFER is nil, we must read process output once and then
+       discard it, so setup coding system but with nil.  If BUFFER is
+       an integer, we can discard it without reading.  */
+    if (nargs < 3 || NILP (args[2]))
+      setup_coding_system (Qnil, &process_coding);
+    else if (!INTEGERP (args[2]))
+      {
+	if (NILP (val = Vcoding_system_for_read))
+	  {
+	    if (!EQ (coding_systems, Qt))
+	      {
+		args2 = (Lisp_Object *) alloca ((nargs + 1) * sizeof *args2);
+		args2[0] = Qcall_process;
+		for (i = 0; i < nargs; i++) args2[i + 1] = args[i];
+		coding_systems = Ffind_coding_system (nargs + 1, args2);
+	      }
+	    val = CONSP (coding_systems) ? XCONS (coding_systems)->car : Qnil;
+	  }
+	setup_coding_system (Fcheck_coding_system (val), &process_coding);
+      }
+  }
+
   if (nargs >= 2 && ! NILP (args[1]))
     {
       infile = Fexpand_file_name (args[1], current_buffer->directory);
@@ -328,7 +377,21 @@
     for (i = 4; i < nargs; i++)
       {
 	CHECK_STRING (args[i], i);
-	new_argv[i - 3] = XSTRING (args[i])->data;
+	if (argument_coding.type == coding_type_no_conversion)
+	  new_argv[i - 3] = XSTRING (args[i])->data;
+	else
+	  {
+	    /* We must encode the arguments.  */
+	    int size = encoding_buffer_size (&argument_coding,
+					     XSTRING (args[i])->size);
+	    int produced, dummy;
+
+	    new_argv[i - 3] = (unsigned char *) alloca (size);
+	    produced = encode_coding (&argument_coding,
+				      XSTRING (args[i])->data, new_argv[i - 3],
+				      XSTRING (args[i])->size, size, &dummy);
+	    new_argv[i - 3][produced] = 0;
+	  }
       }
     new_argv[i - 3] = 0;
   }
@@ -440,7 +503,9 @@
     if (fd_error != outfilefd)
       close (fd_error);
     fd1 = -1; /* No harm in closing that one!  */
-    fd[0] = open (tempfile, NILP (Vbinary_process_output) ? O_TEXT : O_BINARY);
+    /* Since CRLF is converted to LF within `decode_coding', we can
+       always open a file with binary mode.  */
+    fd[0] = open (tempfile, O_BINARY);
     if (fd[0] < 0)
       {
 	unlink (tempfile);
@@ -530,7 +595,7 @@
 	   of the buffer size we have.  But don't read
 	   less than 1024--save that for the next bufferful.  */
 
-	nread = 0;
+	nread = process_coding.carryover_size; /* This value is initially 0. */
 	while (nread < bufsize - 1024)
 	  {
 	    int this_read
@@ -549,13 +614,32 @@
 
 	/* Now NREAD is the total amount of data in the buffer.  */
 	if (nread == 0)
-	  break;
+	  /* Here, just tell decode_coding that we are processing the
+             last block.  We break the loop after decoding.  */
+	  process_coding.last_block = 1;
 
 	immediate_quit = 0;
 	total_read += nread;
 	
 	if (!NILP (buffer))
-	  insert (bufptr, nread);
+	  {
+	    if (process_coding.type == coding_type_no_conversion)
+	      insert (bufptr, nread);
+	    else
+	      {			/* We have to decode the input.  */
+		int size = decoding_buffer_size (&process_coding, bufsize);
+		char *decoding_buf = get_conversion_buffer (size);
+		int dummy;
+
+		nread = decode_coding (&process_coding, bufptr, decoding_buf,
+				       nread, size, &dummy);
+		if (nread > 0)
+		  insert (decoding_buf, nread);
+	      }
+	  }
+
+	if (process_coding.last_block)
+	  break;
 
 	/* Make the buffer bigger as we continue to read more data,
 	   but not past 64k.  */
@@ -565,6 +649,12 @@
 	    bufptr = (char *) alloca (bufsize);
 	  }
 
+	if (!NILP (buffer) && process_coding.carryover_size > 0)
+	  /* We have carryover in the last decoding.  It should be
+             processed again after reading more data.  */
+	  bcopy (process_coding.carryover, bufptr,
+		 process_coding.carryover_size);
+
 	if (!NILP (display) && INTERACTIVE)
 	  {
 	    if (first)
@@ -634,6 +724,10 @@
   Lisp_Object filename_string;
   register Lisp_Object start, end;
   int count = specpdl_ptr - specpdl;
+  /* Qt denotes that we have not yet called Ffind_coding_system.  */
+  Lisp_Object coding_systems = Qt;
+  Lisp_Object val, *args2;
+  int i;
 #ifdef DOS_NT
   char *tempfile;
   char *outf = '\0';
@@ -668,13 +762,41 @@
   GCPRO1 (filename_string);
   start = args[0];
   end = args[1];
+  /* Decide coding-system of the contents of the temporary file.  */
 #ifdef DOS_NT
   specbind (Qbuffer_file_type, Vbinary_process_input);
+  if (NILP (Vbinary_process_input))
+    val = Qnil;
+  else
+#endif
+    if (NILP (val = Vcoding_system_for_write))
+      {
+	args2 = (Lisp_Object *) alloca ((nargs + 1) * sizeof *args2);
+	args2[0] = Qcall_process_region;
+	for (i = 0; i < nargs; i++) args2[i + 1] = args[i];
+	coding_systems = Ffind_coding_system (nargs + 1, args2);
+	val = CONSP (coding_systems) ? XCONS (coding_systems)->cdr : Qnil;
+      }
+  specbind (intern ("coding-system-for-write"), val);
   Fwrite_region (start, end, filename_string, Qnil, Qlambda, Qnil);
-  unbind_to (count, Qnil);
-#else  /* not DOS_NT */
-  Fwrite_region (start, end, filename_string, Qnil, Qlambda, Qnil);
-#endif /* not DOS_NT */
+
+#ifdef DOS_NT
+  if (NILP (Vbinary_process_input))
+    val = Qnil;
+  else
+#endif
+    if (NILP (val = Vcoding_system_for_read))
+      {
+	if (EQ (coding_systems, Qt))
+	  {
+	    args2 = (Lisp_Object *) alloca ((nargs + 1) * sizeof *args2);
+	    args2[0] = Qcall_process_region;
+	    for (i = 0; i < nargs; i++) args2[i + 1] = args[i];
+	    coding_systems = Ffind_coding_system (nargs + 1, args2);
+	  }
+	val = CONSP (coding_systems) ? XCONS (coding_systems)->car : Qnil;
+      }
+  specbind (intern ("coding-system-for-read"), val);
 
   record_unwind_protect (delete_temp_file, filename_string);