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