aboutsummaryrefslogtreecommitdiff
path: root/sys/cmd/rc/io.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/cmd/rc/io.c')
-rw-r--r--sys/cmd/rc/io.c359
1 files changed, 359 insertions, 0 deletions
diff --git a/sys/cmd/rc/io.c b/sys/cmd/rc/io.c
new file mode 100644
index 0000000..7f2d869
--- /dev/null
+++ b/sys/cmd/rc/io.c
@@ -0,0 +1,359 @@
+#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);
+ }
+}
+
+static
+void
+printtree(Io *io, Tree *t)
+{
+ if(!t)
+ return;
+
+ switch(t->type){
+ case Tword:
+ print(io,"{%s}",t->str);
+ break;
+
+ case Tbasic:
+ print(io, ">%t", t->child[0]);
+ break;
+
+ case Targs:
+ if(!t->child[0])
+ print(io, "%t", t->child[1]);
+ else if(!t->child[1])
+ print(io, "%t", t->child[0]);
+ else
+ print(io, "[%t %t]", t->child[0], t->child[1]);
+ break;
+
+ case ';':
+ if(t->child[0]){
+ if(t->child[1])
+ print(io, ";[%t %t]", t->child[0], t->child[1]);
+ else
+ print(io, "%t", t->child[0]);
+ }else
+ print(io, "%t", t->child[1]);
+ break;
+
+ case '&':
+ print(io, "&(%t)", t->child[0]);
+ break;
+
+ default:
+ print(io, "bad(%d)[%p %p %p]", t->type, t->child[0], t->child[1], t->child[2]);
+ }
+}
+
+// -----------------------------------------------------------------------
+// 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);
+}