Annotation of 43BSDReno/usr.bin/ex/ex_vops3.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1980 Regents of the University of California.
                      3:  * All rights reserved.  The Berkeley software License Agreement
                      4:  * specifies the terms and conditions for redistribution.
                      5:  */
                      6: 
                      7: #ifndef lint
                      8: static char *sccsid = "@(#)ex_vops3.c  7.4 (Berkeley) 3/9/87";
                      9: #endif not lint
                     10: 
                     11: #include "ex.h"
                     12: #include "ex_tty.h"
                     13: #include "ex_vis.h"
                     14: 
                     15: /*
                     16:  * Routines to handle structure.
                     17:  * Operations supported are:
                     18:  *     ( ) { } [ ]
                     19:  *
                     20:  * These cover:                LISP            TEXT
                     21:  *     ( )             s-exprs         sentences
                     22:  *     { }             list at same    paragraphs
                     23:  *     [ ]             defuns          sections
                     24:  *
                     25:  * { and } for C used to attempt to do something with matching {}'s, but
                     26:  * I couldn't find definitions which worked intuitively very well, so I
                     27:  * scrapped this.
                     28:  *
                     29:  * The code here is very hard to understand.
                     30:  */
                     31: line   *llimit;
                     32: int    (*lf)();
                     33: 
                     34: #ifdef LISPCODE
                     35: int    lindent();
                     36: #endif
                     37: 
                     38: bool   wasend;
                     39: 
                     40: /*
                     41:  * Find over structure, repeated count times.
                     42:  * Don't go past line limit.  F is the operation to
                     43:  * be performed eventually.  If pastatom then the user said {}
                     44:  * rather than (), implying past atoms in a list (or a paragraph
                     45:  * rather than a sentence.
                     46:  */
                     47: lfind(pastatom, cnt, f, limit)
                     48:        bool pastatom;
                     49:        int cnt, (*f)();
                     50:        line *limit;
                     51: {
                     52:        register int c;
                     53:        register int rc = 0;
                     54:        char save[LBSIZE];
                     55: 
                     56:        /*
                     57:         * Initialize, saving the current line buffer state
                     58:         * and computing the limit; a 0 argument means
                     59:         * directional end of file.
                     60:         */
                     61:        wasend = 0;
                     62:        lf = f;
                     63:        strcpy(save, linebuf);
                     64:        if (limit == 0)
                     65:                limit = dir < 0 ? one : dol;
                     66:        llimit = limit;
                     67:        wdot = dot;
                     68:        wcursor = cursor;
                     69: 
                     70:        if (pastatom >= 2) {
                     71:                while (cnt > 0 && word(f, cnt))
                     72:                        cnt--;
                     73:                if (pastatom == 3)
                     74:                        eend(f);
                     75:                if (dot == wdot) {
                     76:                        wdot = 0;
                     77:                        if (cursor == wcursor)
                     78:                                rc = -1;
                     79:                }
                     80:        }
                     81: #ifdef LISPCODE
                     82:        else if (!value(LISP)) {
                     83: #else
                     84:        else {
                     85: #endif
                     86:                char *icurs;
                     87:                line *idot;
                     88: 
                     89:                if (linebuf[0] == 0) {
                     90:                        do
                     91:                                if (!lnext())
                     92:                                        goto ret;
                     93:                        while (linebuf[0] == 0);
                     94:                        if (dir > 0) {
                     95:                                wdot--;
                     96:                                linebuf[0] = 0;
                     97:                                wcursor = linebuf;
                     98:                                /*
                     99:                                 * If looking for sentence, next line
                    100:                                 * starts one.
                    101:                                 */
                    102:                                if (!pastatom) {
                    103:                                        icurs = wcursor;
                    104:                                        idot = wdot;
                    105:                                        goto begin;
                    106:                                }
                    107:                        }
                    108:                }
                    109:                icurs = wcursor;
                    110:                idot = wdot;
                    111: 
                    112:                /*
                    113:                 * Advance so as to not find same thing again.
                    114:                 */
                    115:                if (dir > 0) {
                    116:                        if (!lnext()) {
                    117:                                rc = -1;
                    118:                                goto ret;
                    119:                        }
                    120:                } else
                    121:                        ignore(lskipa1(""));
                    122: 
                    123:                /*
                    124:                 * Count times find end of sentence/paragraph.
                    125:                 */
                    126: begin:
                    127:                for (;;) {
                    128:                        while (!endsent(pastatom))
                    129:                                if (!lnext())
                    130:                                        goto ret;
                    131:                        if (!pastatom || wcursor == linebuf && endPS())
                    132:                                if (--cnt <= 0)
                    133:                                        break;
                    134:                        if (linebuf[0] == 0) {
                    135:                                do
                    136:                                        if (!lnext())
                    137:                                                goto ret;
                    138:                                while (linebuf[0] == 0);
                    139:                        } else
                    140:                                if (!lnext())
                    141:                                        goto ret;
                    142:                }
                    143: 
                    144:                /*
                    145:                 * If going backwards, and didn't hit the end of the buffer,
                    146:                 * then reverse direction.
                    147:                 */
                    148:                if (dir < 0 && (wdot != llimit || wcursor != linebuf)) {
                    149:                        dir = 1;
                    150:                        llimit = dot;
                    151:                        /*
                    152:                         * Empty line needs special treatement.
                    153:                         * If moved to it from other than begining of next line,
                    154:                         * then a sentence starts on next line.
                    155:                         */
                    156:                        if (linebuf[0] == 0 && !pastatom && 
                    157:                           (wdot != dot - 1 || cursor != linebuf)) {
                    158:                                ignore(lnext());
                    159:                                goto ret;
                    160:                        }
                    161:                }
                    162: 
                    163:                /*
                    164:                 * If we are not at a section/paragraph division,
                    165:                 * advance to next.
                    166:                 */
                    167:                if (wcursor == icurs && wdot == idot || wcursor != linebuf || !endPS())
                    168:                        ignore(lskipa1(""));
                    169:        }
                    170: #ifdef LISPCODE
                    171:        else {
                    172:                c = *wcursor;
                    173:                /*
                    174:                 * Startup by skipping if at a ( going left or a ) going
                    175:                 * right to keep from getting stuck immediately.
                    176:                 */
                    177:                if (dir < 0 && c == '(' || dir > 0 && c == ')') {
                    178:                        if (!lnext()) {
                    179:                                rc = -1;
                    180:                                goto ret;
                    181:                        }
                    182:                }
                    183:                /*
                    184:                 * Now chew up repitition count.  Each time around
                    185:                 * if at the beginning of an s-exp (going forwards)
                    186:                 * or the end of an s-exp (going backwards)
                    187:                 * skip the s-exp.  If not at beg/end resp, then stop
                    188:                 * if we hit a higher level paren, else skip an atom,
                    189:                 * counting it unless pastatom.
                    190:                 */
                    191:                while (cnt > 0) {
                    192:                        c = *wcursor;
                    193:                        if (dir < 0 && c == ')' || dir > 0 && c == '(') {
                    194:                                if (!lskipbal("()"))
                    195:                                        goto ret;
                    196:                                /*
                    197:                                 * Unless this is the last time going
                    198:                                 * backwards, skip past the matching paren
                    199:                                 * so we don't think it is a higher level paren.
                    200:                                 */
                    201:                                if (dir < 0 && cnt == 1)
                    202:                                        goto ret;
                    203:                                if (!lnext() || !ltosolid())
                    204:                                        goto ret;
                    205:                                --cnt;
                    206:                        } else if (dir < 0 && c == '(' || dir > 0 && c == ')')
                    207:                                /* Found a higher level paren */
                    208:                                goto ret;
                    209:                        else {
                    210:                                if (!lskipatom())
                    211:                                        goto ret;
                    212:                                if (!pastatom)
                    213:                                        --cnt;
                    214:                        }
                    215:                }
                    216:        }
                    217: #endif
                    218: ret:
                    219:        strcLIN(save);
                    220:        return (rc);
                    221: }
                    222: 
                    223: /*
                    224:  * Is this the end of a sentence?
                    225:  */
                    226: /* ARGSUSED */
                    227: endsent(pastatom)
                    228:        bool pastatom;
                    229: {
                    230:        register char *cp = wcursor;
                    231:        register int d;
                    232: 
                    233:        /*
                    234:         * If this is the beginning of a line, then
                    235:         * check for the end of a paragraph or section.
                    236:         */
                    237:        if (cp == linebuf)
                    238:                return (endPS());
                    239: 
                    240:        /*
                    241:         * Sentences end with . ! ? not at the beginning
                    242:         * of the line, and must be either at the end of the line,
                    243:         * or followed by 2 spaces.  Any number of intervening ) ] ' "
                    244:         * characters are allowed.
                    245:         */
                    246:        if (!any(*cp, ".!?"))
                    247:                goto tryps;
                    248:        do
                    249:                if ((d = *++cp) == 0)
                    250:                        return (1);
                    251:        while (any(d, ")]'"));
                    252:        if (*cp == 0 || *cp++ == ' ' && *cp == ' ')
                    253:                return (1);
                    254: tryps:
                    255:        if (cp[1] == 0)
                    256:                return (endPS());
                    257:        return (0);
                    258: }
                    259: 
                    260: /*
                    261:  * End of paragraphs/sections are respective
                    262:  * macros as well as blank lines and form feeds.
                    263:  */
                    264: endPS()
                    265: {
                    266: 
                    267:        return (linebuf[0] == 0 ||
                    268:                isa(svalue(PARAGRAPHS)) || isa(svalue(SECTIONS)));
                    269:            
                    270: }
                    271: 
                    272: #ifdef LISPCODE
                    273: lindent(addr)
                    274:        line *addr;
                    275: {
                    276:        register int i;
                    277:        char *swcurs = wcursor;
                    278:        line *swdot = wdot;
                    279: 
                    280: again:
                    281:        if (addr > one) {
                    282:                register char *cp;
                    283:                register int cnt = 0;
                    284: 
                    285:                addr--;
                    286:                getline(*addr);
                    287:                for (cp = linebuf; *cp; cp++)
                    288:                        if (*cp == '(')
                    289:                                cnt++;
                    290:                        else if (*cp == ')')
                    291:                                cnt--;
                    292:                cp = vpastwh(linebuf);
                    293:                if (*cp == 0)
                    294:                        goto again;
                    295:                if (cnt == 0)
                    296:                        return (whitecnt(linebuf));
                    297:                addr++;
                    298:        }
                    299:        wcursor = linebuf;
                    300:        linebuf[0] = 0;
                    301:        wdot = addr;
                    302:        dir = -1;
                    303:        llimit = one;
                    304:        lf = lindent;
                    305:        if (!lskipbal("()"))
                    306:                i = 0;
                    307:        else if (wcursor == linebuf)
                    308:                i = 2;
                    309:        else {
                    310:                register char *wp = wcursor;
                    311: 
                    312:                dir = 1;
                    313:                llimit = wdot;
                    314:                if (!lnext() || !ltosolid() || !lskipatom()) {
                    315:                        wcursor = wp;
                    316:                        i = 1;
                    317:                } else
                    318:                        i = 0;
                    319:                i += column(wcursor) - 1;
                    320:                if (!inopen)
                    321:                        i--;
                    322:        }
                    323:        wdot = swdot;
                    324:        wcursor = swcurs;
                    325:        return (i);
                    326: }
                    327: #endif
                    328: 
                    329: lmatchp(addr)
                    330:        line *addr;
                    331: {
                    332:        register int i;
                    333:        register char *parens, *cp;
                    334: 
                    335:        for (cp = cursor; !any(*cp, "({[)}]");)
                    336:                if (*cp++ == 0)
                    337:                        return (0);
                    338:        lf = 0;
                    339:        parens = any(*cp, "()") ? "()" : any(*cp, "[]") ? "[]" : "{}";
                    340:        if (*cp == parens[1]) {
                    341:                dir = -1;
                    342:                llimit = one;
                    343:        } else {
                    344:                dir = 1;
                    345:                llimit = dol;
                    346:        }
                    347:        if (addr)
                    348:                llimit = addr;
                    349:        if (splitw)
                    350:                llimit = dot;
                    351:        wcursor = cp;
                    352:        wdot = dot;
                    353:        i = lskipbal(parens);
                    354:        return (i);
                    355: }
                    356: 
                    357: lsmatch(cp)
                    358:        char *cp;
                    359: {
                    360:        char save[LBSIZE];
                    361:        register char *sp = save;
                    362:        register char *scurs = cursor;
                    363: 
                    364:        wcursor = cp;
                    365:        strcpy(sp, linebuf);
                    366:        *wcursor = 0;
                    367:        strcpy(cursor, genbuf);
                    368:        cursor = strend(linebuf) - 1;
                    369:        if (lmatchp(dot - vcline)) {
                    370:                register int i = insmode;
                    371:                register int c = outcol;
                    372:                register int l = outline;
                    373: 
                    374:                if (!MI)
                    375:                        endim();
                    376:                vgoto(splitw ? WECHO : LINE(wdot - llimit), column(wcursor) - 1);
                    377:                flush();
                    378:                sleep(1);
                    379:                vgoto(l, c);
                    380:                if (i)
                    381:                        goim();
                    382:        }
                    383:        else {
                    384:                strcLIN(sp);
                    385:                strcpy(scurs, genbuf);
                    386:                if (!lmatchp((line *) 0))
                    387:                        beep();
                    388:        }
                    389:        strcLIN(sp);
                    390:        wdot = 0;
                    391:        wcursor = 0;
                    392:        cursor = scurs;
                    393: }
                    394: 
                    395: ltosolid()
                    396: {
                    397: 
                    398:        return (ltosol1("()"));
                    399: }
                    400: 
                    401: ltosol1(parens)
                    402:        register char *parens;
                    403: {
                    404:        register char *cp;
                    405: 
                    406:        if (*parens && !*wcursor && !lnext())
                    407:                return (0);
                    408:        while (isspace(*wcursor) || (*wcursor == 0 && *parens))
                    409:                if (!lnext())
                    410:                        return (0);
                    411:        if (any(*wcursor, parens) || dir > 0)
                    412:                return (1);
                    413:        for (cp = wcursor; cp > linebuf; cp--)
                    414:                if (isspace(cp[-1]) || any(cp[-1], parens))
                    415:                        break;
                    416:        wcursor = cp;
                    417:        return (1);
                    418: }
                    419: 
                    420: lskipbal(parens)
                    421:        register char *parens;
                    422: {
                    423:        register int level = dir;
                    424:        register int c;
                    425: 
                    426:        do {
                    427:                if (!lnext()) {
                    428:                        wdot = NOLINE;
                    429:                        return (0);
                    430:                }
                    431:                c = *wcursor;
                    432:                if (c == parens[1])
                    433:                        level--;
                    434:                else if (c == parens[0])
                    435:                        level++;
                    436:        } while (level);
                    437:        return (1);
                    438: }
                    439: 
                    440: lskipatom()
                    441: {
                    442: 
                    443:        return (lskipa1("()"));
                    444: }
                    445: 
                    446: lskipa1(parens)
                    447:        register char *parens;
                    448: {
                    449:        register int c;
                    450: 
                    451:        for (;;) {
                    452:                if (dir < 0 && wcursor == linebuf) {
                    453:                        if (!lnext())
                    454:                                return (0);
                    455:                        break;
                    456:                }
                    457:                c = *wcursor;
                    458:                if (c && (isspace(c) || any(c, parens)))
                    459:                        break;
                    460:                if (!lnext())
                    461:                        return (0);
                    462:                if (dir > 0 && wcursor == linebuf)
                    463:                        break;
                    464:        }
                    465:        return (ltosol1(parens));
                    466: }
                    467: 
                    468: lnext()
                    469: {
                    470: 
                    471:        if (dir > 0) {
                    472:                if (*wcursor)
                    473:                        wcursor++;
                    474:                if (*wcursor)
                    475:                        return (1);
                    476:                if (wdot >= llimit) {
                    477:                        if (lf == vmove && wcursor > linebuf)
                    478:                                wcursor--;
                    479:                        return (0);
                    480:                }
                    481:                wdot++;
                    482:                getline(*wdot);
                    483:                wcursor = linebuf;
                    484:                return (1);
                    485:        } else {
                    486:                --wcursor;
                    487:                if (wcursor >= linebuf)
                    488:                        return (1);
                    489: #ifdef LISPCODE
                    490:                if (lf == lindent && linebuf[0] == '(')
                    491:                        llimit = wdot;
                    492: #endif
                    493:                if (wdot <= llimit) {
                    494:                        wcursor = linebuf;
                    495:                        return (0);
                    496:                }
                    497:                wdot--;
                    498:                getline(*wdot);
                    499:                wcursor = linebuf[0] == 0 ? linebuf : strend(linebuf) - 1;
                    500:                return (1);
                    501:        }
                    502: }
                    503: 
                    504: lbrack(c, f)
                    505:        register int c;
                    506:        int (*f)();
                    507: {
                    508:        register line *addr;
                    509: 
                    510:        addr = dot;
                    511:        for (;;) {
                    512:                addr += dir;
                    513:                if (addr < one || addr > dol) {
                    514:                        addr -= dir;
                    515:                        break;
                    516:                }
                    517:                getline(*addr);
                    518:                if (linebuf[0] == '{' ||
                    519: #ifdef LISPCODE
                    520:                    value(LISP) && linebuf[0] == '(' ||
                    521: #endif
                    522:                    isa(svalue(SECTIONS))) {
                    523:                        if (c == ']' && f != vmove) {
                    524:                                addr--;
                    525:                                getline(*addr);
                    526:                        }
                    527:                        break;
                    528:                }
                    529:                if (c == ']' && f != vmove && linebuf[0] == '}')
                    530:                        break;
                    531:        }
                    532:        if (addr == dot)
                    533:                return (0);
                    534:        if (f != vmove)
                    535:                wcursor = c == ']' ? strend(linebuf) : linebuf;
                    536:        else
                    537:                wcursor = 0;
                    538:        wdot = addr;
                    539:        vmoving = 0;
                    540:        return (1);
                    541: }
                    542: 
                    543: isa(cp)
                    544:        register char *cp;
                    545: {
                    546: 
                    547:        if (linebuf[0] != '.')
                    548:                return (0);
                    549:        for (; cp[0] && cp[1]; cp += 2)
                    550:                if (linebuf[1] == cp[0]) {
                    551:                        if (linebuf[2] == cp[1])
                    552:                                return (1);
                    553:                        if (linebuf[2] == 0 && cp[1] == ' ')
                    554:                                return (1);
                    555:                }
                    556:        return (0);
                    557: }

unix.superglobalmegacorp.com

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