xref: /plan9/sys/src/libstdio/_IO_putc.c (revision 3e12c5d1bb89fc02707907988834ef147769ddaf)
1*3e12c5d1SDavid du Colombier /*
2*3e12c5d1SDavid du Colombier  * pANS stdio -- _IO_putc, _IO_cleanup
3*3e12c5d1SDavid du Colombier  */
4*3e12c5d1SDavid du Colombier #include "iolib.h"
_IO_cleanup(void)5*3e12c5d1SDavid du Colombier void _IO_cleanup(void){
6*3e12c5d1SDavid du Colombier 	fflush(NULL);
7*3e12c5d1SDavid du Colombier }
8*3e12c5d1SDavid du Colombier /*
9*3e12c5d1SDavid du Colombier  * Look this over for simplification
10*3e12c5d1SDavid du Colombier  */
_IO_putc(int c,FILE * f)11*3e12c5d1SDavid du Colombier int _IO_putc(int c, FILE *f){
12*3e12c5d1SDavid du Colombier 	int cnt;
13*3e12c5d1SDavid du Colombier 	static int first=1;
14*3e12c5d1SDavid du Colombier 	switch(f->state){
15*3e12c5d1SDavid du Colombier 	case RD:
16*3e12c5d1SDavid du Colombier 		f->state=ERR;
17*3e12c5d1SDavid du Colombier 	case ERR:
18*3e12c5d1SDavid du Colombier 	case CLOSED:
19*3e12c5d1SDavid du Colombier 		return EOF;
20*3e12c5d1SDavid du Colombier 	case OPEN:
21*3e12c5d1SDavid du Colombier 		_IO_setvbuf(f);
22*3e12c5d1SDavid du Colombier 		/* fall through */
23*3e12c5d1SDavid du Colombier 	case RDWR:
24*3e12c5d1SDavid du Colombier 	case END:
25*3e12c5d1SDavid du Colombier 		f->rp=f->buf+f->bufl;
26*3e12c5d1SDavid du Colombier 		if(f->flags&LINEBUF){
27*3e12c5d1SDavid du Colombier 			f->wp=f->rp;
28*3e12c5d1SDavid du Colombier 			f->lp=f->buf;
29*3e12c5d1SDavid du Colombier 		}
30*3e12c5d1SDavid du Colombier 		else
31*3e12c5d1SDavid du Colombier 			f->wp=f->buf;
32*3e12c5d1SDavid du Colombier 		break;
33*3e12c5d1SDavid du Colombier 	}
34*3e12c5d1SDavid du Colombier 	if(first){
35*3e12c5d1SDavid du Colombier 		atexit(_IO_cleanup);
36*3e12c5d1SDavid du Colombier 		first=0;
37*3e12c5d1SDavid du Colombier 	}
38*3e12c5d1SDavid du Colombier 	if(f->flags&STRING){
39*3e12c5d1SDavid du Colombier 		f->rp=f->buf+f->bufl;
40*3e12c5d1SDavid du Colombier 		if(f->wp==f->rp){
41*3e12c5d1SDavid du Colombier 			if(f->flags&BALLOC)
42*3e12c5d1SDavid du Colombier 				f->buf=realloc(f->buf, f->bufl+BUFSIZ);
43*3e12c5d1SDavid du Colombier 			else{
44*3e12c5d1SDavid du Colombier 				f->state=ERR;
45*3e12c5d1SDavid du Colombier 				return EOF;
46*3e12c5d1SDavid du Colombier 			}
47*3e12c5d1SDavid du Colombier 			if(f->buf==NULL){
48*3e12c5d1SDavid du Colombier 				f->state=ERR;
49*3e12c5d1SDavid du Colombier 				return EOF;
50*3e12c5d1SDavid du Colombier 			}
51*3e12c5d1SDavid du Colombier 			f->rp=f->buf+f->bufl;
52*3e12c5d1SDavid du Colombier 			f->bufl+=BUFSIZ;
53*3e12c5d1SDavid du Colombier 		}
54*3e12c5d1SDavid du Colombier 		*f->wp++=c;
55*3e12c5d1SDavid du Colombier 	}
56*3e12c5d1SDavid du Colombier 	else if(f->flags&LINEBUF){
57*3e12c5d1SDavid du Colombier 		if(f->lp==f->rp){
58*3e12c5d1SDavid du Colombier 			cnt=f->lp-f->buf;
59*3e12c5d1SDavid du Colombier 			if(f->flags&APPEND) seek(f->fd, 0L, 2);
60*3e12c5d1SDavid du Colombier 			if(cnt!=0 && write(f->fd, f->buf, cnt)!=cnt){
61*3e12c5d1SDavid du Colombier 				f->state=ERR;
62*3e12c5d1SDavid du Colombier 				return EOF;
63*3e12c5d1SDavid du Colombier 			}
64*3e12c5d1SDavid du Colombier 			f->lp=f->buf;
65*3e12c5d1SDavid du Colombier 		}
66*3e12c5d1SDavid du Colombier 		*f->lp++=c;
67*3e12c5d1SDavid du Colombier 		if(c=='\n'){
68*3e12c5d1SDavid du Colombier 			cnt=f->lp-f->buf;
69*3e12c5d1SDavid du Colombier 			if(f->flags&APPEND) seek(f->fd, 0L, 2);
70*3e12c5d1SDavid du Colombier 			if(cnt!=0 && write(f->fd, f->buf, cnt)!=cnt){
71*3e12c5d1SDavid du Colombier 				f->state=ERR;
72*3e12c5d1SDavid du Colombier 				return EOF;
73*3e12c5d1SDavid du Colombier 			}
74*3e12c5d1SDavid du Colombier 			f->lp=f->buf;
75*3e12c5d1SDavid du Colombier 		}
76*3e12c5d1SDavid du Colombier 	}
77*3e12c5d1SDavid du Colombier 	else if(f->buf==f->unbuf){
78*3e12c5d1SDavid du Colombier 		f->unbuf[0]=c;
79*3e12c5d1SDavid du Colombier 		if(f->flags&APPEND) seek(f->fd, 0L, 2);
80*3e12c5d1SDavid du Colombier 		if(write(f->fd, f->buf, 1)!=1){
81*3e12c5d1SDavid du Colombier 			f->state=ERR;
82*3e12c5d1SDavid du Colombier 			return EOF;
83*3e12c5d1SDavid du Colombier 		}
84*3e12c5d1SDavid du Colombier 	}
85*3e12c5d1SDavid du Colombier 	else{
86*3e12c5d1SDavid du Colombier 		if(f->wp==f->rp){
87*3e12c5d1SDavid du Colombier 			cnt=f->wp-f->buf;
88*3e12c5d1SDavid du Colombier 			if(f->flags&APPEND) seek(f->fd, 0L, 2);
89*3e12c5d1SDavid du Colombier 			if(cnt!=0 && write(f->fd, f->buf, cnt)!=cnt){
90*3e12c5d1SDavid du Colombier 				f->state=ERR;
91*3e12c5d1SDavid du Colombier 				return EOF;
92*3e12c5d1SDavid du Colombier 			}
93*3e12c5d1SDavid du Colombier 			f->wp=f->buf;
94*3e12c5d1SDavid du Colombier 			f->rp=f->buf+f->bufl;
95*3e12c5d1SDavid du Colombier 		}
96*3e12c5d1SDavid du Colombier 		*f->wp++=c;
97*3e12c5d1SDavid du Colombier 	}
98*3e12c5d1SDavid du Colombier 	f->state=WR;
99*3e12c5d1SDavid du Colombier 	/*
100*3e12c5d1SDavid du Colombier 	 * Make sure EOF looks different from putc(-1)
101*3e12c5d1SDavid du Colombier 	 * Should be able to cast to unsigned char, but
102*3e12c5d1SDavid du Colombier 	 * there's a vc bug preventing that from working
103*3e12c5d1SDavid du Colombier 	 */
104*3e12c5d1SDavid du Colombier 	return c&0xff;
105*3e12c5d1SDavid du Colombier }
106