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){
26dc5a79c1SDavid du Colombier case 'c':
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)67dc5a79c1SDavid du Colombier pchr(io *b, int c)
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*85497287SDavid du Colombier int
rutf(io * b,char * buf,Rune * r)83*85497287SDavid du Colombier rutf(io *b, char *buf, Rune *r)
84*85497287SDavid du Colombier {
85*85497287SDavid du Colombier int n, i, c;
86*85497287SDavid du Colombier
87*85497287SDavid du Colombier c = rchr(b);
88*85497287SDavid du Colombier if(c == EOF)
89*85497287SDavid du Colombier return EOF;
90*85497287SDavid du Colombier *buf = c;
91*85497287SDavid du Colombier if(c < Runesync){
92*85497287SDavid du Colombier *r = c;
93*85497287SDavid du Colombier return 1;
94*85497287SDavid du Colombier }
95*85497287SDavid du Colombier for(i = 1; (c = rchr(b)) != EOF; ){
96*85497287SDavid du Colombier buf[i++] = c;
97*85497287SDavid du Colombier buf[i] = 0;
98*85497287SDavid du Colombier if(fullrune(buf, i)){
99*85497287SDavid du Colombier n = chartorune(r, buf);
100*85497287SDavid du Colombier b->bufp -= i - n; /* push back unconsumed bytes */
101*85497287SDavid du Colombier assert(b->fd == -1 || b->bufp > b->buf);
102*85497287SDavid du Colombier return n;
103*85497287SDavid du Colombier }
104*85497287SDavid du Colombier }
105*85497287SDavid du Colombier /* at eof */
106*85497287SDavid du Colombier b->bufp -= i - 1; /* consume 1 byte */
107*85497287SDavid du Colombier *r = Runeerror;
108*85497287SDavid du Colombier return runetochar(buf, r);
109*85497287SDavid du Colombier }
110*85497287SDavid du Colombier
111dc5a79c1SDavid du Colombier void
pquo(io * f,char * s)112dc5a79c1SDavid du Colombier pquo(io *f, char *s)
1133e12c5d1SDavid du Colombier {
1143e12c5d1SDavid du Colombier pchr(f, '\'');
1153e12c5d1SDavid du Colombier for(;*s;s++)
116dc5a79c1SDavid du Colombier if(*s=='\'')
117dc5a79c1SDavid du Colombier pfmt(f, "''");
11899eb86a7SDavid du Colombier else pchr(f, *s);
1193e12c5d1SDavid du Colombier pchr(f, '\'');
1203e12c5d1SDavid du Colombier }
121dc5a79c1SDavid du Colombier
122dc5a79c1SDavid du Colombier void
pwrd(io * f,char * s)123dc5a79c1SDavid du Colombier pwrd(io *f, char *s)
1243e12c5d1SDavid du Colombier {
1253e12c5d1SDavid du Colombier char *t;
126fed0fa9eSDavid du Colombier for(t = s;*t;t++) if(*t >= 0 && needsrcquote(*t)) break;
127dc5a79c1SDavid du Colombier if(t==s || *t)
128dc5a79c1SDavid du Colombier pquo(f, s);
12999eb86a7SDavid du Colombier else pstr(f, s);
1303e12c5d1SDavid du Colombier }
131dc5a79c1SDavid du Colombier
132dc5a79c1SDavid du Colombier void
pptr(io * f,void * v)13373e742d7SDavid du Colombier pptr(io *f, void *v)
1343e12c5d1SDavid du Colombier {
1353e12c5d1SDavid du Colombier int n;
13673e742d7SDavid du Colombier uintptr p;
13773e742d7SDavid du Colombier
13873e742d7SDavid du Colombier p = (uintptr)v;
13973e742d7SDavid du Colombier if(sizeof(uintptr) == sizeof(uvlong) && p>>32)
14099eb86a7SDavid du Colombier for(n = 60;n>=32;n-=4) pchr(f, "0123456789ABCDEF"[(p>>n)&0xF]);
14173e742d7SDavid du Colombier
14299eb86a7SDavid du Colombier for(n = 28;n>=0;n-=4) pchr(f, "0123456789ABCDEF"[(p>>n)&0xF]);
1433e12c5d1SDavid du Colombier }
144dc5a79c1SDavid du Colombier
145dc5a79c1SDavid du Colombier void
pstr(io * f,char * s)146dc5a79c1SDavid du Colombier pstr(io *f, char *s)
1473e12c5d1SDavid du Colombier {
148dc5a79c1SDavid du Colombier if(s==0)
149dc5a79c1SDavid du Colombier s="(null)";
15099eb86a7SDavid du Colombier while(*s) pchr(f, *s++);
1513e12c5d1SDavid du Colombier }
152dc5a79c1SDavid du Colombier
153dc5a79c1SDavid du Colombier void
pdec(io * f,int n)15473e742d7SDavid du Colombier pdec(io *f, int n)
1553e12c5d1SDavid du Colombier {
1563e12c5d1SDavid du Colombier if(n<0){
1573e12c5d1SDavid du Colombier n=-n;
1583e12c5d1SDavid du Colombier if(n>=0){
1593e12c5d1SDavid du Colombier pchr(f, '-');
1603e12c5d1SDavid du Colombier pdec(f, n);
1613e12c5d1SDavid du Colombier return;
1623e12c5d1SDavid du Colombier }
1633e12c5d1SDavid du Colombier /* n is two's complement minimum integer */
1643e12c5d1SDavid du Colombier n = 1-n;
1653e12c5d1SDavid du Colombier pchr(f, '-');
1663e12c5d1SDavid du Colombier pdec(f, n/10);
1673e12c5d1SDavid du Colombier pchr(f, n%10+'1');
1683e12c5d1SDavid du Colombier return;
1693e12c5d1SDavid du Colombier }
170dc5a79c1SDavid du Colombier if(n>9)
171dc5a79c1SDavid du Colombier pdec(f, n/10);
1723e12c5d1SDavid du Colombier pchr(f, n%10+'0');
1733e12c5d1SDavid du Colombier }
174dc5a79c1SDavid du Colombier
175dc5a79c1SDavid du Colombier void
poct(io * f,unsigned n)17673e742d7SDavid du Colombier poct(io *f, unsigned n)
1773e12c5d1SDavid du Colombier {
178dc5a79c1SDavid du Colombier if(n>7)
179dc5a79c1SDavid du Colombier poct(f, n>>3);
1803e12c5d1SDavid du Colombier pchr(f, (n&7)+'0');
1813e12c5d1SDavid du Colombier }
182dc5a79c1SDavid du Colombier
183dc5a79c1SDavid du Colombier void
pval(io * f,word * a)184dc5a79c1SDavid du Colombier pval(io *f, word *a)
1853e12c5d1SDavid du Colombier {
1863e12c5d1SDavid du Colombier if(a){
1873e12c5d1SDavid du Colombier while(a->next && a->next->word){
188276e7d6dSDavid du Colombier pwrd(f, (char *)a->word);
1893e12c5d1SDavid du Colombier pchr(f, ' ');
1903e12c5d1SDavid du Colombier a = a->next;
1913e12c5d1SDavid du Colombier }
192276e7d6dSDavid du Colombier pwrd(f, (char *)a->word);
1933e12c5d1SDavid du Colombier }
1943e12c5d1SDavid du Colombier }
195dc5a79c1SDavid du Colombier
196dc5a79c1SDavid du Colombier int
fullbuf(io * f,int c)197dc5a79c1SDavid du Colombier fullbuf(io *f, int c)
1983e12c5d1SDavid du Colombier {
1993e12c5d1SDavid du Colombier flush(f);
2003e12c5d1SDavid du Colombier return *f->bufp++=c;
2013e12c5d1SDavid du Colombier }
202dc5a79c1SDavid du Colombier
203dc5a79c1SDavid du Colombier void
flush(io * f)204dc5a79c1SDavid du Colombier flush(io *f)
2053e12c5d1SDavid du Colombier {
2063e12c5d1SDavid du Colombier int n;
207276e7d6dSDavid du Colombier
2083e12c5d1SDavid du Colombier if(f->strp){
2093e12c5d1SDavid du Colombier n = f->ebuf - f->strp;
210276e7d6dSDavid du Colombier f->strp = realloc(f->strp, n+Stralloc+1);
211dc5a79c1SDavid du Colombier if(f->strp==0)
212276e7d6dSDavid du Colombier panic("Can't realloc %d bytes in flush!", n+Stralloc+1);
2133e12c5d1SDavid du Colombier f->bufp = f->strp + n;
214276e7d6dSDavid du Colombier f->ebuf = f->bufp + Stralloc;
215276e7d6dSDavid du Colombier memset(f->bufp, '\0', Stralloc+1);
2163e12c5d1SDavid du Colombier }
2173e12c5d1SDavid du Colombier else{
2183e12c5d1SDavid du Colombier n = f->bufp-f->buf;
219276e7d6dSDavid du Colombier if(n && Write(f->fd, f->buf, n) != n){
220276e7d6dSDavid du Colombier Write(2, "Write error\n", 12);
221dc5a79c1SDavid du Colombier if(ntrap)
222dc5a79c1SDavid du Colombier dotrap();
2233e12c5d1SDavid du Colombier }
2243e12c5d1SDavid du Colombier f->bufp = f->buf;
2253e12c5d1SDavid du Colombier f->ebuf = f->buf+NBUF;
2263e12c5d1SDavid du Colombier }
2273e12c5d1SDavid du Colombier }
228dc5a79c1SDavid du Colombier
229dc5a79c1SDavid du Colombier io*
openfd(int fd)230dc5a79c1SDavid du Colombier openfd(int fd)
231dc5a79c1SDavid du Colombier {
2323e12c5d1SDavid du Colombier io *f = new(struct io);
2333e12c5d1SDavid du Colombier f->fd = fd;
2343e12c5d1SDavid du Colombier f->bufp = f->ebuf = f->buf;
2353e12c5d1SDavid du Colombier f->strp = 0;
2363e12c5d1SDavid du Colombier return f;
2373e12c5d1SDavid du Colombier }
238dc5a79c1SDavid du Colombier
239dc5a79c1SDavid du Colombier io*
openstr(void)240dc5a79c1SDavid du Colombier openstr(void)
241dc5a79c1SDavid du Colombier {
2423e12c5d1SDavid du Colombier io *f = new(struct io);
243276e7d6dSDavid du Colombier
2443e12c5d1SDavid du Colombier f->fd = -1;
245276e7d6dSDavid du Colombier f->bufp = f->strp = emalloc(Stralloc+1);
246276e7d6dSDavid du Colombier f->ebuf = f->bufp + Stralloc;
247276e7d6dSDavid du Colombier memset(f->bufp, '\0', Stralloc+1);
2483e12c5d1SDavid du Colombier return f;
2493e12c5d1SDavid du Colombier }
2503e12c5d1SDavid du Colombier /*
2513e12c5d1SDavid du Colombier * Open a corebuffer to read. EOF occurs after reading len
2523e12c5d1SDavid du Colombier * characters from buf.
2533e12c5d1SDavid du Colombier */
254dc5a79c1SDavid du Colombier
255dc5a79c1SDavid du Colombier io*
opencore(char * s,int len)256dc5a79c1SDavid du Colombier opencore(char *s, int len)
2573e12c5d1SDavid du Colombier {
2583e12c5d1SDavid du Colombier io *f = new(struct io);
259276e7d6dSDavid du Colombier uchar *buf = emalloc(len);
260276e7d6dSDavid du Colombier
2613e12c5d1SDavid du Colombier f->fd = -1 /*open("/dev/null", 0)*/;
2623e12c5d1SDavid du Colombier f->bufp = f->strp = buf;
2633e12c5d1SDavid du Colombier f->ebuf = buf+len;
2643e12c5d1SDavid du Colombier Memcpy(buf, s, len);
2653e12c5d1SDavid du Colombier return f;
2663e12c5d1SDavid du Colombier }
267dc5a79c1SDavid du Colombier
268dc5a79c1SDavid du Colombier void
rewind(io * io)269dc5a79c1SDavid du Colombier rewind(io *io)
2703e12c5d1SDavid du Colombier {
271dc5a79c1SDavid du Colombier if(io->fd==-1)
272dc5a79c1SDavid du Colombier io->bufp = io->strp;
2733e12c5d1SDavid du Colombier else{
2743e12c5d1SDavid du Colombier io->bufp = io->ebuf = io->buf;
27599eb86a7SDavid du Colombier Seek(io->fd, 0L, 0);
2763e12c5d1SDavid du Colombier }
2773e12c5d1SDavid du Colombier }
278dc5a79c1SDavid du Colombier
279dc5a79c1SDavid du Colombier void
closeio(io * io)280dc5a79c1SDavid du Colombier closeio(io *io)
2813e12c5d1SDavid du Colombier {
282dc5a79c1SDavid du Colombier if(io->fd>=0)
283dc5a79c1SDavid du Colombier close(io->fd);
284dc5a79c1SDavid du Colombier if(io->strp)
285dc5a79c1SDavid du Colombier efree(io->strp);
286276e7d6dSDavid du Colombier efree(io);
2873e12c5d1SDavid du Colombier }
288dc5a79c1SDavid du Colombier
289dc5a79c1SDavid du Colombier int
emptybuf(io * f)290dc5a79c1SDavid du Colombier emptybuf(io *f)
2913e12c5d1SDavid du Colombier {
2923e12c5d1SDavid du Colombier int n;
29399eb86a7SDavid du Colombier if(f->fd==-1 || (n = Read(f->fd, f->buf, NBUF))<=0) return EOF;
2943e12c5d1SDavid du Colombier f->bufp = f->buf;
2953e12c5d1SDavid du Colombier f->ebuf = f->buf + n;
296276e7d6dSDavid du Colombier return *f->bufp++;
2973e12c5d1SDavid du Colombier }
298