2004-08-13  Juan M. Guerrero  <st001906@hrz1.hrz.tu-darmstadt.de>

	* lib/getline.c [__DJGPP__]: strip trailing CR.
	* sed/utils.h: Include fcntl.h.
	(O_BINARY, setmode): Define if O_BINARY is undefined.
	[O_BINARY]: Include io.h.
	(set_read_mode): Declare a prototype.

	* sed/utils.c [O_BINARY]: Include sys/stat.h and make sure S_ISCHR
	is defined.
	(set_read_mode): New function, switches a stream into binary mode.
	This is a no-op unless O_BINARY is defined.
        (is_a_device): New function, checks if the file pointer is associated
        to stdout.
	(ck_fwrite) [O_BINARY]: If we are writing to a character device,
	replace every ^Z character with an ASCII string "^Z".

	* sed/execute.c	(dump_append_queue): Call set_read_mode.
	[O_BINARY]: Remove ^M, if before the newline, and ^Z, if
	immediately before EOF.
	(open_next_file): Call set_read_mode.



diff -apruNU5 sed-4.1.1.orig/lib/getline.c sed-4.1.1.djgpp/lib/getline.c
--- sed-4.1.1.orig/lib/getline.c	2004-01-04 22:47:36.000000000 +0000
+++ sed-4.1.1.djgpp/lib/getline.c	2004-08-13 00:17:20.000000000 +0000
@@ -99,11 +99,11 @@ getline (lineptr, n, stream)
   if (p == *lineptr)
     return (size_t) -1;
 
   /* Return a partial line since we got an error in the middle.  */
  win:
-#if defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__) || defined(MSDOS) || defined(__EMX__)
+#if defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__) || defined(MSDOS) || defined(__EMX__) || defined(__DJGPP__)
   if (p - 2 >= *lineptr && p[-2] == '\r')
     p[-2] = p[-1], --p;
 #endif
   *p = '\0';
   return p - *lineptr;
diff -apruNU5 sed-4.1.1.orig/lib/utils.c sed-4.1.1.djgpp/lib/utils.c
--- sed-4.1.1.orig/lib/utils.c	2004-06-29 18:04:32.000000000 +0000
+++ sed-4.1.1.djgpp/lib/utils.c	2004-08-13 00:17:20.000000000 +0000
@@ -35,10 +35,18 @@
 # include <stdlib.h>
 #endif /* HAVE_STDLIB_H */
 
 #include "utils.h"
 
+#ifdef O_BINARY
+# include <sys/types.h>
+# include <sys/stat.h>
+# ifndef S_ISCHR
+#  define S_ISCHR(m)  (((m) & S_IFMT) == S_IFCHR)
+# endif
+#endif
+
 const char *myname;
 
 /* Store information about files opened with ck_fopen
    so that error messages from ck_fread, ck_fwrite, etc. can print the
    name of the file that had the error */
@@ -124,10 +132,25 @@ utils_fp_name(fp)
     return "stderr";
 
   return "<unknown>";
 }
 
+void
+set_read_mode (fp)
+  FILE *fp;
+{
+#ifdef O_BINARY
+  /* For systems that distinguish between text and binary files,
+     switch all input streams to binary mode.  This is so we get all
+     the characters from the file, instead of relying on the
+     misfeatures of the C library conversions (e.g., most of them drop
+     lone ^M characters, stop at the first ^Z character, etc.)  */
+  if (!isatty(fileno(fp)))
+    setmode(fileno(fp), O_BINARY);
+#endif
+}
+
 /* Panic on failing fopen */
 FILE *
 ck_fopen(name, mode, fail)
   const char *name;
   const char *mode;
@@ -205,23 +228,74 @@ ck_mkstemp (p_filename, tmpdir, base)
   p->link = utils_id_s;
   utils_id_s = p;
   return fp;
 }
 
+#ifdef O_BINARY
+static int stdout_is_a_device;
+
+static int __inline__ is_a_device P_((FILE *fp));
+static int __inline__
+is_a_device(fp)
+  FILE *fp;
+{
+  struct stat st;
+
+  if (fp == stdout)
+    {
+      /* Warning!  This assumes stdout is never switched during the
+	 program's run!  */
+      if (stdout_is_a_device == -1
+	  && fstat(fileno(stdout), &st) == 0)
+	stdout_is_a_device = S_ISCHR(st.st_mode) != 0;
+      return stdout_is_a_device == 1;
+    }
+  else
+    return fstat(fileno(fp), &st) == 0 && S_ISCHR(st.st_mode);
+}
+#endif
+
 /* Panic on failing fwrite */
 void
 ck_fwrite(ptr, size, nmemb, stream)
   const VOID *ptr;
   size_t size;
   size_t nmemb;
   FILE *stream;
 {
   clearerr(stream);
-  if (size && fwrite(ptr, size, nmemb, stream) != nmemb)
-    panic(ngettext("couldn't write %d item to %s: %s",
-		   "couldn't write %d items to %s: %s", nmemb), 
-		nmemb, utils_fp_name(stream), strerror(errno));
+
+#ifdef O_BINARY
+  if (!size)
+    return;
+  if (is_a_device(stream))
+    {
+      char *p;
+      size_t left = nmemb * size;
+
+      /* Text-mode writes to character devices stop at the first ^Z
+	 character.  Repair this lossage.  */
+      while ((p = memchr(ptr, 0x1a, left)) != NULL)
+	{
+	  size_t this_write = p - (char *)ptr;
+
+	  if (fwrite(ptr, 1, this_write, stream) != this_write)
+	    break;
+	  fwrite("^Z", 1, 2, stream);
+	  left -= this_write + 1;
+	  ptr = (char *)ptr + this_write + 1;
+	}
+      if (p == NULL && fwrite(ptr, 1, left, stream) == left)
+	return;
+    }
+  else
+#endif
+  if (!size || fwrite(ptr, size, nmemb, stream) == nmemb)
+    return;
+  panic(ngettext("couldn't write %d item to %s: %s",
+		 "couldn't write %d items to %s: %s", nmemb), 
+	nmemb, utils_fp_name(stream), strerror(errno));
 }
 
 /* Panic on failing fread */
 size_t
 ck_fread(ptr, size, nmemb, stream)
diff -apruNU5 sed-4.1.1.orig/lib/utils.h sed-4.1.1.djgpp/lib/utils.h
--- sed-4.1.1.orig/lib/utils.h	2004-03-13 09:14:56.000000000 +0000
+++ sed-4.1.1.djgpp/lib/utils.h	2004-08-13 00:17:20.000000000 +0000
@@ -18,12 +18,24 @@
 
 #include <stdio.h>
 
 #include "basicdefs.h"
 
+#include <fcntl.h>
+#ifndef O_BINARY
+# ifdef _O_BINARY
+#  define O_BINARY _O_BINARY
+#  define setmode  _setmode
+# endif
+#endif
+#ifdef O_BINARY
+# include <io.h>
+#endif
+
 void panic P_((const char *str, ...));
 
+void set_read_mode P_((FILE *stream));
 FILE *ck_fopen P_((const char *name, const char *mode, bool fail));
 void ck_fwrite P_((const VOID *ptr, size_t size, size_t nmemb, FILE *stream));
 size_t ck_fread P_((VOID *ptr, size_t size, size_t nmemb, FILE *stream));
 void ck_fflush P_((FILE *stream));
 void ck_fclose P_((FILE *stream));
diff -apruNU5 sed-4.1.1.orig/sed/execute.c sed-4.1.1.djgpp/sed/execute.c
--- sed-4.1.1.orig/sed/execute.c	2004-07-01 16:28:58.000000000 +0000
+++ sed-4.1.1.djgpp/sed/execute.c	2004-08-13 00:17:20.000000000 +0000
@@ -582,12 +582,56 @@ dump_append_queue()
 	     condition."  IEEE Std 1003.2-1992
 	     So, don't fail. */
 	  fp = ck_fopen(p->fname, "r", false);
 	  if (fp)
 	    {
+	      set_read_mode(fp);
 	      while ((cnt = ck_fread(buf, 1, sizeof buf, fp)) > 0)
-		ck_fwrite(buf, 1, cnt, output_file.fp);
+		{
+#ifdef O_BINARY
+		  /* Remove CRs from CR-LF pairs, and the trailing ^Z.  */
+		  register char *src = buf, *dest = buf;
+		  register size_t len = cnt;
+
+		  while (len--)
+		    {
+		      if (*src == '\r' || *src == 0x1a)
+			{
+			  if (!len)
+			    {
+			      if (getc(fp) != EOF)
+				{
+				  if (*src == '\r')
+				    {
+				      fseek(fp, -2L, SEEK_CUR);
+				      cnt--;
+				    }
+				  else
+				    {
+				      fseek(fp, -1L, SEEK_CUR);
+				      *dest++ = *src++;
+				    }
+				  break;
+				}
+			      else if (*src == 0x1a)
+				{
+				  cnt--;
+				  break;
+				}
+			    }
+			  else if (src[1] == '\n')
+			    {
+			      src++;
+			      len--;
+			      cnt--;
+			    }
+			}
+		      *dest++ = *src++;
+		    }
+#endif
+		  ck_fwrite(buf, 1, cnt, output_file.fp);
+		}
 	      ck_fclose(fp);
 	    }
 	}
     }
 
@@ -650,10 +694,12 @@ open_next_file(name, input)
       input->read_fn = read_always_fail; /* a redundancy */
       ++input->bad_count;
       return;
     }
 
+  set_read_mode (input->fp); /* for systems with text/binary schizophrenia */
+
   input->read_fn = read_file_line;
 
   if (in_place_extension)
     {
       int output_fd;
