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