clearerr.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	void clearerr(FILE *stream);
 *
 *
 *	Description
 *
 *		The clearerr function clears the end-of-file and error indicators for
 *	the stream pointed to by stream.
 *
 *
 *	Returns
 *
 *		The clearerr function returns no value.
 */

#include <stdio.h>

#undef clearerr

void
clearerr(FILE *stream)
{
	stream->_flags &= ~(_IOERR|_IOEOF);
}

fclose.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	int fclose(FILE *stream);
 *
 *
 *	Description
 *
 *		The fclose function causes the stream pointed to by stream to be
 *	flushed and the associated file to be closed. Any unwritten buffered data
 *	for the stream are delivered to the host environment to be written to the
 *	file; any unread buffered data are discarded. The stream is disassociated
 *	from the file. If the associated buffer was automatically allocated, it is
 *	deallocated.
 *
 *
 *	Returns
 *
 *		The fclose function returns zero if the stream was successfully closed,
 *	or EOF if any errors were detected.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

extern int _unlink(char *name);
extern int _close(int fildes);

int
fclose(register FILE *stream)
{
	register int err = 0;

	if (stream == 0 || stream->_flags == 0)
		return(EOF);
	if ((stream->_flags & _IOR) == 0)
		err |= fflush(stream);
	err |= _close((int)stream->_unit);
	if (stream->_flags & _IOMYBUF)
		free(stream->_buff);
	if (stream->_tmpnum) {					/* temp file, delete it */
		register unsigned short val;
		register int i;
		char tmpbuf[9];

		strcpy(tmpbuf, "TMP");
		val = stream->_tmpnum;
		for (i=0;i<5;i++) {
			tmpbuf[3+4-i] = '0' + val % 10;
			val /= 10;
		}
		tmpbuf[8] = 0;
		_unlink(tmpbuf);
	}

	stream->_buff =
	stream->_bend =
	stream->_bp = 0;	/* nothing in buffer */
	stream->_flags = 0;
	if (err)
		return(EOF);
	return(0);
}

fdopen.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	FILE *fdopen(int fildes, const char *mode);
 *
 *
 *	Description
 *
 *		The fdopen function associates a stream with the file whose file
 *	descriptor is specified by fildes. The mode argument is used as in the
 *	_fileopen function and must agree with the low-level open used to get the
 *	file descriptor.
 *
 *
 *	Returns
 *
 *		The fdopen function returns a null pointer if the operation fails.
 *	Otherwise, fdopen returns the value of the stream allocated.
 */

#include <stdio.h>

extern FILE *_getiob(void);
extern FILE *_fileopen(const char *name, const char *mode,
													FILE *stream, int fildes);

FILE *
fdopen(register int fd, register const char *mode)
{
	return(_fileopen((char *)0, mode, _getiob(), fd));
}

feof.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	int feof(FILE *stream);
 *
 *
 *	Description
 *
 *		The feof function tests the end-of-file indicator for the stream
 *	pointed to by stream.
 *
 *
 *	Returns
 *
 *		The feof function returns nonzero if and only if the end-of-file
 *	indicator is set for the stream.
 */

#include <stdio.h>

#undef feof

int
feof(FILE *stream)
{
	return(stream->_flags&_IOEOF);
}

ferror.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	int ferror(FILE *stream);
 *
 *
 *	Description
 *
 *		The ferror function tests the error indicator for the stream pointed to
 *	by stream.
 *
 *
 *	Returns
 *
 *		The ferror function returns nonzero if and only if the error indicator
 *	is set for the stream.
 */

#include <stdio.h>

#undef ferror

int
ferror(FILE *stream)
{
	return(stream->_flags&_IOERR);
}

fflush.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	int fflush(FILE *stream);
 *
 *
 *	Description
 *
 *		If stream points to an output stream or an update stream in which the
 *	most recent operation was output, the fflush function causes any unwritten
 *	data for that stream to be delivered to the host environment to be written
 *	to the file; otherwise, the behavior is undefined.
 *
 *		If stream is a null pointer, the fflush function performs this flushing
 *	action on all streams for which the behavior is defined above.
 *
 *
 *	Returns
 *
 *		The fflush function returns EOF if a write error occurs, otherwise
 *	zero.
 */

#include <stdio.h>

extern int _flsbuf(FILE *stream, int data);

int
fflush(register FILE *stream)
{
	if (stream == 0) {
		for (stream=_iob;stream < _iob+FOPEN_MAX;stream++) {
			if (stream->_flags == 0 || (stream->_flags&(_IOR|_IOSTRNG)))
				continue;
			if (_flsbuf(stream, -1) == EOF)
				return(EOF);
		}
		return(0);
	}
	return(_flsbuf(stream, -1));
}

fgetc.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	int fgetc(FILE *stream);
 *
 *
 *	Description
 *
 *		The fgetc function obtains the next character (if present) as an
 *	unsigned char converted to an int, from the input stream pointed to by
 *	stream, and advances the associated file position indicator for the stream
 *	(if defined).
 *
 *
 *	Returns
 *
 *		The fgetc function returns the next character from the input stream
 *	pointed to by stream. If the stream is at end-of-file, the end-of-file
 *	indicator for the stream is set and fgetc returns EOF. If a read error
 *	occurs, the error indicator for the stream is set and fgetc returns EOF.
 */

#asm
	cseg
	xdef	_fgetc
_fgetc:
	jmp		_getc
#endasm

/*
 *	Synopsis
 *
 *	int getc(FILE *stream);
 *
 *
 *	Description
 *
 *		The getc function is equivalent to fgetc, except that if it is
 *	implemented as a macro, it may evaluate stream more than once, so the
 *	argument should never be an expression with side effects.
 *
 *
 *	Returns
 *
 *		The getc function returns the next character from the input stream
 *	pointed to by stream. If the stream is at end-of-file, the end-of-file
 *	indicator for the stream is set and getc returns EOF. If a read error
 *	occurs, the error indicator for the stream is set and getc returns EOF.
 */

#include <stdio.h>

#undef getc

int
getc(register FILE *stream)
{
	if (stream == 0 || stream->_flags == 0)
		return(EOF);
	if (stream->_bp < stream->_bend)
		return(*stream->_bp++);
	return(_filbuf(stream));
}

fgetpos.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	int fgetpos(FILE *stream, fpos_t *pos);
 *
 *
 *	Description
 *
 *		The fgetpos function stores the current value of the file position
 *	indicator for the stream pointed to by stream in the object pointed to by
 *	pos. The value stored contains unspecified information usable by the
 *	fsetpos function for repositioning the stream to its position at the time
 *	of the call to the fgetpos function.
 *
 *
 *	Returns
 *
 *		If successful, the fgetpos function returns zero; on failure, the
 *	fgetpos function returns nonzero and stores an implementation-defined
 *	positive value in errno.
 */

#include <stdio.h>
#include <errno.h>

int
fgetpos(FILE *stream, fpos_t *pos)
{
	long curp;

	curp = ftell(stream);
	if (curp == -1L) {
		errno = EINVAL;
		return(EOF);
	}
	*pos = (fpos_t)curp;
	return(0);
}

fgets.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	char *fgets(char *s, int n, FILE *stream);
 *
 *
 *	Description
 *
 *		The fgets function reads at most one less than the number of characters
 *	specified by n from the stream pointed to by stream into the array pointed
 *	to by s. No additional characters are read after a new-line character
 *	(which is retained) or after end-of-file. A null character is written
 *	immediately after the last character read into the array.
 *
 *
 *	Returns
 *
 *		The fgets function returns s if successful. If end-of-file is
 *	encountered and no characters have been read into the array, the contents
 *	of the array remain unchanged and a null pointer is returned. If a read
 *	error occurs during the operation, the array contents are indeterminate and
 *	a null pointer is returned.
 */

#include <stdio.h>

char *
fgets(char *s, register int n, register FILE *stream)
{
	register c;
	register char *cp;

	cp = s;
	while (--n > 0) {
		if ((c = getc(stream)) != EOF) {
			*cp = c;
			cp++;
			if (c != '\n')
				continue;
			break;
		}
		if (cp == s || !feof(stream))
			return(0);
		break;
	}
	*cp = '\0';
	return(s);
}

filbuf.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	int _filbuf(FILE *stream);
 *
 *
 *	Description
 *
 *		The _filbuf function
 *
 *
 *	Returns
 *
 *
 */

#include <stdio.h>

extern int _read(int fildes, void *ptr, size_t size);
extern void _getbuf(FILE *stream);

int
_filbuf(register FILE *stream)
{
	register int len;
	register int flags;
	register FILE *fp;

	if (stream == 0 || (flags=stream->_flags) == 0 || (flags & _IOW) ||
															(flags & _IOSTRNG))
		return(EOF);

	if (stream->_bp >= stream->_bend) {
		if (stream->_buff == 0)
			_getbuf(stream);
 		if (stream->_flags & (_IOLBF|_IONBF)) {
			for (fp=_iob;fp < _iob+FOPEN_MAX;fp++) {
				if ((fp->_flags & (_IOLBF|_IODIRTY)) == (_IOLBF|_IODIRTY))
					fflush(fp);
			}
		}
		stream->_flags &= ~(_IODIRTY|_IOUNG);
		if ((len = _read((int)stream->_unit, stream->_buff,
												stream->_buflen)) <= 0) {
			stream->_flags |= len==0 ? _IOEOF : _IOERR;
			return(EOF);
		}
		stream->_bend = (stream->_bp = stream->_buff) + len;
	}
	return(*stream->_bp++);
}

fileopen.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	FILE *_fileopen(const char *name, const char *mode, FILE *stream,
 *			int fildes);
 *
 *
 *	Description
 *
 *		The _fileopen function opens the file whose name is the string pointed
 *	to by filename, and associates the stream stream with it. If name is a null
 *	pointer, then the stream is associated with the file descriptor fildes.
 *
 *		The argument mode pointes to a string beginning with one of the
 *	following sequences:
 *
 *		"r"		open text file for reading
 *		"w"		truncate to zero length or create text file for writing
 *		"a"		append; open or create text file for writing at end-of-file
 *		"rb"	open binary file for reading
 *		"wb"	truncate to zero length or create binary file for writing
 *		"ab"	append; open or create binary file for writing at end-of-file
 *		"r+"	open text file for update (reading and writing)
 *		"w+"	truncate to zero length or create text file for update
 *		"a+"	append; open or create text file for update, writing at
 *				end-of-file
 *		"r+b"
 *		"rb+"	open binary file for update (reading and writing)
 *		"w+b"
 *		"wb+"	truncate to zero length or create binary file for update
 *		"a+b"
 *		"ab+"	append; open or create binary file for update, writing at
 *				end-of-file
 *
 *		Opening a file with read mode ('r' as the first character in the mode
 *	argument) fails if the file does not exist or cannot be read.
 *
 *		Opening a file with append mode ('a' as the first character in the mode
 *	argument) causes all subsequent writes to the file to be forced to the then
 *	current end-of-file, regardless of intervening calls to the fseek function.
 *	In some implementations, opening a binary file with append mode ('b' as the
 *	second or third character in the mode argument) may initially position the
 *	file position indicator for the stream beyond the last data written,
 *	because of null character padding.
 *
 *		When a file is opened with update mode ('+' as the second or third
 *	character in the mode argument), both input and output may be performed on
 *	the associated stream. However, output may not be directly followed by
 *	input without an intervening call to the fflush function or to a file
 *	positioning function (fseek, fsetpos, or rewind), and input may not be
 *	directly followed by output without an intervening call to a file
 *	positioning function, unless the input operation encounters end-of-file.
 *	Opening a file with update mode may open or create a binary stream in some
 *	implementations.
 *
 *		When opened, a stream is fully buffered if and only if it can be
 *	determined not to refer to an interactive device. The error and end-of-file
 *	indicators for the stream are cleared.
 *
 *
 *	Returns
 *
 *		The _fileopen function returns a pointer to the object controlling the
 *	stream. If the open operation fails, _fileopen returns a null pointer.
 */

#include <stdio.h>
#include <fcntl.h>

FILE *
_fileopen(const char *name, register const char *mode,
											register FILE *fp, int fd)
{
	register int omode, flag;
	register int c;

	flag = _IOW;
	if ((c=mode[0]) == 'r') {
		omode = O_RDONLY|O_TEXT;
		flag = _IOR;
	}
	else if (c == 'w')
		omode = O_WRONLY|O_CREAT|O_TRUNC|O_TEXT;
	else if (c == 'a')
		omode = O_WRONLY|O_CREAT|O_APPEND|O_TEXT;
	else
nullret:
		return(0);
	++mode;
	if (mode[0] == '+' && mode[1] == 'b')
		goto isbinary;
	if (mode[0] == 'b') {
		++mode;
isbinary:
		flag |= _IOBIN;
		omode &= ~O_TEXT;
	}
	if (mode[0] == '+') {
		omode = (omode & ~(O_RDONLY|O_WRONLY)) | O_RDWR;
		flag = (flag & ~(_IOR|_IOW)) | _IORW;
	}

	if (name != 0)
		fd = open(name, (int)omode);

	if (fd < 0 || fd >= FOPEN_MAX)
		goto nullret;

	fp->_unit = fd;
	fp->_flags = flag;
	return(fp);
}

FILE *
_getiob(void)
{
	register FILE *stream;

	stream = _iob;
	while (stream->_flags)
		if (++stream == _iob+FOPEN_MAX)
			return(0);

	stream->_tmpnum = 0;	/* no temporary file */

	stream->_buff =			/* nothing in buffer */
	stream->_bend =
	stream->_bp = 0;

	return(stream);
}

flsbuf.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	int _flsbuf(FILE *stream, int data);
 *
 *
 *	Description
 *
 *		The _flsbuf function flushes the specified stream if it has been opened
 *	for writing or updating and is dirty. If data is not a -1, then data is
 *	placed in the newly flushed buffer and the buffer marked as dirty.
 *	Otherwise, the stream is placed in the neutral state awaiting either reads
 *	or writes.
 *
 *
 *	Returns
 *
 *		The _flsbuf function returns the value of the data passed in. If an
 *	error occurs writing the stream, the error flag is set in the stream and
 *	EOF is returned. If the data value is -1, a zero is returned if nor errors
 *	occur.
 */

#include <stdio.h>
#include <fcntl.h>

extern void (*_close_stdio)(void);
extern void _getbuf(FILE *stream);
extern int _write(int fildes, void *ptr, size_t len);

static void
closeall(void)		/* called by exit to close any open files */
{
	register FILE *stream;

	for (stream=_iob;stream<_iob+FOPEN_MAX;stream++)
		fclose(stream);
}

int
_flsbuf(register FILE *stream, register int data)
{
	register short flags;
	register size_t len;
	register unsigned char c;

	if (stream == 0 || (flags=stream->_flags) == 0 || (flags & _IOR) ||
															(flags & _IOSTRNG))
		goto errout;

	stream->_flags &= ~(_IOEOF|_IOUNG);

	if (stream->_buff == 0) {
		if (data == -1)
			return(0);
		_getbuf(stream);
		flags = stream->_flags;
	}

	if ((flags & _IODIRTY) == 0) {
		if (stream->_bp > stream->_buff)	/* unread data in buffer */
			lseek((int)stream->_unit, (long)(stream->_bp-stream->_bend), 1);
		stream->_bp = stream->_buff;
		stream->_bend = stream->_bp + stream->_buflen;
	}
	if (data == -1)
		c = 0;
	else
		c = data;

	len = stream->_bp - stream->_buff;
	if (flags & (_IOLBF|_IONBF)) {
		if (data != -1) {						/* not flushing, add to buf */
			*stream->_bp++ = c;
			flags = stream->_flags |= _IODIRTY;
			_close_stdio = closeall;
			len++;
		}
		if (data == -1 || c == '\n' || len >= stream->_buflen)
			data = -1;
		else {
			stream->_bend = stream->_bp;
			return(c);
		}
	}

	if (flags & _IODIRTY) {
		if (len && _write((int)stream->_unit, stream->_buff, len) != len)
			goto ioerr;
		stream->_flags &= ~_IODIRTY;
	}

	if (data == -1) {						/* flush only and return */
		stream->_bend = stream->_bp = stream->_buff;
		return(c);
	}

	_close_stdio = closeall;
	stream->_flags |= _IODIRTY;
	stream->_bp = stream->_buff;
	stream->_bend = stream->_bp + stream->_buflen;
	return(*stream->_bp++ = c);

ioerr:
	stream->_flags |= _IOERR;
	stream->_bp = stream->_bend = stream->_buff;

errout:
	return(EOF);
}

fopen.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	FILE *fopen(const char *filename, const char *mode);
 *
 *
 *	Description
 *
 *		The fopen function opens the file whose name is the string pointed to
 *	by filename, and associates a stream with it. The mode argument is used
 *	just as in the _fileopen function.
 *
 *
 *	Returns
 *
 *		The fopen function returns a pointer to the object controlling the
 *	stream. If the open operation fails, fopen returns a null pointer.
 */

#include <stdio.h>

extern FILE *_getiob(void);
extern FILE *_fileopen(const char *name, const char *mode,
													FILE *stream, int fildes);

FILE *
fopen(const char *name, const char *mode)
{
	return(_fileopen(name, mode, _getiob(), -1));
}

format.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	int _format(FILE *stream, const char *format, va_list varg);
 *
 *
 *	Description
 *
 *		The format shall be a multibyte character sequence, beginning and
 *	ending in its initial shift state. The format is composed of zero or more
 *	directives: ordinary multibyte characters (not %), which are copied
 *	unchanged to the output stream; and conversion specifications, each of
 *	which results in fetching zero or more subsequent arguments. Each
 *	conversion specification is introduced by the character %. After the %, the
 *	following appear in sequence:
 *
 *	  - Zero or more flags that modify the meaning of the conversion
 *		specification.
 *
 *	  - An optional decimal integer specifying a minimum field width. If the
 *		converted value has fewer characters than the field width, it will be
 *		padded with spaces on the left (or right, if the left adjustment flag,
 *		described later, has been given) to the field width.
 *
 *	  - An optional precision that gives the minimum number of digits to appear
 *		for the d, i, o, u, x, and X conversions, the number of digits to
 *		appear after the decimal-point character for e, E, and f conversions,
 *		the maximum number of significant digits for the g and G conversions,
 *		or the maximum number of characters to be written from a string in s
 *		conversion. The precision takes the form of a period (.) followed by an
 *		optional decimal integer, if the integer is omitted, it is treated as
 *		zero.
 *
 *	  - An optional h specifying that a following d, i, o, u, x, or X
 *		conversion specifier applies to a short int or unsigned short int
 *		argument (the argument will have been promoted according to integral
 *		promotions, and its value shall be converted to short int or unsigned
 *		short int before printing); an optional h specifying that a following n
 *		conversion specifier applies to a pointer to a short int argument; an
 *		optional l (ell) specifying that a following d, i, o, u, x, or X
 *		conversion specifier applies to a long int or unsigned long int
 *		argument; an optional l specifying that a following n conversion
 *		specifier applies to a pointer to a long int argument; or an optional L
 *		specifying that a following e, E, f, g, or G conversion specifier
 *		applies to a long double argument. If an h, l, or L appears with any
 *		other conversion specifier, the behavior is undefined.
 *
 *	  - A character that specifies the type of conversion to be applied.
 *
 *		A field width or precision, or both, may be indicated by an asterisk *
 *	instead of a digit string. In this case, an int argument supplies the field
 *	width or precision. The arguments specifying field width or precision, or
 *	both, shall appear (in that order) before the argument (if any) to be
 *	converted. A negative field width argument is taken as a - flag followed by
 *	a positive field width. A negative precision argument is taken as if it
 *	were missing.
 *
 *		The flag characters and their meanings are:
 *
 *	-	The result of the conversion will be left-justified within the field.
 *
 *	+	The result of a signed conversion will always begin with a plus or
 *		minus sign.
 *
 *	space	If the first character of a signed conversion is not a sign, or if
 *			a signed conversion results in no characters, a space will be
 *			prepended to the result. If the space and + flags both appear, the
 *			space flag will be ignored.
 *
 *	#	The result is to be converted to an "alternate form." For o conversion,
 *		it increases the precision to force the first digit of the result to be
 *		a zero. For x (or X) conversion, a nonzero result will have 0x (or 0X)
 *		prepended to it. For e, E, f, g, and G conversions, the result will
 *		always contain a decimal-point character, even if no digits follow it
 *		(normally, a decimal-point character appears in the result of these
 *		conversions only if a digit follows it). For g and G conversions,
 *		trailing zeros will NOT be removed from the result. For other
 *		conversions, the behavior is undefined.
 *
 *	0	For d, i, o, u, x, X, e, E, f, g, and G conversions, leading zeros
 *		(following any indication of a sign or base) are used to pad to the
 *		field width; no space padding is performed. If the 0 and - flags both
 *		appear, the 0 flag will be ignored. For d, i, o, u, x, and X
 *		conversions, if a precision is specified, the 0 flag will be ignored.
 *		For other conversions, the behavior is undefined.
 *
 *		The conversion specifiers and their meanings are:
 *
 *	d,i	The int argument is converted to signed decimal (d or i), unsigned
 *	o,u	octal (o), unsigned decimal (u), or unsigned hexadecimal notation
 *	x,X	(x or X); The letters abcdef are used for x conversion and the
 *		letters ABCDEF for X conversion. The precision specifies the
 *		minimum number of digits to appear; if the value being converted
 *		can be represented in fewer digits, it will be expanded with
 *		leading zeros. The default precision is 1. The result of converting
 *		a zero value with an explicit precision of zero is no characters.
 *
 *	f	The double argument is converted to decimal notation in the style
 *		[-]ddd.ddd, where the number of digits after the decimal-point
 *		character is equal to the precision specification. If the precision is
 *		missing, it is taken as 6; if the precision is explicitly zero, no
 *		decimal-point character appears. If a decimal-point character appears,
 *		at least one digit appears before it. The value is rounded to the
 *		appropriate number of digits.
 *
 *	e,E	The double argument is converted in the style [-]d.ddde[+-]dd, where
 *		there is one digit before the decimal-point character (which is nonzero
 *		if the argument is nonzero) and the number of digits after it is equal
 *		to the precision; if the precision is missing, it is taken as 6; if the
 *		precision is zero, no decimal-point character appears. The value is
 *		rounded to the appropriate number of digits. The E conversion specifier
 *		will produce a number with E instead of e introducing the exponent. The
 *		exponent always contains at least two digits. If the value is zero, the
 *		exponent is zero.
 *
 *	g,G	The double argument is converted in style f or e (or in style E in the
 *		case of G conversion specifier), with the precision specifying the
 *		number of significant digits. If an explicit precisio is zero, it is
 *		taken as 1. The style used depends on the value converted; style e will
 *		be used only if the exponent resulting from such a conversion is less
 *		than -4 or greater than or equal to the precision. Trailing zeros are
 *		removed from the fractional portion of the result; a decimal-point
 *		character appears only if it is followed by a digit.
 *
 *	c	The int argument is converted to an unsigned char, and the resulting
 *		character is written.
 *
 *	s	The argument shall be a pointer to an array of character type.
 *		Characters from the array are written up to (but not including) a
 *		terminating null character; if the precision is specified, no more than
 *		that many characters are written. If the precision is not specified or
 *		is greater than the size of the array, the array shall contain a null
 *		character.
 *
 *	p	The argument shall be a pointer to void. The value of the pointer is
 *		converted to a sequence of printable characters, in an implementation-
 *		defined manner.
 *
 *	n	The argument shall be a pointer to an integer into which is written the
 *		number of characters written to the output stream so far by this call
 *		to _format. No argument is converted.
 *
 *	%	A % is written. No argument is converted. The complete conversion
 *		specification shall be %%.
 *
 *		If a conversion specification is invalid, the behavior is undefined.
 *
 *		If any argument is, or points to, a union or aggregate (except for an
 *	array of character type using %s conversion, or a pointer cast to be a
 *	pointer to void using %p converstion), the behavior is undefined.
 *
 *		In no case does a nonexistent or small field width cause truncation of
 *	a field; if the result of a conversion is wider than the field width, the
 *	field is expanded to contain the conversion result.
 *
 *
 *	Returns
 *
 *		The _format function returns the number of characters transmitted, or a
 *	negative value if an output error occurred.
 */


#include <stdio.h>
#include <ctype.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>

#define PMISSING (32198)	/* unlikely precision */
#define SLEN 512
#define SLAST (SLEN-1)

#define LEFTJ		0x0001
#define SIGNED		0x0002
#define SPACED		0x0004
#define ALTERED		0x0008
#define SINTCONV	0x0010
#define NEGVAL		0x0020
#define LONGVAL		0x0040
#define SHORTVAL	0x0080
#define LONGDOUBLE	0x0100

#ifdef FLOAT
static void ldtoa(long double number, char *buffer, int maxwidth, int mode);
#endif

int
_format(register FILE *stream, const char *format, va_list varg)
{
	register short flags;
	register int i;
	register unsigned char c;
	int charcount;
	int fillc;
	int precision, width;
	auto char s[SLEN];
#ifdef FLOAT
	long double ld;
#endif

	charcount = 0;
	for (;;) {
		{
			register const char *fmt;

			if ((c = *(fmt=format)) == '\0')
				return(charcount);
			++fmt;
			if ( c != '%' ) {
				i = charcount;
				do {
					if (putc(c, stream) == EOF)
						goto errout;
					++i;
					if ((c = *fmt) == '\0')
						return(i);
					++fmt;
				} while (c != '%');
				charcount = i;
			}
			flags = 0;
			fillc = ' ';
parse_flags:
			switch (c = *fmt++) {
			case '-':
				flags |= LEFTJ;
				goto parse_flags;
			case '+':
				flags |= SIGNED;
				goto parse_flags;
			case ' ':
				flags |= SPACED;
				goto parse_flags;
			case '#':
				flags |= ALTERED;
				goto parse_flags;

/* field width */
			case '*':
				i = va_arg(varg, int);
				if (i < 0) {
					flags |= LEFTJ;
					i = -i;
				}
				c = *fmt++;
				break;
			case '0':
				fillc = '0';
				/*FALLTHROUGH*/
			default:
				for (i = 0 ; isdigit(c) ; c = *fmt++)
					i = (i*8+i+i) + c - '0';

			} /* endswitch */
			width = i;

/* precision */
			i = PMISSING;
			if (c == '.') {
				if ((c = *fmt++) == '*') {
					i = va_arg(varg, int);
					if (i < 0)
						i = PMISSING;
					c = *fmt++;
				} else {
					for (i = 0 ; isdigit(c) ; c = *fmt++)
						i = (i*8+i+i) + c - '0';
				}
				if (i != PMISSING)
					fillc = ' ';
			}
			precision = i;
			if (c == 'h') {
				flags |= SHORTVAL;
				goto skip_l;
			}
			if (c == 'l') {
				flags |= LONGVAL;
				goto skip_l;
			}
			if (c == 'L') {
				flags |= LONGDOUBLE;
skip_l:
				c = *fmt++;
			}
			format = fmt;
		}
		{
			register char *cp;

			switch ( c ) {
			default:
				goto errout;

			case 'n':
				if (flags & SHORTVAL)
					*va_arg(varg, short int *) = charcount;
				else if (flags & LONGVAL)
					*va_arg(varg, long int *) = charcount;
				else
					*va_arg(varg, int *) = charcount;
				i = 0;
				break;
#ifdef FLOAT
			case 'e':
			case 'f':
			case 'g':
			case 'E':
			case 'G':
				flags |= SINTCONV;
				cp = s;
				if (precision == PMISSING)
					precision = 6;
				i = tolower((int)c) - 'e';
				if (isupper(c))
					i |= 0x10;
				if (flags & ALTERED)
					i |= 0x20;
				if (flags & LONGDOUBLE)
					ld = va_arg(varg, long double);
				else
					ld = va_arg(varg, double);
				ldtoa(ld, cp, precision, i);
				if (*cp == '-') {
					++cp;
					flags |= NEGVAL;
				}
				precision = SLEN;
				goto ilencp;
#endif
			case 's':
				cp = va_arg(varg, char *);
ilencp:
				i = strlen(cp);
				if (precision != PMISSING && i > precision)
					i = precision;
				break;
			case 'c':
				c = va_arg(varg, int);
				/*FALLTHROUGH*/
			case '%':
				*(cp = s) = c;
				i = 1;
				break;
			case 'o':
				i = 8;
				goto do_conversion;
			case 'p':
				flags |= ALTERED|LONGVAL;
				c = 'x';
				/*FALLTHROUGH*/
			case 'X':
			case 'x':
				i = 16;
				goto do_conversion;
			case 'i':
			case 'd':
				flags |= SINTCONV;
				/*FALLTHROUGH*/
			case 'u':
				i = 10;
do_conversion:
				{
					register unsigned long val;
					char *digits;

					digits = (c == 'X' ) ? "0123456789ABCDEF" :
															"0123456789abcdef";
					if (flags & LONGVAL)
						val = va_arg(varg, long);
					else if (flags & SINTCONV) 
						val = va_arg(varg, int);
					else
						val = va_arg(varg, unsigned int);
					if (flags & SINTCONV) {
						if ((long)val < 0) {
							val = -val;
							flags |= NEGVAL;
						}
					}

					cp = &s[SLAST+1];

/*	The default precision is 1 */

					if (precision == PMISSING)
						precision = 1;

/*	The result of converting a 0 value with a 0 precision is no characters */

					if (val != 0 || precision != 0) {
						do {
							*--cp = digits[(int)(val%i)];
						} while ((val /= i) != 0);
					}

					i = &s[SLAST+1] - cp;	/* # of characters in |value| */
					if (flags & ALTERED) {
/*
 *	For o conversion, increase the precision to force the first digit of the
 *	result to be a zero.  For x (or X) conversion, a nonzero result will have
 *	0x (or 0X) prepended to it.
 */
						if (c == 'o') {
							if (i == 0 || (*cp != '0' && i >= precision))
								 precision = i+1;
						} else if (c == 'x' || c == 'X') {
							if (i != 0 && *cp != '0') {
hexprex:
								while (i < precision && cp > &s[2]) {
									*--cp = '0';
									++i;
								}
								if(!(flags&LEFTJ) && fillc == '0' &&
																width > i+2) {
									precision = width - 2;
									goto hexprex;
								}
								*--cp = c;
								*--cp = '0';
								i += 2;
							}
						}
					}
							
					while (i < precision && cp > &s[0]) {
						*--cp = '0';
						++i;
					}
				} /* end of do_conversion block statement */

			} /* endswitch */

			if (flags & SINTCONV) {
				if (flags & NEGVAL)
			    	*--cp = '-';
				else if (flags & SIGNED)
					*--cp = '+';
				else if (flags & SPACED)
					*--cp = ' ';
				else
					--i;	/* nullify following ++i; */
				++i;
			} 
			charcount += i;
			if ( !(flags & LEFTJ) ) {
/*
 *	While the following may be reasonable (instead of 000-1 you get	-0001),
 *	it doesn't seem to be blessed by ANSI C.
 */
				if (fillc == '0') {
					if ((flags&SINTCONV) && (flags & (NEGVAL|SIGNED|SPACED))) {
						if (putc(*cp++, stream) == EOF)
							goto errout;
						--width;
						--i;
					}
				}
				for (; width-- > i ; ++charcount) {
					if (putc(fillc, stream) == EOF)
						goto errout;
				}
			}

/*	Output characters cp[0] through cp[i-1] of the converted value */

			precision = i;		/* save value of i in meaningless variable */
			while (i--)
				if (putc(*cp++, stream) == EOF)
					goto errout;

			if (flags & LEFTJ) {
				i = precision;	/* restore i */
		 		for (; width-- > i ; ++charcount)
					if (putc(' ', stream) == EOF)
						goto errout;
			}
		}
	}
errout:
	return(-1);
}

#ifdef FLOAT

#ifdef FP_FFP
static long lround[] = {
	0xa0000044L, 0x80000041L,
	0x80000040L, 0xcccccd3cL, 0xa3d70a39L, 0x83126e36L,
	0xd1b71632L, 0xa7c5ab2fL, 0x8637bc2cL, 0xd6bf9328L,
	0xabcc7625L, 0x89705e22L, 0xdbe6fd1eL, 0xafebfe1bL,
	0x8cbccb18L, 0xe12e1214L, 0xb424db11L, 0x901d7c0eL,
};
#else
static long double round[] = { 10, 1,
	5e-1, 5e-2, 5e-3, 5e-4, 5e-5, 5e-6, 5e-7, 5e-8, 5e-9, 5e-10,
	5e-11, 5e-12, 5e-13, 5e-14, 5e-15, 5e-16 };
#endif

void
ldtoa(long double number, register char *buffer, int maxwidth, int mode)
{
	register int i;
	register int exp, digit, decpos, ndig;
	register int flag;
#ifdef FP_FFP
	register float *round = (float *)lround;
#endif

#ifndef FP_FFP
#if FP_MANX || FP_881
	if ((*(short *)&number&0x7fff) == 0x7fff) {
#else
	if ((*(short *)&number&0x7ff0) == 0x7ff0) {
#endif
		exp = (*(short *)&number&0x8000) ? '-' : '+';
		while (maxwidth--)
			*buffer++ = exp;
		*buffer = 0;
		return;
	}
#endif	/* FP_FFP */

	/*
	 *	Convert the number to a number between 1 and 10 or 0. Calculate the
	 *	exponent at the same time.
	 */

	exp = 0;
	if (number < 0.0) {
		number = -number;
		*buffer++ = '-';
	}
	if (number > 0.0) {
		while (number < round[1]) {
			number *= round[0];
			--exp;
		}
		while (number >= round[0]) {
			number /= round[0];
			++exp;
		}
	}


	/*
	 *	The number of digits to display is equal to the number of digits
	 *	following the decimal point (maxwidth) + digits to the left (exp) +
	 *	a guaranteed digit since the number 10 > x >= 1. For E format, the
	 *	exp digits are not counted, while G format works differently.
	 */

	flag = mode & 3;
	if (flag == 2) {						/* 'g' format */
		if (maxwidth == 0)
			maxwidth = 1;
		if (exp < -4 || exp >= maxwidth)
			flag = -1;						/* switch to 'e' format */
		ndig = maxwidth;
	} else if (flag == 1)					/* 'f' format */
		ndig = maxwidth + exp + 1;
	else									/* 'e' format */
		ndig = maxwidth + 1;

	/*
	 *	Round the number up using 5e-x where x is one more than the
	 *	precision of the number.
	 */

	if (ndig > 0) {
		if ((number += round[(ndig>16?16:ndig)+1]) >= round[0]) {
			number = round[1];
			++exp;
			if (flag > 0)
				++ndig;
		}
	}

	if (flag > 0) {
		if (exp < 0) {
			*buffer++ = '0';
			*buffer++ = '.';
			i = -exp - 1;
			if (ndig <= 0)
				i = maxwidth;
			while (i--)
				*buffer++ = '0';
			decpos = 0;
		} else {
			decpos = exp+1;
		}
	} else {
		decpos = 1;
	}

	if (ndig > 0) {
		for (i = 0 ; ; ++i) {
			if (i < 16) {
				digit = (int)number;
				*buffer++ = digit+'0';
				number = (number - digit) * round[0];
			} else
				*buffer++ = '0';
			if (--ndig == 0)
				break;
			if (decpos && --decpos == 0)
				*buffer++ = '.';
		}
	}

	if (decpos && (mode&0x20))
		*buffer++ = '.';
	if (flag <= 0) {
		*buffer++ = (mode&0x10)?'E':'e';
		if (exp < 0) {
			exp = -exp;
			*buffer++ = '-';
		} else
			*buffer++ = '+';
		*buffer++ = exp/100 + '0';
		exp %= 100;
		*buffer++ = exp/10 + '0';
		*buffer++ = exp%10 + '0';
	}
	if (decpos == 0 && (flag == 2 || flag == -1) && (mode&0x20) == 0) {
		while (*--buffer == '0')
			;
		if (*buffer != '.')
			++buffer;
	}
	*buffer = 0;
}
#endif /* FLOAT */

fprintf.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	int fprintf(FILE *stream, const char *format, ...);
 *
 *
 *	Description
 *
 *		The fprintf function writes output to the stream pointed to by stream,
 *	under control of the string pointed to by format that specifies how
 *	subsequent arguments are converted for output. If there are insufficient
 *	arguments for the format, the behavior is undefined. If the format is
 *	exhausted while arguments remain, the excess arguments are evaluated (as
 *	always) but are otherwise ignored. The fprintf function returns when the
 *	end of the format string is encountered.
 *
 *		See the _format function for a complete description of the format
 *	string.
 *
 *
 *	Returns
 *
 *		The fprintf function returns the number of characters transmitted, or a
 *	negative value if an output error occurred.
 *
 *
 *	Environmental limit
 *
 *		The minimum value for the maximum number of characters produced by any
 *	single conversion shall be 509.
 */

#include <stdio.h>
#include <stdarg.h>

extern int _format(FILE *stream, const char *format, va_list vargs);

int
fprintf(FILE *stream, const char *format, ...)
{
	register va_list vargs;
	register int ret;

	va_start(vargs, format);
	ret = _format(stream, format, vargs);
	va_end(vargs);
	return(ret);
}

fputc.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	int fputc(int c, FILE *stream);
 *
 *
 *	Description
 *
 *		The fputc function writes the character specified by c (converted to an
 *	unsigned char) to the output stream pointed to by stream, at the position
 *	indicated by the by the associated file position indicator for the stream
 *	(if defined), and advances the indicator appropriately. If the file cannot
 *	support positioning requests, or if the stream was opened with append mode,
 *	the character is appended to the output stream.
 *
 *
 *	Returns
 *
 *		The fputc function returns the character written. If a write error
 *	occurs, the error indicator for the stream is set and fputc returns EOF.
 */

#asm
	cseg
	xdef	_fputc
_fputc:
	jmp		_putc
#endasm

/*
 *	Synopsis
 *
 *	int putc(int c, FILE *stream);
 *
 *
 *	Description
 *
 *		The putc function is equivalent to fputc, except that if it is
 *	implemented as a macro, it may evaluate stream more than once, so the
 *	argument should never be an expression with side effects.
 *
 *
 *	Returns
 *
 *		The putc function returns the character written. If a write error
 *	occurs, the error indicator for the stream is set and putc returns EOF.
 */

#include <stdio.h>

#undef putc

int
putc(int c, register FILE *fp)
{
	if (fp == 0 || fp->_flags == 0)
		return(EOF);
	if (fp->_bp < fp->_bend)
		return(*fp->_bp++ = c);
	return(_flsbuf(fp, (int)(unsigned char)c));
}

fputs.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	int fputs(const char *s, FILE *stream);
 *
 *
 *	Description
 *
 *		The fputs function writes the string pointed to by s to the stream
 *	pointed to by stream. The terminating null character is not written.
 *
 *
 *	Returns
 *
 *		The fputs function returns EOF if a write error occurs; otherwise it
 *	returns a nonnegative value.
 */

#include <stdio.h>

int
fputs(register const char *s, register FILE *stream)
{
	register char c;

	for (; (c = *s); ++s) {
		if (putc(c, stream) == EOF)
			return(EOF);
	}
	return(0);
}

fread.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
 *
 *
 *	Description
 *
 *		The fread function reads, into the array pointed to by ptr, up to nmemb
 *	members whose size is specified by size, from the stream pointed to by
 *	stream. The file position indicator for the stream (if defined) is advanced
 *	by the number of characters successfully read. If an error occurs, the
 *	resulting value of the file position indicator for the stream is
 *	indeterminate. If a partial member is read, its value is indeterminate.
 *
 *
 *	Returns
 *
 *		The fread function returns the number of members successfully read,
 *	which may be less than nmemb if a read error or end-of-file is encountered.
 *	If size or nmemb is zero, fread returns zero and the contents of the array
 *	and the state of the stream remain unchanged.
 */

#include <stdio.h>

size_t
fread(register void *ptr, register size_t size, register size_t nmemb,
														register FILE *stream)
{
	register size_t total, i;
	register int c;

	if (size == 0)
		return(0);
	for ( total = 0 ; total < nmemb ; ++total ) {
		for ( i = size ; i ; --i ) {
			if ( (c = getc(stream)) == EOF )
				goto eof;
			*(char *)ptr = (char)c;
			((char *)ptr)++;
		}
	}
eof:
	return(total);
}

freopen.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	FILE *freopen(const char *filename, const char *mode, FILE *stream);
 *
 *
 *	Description
 *
 *		The freopen funciton opens the file whose name is the string pointed to
 *	by filename and associates the stream pointed to by stream with it. The
 *	mode argument is used just as in the _fileopen function.
 *
 *		The freopen function first attempts to close any file that is
 *	associated with the specified stream. Failure to close the file
 *	successfully is ignored. The error and end-of-file indicators for the
 *	stream are cleared.
 *
 *
 *	Returns
 *
 *		The freopen function returns a null pointer if the open operation
 *	fails. Otherwise, freopen returns the value of stream.
 */

#include <stdio.h>

extern FILE *_fileopen(const char *name, const char *mode,
													FILE *stream, int fildes);

FILE *
freopen(const char *name, const char *mode, register FILE *fp)
{
	if (fp == 0 || fp->_flags == 0)
		return(0);
	fclose(fp);
	fp->_flags = 0;
	return(_fileopen(name, mode, fp, -1));
}

fscanf.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	int fscanf(FILE *stream, const char *format, ...);
 *
 *
 *	Description
 *
 *		The fscanf function reads input from the stream pointed to by stream,
 *	under control of the string pointed to by format that specifies the
 *	admissible input sequences and how they are to be converted for assignment,
 *	using subsequent arguments as pointers to the objects to receive the
 *	converted input. If there are insufficient arguments for the format, the
 *	behavior is undefined. If the format is exhausted while arguments remain,
 *	the excess arguments are evaluated (as always) but are otherwise ignored.
 *
 *		See the _scan function for a complete description of the format
 *	string.
 *
 *
 *	Returns
 *
 *		The fscanf function returns the value of the macro EOF if an input
 *	failure occurs before any conversion. Otherwise, the fscanf function
 *	returns the number of input items assigned, which can be fewer than
 *	provided for, or even zero, in the event of an early matching failure.
 */

#include <stdio.h>
#include <stdarg.h>

extern int _scan(FILE *stream, const char *format, va_list vargs);

int
fscanf(FILE *stream, const char *format, ...)
{
	register va_list vargs;
	register int ret;

	va_start(vargs, format);
	ret = _scan(stream, format, vargs);
	va_end(vargs);
	return(ret);
}

fseek.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	int fseek(FILE *stream, long int offset, int whence);
 *
 *
 *	Description
 *
 *		The fseek function sets the file position indicator for the stream
 *	pointed to by stream.
 *
 *		For a binary stream, the new position, measured in characters from the
 *	beginning of the file, is obtained by adding offset to the position
 *	specified by whence. The specified point is the beginning of the file for
 *	SEEK_SET, the current value of the file poistion indicator for SEEK_CUR, or
 *	end-of-file for SEEK_END. A binary stream need not meaningfully support
 *	fseek calls with a whence value of SEEK_END.
 *
 *		For a text stream, either offset shall be zero, or offset shall be a
 *	value returned by an earlier call to the ftell function on the same stream
 *	and whence shall be SEEK_SET.
 *
 *		A successful call to the fseek function clears the end-of-file
 *	indicator for the stream and undoes any effects of the ungetc function on
 *	the same stream. After an fseek call, the next operation on an update
 *	stream may be either input or output.
 *
 *
 *	Returns
 *
 *		The fseek function returns nonzero only for a request that cannot be
 *	satisfied.
 */

#include <stdio.h>

extern long _lseek(int fd, long pos, int whence);

int
fseek(register FILE *fp, register long pos, register int mode)
{
	register unsigned short flags;
	register long cleft;
	register long dist;

	if (fp == 0 || (flags = fp->_flags) == 0)
		goto errout;
	fp->_flags &= ~(_IOEOF|_IOUNG);
	if (flags & _IODIRTY) {
		if (_flsbuf(fp,-1))
			goto errout;
	} else if (mode != SEEK_END) {
		if ((cleft = fp->_bend - fp->_bp) > 0) {
 			if ((flags & (_IOUNG|_IORW|_IONBF)) == 0) {
				dist = pos;
				if (mode == SEEK_SET)	/* recalculate as SEEK_CUR */
 					dist -= _lseek(fileno(fp), 0L, SEEK_CUR) - cleft;
				if (dist + (fp->_bp - fp->_buff) >= 0 && dist <= cleft) {
					fp->_bp += dist;	/* seek inside buffer */
					goto okout;
				}
			}
			if (mode == SEEK_CUR)
				pos -= cleft;
		}
	}
	fp->_bp = fp->_bend = fp->_buff;
	if (_lseek(fileno(fp), pos, mode) >= 0)
okout:
		return(0);
errout:
	return(EOF);
}

fsetpos.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	int fsetpos(FILE *stream, const fpos_t *pos);
 *
 *
 *	Description
 *
 *		The fsetpos function sets the file position indicator for the stream
 *	pointed to by stream according to the value of the object pointed to by
 *	pos, which shall be a value returned by an earlier call to the fgetpos
 *	function on the same stream.
 *
 *		A successful call to the fsetpos function clears the end-of-file
 *	indicator for the stream and undoes any effects of the ungetc function on
 *	the same stream. After an fsetpos call, the next operation on an update
 *	stream may be either input or output.
 *
 *
 *	Returns
 *
 *		If successful, the fsetpos function returns zero; on failure, the
 *	fsetpos function returns nonzero and stores an implementation-defined
 *	positive value in errno.
 */

#include <stdio.h>
#include <errno.h>

int
fsetpos(FILE *stream, const fpos_t *pos)
{
	if (fseek(stream, (long)*pos, SEEK_SET) != 0) {
		errno = EINVAL;
		return(EOF);
	}
	return(0);
}

ftell.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	long int ftell(FILE *stream);
 *
 *
 *	Description
 *
 *		The ftell function obtains the current value of the file position
 *	indicator for the stream pointed to by stream. For a binary stream, the
 *	value is the number of characters from the beginning of the file. For a
 *	text stream, its file position indicator contains unspecified information,
 *	usable by the fseek function for returning the file position indicator for
 *	the stream to its position at the time of the ftell call; the difference
 *	between two such return values is not necessarily a meaningful measure of
 *	the number of characters written or read.
 *
 *
 *	Returns
 *
 *		If successful, the ftell function returns the current value of the file
 *	position indicator for the stream. On failure, the ftell function returns
 *	-1L and stores an implementation-defined positive value in errno.
 */

#include <stdio.h>
#include <errno.h>

extern long _lseek(int fd, long pos, int whence);

long int
ftell(register FILE *stream)
{
	register long pos;

	if ((pos = _lseek(fileno(stream), 0L, SEEK_CUR)) >= 0) {
		if (stream->_flags & _IODIRTY)
			pos += stream->_bp - stream->_buff;
		else if (stream->_bp)
			pos -= stream->_bend - stream->_bp;
		return(pos);
	}
	errno = EINVAL;
	return(EOF);
}

fwrite.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
 *
 *
 *	Description
 *
 *		The fwrite function writes, from the array pointed to by ptr, up to
 *	nmemb members whose size is specified by size, to the stream pointed to by
 *	stream. The file position indicator for the stream (if defined) is advanced
 *	by the number of characters successfully written. If an error occurs, the
 *	resulting value of the file position indicator for the stream is
 *	indeterminate.
 *
 *
 *	Returns
 *
 *		The fwrite function returns the number of members successfully written,
 *	which will be less than nmemb only if a write error is encountered.
 */

#include <stdio.h>

size_t
fwrite(register const void *ptr, register size_t size, register size_t nmemb,
														register FILE *stream)
{
	register size_t total, i;

	for ( total = 0 ; total < nmemb ; ++total ) {
		for ( i = size ; i ; --i ) {
			if ( putc(*(char *)ptr, stream) == EOF )
				goto eof;
			++((char *)ptr);
		}
	}
eof:
	return(total);
}

getbuf.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	void _getbuf(FILE *stream);
 *
 *
 *	Description
 *
 *		The _getbuf function is an internal function that associates a buffer
 *	with a stream. stderr is always unbuffered and interactive files are always
 *	line buffered.
 *
 *
 *	Returns
 *
 *		The _getbuf function returns no value. If it is not possible to
 *	allocate a buffer of the required size, the stream is marked as unbufferd.
 */

#include <stdio.h>
#include <stdlib.h>

FILE _iob[FOPEN_MAX] = {
	{ 0,0,0, _IOR,0,0,1,0 },
	{ 0,0,0, _IOW,1,0,1,0 },
	{ 0,0,0, _IOW,2,0,1,0 },
};

extern int _isatty(int fildes);

void
_getbuf(register FILE *stream)
{
	register short bufkind;

#ifdef FOOP
	if (stream == stderr)
		goto unbuf;
#endif
	bufkind = _IOFBF|_IOMYBUF;
	if (_isatty(fileno(stream)))
		bufkind = _IOLBF|_IOMYBUF;
	stream->_buflen = BUFSIZ;
	if ((stream->_buff = malloc((size_t)BUFSIZ)) == 0) {
#ifdef FOOP
unbuf:
#endif
		stream->_buflen = 1;
		stream->_buff = &stream->_bytbuf;
		bufkind = _IONBF;
	}
	stream->_flags |= bufkind;
	stream->_bp = stream->_bend = stream->_buff;
}

getchar.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	int getchar(void);
 *
 *
 *	Description
 *
 *		The getchar function is equivalent to getc with the argument stdin.
 *
 *
 *	Returns
 *
 *		The getchar function returns the next character from the input stream
 *	pointed to by stdin. If the stream is at end-of-file, the end-of-file
 *	indicator for the stream is set and getchar returns EOF. If a read error
 *	occurs, the error indicator for the stream is set and getchar returns EOF.
 */

#include <stdio.h>

#undef getchar

int
getchar(void)
{
	return(getc(stdin));
}

gets.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	char *gets(char *s);
 *
 *
 *	Description
 *
 *		The gets function reads characters from the input stream pointed to by
 *	stdin, into the array pointed to by s, until end-of-file is encountered or
 *	a new-line character is read. Any new-line character is discarded, and a
 *	null character is written immediately after the last character read into
 *	the array.
 *
 *
 *	Returns
 *
 *		The gets function returns s if successful. If end-of-file is
 *	encountered and no characters have been read into the array, the contents
 *	of the array remain unchanged and a null pointer is returned. If a read
 *	error occurs during the operation, the array contents are indeterminate and
 *	a null pointer is returned.
 */

#include <stdio.h>

char *
gets(char *s)
{
	register char *cp;
	register int i;

	cp = s;
	while ((i = getchar()) != EOF && i != '\n')
		*cp = i, cp++;
	if (i == EOF && (cp == s || !feof(stdin)))
		return(0);
	*cp = '\0';
	return(s);
}

getw.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	int getw(FILE *stream);
 *
 *
 *	Description
 *
 *		The getw function reads from the input stream pointed to by stream, a
 *	word in an implementation-defined manner. It should be the same as used by
 *	the putw function.
 *
 *
 *	Returns
 *
 *		The getw function returns an int that is the word received. If an error
 *	or end-of-file occurs, EOF is returned. Since EOF is a valid return value,
 *	the ferror and the feof functions must be used to determine if an error
 *	really occurred when EOF is returned.
 */

#include <stdio.h>

getw(register FILE *stream)
{
	register int x1,x2;

	if ((x1 = getc(stream)) == EOF || (x2 = getc(stream)) == EOF)
		return(EOF);
	return((x1<<8) | x2);
}

makefile
CC=qcc
AS=as
CFLAGS=
AFLAGS=
O=oss

.c.$O:
	$(CC) -o $@ $(CFLAGS) $*.c
.a68.$O:
	$(AS) -o $@ $(AFLAGS) $*.a68

CLIB=\
	clearerr.$O fclose.$O fdopen.$O feof.$O ferror.$O \
	fflush.$O fgetc.$O fgetpos.$O fgets.$O filbuf.$O \
	fileopen.$O flsbuf.$O fopen.$O format.$O fprintf.$O \
	fputc.$O fputs.$O fread.$O freopen.$O fscanf.$O \
	fseek.$O fsetpos.$O ftell.$O fwrite.$O getbuf.$O \
	getchar.$O gets.$O perror.$O printf.$O putchar.$O \
	puts.$O remove.$O rename.$O rewind.$O scan.$O \
	scanf.$O setbuf.$O setvbuf.$O sprintf.$O sscanf.$O \
	tmpfile.$O tmpnam.$O ungetc.$O vfprintf.$O vprintf.$O \
	vsprintf.$O putw.$O getw.$O
MLIB=\
	format.$O vsprintf.$O vprintf.$O vfprintf.$O sprintf.$O \
	printf.$O fprintf.$O scan.$O sscanf.$O scanf.$O \
	fscanf.$O

clib:	$(CLIB)

mlib:	$(MLIB)

perror.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	void perror(const char *s);
 *
 *
 *	Description
 *
 *		The perror function maps the error number in the integer expression
 *	errno to an error message. It writes a sequence of characters to the
 *	standard error stream thus: first (if s is not a null pointer and the
 *	character pointed to by s is not the null character), the string pointed to
 *	by s followed by a colon and a space; then an appropriate error message
 *	string followed by a new-line character. The contents of the error message
 *	strings are the same as those returned by the strerror function with
 *	argument errno, which are implementation-defined.
 *
 *
 *	Returns
 *
 *		The perror function returns no value.
 */


#include <stdio.h>
#include <string.h>
#include <errno.h>

void
perror(const char *s)
{
	if (s && *s != '\0') {
		fputs(s, stderr);
		fputs(": ", stderr);
	}
	if ((s = strerror(errno)) && *s) {
		fputs(strerror(errno), stderr);
		fputc('\n', stderr);
	}
}
printf.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	int printf(const char *format, ...);
 *
 *
 *	Description
 *
 *		The printf function is equivalent to fprintf with the argument stdout
 *	interposed before the arguments to printf.
 *
 *		See the _format function for a complete description of the format
 *	string.
 *
 *
 *	Returns
 *
 *		The printf function returns the number of characters transmitted, or a
 *	negative value if an output error occurred.
 *
 *
 *	Environmental limit
 *
 *		The minimum value for the maximum number of characters produced by any
 *	single conversion shall be 509.
 */

#include <stdio.h>
#include <stdarg.h>

int _format(FILE *stream, const char *format, va_list vargs);

int
printf(const char *format, ...)
{
	register va_list vargs;
	register int ret;

	va_start(vargs, format);
	ret = _format(stdout, format, vargs);
	va_end(vargs);
	return(ret);
}

putchar.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	int putchar(int c);
 *
 *
 *	Description
 *
 *		The putchar function is equivalent to putc with the second argument
 *	stdout.
 *
 *
 *	Returns
 *
 *		The putchar function returns the character written. If a write error
 *	occurs, the error indicator for the stream is set and putchar returns EOF.
 */


#include <stdio.h>

#undef putchar

int
putchar(int c)
{
	return( putc(c,stdout));
}

puts.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	int puts(const char *s);
 *
 *
 *	Description
 *
 *		The puts function writes the string pointed to by s to the stream
 *	pointed to by stdout, and appends a new-line character to the output. The
 *	terminating null character is not written.
 *
 *
 *	Returns
 *
 *		The puts function returns EOF if a write error occurs; otherwise it
 *	returns a nonnegative.
 */

#include <stdio.h>

#undef puts

int
puts(register const char *s)
{
	register FILE *fp = stdout;
	register char c;

	for( ; (c = *s); ++s) {
		if (putc(c, fp) == EOF)
			goto err;
	}
	if (putc('\n', fp) != EOF)
		return(0);
err:
	return(EOF);
}

putw.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	int putw(int w, FILE *stream);
 *
 *
 *	Description
 *
 *		The putw function outputs the word w to the stream pointed to by stream
 *	in an implementation defined manner.
 *
 *
 *	Returns
 *
 *		The putw function returns the argument w as its value and EOF if an
 *	error occurs while writing to the output stream. Since EOF is a valid
 *	argument to the putw function, the caller must use the ferror or the feof
 *	function to determine if an error has really occurred when EOF is returned.
 */

#include <stdio.h>

int
putw(register int w, register FILE *stream)
{
	if (putc(w>>8, stream) < 0) 
		return(EOF);
	else if (putc(w, stream) < 0)
		return(EOF);
	return(w);
}

remove.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	int remove(const char *filename);
 *
 *
 *	Description
 *
 *		The remove function causes the file whose name is the string pointed to
 *	by filename to be no longer accessible by that name. A subsequent attempt
 *	to open that file using that name will fail, unless it is created anew. If
 *	the file is open, the behavior of the remove function is implementation-
 *	defined.
 *
 *
 *	Returns
 *
 *		The remove function returns zero if the operation succeeds, nonzero if
 *	it fails.
 */


#include <stdio.h>

int _unlink(const char *filename);

int
remove(const char *filename)
{
	return _unlink(filename);
}

rename.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	int rename(const char *old, const char *new);
 *
 *
 *	Description
 *
 *		The rename function causes the file whose name is the string pointed to
 *	by old to be henceforth known by the name given by the string pointed to by
 *	new. The file named old is effectively removed. If a file named by the
 *	string pointed to by new exists prior to the call to the rename function,
 *	the behavior is implementation-defined.
 *
 *
 *	Returns
 *
 *		The rename function returns zero if the operation succeeds, nonzero if
 *	it fails, in which case if the file existed previously it is still known by
 *	its original name.
 */


#include <stdio.h>

int _rename(const char *old, const char *new);

int
rename(const char *old, const char *new)
{
	return _rename(old, new);
}

rewind.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	void rewind(FILE *stream);
 *
 *
 *	Description
 *
 *		The rewind function sets the file position indicator for the stream
 *	pointed to by stream to the beginning of the file. It is equivalent to
 *
 *			(void)fseek(stream, 0L, SEEK_SET)
 *
 *	except that the error indicator for the stream is also cleared.
 *
 *
 *	Returns
 *
 *		The rewind function returns no value.
 */

#include <stdio.h>

void
rewind(FILE *stream)
{
	clearerr(stream);
	(void)fseek(stream, 0L, SEEK_SET);
}

scan.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	int _scan(FILE *stream, const char *format, va_list varg);
 *
 *
 *	Description
 *
 *		The format shall be a multibyte character sequence, beginning and
 *	ending in its initial shift state. The format is composed of zero or more
 *	directives; one or more white-space characters; an ordinary multibyte
 *	character (not %); or a conversion specification. Each conversion
 *	specification is introduced by the character %. After the %, the following
 *	appear in sequence:
 *
 *	- An optional assignment-suppressing character *.
 *
 *	- An optional decimal integer that specifies the maximum field width.
 *
 *	- An optional h, l (ell) or L indicating the size of the receiving object.
 *		The conversion specifiers d, i, and n shall be preceded by h if the 
 *		corresponging argument is a pointer to short int rather than a pointer
 *		to int, or by l if it is a pointer to long int. Similarly, the
 *		conversion specifiers o, u, and x shall be preceded by h if the
 *		corresponding argument is a pointer to unsigned short int rather than a
 *		pointer to unsigned int, or by l if it is a pointer to unsigned long
 *		int. Finally, the conversion specifiers e, f, and g shall be preceded
 *		by l if the corresponding argument is a pointer to double rather than a
 *		pointer to float, or by L if it is a pointer to long double. If an h,
 *		l, or L appears with any other conversion specifier, the behavior is
 *		undefined.
 *
 *	- A character that specifies the type of conversion to be applied. The
 *		valid conversion specifiers are described below.
 *
 *		The _scan function executes each directive of the format in turn. If a
 *	directive fails, as detailed below, the _scan function returns. Failures
 *	are described as input failures (due to the unavailability or input
 *	characters), or matching failures (due to inappropriate input).
 *
 *		A directive composed of white space is executed by reading input up to
 *	the first non-white space character (which remains unread), or until no
 *	more characters can be read.
 *
 *		A directive that is an ordinary multibyte character is executed by
 *	reading the next characters of the stream. If one of the characters differs
 *	from one comprising the directive, the directive fails, and the differing
 *	and subsequent characters remain unread.
 *
 *		A directive that is a conversion specification defines a set of
 *	matching input sequences, as described below for each specifier. A
 *	conversion specification is executed in the following steps:
 *
 *		Input white-space characters (as specified by the isspace function) are
 *	skipped, unless the specification includes a [, c, or n specifier.
 *
 *		An input item is read from the stream, unless the specification
 *	includes an n specifier. An input item is defined as the longest sequence
 *	of input characters (up to any specified maximum field width) which is an
 *	initial subsequence of a matching sequence. The first character, if any,
 *	after the input item remains unread. If the length of the input item is
 *	zero, the execution of the directive fails: this condition is a matching
 *	failure, unless an error prevented input from the stream, in which case it
 *	is an input failure.
 *
 *		Except in the case of a % specifier, the input item (or, inthe case of
 *	a %n directive, the count of input characters) is converted to a type
 *	appropriate to the conversion specifier. If the input item is not a
 *	matching sequence, the executeion of the directive fails: this condition is
 *	a matching failure. Unless assignment suppression was indicated by a *, the
 *	result of the conversion is placed in the object pointed to by the first
 *	argument following the format argument that has not already received a
 *	conversion result. If this object does not have an appropriate type, or if
 *	the result of the conversion cannot be represented in the space provided,
 *	the behavior is undefined.
 *
 *		The following conversion specifiers are valid:
 *
 *	d	Matches an optionally signed decimal integer, whose format is the same
 *		as expected for the subject sequence of the strtol function with the
 *		value 10 for the base argument. The corresponding argument shall be a
 *		pointer to integer.
 *
 *	i	Matches an optionally signed integer, whose format is the same as
 *		expected for the subject sequence fo the strtol function with the value
 *		0 for the base argument. The corresponding argument shall be a pointer
 *		to integer.
 *
 *	o	Matches an optionally signed octal integer, whose format is the same
 *		as expected for the subject sequence of the strtol function with the
 *		value 8 for the base argument. The corresponding argument shall be a
 *		pointer to unsigned integer.
 *
 *	u	Matches an optionally signed decimal integer, whose format is the same
 *		as expected for the subject sequence of the strtol function with the
 *		value 10 for the base argument. The corresponding argument shall be a
 *		pointer to unsigned integer.
 *
 *	x	Matches an optionally signed hexadecimal integer, whose format is the
 *		same as expected for the subject sequence of the strtol function with
 *		the value 10 for the base argument. The corresponding argument shall be
 *		a pointer to unsigned integer.
 *
 *	e,	Matches an optionally signed floating-point number, whose format is the
 *	f,	same as expected for the subject string of the strtod function. The
 *	g	corresponding argument shall be a pointer to floating.
 *
 *	s	Matches a sequence of non-white-space characters. The corresponding
 *		argument shall be a pointer to the initial character of an array large
 *		enough to accept the sequence and a terminating null character, which
 *		will be added automatically.
 *
 *	[	Matches a nonempty sequence of characters from a set of expected
 *		characters (the scanset). The corresponding argument shall be a pointer
 *		to the initial character of an array large enough to accept the
 *		sequence and a terminating null character, which will be added
 *		automatically. The conversion specifier includes all subsequent
 *		characters in the format string, up to and including the matching right
 *		bracket (]). The characters between the brackets (the scanlist)
 *		comprise the scanset, unless the character after the left bracket is a
 *		circumflex (^), in which case the scanset contains all characters that
 *		do not appear in the scanlist between the circumflex and the right
 *		bracket. As a special case, if the conversion specifier begins with []
 *		or [^], the right bracket character is in the scanlist and the NEXT
 *		right bracket character is the matching right bracket that ends the
 *		specification. If a - character is in the scanlist and is not the
 *		first, nor the second where the first character is a ^, nor the last
 *		character, the behavior is implementation-defined.
 *
 *	c	Matches a sequence of characters of the number specified by the field
 *		width (1 if no field width is present in the directive). The
 *		corresponding argument shall be a pointer to the initial character of
 *		an array large enough to accept the sequence. No null character is
 *		added.
 *
 *	p	Matches an implementation-defined set of sequences, which should be the
 *		same as the set of sequences that may be produced by the %p conversion
 *		of the _format function. The corresponding argument shall be a pointer
 *		to a pointer to void. The interpretation of the input item is 
 *		implementation-defined; however, for any input item other than a value
 *		converted earlier during the same program execution, the behavior of
 *		the %p conversion is undefined.
 *
 *	n	No input is consumed. The corresponding argument shall be a pointer to
 *		integer into which is written the number of characters read from the
 *		input stream so far by this call to the _scan function. Execution of a
 *		%n directive does not increment the assignment count returned at the
 *		completion of the _scan function.
 *
 *	%	Matches a single %; no conversion or assignment occurs. The complete
 *		conversion specification shall be %%.
 *
 *		If a conversion specification is invalid, the behavior is undefined.
 *
 *		The conversion specifiers, E, G, and X are also valid and behave the
 *	same as, respectively, e, g, and x.
 *
 *		If end-of-file is encountered during input, conversion is terminated.
 *	If end-of-file occurs before any characters matching the current directive
 *	have been read (other than leading white space, where permitted), execution
 *	of the current directive terminates with an input failure; otherwise,
 *	unless execution of the current directive is terminated with a matching
 *	failure, execution of the following directive (if any) is terminated with
 *	an input failure.
 *
 *		If conversion terminates on a conflicting input character, the
 *	offending input character is left unread in the input stream. Trailing
 *	white space (including new-line characters) is left unread unless matched
 *	by a directive. The success of literal matches and suppressed assignments
 *	is not directly determinable other than via the %n directive.
 *
 *
 *	Returns
 *
 *		The _scan function returns the value of the macro EOF if an input
 *	failure occurs before any conversion. Otherwise, the _scan function returns
 *	the number of input items assigned, which can be fewer than provided for,
 *	or even zero, in the event of an early matching failure.
 */

#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <ctype.h>
#include <string.h>

#define GETCH(stream)	(chcnt++,getc(stream))
#define UNGETCH(c,stream) (chcnt--,ungetc(c,stream))

#ifdef FLOAT
static long double dpower(int n);
static long double strtold(const char *str, char **ep);
#endif

int
_scan(FILE *stream, register char *fmt, register va_list varg)
{
	long lv;
	register int c, chcnt, count, base, cc;
	char suppress, lflag, widflg, pushback;
	int maxwidth;
	int savchcnt, off;
#ifdef FLOAT
	char decpt, exp;
#endif
	char sign;
	char *cp;
	auto char tlist[130];
	static char list[] = "ABCDEFabcdef9876543210";
	static char vals[] = {
			10,11,12,13,14,15,10,11,12,13,14,15,9,8,7,6,5,4,3,2,1,0
	};

	chcnt = count = 0;
	while (c = *fmt++) {
		if (c == '%') {
			widflg = lflag = suppress = 0;
			maxwidth = 127;
			if (*fmt == '*') {
				++fmt;
				suppress = 1;
			}
			if (isdigit(c=*fmt)) {
				maxwidth = 0;
				do {
					maxwidth = maxwidth*10 + c - '0';
				} while (isdigit(c=*++fmt));
				widflg = 1;
			}
			if (c == 'l' || c == 'h' || c == 'L') {
				lflag = c;
				++fmt;
			}
	
			switch (cc = *fmt++) {
			case '%':
				c = '%';
				goto matchit;

			case 'd':
			case 'u':
				base = 10;
				goto getval;

			case 'i':
				base = 0;
				goto getval;

			case 'o':
				base = 8;
				goto getval;

			case 'p':
				lflag = 'l';
			case 'X':
			case 'x':
				base = 16;
				goto getval;

getval:
				while (isspace(pushback=GETCH(stream)))
					;
				if (UNGETCH((int)pushback, stream) == EOF)
					goto stopscan;
				if (maxwidth <= 0)
					goto stopscan;
				savchcnt = chcnt;
				lv = sign = 0;
				if ((c = GETCH(stream)) == '-' || c == '+') {
					if (c == '-')
						sign = 1;
					c = GETCH(stream);
				}
				if (chcnt-savchcnt+1 < maxwidth &&
									(base == 16 || base == 0) && c == '0') {
					if (tolower(c = GETCH(stream)) == 'x') {
						c = GETCH(stream);		/* get next for ungetting */
						if (base == 0)
							base = 16;
					}
					else
						base = 8;
				}
				if (base == 0)
					base = 10;
				UNGETCH(c, stream);

				off = 0;
				if (base == 10)
					off = 12;
				if (base == 8)
					off = 14;

				for ( ; chcnt-savchcnt < maxwidth ; ) {
					if ((cp = strchr(list+off, c = GETCH(stream))) == 0) {
						UNGETCH(c, stream);
						break;
					}
					lv *= base;
					lv += vals[cp-list];
				}
				if (sign)
					lv = -lv;
putval:
				if (!suppress) {
					if (lflag == 'h')
						*va_arg(varg, short *) = lv;
					else if (lflag == 'l')
						*va_arg(varg, long *) = lv;
					else
						*va_arg(varg, int *) = lv;
					++count;
				}
				break;

			case 'n':
				lv = chcnt;
				count--;
				goto putval;

#ifdef FLOAT
			case 'E':
			case 'e':
			case 'f':
			case 'g':
			case 'G':
				while (isspace(pushback=GETCH(stream)))
					;
				if (UNGETCH((int)pushback, stream) == EOF)
					goto stopscan;

				sign = exp = decpt = 0;

				for (cp = tlist ; maxwidth-- ; *cp++ = c) {
					c = GETCH(stream);
					if (!isdigit(c)) {
						if (!decpt && c == '.')
							decpt = 1;
						else if (!exp && (c == 'e' || c == 'E') &&
																cp != tlist) {
							sign = 0;
							exp = decpt = 1;
							continue;
						} else if (sign || (c != '-' && c != '+')) {
							UNGETCH(c, stream);
							break;
						}
					}
					sign = 1;
				}
				*cp = 0;
				if (cp == tlist)
					goto stopscan;

				if (!suppress) {
					if (lflag == 'l')
						*va_arg(varg, double *) = strtold(tlist, (char *)0);
					else if (lflag == 'L')
						*va_arg(varg, long double *) =
												strtold(tlist, (char *)0);
					else
						*va_arg(varg, float *) = strtold(tlist, (char *)0);
					++count;
				}
				break;
#endif
			case 's':
				while (isspace(pushback=GETCH(stream)))
					;
				if (UNGETCH((int)pushback, stream) == EOF)
					goto stopscan;
				lflag = 2;
				goto charstring;
			case 'c':
				if (!widflg)
					maxwidth = 1;
				lflag = 3;
				goto charstring;
			case '[':
				lflag = 0;
				if (*fmt == '^') {
					++fmt;
					lflag = 1;
				}
				cp = tlist;
				if (*fmt == ']')
					*cp++ = *fmt++;
				while ((c = *fmt++) && c != ']')
					*cp++ = c;
				*cp = 0;
charstring:
				if (!suppress)
					cp = va_arg(varg, char *);
				widflg = 0;
				while (maxwidth--) {
					if ((c = GETCH(stream)) == EOF)
						break;
					if (lflag == 2) {
						if (isspace(c)) {
							UNGETCH(c, stream);
							break;
						}
					}
					else if (lflag < 2 && lflag == (strchr(tlist, c) != 0)) {
						UNGETCH(c, stream);
						break;
					}
					if (!suppress)
						*cp++ = c;
					widflg = 1;
				}
				if (!widflg)
					goto stopscan;
				if (!suppress) {
					if (cc != 'c')
						*cp = 0;
					++count;
				}
				break;

			}
		} else if (isspace(c)) {
			while (isspace(pushback=GETCH(stream)))
				;
			if (UNGETCH((int)pushback, stream) == EOF)
				goto stopscan;
		} else {
matchit:
			if ((pushback=GETCH(stream)) != c) {
				UNGETCH((int)pushback, stream);
				goto stopscan;
			}
		}
	}

stopscan:
	if (count == 0) {
		if ((pushback=GETCH(stream)) == EOF)
			return(EOF);
		UNGETCH((int)pushback, stream);
	}
	return count;
}

#ifdef FLOAT
static long double
strtold(register const char *str, register char **ep)
{
	register long double val, oldval;
	register const char *bp, *x, *op;
	int exp, oexp;
	char mflg = 0;

	for (bp=str;isspace(*bp);bp++)			/* scan past leading spaces */
		;
	if (*bp == '\0') {						/* return(0) if unable */
empty:
		if (ep != 0)
			*ep = (char *)str;
		return(0.0);
	}
	
	switch (*bp) {							/* may be preceded by '+' or '-' */
		case '-':
			mflg = 1;
			/* fall through */
		case '+':
			bp++;
			break;
		default:
			if (!isdigit(*bp) && *bp != '.')
				goto empty;
	}

	val = 0;
	for (x=bp;isdigit(*x);x++)				/* scan to end of first part */
		;
	op = x;
	val = 0;	
	for (x--;x>=bp;x--) {					/* calculate left of dec. pt. */
		oldval = val;
		val += (*x-'0') * dpower((int)(op-x-1));
		if (val < oldval) {					/*check for overflow*/
error:
			errno = ERANGE;
			if (mflg)
				return(-HUGE_VAL);
			return(HUGE_VAL);
		}
	}
	if (*op == '.') {
		for (x=op+1;isdigit(*x);x++)		/*calculate right of dec. pt.*/
			val += (*x-'0')/dpower((int)(x-op));
		op = x;
	}
	else
		x = op;
	if (*x == 'e' || *x == 'E') {			/* scientific notation? */
		if (*(x+1) == '-' || *(x+1) == '+')
			x++;
		if (isdigit(*(op=x+1))) {
			exp = 0;
			while (isdigit(*op)) {
				oexp = exp;
				exp = exp*10+*op-'0';
				if (exp < oexp) {
					if (*x == '-') {
						val = 0;
						exp = 0;
						errno = ERANGE;
						break;
					}
					else
						goto error;
				}
				op++;
			}
			if (*x == '-') {
				oldval = val;
				val /= dpower(exp);
				if ((oldval != 0.0)&&(val == 0.0)) /*underflow?*/
					errno = ERANGE;
			}
			else {
				oldval = val;
				val *= dpower(exp);
				if (val < oldval)		/*overflow?*/
					goto error;
			}
		}
	}
	if (ep != NULL)
		*ep = (char *)op;
	if (mflg)
		val = -val;
	return(val);
}

static long double
dpower(int n) 
{
	long double p;
	int i;
	p = 1;
	for (i=1; i<=n; ++i)
		p *=10.0;
	return(p); /* 10 to the nth power */
}
#endif

scanf.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	int scanf(const char *format, ...);
 *
 *
 *	Description
 *
 *		The scanf function is equivalent to fscanf with the argument stdin
 *	interposed before the arguments to scanf.
 *
 *		See the _scan function for a complete description of the format
 *	string.
 *
 *
 *	Returns
 *
 *		The scanf function returns the value of the macro EOF if an input
 *	failure occurs before any conversion. Otherwise, the fscanf function
 *	returns the number of input items assigned, which can be fewer than
 *	provided for, or even zero, in the event of an early matching failure.
 */

#include <stdio.h>
#include <stdarg.h>

extern int _scan(FILE *stream, const char *format, va_list vargs);

int
scanf(const char *format, ...)
{
	register va_list vargs;
	register int ret;

	va_start(vargs, format);
	ret = _scan(stdin, format, vargs);
	va_end(vargs);
	return(ret);
}

setbuf.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	void setbuf(FILE *stream, char *buf);
 *
 *
 *	Description
 *
 *		Except that it returns no value, the setbuf function is equivalent to
 *	the setvbuf function invoked with the values _IOFBF for mode and BUFSIZ for
 *	size, or (if buf is a null pointer), with the value _IONBF for mode.
 *
 *
 *	Returns
 *
 *		The setbuf function returns no value.
 */

#include <stdio.h>

void
setbuf(FILE *stream, char *buf)
{
	(void)setvbuf(stream, buf, buf==0 ? _IONBF : _IOFBF, (size_t)BUFSIZ);
}

setvbuf.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	int setvbuf(FILE *stream, char *buf, int mode, size_t size);
 *
 *
 *	Description
 *
 *		The setvbuf function may be used after the stream pointed to by stream
 *	has been associated with an open file but before any other operation is
 *	performed on the stream. The argument mode determines how stream will be
 *	buffered, as follows: _IOFBF causes input/output to be fully buffered;
 *	_IOLBF causes input/output to be line buffered; _IONBF causes input/output
 *	to be unbuffered. If buf is not a null pointer, the array it points to may
 *	be used instead of a buffer allocated by the setvbuf function. The argument
 *	size specifies the size of the array. The contents of the array at any time
 *	are indeterminate.
 *
 *
 *	Returns
 *
 *		The setvbuf function returns zero on success, or nonzero if an invalid
 *	value is given for mode or if the request cannot be honored.
 */

#include <stdio.h>
#include <stdlib.h>

int
setvbuf(register FILE *stream, register char *buf, int mode, size_t size)
{
	if (stream == 0 || stream->_flags == 0 || size == -1)
		return(EOF);
	if (stream->_flags & _IOMYBUF) {
		fflush(stream);
		free(stream->_buff);
	}
	stream->_bp = stream->_bend = stream->_buff = 0;
	stream->_flags &= ~(_IOMYBUF|_IOFBF|_IOLBF|_IONBF);
	switch(mode) {
	case _IOFBF:		/* fully buffered */
	case _IOLBF:		/* line buffered */
		if (buf == 0) {
			if ((buf = malloc(size)) == 0)
				return(EOF);
			stream->_flags |= _IOMYBUF;
		}
		stream->_buff = (unsigned char *)buf;
		stream->_buflen = size;
		break;
	case _IONBF:		/* completely unbuffered */
		stream->_buff = &stream->_bytbuf;
		stream->_buflen = 1;
		break;
	default:
		return(EOF);
	}
	stream->_flags |= mode;
	stream->_bp = stream->_bend = stream->_buff;
	return(0);
}

sprintf.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	int sprintf(chra *s, const char *format, ...);
 *
 *
 *	Description
 *
 *		The sprintf function is equivalent to fprintf, except that the argument
 *	s specifies an array into which the generated output is to be written,
 *	rather than to a stream. A null character is written at the end of the
 *	characters written; it is not counted as part of the returned sum. If
 *	copying takes place between objects that overlap, the behavior is
 *	undefined.
 *
 *		See the _format function for a complete description of the format
 *	string.
 *
 *
 *	Returns
 *
 *		The sprintf function returns the number of characters written in the
 *	array, not counting the terminating null character.
 *
 *
 *	Environmental limit
 *
 *		The minimum value for the maximum number of characters produced by any
 *	single conversion shall be 509.
 */

#include <stdio.h>
#include <stdarg.h>

int _format(FILE *stream, const char *format, va_list vargs);

int
sprintf(register char *s, const char *format, ...)
{
	register va_list vargs;
	FILE iob;
	register int ret;

	va_start(vargs, format);
	iob._flags = _IOW | _IOSTRNG | _IODIRTY;
	iob._buff = iob._bp = (unsigned char *)s;
	iob._bend = (unsigned char *)s + 32767;
	ret = _format(&iob, format, vargs);
	s[ret] = 0;
	va_end(vargs);
	return(ret);
}

sscanf.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	int sscanf(const char *s, const char *format, ...);
 *
 *
 *	Description
 *
 *		The sscanf function is equivalent to fscanf, except that the argument s
 *	specifies a string from which the input is to be obtained, rather than from
 *	a stream. Reaching the end of the string is equivalent to encountering
 *	end-of-file for the fscanf function. If copying takes place between objects
 *	that overlap, the behavior is undefined.
 *
 *		See the _scan function for a complete description of the format
 *	string.
 *
 *
 *	Returns
 *
 *		The sscanf function returns the value of the macro EOF if an input
 *	failure occurs before any conversion. Otherwise, the sscanf function
 *	returns the number of input items assigned, which can be fewer than
 *	provided for, or even zero, in the event of an early matching failure.
 */

#include <stdio.h>
#include <stdarg.h>
#include <string.h>

extern int _scan(FILE *stream, const char *format, va_list vargs);

int
sscanf(register const char *s, const char *format, ...)
{
	register va_list vargs;
	FILE iob;
	register int ret;

	va_start(vargs, format);
	iob._flags = _IOR | _IOSTRNG | _IOMYBUF;
	iob._buff = iob._bp = (unsigned char *)s;
	iob._bend = (unsigned char *)s + strlen(s);
	ret = _scan(&iob, format, vargs);
	va_end(vargs);
	return(ret);
}

tmpfile.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	FILE *tmpfile(void);
 *
 *
 *	Description
 *
 *		The tmpfile function creates a temporary binary file that will
 *	automatically be removed when it is closed or at program termination. If
 *	the program terminates abnormally, whether an open temporary file is
 *	removed is implementation-defined. The file is opened for update with "wb+"
 *	mode.
 *
 *
 *	Returns
 *
 *		The tmpfile function returns a pointer to the stream of the file that
 *	it created. If the file cannot be created, the tmpfile function returns a
 *	null pointer.
 */


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

FILE *
tmpfile(void)
{
	register FILE *fp;
	register unsigned short val;
	register unsigned short nxttmp = 1;
	register int i;
	char tmpbuf[9];

	strcpy(tmpbuf, "TMP");
	do {
		val = nxttmp++;
		for (i=0;i<5;i++) {
			tmpbuf[3+4-i] = '0' + val % 10;
			val /= 10;
		}
		tmpbuf[8] = 0;
	} while ((fp = fopen(tmpbuf, "wb+")) == NULL && nxttmp);
	if (fp)
		fp->_tmpnum = nxttmp - 1;
	return(fp);
}

tmpnam.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	char *tmpnam(char *s);
 *
 *
 *	Description
 *
 *		The tmpnam function generates a string that is a valid file name and
 *	is not the same as the name of an existing file.
 *
 *		The tmpnam function generates a different string each time it is
 *	called, up to TMP_MAX times. If it is called more than TMP_MAX times, the
 *	behavior is implementation-defined.
 *
 *		The implementation shall behave as if no library function calls the
 *	tmpnam funciton.
 *
 *
 *	Returns
 *
 *		If the argument is a null pointer, the tmpnam function leaves its
 *	result in an internal static object and returns a pointer to that object.
 *	Subsequent calls to the tmpnam function may modify the same object. If the
 *	argument is not a null pointer, it is assumed to point to an array of at
 *	least L_tmpnam chars; the tmpnam function writes its result in that array
 *	and returns the argument as its value.
 *
 *
 *	Environmental Limits
 *
 *		The value of the macro TMP_MAX shall be at least 25.
 */


#include <stdio.h>
#include <string.h>
#include <errno.h>

extern int _access(char *name, int mode);

char *
tmpnam(register char *s)
{
	register unsigned short val;
	register int i;
	register FILE *fp;
	static char tmpbuf[L_tmpnam];
	static unsigned short nxttmp;

	if (s == NULL)
		s = tmpbuf;
	strcpy(s, "TMP");
	for (;;) {
		val = nxttmp++;
		for (i=0;i<5;i++) {
			s[3+4-i] = '0' + val % 10;
			val /= 10;
		}
		s[8] = 0;
		if ((fp=fopen(s, "r")) == NULL) {
			if ((fp=fopen(s, "w")) != NULL) {
				fclose(fp);
				remove(s);
				break;
			}
		}
		else
			fclose(fp);
	}
	return(s);
}

ungetc.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	int ungetc(int c, FILE *stream);
 *
 *
 *	Description
 *
 *		The ungetc function pushes the character specified by c (converted to
 *	an unsigned char) back onto the input stream pointed to by stream. The
 *	pushed-back characters will be returned by subsequent reads on that stream
 *	in the reverse order of their pushing. A successful intervening call (with
 *	the stream pointed to by stream) to a file positioning function (fseek,
 *	fsetpos, or rewind) discards any pushed-back characters for the stream. The
 *	external storage corresponding to the stream is unchanged.
 *
 *		One character of pushback is guaranteed. If the ungetc function is
 *	called too many times on the same stream without an intervening read or
 *	file positioning operation on that stream, the operation may fail.
 *
 *		If the value of c equals that of the macro EOF, the operation fails and
 *	the input stream is unchanged.
 *
 *		A successful call to the ungetc function clears the end-of-file
 *	indicator for the stream. The value of the file position indicator for the
 *	stream after reading or discarding all pushed-back characters shall be the
 *	same as it was before the characters were pushed back. For a text stream,
 *	the value of its file position indicator after a successful call to the
 *	ungetc function is unspecified until all pushed-back characters are read or
 *	discarded. For a binary stream, its file position indicator is decremented
 *	by each successful call to the ungetc function; if its value was zero
 *	before a call, it is indeterminate after the call.
 *
 *
 *	Returns
 *
 *		The ungetc function returns the character pushed back after conversion,
 *	or EOF if the operation fails.
 */

#include <stdio.h>

extern void _getbuf(FILE *stream);

int
ungetc(int c, register FILE *stream)
{
	if (c == EOF || stream == 0 || (stream->_flags) == 0 ||
													(stream->_flags & _IOW))
errout:
		return(EOF);
	if (stream->_buff == 0)
		_getbuf(stream);
	if (stream->_bp == stream->_buff) {		/* at begin of buffer */
		if (stream->_bend > stream->_buff)	/* no place to go */
			goto errout;
		stream->_bp++;
		stream->_bend = stream->_bp;
	}

	stream->_flags &= ~_IOEOF;
	stream->_flags |= _IOUNG;
	return(*--stream->_bp = c);
}

vfprintf.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	int vfprintf(FILE *stream, const char *format, va_list arg);
 *
 *
 *	Description
 *
 *		The vfprintf function is equivalent to fprintf, with the variable
 *	argument list replaced by arg, which has been initialized by the va_start
 *	macro (and possibly subsequent va_arg calls). The vfprintf function does
 *	not invoke the va_end macro.
 *
 *		See the _format function for a complete description of the format
 *	string.
 *
 *
 *	Returns
 *
 *		The vfprintf function returns the number of characters transmitted, or
 *	a negative value if an output error occurred.
 *
 *
 *	Environmental limit
 *
 *		The minimum value for the maximum number of characters produced by any
 *	single conversion shall be 509.
 */

#include <stdio.h>
#include <stdarg.h>

extern int _format(FILE *stream, const char *format, va_list vargs);

int
vfprintf(FILE *stream, const char *format, va_list vargs)
{
	return(_format(stream, format, vargs));
}

vprintf.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	int vprintf(char *format, va_list arg);
 *
 *
 *	Description
 *
 *		The vprintf function is equivalent to printf, with the variable
 *	argument list replaced by arg, which has been initialized by the va_start
 *	macro (and possibly subsequent va_arg calls). The vprintf function does
 *	not invoke the va_end macro.
 *
 *		See the _format function for a complete description of the format
 *	string.
 *
 *
 *	Returns
 *
 *		The vprintf function returns the number of characters transmitted, or
 *	a negative value if an output error occurred.
 *
 *
 *	Environmental limit
 *
 *		The minimum value for the maximum number of characters produced by any
 *	single conversion shall be 509.
 */

#include <stdio.h>
#include <stdarg.h>

extern int _format(FILE *stream, const char *format, va_list vargs);

int
vprintf(const char *format, va_list vargs)
{
	return(_format(stdout, format, vargs));
}

vsprintf.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	Synopsis
 *
 *	int vsprintf(char *s, char *format, va_list arg);
 *
 *
 *	Description
 *
 *		The vsprintf function is equivalent to sprintf, with the variable
 *	argument list replaced by arg, which has been initialized by the va_start
 *	macro (and possibly subsequent va_arg calls). The vsprintf function does
 *	not invoke the va_end macro. If copying takes place between objects that
 *	overlap, the behavior is undefined.
 *
 *		See the _format function for a complete description of the format
 *	string.
 *
 *
 *	Returns
 *
 *		The vsprintf function returns the number of characters transmitted, or
 *	a negative value if an output error occurred.
 *
 *
 *	Environmental limit
 *
 *		The minimum value for the maximum number of characters produced by any
 *	single conversion shall be 509.
 */

#include <stdio.h>
#include <stdarg.h>

extern int _format(FILE *stream, const char *format, va_list vargs);

int
vsprintf(char *s, const char *format, va_list vargs)
{
	FILE iob;
	register int ret;

	iob._flags = _IOW | _IOSTRNG;
	iob._buff = iob._bp = (unsigned char *)s;
	iob._bend = (unsigned char *)s + 32767;
	ret = _format(&iob, format, vargs);
	s[ret] = 0;
	return(ret);
}

