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