Annotation of lucent/sys/src/cmd/rc/lex.c, revision 1.1.1.1

1.1       root        1: #include "rc.h"
                      2: #include "exec.h"
                      3: #include "io.h"
                      4: #include "getflags.h"
                      5: #include "fns.h"
                      6: int getnext(void);
                      7: int wordchr(int c)
                      8: {
                      9:        return !strchr("\n \t#;&|^$=`'{}()<>", c) && c!=EOF;
                     10: }
                     11: int idchr(int c)
                     12: {
                     13:        /*
                     14:         * Formerly:
                     15:         * return 'a'<=c && c<='z' || 'A'<=c && c<='Z' || '0'<=c && c<='9'
                     16:         *      || c=='_' || c=='*';
                     17:         */
                     18:        return c>' ' && !strchr("!\"#$%&'()+,-./:;<=>?@[\\]^`{|}~", c);
                     19: }
                     20: int future=EOF;
                     21: int doprompt=1;
                     22: int inquote;
                     23: /*
                     24:  * Look ahead in the input stream
                     25:  */
                     26: int nextc(void){
                     27:        if(future==EOF) future=getnext();
                     28:        return future;
                     29: }
                     30: /*
                     31:  * Consume the lookahead character.
                     32:  */
                     33: int advance(void){
                     34:        int c=nextc();
                     35:        lastc=future;
                     36:        future=EOF;
                     37:        return c;
                     38: }
                     39: /*
                     40:  * read a character from the input stream
                     41:  */    
                     42: int getnext(void){
                     43:        register int c;
                     44:        static peekc=EOF;
                     45:        if(peekc!=EOF){
                     46:                c=peekc;
                     47:                peekc=EOF;
                     48:                return c;
                     49:        }
                     50:        if(runq->eof) return EOF;
                     51:        if(doprompt) pprompt();
                     52:        c=rchr(runq->cmdfd);
                     53:        if(!inquote && c=='\\'){
                     54:                c=rchr(runq->cmdfd);
                     55:                if(c=='\n'){
                     56:                        doprompt=1;
                     57:                        c=' ';
                     58:                }
                     59:                else{
                     60:                        peekc=c;
                     61:                        c='\\';
                     62:                }
                     63:        }
                     64:        doprompt=doprompt || c=='\n' || c==EOF;
                     65:        if(c==EOF) runq->eof++;
                     66:        else if(flag['V'] || ndot>=2 && flag['v']) pchr(err, c);
                     67:        return c;
                     68: }
                     69: void pprompt(void){
                     70:        var *prompt;
                     71:        if(runq->iflag){
                     72:                pstr(err, promptstr);
                     73:                flush(err);
                     74:                prompt=vlook("prompt");
                     75:                if(prompt->val && prompt->val->next)
                     76:                        promptstr=prompt->val->next->word;
                     77:                else
                     78:                        promptstr="\t";
                     79:        }
                     80:        runq->lineno++;
                     81:        doprompt=0;
                     82: }
                     83: void skipwhite(void){
                     84:        int c;
                     85:        for(;;){
                     86:                c=nextc();
                     87:                if(c=='#'){     /* Why did this used to be  if(!inquote && c=='#') ?? */
                     88:                        for(;;){
                     89:                                c=nextc();
                     90:                                if(c=='\n' || c==EOF) break;
                     91:                                advance();
                     92:                        }
                     93:                }
                     94:                if(c==' ' || c=='\t') advance();
                     95:                else return;
                     96:        }
                     97: }
                     98: void skipnl(void){
                     99:        register int c;
                    100:        for(;;){
                    101:                skipwhite();
                    102:                c=nextc();
                    103:                if(c!='\n') return;
                    104:                advance();
                    105:        }
                    106: }
                    107: int nextis(int c){
                    108:        if(nextc()==c){
                    109:                advance();
                    110:                return 1;
                    111:        }
                    112:        return 0;
                    113: }
                    114: char *addtok(char *p, int val){
                    115:        if(p==0) return 0;
                    116:        if(p==&tok[NTOK]){
                    117:                *p=0;
                    118:                yyerror("token buffer too short");
                    119:                return 0;
                    120:        }
                    121:        *p++=val;
                    122:        return p;
                    123: }
                    124: char *addutf(char *p, int c){
                    125:        p=addtok(p, c);
                    126:        if(twobyte(c))   /* 2-byte escape */
                    127:                return addtok(p, advance());
                    128:        if(threebyte(c)){       /* 3-byte escape */
                    129:                p=addtok(p, advance());
                    130:                return addtok(p, advance());
                    131:        }
                    132:        return p;
                    133: }
                    134: int lastdol;   /* was the last token read '$' or '$#' or '"'? */
                    135: int lastword;  /* was the last token read a word or compound word terminator? */
                    136: int yylex(void){
                    137:        register int c, d=nextc();
                    138:        register char *w=tok;
                    139:        register struct tree *t;
                    140:        yylval.tree=0;
                    141:        /*
                    142:         * Embarassing sneakiness:  if the last token read was a quoted or unquoted
                    143:         * WORD then we alter the meaning of what follows.  If the next character
                    144:         * is `(', we return SUB (a subscript paren) and consume the `('.  Otherwise,
                    145:         * if the next character is the first character of a simple or compound word,
                    146:         * we insert a `^' before it.
                    147:         */
                    148:        if(lastword){
                    149:                lastword=0;
                    150:                if(d=='('){
                    151:                        advance();
                    152:                        strcpy(tok, "( [SUB]");
                    153:                        return SUB;
                    154:                }
                    155:                if(wordchr(d) || d=='\'' || d=='`' || d=='$' || d=='"'){
                    156:                        strcpy(tok, "^");
                    157:                        return '^';
                    158:                }
                    159:        }
                    160:        inquote=0;
                    161:        skipwhite();
                    162:        switch(c=advance()){
                    163:        case EOF:
                    164:                lastdol=0;
                    165:                strcpy(tok, "EOF");
                    166:                return EOF;
                    167:        case '$':
                    168:                lastdol=1;
                    169:                if(nextis('#')){
                    170:                        strcpy(tok, "$#");
                    171:                        return COUNT;
                    172:                }
                    173:                if(nextis('"')){
                    174:                        strcpy(tok, "$\"");
                    175:                        return '"';
                    176:                }
                    177:                strcpy(tok, "$");
                    178:                return '$';
                    179:        case '&':
                    180:                lastdol=0;
                    181:                if(nextis('&')){
                    182:                        skipnl();
                    183:                        strcpy(tok, "&&");
                    184:                        return ANDAND;
                    185:                }
                    186:                strcpy(tok, "&");
                    187:                return '&';
                    188:        case '|':
                    189:                lastdol=0;
                    190:                if(nextis(c)){
                    191:                        skipnl();
                    192:                        strcpy(tok, "||");
                    193:                        return OROR;
                    194:                }
                    195:        case '<':
                    196:        case '>':
                    197:                lastdol=0;
                    198:                /*
                    199:                 * funny redirection tokens:
                    200:                 *      redir:  arrow | arrow '[' fd ']'
                    201:                 *      arrow:  '<' | '<<' | '>' | '>>' | '|'
                    202:                 *      fd:     digit | digit '=' | digit '=' digit
                    203:                 *      digit:  '0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9'
                    204:                 * some possibilities are nonsensical and get a message.
                    205:                 */
                    206:                *w++=c;
                    207:                t=newtree();
                    208:                switch(c){
                    209:                case '|':
                    210:                        t->type=PIPE;
                    211:                        t->fd0=1;
                    212:                        t->fd1=0;
                    213:                        break;
                    214:                case '>':
                    215:                        t->type=REDIR;
                    216:                        if(nextis(c)){
                    217:                                t->rtype=APPEND;
                    218:                                *w++=c;
                    219:                        }
                    220:                        else t->rtype=WRITE;
                    221:                        t->fd0=1;
                    222:                        break;
                    223:                case '<':
                    224:                        t->type=REDIR;
                    225:                        if(nextis(c)){
                    226:                                t->rtype=HERE;
                    227:                                *w++=c;
                    228:                        }
                    229:                        else t->rtype=READ;
                    230:                        t->fd0=0;
                    231:                        break;
                    232:                }
                    233:                if(nextis('[')){
                    234:                        *w++='[';
                    235:                        c=advance();
                    236:                        *w++=c;
                    237:                        if(c<'0' || '9'<c){
                    238:                        RedirErr:
                    239:                                *w=0;
                    240:                                yyerror(t->type==PIPE?"pipe syntax"
                    241:                                                :"redirection syntax");
                    242:                                return EOF;
                    243:                        }
                    244:                        t->fd0=0;
                    245:                        do{
                    246:                                t->fd0=t->fd0*10+c-'0';
                    247:                                *w++=c;
                    248:                                c=advance();
                    249:                        }while('0'<=c && c<='9');
                    250:                        if(c=='='){
                    251:                                *w++='=';
                    252:                                if(t->type==REDIR) t->type=DUP;
                    253:                                c=advance();
                    254:                                if('0'<=c && c<='9'){
                    255:                                        t->rtype=DUPFD;
                    256:                                        t->fd1=t->fd0;
                    257:                                        t->fd0=0;
                    258:                                        do{
                    259:                                                t->fd0=t->fd0*10+c-'0';
                    260:                                                *w++=c;
                    261:                                                c=advance();
                    262:                                        }while('0'<=c && c<='9');
                    263:                                }
                    264:                                else{
                    265:                                        if(t->type==PIPE) goto RedirErr;
                    266:                                        t->rtype=CLOSE;
                    267:                                }
                    268:                        }
                    269:                        if(c!=']'
                    270:                        || t->type==DUP && (t->rtype==HERE || t->rtype==APPEND))
                    271:                                goto RedirErr;
                    272:                        *w++=']';
                    273:                }
                    274:                *w='\0';
                    275:                yylval.tree=t;
                    276:                if(t->type==PIPE) skipnl();
                    277:                return t->type;
                    278:        case '\'':
                    279:                lastdol=0;
                    280:                lastword=1;
                    281:                inquote=1;
                    282:                for(;;){
                    283:                        c=advance();
                    284:                        if(c==EOF) break;
                    285:                        if(c=='\''){
                    286:                                if(nextc()!='\'')
                    287:                                        break;
                    288:                                advance();
                    289:                        }
                    290:                        w=addutf(w, c);
                    291:                }
                    292:                if(w!=0) *w='\0';
                    293:                t=token(tok, WORD);
                    294:                t->quoted=1;
                    295:                yylval.tree=t;
                    296:                return t->type;
                    297:        }
                    298:        if(!wordchr(c)){
                    299:                lastdol=0;
                    300:                tok[0]=c;
                    301:                tok[1]='\0';
                    302:                return c;
                    303:        }
                    304:        for(;;){
                    305:                /* next line should have (char)c==GLOB, but ken's compiler is broken */
                    306:                if(c=='*' || c=='[' || c=='?' || c==(unsigned char)GLOB)
                    307:                        w=addtok(w, GLOB);
                    308:                w=addutf(w, c);
                    309:                c=nextc();
                    310:                if(lastdol?!idchr(c):!wordchr(c)) break;
                    311:                advance();
                    312:        }
                    313: Out:
                    314:        lastword=1;
                    315:        lastdol=0;
                    316:        if(w!=0) *w='\0';
                    317:        t=klook(tok);
                    318:        if(t->type!=WORD) lastword=0;
                    319:        t->quoted=0;
                    320:        yylval.tree=t;
                    321:        return t->type;
                    322: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.