[comp.os.minix] Stdio V2 - Part 5 of 6

cechew@bruce.OZ (Earl Chew) (09/29/89)

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 5 (of 6)."
# Contents:  config.h stdiolib.h vfprintf.c
# Wrapped by cechew@bruce on Fri Sep 29 16:23:40 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'config.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'config.h'\"
else
echo shar: Extracting \"'config.h'\" \(6632 characters\)
sed "s/^X//" >'config.h' <<'END_OF_FILE'
X/*			c o n f i g
X *
X * (C) Copyright C E Chew
X *
X * Feel free to copy, use and distribute this software provided:
X *
X *	1. you do not pretend that you wrote it
X *	2. you leave this copyright notice intact.
X *
X * This file describes the environment under which stdio
X * is to be compiled.
X *
X * Patchlevel 2.0
X *
X * Edit History:
X */
X
X/*
X * The macros that are defined in this file are:
X *
X * _BSD
X *	Select BSD environment.
X * _MINIX
X *	Selects Minix environment.
X * MANUAL
X *	Select code control manually, otherwise it will
X *	be selected `automatically' based on __STDC__
X *	and operating system selection (defaults to _MINIX
X *	if no system selected).
X *
X * Code control:
X *
X * PROTOTYPE
X *	Function prototype inclusion.
X * MEMORY
X *	Use memory.h. If this is not defined, users must provide
X *	definitions for MEMCPY, MEMSET and MEMCHR.
X * MYMEMCPY
X *	Use stdio code for memcpy.
X * MYMEMCHR
X *	Use stdio code for memchr.
X * MYMEMSET
X *	Use stdio code for memset.
X * STDARG
X *	Use stdarg.h instead or varargs.h.
X * LIMITS
X *	Use limits.h.
X * STRING
X *	Use string.h.
X * MEMSTR
X *	Use memchr to do fast strlen.
X * OPEN3
X *	Use open(2) for three argument opens.
X * RENAME
X *	Use rename(2).
X * SYSTYPES
X *	Use sys/types.h.
X * TIME
X *	Use time.h.
X * UNSIGNEDCHAR
X *	Use (int) ((unsigned char) (x)) for unsigned casts instead
X *	of (x) & ((1 << CHAR_BIT) - 1).
X *
X * Stdio performance control:
X *
X * FREADTHRESHOLD
X * FWRITETHRESHOLD
X *	Threshold beyond which fwrite or fread will use memcpy() to
X *	do the transfer instead of PUTC().
X * MEMSET(s,v,n)
X *	Set a piece of memory to the specified value.
X * MEMCPY(d,s,n)
X *	Copy a piece of memory of length n from s to d. No return
X *	value expected.
X * MEMCHR(s,c,n)
X *	Look in a piece of memory s of length n for character c. Return
X *	a pointer to the c if found, otherwise null.
X * TOLOWER(c)
X *	Convert uppercase to lowercase.
X */
X
X/****************************************************************
X *			System Configuration			*
X ***************************************************************/
X
X#ifndef		SOURCE
X
X/*define _BSD*/				/* BSD system */
X/*define _MINIX*/			/* Minix system */
X
X/*define MANUAL*/			/* manual code control */
X
X# define FWRITETHRESHOLD	10	/* fwrite memcpy call threshold */
X# define FREADTHRESHOLD		10	/* fread memcpy call threshold */
X
X/****************************************************************
X *			Manual Selection			*
X ****************************************************************/
X# ifdef		MANUAL
X# include "site.h"
X/* define PROTOTYPE*/			/* use function prototypes */
X/* define UNSIGNEDCHAR*/		/* use (unsigned char) cast */
X/* define MEMORY*/			/* use memory.h */
X/* define STDARG*/			/* use stdarg.h */
X/* define LIMITS*/			/* use limits.h */
X/* define STRING*/			/* use string.h */
X/* define MEMSTR*/			/* use memory for string */
X/* define SYSTYPES*/			/* use sys/types.h */
X/* define TIME*/			/* use time.h */
X/* define TOLOWER tolower*/		/* use tolower */
X/* define OPEN3*/			/* use 3 argument opens */
X
X/****************************************************************
X *			Automatic Selection			*
X ****************************************************************/
X# else
X#   ifndef	_BSD
X#     ifndef	_MINIX
X#       define	_MINIX
X#     endif
X#  endif
X#  ifdef	__STDC__
X#    define PROTOTYPE			/* use function prototypes */
X#    define UNSIGNEDCHAR		/* use (unsigned char) cast */
X#  endif
X#  define MEMORY			/* use memory.h */
X#  undef  MYMEMCPY			/* don't use local memcpy */
X#  undef  MYMEMCHR			/* don't use local memchr */
X#  undef  MYMEMSET			/* don't use local memset */
X#  define STDARG			/* use stdarg.h */
X#  define LIMITS			/* use limits.h */
X#  define STRING			/* use string.h */
X#  define MEMSTR			/* use memory for string */
X#  define SYSTYPES			/* use sys/types.h */
X#  define TIME				/* use time.h */
X#  define TOLOWER tolower		/* use tolower */
X#  ifdef	O_CREAT
X#    ifdef	O_TRUNC
X#      ifdef	O_APPEND
X#        define OPEN3			/* use three argument opens */
X#      endif
X#    endif
X#  endif
X# endif
X
X/****************************************************************
X *		Hacks for Non Posix/ANSI Environments		*
X ****************************************************************/
X
X# ifdef		PROTOTYPE
X#   define	P(x)		x
X# else
X#   define	P(x)		()
X# endif
X
X# ifdef		_MINIX
X    extern int tolower P((int));
X
X#   undef TIME
X    typedef long time_t;
X
X#   undef SYSTYPES
X    typedef long off_t;
X    typedef int pid_t;
X    typedef int uid_t;
X    typedef int mode_t;
X#   define _SIZE_T
X    typedef unsigned int size_t;
X# endif
X
X# ifdef		_BSD
X#   undef MEMORY			/* don't use memory.h */
X    extern void bcopy();
X#   define MEMCPY(d,s,n) bcopy((s),(d),(n))
X#   undef  MYMEMCPY
X#   define MYMEMCHR
X#   define MYMEMSET
X
X#   undef STDARG			/* don't use stdarg.h */
X
X#   undef LIMITS			/* don't use limits.h */
X#   include <values.h>
X#   define INT_MAX	(MAXINT)
X#   define USHRT_MAX	((unsigned short) MAXSHORT)
X#   define CHAR_BIT	(BITSPERBYTE)
X
X#   undef STRING			/* don't use string.h */
X#   include <strings.h>
X#   undef MEMSTR			/* don't use memory for string */
X
X#   define SYSTYPES			/* use sys/types.h */
X    typedef int pid_t;
X    typedef int mode_t;
X#   define _SIZE_T			/* already defined in sys/types.h */
X
X#   undef TIME				/* don't use time.h */
X
X#   define RENAME			/* use rename(2) */
X
X#   undef TOLOWER			/* don't use tolower */
X#   define TOLOWER(c)	(isupper((c)) ? tolower((c)) : (c))
X# endif
X
X/****************************************************************
X *			System Support Code			*
X ****************************************************************/
X
X# ifdef		MYMEMCPY
X    char *memcpy P((void *, void *, size_t));
X#   define MEMCPY(s,c,n) memcpy((s),(c),(n))
X# endif
X# ifdef		MYMEMCHR
X    char *memchr P((void *, int, size_t));
X#   define MEMCHR(s,c,n) memchr((s),(c),(n))
X# endif
X# ifdef		MYMEMSET
X    void memset P((void *, int, size_t));
X#   define MEMSET(d,c,n) memset((d),(c),(n))
X# endif
X
X# undef P
X#endif
X
X#ifdef		SOURCE
X# ifdef		MYMEMCPY
Xchar *memcpy(T(void *d, d), T(void *s, s), T(size_t n, n))
X
XD(void *d)
XD(void *s)
XD(size_t n)
X
X{
X  char *p = (char *) d;
X  char *q = (char *) s;
X
X  if (n != 0)
X    do
X      *p++ = *q++;
X    while (--n);
X
X  return (char *) d;
X}
X# endif
X
X# ifdef		MYMEMCHR
Xchar *memchr(T(void *s, s), T(int c, c), T(size_t n, n))
X
XD(void *s)
XD(int c)
XD(size_t n)
X
X{
X  char *p = (char *) s;
X
X  if (n != 0)
X    for (; *p++ != c && --n; )
X      ;
X  return n != 0 ? p-1 : 0;
X}
X# endif
X
X# ifdef		MYMEMSET
Xvoid memset(T(void *d, d), T(int c, c), T(size_t n, n))
X
XD(void *d)
XD(int c)
XD(size_t n)
X
X{
X  char *p = (char *) d;
X
X  if (n != 0)
X    for (; *p++ = c, --n; )
X      ;
X}
X# endif
X#endif
END_OF_FILE
if test 6632 -ne `wc -c <'config.h'`; then
    echo shar: \"'config.h'\" unpacked with wrong size!
fi
# end of 'config.h'
fi
if test -f 'stdiolib.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'stdiolib.h'\"
else
echo shar: Extracting \"'stdiolib.h'\" \(12113 characters\)
sed "s/^X//" >'stdiolib.h' <<'END_OF_FILE'
X/*			s t d i o l i b
X *
X * (C) Copyright C E Chew
X *
X * Feel free to copy, use and distribute this software provided:
X *
X *	1. you do not pretend that you wrote it
X *	2. you leave this copyright notice intact.
X *
X * This include file is used by the stdio code. It provides some
X * useful macro definitions that make the code a bit easier to
X * write.
X *
X * Patchlevel 2.0
X *
X * Edit History:
X */
X
X#include <fcntl.h>
X
X#include "config.h"
X
X/* System types */
X
X#ifdef		SYSTYPES
X# include <sys/types.h>
X#endif
X
X/* Time types */
X
X#ifdef		TIME
X# include <time.h>
X#endif
X
X/* Rest of includes */
X
X#include <sys/stat.h>
X#include <pwd.h>
X#include <errno.h>
X#include <stdio.h>
X
X/* Limits */
X
X#ifdef		LIMITS
X# include <limits.h>
X#endif
X
X/* Variable argument list hiding */
X
X#ifdef		STDARG
X# include <stdarg.h>
X# define VA_START(n,l)	va_start(n,l)
X# define VA_ALIST	...
X# define VA_LIST	va_list
X# define VA_END(n)	va_end(n)
X# define VA_ARG(n,t)	va_arg(n,t)
X# define VA_DCL
X#else
X# include <varargs.h>
X# define VA_START(n,l)	va_start(n)
X# define VA_ALIST	va_alist
X# define VA_LIST	va_list
X# define VA_END(n)	va_end(n)
X# define VA_ARG(n,t)	va_arg(n,t)
X# define VA_DCL		va_dcl
X#endif
X
X/* Function prototype hiding */
X
X#ifdef		PROTOTYPE
X# define	P(x)		x
X# define	T(x,y)		x
X# define	D(x)
X#else
X# define	P(x)		()
X# define	T(x,y)		y
X# define	D(x)		x;
X#endif
X
X#ifdef		MEMORY
X# include <memory.h>
X# define MEMCPY(d,s,n)		((void) memcpy((d),(s),(n)))
X# define MEMCHR(s,c,n)		(memchr((s),(c),(n)))
X# define MEMSET(s,v,n)		((void) memset((s),(v),(n)))
X#endif
X
X/* Strings */
X
X#ifdef		STRING
X# include <string.h>
X#endif
X
X/* String functions using memory functions */
X
X#ifdef		MEMSTR
X# undef strlen
X# define strlen(s)	((char *) MEMCHR((s),(0),INT_MAX) - (char *) (s))
X#endif
X
X/* Unsigned char casting */
X
X#ifdef		UNSIGNEDCHAR
X# define UCHAR(x)	((int) ((unsigned char) (x)))
X#else
X# define UCHAR(x)	((int) (x) & ((1 << CHAR_BIT) - 1))
X#endif
X
X/* Stdio internal types */
X
Xtypedef void (*atexit_t) P((void));	/* exit handlers */
X
X/* Function prototypes */
X
Xint _bfail	P((void));		/* fail */
Xint _bsucceed	P((void));		/* succeed */
X
Xint _bwrupdate	P((int, FILE *));	/* write update */
Xint _bwronly	P((int, FILE *));	/* write only */
Xint _bwr	P((int, FILE *));	/* write */
Xint _bwrflush	P((FILE *));		/* write flush */
X
Xint _brdupdate	P((FILE *));		/* read update */
Xint _brdonly	P((FILE *));		/* read only */
Xint _brd	P((FILE *));		/* read */
Xint _brdflush	P((FILE *));		/* read flush */
X
Xint _bstrwr	P((int, FILE *));	/* write string */
Xint _bstrrd	P((FILE *));		/* read string */
X
Xint _iowrite	P((int, char *, int));	/* repeated write */
Xint _ioread	P((int, char *, int));	/* repeated read */
Xvoid _ioflush	P((void));		/* flush output */
Xint _allocbuf	P((FILE *));		/* internal buffering */
Xint _fopen	P((const char *,
X                   const char *,
X		   int, short *));	/* fopen assist */
XFILE *_file	P((FILE *, int, short));/* initialise FILE */
X
X/* Extras not in ANSI but probably could be */
X
Xint _vscanf	P((const char *, VA_LIST));
Xint _vfscanf	P((FILE *, const char *, VA_LIST));
Xint _vsscanf	P((const char *, const char *, VA_LIST));
X
X/* Library globals */
X
Xextern int errno;			/* system error number */
Xextern int sys_nerr;			/* size of error table */
Xextern char *sys_errlist[];		/* error descriptions */
X
X/* Stdio internal variables */
X
Xextern atexit_t *_exit_hp;		/* exit handler list pointer */
Xextern FILE *_iop;			/* stream list */
X
X/* Library calls */
X
Xvoid *malloc	P((size_t));		/* memory allocator */
Xvoid free	P((void *));		/* free memory */
X
X/* System calls */
X
X#ifndef		OPEN3
Xint open	P((const char *, int));	/* two argument open */
X# define open	_open3			/* fake three argument open */
X# undef O_CREAT
X# undef O_APPEND
X# undef O_TRUNC
X# define O_CREAT	(~(O_RDONLY|O_WRONLY|O_RDWR) ^ \
X			(~(O_RDONLY|O_WRONLY|O_RDWR) & \
X                        (~(O_RDONLY|O_WRONLY|O_RDWR) - 1)))
X# define O_APPEND	(~(O_CREAT|O_RDONLY|O_WRONLY|O_RDWR) ^ \
X			(~(O_CREAT|O_RDONLY|O_WRONLY|O_RDWR) & \
X                        (~(O_CREAT|O_RDONLY|O_WRONLY|O_RDWR) - 1)))
X# define O_TRUNC	(~(O_APPEND|O_CREAT|O_RDONLY|O_WRONLY|O_RDWR) ^ \
X			(~(O_APPEND|O_CREAT|O_RDONLY|O_WRONLY|O_RDWR) & \
X                        (~(O_APPEND|O_CREAT|O_RDONLY|O_WRONLY|O_RDWR) - 1)))
X#endif
X
Xvoid		_exit    P((int));		/* exit to system */
Xint		isatty   P((int));		/* channel is tty */
Xint		close    P((int));		/* close channel */
Xint		creat    P((const char *, mode_t)); /* create a file */
Xint		open     P((const char *, int, ...)); /* open a file */
Xoff_t		lseek    P((int, off_t, int));	/* seek within file */
Xint		read     P((int, char *, unsigned int)); /* read channel */
Xint		write    P((int, char *, unsigned int)); /* write channel */
Xint		unlink   P((const char *));	/* unlink a file */
Xint		link     P((const char *, const char *)); /* link a file */
Xint		stat     P((const char *, struct stat *)); /* file status */
Xmode_t		umask    P((mode_t));		/* permission mask */
Xint		chmod    P((const char *, mode_t)); /* change permission */
Xpid_t		getpid   P((void));		/* get process id */
Xtime_t		time     P((time_t *));		/* get time */
Xuid_t		geteuid  P((void));		/* get effective user id */
Xuid_t		getuid   P((void));		/* get user id */
Xstruct passwd * getpwuid P((uid_t));		/* get passwd from uid */
X
X/* Size of tty buffers */
X
X#define TTYBUFSIZ		81
X
X/* Flag manipulation macros */
X
X#define TESTFLAG(f,x)		(((f)->_flag & (x)) != 0)
X#define SETFLAG(f,x)		((f)->_flag |= (x))
X#define CLEARFLAG(f,x)		((f)->_flag &= ~(x))
X#define GETFLAG(f,x)		((f)->_flag & (x))
X#define TOGGLEFLAG(f,x)		((f)->_flag ^= (x))
X#define SAVEFLAG(f,p)		((p) = (int) ((f)->_flag))
X#define RESTOREFLAG(f,p)	((f)->_flag = (short) (p))
X
X/* Add _ioflush to exit code
X *
X * Check is _ioflush needs to be added to the exit code. If so then
X * add it. This macro is run time system dependent.
X */
X#ifdef		MSDOS
X  extern int _wrapstdio;		/* stdio wrap required */
X# define SETIOFLUSH() { if (_wrapstdio != 0) _wrapstdio = atexit(_ioflush); }
X#endif
X
X#ifndef		SETIOFLUSH
X# define SETIOFLUSH()
X#endif
X
X/* Getc with full buffering
X *
X * This version of getc assumes that there is an input buffer
X * that is not empty and simply grabs the character from there.
X */
X#define FGETC(p) ( (int) ((unsigned char) *(p)->_rptr++) )
X
X/* Putc for non buffered streams
X *
X * This version of putc is explicitly for unbuffered streams. A
X * call is made directly to the buffer flushing code.
X */
X#define NPUTC(x,p) ( (*(p)->_flsbuf)((x),(p)) )
X
X/* Putc with full buffering
X *
X * This version of putc() assumes that there is an output buffer
X * that is not full and simply dumps the character in there.
X */
X#define FPUTC(x, p) ( ((int) ((unsigned char) (*(p)->_wptr++ = (x)))) )
X 
X/* Flush a stream
X *
X * Call the flush routine to clear the output buffer.
X */
X#define FFLUSH(f) ( (*(f)->_flush)(f) )
X
X/* Set _flsbuf
X *
X * Set the _flsbuf function pointer.
X */
X#define SETFLSBUF(f,p) ( (f)->_flsbuf = (p) )
X
X/* Set _filbuf
X *
X * Set the _filbuf function pointer.
X */
X#define SETFILBUF(f,p) ( (f)->_filbuf = (p) )
X
X/* Set _flush
X *
X * Set the _flush function pointer.
X */
X#define SETFLUSH(f,p) ( (f)->_flush = (p) )
X
X/* Initialise an output buffer
X *
X * This macro uses _base and _bufsiz to initialise _wptr, _scan and
X * _wend. _wptr and _scan will be set to point at the base of the
X * buffer. _wend will be set to point at one past the end of the
X * buffer if the stream is buffered otherwise it will point at
X * the base of the buffer. Line buffered streams are considered to
X * be fully buffered. This macro must not alter _base unless the
X * code in fflush() is changed.
X */
X#define INITWRITEBUFFER(f) ( \
X  (f)->_wend = ((f)->_scan = (f)->_wptr = (f)->_base) + \
X               (TESTFLAG(f, _IONBF | _IOLBF) ? 0 : (f)->_bufsiz) \
X)
X
X/* Initialise an input buffer
X *
X * This macro empties an input buffer. It uses _base to initialise
X * _rptr and _scan, and sets _rend to point to the high water mark
X * of the buffer.
X */
X#define INITREADBUFFER(f, v) ( \
X  (f)->_rend = ((f)->_scan = (f)->_rptr = (f)->_base) + (v) \
X)
X
X/* Flush the next write
X *
X * This macro initialises the buffer by setting _wend and
X * _wptr to nil. This will force the next putc to call
X * _flsbuf.
X */
X#define CHECKNEXTWRITE(f) ( (f)->_wend = (f)->_wptr = 0 )
X
X/* Check a write
X *
X * If _wptr is zero, the write buffer is checked.
X */
X#define CHECKWRITE(f) ( \
X  (f)->_wptr == 0 ? ((f)->_wend = &(f)->_buf, (*(f)->_flsbuf)(0, f)) : 0 \
X)
X
X/* Flush the next read
X *
X * This macro initialises the buffer by setting _rend and
X * _rptr to nil. This will force the next next getc to call
X * _filbuf.
X */
X#define CHECKNEXTREAD(f) ( (f)->_rend = (f)->_rptr = 0 )
X
X/* Check a read
X *
X * If _rptr is zero, the read buffer is checked.
X */
X#define CHECKREAD(f) ( \
X  (f)->_rptr == 0 ? ((f)->_rend = &(f)->_buf, (*(f)->_filbuf)(f)) : 0 \
X)
X
X/* Test for buffer flush
X *
X * Return true if it is necessary to flush or fill the buffer.
X */
X#define CHECKFLUSH(f) ( \
X  (f)->_ptr == 0 \
X)
X
X/* Buffer size
X *
X * Return the size of the buffer. This will return rubbish
X * for unbuffered streams. Line and fully buffered streams will
X * have the true buffer size returned.
X */
X#define BUFFERSIZE(f) ( (f)->_bufsiz )
X
X/* Bytes left in input buffer
X *
X * This macro returns the number of bytes left in an input buffer.
X */
X#define BYTESINREADBUFFER(f) ( (f)->_rend - (f)->_rptr )
X
X/* Bytes written in output buffer
X *
X * This macro returns the number of bytes left in an output buffer.
X */
X#define BYTESINWRITEBUFFER(f) ( (f)->_wptr - (f)->_base )
X
X/* Unused bytes in output buffer
X *
X * This macro returns the number of unused bytes in an output buffer.
X * Unbuffered streams will return rubbish. Line and fully buffered streams
X * will have the amount of space remaining returned.
X */
X#define UNUSEDINWRITEBUFFER(f) ( (f)->_bufsiz - BYTESINWRITEBUFFER(f) )
X
X/* Get pointer into write buffer
X *
X * This macro gets the pointer into the write buffer.
X */
X#define GETWRITEPTR(f) ( (f)->_wptr )
X
X/* Set pointer into write buffer
X *
X * This macro sets the pointer into the write buffer.
X */
X#define SETWRITEPTR(f,p) ( (f)->_wptr = (p) )
X
X/* Get pointer into read buffer
X *
X * This macro gets the pointer into the read buffer.
X */
X#define GETREADPTR(f) ( (f)->_rptr )
X
X/* Set pointer into read buffer
X *
X * This macro sets the pointer into the read buffer.
X */
X#define SETREADPTR(f,p) ( (f)->_rptr = (p) )
X
X/* Check if buffering has been set
X *
X * Return true if buffering has already been set. A stream
X * set for unbuffered output is considered to have had
X * its buffering set.
X */
X#define HASBUFFER(f) ( (f)->_base != 0 )
X
X/* Set the scan point
X *
X * The _scan field is used for line buffered streams. The _scan
X * field remembers the point at which the next write starts. When
X * the write is complete a scan can be made of the buffer from
X * that point to determine whether the buffer should be flushed.
X */
X#define SETSCAN(f) ( (f)->_scan = (f)->_wptr )
X
X/* Conditionally flush line buffered stream
X *
X * Scan the buffer from the last scan point and if a \n is found
X * flush the stream.
X */
X#define FLUSHSCAN(f) ( \
X  MEMCHR((f)->_scan, '\n', (f)->_wptr - (f)->_scan) && FFLUSH(f) ? EOF : 0 \
X)
X
X/* Set _wend for line buffering
X *
X * Set _wend for line buffering. This means that _wend is set to
X * point at _base.
X */
X#define SETWRITELINEBUFFERING(f) ( (f)->_wend = (f)->_base )
X
X/* Set _wend for full buffering
X *
X * Set _wend to _base + _bufsiz so that the entire buffer can be
X * used.
X */
X#define SETWRITEFULLBUFFERING(f) ( (f)->_wend = (f)->_base + (f)->_bufsiz )
X
X/* Unroll a loop
X *
X * Assume that the loop must execute at least once. The first argument
X * is the name of the loop control variable. The second argument is the
X * name of the loop control variable. The third argument is the expression
X * to be placed in the loop body. The control variable should be unsigned,
X * otherwise the right shift might propagate the sign bit. The caller must
X * also provide the name of a unique label.
X */
X# define UNROLL_DO(l,v,x) { \
X  char t = (v); \
X  (v) = ((v)+1) >> 1; \
X  if (t & 1) goto l; \
X  do { x; l: x; } while (--(v)); \
X}
END_OF_FILE
if test 12113 -ne `wc -c <'stdiolib.h'`; then
    echo shar: \"'stdiolib.h'\" unpacked with wrong size!
fi
# end of 'stdiolib.h'
fi
if test -f 'vfprintf.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'vfprintf.c'\"
else
echo shar: Extracting \"'vfprintf.c'\" \(8218 characters\)
sed "s/^X//" >'vfprintf.c' <<'END_OF_FILE'
X/*			v f p r i n t f
X *
X * (C) Copyright C E Chew
X *
X * Feel free to copy, use and distribute this software provided:
X *
X *	1. you do not pretend that you wrote it
X *	2. you leave this copyright notice intact.
X *
X * This routine provides the same functionality as fprintf
X * except that it uses varargs.h.
X *
X * In this implementation, this routine is basis for all the
X * formatted output routines. printf, fprintf, and sprintf
X * are all defined in terms of vfprintf.
X *
X * The user is referred to the manual page for a full
X * description of the formats available.
X *
X * The function returns the number of bytes generated, or
X * EOF in the case of an error.
X *
X * Patchlevel 2.0
X *
X * Edit History:
X */
X
X#include "stdiolib.h"
X
X/*LINTLIBRARY*/
X
X#define MINBITS		3		/* least bits required --- octal */
X#define MAXPREFIX	3		/* overhead for prefix */
X
X#define MAXDIGITS	((sizeof(long)*CHAR_BIT+MINBITS-1)/MINBITS*MINBITS)
X#define VBUFFERSIZE	MAXDIGITS+MAXPREFIX+1
X
X#define OPTIONAL(p,c,f,v)	if(*(p)==(c)){(f)=(v);(p)++;}
X
X/* Get an integer argument
X *
X * Scan the string beginning at the point indicated for an
X * integer argument. If a '*' is found, the argument pointer
X * is used to retrieve a remote integer.
X */
X
Xstatic int integer(T(char **p, p), T(VA_LIST *ap, ap))
X
XD(char **p)				/* pointer to string pointer */
XD(VA_LIST *ap)				/* pointer to argument list */
X
X{
X  char *cp;				/* character pointer */
X  int v;				/* return value */
X
X  cp = *p;
X
X  if (*cp == '*') {
X    v = VA_ARG(*ap, int);
X    cp++;
X  }
X  else {
X    for (v = 0; *cp >= '0' && *cp <= '9'; ) {
X      v *= 10;
X      v += (*cp++ - '0');
X    }
X  }
X  *p = cp;
X  return v;
X}
X
Xint vfprintf(T(FILE *fp, fp), T(const char *fmt, fmt), T(VA_LIST args, args))
X
XD(FILE *fp)				/* stream for output */
XD(char *fmt)				/* format for output */
XD(VA_LIST args)				/* argument list */
X
X{
X  char buf[VBUFFERSIZE];		/* workspace */
X  int bytes;				/* bytes output */
X
X  char *p, *q;				/* pointers into workspace */
X
X  _stdiobuf_t *bp, *bq;			/* fast copy pointers */
X
X  char leftjustify;			/* left justify */
X  char showsign;			/* display a sign */
X  char blankprefix;			/* prefix with blank */
X  char alternate;			/* alternate format */
X
X  char zerofill;			/* fill with zeros */
X  char flush;				/* flush line buffered stream */
X  int width;				/* field width */
X
X  int precision;			/* precision */
X
X  char longflag;			/* number is long */
X
X  char capitals;			/* capitals */
X
X  char prefix;				/* number has prefix -/ /+ */
X
X  int radixoffset;			/* offset for higher radices */
X  unsigned int radix;			/* radix for conversion */
X  char sign;				/* conversion is signed */
X  char negative;			/* number is negative */
X  long vl;				/* conversion temporary */
X  int vi;				/* conversion temporary */
X  unsigned short vs;			/* conversion temporary */
X  char shortint;			/* short or long */
X  int c;				/* conversion temporary */
X  int length;				/* raw length of output */
X
X  int saveflags;			/* save flags */
X
X  if (CHECKWRITE(fp))
X    return 0;
X
X  SAVEFLAG(fp, saveflags);
X  if (TESTFLAG(fp, _IOLBF)) {
X    CLEARFLAG(fp, _IOLBF);
X    SETWRITEFULLBUFFERING(fp);
X  }
X
X  for (flush = bytes = 0; ; ) {
X
X/* Scan for format dumping directly into output buffer */
X    for (bp = (_stdiobuf_t *) fmt; ; ) {
X      if (TESTFLAG(fp, _IONBF) || (length = UNUSEDINWRITEBUFFER(fp)) == 0)
X	c = *bp++;
X      else {
X	bq = GETWRITEPTR(fp);
X	do
X	  ;
X	while ((c = *bp++) != 0 && c != '%' && c != '\n' &&
X	       (*bq++ = c, --length));
X	SETWRITEPTR(fp, bq);
X      }
X      if (c == 0 || c == '%')  break;
X      if (putc(c, fp) == '\n') flush = 1;
X    }
X
X/* Format or end of format found */
X    bytes += (bp - (_stdiobuf_t *) fmt) - 1;
X    fmt    = bp;
X    if (c == 0) break;
X
X/* Initialise conversion variables */
X    p = q = &buf[sizeof(buf)-1];
X
X    leftjustify = 0;
X    showsign    = 0;
X    blankprefix = 0;
X    alternate   = 0;
X
X    zerofill    = ' ';
X    width       = 0;
X
X    precision   = -1;
X
X    longflag    = 0;
X    capitals    = 0;
X    radixoffset = 'a' - '9' - 1;
X
X    prefix      = 0;
X
X/* Check for optional flags */
X    for ( ; ; ) {
X      switch (*fmt) {
X      case '-': leftjustify = 1; break;
X      case '+': showsign    = 1; break;
X      case ' ': blankprefix = 1; break;
X      case '#': alternate   = 1; break;
X      default:  goto DoneFlags;
X      }
X      fmt++;
X    }
XDoneFlags:
X
X/* Check for field width */
X    OPTIONAL(fmt, '0', zerofill, '0');
X    width = integer((char **) &fmt, &args);
X
X/* Check for precision */
X    if (*fmt == '.') {
X      fmt++;
X      precision = integer((char **) &fmt, &args);
X    }
X
X/* Check for longs */
X    OPTIONAL(fmt, 'l', longflag, 1);
X
X/* Switch through all the format options */
X    switch (*fmt) {
X
X      case 'X':
X	capitals++;
X	radixoffset += 'A' - 'a';
X
X      case 'x':
X	radix = 16;
X	sign  = 0;
X	goto oxud;
X
X      case 'u':
X	radix = 10;
X	sign  = 0;
X	goto oxud;
X
X      case 'o':
X	radix = 8;
X	sign  = 0;
X	goto oxud;
X
X      case 'd':
X        radix = 10;
X        sign  = 1;
X
Xoxud:
X	vs = shortint = 0;
X	if (longflag) {
X	  if (sign) vl = VA_ARG(args, long);
X	  else      vl = VA_ARG(args, unsigned long);
X	  if ((negative = sign && vl < 0) != 0)
X	    vl = -vl;
X	  if ((unsigned long) vl <= USHRT_MAX) {
X	    vs = (unsigned short) vl;
X	    shortint = 1;
X	  }
X	}
X	else {
X	  if (sign) vi = VA_ARG(args, int);
X	  else      vi = VA_ARG(args, unsigned);
X	  if ((negative = sign && vi < 0) != 0)
X	    vi = -vi;
X	  if ((unsigned int) vi > USHRT_MAX)
X	    vl = (unsigned int) vi;
X	  else {
X	    vs = (unsigned short) vi;
X	    shortint = 1;
X	  }
X	}
X	if (! shortint) {
X	  do {
X	    c  = (int) ((unsigned long) (vl) % radix) + '0';
X	    vl = (unsigned long) (vl) / radix;
X	    if (c > '9')
X	      c += radixoffset;
X	    *--q = c;
X	  } while (vl > USHRT_MAX);
X	  if ((vs = (unsigned short) vl) == 0) goto ConversionDone;
X	}
X	do {
X	  c  = (int) ((unsigned short) (vs) % radix) + '0';
X	  vs = (unsigned short) (vs) / radix;
X	  if (c > '9')
X	    c += radixoffset;
X	  *--q = c;
X	} while (vs != 0);
X
XConversionDone:
X	if (precision > width) {
X	  width = precision;
X	  zerofill = '0';
X	}
X	if (negative) {
X	  prefix++;
X	  *--q = '-';
X	}
X	else if (sign) {
X	  if (showsign) {
X	    prefix++;
X	    *--q = '+';
X	  }
X	  else if (blankprefix) {
X	    prefix++;
X	    *--q = ' ';
X	  }
X	}
X	if (alternate) {
X	  if (radix == 8) {
X	    prefix++;
X	    *--q = '0';
X	  }
X	  else if (radix == 16) {
X	    prefix += 2;
X	    *--q = capitals ? 'X' : 'x';
X            *--q = '0';
X	  }
X	}
X	break;
X
X/* Single character format */
X      case 'c':
X	if ((*--q = VA_ARG(args, int)) == '\n')
X	  flush = 1;
X	break;
X
X/* String format */
X      case 's':
X	if ((q = VA_ARG(args, char *)) == NULL)
X	  q = "(null)";
X	p = q;
X	if (precision < 0) {
X	  for (; (c = *p) != 0; p++)
X	    if (c == '\n')
X	      flush = 1;
X	}
X	else if (precision > 0) {
X	  for (; (c = *p) != 0; ) {
X	    if (c == '\n')
X	      flush = 1;
X	    if (p++, --precision)
X	      break;
X	  }
X	}
X	break;
X
X/* Default just print it */
X      default:
X	if ((*--q = *fmt) == '\n')
X	  flush = 1;
X	break;
X    }
X
X/* Scan past conversion character */
X    fmt++;
X
X/* Length of string to be printed */
X    length = p - q;
X
X/* Subtract to find padding required */
X    if ((width -= length) < 0)
X      width = 0;
X
X/* Signal left justification */
X    if (leftjustify == 0)
X      width = -width;
X
X/* Check for left justification */
X    if (width < 0) {
X
X/* Check for negative and zero fill */
X      if (zerofill == '0') {
X	if (prefix != 0) {
X	  bytes  += prefix;
X	  length -= prefix;
X
X/* Don't unroll this loop since the number of iterations is small */
X	  do
X	    (void) putc(*q++, fp);
X	  while (--prefix);
X	}
X      }
X
X/* Now output the rest of the padding */
X      width = -width;
X      bytes += width;
X      do
X	(void) putc(zerofill, fp);
X      while (--width);
X    }
X
X/* Output the string proper */
X    if (length > 0) {
X      bytes += length;
X      do
X	putc(*q++, fp);
X      while (--length);
X    }
X
X/* Do right padding */
X    if (width != 0) {
X      bytes += width;
X      do
X	putc(' ', fp);
X      while (--width);
X    }
X  }
X
X/* Flush line buffered streams */
X  RESTOREFLAG(fp, saveflags);
X  if (TESTFLAG(fp, _IOLBF)) {
X    SETWRITELINEBUFFERING(fp);
X    if (flush)
X      (void) FFLUSH(fp);
X  }
X
X  return ferror(fp) ? EOF : bytes;
X}
END_OF_FILE
if test 8218 -ne `wc -c <'vfprintf.c'`; then
    echo shar: \"'vfprintf.c'\" unpacked with wrong size!
fi
# end of 'vfprintf.c'
fi
echo shar: End of archive 5 \(of 6\).
cp /dev/null ark5isdone
MISSING=""
for I in 1 2 3 4 5 6 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 6 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
Earl Chew, Dept of Computer Science, Monash University, Australia 3168
ARPA: cechew%bruce.cs.monash.oz.au@uunet.uu.net  ACS : cechew@bruce.oz