Annotation of coherent/b/bin/sh_B4_420/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 character of 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:                        /*
        !            47:                         * POSIX.2 says: If there are no positional
        !            48:                         * parameters, the expansion of $@ shall generate
        !            49:                         * zero fields, even when double-quoted.
        !            50:                         */
        !            51: #if 1
        !            52:                        if (m == MDQUO && strcmp (arcp, "\"") == 0)
        !            53:                                argf = 0;
        !            54: #else
        !            55:                        if (m==MDQUO && strcmp(arcp, "$@\"")!=0)
        !            56:                                argf = 0;
        !            57: #endif
        !            58:                        continue;
        !            59:                case '\'':      /* m == MNQUO */
        !            60:                        while ((c = *arcp++) != '\'')
        !            61:                                add_quoted(c);
        !            62:                        argf = 0;
        !            63:                        continue;
        !            64:                case '\\':      /* m == MDQUO || m == MNQUO */
        !            65:                        c = *arcp++;
        !            66:                        if (m != MNQUO && ! class(c, m)) {
        !            67:                                add_char('\\');
        !            68:                                add_char(c);
        !            69:                        } else
        !            70:                                add_quoted(c);
        !            71:                        argf = 0;
        !            72:                        continue;
        !            73:                case '$':       /* m == MNQUO || m = MDQUO */
        !            74:                        variable();
        !            75:                        continue;
        !            76:                case '`':       /* m == MNQUO || m = MDQUO */
        !            77:                        graves (m);
        !            78:                        continue;
        !            79:                default:
        !            80:                        add_char(c);
        !            81:                        continue;
        !            82:                }
        !            83:        }
        !            84:        if (f==EARGS)
        !            85:                end_arg();
        !            86:        else
        !            87:                *strp++ = '\0';
        !            88: }
        !            89: 
        !            90: /*
        !            91:  * Read the name of a shell variable and perform the appropriate substitution.
        !            92:  * Doesn't check for end of buffer.
        !            93:  */
        !            94: variable()
        !            95: {
        !            96:        VAR *vp;
        !            97:        int s;
        !            98:        char *wp, *sav;
        !            99:        register int c, count, quote;
        !           100:        register char *cp, *pp;
        !           101: 
        !           102:        cp = strp;
        !           103:        s = '\0';
        !           104:        c = *arcp++;
        !           105:        if (class(c, MSVAR)) {
        !           106:                special(c);
        !           107:                return;
        !           108:        } else if (class(c, MRVAR)) {
        !           109:                while (class(c, MRVAR)) {
        !           110:                        *cp++ = c;
        !           111:                        c = *arcp++;
        !           112:                }
        !           113:                --arcp;
        !           114:        } else if (c != '{') {
        !           115:                /* Not a legal variable name, put it back. */
        !           116:                add_char('$');
        !           117:                add_char(c);
        !           118:                return;
        !           119:        } else {
        !           120:                /* c == '{' */
        !           121:                if (index("#?$!-@*0123456789", arcp[0]) != NULL && arcp[1] == '}') {
        !           122:                        /* Allow specials of the form "${?}" etc. */
        !           123:                        special(arcp[0]);
        !           124:                        arcp += 2;
        !           125:                        return;
        !           126:                }
        !           127:                while (index("}-=?+", c = *arcp++) == NULL)
        !           128:                        *cp++ = c;
        !           129:                if (c != '}') {
        !           130:                        /* ${VAR [-=?+] token} */
        !           131:                        s = c;
        !           132:                        if (cp[-1] == ':')
        !           133:                                --cp;           /* allow e.g. ${VAR:=foo} */
        !           134:                        *cp++ = '=';
        !           135:                        wp = cp;
        !           136:                        if ((quote = *arcp) == '"' || quote =='\'')
        !           137:                                ++arcp;
        !           138:                        else
        !           139:                                quote = 0;
        !           140:                        for (count = 1; ; ) {
        !           141:                                c = *arcp++;
        !           142:                                if (c == '}' && count-- == 1)
        !           143:                                        break;
        !           144:                                else if (c == '$' && quote != '\'') {
        !           145: /*
        !           146:  * steve 6/24/92
        !           147:  * This truly sleazy hack handles e.g. "${V1-$V2}", oy.
        !           148:  * It doesn't do it very well, paying no attention to quotes (for example).
        !           149:  * The recursive call to variable() should be straightforward but is not,
        !           150:  * the hacky way this module uses globals like strp requires the save/restore.
        !           151:  */
        !           152:                                        sav = strp;
        !           153:                                        strp = cp;
        !           154:                                        variable();
        !           155:                                        cp = strp;
        !           156:                                        strp = sav;
        !           157:                                        continue;
        !           158:                                } else if (c == '{')
        !           159:                                        ++count;
        !           160:                                else if (quote != 0 && c == quote) {
        !           161:                                        quote = 0;
        !           162:                                        continue;
        !           163:                                }
        !           164:                                *cp++ = c;
        !           165:                        }
        !           166:                }
        !           167:        }
        !           168:        *cp++ = '\0';
        !           169:        if (class((c = *strp), MDIGI)) {
        !           170:                if ((c -= '1') >= sargc)
        !           171:                        pp = NULL;
        !           172:                else
        !           173:                        pp = sargp[c];
        !           174:        } else if (namevar(strp) == 0) {
        !           175:                eillvar(strp);
        !           176:                return;
        !           177:        } else {
        !           178:                pp = NULL;
        !           179:                if ((vp=findvar(strp)) != NULL) {
        !           180:                        pp = convvar(vp);
        !           181:                        if (*pp == '\0')
        !           182:                                pp = NULL;      /* regard value "" as not set */
        !           183:                }
        !           184:        }
        !           185:        switch (s) {
        !           186:        case '\0':
        !           187:                if (uflag!=0 && pp==NULL)
        !           188:                        enotdef(strp);
        !           189:                break;
        !           190:        case '-':
        !           191:                if (pp == NULL)
        !           192:                        pp = wp;
        !           193:                break;
        !           194:        case '=':
        !           195:                if (pp == NULL) {
        !           196:                        pp = wp;
        !           197:                        if (class(*strp, MDIGI)) {
        !           198:                                printe("Illegal substitution");
        !           199:                                return;
        !           200:                        }
        !           201:                        setsvar(strp);
        !           202:                }
        !           203:                break;
        !           204:        case '?':
        !           205:                if (pp != NULL)
        !           206:                        break;
        !           207:                if (*wp != '\0')
        !           208:                        prints("%s\n", wp);
        !           209:                else {
        !           210:                        *--wp = '\0';
        !           211:                        enotdef(strp);
        !           212:                }
        !           213:                reset(RUABORT);
        !           214:                NOTREACHED;
        !           215:        case '+':
        !           216:                if (pp != NULL)
        !           217:                        pp = wp;
        !           218:                break;
        !           219:        }
        !           220:        if (pp != NULL)
        !           221:                while ((c = *pp++) != '\0')
        !           222:                        add_char(c);
        !           223:        argf &= ~ argq;
        !           224: }
        !           225: 
        !           226: /*
        !           227:  * Return the value of the special shell variables.
        !           228:  * No check for end of buffer.
        !           229:  */
        !           230: special(n)
        !           231: register int n;
        !           232: {
        !           233:        register char *sp;
        !           234:        register int flag;
        !           235: 
        !           236:        sp = strp;
        !           237:        switch (n) {
        !           238:        case '#':
        !           239:                n = sargc;
        !           240:                goto maked;
        !           241:        case '?':
        !           242:                n = slret;
        !           243:                goto maked;
        !           244:        case '$':
        !           245:                n = shpid;
        !           246:                goto maked;
        !           247:        case '!':
        !           248:                n = sback;
        !           249:                goto maked;
        !           250:        maked:
        !           251:                sprintf(sp, "%d", n);
        !           252:                break;
        !           253:        case '-':
        !           254:                for (sp = &eflag; sp <= &xflag; sp += 1)
        !           255:                        if (*sp)
        !           256:                                add_char(*sp);
        !           257:                argf &= ~ argq;
        !           258:                return;
        !           259:        case '@':
        !           260:        case '*':
        !           261:                flag = (argq == 1 && n == '@');
        !           262:                for (n = 0; n < sargc; n++) {
        !           263:                        if (n) {
        !           264:                                argq ^= flag;
        !           265:                                add_char(' ');
        !           266:                                argq ^= flag;
        !           267:                        }
        !           268:                        sp = sargp[n];
        !           269:                        while (*sp)
        !           270:                                add_char(*sp++);
        !           271:                        /*
        !           272:                         * Make sure that arguments like "" get handled
        !           273:                         * properly when expanding "$@"
        !           274:                         */
        !           275:                        if (flag)
        !           276:                                argf &= ~ argq;
        !           277:                }
        !           278:                return;
        !           279:        case '0':
        !           280:                sp = sarg0;
        !           281:                break;
        !           282:        default:
        !           283:                if ((n-='1') >= sargc) {
        !           284:                        if (uflag)
        !           285:                                printe("Unset parameter: %c", n+'1');
        !           286:                        argf &= ~ argq;
        !           287:                        return;
        !           288:                }
        !           289:                sp = sargp[n];
        !           290:                break;
        !           291:        }
        !           292:        while (*sp)
        !           293:                add_char(*sp++);
        !           294:        argf &= ~ argq;
        !           295: }
        !           296: 
        !           297: /*
        !           298:  * Read and evaluate a command found between graves.
        !           299:  *
        !           300:  * NB : The code below relating to saving/restoring the global variable
        !           301:  * "argf" has been removed; it was not clear what the intended effect was,
        !           302:  * but it caused expansions into single words (eg, "echo `pwd`") to vanish
        !           303:  * and caused the word-break algorithm to perform in an unintuitive (and
        !           304:  * incorrect according to POSIX.2) manner.
        !           305:  *
        !           306:  * NB : Backslash-quoting inside graves was not supported properly before,
        !           307:  * and I'm not sure that I've got it right. The idea is that before passing
        !           308:  * things off to session (), we process the appropriate backslash-escapes.
        !           309:  * What consists of an "appropriate" escape depends on whether the graves
        !           310:  * appeared within a double-quoted section (in which case we recognise the
        !           311:  * specials appropriate to that) or not (in which case we recognised the
        !           312:  * characters $`\ as specials. We also process '$'-expansions in graves now,
        !           313:  * but not globs.
        !           314:  *
        !           315:  * Since we are removing some bashslashes here, we should be building into
        !           316:  * a temporary buffer. We append our work onto the global "strp" buffer and
        !           317:  * cut it back once we have finished.
        !           318:  */
        !           319: graves (quotemode)
        !           320: int            quotemode;
        !           321: {
        !           322:        int pipev[2], f, oslret;
        !           323:        int oargf;
        !           324:        char          * ostrp;
        !           325:        register FILE *fp;
        !           326:        register int c;
        !           327:        register int nnl;
        !           328:        char *cmdp;
        !           329: 
        !           330:        oargf = argf;
        !           331:        ostrp = strp;
        !           332:        oslret = slret;
        !           333: 
        !           334:        cmdp = strp;
        !           335:        while ((c = *arcp++) != '`') {
        !           336:                if (c != '\\') {
        !           337:                        add_arg (c);
        !           338:                        continue;
        !           339:                }
        !           340:                c = * arcp ++;
        !           341: 
        !           342:                if (! (quotemode == MDQUO && class (c, MDQUO)) &&
        !           343:                    (c != '$' && c != '\\' && c != '`'))
        !           344:                        add_arg ('\\');
        !           345:                add_arg (c);
        !           346:        }
        !           347:        * strp = 0;
        !           348: 
        !           349:        if ((f = pipeline(pipev)) == 0) {
        !           350:                slret = oslret;         /* in case grave command uses $? */
        !           351:                dup2(pipev[1], 1);
        !           352:                close(pipev[0]);
        !           353:                close(pipev[1]);
        !           354:                exit(session(SARGS, cmdp));
        !           355:                NOTREACHED;
        !           356:        }
        !           357: 
        !           358:        close(pipev[1]);
        !           359:        if ((fp=fdopen(pipev[0], "r")) == NULL) {
        !           360:                close(pipev[0]);
        !           361:                ecantfdop();
        !           362:                return;
        !           363:        }
        !           364:        strp = ostrp;
        !           365:        argf = oargf;
        !           366:        nnl = 0;
        !           367:        while ((c=getc(fp)) != EOF) {
        !           368:                if ( ! recover(IEVAL)) {
        !           369: #ifdef VERBOSE
        !           370:                        if (xflag) prints("Interrupt in eval\n");
        !           371: #endif
        !           372:                        errflag++;
        !           373:                        break;
        !           374:                }
        !           375:                if (c=='\n')
        !           376:                        ++nnl;
        !           377:                else {
        !           378:                        while (nnl) {
        !           379:                                nnl--;
        !           380:                                add_char('\n');
        !           381:                        }
        !           382:                        add_char(c);
        !           383:                }
        !           384:        }
        !           385: 
        !           386:        /*
        !           387:         * If we expanded to something, we have an arg. If we are in double-
        !           388:         * quotes, we have an arg. Otherwise, we have an arg if we had an arg
        !           389:         * before.
        !           390:         */
        !           391: 
        !           392:        if (argf)
        !           393:                argf = argq ? 0 : oargf;
        !           394: 
        !           395:        fclose(fp);
        !           396:        waitc(f);
        !           397: }
        !           398: 
        !           399: /*
        !           400:  * Add a character to the current argument.
        !           401:  * If no quotation is set, pick off blanks and globs.
        !           402:  */
        !           403: add_char(c)
        !           404: register int c;
        !           405: {
        !           406:        if (argq==0) {
        !           407:                if (index(vifs, c) != NULL) {
        !           408:                        end_arg();
        !           409:                        return;
        !           410:                }
        !           411:                if (argg && class(c, MGLOB)) {
        !           412:                        add_arg(c);
        !           413:                        return;
        !           414:                }
        !           415:        }
        !           416:        add_quoted(c);
        !           417: }
        !           418: 
        !           419: /*
        !           420:  * Add a quoted character to the current argument.
        !           421:  * if argg is set, then glob characters are quoted with a \,
        !           422:  * as well as \ itself.
        !           423:  */
        !           424: add_quoted(c) register int c;
        !           425: {
        !           426:        if (argg && (class(c, MGLOB) || c == '\\'))
        !           427:                add_arg('\\');
        !           428:        add_arg(c);
        !           429: }
        !           430: 
        !           431: /*
        !           432:  * Add a character to the current argument
        !           433:  * and check for end of buffer.
        !           434:  */
        !           435: add_arg(c) register int c;
        !           436: {
        !           437:        if (strp >= &strt[STRSIZE])     /* Should do more */
        !           438:                etoolong();
        !           439:        else
        !           440:                *strp++ = c;
        !           441:        argf = 0;
        !           442: }
        !           443: 
        !           444: /*
        !           445:  * Terminate the current argument if it is non-empty.
        !           446:  * If argg is set, then glob the argument to expand globs
        !           447:  * or to simply remove any quotes.
        !           448:  */
        !           449: end_arg()
        !           450: {
        !           451:        if (argf != 0)
        !           452:                return;
        !           453:        *strp++ = '\0';
        !           454:        if (argg)
        !           455:                glob1(duplstr(strt, 0));
        !           456:        else {
        !           457:                nargv = addargl(nargv, duplstr(strt, 0));
        !           458:                nargc += 1;
        !           459:        }
        !           460:        strp = strt;
        !           461:        argf = 1;
        !           462:        return;
        !           463: }
        !           464: 
        !           465: /*
        !           466:  * Evaluate a here document.
        !           467:  * Unevaluated document is on u2, put the evaluated document there, too.
        !           468:  */
        !           469: evalhere(u2)
        !           470: {
        !           471:        register int u1;
        !           472:        register FILE *f2;
        !           473:        char buf[128];
        !           474:        char *tmp;
        !           475: 
        !           476:        tmp = shtmp();
        !           477:        if ((u1=creat(tmp, 0666))<0) {
        !           478:                ecantmake(tmp);
        !           479:                return -1;
        !           480:        }
        !           481:        if ((f2=fdopen(u2, "r"))==NULL) {
        !           482:                ecantfdop();
        !           483:                close(u1);
        !           484:                close(u2);
        !           485:                return -1;
        !           486:        }
        !           487:        while (fgets(buf, 128, f2) != NULL) {
        !           488:                eval(buf, EHERE);
        !           489:                write(u1, strt, strp-1-strt);
        !           490:        }
        !           491:        close(u1);
        !           492:        fclose(f2);
        !           493:        if ((u2 = open(tmp, 0))<0) {
        !           494:                ecantopen(tmp);
        !           495:                u2 = -1;
        !           496:        }
        !           497:        unlink(tmp);
        !           498:        return u2;
        !           499: }
        !           500: 
        !           501: /* 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.