| #include <limits.h> |
| #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': |
| pptr(f, va_arg(ap, void*)); |
| break; |
| case 'Q': |
| pquo(f, va_arg(ap, char *)); |
| break; |
| case 'q': |
| pwrd(f, va_arg(ap, char *)); |
| break; |
| case 'r': |
| rerrstr(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 |
| pptr(io *f, void *v) |
| { |
| int n; |
| uintptr p; |
| |
| p = (uintptr)v; |
| if(sizeof(uintptr) == sizeof(uvlong) && p>>32) |
| for(n = 60;n>=32;n-=4) pchr(f, "0123456789ABCDEF"[(p>>n)&0xF]); |
| |
| 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, int n) |
| { |
| if(n<0){ |
| if(n!=INT_MIN){ |
| pchr(f, '-'); |
| pdec(f, -n); |
| return; |
| } |
| /* n is two's complement minimum integer */ |
| n = -(INT_MIN+1); |
| 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, unsigned 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 = 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 |
| iorewind(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; |
| } |