| #include "rc.h" |
| #include "exec.h" |
| #include "io.h" |
| #include "fns.h" |
| int pfmtnest=0; |
| void pfmt(io *f, char *fmt, ...){ |
| va_list ap; |
| char err[ERRMAX]; |
| va_start(ap, fmt); |
| pfmtnest++; |
| for(;*fmt;fmt++) |
| if(*fmt!='%') pchr(f, *fmt); |
| else switch(*++fmt){ |
| case '\0': va_end(ap); return; |
| case 'c': pchr(f, va_arg(ap, int)); break; |
| case 'd': pdec(f, va_arg(ap, int)); break; |
| case 'o': poct(f, va_arg(ap, unsigned)); break; |
| case 'p': phex(f, (long)va_arg(ap, char *)); break; /*unportable*/ |
| case 'Q': pquo(f, va_arg(ap, char *)); break; |
| case 'q': pwrd(f, va_arg(ap, char *)); break; |
| case 'r': errstr(err, sizeof err); pstr(f, err); break; |
| case 's': pstr(f, va_arg(ap, char *)); break; |
| case 't': pcmd(f, va_arg(ap, struct tree *)); break; |
| case 'v': pval(f, va_arg(ap, struct word *)); break; |
| default: pchr(f, *fmt); break; |
| } |
| va_end(ap); |
| if(--pfmtnest==0) flush(f); |
| } |
| void pchr(io *b, int c) |
| { |
| if(b->bufp==b->ebuf) fullbuf(b, c); |
| else *b->bufp++=c; |
| } |
| int rchr(io *b) |
| { |
| if(b->bufp==b->ebuf) return emptybuf(b); |
| return *b->bufp++ & 0xFF; |
| } |
| |
| void pquo(io *f, char *s) |
| { |
| pchr(f, '\''); |
| for(;*s;s++) |
| if(*s=='\'') pfmt(f, "''"); |
| else pchr(f, *s); |
| pchr(f, '\''); |
| } |
| void pwrd(io *f, char *s) |
| { |
| char *t; |
| for(t=s;*t;t++) if(!wordchr(*t)) break; |
| if(t==s || *t) pquo(f, s); |
| else pstr(f, s); |
| } |
| void phex(io *f, long p) |
| { |
| int n; |
| for(n=28;n>=0;n-=4) pchr(f, "0123456789ABCDEF"[(p>>n)&0xF]); |
| } |
| void pstr(io *f, char *s) |
| { |
| if(s==0) s="(null)"; |
| while(*s) pchr(f, *s++); |
| } |
| void pdec(io *f, long n) |
| { |
| if(n<0){ |
| n=-n; |
| if(n>=0){ |
| pchr(f, '-'); |
| pdec(f, n); |
| return; |
| } |
| /* n is two's complement minimum integer */ |
| n=1-n; |
| pchr(f, '-'); |
| pdec(f, n/10); |
| pchr(f, n%10+'1'); |
| return; |
| } |
| if(n>9) pdec(f, n/10); |
| pchr(f, n%10+'0'); |
| } |
| void poct(io *f, ulong n) |
| { |
| if(n>7) poct(f, n>>3); |
| pchr(f, (n&7)+'0'); |
| } |
| void pval(io *f, word *a) |
| { |
| if(a){ |
| while(a->next && a->next->word){ |
| pwrd(f, a->word); |
| pchr(f, ' '); |
| a=a->next; |
| } |
| pwrd(f, a->word); |
| } |
| } |
| int fullbuf(io *f, int c) |
| { |
| flush(f); |
| return *f->bufp++=c; |
| } |
| void flush(io *f) |
| { |
| int n; |
| char *s; |
| if(f->strp){ |
| n=f->ebuf-f->strp; |
| f->strp=realloc(f->strp, n+101); |
| if(f->strp==0) panic("Can't realloc %d bytes in flush!", n+101); |
| f->bufp=f->strp+n; |
| f->ebuf=f->bufp+100; |
| for(s=f->bufp;s<=f->ebuf;s++) *s='\0'; |
| } |
| else{ |
| n=f->bufp-f->buf; |
| if(n && Write(f->fd, f->buf, n) < 0){ |
| Write(3, "Write error\n", 12); |
| if(ntrap) dotrap(); |
| } |
| f->bufp=f->buf; |
| f->ebuf=f->buf+NBUF; |
| } |
| } |
| io *openfd(int fd){ |
| io *f; |
| f=new(struct io); |
| f->fd=fd; |
| f->bufp=f->ebuf=f->buf; |
| f->strp=0; |
| return f; |
| } |
| io *openstr(void){ |
| io *f=new(struct io); |
| char *s; |
| f->fd=-1; |
| f->bufp=f->strp=emalloc(101); |
| f->ebuf=f->bufp+100; |
| for(s=f->bufp;s<=f->ebuf;s++) *s='\0'; |
| return f; |
| } |
| /* |
| * Open a corebuffer to read. EOF occurs after reading len |
| * characters from buf. |
| */ |
| io *opencore(char *s, int len) |
| { |
| io *f=new(struct io); |
| char *buf=emalloc(len); |
| f->fd= -1 /*open("/dev/null", 0)*/; |
| f->bufp=f->strp=buf; |
| f->ebuf=buf+len; |
| Memcpy(buf, s, len); |
| return f; |
| } |
| /* |
| void rewind(io *io) |
| { |
| if(io->fd==-1) io->bufp=io->strp; |
| else{ |
| io->bufp=io->ebuf=io->buf; |
| Seek(io->fd, 0L, 0); |
| } |
| } |
| */ |
| void closeio(io *io) |
| { |
| if(io->fd>=0) close(io->fd); |
| if(io->strp) efree(io->strp); |
| efree((char *)io); |
| } |
| int emptybuf(io *f) |
| { |
| int n; |
| if(f->fd==-1 || (n=Read(f->fd, f->buf, NBUF))<=0) return EOF; |
| f->bufp=f->buf; |
| f->ebuf=f->buf+n; |
| return *f->bufp++&0xff; |
| } |