Commit ebe4a9e3 authored by Dan Kegel's avatar Dan Kegel Committed by Alexandre Julliard

msvcrt: Remove CRs earlier in ascii mode.

parent 28ee1ee9
...@@ -1639,27 +1639,6 @@ int CDECL _rmtmp(void) ...@@ -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 * (internal) read_i
*/ */
static int read_i(int fd, void *buf, unsigned int count) 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) ...@@ -1686,18 +1665,25 @@ static int read_i(int fd, void *buf, unsigned int count)
{ {
if (MSVCRT_fdesc[fd].wxflag & WX_TEXT) if (MSVCRT_fdesc[fd].wxflag & WX_TEXT)
{ {
DWORD i; DWORD i, j;
/* in text mode, a ctrl-z signals EOF */ for (i=0, j=0; i<num_read; i++)
for (i=0; i<num_read; i++)
{ {
/* in text mode, a ctrl-z signals EOF */
if (bufstart[i] == 0x1a) if (bufstart[i] == 0x1a)
{ {
num_read = i;
MSVCRT_fdesc[fd].wxflag |= (WX_ATEOF|WX_READEOF); MSVCRT_fdesc[fd].wxflag |= (WX_ATEOF|WX_READEOF);
TRACE(":^Z EOF %s\n",debugstr_an(buf,num_read)); TRACE(":^Z EOF %s\n",debugstr_an(buf,num_read));
break; 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) if (count != 0 && num_read == 0)
{ {
...@@ -1732,10 +1718,6 @@ int CDECL MSVCRT__read(int fd, void *buf, unsigned int count) ...@@ -1732,10 +1718,6 @@ int CDECL MSVCRT__read(int fd, void *buf, unsigned int count)
{ {
int num_read; int num_read;
num_read = read_i(fd, buf, count); 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; return num_read;
} }
...@@ -2219,17 +2201,13 @@ int CDECL MSVCRT_fgetc(MSVCRT_FILE* file) ...@@ -2219,17 +2201,13 @@ int CDECL MSVCRT_fgetc(MSVCRT_FILE* file)
{ {
unsigned char *i; unsigned char *i;
unsigned int j; unsigned int j;
do { if (file->_cnt>0) {
if (file->_cnt>0) { file->_cnt--;
file->_cnt--; i = (unsigned char *)file->_ptr++;
i = (unsigned char *)file->_ptr++; j = *i;
j = *i; } else
} else j = MSVCRT__filbuf(file);
j = MSVCRT__filbuf(file); return j;
if (!(MSVCRT_fdesc[file->_file].wxflag & WX_TEXT)
|| ((j != '\r') || (file->_cnt && file->_ptr[0] != '\n')))
return j;
} while(1);
} }
/********************************************************************* /*********************************************************************
...@@ -2597,17 +2575,13 @@ MSVCRT_size_t CDECL MSVCRT_fread(void *ptr, MSVCRT_size_t size, MSVCRT_size_t nm ...@@ -2597,17 +2575,13 @@ MSVCRT_size_t CDECL MSVCRT_fread(void *ptr, MSVCRT_size_t size, MSVCRT_size_t nm
/* first buffered data */ /* first buffered data */
if(file->_cnt>0) { if(file->_cnt>0) {
while (file->_cnt>0 && rcnt > 0) {
int pcnt= (rcnt>file->_cnt)? file->_cnt:rcnt; int pcnt= (rcnt>file->_cnt)? file->_cnt:rcnt;
memcpy(ptr, file->_ptr, pcnt); memcpy(ptr, file->_ptr, pcnt);
file->_cnt -= pcnt; file->_cnt -= pcnt;
file->_ptr += pcnt; file->_ptr += pcnt;
if (MSVCRT_fdesc[file->_file].wxflag & WX_TEXT)
pcnt -= remove_cr(ptr,pcnt);
read += pcnt ; read += pcnt ;
rcnt -= pcnt ; rcnt -= pcnt ;
ptr = (char*)ptr + pcnt; ptr = (char*)ptr + pcnt;
}
} else if(!(file->_flag & MSVCRT__IOREAD )) { } else if(!(file->_flag & MSVCRT__IOREAD )) {
if(file->_flag & MSVCRT__IORW) { if(file->_flag & MSVCRT__IORW) {
file->_flag |= MSVCRT__IOREAD; file->_flag |= MSVCRT__IOREAD;
...@@ -2723,17 +2697,26 @@ int CDECL MSVCRT_fsetpos(MSVCRT_FILE* file, MSVCRT_fpos_t *pos) ...@@ -2723,17 +2697,26 @@ int CDECL MSVCRT_fsetpos(MSVCRT_FILE* file, MSVCRT_fpos_t *pos)
*/ */
LONG CDECL MSVCRT_ftell(MSVCRT_FILE* file) LONG CDECL MSVCRT_ftell(MSVCRT_FILE* file)
{ {
/* TODO: just call fgetpos and return lower half of result */
int off=0; int off=0;
long pos; long pos;
pos = _tell(file->_file);
if(pos == -1) return -1;
if(file->_bufsiz) { if(file->_bufsiz) {
if( file->_flag & MSVCRT__IOWRT ) { if( file->_flag & MSVCRT__IOWRT ) {
off = file->_ptr - file->_base; off = file->_ptr - file->_base;
} else { } else {
off = -file->_cnt; 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; return off + pos;
} }
...@@ -2742,22 +2725,25 @@ LONG CDECL MSVCRT_ftell(MSVCRT_FILE* file) ...@@ -2742,22 +2725,25 @@ LONG CDECL MSVCRT_ftell(MSVCRT_FILE* file)
*/ */
int CDECL MSVCRT_fgetpos(MSVCRT_FILE* file, MSVCRT_fpos_t *pos) int CDECL MSVCRT_fgetpos(MSVCRT_FILE* file, MSVCRT_fpos_t *pos)
{ {
/* This code has been lifted form the MSVCRT_ftell function */
int off=0; int off=0;
*pos = MSVCRT__lseeki64(file->_file,0,SEEK_CUR); *pos = MSVCRT__lseeki64(file->_file,0,SEEK_CUR);
if(*pos == -1) return -1;
if (*pos == -1) return -1;
if(file->_bufsiz) { if(file->_bufsiz) {
if( file->_flag & MSVCRT__IOWRT ) { if( file->_flag & MSVCRT__IOWRT ) {
off = file->_ptr - file->_base; off = file->_ptr - file->_base;
} else { } else {
off = -file->_cnt; 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; *pos += off;
return 0; return 0;
} }
......
...@@ -36,6 +36,37 @@ ...@@ -36,6 +36,37 @@
static HANDLE proc_handles[2]; 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 void test_fdopen( void )
{ {
static const char buffer[] = {0,1,2,3,4,5,6,7,8,9}; static const char buffer[] = {0,1,2,3,4,5,6,7,8,9};
...@@ -463,7 +494,7 @@ static void test_fgetwc( void ) ...@@ -463,7 +494,7 @@ static void test_fgetwc( void )
ok(l==BUFSIZ-2, "ftell expected %d got %ld\n", BUFSIZ-2, l); ok(l==BUFSIZ-2, "ftell expected %d got %ld\n", BUFSIZ-2, l);
fgetws(wtextW,LLEN,tempfh); fgetws(wtextW,LLEN,tempfh);
l=ftell(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); mytextW = AtoW (mytext);
aptr = mytextW; aptr = mytextW;
wptr = wtextW; wptr = wtextW;
...@@ -1146,6 +1177,7 @@ START_TEST(file) ...@@ -1146,6 +1177,7 @@ START_TEST(file)
test_unlink(); test_unlink();
/* testing stream I/O */ /* testing stream I/O */
test_filbuf();
test_fdopen(); test_fdopen();
test_fopen_fclose_fcloseall(); test_fopen_fclose_fcloseall();
test_fileops(); test_fileops();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment