sync with plan 9
This commit is contained in:
278
src/cmd/rc/lex.c
278
src/cmd/rc/lex.c
@@ -4,11 +4,15 @@
|
||||
#include "getflags.h"
|
||||
#include "fns.h"
|
||||
int getnext(void);
|
||||
int wordchr(int c)
|
||||
|
||||
int
|
||||
wordchr(int c)
|
||||
{
|
||||
return !strchr("\n \t#;&|^$=`'{}()<>", c) && c!=EOF;
|
||||
}
|
||||
int idchr(int c)
|
||||
|
||||
int
|
||||
idchr(int c)
|
||||
{
|
||||
/*
|
||||
* Formerly:
|
||||
@@ -17,127 +21,170 @@ int idchr(int c)
|
||||
*/
|
||||
return c>' ' && !strchr("!\"#$%&'()+,-./:;<=>?@[\\]^`{|}~", c);
|
||||
}
|
||||
int future=EOF;
|
||||
int doprompt=1;
|
||||
int future = EOF;
|
||||
int doprompt = 1;
|
||||
int inquote;
|
||||
int incomm;
|
||||
/*
|
||||
* Look ahead in the input stream
|
||||
*/
|
||||
int nextc(void){
|
||||
if(future==EOF) future=getnext();
|
||||
|
||||
int
|
||||
nextc(void)
|
||||
{
|
||||
if(future==EOF)
|
||||
future = getnext();
|
||||
return future;
|
||||
}
|
||||
/*
|
||||
* Consume the lookahead character.
|
||||
*/
|
||||
int advance(void){
|
||||
int c=nextc();
|
||||
lastc=future;
|
||||
future=EOF;
|
||||
|
||||
int
|
||||
advance(void)
|
||||
{
|
||||
int c = nextc();
|
||||
lastc = future;
|
||||
future = EOF;
|
||||
return c;
|
||||
}
|
||||
/*
|
||||
* read a character from the input stream
|
||||
*/
|
||||
int getnext(void){
|
||||
register int c;
|
||||
static int peekc=EOF;
|
||||
|
||||
int
|
||||
getnext(void)
|
||||
{
|
||||
int c;
|
||||
static int peekc = EOF;
|
||||
if(peekc!=EOF){
|
||||
c=peekc;
|
||||
peekc=EOF;
|
||||
c = peekc;
|
||||
peekc = EOF;
|
||||
return c;
|
||||
}
|
||||
if(runq->eof) return EOF;
|
||||
if(doprompt) pprompt();
|
||||
c=rchr(runq->cmdfd);
|
||||
if(runq->eof)
|
||||
return EOF;
|
||||
if(doprompt)
|
||||
pprompt();
|
||||
c = rchr(runq->cmdfd);
|
||||
if(!inquote && c=='\\'){
|
||||
c=rchr(runq->cmdfd);
|
||||
if(c=='\n'){
|
||||
doprompt=1;
|
||||
c = rchr(runq->cmdfd);
|
||||
if(c=='\n' && !incomm){ /* don't continue a comment */
|
||||
doprompt = 1;
|
||||
c=' ';
|
||||
}
|
||||
else{
|
||||
peekc=c;
|
||||
peekc = c;
|
||||
c='\\';
|
||||
}
|
||||
}
|
||||
doprompt=doprompt || c=='\n' || c==EOF;
|
||||
if(c==EOF) runq->eof++;
|
||||
doprompt = doprompt || c=='\n' || c==EOF;
|
||||
if(c==EOF)
|
||||
runq->eof++;
|
||||
else if(flag['V'] || ndot>=2 && flag['v']) pchr(err, c);
|
||||
return c;
|
||||
}
|
||||
void pprompt(void){
|
||||
|
||||
void
|
||||
pprompt(void)
|
||||
{
|
||||
var *prompt;
|
||||
if(runq->iflag){
|
||||
pstr(err, promptstr);
|
||||
flush(err);
|
||||
prompt=vlook("prompt");
|
||||
prompt = vlook("prompt");
|
||||
if(prompt->val && prompt->val->next)
|
||||
promptstr=prompt->val->next->word;
|
||||
promptstr = prompt->val->next->word;
|
||||
else
|
||||
promptstr="\t";
|
||||
}
|
||||
runq->lineno++;
|
||||
doprompt=0;
|
||||
doprompt = 0;
|
||||
}
|
||||
void skipwhite(void){
|
||||
|
||||
void
|
||||
skipwhite(void)
|
||||
{
|
||||
int c;
|
||||
for(;;){
|
||||
c=nextc();
|
||||
if(c=='#'){ /* Why did this used to be if(!inquote && c=='#') ?? */
|
||||
c = nextc();
|
||||
/* Why did this used to be if(!inquote && c=='#') ?? */
|
||||
if(c=='#'){
|
||||
incomm = 1;
|
||||
for(;;){
|
||||
c=nextc();
|
||||
if(c=='\n' || c==EOF) break;
|
||||
c = nextc();
|
||||
if(c=='\n' || c==EOF) {
|
||||
incomm = 0;
|
||||
break;
|
||||
}
|
||||
advance();
|
||||
}
|
||||
}
|
||||
if(c==' ' || c=='\t') advance();
|
||||
if(c==' ' || c=='\t')
|
||||
advance();
|
||||
else return;
|
||||
}
|
||||
}
|
||||
void skipnl(void){
|
||||
register int c;
|
||||
|
||||
void
|
||||
skipnl(void)
|
||||
{
|
||||
int c;
|
||||
for(;;){
|
||||
skipwhite();
|
||||
c=nextc();
|
||||
if(c!='\n') return;
|
||||
c = nextc();
|
||||
if(c!='\n')
|
||||
return;
|
||||
advance();
|
||||
}
|
||||
}
|
||||
int nextis(int c){
|
||||
|
||||
int
|
||||
nextis(int c)
|
||||
{
|
||||
if(nextc()==c){
|
||||
advance();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
char *addtok(char *p, int val){
|
||||
if(p==0) return 0;
|
||||
|
||||
char*
|
||||
addtok(char *p, int val)
|
||||
{
|
||||
if(p==0)
|
||||
return 0;
|
||||
if(p==&tok[NTOK-1]){
|
||||
*p=0;
|
||||
*p = 0;
|
||||
yyerror("token buffer too short");
|
||||
return 0;
|
||||
}
|
||||
*p++=val;
|
||||
return p;
|
||||
}
|
||||
char *addutf(char *p, int c){
|
||||
p=addtok(p, c);
|
||||
|
||||
char*
|
||||
addutf(char *p, int c)
|
||||
{
|
||||
p = addtok(p, c);
|
||||
if(twobyte(c)) /* 2-byte escape */
|
||||
return addtok(p, advance());
|
||||
if(threebyte(c)){ /* 3-byte escape */
|
||||
p=addtok(p, advance());
|
||||
p = addtok(p, advance());
|
||||
return addtok(p, advance());
|
||||
}
|
||||
return p;
|
||||
}
|
||||
int lastdol; /* was the last token read '$' or '$#' or '"'? */
|
||||
int lastword; /* was the last token read a word or compound word terminator? */
|
||||
int yylex(void){
|
||||
register int c, d=nextc();
|
||||
register char *w=tok;
|
||||
register struct tree *t;
|
||||
yylval.tree=0;
|
||||
|
||||
int
|
||||
yylex(void)
|
||||
{
|
||||
int c, d = nextc();
|
||||
char *w = tok;
|
||||
struct tree *t;
|
||||
yylval.tree = 0;
|
||||
/*
|
||||
* Embarassing sneakiness: if the last token read was a quoted or unquoted
|
||||
* WORD then we alter the meaning of what follows. If the next character
|
||||
@@ -146,7 +193,7 @@ int yylex(void){
|
||||
* we insert a `^' before it.
|
||||
*/
|
||||
if(lastword){
|
||||
lastword=0;
|
||||
lastword = 0;
|
||||
if(d=='('){
|
||||
advance();
|
||||
strcpy(tok, "( [SUB]");
|
||||
@@ -157,15 +204,15 @@ int yylex(void){
|
||||
return '^';
|
||||
}
|
||||
}
|
||||
inquote=0;
|
||||
inquote = 0;
|
||||
skipwhite();
|
||||
switch(c=advance()){
|
||||
switch(c = advance()){
|
||||
case EOF:
|
||||
lastdol=0;
|
||||
lastdol = 0;
|
||||
strcpy(tok, "EOF");
|
||||
return EOF;
|
||||
case '$':
|
||||
lastdol=1;
|
||||
lastdol = 1;
|
||||
if(nextis('#')){
|
||||
strcpy(tok, "$#");
|
||||
return COUNT;
|
||||
@@ -177,7 +224,7 @@ int yylex(void){
|
||||
strcpy(tok, "$");
|
||||
return '$';
|
||||
case '&':
|
||||
lastdol=0;
|
||||
lastdol = 0;
|
||||
if(nextis('&')){
|
||||
skipnl();
|
||||
strcpy(tok, "&&");
|
||||
@@ -186,7 +233,7 @@ int yylex(void){
|
||||
strcpy(tok, "&");
|
||||
return '&';
|
||||
case '|':
|
||||
lastdol=0;
|
||||
lastdol = 0;
|
||||
if(nextis(c)){
|
||||
skipnl();
|
||||
strcpy(tok, "||");
|
||||
@@ -194,7 +241,7 @@ int yylex(void){
|
||||
}
|
||||
case '<':
|
||||
case '>':
|
||||
lastdol=0;
|
||||
lastdol = 0;
|
||||
/*
|
||||
* funny redirection tokens:
|
||||
* redir: arrow | arrow '[' fd ']'
|
||||
@@ -204,121 +251,128 @@ int yylex(void){
|
||||
* some possibilities are nonsensical and get a message.
|
||||
*/
|
||||
*w++=c;
|
||||
t=newtree();
|
||||
t = newtree();
|
||||
switch(c){
|
||||
case '|':
|
||||
t->type=PIPE;
|
||||
t->fd0=1;
|
||||
t->fd1=0;
|
||||
t->type = PIPE;
|
||||
t->fd0 = 1;
|
||||
t->fd1 = 0;
|
||||
break;
|
||||
case '>':
|
||||
t->type=REDIR;
|
||||
t->type = REDIR;
|
||||
if(nextis(c)){
|
||||
t->rtype=APPEND;
|
||||
t->rtype = APPEND;
|
||||
*w++=c;
|
||||
}
|
||||
else t->rtype=WRITE;
|
||||
t->fd0=1;
|
||||
else t->rtype = WRITE;
|
||||
t->fd0 = 1;
|
||||
break;
|
||||
case '<':
|
||||
t->type=REDIR;
|
||||
t->type = REDIR;
|
||||
if(nextis(c)){
|
||||
t->rtype=HERE;
|
||||
t->rtype = HERE;
|
||||
*w++=c;
|
||||
}
|
||||
else t->rtype=READ;
|
||||
t->fd0=0;
|
||||
} else if (nextis('>')){
|
||||
t->rtype = RDWR;
|
||||
*w++=c;
|
||||
} else t->rtype = READ;
|
||||
t->fd0 = 0;
|
||||
break;
|
||||
}
|
||||
if(nextis('[')){
|
||||
*w++='[';
|
||||
c=advance();
|
||||
c = advance();
|
||||
*w++=c;
|
||||
if(c<'0' || '9'<c){
|
||||
RedirErr:
|
||||
*w++ = c;
|
||||
*w=0;
|
||||
*w = 0;
|
||||
yyerror(t->type==PIPE?"pipe syntax"
|
||||
:"redirection syntax");
|
||||
return EOF;
|
||||
}
|
||||
t->fd0=0;
|
||||
t->fd0 = 0;
|
||||
do{
|
||||
t->fd0=t->fd0*10+c-'0';
|
||||
t->fd0 = t->fd0*10+c-'0';
|
||||
*w++=c;
|
||||
c=advance();
|
||||
c = advance();
|
||||
}while('0'<=c && c<='9');
|
||||
if(c=='='){
|
||||
*w++='=';
|
||||
if(t->type==REDIR) t->type=DUP;
|
||||
c=advance();
|
||||
if(t->type==REDIR)
|
||||
t->type = DUP;
|
||||
c = advance();
|
||||
if('0'<=c && c<='9'){
|
||||
t->rtype=DUPFD;
|
||||
t->fd1=t->fd0;
|
||||
t->fd0=0;
|
||||
t->rtype = DUPFD;
|
||||
t->fd1 = t->fd0;
|
||||
t->fd0 = 0;
|
||||
do{
|
||||
t->fd0=t->fd0*10+c-'0';
|
||||
t->fd0 = t->fd0*10+c-'0';
|
||||
*w++=c;
|
||||
c=advance();
|
||||
c = advance();
|
||||
}while('0'<=c && c<='9');
|
||||
}
|
||||
else{
|
||||
if(t->type==PIPE) goto RedirErr;
|
||||
t->rtype=CLOSE;
|
||||
if(t->type==PIPE)
|
||||
goto RedirErr;
|
||||
t->rtype = CLOSE;
|
||||
}
|
||||
}
|
||||
*w=0;
|
||||
if(c!=']'
|
||||
|| t->type==DUP && (t->rtype==HERE || t->rtype==APPEND))
|
||||
goto RedirErr;
|
||||
*w++=']';
|
||||
}
|
||||
*w='\0';
|
||||
yylval.tree=t;
|
||||
if(t->type==PIPE) skipnl();
|
||||
yylval.tree = t;
|
||||
if(t->type==PIPE)
|
||||
skipnl();
|
||||
return t->type;
|
||||
case '\'':
|
||||
lastdol=0;
|
||||
lastword=1;
|
||||
inquote=1;
|
||||
lastdol = 0;
|
||||
lastword = 1;
|
||||
inquote = 1;
|
||||
for(;;){
|
||||
c=advance();
|
||||
if(c==EOF) break;
|
||||
c = advance();
|
||||
if(c==EOF)
|
||||
break;
|
||||
if(c=='\''){
|
||||
if(nextc()!='\'')
|
||||
break;
|
||||
advance();
|
||||
}
|
||||
w=addutf(w, c);
|
||||
w = addutf(w, c);
|
||||
}
|
||||
if(w!=0) *w='\0';
|
||||
t=token(tok, WORD);
|
||||
t->quoted=1;
|
||||
yylval.tree=t;
|
||||
if(w!=0)
|
||||
*w='\0';
|
||||
t = token(tok, WORD);
|
||||
t->quoted = 1;
|
||||
yylval.tree = t;
|
||||
return t->type;
|
||||
}
|
||||
if(!wordchr(c)){
|
||||
lastdol=0;
|
||||
tok[0]=c;
|
||||
lastdol = 0;
|
||||
tok[0] = c;
|
||||
tok[1]='\0';
|
||||
return c;
|
||||
}
|
||||
for(;;){
|
||||
/* next line should have (char)c==GLOB, but ken's compiler is broken */
|
||||
if(c=='*' || c=='[' || c=='?' || c==(unsigned char)GLOB)
|
||||
w=addtok(w, GLOB);
|
||||
w=addutf(w, c);
|
||||
c=nextc();
|
||||
w = addtok(w, GLOB);
|
||||
w = addutf(w, c);
|
||||
c = nextc();
|
||||
if(lastdol?!idchr(c):!wordchr(c)) break;
|
||||
advance();
|
||||
}
|
||||
|
||||
lastword=1;
|
||||
lastdol=0;
|
||||
if(w!=0) *w='\0';
|
||||
t=klook(tok);
|
||||
if(t->type!=WORD) lastword=0;
|
||||
t->quoted=0;
|
||||
yylval.tree=t;
|
||||
lastword = 1;
|
||||
lastdol = 0;
|
||||
if(w!=0)
|
||||
*w='\0';
|
||||
t = klook(tok);
|
||||
if(t->type!=WORD)
|
||||
lastword = 0;
|
||||
t->quoted = 0;
|
||||
yylval.tree = t;
|
||||
return t->type;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user