1 #include "rc.h" 2 #include "exec.h" 3 #include "io.h" 4 #include "fns.h" 5 int pfmtnest=0; 6 void pfmt(io *f, char *fmt, ...){ 7 va_list ap; 8 va_start(ap, fmt); 9 pfmtnest++; 10 for(;*fmt;fmt++) 11 if(*fmt!='%') pchr(f, *fmt); 12 else switch(*++fmt){ 13 case '\0': va_end(ap); return; 14 case 'c': pchr(f, va_arg(ap, int)); break; 15 case 'd': pdec(f, va_arg(ap, int)); break; 16 case 'o': poct(f, va_arg(ap, unsigned)); break; 17 case 'p': phex(f, (long)va_arg(ap, char *)); break; /*unportable*/ 18 case 'Q': pquo(f, va_arg(ap, char *)); break; 19 case 'q': pwrd(f, va_arg(ap, char *)); break; 20 case 's': pstr(f, va_arg(ap, char *)); break; 21 case 't': pcmd(f, va_arg(ap, struct tree *)); break; 22 case 'v': pval(f, va_arg(ap, struct word *)); break; 23 default: pchr(f, *fmt); break; 24 } 25 va_end(ap); 26 if(--pfmtnest==0) flush(f); 27 } 28 void pchr(io *b, int c) 29 { 30 if(b->bufp==b->ebuf) fullbuf(b, c); 31 else *b->bufp++=c; 32 } 33 int rchr(io *b) 34 { 35 if(b->bufp==b->ebuf) return emptybuf(b); 36 return *b->bufp++ & 0xFF; 37 } 38 void pquo(io *f, char *s) 39 { 40 pchr(f, '\''); 41 for(;*s;s++) 42 if(*s=='\'') pfmt(f, "''"); 43 else pchr(f, *s); 44 pchr(f, '\''); 45 } 46 void pwrd(io *f, char *s) 47 { 48 char *t; 49 for(t=s;*t;t++) if(!wordchr(*t)) break; 50 if(t==s || *t) pquo(f, s); 51 else pstr(f, s); 52 } 53 void phex(io *f, long p) 54 { 55 int n; 56 for(n=28;n>=0;n-=4) pchr(f, "0123456789ABCDEF"[(p>>n)&0xF]); 57 } 58 void pstr(io *f, char *s) 59 { 60 if(s==0) s="(null)"; 61 while(*s) pchr(f, *s++); 62 } 63 void pdec(io *f, long n) 64 { 65 if(n<0){ 66 n=-n; 67 if(n>=0){ 68 pchr(f, '-'); 69 pdec(f, n); 70 return; 71 } 72 /* n is two's complement minimum integer */ 73 n=1-n; 74 pchr(f, '-'); 75 pdec(f, n/10); 76 pchr(f, n%10+'1'); 77 return; 78 } 79 if(n>9) pdec(f, n/10); 80 pchr(f, n%10+'0'); 81 } 82 void poct(io *f, ulong n) 83 { 84 if(n>7) poct(f, n>>3); 85 pchr(f, (n&7)+'0'); 86 } 87 void pval(io *f, word *a) 88 { 89 if(a){ 90 while(a->next && a->next->word){ 91 pwrd(f, a->word); 92 pchr(f, ' '); 93 a=a->next; 94 } 95 pwrd(f, a->word); 96 } 97 } 98 int fullbuf(io *f, int c) 99 { 100 flush(f); 101 return *f->bufp++=c; 102 } 103 void flush(io *f) 104 { 105 int n; 106 char *s; 107 if(f->strp){ 108 n=f->ebuf-f->strp; 109 f->strp=realloc(f->strp, n+101); 110 if(f->strp==0) panic("Can't realloc %d bytes in flush!", n+101); 111 f->bufp=f->strp+n; 112 f->ebuf=f->bufp+100; 113 for(s=f->bufp;s<=f->ebuf;s++) *s='\0'; 114 } 115 else{ 116 n=f->bufp-f->buf; 117 if(n && Write(f->fd, f->buf, n) < 0){ 118 Write(3, "Write error\n", 12); 119 if(ntrap) dotrap(); 120 } 121 f->bufp=f->buf; 122 f->ebuf=f->buf+NBUF; 123 } 124 } 125 io *openfd(int fd){ 126 io *f=new(struct io); 127 f->fd=fd; 128 f->bufp=f->ebuf=f->buf; 129 f->strp=0; 130 return f; 131 } 132 io *openstr(void){ 133 io *f=new(struct io); 134 char *s; 135 f->fd=-1; 136 f->bufp=f->strp=emalloc(101); 137 f->ebuf=f->bufp+100; 138 for(s=f->bufp;s<=f->ebuf;s++) *s='\0'; 139 return f; 140 } 141 /* 142 * Open a corebuffer to read. EOF occurs after reading len 143 * characters from buf. 144 */ 145 io *opencore(char *s, int len) 146 { 147 io *f=new(struct io); 148 char *buf=emalloc(len); 149 f->fd= -1 /*open("/dev/null", 0)*/; 150 f->bufp=f->strp=buf; 151 f->ebuf=buf+len; 152 Memcpy(buf, s, len); 153 return f; 154 } 155 void rewind(io *io) 156 { 157 if(io->fd==-1) io->bufp=io->strp; 158 else{ 159 io->bufp=io->ebuf=io->buf; 160 Seek(io->fd, 0L, 0); 161 } 162 } 163 void closeio(io *io) 164 { 165 if(io->fd>=0) close(io->fd); 166 if(io->strp) efree(io->strp); 167 efree((char *)io); 168 } 169 int emptybuf(io *f) 170 { 171 int n; 172 if(f->fd==-1 || (n=Read(f->fd, f->buf, NBUF))<=0) return EOF; 173 f->bufp=f->buf; 174 f->ebuf=f->buf+n; 175 return *f->bufp++&0xff; 176 } 177