Annotation of 3BSD/cmd/ex/ex_vops3.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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