diff options
Diffstat (limited to 'sys/cmd/rc/lex.c')
-rw-r--r-- | sys/cmd/rc/lex.c | 75 |
1 files changed, 70 insertions, 5 deletions
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; |