xref: /plan9/sys/src/cmd/rc/io.c (revision 85497287b283897cd1b6b9861082a5ae80fadd80)
1 #include "rc.h"
2 #include "exec.h"
3 #include "io.h"
4 #include "fns.h"
5 
6 enum { Stralloc = 100, };
7 
8 int pfmtnest = 0;
9 
10 void
pfmt(io * f,char * fmt,...)11 pfmt(io *f, char *fmt, ...)
12 {
13 	va_list ap;
14 	char err[ERRMAX];
15 
16 	va_start(ap, fmt);
17 	pfmtnest++;
18 	for(;*fmt;fmt++) {
19 		if(*fmt!='%') {
20 			pchr(f, *fmt);
21 			continue;
22 		}
23 		if(*++fmt == '\0')		/* "blah%"? */
24 			break;
25 		switch(*fmt){
26 		case 'c':
27 			pchr(f, va_arg(ap, int));
28 			break;
29 		case 'd':
30 			pdec(f, va_arg(ap, int));
31 			break;
32 		case 'o':
33 			poct(f, va_arg(ap, unsigned));
34 			break;
35 		case 'p':
36 			pptr(f, va_arg(ap, void*));
37 			break;
38 		case 'Q':
39 			pquo(f, va_arg(ap, char *));
40 			break;
41 		case 'q':
42 			pwrd(f, va_arg(ap, char *));
43 			break;
44 		case 'r':
45 			errstr(err, sizeof err); pstr(f, err);
46 			break;
47 		case 's':
48 			pstr(f, va_arg(ap, char *));
49 			break;
50 		case 't':
51 			pcmd(f, va_arg(ap, struct tree *));
52 			break;
53 		case 'v':
54 			pval(f, va_arg(ap, struct word *));
55 			break;
56 		default:
57 			pchr(f, *fmt);
58 			break;
59 		}
60 	}
61 	va_end(ap);
62 	if(--pfmtnest==0)
63 		flush(f);
64 }
65 
66 void
pchr(io * b,int c)67 pchr(io *b, int c)
68 {
69 	if(b->bufp==b->ebuf)
70 		fullbuf(b, c);
71 	else *b->bufp++=c;
72 }
73 
74 int
rchr(io * b)75 rchr(io *b)
76 {
77 	if(b->bufp==b->ebuf)
78 		return emptybuf(b);
79 	return *b->bufp++;
80 }
81 
82 int
rutf(io * b,char * buf,Rune * r)83 rutf(io *b, char *buf, Rune *r)
84 {
85 	int n, i, c;
86 
87 	c = rchr(b);
88 	if(c == EOF)
89 		return EOF;
90 	*buf = c;
91 	if(c < Runesync){
92 		*r = c;
93 		return 1;
94 	}
95 	for(i = 1; (c = rchr(b)) != EOF; ){
96 		buf[i++] = c;
97 		buf[i] = 0;
98 		if(fullrune(buf, i)){
99 			n = chartorune(r, buf);
100 			b->bufp -= i - n;	/* push back unconsumed bytes */
101 			assert(b->fd == -1 || b->bufp > b->buf);
102 			return n;
103 		}
104 	}
105 	/* at eof */
106 	b->bufp -= i - 1;			/* consume 1 byte */
107 	*r = Runeerror;
108 	return runetochar(buf, r);
109 }
110 
111 void
pquo(io * f,char * s)112 pquo(io *f, char *s)
113 {
114 	pchr(f, '\'');
115 	for(;*s;s++)
116 		if(*s=='\'')
117 			pfmt(f, "''");
118 		else pchr(f, *s);
119 	pchr(f, '\'');
120 }
121 
122 void
pwrd(io * f,char * s)123 pwrd(io *f, char *s)
124 {
125 	char *t;
126 	for(t = s;*t;t++) if(*t >= 0 && needsrcquote(*t)) break;
127 	if(t==s || *t)
128 		pquo(f, s);
129 	else pstr(f, s);
130 }
131 
132 void
pptr(io * f,void * v)133 pptr(io *f, void *v)
134 {
135 	int n;
136 	uintptr p;
137 
138 	p = (uintptr)v;
139 	if(sizeof(uintptr) == sizeof(uvlong) && p>>32)
140 		for(n = 60;n>=32;n-=4) pchr(f, "0123456789ABCDEF"[(p>>n)&0xF]);
141 
142 	for(n = 28;n>=0;n-=4) pchr(f, "0123456789ABCDEF"[(p>>n)&0xF]);
143 }
144 
145 void
pstr(io * f,char * s)146 pstr(io *f, char *s)
147 {
148 	if(s==0)
149 		s="(null)";
150 	while(*s) pchr(f, *s++);
151 }
152 
153 void
pdec(io * f,int n)154 pdec(io *f, int n)
155 {
156 	if(n<0){
157 		n=-n;
158 		if(n>=0){
159 			pchr(f, '-');
160 			pdec(f, n);
161 			return;
162 		}
163 		/* n is two's complement minimum integer */
164 		n = 1-n;
165 		pchr(f, '-');
166 		pdec(f, n/10);
167 		pchr(f, n%10+'1');
168 		return;
169 	}
170 	if(n>9)
171 		pdec(f, n/10);
172 	pchr(f, n%10+'0');
173 }
174 
175 void
poct(io * f,unsigned n)176 poct(io *f, unsigned n)
177 {
178 	if(n>7)
179 		poct(f, n>>3);
180 	pchr(f, (n&7)+'0');
181 }
182 
183 void
pval(io * f,word * a)184 pval(io *f, word *a)
185 {
186 	if(a){
187 		while(a->next && a->next->word){
188 			pwrd(f, (char *)a->word);
189 			pchr(f, ' ');
190 			a = a->next;
191 		}
192 		pwrd(f, (char *)a->word);
193 	}
194 }
195 
196 int
fullbuf(io * f,int c)197 fullbuf(io *f, int c)
198 {
199 	flush(f);
200 	return *f->bufp++=c;
201 }
202 
203 void
flush(io * f)204 flush(io *f)
205 {
206 	int n;
207 
208 	if(f->strp){
209 		n = f->ebuf - f->strp;
210 		f->strp = realloc(f->strp, n+Stralloc+1);
211 		if(f->strp==0)
212 			panic("Can't realloc %d bytes in flush!", n+Stralloc+1);
213 		f->bufp = f->strp + n;
214 		f->ebuf = f->bufp + Stralloc;
215 		memset(f->bufp, '\0', Stralloc+1);
216 	}
217 	else{
218 		n = f->bufp-f->buf;
219 		if(n && Write(f->fd, f->buf, n) != n){
220 			Write(2, "Write error\n", 12);
221 			if(ntrap)
222 				dotrap();
223 		}
224 		f->bufp = f->buf;
225 		f->ebuf = f->buf+NBUF;
226 	}
227 }
228 
229 io*
openfd(int fd)230 openfd(int fd)
231 {
232 	io *f = new(struct io);
233 	f->fd = fd;
234 	f->bufp = f->ebuf = f->buf;
235 	f->strp = 0;
236 	return f;
237 }
238 
239 io*
openstr(void)240 openstr(void)
241 {
242 	io *f = new(struct io);
243 
244 	f->fd = -1;
245 	f->bufp = f->strp = emalloc(Stralloc+1);
246 	f->ebuf = f->bufp + Stralloc;
247 	memset(f->bufp, '\0', Stralloc+1);
248 	return f;
249 }
250 /*
251  * Open a corebuffer to read.  EOF occurs after reading len
252  * characters from buf.
253  */
254 
255 io*
opencore(char * s,int len)256 opencore(char *s, int len)
257 {
258 	io *f = new(struct io);
259 	uchar *buf = emalloc(len);
260 
261 	f->fd = -1 /*open("/dev/null", 0)*/;
262 	f->bufp = f->strp = buf;
263 	f->ebuf = buf+len;
264 	Memcpy(buf, s, len);
265 	return f;
266 }
267 
268 void
rewind(io * io)269 rewind(io *io)
270 {
271 	if(io->fd==-1)
272 		io->bufp = io->strp;
273 	else{
274 		io->bufp = io->ebuf = io->buf;
275 		Seek(io->fd, 0L, 0);
276 	}
277 }
278 
279 void
closeio(io * io)280 closeio(io *io)
281 {
282 	if(io->fd>=0)
283 		close(io->fd);
284 	if(io->strp)
285 		efree(io->strp);
286 	efree(io);
287 }
288 
289 int
emptybuf(io * f)290 emptybuf(io *f)
291 {
292 	int n;
293 	if(f->fd==-1 || (n = Read(f->fd, f->buf, NBUF))<=0) return EOF;
294 	f->bufp = f->buf;
295 	f->ebuf = f->buf + n;
296 	return *f->bufp++;
297 }
298