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