Google
 

Trailing-Edge - PDP-10 Archives - SRI_NIC_PERM_FS_1_19910112 - c/lib5/stdio/new/fputc.c
There are 9 other files named fputc.c in the archive. Click here to see a list.
/*
 *	FPUTC - put a character to stream
 *
 *	Copyright (c) 1986 by Ian Macky, SRI International
 */

#include "stdio.h"
#include "errno.h"

int fputc(c, f)
register int c;
register FILE *f;
{
    int n;
    char *buffer, *malloc();
    char tinybuf[1];			/* grossness!  ick! */

    if (!_writeable(f)) return EOF;
    else if (--f->siocnt >= 0)
	return *++f->siocp = c;
    else if (f->sioflgs & _SIOF_BUF) {
	if (f->sioflgs & _SIOF_LINEBUF && --f->siolcnt >= 0) {
	    if ((*++f->siocp = c) == '\n' && fflush(f))
		return EOF;			/* couldn't flush old data */
	    return c;
	} else {
	    if (f->sioflgs & _SIOF_GROWBUF) {	/* if a string with growbuf, */
		if (!_expand(f, f->siosinc)) return EOF;
		return putc(c, f);
	    } else {
		if (fflush(f)) return EOF;	/* couldn't flush old data */
		return putc(c, f);
	    }
	}
    } else if (f->sioflgs & _SIOF_AUTOBUF) {
	if ((buffer = malloc(BUFSIZ)) == NULL) {
	    f->sioerr = errno = ENOMEM;
	    return EOF;
	} else {
	    setbuf(f, buffer);
	    f->sioflgs |= _SIOF_DYNAMBUF;
	    return putc(c, f);
	}
    } else {
	tinybuf[0] = c;
	if ((n = write(f->siofd, tinybuf, 1)) == -1) {
	    f->sioerr = errno;
	    return EOF;
	} else return c;
    }
}

int _writeable(f)
FILE *f;
{
    if (f->siocheck != _SIOF_OPEN)	/* make sure real FILE block */
	return 0;			/* and open, too. */
    if (f->sioflgs & _SIOF_WRITE)
	return 1;
    if (f->sioflgs & _SIOF_UPDATE &&
	(!(f->sioflgs & _SIOF_READ) || (f->sioflgs & _SIOF_EOF))) {
	f->sioflgs = f->sioflgs & ~_SIOF_READ | _SIOF_WRITE;
	_prime(f);			/* prime i/o */
	return 1;
    }
    return 0;
}

/*
 *	expand the given string file <by> chars.
 */

int _expand(f, by)
FILE *f;
int by;
{
    int new_size;
    char *new_buf, *realloc();

    if (!(f->sioflgs & _SIOF_GROWBUF))	/* if not an auto-expand string */
	return 0;			/* then don't do it!! */
    new_size = f->siolbuf + by;		/* new size of string buf */
    if (!(new_buf = realloc(f->siopbuf, new_size)))
	return 0;			/* couldn't get bigger buffer */
    if (new_buf != f->siopbuf) {	/* if our buffer moved */
	f->siopbuf = new_buf;		/* move to same pos in new buffer */
	f->siocp = new_buf + (f->siolbuf - f->siocnt) - 1;
    }
    f->siolbuf = new_size;		/* it's this big */
    f->siocnt = by;			/* this much gap now */
    return 1;
}