xref: /plan9-contrib/sys/src/cmd/rc/io.c (revision 73e742d79f6b0cfc24f3b01d7ade790955db63c2)
13e12c5d1SDavid du Colombier #include "rc.h"
23e12c5d1SDavid du Colombier #include "exec.h"
33e12c5d1SDavid du Colombier #include "io.h"
43e12c5d1SDavid du Colombier #include "fns.h"
53e12c5d1SDavid du Colombier int pfmtnest = 0;
6dc5a79c1SDavid du Colombier 
7dc5a79c1SDavid du Colombier void
8dc5a79c1SDavid du Colombier pfmt(io *f, char *fmt, ...)
9dc5a79c1SDavid du Colombier {
103e12c5d1SDavid du Colombier 	va_list ap;
119a747e4fSDavid du Colombier 	char err[ERRMAX];
123e12c5d1SDavid du Colombier 	va_start(ap, fmt);
133e12c5d1SDavid du Colombier 	pfmtnest++;
143e12c5d1SDavid du Colombier 	for(;*fmt;fmt++)
15dc5a79c1SDavid du Colombier 		if(*fmt!='%')
16dc5a79c1SDavid du Colombier 			pchr(f, *fmt);
173e12c5d1SDavid du Colombier 		else switch(*++fmt){
18dc5a79c1SDavid du Colombier 		case '\0':
19dc5a79c1SDavid du Colombier 			va_end(ap);
20dc5a79c1SDavid du Colombier 			return;
21dc5a79c1SDavid du Colombier 		case 'c':
22dc5a79c1SDavid du Colombier 			pchr(f, va_arg(ap, int));
23dc5a79c1SDavid du Colombier 			break;
24dc5a79c1SDavid du Colombier 		case 'd':
25dc5a79c1SDavid du Colombier 			pdec(f, va_arg(ap, int));
26dc5a79c1SDavid du Colombier 			break;
27dc5a79c1SDavid du Colombier 		case 'o':
28dc5a79c1SDavid du Colombier 			poct(f, va_arg(ap, unsigned));
29dc5a79c1SDavid du Colombier 			break;
30dc5a79c1SDavid du Colombier 		case 'p':
31*73e742d7SDavid du Colombier 			pptr(f, va_arg(ap, void*));
32*73e742d7SDavid du Colombier 			break;
33dc5a79c1SDavid du Colombier 		case 'Q':
34dc5a79c1SDavid du Colombier 			pquo(f, va_arg(ap, char *));
35dc5a79c1SDavid du Colombier 			break;
36dc5a79c1SDavid du Colombier 		case 'q':
37dc5a79c1SDavid du Colombier 			pwrd(f, va_arg(ap, char *));
38dc5a79c1SDavid du Colombier 			break;
39dc5a79c1SDavid du Colombier 		case 'r':
40dc5a79c1SDavid du Colombier 			errstr(err, sizeof err); pstr(f, err);
41dc5a79c1SDavid du Colombier 			break;
42dc5a79c1SDavid du Colombier 		case 's':
43dc5a79c1SDavid du Colombier 			pstr(f, va_arg(ap, char *));
44dc5a79c1SDavid du Colombier 			break;
45dc5a79c1SDavid du Colombier 		case 't':
46dc5a79c1SDavid du Colombier 			pcmd(f, va_arg(ap, struct tree *));
47dc5a79c1SDavid du Colombier 			break;
48dc5a79c1SDavid du Colombier 		case 'v':
49dc5a79c1SDavid du Colombier 			pval(f, va_arg(ap, struct word *));
50dc5a79c1SDavid du Colombier 			break;
51dc5a79c1SDavid du Colombier 		default:
52dc5a79c1SDavid du Colombier 			pchr(f, *fmt);
53dc5a79c1SDavid du Colombier 			break;
543e12c5d1SDavid du Colombier 		}
553e12c5d1SDavid du Colombier 	va_end(ap);
56dc5a79c1SDavid du Colombier 	if(--pfmtnest==0)
57dc5a79c1SDavid du Colombier 		flush(f);
583e12c5d1SDavid du Colombier }
59dc5a79c1SDavid du Colombier 
60dc5a79c1SDavid du Colombier void
61dc5a79c1SDavid du Colombier pchr(io *b, int c)
627dd7cddfSDavid du Colombier {
63dc5a79c1SDavid du Colombier 	if(b->bufp==b->ebuf)
64dc5a79c1SDavid du Colombier 		fullbuf(b, c);
657dd7cddfSDavid du Colombier 	else *b->bufp++=c;
667dd7cddfSDavid du Colombier }
67dc5a79c1SDavid du Colombier 
68dc5a79c1SDavid du Colombier int
69dc5a79c1SDavid du Colombier rchr(io *b)
707dd7cddfSDavid du Colombier {
71dc5a79c1SDavid du Colombier 	if(b->bufp==b->ebuf)
72dc5a79c1SDavid du Colombier 		return emptybuf(b);
737dd7cddfSDavid du Colombier 	return *b->bufp++ & 0xFF;
747dd7cddfSDavid du Colombier }
75dc5a79c1SDavid du Colombier 
76dc5a79c1SDavid du Colombier void
77dc5a79c1SDavid du Colombier pquo(io *f, char *s)
783e12c5d1SDavid du Colombier {
793e12c5d1SDavid du Colombier 	pchr(f, '\'');
803e12c5d1SDavid du Colombier 	for(;*s;s++)
81dc5a79c1SDavid du Colombier 		if(*s=='\'')
82dc5a79c1SDavid du Colombier 			pfmt(f, "''");
833e12c5d1SDavid du Colombier 		else pchr(f, *s);
843e12c5d1SDavid du Colombier 	pchr(f, '\'');
853e12c5d1SDavid du Colombier }
86dc5a79c1SDavid du Colombier 
87dc5a79c1SDavid du Colombier void
88dc5a79c1SDavid du Colombier pwrd(io *f, char *s)
893e12c5d1SDavid du Colombier {
903e12c5d1SDavid du Colombier 	char *t;
913e12c5d1SDavid du Colombier 	for(t = s;*t;t++) if(!wordchr(*t)) break;
92dc5a79c1SDavid du Colombier 	if(t==s || *t)
93dc5a79c1SDavid du Colombier 		pquo(f, s);
943e12c5d1SDavid du Colombier 	else pstr(f, s);
953e12c5d1SDavid du Colombier }
96dc5a79c1SDavid du Colombier 
97dc5a79c1SDavid du Colombier void
98*73e742d7SDavid du Colombier pptr(io *f, void *v)
993e12c5d1SDavid du Colombier {
1003e12c5d1SDavid du Colombier 	int n;
101*73e742d7SDavid du Colombier 	uintptr p;
102*73e742d7SDavid du Colombier 
103*73e742d7SDavid du Colombier 	p = (uintptr)v;
104*73e742d7SDavid du Colombier 	if(sizeof(uintptr) == sizeof(uvlong) && p>>32)
105*73e742d7SDavid du Colombier 		for(n = 60;n>=32;n-=4) pchr(f, "0123456789ABCDEF"[(p>>n)&0xF]);
106*73e742d7SDavid du Colombier 
1073e12c5d1SDavid du Colombier 	for(n = 28;n>=0;n-=4) pchr(f, "0123456789ABCDEF"[(p>>n)&0xF]);
1083e12c5d1SDavid du Colombier }
109dc5a79c1SDavid du Colombier 
110dc5a79c1SDavid du Colombier void
111dc5a79c1SDavid du Colombier pstr(io *f, char *s)
1123e12c5d1SDavid du Colombier {
113dc5a79c1SDavid du Colombier 	if(s==0)
114dc5a79c1SDavid du Colombier 		s="(null)";
1153e12c5d1SDavid du Colombier 	while(*s) pchr(f, *s++);
1163e12c5d1SDavid du Colombier }
117dc5a79c1SDavid du Colombier 
118dc5a79c1SDavid du Colombier void
119*73e742d7SDavid du Colombier pdec(io *f, int n)
1203e12c5d1SDavid du Colombier {
1213e12c5d1SDavid du Colombier 	if(n<0){
1223e12c5d1SDavid du Colombier 		n=-n;
1233e12c5d1SDavid du Colombier 		if(n>=0){
1243e12c5d1SDavid du Colombier 			pchr(f, '-');
1253e12c5d1SDavid du Colombier 			pdec(f, n);
1263e12c5d1SDavid du Colombier 			return;
1273e12c5d1SDavid du Colombier 		}
1283e12c5d1SDavid du Colombier 		/* n is two's complement minimum integer */
1293e12c5d1SDavid du Colombier 		n = 1-n;
1303e12c5d1SDavid du Colombier 		pchr(f, '-');
1313e12c5d1SDavid du Colombier 		pdec(f, n/10);
1323e12c5d1SDavid du Colombier 		pchr(f, n%10+'1');
1333e12c5d1SDavid du Colombier 		return;
1343e12c5d1SDavid du Colombier 	}
135dc5a79c1SDavid du Colombier 	if(n>9)
136dc5a79c1SDavid du Colombier 		pdec(f, n/10);
1373e12c5d1SDavid du Colombier 	pchr(f, n%10+'0');
1383e12c5d1SDavid du Colombier }
139dc5a79c1SDavid du Colombier 
140dc5a79c1SDavid du Colombier void
141*73e742d7SDavid du Colombier poct(io *f, unsigned n)
1423e12c5d1SDavid du Colombier {
143dc5a79c1SDavid du Colombier 	if(n>7)
144dc5a79c1SDavid du Colombier 		poct(f, n>>3);
1453e12c5d1SDavid du Colombier 	pchr(f, (n&7)+'0');
1463e12c5d1SDavid du Colombier }
147dc5a79c1SDavid du Colombier 
148dc5a79c1SDavid du Colombier void
149dc5a79c1SDavid du Colombier pval(io *f, word *a)
1503e12c5d1SDavid du Colombier {
1513e12c5d1SDavid du Colombier 	if(a){
1523e12c5d1SDavid du Colombier 		while(a->next && a->next->word){
1533e12c5d1SDavid du Colombier 			pwrd(f, a->word);
1543e12c5d1SDavid du Colombier 			pchr(f, ' ');
1553e12c5d1SDavid du Colombier 			a = a->next;
1563e12c5d1SDavid du Colombier 		}
1573e12c5d1SDavid du Colombier 		pwrd(f, a->word);
1583e12c5d1SDavid du Colombier 	}
1593e12c5d1SDavid du Colombier }
160dc5a79c1SDavid du Colombier 
161dc5a79c1SDavid du Colombier int
162dc5a79c1SDavid du Colombier fullbuf(io *f, int c)
1633e12c5d1SDavid du Colombier {
1643e12c5d1SDavid du Colombier 	flush(f);
1653e12c5d1SDavid du Colombier 	return *f->bufp++=c;
1663e12c5d1SDavid du Colombier }
167dc5a79c1SDavid du Colombier 
168dc5a79c1SDavid du Colombier void
169dc5a79c1SDavid du Colombier flush(io *f)
1703e12c5d1SDavid du Colombier {
1713e12c5d1SDavid du Colombier 	int n;
1723e12c5d1SDavid du Colombier 	char *s;
1733e12c5d1SDavid du Colombier 	if(f->strp){
1743e12c5d1SDavid du Colombier 		n = f->ebuf-f->strp;
1753e12c5d1SDavid du Colombier 		f->strp = realloc(f->strp, n+101);
176dc5a79c1SDavid du Colombier 		if(f->strp==0)
177dc5a79c1SDavid du Colombier 			panic("Can't realloc %d bytes in flush!", n+101);
1783e12c5d1SDavid du Colombier 		f->bufp = f->strp+n;
1793e12c5d1SDavid du Colombier 		f->ebuf = f->bufp+100;
1803e12c5d1SDavid du Colombier 		for(s = f->bufp;s<=f->ebuf;s++) *s='\0';
1813e12c5d1SDavid du Colombier 	}
1823e12c5d1SDavid du Colombier 	else{
1833e12c5d1SDavid du Colombier 		n = f->bufp-f->buf;
1843e12c5d1SDavid du Colombier 		if(n && Write(f->fd, f->buf, n) < 0){
1853e12c5d1SDavid du Colombier 			Write(3, "Write error\n", 12);
186dc5a79c1SDavid du Colombier 			if(ntrap)
187dc5a79c1SDavid du Colombier 				dotrap();
1883e12c5d1SDavid du Colombier 		}
1893e12c5d1SDavid du Colombier 		f->bufp = f->buf;
1903e12c5d1SDavid du Colombier 		f->ebuf = f->buf+NBUF;
1913e12c5d1SDavid du Colombier 	}
1923e12c5d1SDavid du Colombier }
193dc5a79c1SDavid du Colombier 
194dc5a79c1SDavid du Colombier io*
195dc5a79c1SDavid du Colombier openfd(int fd)
196dc5a79c1SDavid du Colombier {
1973e12c5d1SDavid du Colombier 	io *f = new(struct io);
1983e12c5d1SDavid du Colombier 	f->fd = fd;
1993e12c5d1SDavid du Colombier 	f->bufp = f->ebuf = f->buf;
2003e12c5d1SDavid du Colombier 	f->strp = 0;
2013e12c5d1SDavid du Colombier 	return f;
2023e12c5d1SDavid du Colombier }
203dc5a79c1SDavid du Colombier 
204dc5a79c1SDavid du Colombier io*
205dc5a79c1SDavid du Colombier openstr(void)
206dc5a79c1SDavid du Colombier {
2073e12c5d1SDavid du Colombier 	io *f = new(struct io);
2083e12c5d1SDavid du Colombier 	char *s;
2093e12c5d1SDavid du Colombier 	f->fd=-1;
2103e12c5d1SDavid du Colombier 	f->bufp = f->strp = emalloc(101);
2113e12c5d1SDavid du Colombier 	f->ebuf = f->bufp+100;
2123e12c5d1SDavid du Colombier 	for(s = f->bufp;s<=f->ebuf;s++) *s='\0';
2133e12c5d1SDavid du Colombier 	return f;
2143e12c5d1SDavid du Colombier }
2153e12c5d1SDavid du Colombier /*
2163e12c5d1SDavid du Colombier  * Open a corebuffer to read.  EOF occurs after reading len
2173e12c5d1SDavid du Colombier  * characters from buf.
2183e12c5d1SDavid du Colombier  */
219dc5a79c1SDavid du Colombier 
220dc5a79c1SDavid du Colombier io*
221dc5a79c1SDavid du Colombier opencore(char *s, int len)
2223e12c5d1SDavid du Colombier {
2233e12c5d1SDavid du Colombier 	io *f = new(struct io);
2243e12c5d1SDavid du Colombier 	char *buf = emalloc(len);
2253e12c5d1SDavid du Colombier 	f->fd= -1 /*open("/dev/null", 0)*/;
2263e12c5d1SDavid du Colombier 	f->bufp = f->strp = buf;
2273e12c5d1SDavid du Colombier 	f->ebuf = buf+len;
2283e12c5d1SDavid du Colombier 	Memcpy(buf, s, len);
2293e12c5d1SDavid du Colombier 	return f;
2303e12c5d1SDavid du Colombier }
231dc5a79c1SDavid du Colombier 
232dc5a79c1SDavid du Colombier void
233dc5a79c1SDavid du Colombier rewind(io *io)
2343e12c5d1SDavid du Colombier {
235dc5a79c1SDavid du Colombier 	if(io->fd==-1)
236dc5a79c1SDavid du Colombier 		io->bufp = io->strp;
2373e12c5d1SDavid du Colombier 	else{
2383e12c5d1SDavid du Colombier 		io->bufp = io->ebuf = io->buf;
2393e12c5d1SDavid du Colombier 		Seek(io->fd, 0L, 0);
2403e12c5d1SDavid du Colombier 	}
2413e12c5d1SDavid du Colombier }
242dc5a79c1SDavid du Colombier 
243dc5a79c1SDavid du Colombier void
244dc5a79c1SDavid du Colombier closeio(io *io)
2453e12c5d1SDavid du Colombier {
246dc5a79c1SDavid du Colombier 	if(io->fd>=0)
247dc5a79c1SDavid du Colombier 		close(io->fd);
248dc5a79c1SDavid du Colombier 	if(io->strp)
249dc5a79c1SDavid du Colombier 		efree(io->strp);
2503e12c5d1SDavid du Colombier 	efree((char *)io);
2513e12c5d1SDavid du Colombier }
252dc5a79c1SDavid du Colombier 
253dc5a79c1SDavid du Colombier int
254dc5a79c1SDavid du Colombier emptybuf(io *f)
2553e12c5d1SDavid du Colombier {
2563e12c5d1SDavid du Colombier 	int n;
2573e12c5d1SDavid du Colombier 	if(f->fd==-1 || (n = Read(f->fd, f->buf, NBUF))<=0) return EOF;
2583e12c5d1SDavid du Colombier 	f->bufp = f->buf;
2593e12c5d1SDavid du Colombier 	f->ebuf = f->buf+n;
2603e12c5d1SDavid du Colombier 	return *f->bufp++&0xff;
2613e12c5d1SDavid du Colombier }
262