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