delorie.com/archives/browse.cgi   search  
Mail Archives: cygwin-developers/2000/05/01/12:10:41

Mailing-List: contact cygwin-developers-help AT sourceware DOT cygnus DOT com; run by ezmlm
List-Subscribe: <mailto:cygwin-developers-subscribe AT sourceware DOT cygnus DOT com>
List-Archive: <http://sourceware.cygnus.com/ml/cygwin-developers/>
List-Post: <mailto:cygwin-developers AT sourceware DOT cygnus DOT com>
List-Help: <mailto:cygwin-developers-help AT sourceware DOT cygnus DOT com>, <http://sourceware.cygnus.com/ml/#faqs>
Sender: cygwin-developers-owner AT sourceware DOT cygnus DOT com
Delivered-To: mailing list cygwin-developers AT sourceware DOT cygnus DOT com
Date: Mon, 1 May 2000 13:11:42 -0400
Message-Id: <200005011711.NAA16447@envy.delorie.com>
From: DJ Delorie <dj AT delorie DOT com>
To: cygwin-developers AT sourceware DOT cygnus DOT com
Subject: cygwin, ftell, cr/lf - better handling

A longstanding bug in cygwin is that ftell returns bogus values,
because it doesn't know what kind of line ending conversions cygwin
did before handing the buffer to newlib.  This patch moves the CR/LF
conversions to newlib, so that its buffers always reflect the actual
file (and thus ftell can be accurate).  As a bonus, fgetc and fgets
are much faster, with only a slight slowdown for fread.

Note that this bug only exists for DOS text files; Mac CR files won't
have this problem because text conversions preserve the number of
characters.

2000-05-01  DJ Delorie  <dj AT cygnus DOT com>

	* libc/include/stdio.h (FILE): define __SCLE for "convert line
 	endings" for Cygwin.
	(__sgetc): convert line endings if needed
	(__sputc): ditto
	* libc/stdio/fdopen.c (_fdopen_r): Remember if we opened in text mode
	* libc/stdio/fopen.c (_fopen_r): ditto
	* libc/stdio/freopen.c (freopen): ditto
	* libc/stdio/fread.c (fread): perform CRLF conversions if __SCLE
	* libc/stdio/fvwrite.c (__sfvwrite): ditto

Index: newlib/libc/include/stdio.h
===================================================================
RCS file: /cvs/src/src/newlib/libc/include/stdio.h,v
retrieving revision 1.1.1.1
diff -p -3 -r1.1.1.1 stdio.h
*** stdio.h	2000/02/17 19:39:46	1.1.1.1
--- stdio.h	2000/05/01 16:54:25
*************** typedef struct __sFILE FILE;
*** 66,71 ****
--- 66,74 ----
  #define	__SNPT	0x0800		/* do not do fseek() optimisation */
  #define	__SOFF	0x1000		/* set iff _offset is in fact correct */
  #define	__SMOD	0x2000		/* true => fgetline modified _p text */
+ #if defined(__CYGWIN__) || defined(__CYGWIN32__)
+ #define __SCLE	0x4000		/* convert line endings CR/LF <-> NL */
+ #endif
  
  /*
   * The following three definitions are for ANSI C, which took them
*************** FILE	*_EXFUN(funopen,(const _PTR _cookie
*** 251,257 ****
   * The __sfoo macros are here so that we can 
   * define function versions in the C library.
   */
! #define	__sgetc(p) (--(p)->_r < 0 ? __srget(p) : (int)(*(p)->_p++))
  #ifdef _never /* __GNUC__ */
  /* If this inline is actually used, then systems using coff debugging
     info get hopelessly confused.  21sept93 rich AT cygnus DOT com.  */
--- 254,279 ----
   * The __sfoo macros are here so that we can 
   * define function versions in the C library.
   */
! #define	__sgetc_raw(p) (--(p)->_r < 0 ? __srget(p) : (int)(*(p)->_p++))
! 
! #ifdef __SCLE
! static __inline__ int __sgetc(FILE *__p)
!   {
!     int __c = __sgetc_raw(__p);
!     if ((__p->_flags & __SCLE) && (__c == '\r'))
!       {
! 	int __c2 = __sgetc_raw(__p);
! 	if (__c2 == '\n')
! 	  __c = __c2;
! 	else
! 	  ungetc(__c2, __p);
!       }
!     return __c;
!   }
! #else
! #define __sgetc(p) __sgetc_raw(p)
! #endif
! 
  #ifdef _never /* __GNUC__ */
  /* If this inline is actually used, then systems using coff debugging
     info get hopelessly confused.  21sept93 rich AT cygnus DOT com.  */
*************** static __inline int __sputc(int _c, FILE
*** 265,271 ****
  /*
   * This has been tuned to generate reasonable code on the vax using pcc
   */
! #define	__sputc(c, p) \
  	(--(p)->_w < 0 ? \
  		(p)->_w >= (p)->_lbfsize ? \
  			(*(p)->_p = (c)), *(p)->_p != '\n' ? \
--- 287,293 ----
  /*
   * This has been tuned to generate reasonable code on the vax using pcc
   */
! #define	__sputc_raw(c, p) \
  	(--(p)->_w < 0 ? \
  		(p)->_w >= (p)->_lbfsize ? \
  			(*(p)->_p = (c)), *(p)->_p != '\n' ? \
*************** static __inline int __sputc(int _c, FILE
*** 273,278 ****
--- 295,308 ----
  				__swbuf('\n', p) : \
  			__swbuf((int)(c), p) : \
  		(*(p)->_p = (c), (int)*(p)->_p++))
+ #ifdef __SCLE
+ #define __sputc(c, p) \
+ 	  ((((p)->_flags & __SCLE) && ((c) == '\n')) \
+ 	    ? __sputc_raw('\r', (p)) : 0 , \
+ 	  __sputc_raw((c), (p)))
+ #else
+ #define __sputc(c, p) __sputc_raw(c, p)
+ #endif
  #endif
  
  #define	__sfeof(p)	(((p)->_flags & __SEOF) != 0)
Index: newlib/libc/stdio/fdopen.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/fdopen.c,v
retrieving revision 1.1.1.1
diff -p -3 -r1.1.1.1 fdopen.c
*** fdopen.c	2000/02/17 19:39:47	1.1.1.1
--- fdopen.c	2000/05/01 16:54:25
*************** _DEFUN (_fdopen_r, (ptr, fd, mode),
*** 100,105 ****
--- 100,111 ----
    fp->_write = __swrite;
    fp->_seek = __sseek;
    fp->_close = __sclose;
+ 
+ #ifdef __SCLE
+   if (setmode(fp->_file, O_BINARY) == O_TEXT)
+     fp->_flags |= __SCLE;
+ #endif
+ 
    return fp;
  }
  
Index: newlib/libc/stdio/fopen.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/fopen.c,v
retrieving revision 1.1.1.1
diff -p -3 -r1.1.1.1 fopen.c
*** fopen.c	2000/02/17 19:39:47	1.1.1.1
--- fopen.c	2000/05/01 16:54:25
*************** static char sccsid[] = "%W% (Berkeley) %
*** 116,121 ****
--- 116,124 ----
  #include <stdio.h>
  #include <errno.h>
  #include "local.h"
+ #ifdef __CYGWIN__
+ #include <fcntl.h>
+ #endif
  
  FILE *
  _DEFUN (_fopen_r, (ptr, file, mode),
*************** _DEFUN (_fopen_r, (ptr, file, mode),
*** 148,153 ****
--- 151,161 ----
  
    if (fp->_flags & __SAPP)
      fseek (fp, 0, SEEK_END);
+ 
+ #ifdef __SCLE
+   if (setmode(fp->_file, O_BINARY) == O_TEXT)
+     fp->_flags |= __SCLE;
+ #endif
  
    return fp;
  }
Index: newlib/libc/stdio/fread.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/fread.c,v
retrieving revision 1.1.1.1
diff -p -3 -r1.1.1.1 fread.c
*** fread.c	2000/02/17 19:39:47	1.1.1.1
--- fread.c	2000/05/01 16:54:25
*************** Supporting OS subroutines required: <<cl
*** 59,64 ****
--- 59,113 ----
  #include <string.h>
  #include "local.h"
  
+ #ifdef __SCLE
+ static size_t
+ _DEFUN (crlf, (fp, buf, count, eof),
+ 	FILE * fp _AND
+ 	char * buf _AND
+ 	size_t count _AND
+ 	int eof)
+ {
+   int newcount = 0, r;
+   char *s, *d, *e;
+ 
+   if (count == 0)
+     return 0;
+ 
+   e = buf + count;
+   for (s=d=buf; s<e-1; s++)
+     {
+       if (*s == '\r' && s[1] == '\n')
+ 	s++;
+       *d++ = *s;
+     }
+   if (s < e)
+     {
+       if (*s == '\r')
+ 	{
+ 	  int c = __sgetc_raw(fp);
+ 	  if (c == '\n')
+ 	    *s = '\n';
+ 	  else
+ 	    ungetc(c, fp);
+ 	}
+       *d++ = *s++;
+     }
+ 
+ 
+   while (d < e)
+     {
+       r = getc(fp);
+       if (r == EOF)
+ 	return count - (e-d);
+       *d++ = r;
+     }
+ 
+   return count;
+   
+ }
+ 
+ #endif
+ 
  size_t
  _DEFUN (fread, (buf, size, count, fp),
  	_PTR buf _AND
*************** _DEFUN (fread, (buf, size, count, fp),
*** 77,82 ****
--- 126,132 ----
      fp->_r = 0;
    total = resid;
    p = buf;
+ 
    while (resid > (r = fp->_r))
      {
        (void) memcpy ((void *) p, (void *) fp->_p, (size_t) r);
*************** _DEFUN (fread, (buf, size, count, fp),
*** 87,97 ****
--- 137,155 ----
        if (__srefill (fp))
  	{
  	  /* no more input: return partial result */
+ #ifdef __SCLE
+ 	  if (fp->_flags & __SCLE)
+ 	      return crlf(fp, buf, total-resid, 1) / size;
+ #endif
  	  return (total - resid) / size;
  	}
      }
    (void) memcpy ((void *) p, (void *) fp->_p, resid);
    fp->_r -= resid;
    fp->_p += resid;
+ #ifdef __SCLE
+   if (fp->_flags & __SCLE)
+     return crlf(fp, buf, total, 0) / size;
+ #endif
    return count;
  }
Index: newlib/libc/stdio/freopen.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/freopen.c,v
retrieving revision 1.1.1.1
diff -p -3 -r1.1.1.1 freopen.c
*** freopen.c	2000/02/17 19:39:47	1.1.1.1
--- freopen.c	2000/05/01 16:54:25
*************** _DEFUN (freopen, (file, mode, fp),
*** 147,151 ****
--- 147,157 ----
    fp->_write = __swrite;
    fp->_seek = __sseek;
    fp->_close = __sclose;
+ 
+ #ifdef __SCLE
+   if (setmode(fp->_file, O_BINARY) == O_TEXT)
+     fp->_flags |= __SCLE;
+ #endif
+ 
    return fp;
  }
Index: newlib/libc/stdio/fvwrite.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/fvwrite.c,v
retrieving revision 1.1.1.1
diff -p -3 -r1.1.1.1 fvwrite.c
*** fvwrite.c	2000/02/17 19:39:47	1.1.1.1
--- fvwrite.c	2000/05/01 16:54:25
*************** __sfvwrite (fp, uio)
*** 62,67 ****
--- 62,88 ----
  
    iov = uio->uio_iov;
    len = 0;
+ 
+ #ifdef __SCLE
+   if (fp->_flags & __SCLE) /* text mode */
+     {
+       do
+ 	{
+ 	  GETIOV (;);
+ 	  while (len > 0)
+ 	    {
+ 	      if (putc(*p, fp) == EOF)
+ 		return EOF;
+ 	      p++;
+ 	      len--;
+ 	      uio->uio_resid--;
+ 	    }
+ 	}
+       while (uio->uio_resid > 0);
+       return 0;
+     }
+ #endif
+ 
    if (fp->_flags & __SNBF)
      {
        /*

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019