Annotation of coherent/d/bin/sh/eval.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * sh/eval.c
                      3:  * Bourne shell.
                      4:  * Evaluation of parameter substitution, command substitution,
                      5:  * blank interpretation, and file name generation.
                      6:  */
                      7: 
                      8: #include "sh.h"
                      9: 
                     10: char   *arcp;          /* character position in argument */
                     11: int    argf = 1;       /* First argument flag */
                     12: int    argg = 0;       /* Glob seek, escape quoted glob chars */
                     13: int    argq = 0;       /* Quotation flag, no blanks or glob */
                     14: 
                     15: /*
                     16:  * Evaluate a string.
                     17:  */
                     18: eval(cp, f)
                     19: char *cp;
                     20: {
                     21:        register int m, c;
                     22: 
                     23:        strp = strt;
                     24:        arcp = cp;
                     25:        argf = 1;
                     26:        if (f==EHERE) {
                     27:                m = MHERE;
                     28:                argq = 2;
                     29:        } else if (f==EWORD) {
                     30:                m = MNQUO;
                     31:                argq = 2;
                     32:        } else {
                     33:                m = MNQUO;
                     34:                argq = 0;
                     35:        }
                     36:        argg = (f==EARGS || f==EPATT);
                     37: 
                     38:        while ((c = *arcp++) != '\0') {
                     39:                if (!class(c, m)) {
                     40:                        add_char(c);
                     41:                        continue;
                     42:                }
                     43:                switch (c) {
                     44:                case '"':       /* m == MNQUO || m == MDQUO */
                     45:                        m = ((argq ^= 1) & 1) ? MDQUO : MNQUO;
                     46:                        if (m==MDQUO && strcmp(arcp, "$@\"")!=0)
                     47:                                argf = 0;
                     48:                        continue;
                     49:                case '\'':      /* m == MNQUO */
                     50:                        while ((c = *arcp++) != '\'')
                     51:                                add_quoted(c);
                     52:                        argf = 0;
                     53:                        continue;
                     54:                case '\\':      /* m == MDQUO || m == MNQUO */
                     55:                        c = *arcp++;
                     56:                        if (m != MNQUO && ! class(c, m)) {
                     57:                                add_char('\\');
                     58:                                add_char(c);
                     59:                        } else
                     60:                                add_quoted(c);
                     61:                        argf = 0;
                     62:                        continue;
                     63:                case '$':       /* m == MNQUO || m = MDQUO */
                     64:                        variable();
                     65:                        continue;
                     66:                case '`':       /* m == MNQUO || m = MDQUO */
                     67:                        graves();
                     68:                        continue;
                     69:                default:
                     70:                        add_char(c);
                     71:                        continue;
                     72:                }
                     73:        }
                     74:        if (f==EARGS)
                     75:                end_arg();
                     76:        else
                     77:                *strp++ = '\0';
                     78: }
                     79: 
                     80: /*
                     81:  * Read the name of a shell variable and perform the appropriate substitution.
                     82:  * Doesn't check for end of buffer.
                     83:  */
                     84: variable()
                     85: {
                     86:        VAR *vp;
                     87:        int s;
                     88:        char *wp, *sav;
                     89:        register int c, count, quote;
                     90:        register char *cp, *pp;
                     91: 
                     92:        cp = strp;
                     93:        s = '\0';
                     94:        c = *arcp++;
                     95:        if (class(c, MSVAR)) {
                     96:                special(c);
                     97:                return;
                     98:        } else if (class(c, MRVAR)) {
                     99:                while (class(c, MRVAR)) {
                    100:                        *cp++ = c;
                    101:                        c = *arcp++;
                    102:                }
                    103:                --arcp;
                    104:        } else if (c != '{') {
                    105:                /* Not a legal variable name, put it back. */
                    106:                add_char('$');
                    107:                add_char(c);
                    108:                return;
                    109:        } else {
                    110:                /* c == '{' */
                    111:                if (index("#?$!-@*0123456789", arcp[0]) != NULL && arcp[1] == '}') {
                    112:                        /* Allow specials of the form "${?}" etc. */
                    113:                        special(arcp[0]);
                    114:                        arcp += 2;
                    115:                        return;
                    116:                }
                    117:                while (index("}-=?+", c = *arcp++) == NULL)
                    118:                        *cp++ = c;
                    119:                if (c != '}') {
                    120:                        /* ${VAR [-=?+] token} */
                    121:                        s = c;
                    122:                        if (cp[-1] == ':')
                    123:                                --cp;           /* allow e.g. ${VAR:=foo} */
                    124:                        *cp++ = '=';
                    125:                        wp = cp;
                    126:                        if ((quote = *arcp) == '"' || quote =='\'')
                    127:                                ++arcp;
                    128:                        else
                    129:                                quote = 0;
                    130:                        for (count = 1; ; ) {
                    131:                                c = *arcp++;
                    132:                                if (c == '}' && count-- == 1)
                    133:                                        break;
                    134:                                else if (c == '$' && quote != '\'') {
                    135: /*
                    136:  * steve 6/24/92
                    137:  * This truly sleazy hack handles e.g. "${V1-$V2}", oy.
                    138:  * It doesn't do it very well, paying no attention to quotes (for example).
                    139:  * The recursive call to variable() should be straightforward but is not,
                    140:  * the hacky way this module uses globals like strp requires the save/restore.
                    141:  */
                    142:                                        sav = strp;
                    143:                                        strp = cp;
                    144:                                        variable();
                    145:                                        cp = strp;
                    146:                                        strp = sav;
                    147:                                        continue;
                    148:                                } else if (c == '{')
                    149:                                        ++count;
                    150:                                else if (quote != 0 && c == quote) {
                    151:                                        quote = 0;
                    152:                                        continue;
                    153:                                }
                    154:                                *cp++ = c;
                    155:                        }
                    156:                }
                    157:        }
                    158:        *cp++ = '\0';
                    159:        if (class((c = *strp), MDIGI)) {
                    160:                if ((c -= '1') >= sargc)
                    161:                        pp = NULL;
                    162:                else
                    163:                        pp = sargp[c];
                    164:        } else if (namevar(strp) == 0) {
                    165:                eillvar(strp);
                    166:                return;
                    167:        } else {
                    168:                pp = NULL;
                    169:                if ((vp=findvar(strp)) != NULL) {
                    170:                        pp = convvar(vp);
                    171:                        if (*pp == '\0')
                    172:                                pp = NULL;      /* regard value "" as not set */
                    173:                }
                    174:        }
                    175:        switch (s) {
                    176:        case '\0':
                    177:                if (uflag!=0 && pp==NULL)
                    178:                        enotdef(strp);
                    179:                break;
                    180:        case '-':
                    181:                if (pp == NULL)
                    182:                        pp = wp;
                    183:                break;
                    184:        case '=':
                    185:                if (pp == NULL) {
                    186:                        pp = wp;
                    187:                        if (class(*strp, MDIGI)) {
                    188:                                printe("Illegal substitution");
                    189:                                return;
                    190:                        }
                    191:                        setsvar(strp);
                    192:                }
                    193:                break;
                    194:        case '?':
                    195:                if (pp != NULL)
                    196:                        break;
                    197:                if (*wp != '\0')
                    198:                        prints("%s\n", wp);
                    199:                else {
                    200:                        *--wp = '\0';
                    201:                        enotdef(strp);
                    202:                }
                    203:                reset(RUABORT);
                    204:                NOTREACHED;
                    205:        case '+':
                    206:                if (pp != NULL)
                    207:                        pp = wp;
                    208:                break;
                    209:        }
                    210:        if (pp == NULL)
                    211:                return;
                    212:        while ((c = *pp++) != '\0')
                    213:                add_char(c);
                    214: }
                    215: 
                    216: /*
                    217:  * Return the value of the special shell variables.
                    218:  * No check for end of buffer.
                    219:  */
                    220: special(n)
                    221: register int n;
                    222: {
                    223:        register char *sp;
                    224:        register int flag;
                    225: 
                    226:        sp = strp;
                    227:        switch (n) {
                    228:        case '#':
                    229:                n = sargc;
                    230:                goto maked;
                    231:        case '?':
                    232:                n = slret;
                    233:                goto maked;
                    234:        case '$':
                    235:                n = shpid;
                    236:                goto maked;
                    237:        case '!':
                    238:                n = sback;
                    239:                goto maked;
                    240:        maked:
                    241:                sprintf(sp, "%d", n);
                    242:                break;
                    243:        case '-':
                    244:                for (sp = &eflag; sp <= &xflag; sp += 1)
                    245:                        if (*sp)
                    246:                                add_char(*sp);
                    247:                return;
                    248:        case '@':
                    249:        case '*':
                    250:                flag = (argq == 1 && n == '@');
                    251:                for (n = 0; n < sargc; n++) {
                    252:                        if (n) {
                    253:                                argq ^= flag;
                    254:                                add_char(' ');
                    255:                                argq ^= flag;
                    256:                        }
                    257:                        sp = sargp[n];
                    258:                        while (*sp)
                    259:                                add_char(*sp++);
                    260:                }
                    261:                return;
                    262:        case '0':
                    263:                sp = sarg0;
                    264:                break;
                    265:        default:
                    266:                if ((n-='1') >= sargc) {
                    267:                        if (uflag)
                    268:                                printe("Unset parameter: %c", n+'1');
                    269:                        return;
                    270:                }
                    271:                sp = sargp[n];
                    272:                break;
                    273:        }
                    274:        while (*sp)
                    275:                add_char(*sp++);
                    276: }
                    277: 
                    278: /*
                    279:  * Read and evaluate a command found between graves.
                    280:  */
                    281: graves()
                    282: {
                    283:        int pipev[2], f, oslret, oargf;
                    284:        register FILE *fp;
                    285:        register int c;
                    286:        register int nnl;
                    287:        char *cmdp;
                    288: 
                    289:        oargf = argf;
                    290:        oslret = slret;
                    291:        cmdp = arcp;
                    292:        while ((c = *arcp++) != '`')
                    293:                ;
                    294:        if ((f = pipeline(pipev)) == 0) {
                    295:                slret = oslret;         /* in case grave command uses $? */
                    296:                dup2(pipev[1], 1);
                    297:                close(pipev[0]);
                    298:                close(pipev[1]);
                    299:                *--arcp = '\0';
                    300:                exit(session(SARGS, cmdp));
                    301:                NOTREACHED;
                    302:        }
                    303:        close(pipev[1]);
                    304:        if ((fp=fdopen(pipev[0], "r")) == NULL) {
                    305:                close(pipev[0]);
                    306:                ecantfdop();
                    307:                return;
                    308:        }
                    309:        argf = 1;
                    310:        nnl = 0;
                    311:        while ((c=getc(fp)) != EOF) {
                    312:                if ( ! recover(IEVAL)) {
                    313: #ifdef VERBOSE
                    314:                        if (xflag) prints("Interrupt in eval\n");
                    315: #endif
                    316:                        errflag++;
                    317:                        break;
                    318:                }
                    319:                if (c=='\n')
                    320:                        ++nnl;
                    321:                else {
                    322:                        while (nnl) {
                    323:                                nnl--;
                    324:                                add_char('\n');
                    325:                        }
                    326:                        add_char(c);
                    327:                }
                    328:        }
                    329:        argf = oargf;
                    330:        fclose(fp);
                    331:        waitc(f);
                    332: }
                    333: 
                    334: /*
                    335:  * Add a character to the current argument.
                    336:  * If no quotation is set, pick off blanks and globs.
                    337:  */
                    338: add_char(c)
                    339: register int c;
                    340: {
                    341:        if (argq==0) {
                    342:                if (index(vifs, c) != NULL) {
                    343:                        end_arg();
                    344:                        return;
                    345:                }
                    346:                if (argg && class(c, MGLOB)) {
                    347:                        add_arg(c);
                    348:                        return;
                    349:                }
                    350:        }
                    351:        add_quoted(c);
                    352: }
                    353: 
                    354: /*
                    355:  * Add a quoted character to the current argument.
                    356:  * if argg is set, then glob characters are quoted with a \,
                    357:  * as well as \ itself.
                    358:  */
                    359: add_quoted(c) register int c;
                    360: {
                    361:        if (argg && (class(c, MGLOB) || c == '\\'))
                    362:                add_arg('\\');
                    363:        add_arg(c);
                    364: }
                    365: 
                    366: /*
                    367:  * Add a character to the current argument
                    368:  * and check for end of buffer.
                    369:  */
                    370: add_arg(c) register int c;
                    371: {
                    372:        if (strp >= &strt[STRSIZE])     /* Should do more */
                    373:                etoolong();
                    374:        else
                    375:                *strp++ = c;
                    376:        argf = 0;
                    377: }
                    378: 
                    379: /*
                    380:  * Terminate the current argument if it is non-empty.
                    381:  * If argg is set, then glob the argument to expand globs
                    382:  * or to simply remove any quotes.
                    383:  */
                    384: end_arg()
                    385: {
                    386:        if (argf != 0)
                    387:                return;
                    388:        *strp++ = '\0';
                    389:        if (argg)
                    390:                glob1(duplstr(strt, 0));
                    391:        else {
                    392:                nargv = addargl(nargv, duplstr(strt, 0));
                    393:                nargc += 1;
                    394:        }
                    395:        strp = strt;
                    396:        argf = 1;
                    397:        return;
                    398: }
                    399: 
                    400: /*
                    401:  * Evaluate a here document.
                    402:  * Unevaluated document is on u2, put the evaluated document there, too.
                    403:  */
                    404: evalhere(u2)
                    405: {
                    406:        register int u1;
                    407:        register FILE *f2;
                    408:        char buf[128];
                    409:        char *tmp;
                    410: 
                    411:        tmp = shtmp();
                    412:        if ((u1=creat(tmp, 0666))<0) {
                    413:                ecantmake(tmp);
                    414:                return -1;
                    415:        }
                    416:        if ((f2=fdopen(u2, "r"))==NULL) {
                    417:                ecantfdop();
                    418:                close(u1);
                    419:                close(u2);
                    420:                return -1;
                    421:        }
                    422:        while (fgets(buf, 128, f2) != NULL) {
                    423:                eval(buf, EHERE);
                    424:                write(u1, strt, strp-1-strt);
                    425:        }
                    426:        close(u1);
                    427:        fclose(f2);
                    428:        if ((u2 = open(tmp, 0))<0) {
                    429:                ecantopen(tmp);
                    430:                u2 = -1;
                    431:        }
                    432:        unlink(tmp);
                    433:        return u2;
                    434: }
                    435: 
                    436: /* end of sh/eval.c */

unix.superglobalmegacorp.com

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