From 425ef692da7e74112f88f0b368f3286dba84f846 Mon Sep 17 00:00:00 2001 From: Nicholas Noll Date: Thu, 18 Jun 2020 19:45:40 -0700 Subject: feat: working parser for rc shell language --- sys/cmd/rc/io.c | 435 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 435 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..8cc2f5b --- /dev/null +++ b/sys/cmd/rc/io.c @@ -0,0 +1,435 @@ +#include "rc.h" + +#undef bufsize +#define c0 t->child[0] +#define c1 t->child[1] +#define c2 t->child[2] + +#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; + + 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 = ""; + + 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 '$': pfmt(f, "$%t", c0); + break; + case '"': pfmt(f, "$\"%t", c0); + break; + case '&': pfmt(f, "%t&", c0); + break; + case '^': pfmt(f, "%t^%t", c0, c1); + break; + case '`': pfmt(f, "`%t", c0); + break; + case Aandand: pfmt(f, "%t && %t", c0, c1); + break; + case Kbang: pfmt(f, "! %t", c0); + break; + case Abrace: pfmt(f, "{%t}", c0); + break; + case Acount: pfmt(f, "$#%t", c0); + break; + case Kfunc: pfmt(f, "fn %t %t", c0, c1); + break; + case Kif: pfmt(f, "if%t%t", c0, c1); + break; + case Kelse: pfmt(f, "else %t", c0); + break; + case Aoror: pfmt(f, "%t || %t", c0, c1); + break; + case Aparen: pfmt(f, "(%t)", c0); + break; + case Asub: pfmt(f, "$%t(%t)", c0, c1); + break; + case Asimple: pfmt(f, "%t", c0); + break; + case Ksubsh: pfmt(f, "@ %t", c0); + break; + case Kswitch: pfmt(f, "switch %t %t", c0, c1); + break; + case Ktwiddle: pfmt(f, "~ %t %t", c0, c1); + break; + case Kwhile: pfmt(f, "while %t%t", c0, c1); + break; + case Aargs: + if(c0==0) + pfmt(f, "%t", c1); + else if(c1==0) + pfmt(f, "%t", c0); + else + pfmt(f, "%t %t", c0, c1); + break; + case ';': + if(c0){ + if(c1) + pfmt(f, "%t%c%t", c0, '\n', c1); + else pfmt(f, "%t", c0); + } + else pfmt(f, "%t", c1); + break; + case Awords: + if(c0) + pfmt(f, "%t ", c0); + pfmt(f, "%t", c1); + break; + case Kfor: + pfmt(f, "for(%t", c0); + if(c1) + pfmt(f, " in %t", c1); + pfmt(f, ")%t", c2); + break; + case Aword: + if(t->quoted) + pfmt(f, "%Q", t->str); + else + pdeglob(f, t->str); + break; + case Adup: + 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 Apipefd: + case Aredir: + 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 '=': + pfmt(f, "%t=%t", c0, c1); + if(c2) + pfmt(f, " %t", c2); + break; + case Apipe: + 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 '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