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

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

unix.superglobalmegacorp.com

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