2003-09-09  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 -acprNC5 sed-4.0.7.orig/lib/getline.c sed-4.0.7.djgpp/lib/getline.c
*** sed-4.0.7.orig/lib/getline.c	Tue Dec 24 09:49:18 2002
--- sed-4.0.7.djgpp/lib/getline.c	Tue Sep  9 01:31:06 2003
*************** getline (lineptr, n, stream)
*** 89,99 ****
    if (p == *lineptr)
      return -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 (p - 2 >= *lineptr && p[-2] == '\r')
      p[-2] = p[-1], --p;
  #endif
    *p = '\0';
    return p - *lineptr;
--- 89,99 ----
    if (p == *lineptr)
      return -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__) || defined(__DJGPP__)
    if (p - 2 >= *lineptr && p[-2] == '\r')
      p[-2] = p[-1], --p;
  #endif
    *p = '\0';
    return p - *lineptr;
diff -acprNC5 sed-4.0.7.orig/lib/utils.c sed-4.0.7.djgpp/lib/utils.c
*** sed-4.0.7.orig/lib/utils.c	Sat Mar 15 07:12:16 2003
--- sed-4.0.7.djgpp/lib/utils.c	Tue Sep  9 01:31:06 2003
***************
*** 36,45 ****
--- 36,53 ----
  #endif /* HAVE_STDLIB_H */
  
  #include "basicdefs.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;
  
  void do_ck_fclose P_((FILE *stream));
  
  /* Print an error message and exit */
*************** utils_fp_name(fp)
*** 108,117 ****
--- 116,140 ----
      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;
*************** ck_fopen(name, mode, fail)
*** 146,168 ****
    p->name = ck_strdup(name);
    p->fp = fp;
    return fp;
  }
  
  /* 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));
  }
  
  /* Panic on failing fread */
  size_t
  ck_fread(ptr, size, nmemb, stream)
--- 169,243 ----
    p->name = ck_strdup(name);
    p->fp = fp;
    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);
! 
! #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 -acprNC5 sed-4.0.7.orig/lib/utils.h sed-4.0.7.djgpp/lib/utils.h
*** sed-4.0.7.orig/lib/utils.h	Sat Jan  4 01:29:46 2003
--- sed-4.0.7.djgpp/lib/utils.h	Tue Sep  9 01:31:06 2003
***************
*** 16,27 ****
--- 16,39 ----
      along with this program; if not, write to the Free Software
      Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
  
  #include <stdio.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, flagT 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 -acprNC5 sed-4.0.7.orig/sed/execute.c sed-4.0.7.djgpp/sed/execute.c
*** sed-4.0.7.orig/sed/execute.c	Tue Mar 25 17:51:22 2003
--- sed-4.0.7.djgpp/sed/execute.c	Tue Sep  9 01:31:06 2003
*************** dump_append_queue()
*** 452,463 ****
--- 452,507 ----
  	     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)
+ 		{
+ #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);
+ 		}
  	      ck_fclose(fp);
  	    }
  	}
      }
    release_append_queue();
*************** open_next_file(name, input)
*** 518,527 ****
--- 562,573 ----
        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;
