#include "rc.h" #include "parse.h" #define CAP0 512 Io* openfd(int fd) { Io *io = emalloc(sizeof(*io) + CAP0); io->fd = fd; io->cap = CAP0; io->b = io->e = io->buf; io->s = nil; return io; } Io* openstr(void) { char *s; Io *io = emalloc(sizeof(*io) + CAP0); io->fd = -1; io->cap = CAP0; io->b = io->s = emalloc(101); io->e = io->b+100; for(s = io->b; s<=io->e; s++) *s=0; return io; } #if 0 /* * open a corebuffer to read. EOF occurs after reading len characters from buf */ Io* opencore(char *s, int len) { Io *io = emalloc(sizeof(*io)); char *buf = emalloc(len); io->fd = -1 /*open("/dev/null", 0)*/; io->b = io->s = buf; io->e = buf+len; memcpy(buf, s, len); return io; } #endif void iorewind(Io *io) { if(io->fd==-1) io->b = io->s; else{ io->b = io->e = io->buf; lseek(io->fd, 0L, 0); } } void terminate(Io *io) { if(io->fd>=0) close(io->fd); if(io->s) efree(io->s); efree((char *)io); } static int refill(Io *io) { int n; if(io->fd==-1 || (n = read(io->fd, io->buf, io->cap))<=0) return EOF; io->b = io->buf; io->e = io->buf+n; return *io->b++&0xff; } void flush(Io *io) { int n; char *s; if(io->s){ n = io->e-io->s; io->s = realloc(io->s, n+101); if(io->s==0) panicf("Can't realloc %d bytes in flush!", n+101); io->b = io->s+n; io->e = io->b+100; for(s = io->b;s<=io->e;s++) *s='\0'; }else{ n = io->b-io->buf; if(n && write(io->fd, io->buf, n) < 0) write(3, "write error\n", 12); io->b = io->buf; io->e = io->buf + io->cap; } } static void printchar(Io *io, int c) { if(io->b==io->e) flush(io); *io->b++=c; } void printquote(Io *io, char *s) { printchar(io, '\''); for(;*s;s++) if(*s=='\'') print(io, "''"); else printchar(io, *s); printchar(io, '\''); } void printstr(Io *io, char *s) { if(s==0) s="(null)"; while(*s) printchar(io, *s++); } void printword(Io *io, char *s) { char *t; for(t = s;*t;t++) if(!iswordchar(*t)) break; if(t==s || *t) printquote(io, s); else printstr(io, s); } void printptr(Io *io, void *v) { int n; uintptr p; p = (uintptr)v; if(sizeof(uintptr) == sizeof(uvlong) && p>>32) for(n = 60;n>=32;n-=4) printchar(io, "0123456789ABCDEF"[(p>>n)&0xF]); for(n = 28;n>=0;n-=4) printchar(io, "0123456789ABCDEF"[(p>>n)&0xF]); } static void printint(Io *io, int n) { if(n<0){ if(n!=INT_MIN){ printchar(io, '-'); printint(io, -n); return; } /* n is two's complement minimum integer */ n = -(INT_MIN+1); printchar(io, '-'); printint(io, n/10); printchar(io, n%10+'1'); return; } if(n>9) printint(io, n/10); printchar(io, n%10+'0'); } static void printoct(Io *io, unsigned n) { if(n>7) printoct(io, n>>3); printchar(io, (n&7)+'0'); } static void printval(Io *io, Word *a) { if(a){ while(a->link && a->link->str){ printword(io, a->str); printchar(io, ' '); a = a->link; } printword(io, a->str); } } #define C0 t->child[0] #define C1 t->child[1] #define C2 t->child[2] static void printtree(Io *io, Tree *t) { if(!t) return; switch(t->type){ default: print(io, "bad(%d)[%p %p %p]", t->type, C0, C1, C2); break; case '$': print(io,"$%t",C0); break; case '&': print(io,"%t&",C0); break; case '^': print(io,"%t^%t",C0,C1); break; case '`': print(io,"`%t",C0); break; case Tbasic: print(io, "%t", C0); break; case Tbang: print(io, "!%t", C0); break; case Tblock: print(io, "{%t}", C0); break; case Tcount: print(io, "$#%t", C0); break; case Tparen: print(io, "(%t)", C0); break; case Tjoin: print(io,"$\"%t",C0); break; case Tindex: print(io, "%t(%t)",C0); break; case Tsubshell: print(io, "@ %t",C0); break; //case Ttwiddle: print(io, "~ %t %t", C0, C1); break; case Toror: case Tandand: case Targs: if(!C0) print(io, "%t", C1); else if(!C1) print(io, "%t", C0); else print(io, "%t %t", C0, C1); break; case ';': if(C0){ if(C1) print(io, "%t;%t", C0, C1); else print(io, "%t", C0); }else print(io, "%t", C1); break; case Twords: if(C0) print(io, "%t", C0); print(io, "%t", C1); case Tword: if(t->quoted) print(io, "%Q", t->str); print(io, "%q", t->str); break; case '=': print(io, "%t=%t", C0, C1); if(C2) print(io, " %t", C2); break; case Tdup: if(t->redir.type == Rdupfd) print(io, ">[%d=%d]", t->redir.fd[1], t->redir.fd[0]); else print(io, ">[%d=]", t->redir.fd[0]); print(io, "%t", C1); break; case Tredir: switch(t->redir.type){ case Rhere: printchar(io, '<'); case Rread: printchar(io, '<'); goto readfd; case Rrdwr: printchar(io, '<'); printchar(io, '>'); readfd: if(t->redir.fd[0]!=0) print(io, "[%d]", t->redir.fd[0]); break; case Rappend: printchar(io, '>'); goto writefd; case Rwrite: printchar(io, '>'); printchar(io, '>'); writefd: if(t->redir.fd[0]!=1) print(io, "[%d]", t->redir.fd[0]); break; } print(io, "%t", C0); if(C1) print(io, " %t", C1); break; case Tpipe: print(io, "%t|", C0); if(t->redir.fd[1]==0){ if(t->redir.fd[0]!=1) print(io, "[%d]", t->redir.fd[0]); } else print(io, "[%d=%d]", t->redir.fd[0], t->redir.fd[1]); print(io, "%t", C1); break; } } #undef C0 #undef C1 #undef C2 // ----------------------------------------------------------------------- // exports /* readers */ int get(Io *io) { if(io->b==io->e) return refill(io); return *io->b++ & 0xFF; } /* writers */ int put(Io **iop, char c) { int nb, ne, nc; Io *io = *iop; char *e = io->b + io->cap; if(io->e == e){ nb = io->b - io->buf; ne = io->e - io->buf; nc = 2*io->cap; if(!(io = erealloc(io, sizeof(*io)+nc))) return 0; io->b = io->buf + nb; io->e = io->buf + ne; io->cap = nc; *iop = io; } *io->e++ = c; return 1; } /* printers */ static int pfmtnest; void print(Io *io, char *fmt, ...) { va_list args; char err[ERRMAX]; va_start(args, fmt); pfmtnest++; for(;*fmt;fmt++) if(*fmt!='%') printchar(io, *fmt); else switch(*++fmt){ case '\0': va_end(args); return; case 'c': printchar(io, va_arg(args, int)); break; case 'd': printint(io, va_arg(args, int)); break; case 'o': printoct(io, va_arg(args, unsigned)); break; case 'p': printptr(io, va_arg(args, void*)); break; case 'Q': printquote(io, va_arg(args, char *)); break; case 'q': printword(io, va_arg(args, char *)); break; case 's': printstr(io, va_arg(args, char *)); break; case 't': printtree(io, va_arg(args, struct Tree *)); break; case 'v': printval(io, va_arg(args, struct Word *)); break; default: printchar(io, *fmt); break; } va_end(args); if(--pfmtnest==0) flush(io); }