Module: wine Branch: master Commit: ebe4a9e321800fbe6d2004a640cd276a28d15c38 URL: http://source.winehq.org/git/wine.git/?a=commit;h=ebe4a9e321800fbe6d2004a640...
Author: Dan Kegel dank@kegel.com Date: Sun Jan 18 19:19:46 2009 -0800
msvcrt: Remove CRs earlier in ascii mode.
---
dlls/msvcrt/file.c | 90 +++++++++++++++++++-------------------------- dlls/msvcrt/tests/file.c | 34 +++++++++++++++++- 2 files changed, 71 insertions(+), 53 deletions(-)
diff --git a/dlls/msvcrt/file.c b/dlls/msvcrt/file.c index 8945044..e3bc6c4 100644 --- a/dlls/msvcrt/file.c +++ b/dlls/msvcrt/file.c @@ -1639,27 +1639,6 @@ int CDECL _rmtmp(void) }
/********************************************************************* - * (internal) remove_cr - * - * Translate all \r\n to \n inplace. - * return the number of \r removed - * Corner cases required by some apps: - * \r\r\n -> \r\n - * BUG: should save state across calls somehow, so CR LF that - * straddles buffer boundary gets recognized properly? - */ -static unsigned int remove_cr(char *buf, unsigned int count) -{ - unsigned int i, j; - - for (i=0, j=0; j < count; j++) - if ((buf[j] != '\r') || ((j+1) < count && buf[j+1] != '\n')) - buf[i++] = buf[j]; - - return count - i; -} - -/********************************************************************* * (internal) read_i */ static int read_i(int fd, void *buf, unsigned int count) @@ -1686,18 +1665,25 @@ static int read_i(int fd, void *buf, unsigned int count) { if (MSVCRT_fdesc[fd].wxflag & WX_TEXT) { - DWORD i; - /* in text mode, a ctrl-z signals EOF */ - for (i=0; i<num_read; i++) + DWORD i, j; + for (i=0, j=0; i<num_read; i++) { + /* in text mode, a ctrl-z signals EOF */ if (bufstart[i] == 0x1a) { - num_read = i; MSVCRT_fdesc[fd].wxflag |= (WX_ATEOF|WX_READEOF); TRACE(":^Z EOF %s\n",debugstr_an(buf,num_read)); break; } + /* in text mode, strip \r if followed by \n. + * BUG: should save state across calls somehow, so CR LF that + * straddles buffer boundary gets recognized properly? + */ + if ((bufstart[i] != '\r') + || ((i+1) < num_read && bufstart[i+1] != '\n')) + bufstart[j++] = bufstart[i]; } + num_read = j; } if (count != 0 && num_read == 0) { @@ -1732,10 +1718,6 @@ int CDECL MSVCRT__read(int fd, void *buf, unsigned int count) { int num_read; num_read = read_i(fd, buf, count); - if (num_read>0 && MSVCRT_fdesc[fd].wxflag & WX_TEXT) - { - num_read -= remove_cr(buf,num_read); - } return num_read; }
@@ -2219,17 +2201,13 @@ int CDECL MSVCRT_fgetc(MSVCRT_FILE* file) { unsigned char *i; unsigned int j; - do { - if (file->_cnt>0) { - file->_cnt--; - i = (unsigned char *)file->_ptr++; - j = *i; - } else - j = MSVCRT__filbuf(file); - if (!(MSVCRT_fdesc[file->_file].wxflag & WX_TEXT) - || ((j != '\r') || (file->_cnt && file->_ptr[0] != '\n'))) - return j; - } while(1); + if (file->_cnt>0) { + file->_cnt--; + i = (unsigned char *)file->_ptr++; + j = *i; + } else + j = MSVCRT__filbuf(file); + return j; }
/********************************************************************* @@ -2597,17 +2575,13 @@ MSVCRT_size_t CDECL MSVCRT_fread(void *ptr, MSVCRT_size_t size, MSVCRT_size_t nm
/* first buffered data */ if(file->_cnt>0) { - while (file->_cnt>0 && rcnt > 0) { int pcnt= (rcnt>file->_cnt)? file->_cnt:rcnt; memcpy(ptr, file->_ptr, pcnt); file->_cnt -= pcnt; file->_ptr += pcnt; - if (MSVCRT_fdesc[file->_file].wxflag & WX_TEXT) - pcnt -= remove_cr(ptr,pcnt); read += pcnt ; rcnt -= pcnt ; ptr = (char*)ptr + pcnt; - } } else if(!(file->_flag & MSVCRT__IOREAD )) { if(file->_flag & MSVCRT__IORW) { file->_flag |= MSVCRT__IOREAD; @@ -2723,17 +2697,26 @@ int CDECL MSVCRT_fsetpos(MSVCRT_FILE* file, MSVCRT_fpos_t *pos) */ LONG CDECL MSVCRT_ftell(MSVCRT_FILE* file) { + /* TODO: just call fgetpos and return lower half of result */ int off=0; long pos; + pos = _tell(file->_file); + if(pos == -1) return -1; if(file->_bufsiz) { if( file->_flag & MSVCRT__IOWRT ) { off = file->_ptr - file->_base; } else { off = -file->_cnt; + if (MSVCRT_fdesc[file->_file].wxflag & WX_TEXT) { + /* Black magic correction for CR removal */ + int i; + for (i=0; i<file->_cnt; i++) { + if (file->_ptr[i] == '\n') + off--; + } + } } } - pos = _tell(file->_file); - if(pos == -1) return pos; return off + pos; }
@@ -2742,22 +2725,25 @@ LONG CDECL MSVCRT_ftell(MSVCRT_FILE* file) */ int CDECL MSVCRT_fgetpos(MSVCRT_FILE* file, MSVCRT_fpos_t *pos) { - /* This code has been lifted form the MSVCRT_ftell function */ int off=0; - *pos = MSVCRT__lseeki64(file->_file,0,SEEK_CUR); - - if (*pos == -1) return -1; - + if(*pos == -1) return -1; if(file->_bufsiz) { if( file->_flag & MSVCRT__IOWRT ) { off = file->_ptr - file->_base; } else { off = -file->_cnt; + if (MSVCRT_fdesc[file->_file].wxflag & WX_TEXT) { + /* Black magic correction for CR removal */ + int i; + for (i=0; i<file->_cnt; i++) { + if (file->_ptr[i] == '\n') + off--; + } + } } } *pos += off; - return 0; }
diff --git a/dlls/msvcrt/tests/file.c b/dlls/msvcrt/tests/file.c index 91effe9..44ca961 100644 --- a/dlls/msvcrt/tests/file.c +++ b/dlls/msvcrt/tests/file.c @@ -36,6 +36,37 @@
static HANDLE proc_handles[2];
+static void test_filbuf( void ) +{ + FILE *fp; + int c; + fpos_t pos; + + fp = fopen("filbuf.tst", "wb"); + fwrite("\n\n\n\n", 1, 4, fp); + fclose(fp); + + fp = fopen("filbuf.tst", "rt"); + c = _filbuf(fp); + ok(c == '\n', "read wrong byte\n"); + /* See bug 16970 for why we care about _filbuf. + * ftell returns screwy values on files with lots + * of bare LFs in ascii mode because it assumes + * that ascii files contain only CRLFs, removes + * the CR's early in _filbuf, and adjusts the return + * value of ftell to compensate. + * native _filbuf will read the whole file, then consume and return + * the first one. That leaves fp->_fd at offset 4, and fp->_ptr + * pointing to a buffer of three bare LFs, so + * ftell will return 4 - 3 - 3 = -2. + */ + ok(ftell(fp) == -2, "ascii crlf removal does not match native\n"); + ok(fgetpos(fp, &pos) == 0, "fgetpos fail\n"); + ok(pos == -2, "ftell does not match fgetpos\n"); + fclose(fp); + unlink("filbuf.tst"); +} + static void test_fdopen( void ) { static const char buffer[] = {0,1,2,3,4,5,6,7,8,9}; @@ -463,7 +494,7 @@ static void test_fgetwc( void ) ok(l==BUFSIZ-2, "ftell expected %d got %ld\n", BUFSIZ-2, l); fgetws(wtextW,LLEN,tempfh); l=ftell(tempfh); - ok(l==BUFSIZ-2+strlen(mytext), "ftell got %ld\n", l); + ok(l==BUFSIZ-2+strlen(mytext), "ftell expected %d got %ld\n", BUFSIZ-2+strlen(mytext), l); mytextW = AtoW (mytext); aptr = mytextW; wptr = wtextW; @@ -1146,6 +1177,7 @@ START_TEST(file) test_unlink();
/* testing stream I/O */ + test_filbuf(); test_fdopen(); test_fopen_fclose_fcloseall(); test_fileops();