Logo Search packages:      
Sourcecode: 9base version File versions  Download package

lex.c

#include "rc.h"
#include "exec.h"
#include "io.h"
#include "getflags.h"
#include "fns.h"
int getnext(void);
int wordchr(int c)
{
      return !strchr("\n \t#;&|^$=`'{}()<>", c) && c!=EOF;
}
int idchr(int c)
{
      /*
       * Formerly:
       * return 'a'<=c && c<='z' || 'A'<=c && c<='Z' || '0'<=c && c<='9'
       *    || c=='_' || c=='*';
       */
      return c>' ' && !strchr("!\"#$%&'()+,-./:;<=>?@[\\]^`{|}~", c);
}
int future=EOF;
int doprompt=1;
int inquote;
/*
 * Look ahead in the input stream
 */
int nextc(void){
      if(future==EOF) future=getnext();
      return future;
}
/*
 * Consume the lookahead character.
 */
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;
      if(peekc!=EOF){
            c=peekc;
            peekc=EOF;
            return c;
      }
      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=' ';
            }
            else{
                  peekc=c;
                  c='\\';
            }
      }
      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){
      var *prompt;
      if(runq->iflag){
            pstr(err, promptstr);
            flush(err);
            prompt=vlook("prompt");
            if(prompt->val && prompt->val->next)
                  promptstr=prompt->val->next->word;
            else
                  promptstr="\t";
      }
      runq->lineno++;
      doprompt=0;
}
void skipwhite(void){
      int c;
      for(;;){
            c=nextc();
            if(c=='#'){ /* Why did this used to be  if(!inquote && c=='#') ?? */
                  for(;;){
                        c=nextc();
                        if(c=='\n' || c==EOF) break;
                        advance();
                  }
            }
            if(c==' ' || c=='\t') advance();
            else return;
      }
}
void skipnl(void){
      register int c;
      for(;;){
            skipwhite();
            c=nextc();
            if(c!='\n') return;
            advance();
      }
}
int nextis(int c){
      if(nextc()==c){
            advance();
            return 1;
      }
      return 0;
}
char *addtok(char *p, int val){
      if(p==0) return 0;
      if(p==&tok[NTOK]){
            *p=0;
            yyerror("token buffer too short");
            return 0;
      }
      *p++=val;
      return p;
}
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());
            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;
      /*
       * 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
       * is `(', we return SUB (a subscript paren) and consume the `('.  Otherwise,
       * if the next character is the first character of a simple or compound word,
       * we insert a `^' before it.
       */
      if(lastword){
            lastword=0;
            if(d=='('){
                  advance();
                  strcpy(tok, "( [SUB]");
                  return SUB;
            }
            if(wordchr(d) || d=='\'' || d=='`' || d=='$' || d=='"'){
                  strcpy(tok, "^");
                  return '^';
            }
      }
      inquote=0;
      skipwhite();
      switch(c=advance()){
      case EOF:
            lastdol=0;
            strcpy(tok, "EOF");
            return EOF;
      case '$':
            lastdol=1;
            if(nextis('#')){
                  strcpy(tok, "$#");
                  return COUNT;
            }
            if(nextis('"')){
                  strcpy(tok, "$\"");
                  return '"';
            }
            strcpy(tok, "$");
            return '$';
      case '&':
            lastdol=0;
            if(nextis('&')){
                  skipnl();
                  strcpy(tok, "&&");
                  return ANDAND;
            }
            strcpy(tok, "&");
            return '&';
      case '|':
            lastdol=0;
            if(nextis(c)){
                  skipnl();
                  strcpy(tok, "||");
                  return OROR;
            }
      case '<':
      case '>':
            lastdol=0;
            /*
             * funny redirection tokens:
             *    redir:      arrow | arrow '[' fd ']'
             *    arrow:      '<' | '<<' | '>' | '>>' | '|'
             *    fd:   digit | digit '=' | digit '=' digit
             *    digit:      '0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9'
             * some possibilities are nonsensical and get a message.
             */
            *w++=c;
            t=newtree();
            switch(c){
            case '|':
                  t->type=PIPE;
                  t->fd0=1;
                  t->fd1=0;
                  break;
            case '>':
                  t->type=REDIR;
                  if(nextis(c)){
                        t->rtype=APPEND;
                        *w++=c;
                  }
                  else t->rtype=WRITE;
                  t->fd0=1;
                  break;
            case '<':
                  t->type=REDIR;
                  if(nextis(c)){
                        t->rtype=HERE;
                        *w++=c;
                  }
                  else t->rtype=READ;
                  t->fd0=0;
                  break;
            }
            if(nextis('[')){
                  *w++='[';
                  c=advance();
                  if(c<'0' || '9'<c){
                  RedirErr:
                        *w++ = c;
                        *w=0;
                        yyerror(t->type==PIPE?"pipe syntax"
                                    :"redirection syntax");
                        return EOF;
                  }
                  t->fd0=0;
                  do{
                        t->fd0=t->fd0*10+c-'0';
                        *w++=c;
                        c=advance();
                  }while('0'<=c && c<='9');
                  if(c=='='){
                        *w++='=';
                        if(t->type==REDIR) t->type=DUP;
                        c=advance();
                        if('0'<=c && c<='9'){
                              t->rtype=DUPFD;
                              t->fd1=t->fd0;
                              t->fd0=0;
                              do{
                                    t->fd0=t->fd0*10+c-'0';
                                    *w++=c;
                                    c=advance();
                              }while('0'<=c && c<='9');
                        }
                        else{
                              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();
            return t->type;
      case '\'':
            lastdol=0;
            lastword=1;
            inquote=1;
            for(;;){
                  c=advance();
                  if(c==EOF) break;
                  if(c=='\''){
                        if(nextc()!='\'')
                              break;
                        advance();
                  }
                  w=addutf(w, c);
            }
            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;
            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();
            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;
      return t->type;
}


Generated by  Doxygen 1.6.0   Back to index