aboutsummaryrefslogtreecommitdiff
path: root/sys/cmd/rc/lex.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/cmd/rc/lex.c')
-rw-r--r--sys/cmd/rc/lex.c75
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;