Google
 

Trailing-Edge - PDP-10 Archives - SRI_NIC_PERM_FS_1_19910112 - c/lib5/stdio/ftell.c
There are 8 other files named ftell.c in the archive. Click here to see a list.
/*
 *	FTELL - tell position within file
 *
 *	Copyright (C) 1986 by Ian Macky, SRI International
 *
 *	For reading:
 *
 * OLD method:
 *	we want the real physical position within the file, so it's the
 *	physical position at the start of the current buffer (which was
 *	saved in fdoff), then we need to skip past (ocnt - cnt) C chars
 *	and see where we are.  keeping in mind that in a converted file,
 *	a newline character may OR MAY NOT have originally been a CRLF,
 *	so we let bufpos() scan the buffer and figure it out for us.
 *
 * NEW method:
 *	For an unconverted file (_SIOF_CONVERTED off), the I/O ptr is
 *		the real physical position.
 *	For a converted file (_SIOF_CONVERTED on), the I/O ptr is:
 *		<real phys pos of beg of buff><offset in buff>
 *		where the <offset> is kept in the low _SIOP_BITS bits.
 */

#include "stdio.h"
#include "sys/file.h"

long ftell(f)
FILE *f;
{
    long n, pos;
    int cur_cnt;				/* current count */

    if (f->siocheck != _SIOF_OPEN)		/* validate FILE block */
	return -1;
    switch (f->sioflgs & (_SIOF_READ | _SIOF_WRITE)) {
	case _SIOF_READ:
/*
 *	if ungetc's have been done then siocnt now has the # of ungetc'd
 *	characters, and sio2cnt has the old siocnt from before the first
 *	ungetc.  ANSI says pushed-back chars should be included for binary
 *	streams, though the pointer value is unspecified if you ungetc
 *	at position 0.  For text streams the behavior is unspecified; we
 *	try to do the same thing as for binary (because that's simplest) but
 *	the results will probably not be useful.
 */
	    cur_cnt = (f->sioflgs & _SIOF_PBC)
			? f->sio2cnt + f->siocnt	/* Include pushback */
			: f->siocnt;
#ifndef _SIOP_BITS
	    { extern long _bufpos();
	      pos = f->siofdoff + _bufpos(f->siofd, (f->sioocnt - cur_cnt));
	    }
#else	/* new method */
	    if (f->sioflgs & _SIOF_CONVERTED)
		pos = (f->siofdoff << _SIOP_BITS(f)) + (f->sioocnt - cur_cnt);
	    else pos = f->siofdoff + (f->sioocnt - cur_cnt);
#endif
	    return pos;

	case _SIOF_WRITE:
	    cur_cnt = (f->sioflgs & _SIOF_LINEBUF) ? f->siolcnt : f->siocnt;
#ifndef _SIOP_BITS	/* Old method */
	    pos = f->siofdoff + f->siolbuf - cur_cnt;
#else	/* new method */
	    if (f->sioflgs & _SIOF_CONVERTED) {
		fflush(f);		/* Ensure output forced out */
		pos = (f->siofdoff << _SIOP_BITS(f));	/* so need no offset */
	    }
	    else pos = f->siofdoff + (f->siolbuf - cur_cnt);
#endif
	    return pos;

	case 0:
	    if (f->sioflgs & _SIOF_UPDATE) {
		if (f->sioflgs & _SIOF_CONVERTED)
		    return -1;		/* Cannot handle this case yet */
		return f->siofdoff;
	    }
	    /* Not updating, return failure */

	default:
	    return -1;
    }
}