MSVCRT: Handle \r at buffer boundary

Uwe Bonnes bon at hertz.ikp.physik.tu-darmstadt.de
Sun Jan 10 07:47:41 CST 2010


--text follows this line--
ADISIM
http://www.analog.com/en/clock-and-timing/clock-generation-and-distribution/products/dt-adisim-design-sim-tool/ADIsimCLK_evaluation_tools/resources/fca.html

failed to parse wizdefaults.lib when using builtin msvcrt and displayed hugh
numbers. This was caused when reading in textmode a \r on the buffer
boundary. The position of the filepointer in this case must be on the \r
when called by read(), but fgetc() always skips the \r. A test case is
included and validated against native msvcrt. Some more read() test cases
for the \r\n case are also added to show window behaviour.

Pleas let me know if the patch needs rework.
---
 dlls/msvcrt/file.c       |   18 ++++++++++++++----
 dlls/msvcrt/tests/file.c |   41 +++++++++++++++++++++++++++++++++++++++--
 2 files changed, 53 insertions(+), 6 deletions(-)

diff --git a/dlls/msvcrt/file.c b/dlls/msvcrt/file.c
index cbaa04e..bce0f65 100644
--- a/dlls/msvcrt/file.c
+++ b/dlls/msvcrt/file.c
@@ -1741,8 +1741,12 @@ int CDECL _rmtmp(void)
 
 /*********************************************************************
  * (internal) read_i
+ *
+ * When reading \r as last character in text mode, read() positions 
+ * the file pointer on the \r character while getc() goes on to
+ * the following \n
  */
-static int read_i(int fd, void *buf, unsigned int count)
+static int read_i(int fd, void *buf, unsigned int count, int pushback)
 {
   DWORD num_read;
   char *bufstart = buf;
@@ -1767,6 +1771,12 @@ static int read_i(int fd, void *buf, unsigned int count)
         if (MSVCRT_fdesc[fd].wxflag & WX_TEXT)
         {
             DWORD i, j;
+            if (bufstart[num_read-1] == '\r')
+            {
+                if(pushback)
+                   MSVCRT__lseeki64(fd, -1, SEEK_CUR);
+                num_read--;
+            }
             for (i=0, j=0; i<num_read; i++)
             {
                 /* in text mode, a ctrl-z signals EOF */
@@ -1818,7 +1828,7 @@ static int read_i(int fd, void *buf, unsigned int count)
 int CDECL MSVCRT__read(int fd, void *buf, unsigned int count)
 {
   int num_read;
-  num_read = read_i(fd, buf, count);
+  num_read = read_i(fd, buf, count,0);
   return num_read;
 }
 
@@ -2329,13 +2339,13 @@ int CDECL MSVCRT__filbuf(MSVCRT_FILE* file)
   if(file->_flag & MSVCRT__IONBF) {
 	unsigned char c;
         int r;
-  	if ((r = read_i(file->_file,&c,1)) != 1) {
+  	if ((r = read_i(file->_file,&c,1,1)) != 1) {
             file->_flag |= (r == 0) ? MSVCRT__IOEOF : MSVCRT__IOERR;
             return MSVCRT_EOF;
 	}
   	return c;
   } else {
-	file->_cnt = read_i(file->_file, file->_base, file->_bufsiz);
+    file->_cnt = read_i(file->_file, file->_base, file->_bufsiz,1);
 	if(file->_cnt<=0) {
             file->_flag |= (file->_cnt == 0) ? MSVCRT__IOEOF : MSVCRT__IOERR;
             file->_cnt = 0;
diff --git a/dlls/msvcrt/tests/file.c b/dlls/msvcrt/tests/file.c
index e164555..dd1baaa 100644
--- a/dlls/msvcrt/tests/file.c
+++ b/dlls/msvcrt/tests/file.c
@@ -422,6 +422,34 @@ static WCHAR* AtoW( const char* p )
     return buffer;
 }
 
+/* Test reading in text mode when the 512'th character read is \r*/
+static void test_readboundary(void)
+{
+  FILE *fp;
+  char buf[513], rbuf[513];
+  int i, j;
+  for (i = 0; i < 511; i++)
+    {
+      j = (i%('~' - ' ')+ ' ');
+      buf[i] = j;
+    }
+  buf[511] = '\n';
+  buf[512] =0;
+  fp = fopen("boundary.tst", "wt");
+  fwrite(buf, 512,1,fp);
+  fclose(fp);
+  fp = fopen("boundary.tst", "rt");
+  for(i=0; i<512; i++)
+    {
+      fseek(fp,0 , SEEK_CUR);
+      rbuf[i] = fgetc(fp);
+    }
+  rbuf[512] =0;
+  fclose(fp);
+
+  ok(strcmp(buf, rbuf) == 0,"CRLF on buffer boundary failure\n");
+  }
+
 static void test_fgetc( void )
 {
   char* tempf;
@@ -800,15 +828,23 @@ static void test_file_write_read( void )
   tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
   _lseek(tempfd, -1, FILE_END);
   ret = _read(tempfd,btext,LLEN);
-  ok(ret == 1, "_read expected 1 got bad length: %d\n", ret);
+  ok(ret == 1 && *btext == '\n', "_read expected 1 got bad length: %d\n", ret);
   _lseek(tempfd, -2, FILE_END);
   ret = _read(tempfd,btext,LLEN);
   ok(ret == 1 && *btext == '\n', "_read expected '\\n' got bad length: %d\n", ret);
   _lseek(tempfd, -3, FILE_END);
+  ret = _read(tempfd,btext,1);
+  ok(ret == 1 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret);
+  ok(tell(tempfd) == 41, "bad position %u expecting 41\n", tell(tempfd));
+  _lseek(tempfd, -3, FILE_END);
   ret = _read(tempfd,btext,2);
   ok(ret == 1 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret);
   ok(tell(tempfd) == 42, "bad position %u expecting 42\n", tell(tempfd));
-  _close(tempfd);
+  _lseek(tempfd, -3, FILE_END);
+  ret = _read(tempfd,btext,3);
+  ok(ret == 2 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret);
+  ok(tell(tempfd) == 43, "bad position %u expecting 43\n", tell(tempfd));
+   _close(tempfd);
 
   ret = unlink(tempf);
   ok( ret == 0 ,"Can't unlink '%s': %d\n", tempf, errno);
@@ -1388,6 +1424,7 @@ START_TEST(file)
     test_asciimode2();
     test_readmode(FALSE); /* binary mode */
     test_readmode(TRUE);  /* ascii mode */
+    test_readboundary();
     test_fgetc();
     test_fputc();
     test_flsbuf();
-- 
1.6.4.2




More information about the wine-patches mailing list