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