aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/rc/io.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/rc/io.c')
-rw-r--r--src/cmd/rc/io.c437
1 files changed, 437 insertions, 0 deletions
diff --git a/src/cmd/rc/io.c b/src/cmd/rc/io.c
new file mode 100644
index 0000000..dc81c2e
--- /dev/null
+++ b/src/cmd/rc/io.c
@@ -0,0 +1,437 @@
+#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);
+}