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.c446
1 files changed, 446 insertions, 0 deletions
diff --git a/sys/cmd/rc/io.c b/sys/cmd/rc/io.c
new file mode 100644
index 0000000..e06bfcc
--- /dev/null
+++ b/sys/cmd/rc/io.c
@@ -0,0 +1,446 @@
+#include "rc.h"
+
+#define c0 t->child[0]
+#define c1 t->child[1]
+#define c2 t->child[2]
+
+#undef bufsize
+#define bufsize 512
+#define strsize 100
+
+//------------------------------------------------------------------------
+// buffer operations
+
+/* open file */
+Io*
+openfd(int fd)
+{
+ Io *f;
+
+ f = emalloc(sizeof *f + bufsize);
+ f->fd = fd;
+ f->b = f->e = f->buf;
+ return f;
+}
+
+/* open string */
+Io*
+openstr(void)
+{
+ Io *f;
+
+ f = emalloc(sizeof *f + strsize + 1);
+ f->fd = -1;
+ f->b = f->buf;
+ f->e = f->buf+strsize;
+ memset(f->b, 0, strsize+1);
+
+ return f;
+}
+
+/* open core (not nil terminated) */
+Io*
+opencore(int len, char *s)
+{
+ Io *f;
+
+ f = emalloc(sizeof *f + len);
+ f->fd = -1;
+ f->b = f->buf;
+ f->e = f->buf+len;
+ memcpy(f->b, s, len);
+
+ return f;
+}
+
+void
+rewindio(Io *f)
+{
+ if (f->fd < 0)
+ f->b = f->buf;
+ else {
+ f->b = f->e = f->buf;
+ lseek(f->fd, 0, 0);
+ }
+}
+
+void
+closeio(Io *f)
+{
+ if (f->fd >= 0)
+ close(f->fd);
+
+ efree(f);
+}
+
+/* has the chance to realloc */
+void
+flush(Io **fp)
+{
+ int n;
+ char *s;
+ Io *f;
+
+ f = *fp;
+ if (f->fd < 0) {
+ n = f->e - f->b;
+ f = erealloc(f, sizeof *f + n + strsize + 1);
+ if (!f)
+ panic("can't realloc %d bytes in flush", n+strsize+1);
+ f->b = f->buf+n;
+ f->e = f->buf+n+strsize;
+ memset(f->b, 0, strsize+1);
+ } else {
+ n = f->b - f->buf;
+ if (n && write(f->fd, f->buf, n) < 0) {
+ write(3, "write error\n", 12);
+ // if (ntrap)
+ // dotrap();
+ }
+ f->b = f->buf;
+ f->e = f->buf + bufsize;
+ }
+
+ *fp = f;
+}
+
+//------------------------------------------------------------------------
+// read from io
+
+int
+rchr(Io *f)
+{
+ int n;
+ if (f->b == f->e) {
+ if (f->fd < 0 || (n = read(f->fd, f->buf, bufsize)) <= 0)
+ return EOF;
+
+ f->b = f->buf;
+ f->e = f->b + n;
+ }
+
+ return *f->b++&0xFF;
+}
+
+//------------------------------------------------------------------------
+// printf functionality
+
+/* character literal */
+int
+pchr(Io *f, int c)
+{
+ if (f->b == f->e)
+ flush(&f);
+
+ return *f->b++=c;
+}
+
+/* quote */
+void
+pquo(Io *f, char *s)
+{
+ pchr(f, '\'');
+ for (; *s; s++)
+ if (*s == '\'')
+ pfmt(f, "''");
+ else
+ pchr(f, *s);
+ pchr(f, '\'');
+}
+
+/* word */
+void
+pwrd(Io *f, char *s)
+{
+ char *t;
+ for(t = s; *t; t++)
+ if(!wordchr(*t))
+ break;
+ if(t == s || *t)
+ pquo(f, s);
+ else
+ pstr(f, s);
+}
+
+/* pointer */
+void
+pptr(Io *f, void *v)
+{
+ int n;
+ uintptr p;
+
+ if (!v) {
+ pstr(f, "<nil>");
+ return;
+ }
+
+ p = (uintptr)v;
+ if ((sizeof(uintptr) == sizeof(uvlong)) && p >>32)
+ for (n = 60; n >= 32; n-=4)
+ pchr(f, "0123456789ABCDEF"[(p>>n)&0xF]);
+ for (n = 28; n >= 0; n-=4)
+ pchr(f, "0123456789ABCDEF"[(p>>n)&0xF]);
+}
+
+/* string */
+void
+pstr(Io *f, char *s)
+{
+ if(!s || !s[0])
+ s = "<null>";
+
+ while(*s)
+ pchr(f, *s++);
+}
+
+/* decimal */
+void
+pdec(Io *f, int n)
+{
+ if (n < 0) {
+ n = -n;
+ pchr(f, '-');
+ if (n >= 0) {
+ pdec(f, n);
+ return;
+ }
+ n = 1 - n;
+ pdec(f, n/10);
+ pchr(f, n%10+'1');
+ return;
+ }
+
+ if (n > 9)
+ pdec(f, n/10);
+ pchr(f, n%10+'0');
+}
+
+/* octal */
+void
+poct(Io *f, uint n)
+{
+ if (n > 7)
+ poct(f, n>>3);
+ pchr(f, (n&7)+'0');
+}
+
+/* value */
+void
+pval(Io *f, Word *a)
+{
+ if(a) {
+ while(a->link && a->link->word) {
+ pwrd(f, a->word);
+ pchr(f, ' ');
+ a = a->link;
+ }
+ pwrd(f, a->word);
+ }
+}
+
+/* tree */
+static
+void
+pdeglob(Io *f, char *s)
+{
+ while(*s){
+ if(*s==GLOB)
+ s++;
+ pchr(f, *s++);
+ }
+}
+
+void
+pcmd(Io *f, Tree *t)
+{
+ if(!t)
+ return;
+
+ switch(t->type){
+ default: pfmt(f, "bad<%d> %p %p %p", t->type, c0, c1, c2);
+ break;
+ case Tdol: pfmt(f, "$%t", c0);
+ break;
+ case Tquote: pfmt(f, "$\"%t", c0);
+ break;
+ case Tand: pfmt(f, "%t&", c0);
+ break;
+ case Tcarot: pfmt(f, "%t^%t", c0, c1);
+ break;
+ case Ttick: pfmt(f, "`%t", c0);
+ break;
+ case Tandand: pfmt(f, "%t && %t", c0, c1);
+ break;
+ case Tbang: pfmt(f, "! %t", c0);
+ break;
+ case Tbrace: pfmt(f, "{%t}", c0);
+ break;
+ case Tcount: pfmt(f, "$#%t", c0);
+ break;
+ case Tfunc: pfmt(f, "func %t %t", c0, c1);
+ break;
+ case Tif: (c2) ? pfmt(f, "if%t%t else %t", c0, c1, c2): pfmt(f, "if%t%t", c0, c1);
+ break;
+ case Toror: pfmt(f, "%t || %t", c0, c1);
+ break;
+ case Tpcmd: /* fallthrough */
+ case Tparen: pfmt(f, "(%t)", c0);
+ break;
+ case Tsub: pfmt(f, "$%t(%t)", c0, c1);
+ break;
+ case Tsimple: pfmt(f, "%t", c0);
+ break;
+ case Tsubshell: pfmt(f, "@ %t", c0);
+ break;
+ case Tswitch: pfmt(f, "switch %t %t", c0, c1);
+ break;
+ case Tcase: pfmt(f, "case %t:\n%t", c0, c1);
+ break;
+ case Ttwiddle: pfmt(f, "~ %t %t", c0, c1);
+ break;
+ case Twhile: pfmt(f, "while %t%t", c0, c1);
+ break;
+ case Targs:
+ if(c0==0)
+ pfmt(f, "%t", c1);
+ else if(c1==0)
+ pfmt(f, "%t", c0);
+ else
+ pfmt(f, "%t %t", c0, c1);
+ break;
+ case Tsemi:
+ if(c0) {
+ if(c1)
+ pfmt(f, "%t%c%t", c0, '\n', c1);
+ else
+ pfmt(f, "%t", c0);
+ } else
+ pfmt(f, "%t", c1);
+ break;
+ case Twords:
+ if(c0)
+ pfmt(f, "%t ", c0);
+ pfmt(f, "%t", c1);
+ break;
+ case Tfor:
+ pfmt(f, "for(%t", c0);
+ if(c1)
+ pfmt(f, " in %t", c1);
+ pfmt(f, ")%t", c2);
+ break;
+ case Tword:
+ if(t->quoted)
+ pfmt(f, "%Q", t->str);
+ else
+ pdeglob(f, t->str);
+ break;
+ case Tdup:
+ if(t->redir.type==Rdupfd)
+ pfmt(f, ">[%d=%d]", t->redir.fd[1], t->redir.fd[0]); /* yes, fd1, then fd0; read lex.c */
+ else
+ pfmt(f, ">[%d=]", t->redir.fd[0]);
+ pfmt(f, "%t", c1);
+ break;
+ case Tpipefd:
+ case Tredir:
+ switch(t->redir.type){
+ case Rhere:
+ pchr(f, '<');
+ case Rread:
+ case Rrdwr:
+ pchr(f, '<');
+ if(t->redir.type==Rrdwr)
+ pchr(f, '>');
+ if(t->redir.fd[0]!=0)
+ pfmt(f, "[%d]", t->redir.fd[0]);
+ break;
+ case Rappend:
+ pchr(f, '>');
+ case Rwrite:
+ pchr(f, '>');
+ if(t->redir.fd[0]!=1)
+ pfmt(f, "[%d]", t->redir.fd[0]);
+ break;
+ }
+ pfmt(f, "%t", c0);
+ if(c1)
+ pfmt(f, " %t", c1);
+ break;
+ case Teq:
+ pfmt(f, "%t=%t", c0, c1);
+ if(c2)
+ pfmt(f, " %t", c2);
+ break;
+ case Tpipe:
+ pfmt(f, "%t|", c0);
+ if(t->redir.fd[1]==0){
+ if(t->redir.fd[0]!=1)
+ pfmt(f, "[%d]", t->redir.fd[0]);
+ }
+ else pfmt(f, "[%d=%d]", t->redir.fd[0], t->redir.fd[1]);
+ pfmt(f, "%t", c1);
+ break;
+ }
+}
+
+/* rc specific printf */
+static int pfmtlev;
+
+void
+vpfmt(Io *f, char *fmt, va_list args)
+{
+ char err[124];
+
+ pfmtlev++;
+ for (; *fmt; fmt++)
+ if (*fmt!='%')
+ pchr(f, *fmt);
+ else switch(*++fmt) {
+ case '\0':
+ break;
+ case 'c':
+ pchr(f, va_arg(args, int));
+ break;
+ case 'd':
+ pdec(f, va_arg(args, int));
+ break;
+ case 'o':
+ poct(f, va_arg(args, uint));
+ break;
+ case 'p':
+ pptr(f, va_arg(args, void*));
+ break;
+ case 'Q':
+ pquo(f, va_arg(args, char*));
+ break;
+ case 'q':
+ pwrd(f, va_arg(args, char*));
+ break;
+ case 'r':
+ pstr(f, strerror(errno));
+ break;
+ case 's':
+ pstr(f, va_arg(args, char*));
+ break;
+ case 't':
+ pcmd(f, va_arg(args, Tree*));
+ break;
+ case 'v':
+ pval(f, va_arg(args, Word*));
+ break;
+ }
+
+ if (--pfmtlev==0)
+ flush(&f);
+}
+
+void
+pfmt(Io *f, char *fmt, ...)
+{
+ va_list args;
+ char err[124];
+
+ va_start(args, fmt);
+ vpfmt(f, fmt, args);
+ va_end(args);
+}