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