Annotation of 3BSD/cmd/csh/sh.lex.c, revision 1.1.1.1

1.1       root        1: /* Copyright (c) 1979 Regents of the University of California */
                      2: #include "sh.h"
                      3: 
                      4: /*
                      5:  * C shell
                      6:  */
                      7: 
                      8: /*
                      9:  * These lexical routines read input and form lists of words.
                     10:  * There is some involved processing here, because of the complications
                     11:  * of input buffering, and especially because of history substitution.
                     12:  */
                     13: 
                     14: char   *word();
                     15: 
                     16: /*
                     17:  * Peekc is a peek characer for getC, peekread for readc.
                     18:  * There is a subtlety here in many places... history routines
                     19:  * will read ahead and then insert stuff into the input stream.
                     20:  * If they push back a character then they must push it behind
                     21:  * the text substituted by the history substitution.  On the other
                     22:  * hand in several places we need 2 peek characters.  To make this
                     23:  * all work, the history routines read with getC, and make use both
                     24:  * of ungetC and unreadc.  The key observation is that the state
                     25:  * of getC at the call of a history reference is such that calls
                     26:  * to getC from the history routines will always yield calls of
                     27:  * readc, unless this peeking is involved.  That is to say that during
                     28:  * getexcl the variables lap, exclp, and exclnxt are all zero.
                     29:  *
                     30:  * Getdol invokes history substitution, hence the extra peek, peekd,
                     31:  * which it can ungetD to be before history substitutions.
                     32:  */
                     33: char   peekc, peekd;
                     34: char   peekread;
                     35: 
                     36: char   *exclp;                 /* (Tail of) current word from ! subst */
                     37: struct wordent *exclnxt;       /* The rest of the ! subst words */
                     38: int    exclc;                  /* Count of remainig words in ! subst */
                     39: char   *alvecp;                /* "Globp" for alias resubstitution */
                     40: 
                     41: /*
                     42:  * Lex returns to its caller not only a wordlist (as a "var" parameter)
                     43:  * but also whether a history substitution occurred.  This is used in
                     44:  * the main (process) routine to determine whether to echo, and also
                     45:  * when called by the alias routine to determine whether to keep the
                     46:  * argument list.
                     47:  */
                     48: bool   hadhist;
                     49: 
                     50: #define        ungetC(c)       peekc = c
                     51: #define        ungetD(c)       peekd = c
                     52: 
                     53: lex(hp)
                     54:        register struct wordent *hp;
                     55: {
                     56:        register struct wordent *wdp;
                     57:        int c;
                     58: 
                     59:        lineloc = btell();
                     60:        hp->next = hp->prev = hp;
                     61:        hp->word = "";
                     62:        alvecp = 0, hadhist = 0;
                     63:        do
                     64:                c = readc(0);
                     65:        while (c == ' ' || c == '\t');
                     66:        if (c == '^' && intty)
                     67:                /* ^lef^rit     from tty is short !:s^lef^rit */
                     68:                getexcl(c);
                     69:        else
                     70:                unreadc(c);
                     71:        wdp = hp;
                     72:        /*
                     73:         * The following loop is written so that the links needed
                     74:         * by freelex will be ready and rarin to go even if it is
                     75:         * interrupted.
                     76:         */
                     77:        do {
                     78:                register struct wordent *new = (struct wordent *) calloc(1, sizeof *wdp);
                     79: 
                     80:                new->prev = wdp;
                     81:                new->next = hp;
                     82:                wdp->next = new;
                     83:                wdp = new;
                     84:                wdp->word = word();
                     85:        } while (wdp->word[0] != '\n');
                     86:        hp->prev = wdp;
                     87:        return (hadhist);
                     88: }
                     89: 
                     90: prlex(sp0)
                     91:        struct wordent *sp0;
                     92: {
                     93:        register struct wordent *sp = sp0->next;
                     94: 
                     95:        for (;;) {
                     96:                printf("%s", sp->word);
                     97:                sp = sp->next;
                     98:                if (sp == sp0)
                     99:                        break;
                    100:                printf(" ");
                    101:        }
                    102: }
                    103: 
                    104: copylex(hp, fp)
                    105:        register struct wordent *hp;
                    106:        struct wordent *fp;
                    107: {
                    108:        register struct wordent *wdp;
                    109: 
                    110:        wdp = hp;
                    111:        fp = fp->next;
                    112:        do {
                    113:                register struct wordent *new = (struct wordent *) calloc(1, sizeof *wdp);
                    114: 
                    115:                new->prev = wdp;
                    116:                new->next = hp;
                    117:                wdp->next = new;
                    118:                wdp = new;
                    119:                wdp->word = savestr(fp->word);
                    120:                fp = fp->next;
                    121:        } while (wdp->word[0] != '\n');
                    122:        hp->prev = wdp;
                    123: }
                    124: 
                    125: freelex(vp)
                    126:        register struct wordent *vp;
                    127: {
                    128:        register struct wordent *fp;
                    129: 
                    130:        while (vp->next != vp) {
                    131:                fp = vp->next;
                    132:                vp->next = fp->next;
                    133:                xfree(fp->word);
                    134:                xfree(fp);
                    135:        }
                    136:        vp->prev = vp;
                    137: }
                    138: 
                    139: char   *WORDMETA =     "# '`\"\t;&<>()|\n";
                    140: 
                    141: char *
                    142: word()
                    143: {
                    144:        register char c, c1;
                    145:        register char *wp;
                    146:        char wbuf[BUFSIZ];
                    147:        register bool dolflg;
                    148:        register int i;
                    149: 
                    150:        wp = wbuf;
                    151:        i = BUFSIZ - 4;
                    152: loop:
                    153:        c = getC(DOALL);
                    154:        switch (c) {
                    155: 
                    156:        case ' ':
                    157:        case '\t':
                    158:                goto loop;
                    159: 
                    160:        case '`':
                    161:        case '\'':
                    162:        case '"':
                    163:                *wp++ = c, --i, c1 = c;
                    164:                dolflg = c == '"' ? DOALL : DOEXCL;
                    165:                for (;;) {
                    166:                        c = getC(dolflg);
                    167:                        if (c == c1)
                    168:                                break;
                    169:                        if (c == '\n') {
                    170:                                seterrc("Unmatched ", c1);
                    171:                                ungetC(c);
                    172:                                goto ret;
                    173:                        }
                    174:                        if (c == '\\') {
                    175:                                c = getC(0);
                    176:                                if (c == '!')
                    177:                                        c |= QUOTE;
                    178:                                else {
                    179:                                        if (c == '\n' && c1 != '`')
                    180:                                                c |= QUOTE;
                    181:                                        ungetC(c), c = '\\';
                    182:                                }
                    183:                        }
                    184:                        if (--i <= 0)
                    185:                                goto toochars;
                    186:                        *wp++ = c;
                    187:                }
                    188:                *wp++ = c, --i;
                    189:                goto pack;
                    190: 
                    191:        case '&':
                    192:        case '|':
                    193:        case '<':
                    194:        case '>':
                    195:                *wp++ = c;
                    196:                c1 = getC(DOALL);
                    197:                if (c1 == c)
                    198:                        *wp++ = c1;
                    199:                else
                    200:                        ungetC(c1);
                    201:                goto ret;
                    202: 
                    203:        case '#':
                    204:                if (intty)
                    205:                        break;
                    206:                if (wp != wbuf) {
                    207:                        ungetC(c);
                    208:                        goto ret;
                    209:                }
                    210:                c = 0;
                    211:                do {
                    212:                        c1 = c;
                    213:                        c = getC(0);
                    214:                } while (c != '\n');
                    215:                if (c1 == '\\')
                    216:                        goto loop;
                    217:                /* fall into ... */
                    218: 
                    219:        case ';':
                    220:        case '(':
                    221:        case ')':
                    222:        case '\n':
                    223:                *wp++ = c;
                    224:                goto ret;
                    225: 
                    226: casebksl:
                    227:        case '\\':
                    228:                c = getC(0);
                    229:                if (c == '\n') {
                    230:                        if (onelflg == 1)
                    231:                                onelflg = 2;
                    232:                        goto loop;
                    233:                }
                    234:                if (c != '!')
                    235:                        *wp++ = '\\', --i;
                    236:                c |= QUOTE;
                    237:                break;
                    238:        }
                    239:        ungetC(c);
                    240: pack:
                    241:        for (;;) {
                    242:                c = getC(DOALL);
                    243:                if (c == '\\') {
                    244:                        c = getC(0);
                    245:                        if (c == '\n') {
                    246:                                if (onelflg == 1)
                    247:                                        onelflg = 2;
                    248:                                goto ret;
                    249:                        }
                    250:                        if (c != '!')
                    251:                                *wp++ = '\\', --i;
                    252:                        c |= QUOTE;
                    253:                }
                    254:                if (any(c, WORDMETA + intty)) {
                    255:                        ungetC(c);
                    256:                        if (any(c, "\"'`"))
                    257:                                goto loop;
                    258:                        goto ret;
                    259:                }
                    260:                if (--i <= 0)
                    261:                        goto toochars;
                    262:                *wp++ = c;
                    263:        }
                    264: toochars:
                    265:        seterr("Word too long");
                    266:        wp = &wbuf[1];
                    267: ret:
                    268:        *wp = 0;
                    269:        return (savestr(wbuf));
                    270: }
                    271: 
                    272: getC(flag)
                    273:        register int flag;
                    274: {
                    275:        register char c;
                    276: 
                    277: top:
                    278:        if (c = peekc) {
                    279:                peekc = 0;
                    280:                return (c);
                    281:        }
                    282:        if (lap) {
                    283:                c = *lap++;
                    284:                if (c == 0) {
                    285:                        lap = 0;
                    286:                        goto top;
                    287:                }
                    288:                if (any(c, WORDMETA + intty))
                    289:                        c |= QUOTE;
                    290:                return (c);
                    291:        }
                    292:        if (c = peekd) {
                    293:                peekd = 0;
                    294:                return (c);
                    295:        }
                    296:        if (exclp) {
                    297:                if (c = *exclp++)
                    298:                        return (c);
                    299:                if (exclnxt && --exclc >= 0) {
                    300:                        exclnxt = exclnxt->next;
                    301:                        setexclp(exclnxt->word);
                    302:                        return (' ');
                    303:                }
                    304:                exclp = 0;
                    305:                exclnxt = 0;
                    306:        }
                    307:        if (exclnxt) {
                    308:                exclnxt = exclnxt->next;
                    309:                if (--exclc < 0)
                    310:                        exclnxt = 0;
                    311:                else
                    312:                        setexclp(exclnxt->word);
                    313:                goto top;
                    314:        }
                    315:        c = readc(0);
                    316:        if (c == '$' && (flag & DODOL)) {
                    317:                getdol();
                    318:                goto top;
                    319:        }
                    320:        if (c == '!' && (flag & DOEXCL)) {
                    321:                getexcl(0);
                    322:                goto top;
                    323:        }
                    324:        return (c);
                    325: }
                    326: 
                    327: getdol()
                    328: {
                    329:        register char *np;
                    330:        char name[40];
                    331:        register int c;
                    332:        int sc;
                    333:        bool special = 0;
                    334: 
                    335:        np = name, *np++ = '$';
                    336:        c = sc = getC(DOEXCL);
                    337:        if (any(c, "\t \n")) {
                    338:                ungetD(c);
                    339:                ungetC('$' | QUOTE);
                    340:                return;
                    341:        }
                    342:        if (c == '{')
                    343:                *np++ = c, c = getC(DOEXCL);
                    344:        if (c == '#' || c == '?')
                    345:                special++, *np++ = c, c = getC(DOEXCL);
                    346:        *np++ = c;
                    347:        switch (c) {
                    348:        
                    349:        case '$':
                    350:                if (special)
                    351:                        goto vsyn;
                    352:                goto ret;
                    353: 
                    354:        case '\n':
                    355:                ungetD(c);
                    356:                np--;
                    357:                goto vsyn;
                    358: 
                    359:        case '*':
                    360:                if (special)
                    361:                        goto vsyn;
                    362:                goto ret;
                    363: 
                    364:        default:
                    365:                if (digit(c)) {
                    366: /*
                    367:  * let $?0 pass for now
                    368:                        if (special)
                    369:                                goto vsyn;
                    370: */
                    371:                        while (digit(c = getC(DOEXCL))) {
                    372:                                if (np < &name[sizeof name / 2])
                    373:                                        *np++ = c;
                    374:                        }
                    375:                } else if (letter(c))
                    376:                        while (letter(c = getC(DOEXCL))) {
                    377:                                if (np < &name[sizeof name / 2])
                    378:                                        *np++ = c;
                    379:                        }
                    380:                else
                    381:                        goto vsyn;
                    382:        }
                    383:        if (c == '[') {
                    384:                *np++ = c;
                    385:                do {
                    386:                        c = getC(DOEXCL);
                    387:                        if (c == '\n') {
                    388:                                ungetD(c);
                    389:                                np--;
                    390:                                goto vsyn;
                    391:                        }
                    392:                        if (np >= &name[sizeof name - 8])
                    393:                                goto vsyn;
                    394:                        *np++ = c;
                    395:                } while (c != ']');
                    396:                c = getC(DOEXCL);
                    397:        }
                    398:        if (c == ':') {
                    399:                *np++ = c, c = getC(DOEXCL);
                    400:                if (c == 'g')
                    401:                        *np++ = c, c = getC(DOEXCL);
                    402:                *np++ = c;
                    403:                if (!any(c, "htrqx"))
                    404:                        goto vsyn;
                    405:        } else
                    406:                ungetD(c);
                    407:        if (sc == '{') {
                    408:                c = getC(DOEXCL);
                    409:                if (c != '}') {
                    410:                        ungetC(c);
                    411:                        goto vsyn;
                    412:                }
                    413:                *np++ = c;
                    414:        }
                    415: ret:
                    416:        *np = 0;
                    417:        addla(name);
                    418:        return;
                    419: 
                    420: vsyn:
                    421:        seterr("Variable syntax");
                    422:        goto ret;
                    423: }
                    424: 
                    425: addla(cp)
                    426:        char *cp;
                    427: {
                    428:        char buf[BUFSIZ];
                    429: 
                    430:        if (lap != 0 && strlen(cp) + strlen(lap) >= BUFSIZ - 4) {
                    431:                seterr("Expansion buf ovflo");
                    432:                return;
                    433:        }
                    434:        if (lap)
                    435:                strcpy(buf, lap);
                    436:        strcpy(labuf, cp);
                    437:        if (lap)
                    438:                strcat(labuf, buf);
                    439:        lap = labuf;
                    440: }
                    441: 
                    442: char   lhsb[32];
                    443: char   slhs[32];
                    444: char   rhsb[64];
                    445: int    quesarg;
                    446: 
                    447: getexcl(sc)
                    448:        char sc;
                    449: {
                    450:        register struct wordent *hp, *ip;
                    451:        int left, right, dol;
                    452:        register int c;
                    453: 
                    454:        if (sc == 0) {
                    455:                sc = getC(0);
                    456:                if (sc != '{') {
                    457:                        ungetC(sc);
                    458:                        sc = 0;
                    459:                }
                    460:        }
                    461:        quesarg = -1;
                    462:        lastev = eventno;
                    463:        hp = gethent(sc);
                    464:        if (hp == 0)
                    465:                return;
                    466:        hadhist = 1;
                    467:        dol = 0;
                    468:        if (hp == alhistp)
                    469:                for (ip = hp->next->next; ip != alhistt; ip = ip->next)
                    470:                        dol++;
                    471:        else
                    472:                for (ip = hp->next->next; ip != hp->prev; ip = ip->next)
                    473:                        dol++;
                    474:        left = 0, right = dol;
                    475:        if (sc == '^') {
                    476:                ungetC('s'), unreadc('^'), c = ':';
                    477:                goto subst;
                    478:        }
                    479:        c = getC(0);
                    480:        if (!any(c, ":^$*-%"))
                    481:                goto subst;
                    482:        left = right = -1;
                    483:        if (c == ':') {
                    484:                c = getC(0);
                    485:                unreadc(c);
                    486:                if (letter(c) || c == '&') {
                    487:                        c = ':';
                    488:                        left = 0, right = dol;
                    489:                        goto subst;
                    490:                }
                    491:        } else
                    492:                ungetC(c);
                    493:        if (!getsel(&left, &right, dol))
                    494:                return;
                    495:        c = getC(0);
                    496:        if (c == '*')
                    497:                ungetC(c), c = '-';
                    498:        if (c == '-') {
                    499:                if (!getsel(&left, &right, dol))
                    500:                        return;
                    501:                c = getC(0);
                    502:        }
                    503: subst:
                    504:        exclc = right - left + 1;
                    505:        while (--left >= 0)
                    506:                hp = hp->next;
                    507:        if (sc == '^' || c == ':') {
                    508:                do {
                    509:                        hp = getsub(hp);
                    510:                        c = getC(0);
                    511:                } while (c == ':');
                    512:        }
                    513:        unreadc(c);
                    514:        if (sc == '{') {
                    515:                c = getC(0);
                    516:                if (c != '}')
                    517:                        seterr("Bad ! form");
                    518:        }
                    519:        exclnxt = hp;
                    520: }
                    521: 
                    522: struct wordent *
                    523: getsub(en)
                    524:        struct wordent *en;
                    525: {
                    526:        register char *cp;
                    527:        int delim;
                    528:        register int c;
                    529:        int sc;
                    530:        bool global = 0;
                    531:        char orhsb[sizeof rhsb];
                    532: 
                    533:        exclnxt = 0;
                    534:        sc = c = getC(0);
                    535:        if (c == 'g')
                    536:                global++, c = getC(0);
                    537:        switch (c) {
                    538: 
                    539:        case 'p':
                    540:                justpr++;
                    541:                goto ret;
                    542: 
                    543:        case 'x':
                    544:        case 'q':
                    545:                global++;
                    546:                /* fall into ... */
                    547: 
                    548:        case 'h':
                    549:        case 'r':
                    550:        case 't':
                    551:                break;
                    552: 
                    553:        case '&':
                    554:                if (slhs[0] == 0) {
                    555:                        seterr("No prev sub");
                    556:                        goto ret;
                    557:                }
                    558:                strcpy(lhsb, slhs);
                    559:                break;
                    560: 
                    561: /*
                    562:        case '~':
                    563:                if (lhsb[0] == 0)
                    564:                        goto badlhs;
                    565:                break;
                    566: */
                    567: 
                    568:        case 's':
                    569:                delim = getC(0);
                    570:                if (letter(delim) || digit(delim) || any(delim, " \t\n")) {
                    571:                        unreadc(delim);
                    572: bads:
                    573:                        lhsb[0] = 0;
                    574:                        seterr("Bad substitute");
                    575:                        goto ret;
                    576:                }
                    577:                cp = lhsb;
                    578:                for (;;) {
                    579:                        c = getC(0);
                    580:                        if (c == '\n') {
                    581:                                unreadc(c);
                    582:                                goto bads;
                    583:                        }
                    584:                        if (c == delim)
                    585:                                break;
                    586:                        if (cp > &lhsb[sizeof lhsb - 2])
                    587:                                goto bads;
                    588:                        if (c == '\\') {
                    589:                                c = getC(0);
                    590:                                if (c != delim && c != '\\')
                    591:                                        *cp++ = '\\';
                    592:                        }
                    593:                        *cp++ = c;
                    594:                }
                    595:                if (cp != lhsb)
                    596:                        *cp++ = 0;
                    597:                else if (lhsb[0] == 0) {
                    598: badlhs:
                    599:                        seterr("No prev lhs");
                    600:                        goto ret;
                    601:                }
                    602:                cp = rhsb;
                    603:                strcpy(orhsb, cp);
                    604:                for (;;) {
                    605:                        c = getC(0);
                    606:                        if (c == '\n') {
                    607:                                unreadc(c);
                    608:                                break;
                    609:                        }
                    610:                        if (c == delim)
                    611:                                break;
                    612: /*
                    613:                        if (c == '~') {
                    614:                                if (&cp[strlen(orhsb)] > &rhsb[sizeof rhsb - 2])
                    615:                                        goto toorhs;
                    616:                                cp = strend(strcpy(cp, orhsb));
                    617:                                continue;
                    618:                        }
                    619: */
                    620:                        if (cp > &rhsb[sizeof rhsb - 2]) {
                    621: toorhs:
                    622:                                seterr("Rhs too long");
                    623:                                goto ret;
                    624:                        }
                    625:                        if (c == '\\') {
                    626:                                c = getC(0);
                    627:                                if (c != delim /* && c != '~' */)
                    628:                                        *cp++ = '\\';
                    629:                        }
                    630:                        *cp++ = c;
                    631:                }
                    632:                *cp++ = 0;
                    633:                break;
                    634: 
                    635:        default:
                    636:                if (c == '\n')
                    637:                        unreadc(c);
                    638:                seterrc("Bad ! modifier: ", c);
                    639:                goto ret;
                    640:        }
                    641:        strcpy(slhs, lhsb);
                    642:        if (exclc)
                    643:                en = dosub(sc, en, global);
                    644: ret:
                    645:        return (en);
                    646: }
                    647: 
                    648: struct wordent *
                    649: dosub(sc, en, global)
                    650:        int sc;
                    651:        struct wordent *en;
                    652:        bool global;
                    653: {
                    654:        struct wordent lex;
                    655:        bool didsub = 0;
                    656:        struct wordent *hp = &lex;
                    657:        register struct wordent *wdp;
                    658:        register int i = exclc;
                    659: 
                    660:        wdp = hp;
                    661:        while (--i >= 0) {
                    662:                register struct wordent *new = (struct wordent *) calloc(1, sizeof *wdp);
                    663: 
                    664:                new->prev = wdp;
                    665:                new->next = hp;
                    666:                wdp->next = new;
                    667:                wdp = new;
                    668:                en = en->next;
                    669:                wdp->word = global || didsub == 0 ?
                    670:                    subword(en->word, sc, &didsub) : savestr(en->word);
                    671:        }
                    672:        if (didsub == 0)
                    673:                seterr("Modifier failed");
                    674:        hp->prev = wdp;
                    675:        return (&enthist(-1000, &lex, 0)->Hlex);
                    676: }
                    677: 
                    678: char *
                    679: subword(cp, type, adid)
                    680:        char *cp;
                    681:        int type;
                    682:        bool *adid;
                    683: {
                    684:        char wbuf[BUFSIZ];
                    685:        register char *wp, *mp, *np;
                    686:        register int i;
                    687: 
                    688:        switch (type) {
                    689: 
                    690:        case 'r':
                    691:        case 'h':
                    692:        case 't':
                    693:        case 'q':
                    694:        case 'x':
                    695:                wp = domod(cp, type);
                    696:                if (wp == 0)
                    697:                        return (savestr(cp));
                    698:                *adid = 1;
                    699:                return (wp);
                    700: 
                    701:        default:
                    702:                wp = wbuf;
                    703:                i = BUFSIZ - 4;
                    704:                for (mp = cp; *mp; mp++)
                    705:                        if (matchs(mp, lhsb)) {
                    706:                                for (np = cp; np < mp;)
                    707:                                        *wp++ = *np++, --i;
                    708:                                for (np = rhsb; *np; np++) switch (*np) {
                    709: 
                    710:                                case '\\':
                    711:                                        if (np[1] == '&')
                    712:                                                np++;
                    713:                                        /* fall into ... */
                    714: 
                    715:                                default:
                    716:                                        if (--i < 0)
                    717:                                                goto ovflo;
                    718:                                        *wp++ = *np;
                    719:                                        continue;
                    720: 
                    721:                                case '&':
                    722:                                        i -= strlen(lhsb);
                    723:                                        if (i < 0)
                    724:                                                goto ovflo;
                    725:                                        *wp = 0;
                    726:                                        strcat(wp, lhsb);
                    727:                                        wp = strend(wp);
                    728:                                        continue;
                    729:                                }
                    730:                                mp += strlen(lhsb);
                    731:                                i -= strlen(mp);
                    732:                                if (i < 0) {
                    733: ovflo:
                    734:                                        seterr("Subst buf ovflo");
                    735:                                        return ("");
                    736:                                }
                    737:                                *wp = 0;
                    738:                                strcat(wp, mp);
                    739:                                *adid = 1;
                    740:                                return (savestr(wbuf));
                    741:                        }
                    742:                return (savestr(cp));
                    743:        }
                    744: }
                    745: 
                    746: char *
                    747: domod(cp, type)
                    748:        char *cp;
                    749:        int type;
                    750: {
                    751:        register char *wp, *xp;
                    752:        register int c;
                    753: 
                    754:        switch (type) {
                    755: 
                    756:        case 'x':
                    757:        case 'q':
                    758:                wp = savestr(cp);
                    759:                for (xp = wp; c = *xp; xp++)
                    760:                        if ((c != ' ' && c != '\t') || type == 'q')
                    761:                                *xp |= QUOTE;
                    762:                return (wp);
                    763: 
                    764:        case 'h':
                    765:        case 't':
                    766:                if (!any('/', cp))
                    767:                        return (0);
                    768:                wp = strend(cp);
                    769:                while (*--wp != '/')
                    770:                        continue;
                    771:                if (type == 'h')
                    772: take:
                    773:                        xp = savestr(cp), xp[wp - cp] = 0;
                    774:                else
                    775:                        xp = savestr(wp + 1);
                    776:                return (xp);
                    777: 
                    778:        case 'r':
                    779:                wp = strend(cp);
                    780:                for (wp--; wp >= cp && *wp != '.'; wp--)
                    781:                        if (*wp == '/')
                    782:                                return (0);
                    783:                if (wp < cp)
                    784:                        return (0);
                    785:                goto take;
                    786:        }
                    787:        return (0);
                    788: }
                    789: 
                    790: matchs(str, pat)
                    791:        register char *str, *pat;
                    792: {
                    793: 
                    794:        while (*str && *pat && *str == *pat)
                    795:                str++, pat++;
                    796:        return (*pat == 0);
                    797: }
                    798: 
                    799: getsel(al, ar, dol)
                    800:        register int *al, *ar;
                    801:        int dol;
                    802: {
                    803:        register int c = getC(0);
                    804:        register int i;
                    805:        bool first = *al < 0;
                    806: 
                    807:        switch (c) {
                    808: 
                    809:        case '%':
                    810:                if (quesarg == -1)
                    811:                        goto bad;
                    812:                if (*al < 0)
                    813:                        *al = quesarg;
                    814:                *ar = quesarg;
                    815:                break;
                    816: 
                    817:        case '-':
                    818:                if (*al < 0) {
                    819:                        *al = 0;
                    820:                        *ar = dol - 1;
                    821:                        unreadc(c);
                    822:                }
                    823:                return (1);
                    824: 
                    825:        case '^':
                    826:                if (*al < 0)
                    827:                        *al = 1;
                    828:                *ar = 1;
                    829:                break;
                    830: 
                    831:        case '$':
                    832:                if (*al < 0)
                    833:                        *al = dol;
                    834:                *ar = dol;
                    835:                break;
                    836: 
                    837:        case '*':
                    838:                if (*al < 0)
                    839:                        *al = 1;
                    840:                *ar = dol;
                    841:                if (*ar < *al) {
                    842:                        *ar = 0;
                    843:                        *al = 1;
                    844:                        return (1);
                    845:                }
                    846:                break;
                    847: 
                    848:        default:
                    849:                if (digit(c)) {
                    850:                        i = 0;
                    851:                        while (digit(c)) {
                    852:                                i = i * 10 + c - '0';
                    853:                                c = getC(0);
                    854:                        }
                    855:                        if (i < 0)
                    856:                                i = dol + 1;
                    857:                        if (*al < 0)
                    858:                                *al = i;
                    859:                        *ar = i;
                    860:                } else
                    861:                        if (*al < 0)
                    862:                                *al = 0, *ar = dol;
                    863:                        else
                    864:                                *ar = dol - 1;
                    865:                unreadc(c);
                    866:                break;
                    867:        }
                    868:        if (first) {
                    869:                c = getC(0);
                    870:                unreadc(c);
                    871:                if (any(c, "-$*"))
                    872:                        return (1);
                    873:        }
                    874:        if (*al > *ar || *ar > dol) {
                    875: bad:
                    876:                seterr("Bad ! arg selector");
                    877:                return (0);
                    878:        }
                    879:        return (1);
                    880: }
                    881: 
                    882: struct wordent *
                    883: gethent(sc)
                    884:        int sc;
                    885: {
                    886:        register struct Hist *hp;
                    887:        register char *np;
                    888:        register int c;
                    889:        int event;
                    890:        bool back = 0;
                    891: 
                    892:        c = sc == '^' ? '!' : getC(0);
                    893:        switch (c) {
                    894: 
                    895:        case ':':
                    896:        case '^':
                    897:        case '$':
                    898:        case '*':
                    899:        case '%':
                    900:                ungetC(c);
                    901:                if (lastev == eventno && alhistp)
                    902:                        return (alhistp);
                    903:                event = lastev;
                    904:                break;
                    905: 
                    906:        case '!':
                    907:                event = eventno;
                    908:                break;
                    909: 
                    910:        case '-':
                    911:                back = 1;
                    912:                c = getC(0);
                    913:                goto number;
                    914: 
                    915:        default:
                    916:                if (any(c, "(=")) {
                    917:                        unreadc(c);
                    918:                        ungetC('!');
                    919:                        return (0);
                    920:                }
                    921:                if (digit(c))
                    922:                        goto number;
                    923:                np = lhsb;
                    924:                while (!any(c, ": \t\\\n}")) {
                    925:                        if (np < &lhsb[sizeof lhsb - 2])
                    926:                                *np++ = c;
                    927:                        c = getC(0);
                    928:                }
                    929:                unreadc(c);
                    930:                if (np == lhsb) {
                    931:                        ungetC('!');
                    932:                        return (0);
                    933:                }
                    934:                *np++ = 0;
                    935:                hp = findev(lhsb, 0);
                    936:                if (hp)
                    937:                        lastev = hp->Hnum;
                    938:                return (&hp->Hlex);
                    939: 
                    940:        case '?':
                    941:                np = lhsb;
                    942:                for (;;) {
                    943:                        c = getC(0);
                    944:                        if (c == '\n') {
                    945:                                unreadc(c);
                    946:                                break;
                    947:                        }
                    948:                        if (c == '?')
                    949:                                break;
                    950:                        if (np < &lhsb[sizeof lhsb - 2])
                    951:                                *np++ = c;
                    952:                }
                    953:                if (np == lhsb) {
                    954:                        if (lhsb[0] == 0) {
                    955:                                seterr("No prev search");
                    956:                                return (0);
                    957:                        }
                    958:                } else
                    959:                        *np++ = 0;
                    960:                hp = findev(lhsb, 1);
                    961:                if (hp)
                    962:                        lastev = hp->Hnum;
                    963:                return (&hp->Hlex);
                    964: 
                    965:        number:
                    966:                event = 0;
                    967:                while (digit(c)) {
                    968:                        event = event * 10 + c - '0';
                    969:                        c = getC(0);
                    970:                }
                    971:                if (back)
                    972:                        event = eventno + (alhistp == 0) - (event ? event : 0);
                    973:                unreadc(c);
                    974:                break;
                    975:        }
                    976:        for (hp = Histlist.Hnext; hp; hp = hp->Hnext)
                    977:                if (hp->Hnum == event) {
                    978:                        hp->Href = eventno;
                    979:                        lastev = hp->Hnum;
                    980:                        return (&hp->Hlex);
                    981:                }
                    982:        np = putn(event);
                    983:        noev(np);
                    984:        return (0);
                    985: }
                    986: 
                    987: struct Hist *
                    988: findev(cp, anyarg)
                    989:        char *cp;
                    990:        bool anyarg;
                    991: {
                    992:        register struct Hist *hp;
                    993: 
                    994:        for (hp = Histlist.Hnext; hp; hp = hp->Hnext)
                    995:                if (matchev(hp, cp, anyarg))
                    996:                        return (hp);
                    997:        noev(cp);
                    998:        return (0);
                    999: }
                   1000: 
                   1001: noev(cp)
                   1002:        char *cp;
                   1003: {
                   1004: 
                   1005:        seterr2(cp, ": Event not found");
                   1006: }
                   1007: 
                   1008: matchev(hp, cp, anyarg)
                   1009:        register struct Hist *hp;
                   1010:        char *cp;
                   1011:        bool anyarg;
                   1012: {
                   1013:        register char *dp;
                   1014:        struct wordent *lp = &hp->Hlex;
                   1015:        int argno = 0;
                   1016:        
                   1017:        for (;;) {
                   1018:                lp = lp->next;
                   1019:                if (lp->word[0] == '\n')
                   1020:                        return (0);
                   1021:                for (dp = lp->word; *dp; dp++) {
                   1022:                        if (matchs(dp, cp)) {
                   1023:                                if (anyarg)
                   1024:                                        quesarg = argno;
                   1025:                                return (1);
                   1026:                        }
                   1027:                        if (!anyarg)
                   1028:                                return (0);
                   1029:                }
                   1030:                argno++;
                   1031:        }
                   1032: }
                   1033: 
                   1034: setexclp(cp)
                   1035:        register char *cp;
                   1036: {
                   1037: 
                   1038:        if (cp[0] == '\n')
                   1039:                return;
                   1040:        exclp = cp;
                   1041: }
                   1042: 
                   1043: unreadc(c)
                   1044:        char c;
                   1045: {
                   1046: 
                   1047:        peekread = c;
                   1048: }
                   1049: 
                   1050: readc(wanteof)
                   1051:        bool wanteof;
                   1052: {
                   1053:        register int c;
                   1054: 
                   1055:        if (c = peekread) {
                   1056:                peekread = 0;
                   1057:                return (c);
                   1058:        }
                   1059: top:
                   1060:        if (alvecp) {
                   1061:                if (c = *alvecp++)
                   1062:                        return (c);
                   1063:                if (*alvec) {
                   1064:                        alvecp = *alvec++;
                   1065:                        return (' ');
                   1066:                }
                   1067:        }
                   1068:        if (alvec) {
                   1069:                if (alvecp = *alvec) {
                   1070:                        alvec++;
                   1071:                        goto top;
                   1072:                }
                   1073:                /* Infinite source! */
                   1074:                return ('\n');
                   1075:        }
                   1076:        do {
                   1077:                if (arginp == (char *) 1 || onelflg == 1) {
                   1078:                        if (wanteof)
                   1079:                                return (-1);
                   1080:                        exitstat();
                   1081:                }
                   1082:                if (arginp) {
                   1083:                        if ((c = *arginp++) == 0) {
                   1084:                                arginp = (char *) 1;
                   1085:                                return ('\n');
                   1086:                        }
                   1087:                        return (c);
                   1088:                }
                   1089:                c = bgetc();
                   1090:                if (c < 0) {
                   1091: #include <sgtty.h>
                   1092:                        struct sgttyb tty;
                   1093: 
                   1094:                        if (wanteof)
                   1095:                                return (-1);
                   1096:                        /* was isatty but raw with ignoreeof yields problems */
                   1097:                        if (adrof("ignoreeof") && gtty(SHIN, &tty)==0 && (tty.sg_flags & RAW) == 0) {
                   1098:                                if (loginsh)
                   1099:                                        printf("\nUse \"logout\" to logout.\n");
                   1100:                                else
                   1101:                                        printf("\nUse \"exit\" to leave csh.\n");
                   1102:                                reset();
                   1103:                        }
                   1104:                        doneinp = 1;
                   1105:                        reset();
                   1106:                }
                   1107:                if (c == '\n' && onelflg)
                   1108:                        onelflg--;
                   1109:        } while (c == 0);
                   1110:        return (c);
                   1111: }
                   1112: 
                   1113: bgetc()
                   1114: {
                   1115:        register int buf, off, c;
                   1116: 
                   1117: #ifdef TELL
                   1118:        if (cantell) {
                   1119:                if (fseekp < fbobp || fseekp > feobp) {
                   1120:                        fbobp = feobp = fseekp;
                   1121:                        lseek(SHIN, fseekp, 0);
                   1122:                }
                   1123:                if (fseekp == feobp) {
                   1124:                        fbobp = feobp;
                   1125:                        do
                   1126:                                c = read(SHIN, fbuf[0], BUFSIZ);
                   1127:                        while (c < 0 && errno == EINTR);
                   1128:                        if (c <= 0)
                   1129:                                return (-1);
                   1130:                        feobp += c;
                   1131:                }
                   1132:                c = fbuf[0][fseekp - fbobp];
                   1133:                fseekp++;
                   1134:                return (c);
                   1135:        }
                   1136: #endif
                   1137: again:
                   1138:        buf = (int) fseekp / BUFSIZ;
                   1139:        if (buf >= fblocks) {
                   1140:                register char **nfbuf = (char **) calloc(fblocks+2, sizeof (char **));
                   1141: 
                   1142:                if (fbuf) {
                   1143:                        blkcpy(nfbuf, fbuf);
                   1144:                        xfree(fbuf);
                   1145:                }
                   1146:                fbuf = nfbuf;
                   1147:                fbuf[fblocks] = calloc(BUFSIZ, sizeof (char));
                   1148:                fblocks++;
                   1149:                goto again;
                   1150:        }
                   1151:        if (fseekp >= feobp) {
                   1152:                buf = (int) feobp / BUFSIZ;
                   1153:                off = (int) feobp % BUFSIZ;
                   1154:                do
                   1155:                        c = read(SHIN, fbuf[buf] + off, BUFSIZ - off);
                   1156:                while (c < 0 && errno == EINTR);
                   1157:                if (c <= 0)
                   1158:                        return (-1);
                   1159:                feobp += c;
                   1160:                goto again;
                   1161:        }
                   1162:        c = fbuf[buf][(int) fseekp % BUFSIZ];
                   1163:        fseekp++;
                   1164:        return (c);
                   1165: }
                   1166: 
                   1167: bfree()
                   1168: {
                   1169:        register int sb, i;
                   1170: 
                   1171: #ifdef TELL
                   1172:        if (cantell)
                   1173:                return;
                   1174: #endif
                   1175:        if (whyles)
                   1176:                return;
                   1177:        sb = (int) (fseekp - 1) / BUFSIZ;
                   1178:        if (sb > 0) {
                   1179:                for (i = 0; i < sb; i++)
                   1180:                        xfree(fbuf[i]);
                   1181:                blkcpy(fbuf, &fbuf[sb]);
                   1182:                fseekp -= BUFSIZ * sb;
                   1183:                feobp -= BUFSIZ * sb;
                   1184:                fblocks -= sb;
                   1185:        }
                   1186: }
                   1187: 
                   1188: bseek(l)
                   1189:        long l;
                   1190: {
                   1191:        register struct whyle *wp;
                   1192: 
                   1193:        fseekp = l;
                   1194: #ifdef TELL
                   1195:        if (!cantell) {
                   1196: #endif
                   1197:                if (!whyles)
                   1198:                        return;
                   1199:                for (wp = whyles; wp->w_next; wp = wp->w_next)
                   1200:                        continue;
                   1201:                if (wp->w_start > l)
                   1202:                        l = wp->w_start;
                   1203: #ifdef TELL
                   1204:        }
                   1205: #endif
                   1206: }
                   1207: 
                   1208: /* any similarity to bell telephone is purely accidental */
                   1209: long
                   1210: btell()
                   1211: {
                   1212: 
                   1213:        return (fseekp);
                   1214: }
                   1215: 
                   1216: btoeof()
                   1217: {
                   1218: 
                   1219:        lseek(SHIN, 0l, 2);
                   1220:        fseekp = feobp;
                   1221:        wfree();
                   1222:        bfree();
                   1223: }
                   1224: 
                   1225: #ifdef TELL
                   1226: settell()
                   1227: {
                   1228: 
                   1229:        cantell = 0;
                   1230:        if (arginp || onelflg || intty)
                   1231:                return;
                   1232:        if (lseek(SHIN, 0l, 1) < 0 || errno == ESPIPE)
                   1233:                return;
                   1234:        fbuf = (char **) calloc(2, sizeof (char **));
                   1235:        fblocks = 1;
                   1236:        fbuf[0] = calloc(BUFSIZ, sizeof (char));
                   1237:        fseekp = fbobp = feobp = tell(SHIN);
                   1238:        cantell = 1;
                   1239: }
                   1240: #endif

unix.superglobalmegacorp.com

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