Date: Sun, 18 Feb 1996 15:07:43 +0200 (IST) From: Eli Zaretskii To: Robert Hoehne Cc: djgpp AT delorie DOT com, DJ Delorie Subject: Re: Patch 2.1 from DJGPP V2.0 doesn't work In-Reply-To: <4fv73i$dhn@pyrrhus-f.hrz.tu-chemnitz.de> Message-Id: Mime-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII On 15 Feb 1996, Robert Hoehne wrote: > Patch 2.1 from DJGPP V2.0 doesn't work [snipp] > Hmm... Looks like a new-style context diff to me... > Exiting due to signal SIGABRT > Assertion failed at pch.c line 409: p_base <= file_pos > > > I think, this is only an error in compiling patch. No, it's a bug in the library function `ftell' (unless I didn't understand its code). It incorrectly assumes that, for files open for reading, the position returned by `lseek (file, 0L, SEEK_CUR)' corresponds to the *beginning* of the buffered portion of the file. The truth is, that it corresponds to the *end* of that buffered portion. Below please find a patch to fix this problem. When linked with the fixed version of `ftell', `patch' works under v2.0 (at least for the simple test submitted by Robert). The test program `fseek' from djtst200.zip also succeeds with the fixed version of `ftell', except with Unix-style text files (without a CR before each NL) in TEXT mode. The original code also failed in that case, and IMHO there is no way to make it work unless some low-level library function (like `filbuf') detects that this is a Unix-style file and sets a flag which could be tested by `ftell'. DJ, can we make such a change? I can submit it, if we decide to do it (but then I already submitted it once and it wasn't installed ;-). *** ansi/stdio/ftell.c~0 Mon Feb 5 00:13:42 1996 --- ansi/stdio/ftell.c Sun Feb 18 14:35:22 1996 *************** *** 17,44 **** f->_cnt = 0; if (f->_flag&_IOREAD) { if (__file_handle_modes[f->_file] & O_TEXT) /* if a text file */ { ! if (f->_cnt && f->_ptr != f->_base) { char *cp; ! adjust = - f->_bufsiz + (f->_ptr-f->_base); ! for (cp=f->_base; cp < f->_ptr; cp++) /* for every char in buf */ ! if (*cp == '\n') /* if it's LF */ ! adjust++; /* there was a CR also */ } } - else - adjust = - f->_cnt; } else if (f->_flag&(_IOWRT|_IORW)) { ! adjust = 0; if (f->_flag&_IOWRT && f->_base && (f->_flag&_IONBF)==0) { ! adjust = f->_ptr - f->_base; if (__file_handle_modes[f->_file] & O_TEXT) ! for (idx=0; idx_base[idx] == '\n') adjust++; } --- 17,55 ---- f->_cnt = 0; if (f->_flag&_IOREAD) { + /* When reading files, the file position known by `lseek' is + at the end of the buffered portion of the file. So `adjust' + is negative (current buf position is BEFORE the one returned + by `lseek') and, for TEXT files, it gets decremented (larger + in absolute value) for every NL from current pos to the end + of the buffer, to account for stripped CR characters. */ + adjust = - f->_cnt; + if (__file_handle_modes[f->_file] & O_TEXT) /* if a text file */ { ! if (f->_cnt) { char *cp; ! ! /* For every char in buf AFTER current pos... */ ! for (cp=f->_ptr + f->_cnt - 1; cp >= f->_ptr; cp--) ! if (*cp == '\n') /* ...if it's LF... */ ! adjust--; /* ...there was a CR also */ } } } else if (f->_flag&(_IOWRT|_IORW)) { ! /* When writing a file, the current file position known by `lseek' ! is at the beginning of the buffered portion of the file. We ! have to adjust it by our offset from the beginning of the buffer, ! and account for the CR characters which will be added by `write'. */ if (f->_flag&_IOWRT && f->_base && (f->_flag&_IONBF)==0) { ! int lastidx = adjust = f->_ptr - f->_base; ! if (__file_handle_modes[f->_file] & O_TEXT) ! for (idx=0; idx < lastidx; idx++) if (f->_base[idx] == '\n') adjust++; }