The same big piece of ftell code repeated in 3 places. Simplify things moving

it into one subfunction instead.
Try to use real offset in strange cases.
This commit is contained in:
Andrey A. Chernov 2001-08-31 18:23:29 +00:00
parent 05c03ed9b8
commit 2ff678f5bb
3 changed files with 30 additions and 94 deletions

View File

@ -104,7 +104,7 @@ _fseeko(fp, offset, whence, ltest)
int ltest;
{
register fpos_t (*seekfn) __P((void *, fpos_t, int));
fpos_t target, curoff, spos;
fpos_t target, curoff;
size_t n;
struct stat st;
int havepos;
@ -126,53 +126,11 @@ _fseeko(fp, offset, whence, ltest)
case SEEK_CUR:
/*
* In order to seek relative to the current stream offset,
* we have to first find the current stream offset a la
* we have to first find the current stream offset via
* ftell (see ftell for details).
*/
if (fp->_flags & __SOFF)
curoff = fp->_offset;
else {
curoff = (*seekfn)(fp->_cookie, (fpos_t)0, SEEK_CUR);
if (curoff == -1)
return (-1);
}
if (fp->_flags & __SRD) {
spos = curoff;
curoff -= fp->_r;
if (curoff < 0) {
if (HASUB(fp)) {
fp->_p -= curoff;
fp->_r += curoff;
curoff = 0;
} else {
fp->_p = fp->_bf._base;
fp->_r = 0;
curoff = spos;
}
}
if (HASUB(fp)) {
curoff -= fp->_ur;
if (curoff < 0) {
if (-curoff <= fp->_r) {
fp->_p -= curoff;
fp->_r += curoff;
curoff = 0;
} else {
fp->_p = fp->_bf._base;
fp->_r = 0;
FREEUB(fp);
curoff = spos;
}
}
}
} else if ((fp->_flags & __SWR) && fp->_p != NULL) {
n = fp->_p - fp->_bf._base;
if (curoff > OFF_MAX - n) {
errno = EOVERFLOW;
return (-1);
}
curoff += n;
}
if ((curoff = _ftello(fp)) == -1)
return (-1);
if (offset > 0 && curoff > OFF_MAX - offset) {
errno = EOVERFLOW;
return (-1);
@ -252,43 +210,8 @@ _fseeko(fp, offset, whence, ltest)
}
}
if (!havepos) {
if (fp->_flags & __SOFF)
curoff = fp->_offset;
else {
curoff = (*seekfn)(fp->_cookie, (fpos_t)0, SEEK_CUR);
if (curoff == POS_ERR)
goto dumb;
}
spos = curoff;
curoff -= fp->_r;
if (curoff < 0) {
if (HASUB(fp)) {
fp->_p -= curoff;
fp->_r += curoff;
curoff = 0;
} else {
fp->_p = fp->_bf._base;
fp->_r = 0;
curoff = spos;
}
}
if (HASUB(fp)) {
curoff -= fp->_ur;
if (curoff < 0) {
if (-curoff <= fp->_r) {
fp->_p -= curoff;
fp->_r += curoff;
curoff = 0;
} else {
fp->_p = fp->_bf._base;
fp->_r = 0;
FREEUB(fp);
curoff = spos;
}
}
}
}
if (!havepos && (curoff = _ftello(fp)) == -1)
goto dumb;
/*
* Compute the number of bytes in the input buffer (pretending
@ -346,7 +269,6 @@ _fseeko(fp, offset, whence, ltest)
fp->_p = fp->_bf._base;
if (HASUB(fp))
FREEUB(fp);
fp->_flags &= ~__SEOF;
n = target - curoff;
if (n) {
if (__srefill(fp) || fp->_r < n)
@ -354,6 +276,7 @@ _fseeko(fp, offset, whence, ltest)
fp->_p += n;
fp->_r -= n;
}
fp->_flags &= ~__SEOF;
return (0);
/*

View File

@ -74,6 +74,18 @@ ftell(fp)
off_t
ftello(fp)
register FILE *fp;
{
register off_t rv;
FLOCKFILE(fp);
rv = _ftello(fp);
FUNLOCKFILE(fp);
return (rv);
}
off_t
_ftello(fp)
register FILE *fp;
{
register fpos_t pos, spos;
size_t n;
@ -83,19 +95,18 @@ ftello(fp)
return (-1);
}
FLOCKFILE(fp);
/*
* Find offset of underlying I/O object, then
* adjust for buffered bytes.
*/
if (fp->_flags & __SOFF)
if (fp->_flags & __SOFF) {
pos = fp->_offset;
else {
pos = (*fp->_seek)(fp->_cookie, (fpos_t)0, SEEK_CUR);
if (pos == -1) {
FUNLOCKFILE(fp);
spos = -1;
} else {
get_real_pos:
spos = pos = (*fp->_seek)(fp->_cookie, (fpos_t)0, SEEK_CUR);
if (pos == -1)
return (-1);
}
}
if (fp->_flags & __SRD) {
/*
@ -103,7 +114,6 @@ ftello(fp)
* those from ungetc) cause the position to be
* smaller than that in the underlying object.
*/
spos = pos;
pos -= fp->_r;
if (pos < 0) {
if (HASUB(fp)) {
@ -111,6 +121,8 @@ ftello(fp)
fp->_r += pos;
pos = 0;
} else {
if (spos == -1)
goto get_real_pos;
fp->_p = fp->_bf._base;
fp->_r = 0;
pos = spos;
@ -124,6 +136,8 @@ ftello(fp)
fp->_r += pos;
pos = 0;
} else {
if (spos == -1)
goto get_real_pos;
fp->_p = fp->_bf._base;
fp->_r = 0;
FREEUB(fp);
@ -139,12 +153,10 @@ ftello(fp)
*/
n = fp->_p - fp->_bf._base;
if (pos > OFF_MAX - n) {
FUNLOCKFILE(fp);
errno = EOVERFLOW;
return (-1);
}
pos += n;
}
FUNLOCKFILE(fp);
return (pos);
}

View File

@ -46,6 +46,7 @@
* in particular, macros and private variables.
*/
extern off_t _ftello __P((FILE *));
extern int _fseeko __P((FILE *, off_t, int, int));
extern int __fflush __P((FILE *fp));
extern int __sflush __P((FILE *));