xref: /plan9/sys/src/cmd/rc/io.c (revision 3468a4915d661daa200976acc4f80f51aae144b2)
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
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':
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
67 pchr(io *b, int c)
68 {
69 	if(b->bufp==b->ebuf)
70 		fullbuf(b, c);
71 	else *b->bufp++=c;
72 }
73 
74 int
75 rchr(io *b)
76 {
77 	if(b->bufp==b->ebuf)
78 		return emptybuf(b);
79 	return *b->bufp++;
80 }
81 
82 void
83 pquo(io *f, char *s)
84 {
85 	pchr(f, '\'');
86 	for(;*s;s++)
87 		if(*s=='\'')
88 			pfmt(f, "''");
89 		else pchr(f, *s);
90 	pchr(f, '\'');
91 }
92 
93 void
94 pwrd(io *f, char *s)
95 {
96 	char *t;
97 	for(t = s;*t;t++) if(*t >= 0 && needsrcquote(*t)) break;
98 	if(t==s || *t)
99 		pquo(f, s);
100 	else pstr(f, s);
101 }
102 
103 void
104 pptr(io *f, void *v)
105 {
106 	int n;
107 	uintptr p;
108 
109 	p = (uintptr)v;
110 	if(sizeof(uintptr) == sizeof(uvlong) && p>>32)
111 		for(n = 60;n>=32;n-=4) pchr(f, "0123456789ABCDEF"[(p>>n)&0xF]);
112 
113 	for(n = 28;n>=0;n-=4) pchr(f, "0123456789ABCDEF"[(p>>n)&0xF]);
114 }
115 
116 void
117 pstr(io *f, char *s)
118 {
119 	if(s==0)
120 		s="(null)";
121 	while(*s) pchr(f, *s++);
122 }
123 
124 void
125 pdec(io *f, int n)
126 {
127 	if(n<0){
128 		n=-n;
129 		if(n>=0){
130 			pchr(f, '-');
131 			pdec(f, n);
132 			return;
133 		}
134 		/* n is two's complement minimum integer */
135 		n = 1-n;
136 		pchr(f, '-');
137 		pdec(f, n/10);
138 		pchr(f, n%10+'1');
139 		return;
140 	}
141 	if(n>9)
142 		pdec(f, n/10);
143 	pchr(f, n%10+'0');
144 }
145 
146 void
147 poct(io *f, unsigned n)
148 {
149 	if(n>7)
150 		poct(f, n>>3);
151 	pchr(f, (n&7)+'0');
152 }
153 
154 void
155 pval(io *f, word *a)
156 {
157 	if(a){
158 		while(a->next && a->next->word){
159 			pwrd(f, (char *)a->word);
160 			pchr(f, ' ');
161 			a = a->next;
162 		}
163 		pwrd(f, (char *)a->word);
164 	}
165 }
166 
167 int
168 fullbuf(io *f, int c)
169 {
170 	flush(f);
171 	return *f->bufp++=c;
172 }
173 
174 void
175 flush(io *f)
176 {
177 	int n;
178 
179 	if(f->strp){
180 		n = f->ebuf - f->strp;
181 		f->strp = realloc(f->strp, n+Stralloc+1);
182 		if(f->strp==0)
183 			panic("Can't realloc %d bytes in flush!", n+Stralloc+1);
184 		f->bufp = f->strp + n;
185 		f->ebuf = f->bufp + Stralloc;
186 		memset(f->bufp, '\0', Stralloc+1);
187 	}
188 	else{
189 		n = f->bufp-f->buf;
190 		if(n && Write(f->fd, f->buf, n) != n){
191 			Write(2, "Write error\n", 12);
192 			if(ntrap)
193 				dotrap();
194 		}
195 		f->bufp = f->buf;
196 		f->ebuf = f->buf+NBUF;
197 	}
198 }
199 
200 io*
201 openfd(int fd)
202 {
203 	io *f = new(struct io);
204 	f->fd = fd;
205 	f->bufp = f->ebuf = f->buf;
206 	f->strp = 0;
207 	return f;
208 }
209 
210 io*
211 openstr(void)
212 {
213 	io *f = new(struct io);
214 
215 	f->fd = -1;
216 	f->bufp = f->strp = emalloc(Stralloc+1);
217 	f->ebuf = f->bufp + Stralloc;
218 	memset(f->bufp, '\0', Stralloc+1);
219 	return f;
220 }
221 /*
222  * Open a corebuffer to read.  EOF occurs after reading len
223  * characters from buf.
224  */
225 
226 io*
227 opencore(char *s, int len)
228 {
229 	io *f = new(struct io);
230 	uchar *buf = emalloc(len);
231 
232 	f->fd = -1 /*open("/dev/null", 0)*/;
233 	f->bufp = f->strp = buf;
234 	f->ebuf = buf+len;
235 	Memcpy(buf, s, len);
236 	return f;
237 }
238 
239 void
240 rewind(io *io)
241 {
242 	if(io->fd==-1)
243 		io->bufp = io->strp;
244 	else{
245 		io->bufp = io->ebuf = io->buf;
246 		Seek(io->fd, 0L, 0);
247 	}
248 }
249 
250 void
251 closeio(io *io)
252 {
253 	if(io->fd>=0)
254 		close(io->fd);
255 	if(io->strp)
256 		efree(io->strp);
257 	efree(io);
258 }
259 
260 int
261 emptybuf(io *f)
262 {
263 	int n;
264 	if(f->fd==-1 || (n = Read(f->fd, f->buf, NBUF))<=0) return EOF;
265 	f->bufp = f->buf;
266 	f->ebuf = f->buf + n;
267 	return *f->bufp++;
268 }
269