Annotation of coherent/d/bin/sh/eval.c, revision 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.