xref: /plan9-contrib/sys/src/cmd/rc/io.c (revision c6df144405f586b73992827d584728dc975dff14)
13e12c5d1SDavid du Colombier #include "rc.h"
23e12c5d1SDavid du Colombier #include "exec.h"
33e12c5d1SDavid du Colombier #include "io.h"
43e12c5d1SDavid du Colombier #include "fns.h"
5276e7d6dSDavid du Colombier 
6276e7d6dSDavid du Colombier enum { Stralloc = 100, };
7276e7d6dSDavid du Colombier 
83e12c5d1SDavid du Colombier int pfmtnest = 0;
9dc5a79c1SDavid du Colombier 
10dc5a79c1SDavid du Colombier void
pfmt(io * f,char * fmt,...)11dc5a79c1SDavid du Colombier pfmt(io *f, char *fmt, ...)
12dc5a79c1SDavid du Colombier {
133e12c5d1SDavid du Colombier 	va_list ap;
149a747e4fSDavid du Colombier 	char err[ERRMAX];
15fbd2c77cSDavid du Colombier 
163e12c5d1SDavid du Colombier 	va_start(ap, fmt);
173e12c5d1SDavid du Colombier 	pfmtnest++;
18fbd2c77cSDavid du Colombier 	for(;*fmt;fmt++) {
19fbd2c77cSDavid du Colombier 		if(*fmt!='%') {
20dc5a79c1SDavid du Colombier 			pchr(f, *fmt);
21fbd2c77cSDavid du Colombier 			continue;
22fbd2c77cSDavid du Colombier 		}
23fbd2c77cSDavid du Colombier 		if(*++fmt == '\0')		/* "blah%"? */
24fbd2c77cSDavid du Colombier 			break;
25fbd2c77cSDavid du Colombier 		switch(*fmt){
26*c6df1444SDavid du Colombier 		case 'c':			/* char, not Rune */
27dc5a79c1SDavid du Colombier 			pchr(f, va_arg(ap, int));
28dc5a79c1SDavid du Colombier 			break;
29dc5a79c1SDavid du Colombier 		case 'd':
30dc5a79c1SDavid du Colombier 			pdec(f, va_arg(ap, int));
31dc5a79c1SDavid du Colombier 			break;
32dc5a79c1SDavid du Colombier 		case 'o':
33dc5a79c1SDavid du Colombier 			poct(f, va_arg(ap, unsigned));
34dc5a79c1SDavid du Colombier 			break;
35dc5a79c1SDavid du Colombier 		case 'p':
3673e742d7SDavid du Colombier 			pptr(f, va_arg(ap, void*));
3773e742d7SDavid du Colombier 			break;
38dc5a79c1SDavid du Colombier 		case 'Q':
39dc5a79c1SDavid du Colombier 			pquo(f, va_arg(ap, char *));
40dc5a79c1SDavid du Colombier 			break;
41dc5a79c1SDavid du Colombier 		case 'q':
42dc5a79c1SDavid du Colombier 			pwrd(f, va_arg(ap, char *));
43dc5a79c1SDavid du Colombier 			break;
44dc5a79c1SDavid du Colombier 		case 'r':
45dc5a79c1SDavid du Colombier 			errstr(err, sizeof err); pstr(f, err);
46dc5a79c1SDavid du Colombier 			break;
47dc5a79c1SDavid du Colombier 		case 's':
48dc5a79c1SDavid du Colombier 			pstr(f, va_arg(ap, char *));
49dc5a79c1SDavid du Colombier 			break;
50dc5a79c1SDavid du Colombier 		case 't':
51dc5a79c1SDavid du Colombier 			pcmd(f, va_arg(ap, struct tree *));
52dc5a79c1SDavid du Colombier 			break;
53dc5a79c1SDavid du Colombier 		case 'v':
54dc5a79c1SDavid du Colombier 			pval(f, va_arg(ap, struct word *));
55dc5a79c1SDavid du Colombier 			break;
56dc5a79c1SDavid du Colombier 		default:
57dc5a79c1SDavid du Colombier 			pchr(f, *fmt);
58dc5a79c1SDavid du Colombier 			break;
593e12c5d1SDavid du Colombier 		}
60fbd2c77cSDavid du Colombier 	}
613e12c5d1SDavid du Colombier 	va_end(ap);
62dc5a79c1SDavid du Colombier 	if(--pfmtnest==0)
63dc5a79c1SDavid du Colombier 		flush(f);
643e12c5d1SDavid du Colombier }
65dc5a79c1SDavid du Colombier 
66dc5a79c1SDavid du Colombier void
pchr(io * b,int c)67*c6df1444SDavid du Colombier pchr(io *b, int c)			/* print a char, not a Rune */
687dd7cddfSDavid du Colombier {
69dc5a79c1SDavid du Colombier 	if(b->bufp==b->ebuf)
70dc5a79c1SDavid du Colombier 		fullbuf(b, c);
7199eb86a7SDavid du Colombier 	else *b->bufp++=c;
727dd7cddfSDavid du Colombier }
73dc5a79c1SDavid du Colombier 
74dc5a79c1SDavid du Colombier int
rchr(io * b)75dc5a79c1SDavid du Colombier rchr(io *b)
767dd7cddfSDavid du Colombier {
77dc5a79c1SDavid du Colombier 	if(b->bufp==b->ebuf)
78dc5a79c1SDavid du Colombier 		return emptybuf(b);
79276e7d6dSDavid du Colombier 	return *b->bufp++;
807dd7cddfSDavid du Colombier }
81dc5a79c1SDavid du Colombier 
82*c6df1444SDavid du Colombier /*
83*c6df1444SDavid du Colombier  * read next utf sequence from b into buf, and convert it to Rune *r.
84*c6df1444SDavid du Colombier  * return EOF or number of bytes consumed.
85*c6df1444SDavid du Colombier  */
8685497287SDavid du Colombier int
rutf(io * b,char * buf,Rune * r)8785497287SDavid du Colombier rutf(io *b, char *buf, Rune *r)
8885497287SDavid du Colombier {
89*c6df1444SDavid du Colombier 	int i, c;
9085497287SDavid du Colombier 
9185497287SDavid du Colombier 	c = rchr(b);
92*c6df1444SDavid du Colombier 	if(c == EOF) {
93*c6df1444SDavid du Colombier 		buf[0] = 0;
94*c6df1444SDavid du Colombier 		*r = EOF;
9585497287SDavid du Colombier 		return EOF;
96*c6df1444SDavid du Colombier 	}
9785497287SDavid du Colombier 	*buf = c;
98*c6df1444SDavid du Colombier 	if(c < Runeself){			/* ascii? */
99*c6df1444SDavid du Colombier 		buf[1] = 0;
10085497287SDavid du Colombier 		*r = c;
10185497287SDavid du Colombier 		return 1;
10285497287SDavid du Colombier 	}
103*c6df1444SDavid du Colombier 
104*c6df1444SDavid du Colombier 	/* multi-byte utf sequence */
105*c6df1444SDavid du Colombier 	for(i = 1; i <= UTFmax && (c = rchr(b)) != EOF && c >= Runeself; ){
10685497287SDavid du Colombier 		buf[i++] = c;
10785497287SDavid du Colombier 		buf[i] = 0;
108*c6df1444SDavid du Colombier 		if(fullrune(buf, i))
109*c6df1444SDavid du Colombier 			return chartorune(r, buf);
11085497287SDavid du Colombier 	}
111*c6df1444SDavid du Colombier 
112*c6df1444SDavid du Colombier 	/* bad utf sequence: too long, or unexpected ascii or EOF */
113*c6df1444SDavid du Colombier 	if (c != EOF && c < Runeself && b->bufp > b->buf)
114*c6df1444SDavid du Colombier 		b->bufp--;			/* push back ascii */
11585497287SDavid du Colombier 	*r = Runeerror;
11685497287SDavid du Colombier 	return runetochar(buf, r);
11785497287SDavid du Colombier }
11885497287SDavid du Colombier 
119dc5a79c1SDavid du Colombier void
pquo(io * f,char * s)120dc5a79c1SDavid du Colombier pquo(io *f, char *s)
1213e12c5d1SDavid du Colombier {
1223e12c5d1SDavid du Colombier 	pchr(f, '\'');
1233e12c5d1SDavid du Colombier 	for(;*s;s++)
124dc5a79c1SDavid du Colombier 		if(*s=='\'')
125dc5a79c1SDavid du Colombier 			pfmt(f, "''");
12699eb86a7SDavid du Colombier 		else pchr(f, *s);
1273e12c5d1SDavid du Colombier 	pchr(f, '\'');
1283e12c5d1SDavid du Colombier }
129dc5a79c1SDavid du Colombier 
130dc5a79c1SDavid du Colombier void
pwrd(io * f,char * s)131dc5a79c1SDavid du Colombier pwrd(io *f, char *s)
1323e12c5d1SDavid du Colombier {
1333e12c5d1SDavid du Colombier 	char *t;
134*c6df1444SDavid du Colombier 
135*c6df1444SDavid du Colombier 	for (t = s; *t; t++)
136*c6df1444SDavid du Colombier 		if (*(uchar *)t < Runeself && needsrcquote(*t))
137*c6df1444SDavid du Colombier 			break;
138dc5a79c1SDavid du Colombier 	if (t == s || *t)
139dc5a79c1SDavid du Colombier 		pquo(f, s);
140*c6df1444SDavid du Colombier 	else
141*c6df1444SDavid du Colombier 		pstr(f, s);
1423e12c5d1SDavid du Colombier }
143dc5a79c1SDavid du Colombier 
144dc5a79c1SDavid du Colombier void
pptr(io * f,void * v)14573e742d7SDavid du Colombier pptr(io *f, void *v)
1463e12c5d1SDavid du Colombier {
1473e12c5d1SDavid du Colombier 	int n;
14873e742d7SDavid du Colombier 	uintptr p;
149*c6df1444SDavid du Colombier 	static char uphex[] = "0123456789ABCDEF";
15073e742d7SDavid du Colombier 
15173e742d7SDavid du Colombier 	p = (uintptr)v;
15273e742d7SDavid du Colombier 	if (sizeof(uintptr) == sizeof(uvlong) && p >> 32)
153*c6df1444SDavid du Colombier 		for (n = 60; n >= 32; n -= 4)
154*c6df1444SDavid du Colombier 			pchr(f, uphex[(p>>n)&0xF]);
155*c6df1444SDavid du Colombier 	for (n = 28; n >= 0; n -= 4)
156*c6df1444SDavid du Colombier 		pchr(f, uphex[(p>>n)&0xF]);
1573e12c5d1SDavid du Colombier }
158dc5a79c1SDavid du Colombier 
159dc5a79c1SDavid du Colombier void
pstr(io * f,char * s)160dc5a79c1SDavid du Colombier pstr(io *f, char *s)
1613e12c5d1SDavid du Colombier {
162dc5a79c1SDavid du Colombier 	if(s==0)
163dc5a79c1SDavid du Colombier 		s="(null)";
16499eb86a7SDavid du Colombier 	while(*s) pchr(f, *s++);
1653e12c5d1SDavid du Colombier }
166dc5a79c1SDavid du Colombier 
167dc5a79c1SDavid du Colombier void
pdec(io * f,int n)16873e742d7SDavid du Colombier pdec(io *f, int n)
1693e12c5d1SDavid du Colombier {
1703e12c5d1SDavid du Colombier 	if(n<0){
1713e12c5d1SDavid du Colombier 		n=-n;
1723e12c5d1SDavid du Colombier 		if(n>=0){
1733e12c5d1SDavid du Colombier 			pchr(f, '-');
1743e12c5d1SDavid du Colombier 			pdec(f, n);
1753e12c5d1SDavid du Colombier 			return;
1763e12c5d1SDavid du Colombier 		}
1773e12c5d1SDavid du Colombier 		/* n is two's complement minimum integer */
1783e12c5d1SDavid du Colombier 		n = 1-n;
1793e12c5d1SDavid du Colombier 		pchr(f, '-');
1803e12c5d1SDavid du Colombier 		pdec(f, n/10);
1813e12c5d1SDavid du Colombier 		pchr(f, n%10+'1');
1823e12c5d1SDavid du Colombier 		return;
1833e12c5d1SDavid du Colombier 	}
184dc5a79c1SDavid du Colombier 	if(n>9)
185dc5a79c1SDavid du Colombier 		pdec(f, n/10);
1863e12c5d1SDavid du Colombier 	pchr(f, n%10+'0');
1873e12c5d1SDavid du Colombier }
188dc5a79c1SDavid du Colombier 
189dc5a79c1SDavid du Colombier void
poct(io * f,unsigned n)19073e742d7SDavid du Colombier poct(io *f, unsigned n)
1913e12c5d1SDavid du Colombier {
192dc5a79c1SDavid du Colombier 	if(n>7)
193dc5a79c1SDavid du Colombier 		poct(f, n>>3);
1943e12c5d1SDavid du Colombier 	pchr(f, (n&7)+'0');
1953e12c5d1SDavid du Colombier }
196dc5a79c1SDavid du Colombier 
197dc5a79c1SDavid du Colombier void
pval(io * f,word * a)198dc5a79c1SDavid du Colombier pval(io *f, word *a)
1993e12c5d1SDavid du Colombier {
2003e12c5d1SDavid du Colombier 	if(a){
2013e12c5d1SDavid du Colombier 		while(a->next && a->next->word){
202276e7d6dSDavid du Colombier 			pwrd(f, (char *)a->word);
2033e12c5d1SDavid du Colombier 			pchr(f, ' ');
2043e12c5d1SDavid du Colombier 			a = a->next;
2053e12c5d1SDavid du Colombier 		}
206276e7d6dSDavid du Colombier 		pwrd(f, (char *)a->word);
2073e12c5d1SDavid du Colombier 	}
2083e12c5d1SDavid du Colombier }
209dc5a79c1SDavid du Colombier 
210dc5a79c1SDavid du Colombier int
fullbuf(io * f,int c)211dc5a79c1SDavid du Colombier fullbuf(io *f, int c)
2123e12c5d1SDavid du Colombier {
2133e12c5d1SDavid du Colombier 	flush(f);
2143e12c5d1SDavid du Colombier 	return *f->bufp++=c;
2153e12c5d1SDavid du Colombier }
216dc5a79c1SDavid du Colombier 
217dc5a79c1SDavid du Colombier void
flush(io * f)218dc5a79c1SDavid du Colombier flush(io *f)
2193e12c5d1SDavid du Colombier {
2203e12c5d1SDavid du Colombier 	int n;
221276e7d6dSDavid du Colombier 
2223e12c5d1SDavid du Colombier 	if(f->strp){
2233e12c5d1SDavid du Colombier 		n = f->ebuf - f->strp;
224276e7d6dSDavid du Colombier 		f->strp = realloc(f->strp, n+Stralloc+1);
225dc5a79c1SDavid du Colombier 		if(f->strp==0)
226276e7d6dSDavid du Colombier 			panic("Can't realloc %d bytes in flush!", n+Stralloc+1);
2273e12c5d1SDavid du Colombier 		f->bufp = f->strp + n;
228276e7d6dSDavid du Colombier 		f->ebuf = f->bufp + Stralloc;
229276e7d6dSDavid du Colombier 		memset(f->bufp, '\0', Stralloc+1);
2303e12c5d1SDavid du Colombier 	}
2313e12c5d1SDavid du Colombier 	else{
2323e12c5d1SDavid du Colombier 		n = f->bufp-f->buf;
233276e7d6dSDavid du Colombier 		if(n && Write(f->fd, f->buf, n) != n){
234276e7d6dSDavid du Colombier 			Write(2, "Write error\n", 12);
235dc5a79c1SDavid du Colombier 			if(ntrap)
236dc5a79c1SDavid du Colombier 				dotrap();
2373e12c5d1SDavid du Colombier 		}
2383e12c5d1SDavid du Colombier 		f->bufp = f->buf;
2393e12c5d1SDavid du Colombier 		f->ebuf = f->buf+NBUF;
2403e12c5d1SDavid du Colombier 	}
2413e12c5d1SDavid du Colombier }
242dc5a79c1SDavid du Colombier 
243dc5a79c1SDavid du Colombier io*
openfd(int fd)244dc5a79c1SDavid du Colombier openfd(int fd)
245dc5a79c1SDavid du Colombier {
2463e12c5d1SDavid du Colombier 	io *f = new(struct io);
2473e12c5d1SDavid du Colombier 	f->fd = fd;
2483e12c5d1SDavid du Colombier 	f->bufp = f->ebuf = f->buf;
2493e12c5d1SDavid du Colombier 	f->strp = 0;
2503e12c5d1SDavid du Colombier 	return f;
2513e12c5d1SDavid du Colombier }
252dc5a79c1SDavid du Colombier 
253dc5a79c1SDavid du Colombier io*
openstr(void)254dc5a79c1SDavid du Colombier openstr(void)
255dc5a79c1SDavid du Colombier {
2563e12c5d1SDavid du Colombier 	io *f = new(struct io);
257276e7d6dSDavid du Colombier 
2583e12c5d1SDavid du Colombier 	f->fd = -1;
259276e7d6dSDavid du Colombier 	f->bufp = f->strp = emalloc(Stralloc+1);
260276e7d6dSDavid du Colombier 	f->ebuf = f->bufp + Stralloc;
261*c6df1444SDavid du Colombier 	f->output = 1;
262276e7d6dSDavid du Colombier 	memset(f->bufp, '\0', Stralloc+1);
2633e12c5d1SDavid du Colombier 	return f;
2643e12c5d1SDavid du Colombier }
2653e12c5d1SDavid du Colombier /*
2663e12c5d1SDavid du Colombier  * Open a corebuffer to read.  EOF occurs after reading len
2673e12c5d1SDavid du Colombier  * characters from buf.
2683e12c5d1SDavid du Colombier  */
269dc5a79c1SDavid du Colombier 
270dc5a79c1SDavid du Colombier io*
opencore(char * s,int len)271dc5a79c1SDavid du Colombier opencore(char *s, int len)
2723e12c5d1SDavid du Colombier {
2733e12c5d1SDavid du Colombier 	io *f = new(struct io);
274276e7d6dSDavid du Colombier 	uchar *buf = emalloc(len);
275276e7d6dSDavid du Colombier 
2763e12c5d1SDavid du Colombier 	f->fd = -1 /*open("/dev/null", 0)*/;
2773e12c5d1SDavid du Colombier 	f->bufp = f->strp = buf;
2783e12c5d1SDavid du Colombier 	f->ebuf = buf+len;
279*c6df1444SDavid du Colombier 	f->output = 0;
2803e12c5d1SDavid du Colombier 	Memcpy(buf, s, len);
2813e12c5d1SDavid du Colombier 	return f;
2823e12c5d1SDavid du Colombier }
283dc5a79c1SDavid du Colombier 
284dc5a79c1SDavid du Colombier void
rewind(io * io)285dc5a79c1SDavid du Colombier rewind(io *io)
2863e12c5d1SDavid du Colombier {
287*c6df1444SDavid du Colombier 	if(io->fd==-1) {
288dc5a79c1SDavid du Colombier 		io->bufp = io->strp;
289*c6df1444SDavid du Colombier 		if (io->output)
290*c6df1444SDavid du Colombier 			memset(io->strp, 0, io->ebuf - io->strp);
291*c6df1444SDavid du Colombier 	}else{
2923e12c5d1SDavid du Colombier 		io->bufp = io->ebuf = io->buf;
293*c6df1444SDavid du Colombier 		seek(io->fd, 0, 0);
2943e12c5d1SDavid du Colombier 	}
2953e12c5d1SDavid du Colombier }
296dc5a79c1SDavid du Colombier 
297dc5a79c1SDavid du Colombier void
closeio(io * io)298dc5a79c1SDavid du Colombier closeio(io *io)
2993e12c5d1SDavid du Colombier {
300dc5a79c1SDavid du Colombier 	if(io->fd>=0)
301dc5a79c1SDavid du Colombier 		close(io->fd);
302dc5a79c1SDavid du Colombier 	if(io->strp)
303dc5a79c1SDavid du Colombier 		efree(io->strp);
304276e7d6dSDavid du Colombier 	efree(io);
3053e12c5d1SDavid du Colombier }
306dc5a79c1SDavid du Colombier 
307dc5a79c1SDavid du Colombier int
emptybuf(io * f)308dc5a79c1SDavid du Colombier emptybuf(io *f)
3093e12c5d1SDavid du Colombier {
3103e12c5d1SDavid du Colombier 	int n;
311*c6df1444SDavid du Colombier 
312*c6df1444SDavid du Colombier 	if(f->fd == -1 || (n = Read(f->fd, f->buf, NBUF))<=0)
313*c6df1444SDavid du Colombier 		return EOF;
3143e12c5d1SDavid du Colombier 	f->bufp = f->buf;
3153e12c5d1SDavid du Colombier 	f->ebuf = f->buf + n;
316276e7d6dSDavid du Colombier 	return *f->bufp++;
3173e12c5d1SDavid du Colombier }
318