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
pfmt(Io * f,char * fmt,...)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
perr(Io * f)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
pquo(Io * f,char * s)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
pwrd(Io * f,char * s)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
phex(Io * f,long p)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
pstr(Io * f,char * s)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
pdec(Io * f,long n)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
poct(Io * f,ulong n)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
pval(Io * f,Word * a)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
fullbuf(Io * f,int c)133 fullbuf(Io *f, int c)
134 {
135 flush(f);
136 return *f->bufp++=c;
137 }
138
139 void
flush(Io * f)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 *
openfd(int fd)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 *
openstr(void)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 *
opencore(char * s,int len)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
rewind(Io * io)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
closeio(Io * io)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
emptybuf(Io * f)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