From 6f2cac23a7e759c464ef52103fac929e1eeb6b10 Mon Sep 17 00:00:00 2001 From: Nicholas Noll Date: Sat, 9 Oct 2021 10:30:50 -0700 Subject: feat(rc): added shell --- sys/cmd/rc/io.c | 446 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 446 insertions(+) create mode 100644 sys/cmd/rc/io.c (limited to 'sys/cmd/rc/io.c') 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, ""); + 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 = ""; + + 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); +} -- cgit v1.2.1