Mailing-List: contact cygwin-developers-help AT sourceware DOT cygnus DOT com; run by ezmlm List-Subscribe: List-Archive: List-Post: List-Help: , 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 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 * 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 #include #include "local.h" + #ifdef __CYGWIN__ + #include + #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: < #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_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) { /*