Mail Archives: cygwin-developers/2000/05/01/12:10:41
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 -