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