xref: /plan9-contrib/sys/src/cmd/rc/io.c (revision c6df144405f586b73992827d584728dc975dff14)
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':			/* char, not Rune */
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)			/* print a char, not a Rune */
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 /*
83  * read next utf sequence from b into buf, and convert it to Rune *r.
84  * return EOF or number of bytes consumed.
85  */
86 int
rutf(io * b,char * buf,Rune * r)87 rutf(io *b, char *buf, Rune *r)
88 {
89 	int i, c;
90 
91 	c = rchr(b);
92 	if(c == EOF) {
93 		buf[0] = 0;
94 		*r = EOF;
95 		return EOF;
96 	}
97 	*buf = c;
98 	if(c < Runeself){			/* ascii? */
99 		buf[1] = 0;
100 		*r = c;
101 		return 1;
102 	}
103 
104 	/* multi-byte utf sequence */
105 	for(i = 1; i <= UTFmax && (c = rchr(b)) != EOF && c >= Runeself; ){
106 		buf[i++] = c;
107 		buf[i] = 0;
108 		if(fullrune(buf, i))
109 			return chartorune(r, buf);
110 	}
111 
112 	/* bad utf sequence: too long, or unexpected ascii or EOF */
113 	if (c != EOF && c < Runeself && b->bufp > b->buf)
114 		b->bufp--;			/* push back ascii */
115 	*r = Runeerror;
116 	return runetochar(buf, r);
117 }
118 
119 void
pquo(io * f,char * s)120 pquo(io *f, char *s)
121 {
122 	pchr(f, '\'');
123 	for(;*s;s++)
124 		if(*s=='\'')
125 			pfmt(f, "''");
126 		else pchr(f, *s);
127 	pchr(f, '\'');
128 }
129 
130 void
pwrd(io * f,char * s)131 pwrd(io *f, char *s)
132 {
133 	char *t;
134 
135 	for (t = s; *t; t++)
136 		if (*(uchar *)t < Runeself && needsrcquote(*t))
137 			break;
138 	if (t == s || *t)
139 		pquo(f, s);
140 	else
141 		pstr(f, s);
142 }
143 
144 void
pptr(io * f,void * v)145 pptr(io *f, void *v)
146 {
147 	int n;
148 	uintptr p;
149 	static char uphex[] = "0123456789ABCDEF";
150 
151 	p = (uintptr)v;
152 	if (sizeof(uintptr) == sizeof(uvlong) && p >> 32)
153 		for (n = 60; n >= 32; n -= 4)
154 			pchr(f, uphex[(p>>n)&0xF]);
155 	for (n = 28; n >= 0; n -= 4)
156 		pchr(f, uphex[(p>>n)&0xF]);
157 }
158 
159 void
pstr(io * f,char * s)160 pstr(io *f, char *s)
161 {
162 	if(s==0)
163 		s="(null)";
164 	while(*s) pchr(f, *s++);
165 }
166 
167 void
pdec(io * f,int n)168 pdec(io *f, int n)
169 {
170 	if(n<0){
171 		n=-n;
172 		if(n>=0){
173 			pchr(f, '-');
174 			pdec(f, n);
175 			return;
176 		}
177 		/* n is two's complement minimum integer */
178 		n = 1-n;
179 		pchr(f, '-');
180 		pdec(f, n/10);
181 		pchr(f, n%10+'1');
182 		return;
183 	}
184 	if(n>9)
185 		pdec(f, n/10);
186 	pchr(f, n%10+'0');
187 }
188 
189 void
poct(io * f,unsigned n)190 poct(io *f, unsigned n)
191 {
192 	if(n>7)
193 		poct(f, n>>3);
194 	pchr(f, (n&7)+'0');
195 }
196 
197 void
pval(io * f,word * a)198 pval(io *f, word *a)
199 {
200 	if(a){
201 		while(a->next && a->next->word){
202 			pwrd(f, (char *)a->word);
203 			pchr(f, ' ');
204 			a = a->next;
205 		}
206 		pwrd(f, (char *)a->word);
207 	}
208 }
209 
210 int
fullbuf(io * f,int c)211 fullbuf(io *f, int c)
212 {
213 	flush(f);
214 	return *f->bufp++=c;
215 }
216 
217 void
flush(io * f)218 flush(io *f)
219 {
220 	int n;
221 
222 	if(f->strp){
223 		n = f->ebuf - f->strp;
224 		f->strp = realloc(f->strp, n+Stralloc+1);
225 		if(f->strp==0)
226 			panic("Can't realloc %d bytes in flush!", n+Stralloc+1);
227 		f->bufp = f->strp + n;
228 		f->ebuf = f->bufp + Stralloc;
229 		memset(f->bufp, '\0', Stralloc+1);
230 	}
231 	else{
232 		n = f->bufp-f->buf;
233 		if(n && Write(f->fd, f->buf, n) != n){
234 			Write(2, "Write error\n", 12);
235 			if(ntrap)
236 				dotrap();
237 		}
238 		f->bufp = f->buf;
239 		f->ebuf = f->buf+NBUF;
240 	}
241 }
242 
243 io*
openfd(int fd)244 openfd(int fd)
245 {
246 	io *f = new(struct io);
247 	f->fd = fd;
248 	f->bufp = f->ebuf = f->buf;
249 	f->strp = 0;
250 	return f;
251 }
252 
253 io*
openstr(void)254 openstr(void)
255 {
256 	io *f = new(struct io);
257 
258 	f->fd = -1;
259 	f->bufp = f->strp = emalloc(Stralloc+1);
260 	f->ebuf = f->bufp + Stralloc;
261 	f->output = 1;
262 	memset(f->bufp, '\0', Stralloc+1);
263 	return f;
264 }
265 /*
266  * Open a corebuffer to read.  EOF occurs after reading len
267  * characters from buf.
268  */
269 
270 io*
opencore(char * s,int len)271 opencore(char *s, int len)
272 {
273 	io *f = new(struct io);
274 	uchar *buf = emalloc(len);
275 
276 	f->fd = -1 /*open("/dev/null", 0)*/;
277 	f->bufp = f->strp = buf;
278 	f->ebuf = buf+len;
279 	f->output = 0;
280 	Memcpy(buf, s, len);
281 	return f;
282 }
283 
284 void
rewind(io * io)285 rewind(io *io)
286 {
287 	if(io->fd==-1) {
288 		io->bufp = io->strp;
289 		if (io->output)
290 			memset(io->strp, 0, io->ebuf - io->strp);
291 	}else{
292 		io->bufp = io->ebuf = io->buf;
293 		seek(io->fd, 0, 0);
294 	}
295 }
296 
297 void
closeio(io * io)298 closeio(io *io)
299 {
300 	if(io->fd>=0)
301 		close(io->fd);
302 	if(io->strp)
303 		efree(io->strp);
304 	efree(io);
305 }
306 
307 int
emptybuf(io * f)308 emptybuf(io *f)
309 {
310 	int n;
311 
312 	if(f->fd == -1 || (n = Read(f->fd, f->buf, NBUF))<=0)
313 		return EOF;
314 	f->bufp = f->buf;
315 	f->ebuf = f->buf + n;
316 	return *f->bufp++;
317 }
318