xref: /plan9-contrib/sys/src/cmd/rc/io.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
1 #include "rc.h"
2 #include "exec.h"
3 #include "io.h"
4 #include "fns.h"
5 int pfmtnest=0;
6 void pfmt(io *f, char *fmt, ...){
7 	va_list ap;
8 	va_start(ap, fmt);
9 	pfmtnest++;
10 	for(;*fmt;fmt++)
11 		if(*fmt!='%') pchr(f, *fmt);
12 		else switch(*++fmt){
13 		case '\0': va_end(ap); return;
14 		case 'c': pchr(f, va_arg(ap, int)); break;
15 		case 'd': pdec(f, va_arg(ap, int)); break;
16 		case 'o': poct(f, va_arg(ap, unsigned)); break;
17 		case 'p': phex(f, (long)va_arg(ap, char *)); break; /*unportable*/
18 		case 'Q': pquo(f, va_arg(ap, char *)); break;
19 		case 'q': pwrd(f, va_arg(ap, char *)); break;
20 		case 's': pstr(f, va_arg(ap, char *)); break;
21 		case 't': pcmd(f, va_arg(ap, struct tree *)); break;
22 		case 'v': pval(f, va_arg(ap, struct word *)); break;
23 		default: pchr(f, *fmt); break;
24 		}
25 	va_end(ap);
26 	if(--pfmtnest==0) flush(f);
27 }
28 void pchr(io *b, int c)
29 {
30 	if(b->bufp==b->ebuf) fullbuf(b, c);
31 	else *b->bufp++=c;
32 }
33 int rchr(io *b)
34 {
35 	if(b->bufp==b->ebuf) return emptybuf(b);
36 	return *b->bufp++ & 0xFF;
37 }
38 void pquo(io *f, char *s)
39 {
40 	pchr(f, '\'');
41 	for(;*s;s++)
42 		if(*s=='\'') pfmt(f, "''");
43 		else pchr(f, *s);
44 	pchr(f, '\'');
45 }
46 void pwrd(io *f, char *s)
47 {
48 	char *t;
49 	for(t=s;*t;t++) if(!wordchr(*t)) break;
50 	if(t==s || *t) pquo(f, s);
51 	else pstr(f, s);
52 }
53 void phex(io *f, long p)
54 {
55 	int n;
56 	for(n=28;n>=0;n-=4) pchr(f, "0123456789ABCDEF"[(p>>n)&0xF]);
57 }
58 void pstr(io *f, char *s)
59 {
60 	if(s==0) s="(null)";
61 	while(*s) pchr(f, *s++);
62 }
63 void pdec(io *f, long n)
64 {
65 	if(n<0){
66 		n=-n;
67 		if(n>=0){
68 			pchr(f, '-');
69 			pdec(f, n);
70 			return;
71 		}
72 		/* n is two's complement minimum integer */
73 		n=1-n;
74 		pchr(f, '-');
75 		pdec(f, n/10);
76 		pchr(f, n%10+'1');
77 		return;
78 	}
79 	if(n>9) pdec(f, n/10);
80 	pchr(f, n%10+'0');
81 }
82 void poct(io *f, ulong n)
83 {
84 	if(n>7) poct(f, n>>3);
85 	pchr(f, (n&7)+'0');
86 }
87 void pval(io *f, word *a)
88 {
89 	if(a){
90 		while(a->next && a->next->word){
91 			pwrd(f, a->word);
92 			pchr(f, ' ');
93 			a=a->next;
94 		}
95 		pwrd(f, a->word);
96 	}
97 }
98 int fullbuf(io *f, int c)
99 {
100 	flush(f);
101 	return *f->bufp++=c;
102 }
103 void flush(io *f)
104 {
105 	int n;
106 	char *s;
107 	if(f->strp){
108 		n=f->ebuf-f->strp;
109 		f->strp=realloc(f->strp, n+101);
110 		if(f->strp==0) panic("Can't realloc %d bytes in flush!", n+101);
111 		f->bufp=f->strp+n;
112 		f->ebuf=f->bufp+100;
113 		for(s=f->bufp;s<=f->ebuf;s++) *s='\0';
114 	}
115 	else{
116 		n=f->bufp-f->buf;
117 		if(n && Write(f->fd, f->buf, n) < 0){
118 			Write(3, "Write error\n", 12);
119 			if(ntrap) dotrap();
120 		}
121 		f->bufp=f->buf;
122 		f->ebuf=f->buf+NBUF;
123 	}
124 }
125 io *openfd(int fd){
126 	io *f=new(struct io);
127 	f->fd=fd;
128 	f->bufp=f->ebuf=f->buf;
129 	f->strp=0;
130 	return f;
131 }
132 io *openstr(void){
133 	io *f=new(struct io);
134 	char *s;
135 	f->fd=-1;
136 	f->bufp=f->strp=emalloc(101);
137 	f->ebuf=f->bufp+100;
138 	for(s=f->bufp;s<=f->ebuf;s++) *s='\0';
139 	return f;
140 }
141 /*
142  * Open a corebuffer to read.  EOF occurs after reading len
143  * characters from buf.
144  */
145 io *opencore(char *s, int len)
146 {
147 	io *f=new(struct io);
148 	char *buf=emalloc(len);
149 	f->fd= -1 /*open("/dev/null", 0)*/;
150 	f->bufp=f->strp=buf;
151 	f->ebuf=buf+len;
152 	Memcpy(buf, s, len);
153 	return f;
154 }
155 void rewind(io *io)
156 {
157 	if(io->fd==-1) io->bufp=io->strp;
158 	else{
159 		io->bufp=io->ebuf=io->buf;
160 		Seek(io->fd, 0L, 0);
161 	}
162 }
163 void closeio(io *io)
164 {
165 	if(io->fd>=0) close(io->fd);
166 	if(io->strp) efree(io->strp);
167 	efree((char *)io);
168 }
169 int emptybuf(io *f)
170 {
171 	int n;
172 	if(f->fd==-1 || (n=Read(f->fd, f->buf, NBUF))<=0) return EOF;
173 	f->bufp=f->buf;
174 	f->ebuf=f->buf+n;
175 	return *f->bufp++&0xff;
176 }
177