[comp.os.minix] Stdio V2 - Part 3 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 3 (of 6)."
# Contents:  _file.c _fopen.c _open3.c _update.c bitset.h fgets.c
#   fread.c fwrite.c gets.c makefile.dos makefile.unx setvbuf.c
#   tmpnam.c
# Wrapped by cechew@bruce on Fri Sep 29 16:23:38 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f '_file.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'_file.c'\"
else
echo shar: Extracting \"'_file.c'\" \(1834 characters\)
sed "s/^X//" >'_file.c' <<'END_OF_FILE'
X/*				_ f i l e
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 * Allocate and initialise a FILE structure. If the pointer passed
X * to the function is NULL, a FILE will be allocated, otherwise
X * the one specified will be used. The function will return
X * a pointer to the FILE structure, or NULL if it fails.
X *
X * Patchlevel 2.0
X *
X * Edit History:
X */
X
X#include "stdiolib.h"
X
X/*LINTLIBRARY*/
X
X#if	_IOREAD != 1 || _IOWRITE != 2
X	_IOREAD == 1 and _IOWRITE == 2 assumed
X#endif
X
Xstatic int (*filtable[]) P((FILE *)) =
X  {_brdupdate, _brdonly, (int (*) P((FILE *))) _bfail};
X
Xstatic int (*flstable[]) P((int, FILE *)) =
X  {_bwrupdate, (int (*) P((int, FILE *))) _bfail, _bwronly};
X
XFILE *_file(T(FILE *fp, fp), T(int fd, fd), T(short flags, flags))
X
XD(FILE *fp)				/* stream */
XD(int fd)				/* channel */
XD(short flags)				/* flags */
X
X{
X/* Allocate or find a file structure */
X  if (fp == NULL) {
X    for (fp = _iop; fp != NULL && TESTFLAG(fp, ~_IOSTATIC); fp = fp->_next)
X      if (fileno(fp) == fd)
X	return NULL;
X
X/* Existing descriptor hopefully is _IOSTATIC */
X    if (fp != NULL)
X      flags |= _IOSTATIC;
X
X/* No existing descriptor */
X    else {
X      if ((fp = (FILE *) malloc(sizeof(*fp))) == NULL)
X	return NULL;
X
X      fp->_next = _iop;
X      _iop      = fp;
X    }
X  }
X
X/* Stream descriptor needs to be initialised */
X  fp->_rend   = NULL;
X  fp->_rptr   = NULL;
X  fp->_wend   = NULL;
X  fp->_wptr   = NULL;
X  fp->_base   = NULL;
X  fp->_scan   = NULL;
X  fp->_bufsiz = 0;
X  fp->_flag   = flags;
X  fp->_file   = fd;
X
X  flags      &= _IOREAD | _IOWRITE;
X  fp->_filbuf = filtable[flags];
X  fp->_flsbuf = flstable[flags];
X  fp->_flush  = (int (*) P((FILE *))) _bsucceed;
X
X  return fp;
X}
END_OF_FILE
if test 1834 -ne `wc -c <'_file.c'`; then
    echo shar: \"'_file.c'\" unpacked with wrong size!
fi
# end of '_file.c'
fi
if test -f '_fopen.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'_fopen.c'\"
else
echo shar: Extracting \"'_fopen.c'\" \(1817 characters\)
sed "s/^X//" >'_fopen.c' <<'END_OF_FILE'
X/*			_ f o p e n
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 function scans the mode with which a channel should be
X * opened. It then opens the channel using that mode and returns
X * the channel number to the caller. On error, the value -1 will
X * be returned.
X *
X * If the function succeeds, the flags argument will be set to the
X * mode with which the channel was opened. If the fd argument is
X * -1, the channel will be allocated, otherwise the specified channel
X * will be used.
X *
X * Patchlevel 2.0
X *
X * Edit History:
X */
X
X#include "stdiolib.h"
X
X/*LINTLIBRARY*/
X
X#define CREATMODE 0666			/* mode to creat file */
X
Xint _fopen(T(const char *name, name), T(const char *mode, mode),
X           T(int fd, fd), T(short *flags, flags))
X
XD(char *name)				/* name of file */
XD(char *mode)				/* mode to open */
XD(int fd)				/* allocated channel */
XD(short *flags)				/* stdio flags */
X
X{
X  int openmode;				/* mode for open */
X  int readwrite;			/* basic mode */
X  int update;				/* read and write required */
X
X  readwrite = *mode++;
X  if (*mode == 'b')
X    mode++;
X  if ((update = *mode == '+') != 0) {
X    *flags = _IORW;
X    openmode = O_RDWR;
X  }
X
X  if (readwrite == 'r') {
X
X    if (! update) {
X      *flags = _IOREAD;
X      openmode = O_RDONLY;
X    }
X
X    if (fd < 0)
X      fd = open(name, openmode, CREATMODE);
X  }
X
X  else {
X    if (! update) {
X      *flags = _IOWRITE;
X      openmode = O_WRONLY;
X    }
X
X    openmode |= O_CREAT;
X    if (readwrite != 'a')
X      openmode |= O_TRUNC;
X    else {
X      openmode |= O_APPEND;
X#ifndef		OPEN3
X      *flags |= _IOAPPEND;
X#endif
X    }
X
X    if (fd < 0)
X      fd = open(name, openmode, CREATMODE);
X  }
X
X  return fd;
X}
END_OF_FILE
if test 1817 -ne `wc -c <'_fopen.c'`; then
    echo shar: \"'_fopen.c'\" unpacked with wrong size!
fi
# end of '_fopen.c'
fi
if test -f '_open3.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'_open3.c'\"
else
echo shar: Extracting \"'_open3.c'\" \(1934 characters\)
sed "s/^X//" >'_open3.c' <<'END_OF_FILE'
X/*				_ o p e n 3
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 * For those ancient systems without three argument opens, we fake it.
X * The following code works for:
X *
X *		r  O_RDONLY
X *		w  O_WRONLY | O_CREAT | O_TRUNC
X *		a  O_WRONLY | O_CREAT | O_APPEND
X *		r+ O_RDWR
X *		w+ O_RDWR   | O_CREAT | O_TRUNC
X *		a+ O_RDWR   | O_CREAT | O_APPEND
X *	other modes may not work
X *
X * Code based on open3.c from Bruce Evan's stdio. It is necessary to
X * set the umask to zero so that creat works implies that open works.
X * The O_APPEND mode is ignored since two argument opens don't support
X * it at all.
X *
X * Patchlevel 2.0
X *
X * Edit History:
X */
X
X#include "stdiolib.h"
X
X/*LINTLIBRARY*/
X/*VARARGS2*/
X/*ARGSUSED*/
X
X#ifndef		OPEN3
X
X#undef open
X
Xint _open3(T(const char *path, path), T(int mode, mode), VA_ALIST)
X
XD(char *path)				/* path to open */
XD(int mode)				/* mode to open with */
XVA_DCL
X
X{
X  int fd;				/* file descriptor */
X  int mask;				/* saved umask */
X  int perms;				/* permissions */
X  VA_LIST arg;				/* argument vector */
X
X/* r, a, r+ and a+ modes */
X  if ((mode & O_TRUNC) == 0) {
X    if ((fd = open(path, mode & (O_WRONLY|O_RDONLY|O_RDWR))) >= 0 ||
X	(mode & O_CREAT) == 0                                     ||
X	errno != ENOENT)
X      return fd;
X
X/* Fall through on a and a+ modes => couldn't open because ENOENT */
X  }
X
X/* Extract file permissions */
X  VA_START(arg, mode);
X  perms = VA_ARG(arg, int);
X  VA_END(arg);
X
X/* w and a modes */
X  if ((mode & (O_WRONLY|O_RDONLY|O_RDWR)) != O_RDWR)
X      fd = creat(path, perms);
X
X/* w+ and a+ modes */
X  else {
X      mask = umask(0);
X      if ((fd = creat(path, perms)) >= 0) {
X	  (void) close(fd);
X	  fd = open(path, O_RDWR);
X	  (void) chmod(path, ~mask & perms);
X      }
X      (void) umask(mask);
X  }
X
X  return fd;
X}
X#endif
END_OF_FILE
if test 1934 -ne `wc -c <'_open3.c'`; then
    echo shar: \"'_open3.c'\" unpacked with wrong size!
fi
# end of '_open3.c'
fi
if test -f '_update.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'_update.c'\"
else
echo shar: Extracting \"'_update.c'\" \(1695 characters\)
sed "s/^X//" >'_update.c' <<'END_OF_FILE'
X/*			_ u p d a t e
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 contains the additional buffering functions required
X * to implement the update modes of access (r+, w+ and a+).
X *
X * The functions perform adjustments to the FILE descriptor before
X * passing control to the appropriate rdonly or wronly function.
X *
X * The functions are placed here so that they will not be linked
X * in to a basic stdio application unless they are absolutely
X * necessary (specifically if _fopen() or fseek() are used).
X *
X * Patchlevel 2.0
X *
X * Edit History:
X */
X
X#include "stdiolib.h"
X
X/*LINTLIBRARY*/
X
X/* Check and initialise a read update stream
X *
X * _brdupdate is intended for read/write streams. It will check
X * that the stream has a buffer and will cope with direction
X * changes. The fill function will then be directed to _brd.
X */
Xint _brdupdate(T(FILE *fp, fp))
X
XD(FILE *fp)				/* stream */
X
X{
X  if (TESTFLAG(fp, (_IOWRITE | _IOEOF | _IOERR)))
X    return EOF;
X
X  SETFLAG(fp, _IOREAD);
X
X  return _brdonly(fp);
X}
X
X/* Check and initialise a write update stream.
X *
X * _bwrupdate is intended for read/write streams. It will check
X * that the stream has a buffer and will cope with direction
X * changes. The flush function will then be directed to _bwr.
X */
Xint _bwrupdate(T(int c, c), T(FILE *fp, fp))
X
XD(int c)				/* character to write */
XD(FILE *fp)				/* stream */
X
X{
X  if (GETFLAG(fp, (_IOREAD | _IOEOF)) == _IOREAD || TESTFLAG(fp, _IOERR))
X    return EOF;
X
X  SETFLAG(fp, _IOWRITE);
X  CLEARFLAG(fp, _IOREAD);
X
X  return _bwronly(c, fp);
X}
END_OF_FILE
if test 1695 -ne `wc -c <'_update.c'`; then
    echo shar: \"'_update.c'\" unpacked with wrong size!
fi
# end of '_update.c'
fi
if test -f 'bitset.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'bitset.h'\"
else
echo shar: Extracting \"'bitset.h'\" \(2335 characters\)
sed "s/^X//" >'bitset.h' <<'END_OF_FILE'
X/*			b i t s e t
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 implements a set of operators to manipulate bitsets
X * is a machine independent way. It may be necessary for other
X * machines to set up the constants at the front (such as the
X * width of int, etc).
X *
X * To avoid double evaluation of the argument in some of the
X * macros, define the data structure as follows:
X *
X *	1. the bitset is int []
X *	2. the first int will be used as scratch int [0]
X *	3. all the following elements will be used for the bitset proper
X *
X * Patchlevel 2.0
X *
X * Edit History:
X */
X
X/* Declare the relative sizing of the components */
X
X#define _BITELEMENT	unsigned int
X#define _BITSINCHAR	CHAR_BIT
X
X/* Determine how many bits there are in an elemental bitset */
X
X#define _BITS		(sizeof(_BITELEMENT)*_BITSINCHAR)
X
X/* Declare the relative offsets of the pieces in the structure */
X
X#define _BIT_SCRATCH_	0
X#define	_BIT_SET_	1
X
X/* Define how to find a bit within a bitset */
X
X#define _BITSIZE_(n)	(((n)+_BITS-1)/_BITS)
X#define _BITGROUP_(n)	((n)/_BITS)
X#define _BITMASK_(n)	(1<<((n)%_BITS))
X
X/* Define how to find a bit within the data structure */
X
X#define _BITSIZE(n)	(_BITSIZE_(n)+_BIT_SET_)
X#define _BITGROUP(n)	(_BITGROUP_(n)+_BIT_SET_)
X#define _BITMASK(n)	(_BITMASK_(n))
X
X/*
X * Declare a bitset of length n bits
X */
X
X#define bitstring(name, n) _BITELEMENT name[_BITSIZE(n)]
X
X/*
X * Clear all elements of the bitset
X */
X
X#define bitempty(name, n) MEMSET(&name[_BIT_SET_], 0, \
X				 _BITSIZE_(n)*sizeof(_BITELEMENT))
X
X/*
X * Set all elements of the bitset
X */
X
X#define bitfill(name, n) (_BITFILL(&name[_BIT_SET_], ~0, \
X				   _BITSIZE_(n)*sizeof(_BITELEMENT)))
X
X/*
X * Set one bit in the bitset
X */
X
X#define bitset(name, n) (name[_BIT_SCRATCH_]=(n), \
X			 name[_BITGROUP(name[_BIT_SCRATCH_])] |= \
X			   _BITMASK(name[_BIT_SCRATCH_]))
X
X/*
X * Clear one bit in the bitset
X */
X
X#define bitclear(name, n) (name[_BIT_SCRATCH_]=(n), \
X			   name[_BITGROUP(name[_BIT_SCRATCH_])] &= \
X			     ~_BITMASK(name[_BIT_SCRATCH_]))
X
X/*
X * Test one bit in the bitset
X */
X
X#define bittest(name, n) (name[_BIT_SCRATCH_]=(n), \
X			  name[_BITGROUP(name[_BIT_SCRATCH_])] & \
X			    _BITMASK(name[_BIT_SCRATCH_]))
END_OF_FILE
if test 2335 -ne `wc -c <'bitset.h'`; then
    echo shar: \"'bitset.h'\" unpacked with wrong size!
fi
# end of 'bitset.h'
fi
if test -f 'fgets.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'fgets.c'\"
else
echo shar: Extracting \"'fgets.c'\" \(1751 characters\)
sed "s/^X//" >'fgets.c' <<'END_OF_FILE'
X/*				f g e t s
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 * Read a line from the specified stream. The function will read
X * characters until n-1 characters are read or a newline character
X * is read or an EOF is encountered. The string is then terminated
X * with a null character. The newline character is placed into the
X * string, unlike gets which strips the newline character. The
X * function returns the first argument, but will return the NULL
X * pointer if no character was read before EOF was read.
X *
X * Patchlevel 2.0
X *
X * Edit History:
X */
X
X#include "stdiolib.h"
X
X/*LINTLIBRARY*/
X
Xchar *fgets(T(char *buf, buf), T(int n, n), T(FILE *fp, fp))
X
XD(char *buf)				/* buffer for input */
XD(int n)				/* size of buffer */
XD(FILE *fp)				/* stream */
X
X{
X  int ch;				/* character read */
X  _stdiobuf_t *q;			/* input buffer pointer */
X  _stdiobuf_t *s;			/* output buffer */
X  unsigned int bytesleft;		/* bytes left in current load */
X
X  if (n <= 1)
X    return n > 0 ? (buf[0] = 0, buf) : NULL;
X
X  if (fp == stdin && TESTFLAG(stdout, _IOLBF))
X    (void) FFLUSH(stdout);
X
X  for (s = (_stdiobuf_t *) buf, --n; ; ) {
X    if ((bytesleft = BYTESINREADBUFFER(fp)) != 0) {
X      if (bytesleft > n)
X	bytesleft = n;
X      n -= bytesleft;
X      q = GETREADPTR(fp);
X      UNROLL_DO(fgetsbytes, bytesleft, if ((*s++ = *q++) == '\n') break);
X      SETREADPTR(fp, q);
X    }
X    *s = 0;
X    if (bytesleft != 0 || n == 0)
X      return buf;
X    if ((ch = getc(fp)) == EOF)
X      return s == (_stdiobuf_t *) buf ? NULL : buf;
X    if ((*s++ = ch) == '\n' || --n == 0) {
X      *s = 0;
X      return buf;
X    }
X  }
X}
END_OF_FILE
if test 1751 -ne `wc -c <'fgets.c'`; then
    echo shar: \"'fgets.c'\" unpacked with wrong size!
fi
# end of 'fgets.c'
fi
if test -f 'fread.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'fread.c'\"
else
echo shar: Extracting \"'fread.c'\" \(2968 characters\)
sed "s/^X//" >'fread.c' <<'END_OF_FILE'
X/*				f r e a d
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 * Read a series of records from an input stream. The function
X * returns the number of items (not bytes) read. The function
X * stops reading when the number of items is satisfied or when
X * EOF is encountered.
X *
X * Patchlevel 2.0
X *
X * Edit History:
X */
X
X#include "stdiolib.h"
X
X/*LINTLIBRARY*/
X
Xsize_t fread(T(void *ptr, ptr), T(size_t size, size),
X             T(size_t nitems, nitems), T(FILE *fp, fp))
X
XD(void *ptr)				/* buffer */
XD(size_t size)				/* size of record */
XD(size_t nitems)			/* number of items */
XD(FILE *fp)				/* stream */
X
X{
X  int red;				/* bytes read in read call */
X  _stdiobuf_t *p;			/* buffer pointer */
X  _stdiobuf_t *q;			/* pointer into getc buffer */
X  unsigned int itemsleft;		/* whole or partial items left */
X  unsigned int nextover;		/* bytes left over next iteration */
X  unsigned int leftover;		/* bytes left over this iteration */
X  unsigned int readitem;		/* whole items to read */
X  unsigned int readsize;		/* amount of data to read */
X  unsigned int oversize;		/* readsize less leftover */
X
X  if (CHECKREAD(fp) ||
X  (itemsleft = nitems) == 0 ||
X  size == 0)
X    return 0;
X
X/* Flush stdout */
X  if (fp == stdin && TESTFLAG(stdout, _IOLBF))
X    (void) FFLUSH(stdout);
X
X/* Fix void * casting problems */
X  p = (_stdiobuf_t *) ptr;
X
X/* Absorb as much data from the input buffer as possible */
X  nextover = 0;
X  readitem = 0;
X  if ((readsize = BYTESINREADBUFFER(fp)) != 0) {
X    if (readsize/size >= itemsleft) {
X      readsize = itemsleft*size;
X      readitem = itemsleft;
X    }
X    else {
X      readitem = readsize/size;
X      nextover = (leftover = readsize%size) != 0 ? size - leftover : 0;
X    }
X    q = GETREADPTR(fp);
X    if (readsize > FREADTHRESHOLD) {
X      MEMCPY(p, q, readsize);
X      p += readsize;
X      q += readsize;
X    }
X    else {
X      do
X	*p++ = *q++;
X      while (--readsize);
X    }
X    SETREADPTR(fp, q);
X  }
X
X/* The rest of the data comes from the file directly */
X  for ( ; (itemsleft -= readitem) != 0; p += readsize) {
X    leftover = nextover;
X    readsize = INT_MAX;
X    readitem = 0;
X
X/* Very large objects will require several large reads */
X    if (readsize < leftover)
X      nextover = leftover - readsize;
X
X/* Account for end of last object and start of new ones */
X    else {
X      if (leftover != 0)
X	readitem = 1;
X      oversize = readsize - leftover;
X      if ((readitem += oversize/size) < itemsleft)
X	nextover = size - oversize%size;
X      else {
X	readitem = itemsleft;
X	readsize = leftover + itemsleft*size;
X	if (leftover != 0)
X	  readsize -= size;
X      }
X    }
X
X    red = _ioread(fileno(fp), (char *) p, (int) readsize);
X
X    if (red != readsize) {
X      if (red != -1 && red > leftover)
X	itemsleft -= 1 + (red-leftover)/size;
X      break;
X    }
X  }
X  return nitems-itemsleft;
X}
END_OF_FILE
if test 2968 -ne `wc -c <'fread.c'`; then
    echo shar: \"'fread.c'\" unpacked with wrong size!
fi
# end of 'fread.c'
fi
if test -f 'fwrite.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'fwrite.c'\"
else
echo shar: Extracting \"'fwrite.c'\" \(3345 characters\)
sed "s/^X//" >'fwrite.c' <<'END_OF_FILE'
X/*			f w r i t e
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 function writes a series of records to the output stream.
X * The function returns the number of items written to the stream.
X * Writing stops when the correct number of items have been written
X * or when the function encounters an error.
X *
X * Patchlevel 2.0
X *
X * Edit History:
X */
X
X#include "stdiolib.h"
X
X/*LINTLIBRARY*/
X
Xsize_t fwrite(T(void *ptr, ptr), T(size_t size, size),
X              T(size_t nitems, nitems), T(FILE *fp, fp))
X
XD(void *ptr)				/* buffer */
XD(size_t size)				/* size of item */
XD(size_t nitems)			/* number of items */
XD(FILE *fp)				/* stream */
X
X{
X  int wrote;				/* bytes written in write call */
X  _stdiobuf_t *p;			/* buffer pointer */
X  _stdiobuf_t *q;			/* output buffer pointer */
X  unsigned int itemsleft;		/* whole or partial items left */
X  unsigned int leftover;		/* bytes left over this iteration */
X  unsigned int nextover;		/* bytes left over next iteration */
X  unsigned int writesize;		/* size of write */
X  unsigned int writeitem;		/* whole items written */
X  unsigned int oversize;		/* writesize less leftover */
X  unsigned int writebytes;		/* total bytes to write (small) */
X  unsigned int bytesleft;		/* bytes left to write (small) */
X
X/* Items left to write */
X  if (CHECKWRITE(fp) || (itemsleft = nitems) == 0 || size == 0)
X    return 0;
X
X/* Fix void * casting problems */
X  p = (_stdiobuf_t *) ptr;
X
X/* Small amounts go via putc */
X  if (! TESTFLAG(fp, _IONBF) &&
X      (UNUSEDINWRITEBUFFER(fp)+BUFFERSIZE(fp))/size > itemsleft) {
X    SETSCAN(fp);
X    writebytes = bytesleft = itemsleft*size;
X    do {
X      if ((writesize = UNUSEDINWRITEBUFFER(fp)) > bytesleft)
X	writesize = bytesleft;
X
X      if (writesize == 0) {
X	if (FFLUSH(fp))
X	  break;
X      }
X      else {
X	bytesleft -= writesize;
X	q = GETWRITEPTR(fp);
X	if (writesize > FWRITETHRESHOLD) {
X	  MEMCPY(q, p, writesize);
X	  p += writesize;
X	  q += writesize;
X	}
X	else {
X	  do
X	    *q++ = *p++;
X	  while (--writesize);
X	}
X	SETWRITEPTR(fp, q);
X      }
X    } while (bytesleft != 0);
X
X    if (TESTFLAG(fp, _IOLBF))
X      (void) FFLUSH(fp);
X
X    return (writebytes-bytesleft)/size;
X  }
X
X/* Large amounts get fed directly to the file */
X  if (BYTESINWRITEBUFFER(fp) != 0 && FFLUSH(fp))
X    return 0;
X
X/* The rest of the data goes to the file directly */
X  for (nextover=writeitem=0; (itemsleft -= writeitem) != 0; p += writesize) {
X    leftover = nextover;
X    writesize = INT_MAX;
X    writeitem = 0;
X
X/* Very large objects will require several large writes */
X    if (writesize < leftover)
X      nextover = leftover - writesize;
X
X/* Account for end of last object and start of new ones */
X    else {
X      if (leftover != 0)
X	writeitem = 1;
X      oversize = writesize - leftover;
X      if ((writeitem += oversize/size) < itemsleft)
X	nextover = size - oversize%size;
X      else {
X	writeitem = itemsleft;
X	writesize = leftover + itemsleft*size;
X	if (leftover != 0)
X	  writesize -= size;
X      }
X    }
X
X    wrote = _iowrite(fileno(fp), (char *) p, (int) writesize);
X
X    if (wrote != writesize) {
X      if (wrote != -1 && wrote > leftover)
X	itemsleft -= 1 + (wrote-leftover)/size;
X      break;
X    }
X  }
X  return nitems-itemsleft;
X}
END_OF_FILE
if test 3345 -ne `wc -c <'fwrite.c'`; then
    echo shar: \"'fwrite.c'\" unpacked with wrong size!
fi
# end of 'fwrite.c'
fi
if test -f 'gets.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'gets.c'\"
else
echo shar: Extracting \"'gets.c'\" \(1481 characters\)
sed "s/^X//" >'gets.c' <<'END_OF_FILE'
X/*				g e t s
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 * Read a line from stdin. The line is read up until the next
X * newline character or EOF is encountered. The newline
X * character is not inserted into the buffer, but the buffer
X * is terminated with a null character. No checks are made
X * that the line will fit into the buffer. The function returns
X * a pointer to the buffer. If EOF is encountered before any
X * characters have been read, the NULL pointer is returned.
X *
X * Patchlevel 2.0
X *
X * Edit History:
X */
X
X#include "stdiolib.h"
X
X/*LINTLIBRARY*/
X
Xchar *gets(T(char *buf, buf))
X
XD(char *buf)				/* input buffer */
X
X{
X  int ch;				/* next character */
X  _stdiobuf_t *q;			/* input buffer pointer */
X  _stdiobuf_t *s;			/* user's buffer pointer */
X  unsigned int bytesleft;		/* bytes left in current load */
X
X  if (TESTFLAG(stdout, _IOLBF))
X    (void) FFLUSH(stdout);
X
X  for (s = (_stdiobuf_t *) buf; ;*s++ = ch) {
X    if ((bytesleft = BYTESINREADBUFFER(stdin)) != 0) {
X      q = GETREADPTR(stdin);
X      UNROLL_DO(fgetsbytes, bytesleft, if ((*s++ = *q++) == '\n') break);
X      SETREADPTR(stdin, q);
X    }
X    if (bytesleft != 0) {
X      *--s = 0;
X      return buf;
X    }
X    *s = 0;
X    if ((ch = getc(stdin)) == EOF)
X      return s == (_stdiobuf_t *) buf ? NULL : buf;
X    if (ch == '\n')
X      return buf;
X  }
X}
END_OF_FILE
if test 1481 -ne `wc -c <'gets.c'`; then
    echo shar: \"'gets.c'\" unpacked with wrong size!
fi
# end of 'gets.c'
fi
if test -f 'makefile.dos' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'makefile.dos'\"
else
echo shar: Extracting \"'makefile.dos'\" \(1880 characters\)
sed "s/^X//" >'makefile.dos' <<'END_OF_FILE'
X#		Makefile for BSD
X#
XSTDIO=	stdio.lib
XALL=	*.c *.g *.h *.sh *.txt makefile.* *.cfg
XETC=	end.lib
XEXIT=	exit.obj _fakfls.obj
XLIBOBJ=	_allocbu.obj _file.obj _fopen.obj \
X	_ioread.obj _iowrite.obj _misc.obj \
X	_open3.obj _os.obj _rename.obj \
X	_stdio.obj _update.obj _vfscanf.obj \
X	_vscanf.obj _vsscanf.obj \
X	atexit.obj clearerr.obj ctermid.obj \
X	cuserid.obj fclose.obj fdopen.obj \
X	feof.obj ferror.obj fflush.obj \
X	fgetc.obj fgets.obj fileno.obj \
X	fopen.obj fprintf.obj fputc.obj \
X	fputs.obj fread.obj freopen.obj \
X	fscanf.obj fseek.obj ftell.obj \
X	fwrite.obj getc.obj getchar.obj \
X	gets.obj getw.obj perror.obj \
X	printf.obj putc.obj putchar.obj \
X	puts.obj putw.obj remove.obj \
X	rewind.obj scanf.obj setbuf.obj \
X	setvbuf.obj sprintf.obj sscanf.obj \
X	tmpfile.obj tmpnam.obj ungetc.obj \
X	vfprintf.obj vprintf.obj vsprintf.obj
XTESTEXE=	xercise xexit xfputs xfwrite \
X		xprintf xputc xputs xsprintf
XTESTOBJ=	xercise.obj xexit.obj xfputs.obj xfwrite.obj \
X		xprintf.obj xputc.obj xputs.obj xsprintf.obj
X#
X.SUFFIXES:	.obj .c
X.c.obj:
X	mcc -v -c -I. $<
X#
Xall:		$(TESTEXE)
X#
Xxercise:	xercise.obj $(STDIO) $(ETC)
X	mcc -v -o xercise xercise.obj $(STDIO) $(ETC)
Xxexit:		xexit.obj $(STDIO) $(ETC)
X	mcc -v -o xexit xexit.obj $(STDIO) $(ETC)
Xxfwrite:	xfwrite.obj $(STDIO) $(ETC)
X	mcc -v -o xfwrite xfwrite.obj $(STDIO) $(ETC)
Xxprintf:	xprintf.obj $(STDIO) $(ETC)
X	mcc -v -o xprintf xprintf.obj $(STDIO) $(ETC)
Xxputc:		xputc.obj $(STDIO) $(ETC)
X	mcc -v -o xputc xputc.obj $(STDIO) $(ETC)
Xxputs:		xputs.obj $(STDIO) $(ETC)
X	mcc -v -o xputs xputs.obj $(STDIO) $(ETC)
Xxsprintf:	xsprintf.obj $(STDIO) $(ETC)
X	mcc -v -o xsprintf xsprintf.obj $(STDIO) $(ETC)
X#
X$(STDIO):	$(LIBOBJ)
X	rm -f $(STDIO)
X	lib $(STDIO) + $(LIBOBJ) ;
X$(ETC):		$(EXIT)
X	rm -f $(ETC)
X	lib $(ETC) + $(EXIT) ;
X#
X$(LIBOBJ) $(EXIT):	stdiolib.h stdio.h
X#
X$(TESTOBJ):	stdio.h
X#
Xarc:
X	rm -f stdio.arc
X	pkarc a stdio $(ALL)
END_OF_FILE
if test 1880 -ne `wc -c <'makefile.dos'`; then
    echo shar: \"'makefile.dos'\" unpacked with wrong size!
fi
# end of 'makefile.dos'
fi
if test -f 'makefile.unx' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'makefile.unx'\"
else
echo shar: Extracting \"'makefile.unx'\" \(2257 characters\)
sed "s/^X//" >'makefile.unx' <<'END_OF_FILE'
X#		Makefile for BSD
X#
XCFLAGS=	-I. -I/usr/include -DMANUAL -gx
X#
XSTDIO=	stdio.a
XALL=	*.c *.g *.h *.sh *.txt makefile.* *.cfg
XLIBOBJ=	_allocbu.o _file.o _fopen.o \
X	_ioread.o _iowrite.o _misc.o \
X	_open3.o _os.o _rename.o \
X	_stdio.o _update.o _vfscanf.o \
X	_vscanf.o _vsscanf.o \
X	atexit.o clearerr.o ctermid.o \
X	cuserid.o fclose.o fdopen.o \
X	feof.o ferror.o fflush.o \
X	fgetc.o fgets.o fileno.o \
X	fopen.o fprintf.o fputc.o \
X	fputs.o fread.o freopen.o \
X	fscanf.o fseek.o ftell.o \
X	fwrite.o getc.o getchar.o \
X	gets.o getw.o perror.o \
X	printf.o putc.o putchar.o \
X	puts.o putw.o remove.o \
X	rewind.o scanf.o setbuf.o \
X	setvbuf.o sprintf.o sscanf.o \
X	tmpfile.o tmpnam.o ungetc.o \
X	vfprintf.o vprintf.o vsprintf.o
XEXIT=	exit.o _fakfls.o
XTESTEXE=	xercise xexit xfputs xfwrite \
X		xprintf xputc xputs xsprintf
XTESTOBJ=	xercise.o xexit.o xfputs.o xfwrite.o \
X		xprintf.o xputc.o xputs.o xsprintf.o
X#
Xall:		$(TESTEXE)
X#
Xinstall:
X	sh yinstall.sh
X#
Xxercise:	xercise.o $(STDIO)
X	cc -o xercise xercise.o $(STDIO)
Xxexit:		xexit.o $(STDIO)
X	cc -o xexit xexit.o $(STDIO)
Xxfputs:		xfputs.o $(STDIO)
X	cc -o xfputs xfputs.o $(STDIO)
Xxfwrite:	xfwrite.o $(STDIO)
X	cc -o xfwrite xfwrite.o $(STDIO)
Xxprintf:	xprintf.o $(STDIO)
X	cc -o xprintf xprintf.o $(STDIO)
Xxputc:		xputc.o $(STDIO)
X	cc -o xputc xputc.o $(STDIO)
Xxputs:		xputs.o $(STDIO)
X	cc -o xputs xputs.o $(STDIO)
Xxsprintf:	xsprintf.o $(STDIO)
X	cc -o xsprintf xsprintf.o $(STDIO)
X#
X$(STDIO):	$(LIBOBJ) $(EXIT)
X	/bin/rm -f $(STDIO)
X	ar cr $(STDIO) `lorder $(LIBOBJ) | tsort` $(EXIT)
X#
X$(LIBOBJ) $(EXIT):	stdiolib.h stdio.h
X#
X$(TESTOBJ):	stdio.h
X#
Xarc:
X	rm -f stdio.arc
X	arc a stdio.arc $(ALL)
X#
Xtar:
X	rm -f stdio.tar.Z
X	tar cvf - $(ALL) | compress > stdio.tar.Z
X#
Xshar:
X	ls $(ALL) | \
X	sed -e '/^site\.h/d' \
X	    -e '/^stdio\.h/d' \
X	    -e 's/^x.*/&	Exercise file/' \
X	    -e 's/^y.*\.c/&	Installation file/' \
X	    -e 's/^y.*\.sh/&	Installation script/' \
X	    -e 's/^.*\.txt/&	Documentation/' \
X	    -e 's/^makefile\..*/&	Makefile/' \
X	    -e 's/^[0-9a-z_]*\.g$$/&	Header file source/' \
X	    -e 's/^[0-9a-z_]*\.h$$/&	Header file/' \
X	    -e 's/^[0-9a-z_]*\.c$$/&	Stdio source code/' | \
X	makekit -nstdio. -s30k -oMANIFEST
X#
Xlint:
X	lint -n -I. -I/usr/include -DBSD `echo $(LIBOBJ) $(EXIT) | sed 's/\.o/.c/g'`
END_OF_FILE
if test 2257 -ne `wc -c <'makefile.unx'`; then
    echo shar: \"'makefile.unx'\" unpacked with wrong size!
fi
# end of 'makefile.unx'
fi
if test -f 'setvbuf.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'setvbuf.c'\"
else
echo shar: Extracting \"'setvbuf.c'\" \(1555 characters\)
sed "s/^X//" >'setvbuf.c' <<'END_OF_FILE'
X/*			s e t v b u 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 * Set the type of buffering to be used on this stream. This
X * must be called before any read or write has been done on
X * the stream. It is legal to make a stream unbuffered and
X * then at some subsequent time, make it buffered.
X *
X * Input streams cannot be line buffered. Attempts to do so
X * will make them fully buffered instead.
X *
X * Patchlevel 2.0
X *
X * Edit History:
X */
X
X#include "stdiolib.h"
X
X/*LINTLIBRARY*/
X
Xint setvbuf(T(FILE *fp, fp), T(char *buf, buf),
X            T(int type, type), T(unsigned int size, size))
X
XD(FILE *fp)				/* stream */
XD(char *buf)				/* buffer */
XD(int type)				/* type of buffering */
XD(unsigned int size)			/* size of buffer */
X
X{
X  if (TESTFLAG(fp, _IONBF))
X    fp->_base = NULL;
X
X  if (fp->_base != NULL)
X    return EOF;
X
X  CLEARFLAG(fp, (_IOFBF | _IONBF | _IOLBF));
X
X  if (type == _IOFBF || type == _IOLBF) {
X    if (size == 0)
X      return EOF;
X
X    if (buf == NULL) {
X      if ((buf = (char *) malloc(size)) == NULL)
X        return EOF;
X      else
X	SETFLAG(fp, _IOMYBUF);
X    }
X
X    fp->_base   = (_stdiobuf_t *) buf;
X    fp->_bufsiz = size;
X
X    if (TESTFLAG(fp, _IOREAD))
X      type = _IOFBF;
X  }
X  else if (type == _IONBF) {
X    fp->_base = &fp->_buf;
X    fp->_bufsiz = sizeof(fp->_buf);
X  }
X  else
X    return EOF;
X
X  SETFLAG(fp, type);
X  CHECKNEXTREAD(fp);
X  CHECKNEXTWRITE(fp);
X  return 0;
X}
END_OF_FILE
if test 1555 -ne `wc -c <'setvbuf.c'`; then
    echo shar: \"'setvbuf.c'\" unpacked with wrong size!
fi
# end of 'setvbuf.c'
fi
if test -f 'tmpnam.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'tmpnam.c'\"
else
echo shar: Extracting \"'tmpnam.c'\" \(2182 characters\)
sed "s/^X//" >'tmpnam.c' <<'END_OF_FILE'
X/*			t m p n a m
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 * Make a temporary file name. The file name is based on the
X * current process id. Following the process id will be a
X * sequence number. The filename format is:
X *
X *		PPPPPPPPS.SSS
X *
X * where P represents the pid in hexadecimal, and S represents
X * the sequence number in hexadecimal. The string P_tmpdir is
X * prefixed to the filename yielding the path of a temporary file.
X *
X * The temporary name will be placed in the string passed in,
X * or if that is null, it will be placed in a static area. The
X * function will return a pointer to the name.
X *
X * Patchlevel 2.0
X *
X * Edit History:
X */
X
X#include "stdiolib.h"
X
X#define P_tmpdir	"/tmp/"		/* temporary directory */
X#define L_tmpdir	(sizeof(P_tmpdir)-1) /* length of tmpdir */
X#define L_pid		8		/* length of pid code */
X#define L_sep		1		/* length of separator */
X#define L_seq		4		/* length of the sequence */
X
X/*LINTLIBRARY*/
X
Xchar *tmpnam(T(char *s, s))
X
XD(char *s)				/* name */
X
X{
X  static char name[L_tmpnam];		/* default place */
X  static time_t seq = 0;		/* sequence number */
X  static pid_t pid = -1;		/* process id */
X  struct stat sbuf;			/* stat buffer */
X  char *p;				/* name generator */
X  unsigned int v;			/* conversion value */
X  int d;				/* digits to generate */
X  int j;				/* counter */
X
X  if (pid < 0)
X    pid = getpid();
X  if (seq == 0)
X    seq = time((time_t *) 0);
X
X  do {
X
X/* Generate name backwards */
X    if ((p = s) == 0)
X      p = name;
X    p += L_tmpnam-1;
X    *p = 0;
X
X/* Fill in last characters */
X    v = (unsigned int) seq;
X    d = L_seq;
X    j = 2;
X    for (;;) {
X      do {
X	*--p = "0123456789abcdef"[v & 0xf];
X	v >>= 4;
X      } while (--d);
X
X      if (--j == 0)
X	break;
X
X      p[-1] = p[0];
X      *p--  = '.';
X
X      v = (unsigned int) pid;
X      d = L_pid;
X    }
X
X/* Fill in directory prefix */
X    s = &P_tmpdir[L_tmpdir];
X    d = L_tmpdir;
X    do
X      *--p = *--s;
X    while (--d);
X
X/* Advance for next name */
X    seq++;
X
X  } while (stat(p, &sbuf) >= 0);
X
X  return p;
X}
END_OF_FILE
if test 2182 -ne `wc -c <'tmpnam.c'`; then
    echo shar: \"'tmpnam.c'\" unpacked with wrong size!
fi
# end of 'tmpnam.c'
fi
echo shar: End of archive 3 \(of 6\).
cp /dev/null ark3isdone
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