aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Noll <nbnoll@eml.cc>2021-10-21 11:17:15 -0700
committerNicholas Noll <nbnoll@eml.cc>2021-10-21 11:17:15 -0700
commit5c20d687c495f2cb3f3a390d04854dcceb2ef74e (patch)
treed32a8c4e419856d4028dd7e12c0d4f2379a7113e
parent89e6da0a7cc2cd8551ae31ac623232a0ccce905d (diff)
feat(rc): expanded tree printing
-rw-r--r--sys/cmd/rc/io.c120
-rw-r--r--sys/cmd/rc/lex.c75
-rw-r--r--sys/cmd/rc/main.c2
-rw-r--r--sys/cmd/rc/rc.h7
-rw-r--r--sys/cmd/rc/sys.c4
5 files changed, 177 insertions, 31 deletions
diff --git a/sys/cmd/rc/io.c b/sys/cmd/rc/io.c
index 7f2d869..f033031 100644
--- a/sys/cmd/rc/io.c
+++ b/sys/cmd/rc/io.c
@@ -216,6 +216,10 @@ printval(Io *io, Word *a)
}
}
+#define C0 t->child[0]
+#define C1 t->child[1]
+#define C2 t->child[2]
+
static
void
printtree(Io *io, Tree *t)
@@ -224,42 +228,116 @@ printtree(Io *io, Tree *t)
return;
switch(t->type){
- case Tword:
- print(io,"{%s}",t->str);
- break;
-
- case Tbasic:
- print(io, ">%t", t->child[0]);
- break;
+ 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&",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 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(!t->child[0])
- print(io, "%t", t->child[1]);
- else if(!t->child[1])
- print(io, "%t", t->child[0]);
+ if(!C0)
+ print(io, "%t", C1);
+ else if(!C1)
+ print(io, "%t", C0);
else
- print(io, "[%t %t]", t->child[0], t->child[1]);
+ print(io, "%t %t", C0, C1);
break;
case ';':
- if(t->child[0]){
- if(t->child[1])
- print(io, ";[%t %t]", t->child[0], t->child[1]);
+ if(C0){
+ if(C1)
+ print(io, "%t;%t", C0, C1);
else
- print(io, "%t", t->child[0]);
+ print(io, "%t", C0);
}else
- print(io, "%t", t->child[1]);
+ print(io, "%t", C1);
break;
- case '&':
- print(io, "&(%t)", t->child[0]);
+ 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;
- default:
- print(io, "bad(%d)[%p %p %p]", t->type, t->child[0], t->child[1], t->child[2]);
+ 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
diff --git a/sys/cmd/rc/lex.c b/sys/cmd/rc/lex.c
index eb3a268..31c7cdc 100644
--- a/sys/cmd/rc/lex.c
+++ b/sys/cmd/rc/lex.c
@@ -10,6 +10,9 @@ struct Lexer
{
int c[2];
ushort doprompt;
+ ushort hadword;
+ ushort haddollar;
+ ushort inquote;
char buf[BUFSIZ];
};
@@ -166,6 +169,7 @@ putrune(char *buf, int c)
// -----------------------------------------------------------------------
// exported functions
+// TODO: turn into static tables
int
iswordchar(int c)
{
@@ -173,33 +177,59 @@ iswordchar(int c)
}
int
+isidentchar(int c)
+{
+ return c>' ' && !strchr("!\"#$%&'()+,-./:;<=>?@[\\]^`{|}~", c);
+}
+
+int
yylex(void)
{
- int c;
+ int c, d = peekc();
Tree *node;
char *w = lexer.buf;
yylval.tree = nil;
+ /* inject tokens */
+ if(lexer.hadword){
+ if(d=='('){
+ advance();
+ strcpy(lexer.buf, "( [Tindex]");
+ return Tindex;
+ }
+ if(iswordchar(d) || d=='\'' || d=='`' || d=='$' || d=='"'){
+ strcpy(lexer.buf, "^");
+ return '^';
+ }
+ }
+
+ lexer.inquote = 0;
+
skipws();
switch(c=advance()){
case EOF:
+ lexer.haddollar = 0;
put3('E','O','F');
return EOF;
case '@':
+ lexer.haddollar = 0;
put1('@');
return Tsubshell;
case '!':
+ lexer.haddollar = 0;
put1('!');
return Tbang;
case '&':
+ lexer.haddollar = 0;
put1('&');
return '&';
case '|':
+ lexer.haddollar = 0;
if(nextis('|')){
put2('|','|');
return Toror;
@@ -213,6 +243,7 @@ yylex(void)
goto redir;
case '>':
+ lexer.haddollar = 0;
node = maketree();
*w++ = '>';
node->type = Tredir;
@@ -226,6 +257,7 @@ yylex(void)
goto redir;
case '<':
+ lexer.haddollar = 0;
node = maketree();
*w++ = '<';
node->type = Tredir;
@@ -270,7 +302,7 @@ yylex(void)
goto badredir;
node->redir.type = Rclose;
}else{
- node->redir.type = Rdup;
+ node->redir.type = Rdupfd;
node->redir.fd[1] = node->redir.fd[0];
node->redir.fd[0] = 0;
do{
@@ -289,6 +321,7 @@ yylex(void)
return node->type;
case '$':
+ lexer.haddollar = 1;
if(nextis('#')){
put2('$','#');
return Tcount;
@@ -300,22 +333,54 @@ yylex(void)
put1('$');
return '$';
+ case '\'':
+ lexer.hadword = 1;
+ lexer.inquote = 1;
+ lexer.haddollar = 0;
+ for(;;){
+ c = advance();
+ if(c==EOF)
+ break;
+
+ if(c=='\''){
+ if(peekc()!='\'')
+ break;
+ advance();
+ }
+ w = putrune(w, c);
+ }
+ if(w)
+ *w = 0;
+ node = token(Tword, lexer.buf);
+ node->quoted = 1;
+ return node->type;
+
default:
;
}
- if(!iswordchar(c))
+ if(!iswordchar(c)){
+ put1(c);
+ lexer.haddollar = 0;
return c;
+ }
for(;;){
w = putrune(w, c);
c = peekc();
- if(!iswordchar(c))
+ if(lexer.haddollar ? !isidentchar(c) : !iswordchar(c))
break;
advance();
}
- w[0] = 0;
+
+ lexer.hadword = 1;
+ lexer.haddollar = 0;
+ if(w)
+ *w = 0;
node = token(Tword, lexer.buf);
+ // TODO: keywords
+
+ node->quoted = 0;
yylval.tree = node;
return node->type;
diff --git a/sys/cmd/rc/main.c b/sys/cmd/rc/main.c
index 86c6792..3f2e02e 100644
--- a/sys/cmd/rc/main.c
+++ b/sys/cmd/rc/main.c
@@ -58,6 +58,6 @@ main(int argc, char *argv[])
initpath();
initshell();
- enablevi();
+ // enablevi();
xboot(argc, argv);
}
diff --git a/sys/cmd/rc/rc.h b/sys/cmd/rc/rc.h
index d3fc7bf..13444e6 100644
--- a/sys/cmd/rc/rc.h
+++ b/sys/cmd/rc/rc.h
@@ -29,7 +29,7 @@ enum
Rwrite,
Rread,
Rhere,
- Rdup,
+ Rdupfd,
Ropen,
Rclose,
Rrdwr
@@ -39,7 +39,10 @@ struct Tree
{
int type;
union{
- char *str; // Tword
+ struct {
+ ushort quoted;
+ char *str; // Tword
+ };
struct {
ushort type; // Tpipe, Tredir, Tdup
int fd[2];
diff --git a/sys/cmd/rc/sys.c b/sys/cmd/rc/sys.c
index a24545f..86c430e 100644
--- a/sys/cmd/rc/sys.c
+++ b/sys/cmd/rc/sys.c
@@ -103,7 +103,7 @@ redirect(Redir *r)
close(r->from);
}
break;
- case Rdup:
+ case Rdupfd:
dup2(r->from, r->to); // TODO: error checking
break;
case Rclose:
@@ -125,7 +125,7 @@ mapfd(int fd)
if(r->from == fd)
fd = -1;
break;
- case Rdup:
+ case Rdupfd:
case Ropen:
if(r->to == fd)
fd = r->from;