xref: /plan9-contrib/sys/src/libstdio/_IO_putc.c (revision 22df390c30710ddd2119f3e7bb6c92dc399cabb9)
13e12c5d1SDavid du Colombier /*
23e12c5d1SDavid du Colombier  * pANS stdio -- _IO_putc, _IO_cleanup
33e12c5d1SDavid du Colombier  */
43e12c5d1SDavid du Colombier #include "iolib.h"
_IO_cleanup(void)53e12c5d1SDavid du Colombier void _IO_cleanup(void){
63e12c5d1SDavid du Colombier 	fflush(NULL);
73e12c5d1SDavid du Colombier }
83e12c5d1SDavid du Colombier /*
93e12c5d1SDavid du Colombier  * Look this over for simplification
103e12c5d1SDavid du Colombier  */
_IO_putc(int c,FILE * f)113e12c5d1SDavid du Colombier int _IO_putc(int c, FILE *f){
123e12c5d1SDavid du Colombier 	int cnt;
133e12c5d1SDavid du Colombier 	static int first=1;
143e12c5d1SDavid du Colombier 	switch(f->state){
153e12c5d1SDavid du Colombier 	case RD:
163e12c5d1SDavid du Colombier 		f->state=ERR;
173e12c5d1SDavid du Colombier 	case ERR:
183e12c5d1SDavid du Colombier 	case CLOSED:
193e12c5d1SDavid du Colombier 		return EOF;
203e12c5d1SDavid du Colombier 	case OPEN:
213e12c5d1SDavid du Colombier 		_IO_setvbuf(f);
223e12c5d1SDavid du Colombier 		/* fall through */
233e12c5d1SDavid du Colombier 	case RDWR:
243e12c5d1SDavid du Colombier 	case END:
253e12c5d1SDavid du Colombier 		f->rp=f->buf+f->bufl;
263e12c5d1SDavid du Colombier 		if(f->flags&LINEBUF){
273e12c5d1SDavid du Colombier 			f->wp=f->rp;
283e12c5d1SDavid du Colombier 			f->lp=f->buf;
293e12c5d1SDavid du Colombier 		}
303e12c5d1SDavid du Colombier 		else
313e12c5d1SDavid du Colombier 			f->wp=f->buf;
323e12c5d1SDavid du Colombier 		break;
333e12c5d1SDavid du Colombier 	}
343e12c5d1SDavid du Colombier 	if(first){
353e12c5d1SDavid du Colombier 		atexit(_IO_cleanup);
363e12c5d1SDavid du Colombier 		first=0;
373e12c5d1SDavid du Colombier 	}
383e12c5d1SDavid du Colombier 	if(f->flags&STRING){
393e12c5d1SDavid du Colombier 		f->rp=f->buf+f->bufl;
403e12c5d1SDavid du Colombier 		if(f->wp==f->rp){
413e12c5d1SDavid du Colombier 			if(f->flags&BALLOC)
423e12c5d1SDavid du Colombier 				f->buf=realloc(f->buf, f->bufl+BUFSIZ);
433e12c5d1SDavid du Colombier 			else{
443e12c5d1SDavid du Colombier 				f->state=ERR;
453e12c5d1SDavid du Colombier 				return EOF;
463e12c5d1SDavid du Colombier 			}
473e12c5d1SDavid du Colombier 			if(f->buf==NULL){
483e12c5d1SDavid du Colombier 				f->state=ERR;
493e12c5d1SDavid du Colombier 				return EOF;
503e12c5d1SDavid du Colombier 			}
513e12c5d1SDavid du Colombier 			f->rp=f->buf+f->bufl;
523e12c5d1SDavid du Colombier 			f->bufl+=BUFSIZ;
533e12c5d1SDavid du Colombier 		}
543e12c5d1SDavid du Colombier 		*f->wp++=c;
553e12c5d1SDavid du Colombier 	}
563e12c5d1SDavid du Colombier 	else if(f->flags&LINEBUF){
573e12c5d1SDavid du Colombier 		if(f->lp==f->rp){
583e12c5d1SDavid du Colombier 			cnt=f->lp-f->buf;
59*22df390cSDavid du Colombier 			if(f->flags&APPEND) seek(f->fd, 0, SEEK_END);
603e12c5d1SDavid du Colombier 			if(cnt!=0 && write(f->fd, f->buf, cnt)!=cnt){
613e12c5d1SDavid du Colombier 				f->state=ERR;
623e12c5d1SDavid du Colombier 				return EOF;
633e12c5d1SDavid du Colombier 			}
643e12c5d1SDavid du Colombier 			f->lp=f->buf;
653e12c5d1SDavid du Colombier 		}
663e12c5d1SDavid du Colombier 		*f->lp++=c;
673e12c5d1SDavid du Colombier 		if(c=='\n'){
683e12c5d1SDavid du Colombier 			cnt=f->lp-f->buf;
69*22df390cSDavid du Colombier 			if(f->flags&APPEND) seek(f->fd, 0, SEEK_END);
703e12c5d1SDavid du Colombier 			if(cnt!=0 && write(f->fd, f->buf, cnt)!=cnt){
713e12c5d1SDavid du Colombier 				f->state=ERR;
723e12c5d1SDavid du Colombier 				return EOF;
733e12c5d1SDavid du Colombier 			}
743e12c5d1SDavid du Colombier 			f->lp=f->buf;
753e12c5d1SDavid du Colombier 		}
763e12c5d1SDavid du Colombier 	}
773e12c5d1SDavid du Colombier 	else if(f->buf==f->unbuf){
783e12c5d1SDavid du Colombier 		f->unbuf[0]=c;
79*22df390cSDavid du Colombier 		if(f->flags&APPEND) seek(f->fd, 0, SEEK_END);
803e12c5d1SDavid du Colombier 		if(write(f->fd, f->buf, 1)!=1){
813e12c5d1SDavid du Colombier 			f->state=ERR;
823e12c5d1SDavid du Colombier 			return EOF;
833e12c5d1SDavid du Colombier 		}
843e12c5d1SDavid du Colombier 	}
853e12c5d1SDavid du Colombier 	else{
863e12c5d1SDavid du Colombier 		if(f->wp==f->rp){
873e12c5d1SDavid du Colombier 			cnt=f->wp-f->buf;
88*22df390cSDavid du Colombier 			if(f->flags&APPEND) seek(f->fd, 0, SEEK_END);
893e12c5d1SDavid du Colombier 			if(cnt!=0 && write(f->fd, f->buf, cnt)!=cnt){
903e12c5d1SDavid du Colombier 				f->state=ERR;
913e12c5d1SDavid du Colombier 				return EOF;
923e12c5d1SDavid du Colombier 			}
933e12c5d1SDavid du Colombier 			f->wp=f->buf;
943e12c5d1SDavid du Colombier 			f->rp=f->buf+f->bufl;
953e12c5d1SDavid du Colombier 		}
963e12c5d1SDavid du Colombier 		*f->wp++=c;
973e12c5d1SDavid du Colombier 	}
983e12c5d1SDavid du Colombier 	f->state=WR;
993e12c5d1SDavid du Colombier 	/*
1003e12c5d1SDavid du Colombier 	 * Make sure EOF looks different from putc(-1)
1013e12c5d1SDavid du Colombier 	 * Should be able to cast to unsigned char, but
1023e12c5d1SDavid du Colombier 	 * there's a vc bug preventing that from working
1033e12c5d1SDavid du Colombier 	 */
1043e12c5d1SDavid du Colombier 	return c&0xff;
1053e12c5d1SDavid du Colombier }
106