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