[alt.sources] Standard I/O reimplementation, part 2 of 3

scs@avarice.pika.mit.edu (Steve Summit) (02/11/90)

This posting contains an essentially complete, "nearly" public
domain reimplementation of the "standard I/O" package. 
("`Nearly' public domain" means that there are the usual few
restrictions; see the copyright notices and COPYING file for
details.)

This is part 2; part 3 follows.  Part 1 (which was Message-ID
<1990Feb10.235159.4522@athena.mit.edu>) contained a more
descriptive cover letter.

                                   Steve Summit
                                   scs@adam.mit.edu
                                   scs@hstbme.mit.edu (temporary)

------8<--------8<--------8<----stdio2.shar----8<--------8<------
overwritecheck=yes
verbose=yes

while true; do
	case $1 in
		-f)	overwritecheck=no
			shift;;

		-q)	verbose=no
			shift;;

		-v)	verbose=yes
			shift;;

		-*)	echo "shar: unknown option $1" 1>&2
			shift;;

		*)	break;;
	esac
done

case $verbose in
yes)	echo "extracting Copyright";;
esac
sed 's/^X//' > Copyright <<\EOF
XThe source and documentation contained here is
XCopyright 1987, 1988, and 1989 by Steve Summit.
XAll Rights Reserved.
XNoncommercial redistribution is permitted as long
Xas these notices are retained.
XAny modifications should be marked as such.
XAny commercial, for-profit use will require
Xprior permission from the author.
EOF
chmod 664 Copyright
shouldbe=319
size=`wc -c < Copyright`
if test $size -ne $shouldbe; then
	echo "shar: $0: error extracting Copyright ($size != $shouldbe)" 1>&2
fi

if test $overwritecheck = no -o ! -f cleanup.c; then
case $verbose in
yes)	echo "extracting cleanup.c";;
esac
sed 's/^X//' > cleanup.c <<\EOF
Xextern int fflush();
Xextern int fclose();
X
X_cleanup()
X{
X#ifdef CLEANUPCLOSE
X_scanfiles(fclose);
X#else
X_scanfiles(fflush);
X#endif
X}
EOF
chmod 644 cleanup.c
shouldbe=131
size=`wc -c < cleanup.c`
if test $size -ne $shouldbe; then
	echo "shar: $0: error extracting cleanup.c ($size != $shouldbe)" 1>&2
fi
else echo "shar: $0: will not overwrite existing file cleanup.c" 1>&2; fi

if test $overwritecheck = no -o ! -f doprnt.c; then
case $verbose in
yes)	echo "extracting doprnt.c";;
esac
sed 's/^X//' > doprnt.c <<\EOF
X/*
X *  Common code for printf et al.
X *
X *  Copyright 1987, 1988 Steve Summit
X *  Permission to use, modify, and redistribute for non-
X *  commercial purposes is granted so long as this notice
X *  is retained.  Commercial use will require prior approval
X *  from the author.
X *
X *  The calling routine typically takes a variable number of arguments,
X *  and passes the address of the first one.  This implementation
X *  assumes a straightforward, stack implementation, aligned to the
X *  machine's wordsize.  Increasing addresses are assumed to point to
X *  successive arguments (left-to-right), as is the case for a machine
X *  with a downward-growing stack with arguments pushed right-to-left.
X *
X *  To write, for example, fprintf() using this routine, the code
X *
X *	#include <stdio.h>
X *	#include <stdarg.h>
X *
X *	fprintf(fd, format)
X *	FILE *fd;
X *	char *format;
X *	{
X *	va_list argp;
X *	int r;
X *
X *	va_start(argp, format);
X *	r = _doprnt(format, argp, fd);
X *	va_end(argp);
X *	return r;
X *	}
X *
X *  would suffice.
X *
X *  This version implements the following printf features:
X *
X *	%d,%i	decimal
X *	%u	unsigned decimal
X *	%x	hexadecimal
X *	%X	hexadecimal with capital letters
X *	%o	octal
X *	%c	character
X *	%s	string
X *	%e	exponential
X *	%f	floating-point
X *	%g	generalized floating-point
X *	%p	pointer
X *	%m.n	field width, precision
X *	%-	left adjustment
X *	%+	explicit '+' for positive numbers
X *	%space	extra leading space for positive numbers
X *	%0	zero-padding
X *	%l	argument is a long int
X *	%h	(ignored) argument is short
X *	%*.*	width and precision taken from arguments
X *	%#	"alternate format"
X *	%n	intermediate return of # of characters printed
X *
X *  This version implements the following nonstandard features:
X *
X *	%b	binary conversion
X *	%r	roman numeral conversion
X *	%R	roman numeral conversion with capital letters
X *	%v,%V	user-defined conversion (caller supplies formatting function)
X *
X *  If an attempt is made to print a null pointer as a string (0
X *  is passed to %s), "(null)" is printed.  (I think the old
X *  pdp11 doprnt did this.)
X *
X *  The return value is the number of characters printed, or EOF
X *  in case of error.
X *
X *  The %g code is imperfect, as it relies almost entirely upon
X *  gcvt().  In particular, neither %#g, %+g, nor % g work correctly.
X *
X *  %D, %O, and %U are not supported; you should be using %ld, %lo
X *  and %lu if you mean long conversion.
X *
X *  Steve Summit 7/16/88
X */
X
X#include <stdio.h>
X#ifdef VARARGS
X#include <varargs.h>
X#else
X#include <stdarg.h>
X#endif
X#include "printf.h"
X
X#define TRUE 1
X#define FALSE 0
X
X/* un#define these to turn off nonstandard features */
X
X#define BINARY
X#define ROMAN
X
X#define NULLPTR "(null)"	/* print null pointers thusly */
X
X/*
X *  Un#define FLOATING if you don't need it, want to save space,
X *  or don't have ecvt(), fcvt(), and gcvt().
X */
X
X#define FLOATING
X
X/*
X *  A few other miscellaneous #definitions are possible:
X *
X *	NOUNSLONG	for compilers which don't support unsigned
X *			long ints
X *
X *	NORETURNVALUE	if you don't care about the return value,
X *			and would rather not have each character
X *			printed laboriously counted.
X *
X *	FASTNBF		avoid one-at-a-time write(2)'s, if
X *			possible, when the stdio stream is
X *			unbuffered (see additional comments below)
X *
X *	NOLONG		turn off code for explicit handling of %l,
X *			which works just fine but is a bit
X *			cumbersome and space-consuming.
X *			Don't #define NOLONG.
X *			(Unless you don't use %l at all, NOLONG only
X *			works on machines with sizeof(long)==sizeof(int),
X *			and those tend to be virtual memory machines
X *			for which the extra code size won't be a problem.)
X */
X
X#define NOUNSLONG
X
X#define isdigit(d) ((d) >= '0' && (d) <= '9')
X#define Ctod(c) ((c) - '0')
X
X#define MAXBUF 128	/* "very wide fields (>128 characters) fail" */
X
X#ifdef ROMAN
Xstatic tack();
Xstatic doit();
X#endif
X
X#ifdef FLOATING
Xextern char *ecvt();
Xextern char *fcvt();
Xextern char *gcvt();
X#endif
X
X_doprnt(fmt, argp, fd)
Xregister char *fmt;
X#ifndef ASKF
Xregister
X#endif
X	 va_list argp;
XFILE *fd;
X{
X
X#ifdef ASKF
X
Xreturn _do2prnt(0, fmt, &argp, fd);
X}
X
X/* only broken up into two routines #ifdef ASKF */
X
X_do2prnt(askf, fmt, argpp, fd)
Xint askf;
Xregister char *fmt;
Xva_list *argpp;
XFILE *fd;
X{
X#ifdef LOCALARGP
Xregister va_list *argp = *argpp;
X#else
X#define argp (*argpp)
X#endif
X
X#endif
X
Xregister char *p;
Xchar *p2;
Xint size;
Xint width;
Xint prec;
Xchar padc;
Xint n;
Xunsigned int u;
Xint base;
Xchar buf[MAXBUF];
Xint flags;
Xint negflag;
Xchar signflag;
Xchar *digs;
X#ifndef NOLONG
Xlong int l;
X#ifdef NOUNSLONG
X#define ul l
Xtypedef long int ulong;
X#else
Xunsigned long int ul;
Xtypedef unsigned long int ulong;
X#endif
X#endif
X#ifdef FLOATING
Xdouble d;
Xint decpt;
Xchar echar;
Xint negexp;
Xchar *p3;
X#endif
X#ifdef ROMAN
Xchar *rdigs;
Xint dig;
X#endif
X#ifndef NORETURNVALUE
Xint nprinted = 0;
X#endif
X#ifdef USERDEFINEDPRINTF
Xint (*func)();
Xchar *ptr;		/* void * if ANSI */
X#endif
X
X#ifndef NORETURNVALUE
X#define Putc(c, fd) {putc((c), (fd)); nprinted++; }
X#else
X#define Putc(c, fd) putc((c), (fd))
X#endif
X
Xwhile(*fmt != '\0')
X	{
X	if(*fmt != '%')
X		{
X#ifdef FASTNBF
X		/*
X		 *  Two caveats concerning the FASTNBF code:
X		 *
X		 *	1. Unlike the rest of this code, it peeks
X		 *	   inside the fd and expects there to be
X		 *	   a field called _flag and a bit therein
X		 *	   called _IONBF.
X		 *
X		 *	2. It doesn't call write() directly, but
X		 *	   rather goes through _fwrite(), which
X		 *	   centralizes the error checking (setting
X		 *	   of _IOERR, etc.) and worries about
X		 *	   calling a write function
X		 *	   other than write(2) in the case of
X		 *	   so-called "functional" stdio's.
X		 */
X
X		if(fd->_flag & _IONBF)
X			{
X			for(p = fmt + 1; *p != '%' && *p != '\0'; p++)
X				;
X			n = _fwrite(fd, fmt, p - fmt);
X#ifndef NORETURNVALUE
X			if(n > 0)
X				nprinted += n;
X#endif
X			fmt = p;
X			continue;
X			}
X#endif
X		Putc(*fmt++, fd);
X		continue;
X		}
X
X	fmt++;
X
X	width = 0;
X	prec = -1;
X	flags = 0;
X	signflag = '-';
X	padc = ' ';
X
X	while(TRUE)
X		{
X		if(*fmt == '-')
X			{
X			flags |= PRF_LADJUST;
X			fmt++;
X			}
X		else if(*fmt == '+' || *fmt == ' ')
X			{
X			signflag = *fmt;
X			fmt++;
X			}
X		else if(*fmt == '0')
X			{
X			padc = '0';
X#ifdef USERDEFINEDPRINTF
X			flags |= PRF_ZEROPAD;
X#endif
X			fmt++;
X			}
X		else if(isdigit(*fmt))
X			{
X			while(isdigit(*fmt))
X				width = 10 * width + Ctod(*fmt++);
X			}
X		else if(*fmt == '*')
X			{
X			width = va_arg(argp, int);
X			fmt++;
X			if(width < 0)
X				{
X				flags ^= PRF_LADJUST;	/* toggle ladjust */
X				width = -width;
X				}
X			}
X		else if(*fmt == '.')
X			{
X			fmt++;
X			if(isdigit(*fmt))
X				{
X				prec = 0;
X				while(isdigit(*fmt))
X					prec = 10 * prec + Ctod(*fmt++);
X				}
X			else if(*fmt == '*')
X				{
X				prec = va_arg(argp, int);
X				fmt++;
X				}
X			}
X		else if(*fmt == '#')
X			{
X			flags |= PRF_NUMSGN;
X			fmt++;
X			}
X		else if(*fmt == 'l')
X			{
X#ifndef NOLONG
X			flags |= PRF_LONG;
X#endif
X			fmt++;
X			}
X		else if(*fmt == 'h')
X			{
X			/*
X			 *  Shorts and floats are widened when passed,
X			 *  so nothing needs be done here (although
X			 *  %hf may be significant for ANSI C).
X			 */
X
X			fmt++;
X			}
X		else	break;
X		}
X
X	negflag = FALSE;
X	digs = "0123456789abcdef";
X#ifdef FLOATING
X	echar = 'e';
X#endif
X#ifdef ROMAN
X	rdigs = "  mdclxvi";
X#endif
X
X	switch(*fmt)
X		{
X#ifdef BINARY
X		case 'b':
X			base = 2;
X#ifndef NOLONG
X			if(flags & PRF_LONG)
X				{
X				ul = va_arg(argp, ulong);
X				goto dolong;
X				}
X#endif
X			u = va_arg(argp, unsigned);
X			goto donum;
X#endif
X		case 'c':
X#ifndef pdp11
X			Putc(va_arg(argp, char), fd);
X#else
X			/* poor little compiler got an "expression */
X			/* overflow" on the above */
X
X			n = va_arg(argp, char);
X			Putc(n, fd);
X#endif
X			break;
X
X		case 'd':
X		case 'i':
X			base = 10;
X#ifndef NOLONG
X			if(flags & PRF_LONG)
X				{
X				l = va_arg(argp, long int);
X
X				if(l < 0)
X					{
X					ul = -l;
X					negflag = TRUE;
X					}
X#ifndef NOUNSLONG
X				else	ul = l;
X#endif
X				goto dolong;
X				}
X#endif
X			n = va_arg(argp, int);
X
X			if(n >= 0)
X				u = n;
X			else	{
X				u = -n;
X				negflag = TRUE;
X				}
X
X			goto donum;
X#ifdef FLOATING
X		case 'E':
X			echar = 'E';
X		case 'e':
X			d = va_arg(argp, double);
X
X			if(prec == -1)
X				prec = 6;
X
X			p2 = ecvt(d, prec + 1, &decpt, &negflag);
X
X			decpt--;
X
X			if(decpt < 0)
X				{
X				negexp = TRUE;
X				decpt = -decpt;
X				}
X			else	negexp = FALSE;
X
X			p = &buf[MAXBUF - 1];
X
X			n = 2;
X
X			do	{
X				*p-- = digs[decpt % 10];
X				decpt /= 10;
X				} while(--n > 0 || decpt != 0);
X
X			if(negexp)
X				*p-- = '-';
X			else	*p-- = '+';
X
X			*p-- = echar;
X
X			if(prec == 0 && (flags & PRF_NUMSGN))
X				*p-- = '.';
X
X			for(p3 = p2; *p3 != '\0'; p3++)
X				;
X
X			while(p3 > p2)
X				{
X				*p-- = *--p3;
X
X				if(p3 - p2 == 1)
X					*p-- = '.';
X				}
X
X			goto putnum;
X
X		case 'f':
X			d = va_arg(argp, double);
X
X			if(prec == -1)
X				prec = 6;
X
X			p2 = fcvt(d, prec, &decpt, &negflag);
X
X			for(p3 = p2; *p3 != '\0'; p3++)
X				;
X
X			p = &buf[MAXBUF - 1];
X
X			if(prec == 0 && (flags & PRF_NUMSGN))
X				*p-- = '.';
X
X			while(p3 > p2)
X				{
X				*p-- = *--p3;
X
X				if(p3 - p2 == decpt)
X					*p-- = '.';
X				}
X
X			goto putnum;
X
X		case 'G':
X			echar = 'E';
X		case 'g':
X			d = va_arg(argp, double);
X
X			if(prec == -1)
X				prec = 6;
X
X			gcvt(d, prec, buf);
X
X			for(p = buf; *p != '\0'; p++)
X				;
X
X			for(p2 = p - 1, p = &buf[MAXBUF - 1]; p2 >= buf; p2--)
X				{
X				if(*p2 == 'e')
X					*p-- = echar;
X				else	*p-- = *p2;
X				}
X
X			goto putpad;
X#endif
X#ifndef NORETURNVALUE
X		case 'n':
X			*va_arg(argp, int *) = nprinted;
X			break;
X#endif
Xoctal:		case 'o':
X			base = 8;
X#ifndef NOLONG
X			if(flags & PRF_LONG)
X				{
X				ul = va_arg(argp, ulong);
X				goto dolong;
X				}
X#endif
X			u = va_arg(argp, unsigned);
X			goto donum;
X
X		case 'p':
X#ifdef pdp11
X			goto octal;
X#else
X#ifdef M_I86
X			ul = va_arg(argp, unsigned long int);
X
X			digs = "0123456789ABCDEF";
X
X			p = &buf[MAXBUF - 1];
X
X			for(n = 0; n < 8; n++)
X				{
X				if(n == 4)
X					*p-- = ':';
X
X				*p-- = digs[ul % 16];
X				ul /= 16;
X				}
X
X			goto putpad;
X#else /* all other machines */
X			goto hex;
X#endif
X#endif
X#ifdef ROMAN
X		case 'R':
X			rdigs = "  MDCLXVI";
X		case 'r':
X			n = va_arg(argp, int);
X			p2 = &buf[MAXBUF - 1];
X
X			dig = n % 10;
X			tack(dig, &rdigs[6], &p2);
X			n = n / 10;
X
X			dig = n % 10;
X			tack(dig, &rdigs[4], &p2);
X			n = n / 10;
X
X			dig = n % 10;
X			tack(dig, &rdigs[2], &p2);
X			n /= 10;
X
X			dig = n % 10;
X			tack(dig, rdigs, &p2);
X
X			p = p2;
X
X			goto putpad;
X#endif
X		case 's':
X			p = va_arg(argp, char *);
X#ifdef NULLPTR
X			if(p == NULL)
X				p = NULLPTR;
X#endif
X			if(width > 0 && !(flags & PRF_LADJUST))
X				{
X				n = 0;
X				p2 = p;
X
X				for(; *p != '\0' &&
X						(prec == -1 || n < prec); p++)
X					n++;
X
X				p = p2;
X
X				while(n < width)
X					{
X					Putc(' ', fd);
X					n++;
X					}
X				}
X
X			n = 0;
X#ifdef FASTNBF
X			if(fd->_flag & _IONBF)
X				{
X				int r;
X
X				p2 = p;
X
X				while(*p2 != '\0')
X					{
X					if(n >= prec && prec != -1)
X						break;
X
X					p2++;
X					n++;
X					}
X
X				r = _fwrite(fd, p, n);
X#ifndef NORETURNVALUE
X				if(r > 0)
X					nprinted += r;
X#endif
X				}
X			else
X#endif
X				while(*p != '\0')
X					{
X					if(n >= prec && prec != -1)
X						break;
X
X					Putc(*p++, fd);
X					n++;
X					}
X
X			if(n < width && (flags & PRF_LADJUST))
X				{
X				while(n < width)
X					{
X					Putc(' ', fd);
X					n++;
X					}
X				}
X
X			break;
X
X		case 'u':
X			base = 10;
X#ifndef NOLONG
X			if(flags & PRF_LONG)
X				{
X				ul = va_arg(argp, ulong);
X				goto dolong;
X				}
X#endif
X			u = va_arg(argp, unsigned);
X			goto donum;
X
X		case 'X':
X			digs = "0123456789ABCDEF";
Xhex:		case 'x':
X			base = 16;
X#ifndef NOLONG
X			if(flags & PRF_LONG)
X				{
X				ul = va_arg(argp, ulong);
X
Xdolong:				p = &buf[MAXBUF - 1];
X
X				if(ul == 0)
X					flags &= ~PRF_NUMSGN;
X
X				n = prec;
X
X				do	{
X#ifdef NOUNSLONG
X					/*
X					 *  Have to simulate unsigned longs
X					 *  with signed ones.
X					 */
X
X					/*
X					 *  Remember, ul is really l,
X					 *  and is signed.
X					 */
X
X					if(ul < 0)
X						{
X						long int ul2;
X						int rem;
X#define BITSPERCHAR 8
X#define HIGHBIT (1L << (sizeof(long int) * BITSPERCHAR - 1))
X
X						ul2 = (ul >> 1) & ~HIGHBIT;
X
X						rem = ul2 % base * 2
X								+ (ul & 1);
X
X						*p-- = digs[rem % base];
X
X						ul = ul2 / base * 2
X								+ rem / base;
X						}
X					else
X#endif
X						{
X						*p-- = digs[ul % base];
X						ul /= base;
X						}
X					n--;
X					} while(ul != 0 || prec != -1 && n >0);
X				goto donumsgn;
X				}
X#endif
X			u = va_arg(argp, unsigned);
X
Xdonum:			p = &buf[MAXBUF - 1];
X
X			if(u == 0)
X				flags &= ~PRF_NUMSGN;
X
X			n = prec;
X
X			do	{
X				*p-- = digs[u % base];
X				u /= base;
X				n--;
X				} while(u != 0 || prec != -1 && n > 0);
Xdonumsgn:
X			if(flags & PRF_NUMSGN)
X				{
X				switch(*fmt)
X					{
X#ifdef BINARY
X					case 'b':
X						*p-- = 'b';
X						*p-- = '0';
X						break;
X#endif
X					case 'x':
X						*p-- = 'x';
X						/* fall through */
X					case 'o':
X						*p-- = '0';
X						break;
X
X					case 'X':
X						*p-- = 'X';
X						*p-- = '0';
X						break;
X					}
X				}
Xputnum:
X			if(negflag)
X				*p-- = '-';
X			else if(signflag != '-')
X				*p-- = signflag;
Xputpad:
X			size = &buf[MAXBUF - 1] - p;
X
X			if(size < width && !(flags & PRF_LADJUST))
X				{
X				while(width > size)
X					{
X					Putc(padc, fd);
X					width--;
X					}
X				}
X#ifdef FASTNBF
X			if(fd->_flag & _IONBF)
X				{
X				n = _fwrite(fd, p + 1, size);
X#ifndef NORETURNVALUE
X				if(n > 0)
X					nprinted += n;
X#endif
X				}
X			else
X#endif
X				while(++p != &buf[MAXBUF])
X					Putc(*p, fd);
X
X			if(size < width)	/* must be ladjust */
X				{
X				while(width > size)
X					{
X					Putc(padc, fd);
X					width--;
X					}
X				}
X
X			break;
X
X#ifdef USERDEFINEDPRINTF
X
X		case 'V':
X			flags |= PRF_CAPITAL;
X		case 'v':
X			func = va_arg(argp, int (*)());
X			ptr = va_arg(argp, char *);
X#ifndef NORETURNVALUE
X			nprinted +=
X#endif
X				    (*func)(fd, ptr, width, prec, flags);
X			break;
X#endif
X		case '\0':
X			fmt--;
X			break;
X
X		default:
X			/* oughta allow caller to register new fmt chars */
X			Putc(*fmt, fd);
X		}
X	fmt++;
X	}
X
X#ifdef ASKF
X#ifdef LOCALARGP
X*argpp = argp;
X#endif
X#endif
X
X#ifndef NORETURNVALUE
X
Xif(ferror(fd))
X	return EOF;
X
Xreturn nprinted;
X
X#endif
X}
X
X#ifdef ROMAN
X
Xstatic
Xtack(d, digs, p)
Xint d;
Xchar *digs;
Xchar **p;
X{
Xif(d == 0) return;
Xif(d >= 1 && d <= 3)
X	{
X	doit(d, digs[2], p);
X	return;
X	}
X
Xif(d == 4 || d == 5)
X	{
X	**p = digs[1];
X	(*p)--;
X	}
X
Xif(d == 4)
X	{
X	**p = digs[2];
X	(*p)--;
X	return;
X	}
X
Xif(d == 5) return;
X
Xif(d >= 6 && d <= 8)
X	{
X	doit(d - 5, digs[2], p);
X	**p = digs[1];
X	(*p)--;
X	return;
X	}
X
X/* d == 9 */
X
X**p = digs[0];
X(*p)--;
X**p = digs[2];
X(*p)--;
Xreturn;
X}
X
Xstatic
Xdoit(d, one, p)
Xint d;
Xchar one;
Xchar **p;
X{
Xint i;
X
Xfor(i = 0; i < d; i++)
X	{
X	**p = one;
X	(*p)--;
X	}
X}
X
X#endif
EOF
chmod 664 doprnt.c
shouldbe=14561
size=`wc -c < doprnt.c`
if test $size -ne $shouldbe; then
	echo "shar: $0: error extracting doprnt.c ($size != $shouldbe)" 1>&2
fi
else echo "shar: $0: will not overwrite existing file doprnt.c" 1>&2; fi

if test $overwritecheck = no -o ! -f doscan.c; then
case $verbose in
yes)	echo "extracting doscan.c";;
esac
sed 's/^X//' > doscan.c <<\EOF
X/*
X *  Common code for scanf et al.
X *
X *  Copyright 1989 Steve Summit
X *  Permission to use, modify, and redistribute for non-
X *  commercial purposes is granted so long as this notice
X *  is retained.  Commercial use will require prior approval
X *  from the author.
X */
X
X#include <stdio.h>
X#include <stdarg.h>
X#include <ctype.h>
X
X#undef getc
X#define getc fgetc	/* temporary; makes debugging easier */
X
X#define UNGETCKLUDGE	/* for mildly-buggy stdio implementations
X			 * in which ungetc after EOF on a "string file"
X			 * doesn't work */
X
X#define TRUE 1
X#define FALSE 0
X
X#ifndef isxdigit
X/* beware: assumes ASCII, and evaluates argument multiple times */
X#define isxdigit(c) (isdigit(c) || ((c) >= 'A' && (c) <= 'F') || \
X					((c) >= 'a' && (c) <= 'f'))
X#endif
X
X/* is scanf's definition of whitespace the same as ctype's? */
X
X#define Iswhite(c) isspace(c)
X
X#define Ctod(c) ((c) - '0')
X
X/* Un#define FLOATING if you don't need it or want to save space. */
X
X#define FLOATING
X
Xstatic int match();
X
X_doscan(fd, fmt, argp)
XFILE *fd;
Xchar *fmt;
Xva_list argp;
X{
X
X#ifdef ASKF
X
Xreturn _do2scan(0, fd, fmt, argp);
X}
X
X/* only broken up into two routines #ifdef ASKF */
X
X_do2scan(askf, fd, fmt, argp)
Xint askf;
XFILE *fd;
Xchar *fmt;
Xva_list argp;
X{
X
X#endif
X
Xregister char *fmtp;
Xregister int c;
Xint retval = 0;
Xint noassign;
Xint sizeflag;
Xint width;
Xint negflag;
Xint gotone;
Xint base;
Xlong int nn;
X#ifdef FLOATING
Xdouble d;
X#endif
Xchar *p;
X
Xfor(fmtp = fmt; *fmtp != '\0'; fmtp++)
X	{
X	if(Iswhite(*fmtp))
X		{
X#ifdef notdef
X		while(Iswhite(*fmtp))
X			fmtp++;
X
X		/* does this belong here? */
X#endif
X		do	{
X			c = getc(fd);
X#ifdef ASKF
X			if(askf && c == '\n')
X				break;
X#endif
X			} while(Iswhite(c));
X#ifdef ASKF
X		if(askf)
X			{
X			if(c == EOF)
X				return 0;
X			else if(c == '\n')
X				{
X				return (*fmtp == '\0') ? retval : -1;
X				}
X			}
X#endif
X		ungetc(c, fd);
X
X		continue;
X		}
X
X	if(*fmtp != '%')
X		{
X		c = getc(fd);
X		if(c != *fmtp)
X			{
X			ungetc(c, fd);
X			return retval;
X			}
X
X		continue;
X		}
X
X	/* else it's a conversion specification */
X
X	noassign = FALSE;	/* i.e. do assign */
X	sizeflag = '\0';
X	width = -1;
X	negflag = FALSE;
X	gotone = FALSE;
X
X	/* first, collect flags */
X
X	fmtp++;		/* over '%' */
X
X	while(TRUE)
X		{
X		if(*fmtp == '*')
X			{
X			noassign = TRUE;
X			fmtp++;
X			}
X		else if(*fmtp == 'h' || *fmtp == 'l')
X			{
X			sizeflag = *fmtp;
X			fmtp++;
X			}
X		else if(isdigit(*fmtp))
X			{
X			width = 0;
X			while(isdigit(*fmtp))
X				width = 10 * width + Ctod(*fmtp++);
X			}
X		else	break;
X		}
X
X	if(*fmtp != '[' && *fmtp != 'c' && *fmtp != '%')	/* % ? */
X		{
X		/* skip leading whitespace in input */
X
X		do	{
X			c = getc(fd);
X#ifdef ASKF
X			if(askf && c == '\n')
X				break;
X#endif
X			} while(Iswhite(c));
X#ifdef ASKF
X		if(askf)
X			{
X			if(c == EOF)
X				return 0;
X			else if(c == '\n')
X				{
X				return (*fmtp == '\0') ? retval : -1;
X				}
X			}
X#endif
X		ungetc(c, fd);
X		}
X
X	switch(*fmtp)
X		{
X		case 'd':
X			base = 10;
Xdonum:
X			c = getc(fd);
X
X			if(c == '-')
X				{
X				negflag = TRUE;
X				if(width > 0)
X					width--;
X				}
X			else if(c == '+')
X				{
X				if(width > 0)
X					width--;
X				}
X			else	ungetc(c, fd);
X
X			/* FALLTHROUGH */
X
Xdounsigned:	case 'u':
X			/*
X			 *  Note that unsigned isn't really treated
X			 *  specially, except for not looking for '-'.
X			 *  This depends on the essential equivalence
X			 *  of simple arithmetic on signed and unsigned
X			 *  integers on a normal 2's complement machine.
X			 */
X
X			nn = 0;
X
X			while(width < 0 || width-- > 0)
X				{
X				c = getc(fd);
X
X				if(!((base != 16) ? isdigit(c) : isxdigit(c)))
X					{
X					ungetc(c, fd);
X
X					if(!gotone)
X						return retval;
X					else	break;
X					}
X
X				if(isdigit(c))
X					c -= '0';
X				else if(islower(c))
X					c -= 'a' - 10;
X				else /* isupper(c) */
X					c -= 'A' - 10;
X
X				nn = base * nn + c;
X
X				gotone = TRUE;
X				}
X
X			if(negflag)
X				nn = -nn;
X
X			if(noassign)
X				break;
X
X			switch(sizeflag)
X				{
X				case '\0':
X					*va_arg(argp, int *) = (int)nn;
X					break;
X
X				case 'h':
X					*va_arg(argp, short *) = (short)nn;
X					break;
X
X				case 'l':
X					*va_arg(argp, long *) = nn;
X					break;
X				}
X
X			retval++;
X
X			break;
X
X		case 'i':
X			c = getc(fd);
X
X			if(c == '0')
X				{
X				if(width > 0)
X					width--;
X
X				c = getc(fd);
X
X				if(c == 'x' || c == 'X')
X					{
X					if(width > 0)
X						width--;
X					base = 16;
X					}
X				else	{
X					if(c != EOF)
X						ungetc(c, fd);
X#ifdef UNGETCKLUDGE
X					else	fd->_cnt = 0;
X#endif
X					ungetc('0', fd); /* in case no others
X								following */
X					base = 8;
X					}
X				}
X			else	{
X				ungetc(c, fd);
X				base = 10;
X				}
X
X			/* worry about minus sign */
X
X			goto donum;
X
X		case 'o':
X			base = 8;
X			goto dounsigned;
X
X		case 'x':
X		case 'X':
X			/* strip leading 0x if present */
X
X			base = 16;
X
X			c = getc(fd);
X
X			if(c == '0')
X				{
X				if(width > 0)
X					width--;
X				c = getc(fd);
X				if(c == 'x' || c == 'X')
X					{
X					if(width > 0)
X						width--;
X					}
X				else	{
X					if(c != EOF)
X						ungetc(c, fd);
X#ifdef UNGETCKLUDGE
X					else	fd->_cnt = 0;
X#endif
X					ungetc('0', fd); /* in case no others
X								following */
X					}
X				}
X			else	{
X				ungetc(c, fd);
X				}
X
X			goto dounsigned;
X
X		case 'c':
X			if(width < 0)
X				width = 1;
X
X			/* FALLTHROUGH */
X
X		case 's':
X		case '[':
Xdostring:		if(!noassign)
X				p = va_arg(argp, char *);
X			else	p = NULL;
X
X			while(width < 0 || width-- > 0)
X				{
X				c = getc(fd);
X
X				if(c == EOF)
X					break;
X
X				if(*fmtp == 's' && Iswhite(c) ||
X					   *fmtp == '[' && !match(c, fmtp + 1))
X					{
X					ungetc(c, fd);
X					break;
X					}
X
X				if(p != NULL)
X					*p++ = c;
X
X				gotone = TRUE;
X				}
X
X			if(!noassign && gotone)
X				{
X				if(*fmtp != 'c')
X					*p = '\0';
X				retval++;
X				}
X
X			if(*fmtp == '[')
X				{
X				for(; *fmtp != ']'; fmtp++)
X					{
X					if(*fmtp == '\0')
X						{
X						fmtp--;
X						break;
X						}
X					}
X				}
X
X			if(c == EOF)
X				return retval;
X
X			break;
X
X		case '%':
X			c = getc(fd);
X			if(c != *fmtp)
X				{
X				ungetc(c, fd);
X				return retval;
X				}
X			break;
X#ifdef FLOATING
X		case 'e': case 'E':
X		case 'f':
X		case 'g': case 'G':
X
X			c = getc(fd);
X
X			if(c == '-')
X				{
X				negflag = TRUE;
X				if(width > 0)
X					width--;
X				c = getc(fd);
X				}
X			else if(c == '+')
X				{
X				if(width > 0)
X					width--;
X				c = getc(fd);
X				}
X
X			d = 0;
X
X			while(isdigit(c) && (width < 0 || width-- > 0))
X				{
X				d = 10. * d + Ctod(c);
X				c = getc(fd);
X				}
X
X			if(c == '.')
X				{
X				double fac = .1;
X
X				if(width > 0)
X					width--;
X
X				while(width < 0 || width-- > 0)
X					{
X					c = getc(fd);
X
X					if(!isdigit(c))
X						break;
X
X					d += Ctod(c) * fac;
X					fac *= .1;
X					}
X				}
X
X			if(c == 'e' || c == 'E')
X				{
X				int negexp = FALSE;
X				unsigned int exponent;
X				double fac, mag;
X
X				if(width > 0)
X					width--;
X
X				c = getc(fd);
X
X				if(c == '-')
X					{
X					negexp = TRUE;
X					if(width > 0)
X						width--;
X					c = getc(fd);
X					}
X				else if(c == '+')
X					{
X					if(width > 0)
X						width--;
X					c = getc(fd);
X					}
X
X				exponent = 0;
X
X				while(isdigit(c) && (width < 0 || width-- > 0))
X					{
X					exponent = 10 * exponent + Ctod(c);
X					c = getc(fd);
X					}
X
X				/* compute 10**n by power-of-two powers of 10 */
X
X				mag = 10.;
X				fac = 1.;
X
X				while(exponent > 0)
X					{
X					if(exponent & 1)
X						fac *= mag;
X
X					mag *= mag;
X					exponent /= 2;
X					}
X
X				if(negexp)
X					fac = 1. / fac;
X
X				d *= fac;
X				}
X
X			ungetc(c, fd);
X
X			if(negflag)
X				d = -d;
X
X			if(noassign)
X				break;
X
X			switch(sizeflag)
X				{
X				case '\0':
X					*va_arg(argp, float *) = (float)d;
X					break;
X
X				case 'l':
X					*va_arg(argp, double *) = d;
X					break;
X				}
X
X			retval++;
X
X			break;
X#endif
X
X		/* what's a reasonable default? */
X		}
X	}
X
X/* Under what conditions should it return EOF? */
X
Xreturn retval;
X}
X
Xstatic int
Xmatch(c, set)
Xint c;
Xchar *set;
X{
Xregister char *p;
Xint negflag = FALSE;
X
Xif(*set == '^')
X	{
X	negflag = TRUE;
X	set++;
X	}
X
Xfor(p = set; *p != ']' && *p != '\0'; p++)
X	{
X	if(c == *p)
X		return !negflag;
X	}
X
Xreturn negflag;
X}
EOF
chmod 644 doscan.c
shouldbe=7954
size=`wc -c < doscan.c`
if test $size -ne $shouldbe; then
	echo "shar: $0: error extracting doscan.c ($size != $shouldbe)" 1>&2
fi
else echo "shar: $0: will not overwrite existing file doscan.c" 1>&2; fi

if test $overwritecheck = no -o ! -f errfunc.c; then
case $verbose in
yes)	echo "extracting errfunc.c";;
esac
sed 's/^X//' > errfunc.c <<\EOF
X#include <stdio.h>
X
Xint _errfunc();
X
Xint (*_deflterrfunc)() = _errfunc;
X
X_errfunc(filename, rw, fp)
Xchar *filename;
Xint rw;
XFILE *fp;
X{
Xif(fp == stderr && rw == 'w')	/* avoid infinite loops */
X	return;		/* abort? */
X
X/* avoids use of fprintf, so won't force _doprnt */
X
Xif(filename != NULL)
X	{
X	fputs(filename, stderr);
X	fputs(": ", stderr);
X	}
X
Xswitch(rw)
X	{
X	case 'c':
X		fputs("close ", stderr);
X		break;
X
X	case 'm':
X		fputs("memory allocation ", stderr);
X		break;
X
X	case 'r':
X		fputs("read ", stderr);
X		break;
X
X	case 's':
X		fputs("seek ", stderr);
X		break;
X
X	case 'w':
X		fputs("write ", stderr);
X		break;
X
X	default:
X		fputc(rw, stderr);
X	}
Xfputs(" error: ", stderr);
Xfflush(stderr);
Xperror("");
X
X#ifndef WRITEERRNOTFATAL
X
Xif(rw == 'w')
X	{
X	if(fp != NULL)
X		_freefile(fp);	/* so it won't get found by _cleanup */
X	exit(1);
X	}
X
X#endif
X
X/* return value? */
X}
EOF
chmod 644 errfunc.c
shouldbe=860
size=`wc -c < errfunc.c`
if test $size -ne $shouldbe; then
	echo "shar: $0: error extracting errfunc.c ($size != $shouldbe)" 1>&2
fi
else echo "shar: $0: will not overwrite existing file errfunc.c" 1>&2; fi

if test $overwritecheck = no -o ! -f fabort.c; then
case $verbose in
yes)	echo "extracting fabort.c";;
esac
sed 's/^X//' > fabort.c <<\EOF
X/*
X *  Discard any buffering for stream, without doing I/O.
X *  For input streams, equivalent to some implementation's fflush.
X */
X
X#include <stdio.h>
X
Xfabort(fp)
Xregister FILE *fp;
X{
Xfp->_ptr = fp->_base;
X
Xif(fp->_flag & (_IOREAD | _IONBF
X#ifdef READWRITE
X				 | _IORW
X#endif
X#ifndef PUTCLBUF
X					 | _IOLBF
X#endif
X						  ))
X	fp->_cnt = 0;
Xelse	fp->_cnt = fp->_bufsiz;
X}
EOF
chmod 644 fabort.c
shouldbe=373
size=`wc -c < fabort.c`
if test $size -ne $shouldbe; then
	echo "shar: $0: error extracting fabort.c ($size != $shouldbe)" 1>&2
fi
else echo "shar: $0: will not overwrite existing file fabort.c" 1>&2; fi

if test $overwritecheck = no -o ! -f fclose.c; then
case $verbose in
yes)	echo "extracting fclose.c";;
esac
sed 's/^X//' > fclose.c <<\EOF
X#include <stdio.h>
X
Xfclose(fp)
Xregister FILE *fp;
X{
Xint r1, r2;
X
Xr1 = fflush(fp);
X
Xif(fp->_closefunc != NULL)
X	{
X#ifdef _IOFPTR
X	if(fp->_flag & _IOFPTR)
X		r2 = (*fp->_closefunc)(fp->_fptr);
X	else
X#endif
X		r2 = (*fp->_closefunc)(fp->_file);
X
X	if(r2 < 0 && fp->_errfunc != NULL)
X		(*fp->_errfunc)(fp->_filename, 'c', fp);
X	}
Xelse	r2 = 0;
X
X_freefile(fp);
X
Xreturn (r1 == EOF || r2 < 0) ? EOF : 0;		/* ? */
X}
EOF
chmod 644 fclose.c
shouldbe=404
size=`wc -c < fclose.c`
if test $size -ne $shouldbe; then
	echo "shar: $0: error extracting fclose.c ($size != $shouldbe)" 1>&2
fi
else echo "shar: $0: will not overwrite existing file fclose.c" 1>&2; fi

if test $overwritecheck = no -o ! -f fdclose.c; then
case $verbose in
yes)	echo "extracting fdclose.c";;
esac
sed 's/^X//' > fdclose.c <<\EOF
X#include <stdio.h>
X
Xfdclose(fp)
Xregister FILE *fp;
X{
Xint r;
X
Xr = fflush(fp);
X
X_freefile(fp);
X
Xreturn r;
X}
EOF
chmod 644 fdclose.c
shouldbe=106
size=`wc -c < fdclose.c`
if test $size -ne $shouldbe; then
	echo "shar: $0: error extracting fdclose.c ($size != $shouldbe)" 1>&2
fi
else echo "shar: $0: will not overwrite existing file fdclose.c" 1>&2; fi

if test $overwritecheck = no -o ! -f fdopen.c; then
case $verbose in
yes)	echo "extracting fdopen.c";;
esac
sed 's/^X//' > fdopen.c <<\EOF
X#include <stdio.h>
X
Xextern FILE *_getfile();
Xextern long int lseek();
X
XFILE *
Xfdopen(fd, mode)
Xint fd;
Xchar *mode;
X{
Xregister FILE *fp;
X
Xif((fp = _getfile()) != NULL)
X	{
X	fp->_file = fd;
X	if(*mode == 'r')
X		fp->_flag |= _IOREAD;
X	else	{
X		fp->_flag |= _IOWRT;
X		if(*mode == 'a')
X			lseek(fd, 0L, 2);	/* should it do this? */
X		}
X	}
X
Xreturn fp;
X}
EOF
chmod 644 fdopen.c
shouldbe=346
size=`wc -c < fdopen.c`
if test $size -ne $shouldbe; then
	echo "shar: $0: error extracting fdopen.c ($size != $shouldbe)" 1>&2
fi
else echo "shar: $0: will not overwrite existing file fdopen.c" 1>&2; fi

if test $overwritecheck = no -o ! -f fflush.c; then
case $verbose in
yes)	echo "extracting fflush.c";;
esac
sed 's/^X//' > fflush.c <<\EOF
X#include <stdio.h>
X
Xfflush(fp)
Xregister FILE *fp;
X{
Xregister int n;
Xint r = 0;
X#ifdef READWRITE
X
Xif(fp->_flag & _IORW)
X	fp->_flag &= ~(_IOREAD | _IOWRT);
X
X#endif
X
Xif((fp->_flag & (_IOWRT | _IORW)) && fp->_base != NULL)
X	{
X	if(fp->_flsbuf != NULL)		/* NULL means standard _flsbuf */
X		{
X		if(fp->_ptr > fp->_base)
X			return 0;
X
X		fp->_cnt++;
X		return (*fp->_flsbuf)(*--fp->_ptr, fp);
X		}
X	
X	if((n = fp->_ptr - fp->_base) > 0)
X		{
X		r = _fwrite(fp, fp->_base, n);
X
X		if(r < 0)
X			r = EOF;
X
X		fp->_ptr = fp->_base;		/* moving these outside of */
X		fp->_cnt = fp->_bufsiz;		/* writeability test would */
X						/* allow "flushing" input */
X						/* fp's, whatever that means */
X		}
X	}
X
Xreturn r;
X}
EOF
chmod 644 fflush.c
shouldbe=693
size=`wc -c < fflush.c`
if test $size -ne $shouldbe; then
	echo "shar: $0: error extracting fflush.c ($size != $shouldbe)" 1>&2
fi
else echo "shar: $0: will not overwrite existing file fflush.c" 1>&2; fi

if test $overwritecheck = no -o ! -f fgetc.c; then
case $verbose in
yes)	echo "extracting fgetc.c";;
esac
sed 's/^X//' > fgetc.c <<\EOF
X#include <stdio.h>
X
Xfgetc(fp)
XFILE *fp;
X{
Xreturn getc(fp);
X}
EOF
chmod 644 fgetc.c
shouldbe=61
size=`wc -c < fgetc.c`
if test $size -ne $shouldbe; then
	echo "shar: $0: error extracting fgetc.c ($size != $shouldbe)" 1>&2
fi
else echo "shar: $0: will not overwrite existing file fgetc.c" 1>&2; fi

if test $overwritecheck = no -o ! -f fgets.c; then
case $verbose in
yes)	echo "extracting fgets.c";;
esac
sed 's/^X//' > fgets.c <<\EOF
X#include <stdio.h>
X
Xchar *
Xfgets(s, n, fp)
Xchar *s;
Xint n;
XFILE *fp;
X{
Xregister char *p = s;
Xregister int c;
X
Xwhile(--n > 0)
X	{
X	c = getc(fp);
X
X	if(c == EOF)
X		break;
X
X	*p++ = c;
X	n--;
X
X	if(c == '\n')
X		break;
X	}
X
X*p = '\0';
X
Xreturn s;
X}
EOF
chmod 644 fgets.c
shouldbe=238
size=`wc -c < fgets.c`
if test $size -ne $shouldbe; then
	echo "shar: $0: error extracting fgets.c ($size != $shouldbe)" 1>&2
fi
else echo "shar: $0: will not overwrite existing file fgets.c" 1>&2; fi

if test $overwritecheck = no -o ! -f filbuf.c; then
case $verbose in
yes)	echo "extracting filbuf.c";;
esac
sed 's/^X//' > filbuf.c <<\EOF
X#include <stdio.h>
X
X_filbuf(fp)
Xregister FILE *fp;
X{
Xregister int r;
Xchar c;
X
Xif(fp == NULL)		/* would also be nice to check validity somehow */
X	{
X	/* set errno? */
X	/* call error handler? */
X	/* abort? */
X
X	return EOF;
X	}
X
Xif(fp->_filbuf != NULL)
X	return (*fp->_filbuf)(fp);
X
Xfp->_cnt = 0;	/* avoid runaway count if repeated getc's at EOF */
X		/* also ensures ungetc at EOF works */
X
X#ifdef READWRITE
X
Xif((fp->_flag & _IORW) && (fp->_flag & (_IOREAD | _IOWRT)) == 0)
X	fp->_flag |= _IOREAD;
X
X#endif
X
Xif(!(fp->_flag & _IOREAD) || (fp->_flag & _IOSTRG))
X	{
X	/* set errno? */
X	/* set _IOERR? */
X	/* call error handler? */
X	/* abort? */
X
X	return EOF;
X	}
X
X#ifdef STICKYEOF
X
Xif(fp->_flag & _IOEOF)
X	return EOF;
X
X#endif
X
X#ifdef STDINFLUSH
X
Xif(fp == stdin && (stdout->_flag & _IOLBF))	/* ? */
X	fflush(stdout);
X
X#endif
X
Xif(fp->_base == NULL)
X	_getbuf(fp);
X
Xif(fp->_readfunc == NULL)
X	r = 0;
Xelse	{
X	r = _fread(fp, fp->_base, fp->_bufsiz);
X
X	if(r > 0)
X		{
X		fp->_cnt = r - 1;
X		fp->_ptr = fp->_base;
X		c = *fp->_ptr++;
X		}
X	}
X
Xif(r <= 0)
X	return EOF;
X
Xreturn c & 0377;
X}
X
X_fread(fp, p, n)
Xregister FILE *fp;
Xchar *p;
Xint n;
X{
Xint r;
X
X#ifdef _IOFPTR
Xif(fp->_flag & _IOFPTR)
X	r = (*fp->_readfunc)(fp->_fptr, p, n);
Xelse
X#endif
X	r = (*fp->_readfunc)(fp->_file, p, n);
X
Xif(r <= 0)
X	{
X	if(r == 0)
X		{
X		fp->_flag |= _IOEOF;
X
X#ifdef READWRITE
X
X		if(fp->_flag & _IORW)
X			fp->_flag &= ~(_IOREAD | _IOWRT);
X#endif
X		}
X	else	{
X		fp->_flag |= _IOERR;
X		if(fp->_errfunc != NULL)
X			(*fp->_errfunc)(fp->_filename, 'r', fp);
X		}
X	}
X
Xreturn r;
X}
EOF
chmod 644 filbuf.c
shouldbe=1523
size=`wc -c < filbuf.c`
if test $size -ne $shouldbe; then
	echo "shar: $0: error extracting filbuf.c ($size != $shouldbe)" 1>&2
fi
else echo "shar: $0: will not overwrite existing file filbuf.c" 1>&2; fi

if test $overwritecheck = no -o ! -f flsbuf.c; then
case $verbose in
yes)	echo "extracting flsbuf.c";;
esac
sed 's/^X//' > flsbuf.c <<\EOF
X#include <stdio.h>
X
X#define TRUE 1
X#define FALSE 0
X
X_flsbuf(c, fp)
Xchar c;
Xregister FILE *fp;
X{
Xregister int r;
Xint nwrt;
Xint bufstyle;
Xint printedc = FALSE;
X
Xif(fp == NULL)		/* would also be nice to check validity somehow */
X	{
X	/* set errno? */
X	/* abort? */
X
X	return EOF;
X	}
X
Xif(fp->_flsbuf != NULL)
X	return (*fp->_flsbuf)(c, fp);
X
X#ifdef READWRITE
X
Xif((fp->_flag & _IORW) && (fp->_flag & (_IOREAD | _IOWRT)) == 0)
X	fp->_flag |= _IOWRT;
X
X#endif
X
Xif(!(fp->_flag & _IOWRT) || (fp->_flag & _IOSTRG) || fp->_writefunc == NULL)
X	{
X	/* set errno? */
X	/* set _IOERR? */
X	/* abort? */
X
X	return EOF;
X	}
X
Xif(fp->_base == NULL)
X	_getbuf(fp);
X
Xnwrt = fp->_ptr - fp->_base;
X
Xbufstyle = fp->_flag & (_IOFBF | _IONBF | _IOLBF);
X
Xif(bufstyle == _IOLBF)
X	{
X#ifdef PUTCLBUF
X	if(fp->_cnt > 0)
X#else
X	if(fp->_ptr < fp->_base + fp->_bufsiz)
X#endif
X		{
X		*fp->_ptr++ = c;
X#ifdef PUTCLBUF				/* shouldn't happen */
X		fp->_cnt--;
X#endif
X		nwrt++;
X		printedc = TRUE;
X		}
X
X#ifndef PUTCLBUF
X	if(c != '\n')
X		return c;
X#endif	
X	}
X
Xif(nwrt > 0)
X	r = _fwrite(fp, fp->_base, nwrt);
Xelse	r = 0;
X
Xif(!printedc && (bufstyle == _IONBF || bufstyle == _IOLBF && c == '\n'))
X	{
X	char realc = c;		/* so can take address portably */
X				/* (strictly speaking, declaring formal */
X				/*	char c; */
X				/* should suffice) */
X
X	if(_fwrite(fp, &realc, 1) < 0)
X		r = -1;
X
X	printedc = TRUE;
X	}
X
Xfp->_ptr = fp->_base;
X
Xfp->_cnt = (fp->_flag & (_IONBF
X#ifndef PUTCLBUF
X				| _IOLBF
X#endif
X					)) ? 0 : fp->_bufsiz;
X
Xif(!printedc)
X	{
X	*fp->_ptr++ = c;
X	fp->_cnt--;
X	}
X
Xif(r < 0)
X	return EOF;
X
Xreturn c & 0377;
X}
X
X_fwrite(fp, p, n)
XFILE *fp;
Xchar *p;
Xint n;
X{
Xint r;
X
Xif(fp->_writefunc == NULL)
X	return -1;
X
X#ifdef _IOFPTR
Xif(fp->_flag & _IOFPTR)
X	r = (*fp->_writefunc)(fp->_fptr, p, n);
Xelse
X#endif
X	r = (*fp->_writefunc)(fp->_file, p, n);
X
Xif(r < 0)		/* if r != n ?? */
X	{
X	fp->_flag |= _IOERR;
X	if(fp->_errfunc != NULL)
X		(*fp->_errfunc)(fp->_filename, 'w', fp);
X	}
X
Xreturn r;
X}
X
X#ifdef FORCECLEANUP
X
Xextern int _cleanup();
X
Xstatic int (*dummy)() = _cleanup;
X
X#endif
EOF
chmod 644 flsbuf.c
shouldbe=2025
size=`wc -c < flsbuf.c`
if test $size -ne $shouldbe; then
	echo "shar: $0: error extracting flsbuf.c ($size != $shouldbe)" 1>&2
fi
else echo "shar: $0: will not overwrite existing file flsbuf.c" 1>&2; fi

if test $overwritecheck = no -o ! -f flushall.c; then
case $verbose in
yes)	echo "extracting flushall.c";;
esac
sed 's/^X//' > flushall.c <<\EOF
Xextern int fflush();
X
X/* actually, this is identical to cleanup() */
X
Xflushall()
X{
X_scanfiles(fflush);
X}
EOF
chmod 644 flushall.c
shouldbe=105
size=`wc -c < flushall.c`
if test $size -ne $shouldbe; then
	echo "shar: $0: error extracting flushall.c ($size != $shouldbe)" 1>&2
fi
else echo "shar: $0: will not overwrite existing file flushall.c" 1>&2; fi

if test $overwritecheck = no -o ! -f fopen.c; then
case $verbose in
yes)	echo "extracting fopen.c";;
esac
sed 's/^X//' > fopen.c <<\EOF
X#include <stdio.h>
X#include "funcs.h"
X
X#define TRUE 1
X#define FALSE 0
X
XFILE *_ioblist = NULL;
X
Xextern FILE *_lastiob;
X
XFILE *_getfile();
X
Xextern (*_deflterrfunc)();
X
XFILE *
Xfopen(filename, mode)
Xchar *filename;
Xchar *mode;
X{
Xregister FILE *fp;
Xregister int fd;
Xint flag;
Xchar rwamode;
Xchar *p;
X#ifdef READWRITE
Xint rwflag = FALSE;
X#endif
X
Xrwamode = *mode;
X
X/*
X *  Should the flags really be accepted in any order?  H & S say
X *  only that "...any of the types ["r", "w+", etc.] [can] be
X *  followed by the character b..."
X */
X
Xfor(p = &mode[1]; *p != '0'; p++)
X	{
X	switch(*p)
X		{
X#ifdef READWRITE
X		case '+':
X			rwflag = TRUE;
X			break;
X#endif
X#ifdef notyet
X		case 'b':
X			binary = TRUE;
X			break;
X#endif
X		/* 
X		 *  Note that unrecognized mode modifiers are _i_g_n_o_r_e_d.
X		 *  This is desirable; semi-standard extensions to stdio
X		 *  are common, but not usually relevant on Unix systems.
X		 */
X		}
X	}
X
Xif(rwamode == 'r')
X	{
X#ifdef READWRITE
X	if(rwflag)
X		{
X		if((fd = (*_openfunc)(filename, 2)) < 0)
X			return NULL;
X		flag = _IORW;
X		}
X	else
X#endif
X		{
X		if((fd = (*_openfunc)(filename, 0)) < 0)
X			return NULL;
X		flag = _IOREAD;
X		}
X	}
Xelse	{
X#ifdef READWRITE
X	if(rwflag)
X		{
X		if(rwamode == 'w' || (fd = (*_openfunc)(filename, 2) < 0))
X			fd = (*_creatfunc)(filename, 0666);
X
X		if(fd < 0)
X			return NULL;
X
X		if((*_closefunc)(fd) < 0 ||
X				(fd = (*_openfunc)(filename, 2)) < 0)
X			return NULL;
X
X		if(rwamode == 'a')
X			(*_seekfunc)(fd, 0L, 2);
X
X		flag = _IORW;
X		}
X	else
X#endif
X		{
X		if(rwamode == 'w' || (fd = (*_openfunc)(filename, 1) < 0))
X			fd = (*_creatfunc)(filename, 0666);
X
X		if(fd < 0)
X			return NULL;
X
X		if(rwamode == 'a')
X			(*_seekfunc)(fd, 0L, 2);
X
X		flag = _IOWRT;
X		}
X	}
X
Xif((fp = _getfile()) != NULL)
X	{
X	fp->_file = fd;
X	fp->_flag |= flag;
X	if((fp->_filename = (*_mallocfunc)(strlen(filename) + 1)) != NULL)
X		strcpy(fp->_filename, filename);
X	}
X
Xreturn fp;
X}
X
XFILE *
X_getfile()
X{
Xregister FILE *fp;
X
Xfor(fp = _iob; fp < _lastiob; fp++)
X	{
X	if(fp->_flag == 0)
X		{
X		_initfile(fp);
X		return fp;
X		}
X	}
X
Xif((fp = (FILE *)(*_mallocfunc)(sizeof(FILE))) != NULL)
X	{
X	_initfile(fp);
X
X	fp->_next = _ioblist;	/* would be nicer to keep FIFO */
X	_ioblist = fp;
X	}
X	/*
X	 *  ...else set errno?  (Generally, library functions
X	 *  shouldn't, but the caller is likely to call perror
X	 *  after f*open returns NULL, and EMFILE is germane.)
X	 */
X
Xreturn fp;
X}
X
X_freefile(fp)
Xregister FILE *fp;
X{
Xregister FILE **fpp;
X
Xif(fp->_base != NULL && (fp->_flag & _IOMYBUF))
X	{
X	(*_freefunc)(fp->_base);
X	fp->_base = NULL;
X	}
X
Xif(fp->_filename != NULL && !(fp->_flag & _IOSTFN))
X	{
X	(*_freefunc)(fp->_filename);
X	fp->_filename = NULL;
X	}
X
Xif(fp >= _iob && fp < _lastiob)		/* potentially unportable */
X	{					/* pointer comparison */
X	fp->_flag = 0;
X	return;
X	}
X
Xfor(fpp = &_ioblist; *fpp != NULL; fpp = &(*fpp)->_next)
X	{
X	if(*fpp == fp)
X		{
X		*fpp = fp->_next;
X		break;
X		}
X	}
X
X/* what if it wasn't found? */
X
X(*_freefunc)((char *)fp);
X}
X
X_initfile(fp)
Xregister FILE *fp;
X{
Xfp->_base = fp->_ptr = fp->_filename = NULL;
Xfp->_cnt = fp->_flag = 0;
Xfp->_bufsiz = BUFSIZ;	/* could be 0; caller will usually fix;
X						but 0 is too dangerous */
Xfp->_filbuf = NULL;
Xfp->_flsbuf = NULL;
Xfp->_readfunc = _readfunc;
Xfp->_writefunc = _writefunc;
Xfp->_seekfunc = _seekfunc;
Xfp->_closefunc = _closefunc;
Xfp->_errfunc = _deflterrfunc;
X
X/* _next not set: would break freopen */
X}
EOF
chmod 644 fopen.c
shouldbe=3375
size=`wc -c < fopen.c`
if test $size -ne $shouldbe; then
	echo "shar: $0: error extracting fopen.c ($size != $shouldbe)" 1>&2
fi
else echo "shar: $0: will not overwrite existing file fopen.c" 1>&2; fi

if test $overwritecheck = no -o ! -f fprintf.c; then
case $verbose in
yes)	echo "extracting fprintf.c";;
esac
sed 's/^X//' > fprintf.c <<\EOF
X#include <stdio.h>
X#include <stdarg.h>
X
X/* VARARGS2 */
X
Xfprintf(fp, fmt)
XFILE *fp;
Xchar *fmt;
X{
Xregister va_list argp;
Xint r;
X
Xva_start(argp, fmt);
Xr = _doprnt(fmt, argp, fp);
Xva_end(argp);
Xreturn r;
X}
EOF
chmod 644 fprintf.c
shouldbe=202
size=`wc -c < fprintf.c`
if test $size -ne $shouldbe; then
	echo "shar: $0: error extracting fprintf.c ($size != $shouldbe)" 1>&2
fi
else echo "shar: $0: will not overwrite existing file fprintf.c" 1>&2; fi

if test $overwritecheck = no -o ! -f fputc.c; then
case $verbose in
yes)	echo "extracting fputc.c";;
esac
sed 's/^X//' > fputc.c <<\EOF
X#include <stdio.h>
X
Xfputc(c, fp)
Xchar c;
XFILE *fp;
X{
Xreturn putc(c, fp);
X}
EOF
chmod 644 fputc.c
shouldbe=75
size=`wc -c < fputc.c`
if test $size -ne $shouldbe; then
	echo "shar: $0: error extracting fputc.c ($size != $shouldbe)" 1>&2
fi
else echo "shar: $0: will not overwrite existing file fputc.c" 1>&2; fi
exit