Annotation of 43BSD/contrib/jove/re1.c, revision 1.1.1.1

1.1       root        1: /*************************************************************************
                      2:  * This program is copyright (C) 1985, 1986 by Jonathan Payne.  It is    *
                      3:  * provided to you without charge for use only on a licensed Unix        *
                      4:  * system.  You may copy JOVE provided that this notice is included with *
                      5:  * the copy.  You may not sell copies of this program or versions        *
                      6:  * modified for use on microcomputer systems, unless the copies are      *
                      7:  * included with a Unix system distribution and the source is provided.  *
                      8:  *************************************************************************/
                      9: 
                     10: #include "jove.h"
                     11: #include "io.h"
                     12: #include "re.h"
                     13: 
                     14: static
                     15: substitute(query, l1, char1, l2, char2)
                     16: Line   *l1,
                     17:        *l2;
                     18: {
                     19:        Line    *lp;
                     20:        int     numdone = 0,
                     21:                offset = curchar,
                     22:                stop = 0;
                     23:        disk_line       UNDO_da = 0;
                     24:        Line            *UNDO_lp = 0;
                     25: 
                     26:        lsave();
                     27:        REdirection = FORWARD;
                     28: 
                     29:        lp = l1;
                     30:        for (lp = l1; (lp != l2->l_next) && !stop; lp = lp->l_next) {
                     31:                offset = (lp == l1) ? char1 : 0;
                     32:                while (!stop && re_lindex(lp, offset, compbuf, alternates, 0)) {
                     33:                        if (lp == l2 && REeom > char2)  /* nope, leave this alone */
                     34:                                break;
                     35:                        DotTo(lp, REeom);
                     36:                        offset = curchar;
                     37:                        if (query) {
                     38:                                message("Replace (Type '?' for help)? ");
                     39: reswitch:                      redisplay();
                     40:                                switch (Upper(getchar())) {
                     41:                                case '.':
                     42:                                        stop++;
                     43:                                        /* Fall into ... */
                     44: 
                     45:                                case ' ':
                     46:                                case 'Y':
                     47:                                        break;
                     48: 
                     49:                                case BS:
                     50:                                case RUBOUT:
                     51:                                case 'N':
                     52:                                        if (linebuf[offset++] == '\0')
                     53:                                                goto nxtline;
                     54:                                        continue;
                     55: 
                     56:                                case CTL(W):
                     57:                                        re_dosub(linebuf, YES);
                     58:                                        numdone++;
                     59:                                        offset = curchar = REbom;
                     60:                                        makedirty(curline);
                     61:                                        /* Fall into ... */
                     62: 
                     63:                                case CTL(R):
                     64:                                case 'R':
                     65:                                        RErecur();
                     66:                                        offset = curchar;
                     67:                                        lp = curline;
                     68:                                        continue;
                     69: 
                     70:                                case CTL(U):
                     71:                                case 'U':
                     72:                                        if (UNDO_lp == 0)
                     73:                                                continue;
                     74:                                        lp = UNDO_lp;
                     75:                                        lp->l_dline = UNDO_da | DIRTY;
                     76:                                        offset = 0;
                     77:                                        numdone--;
                     78:                                        continue;
                     79: 
                     80:                                case 'P':
                     81:                                case '!':
                     82:                                        query = 0;
                     83:                                        break;
                     84: 
                     85:                                case CR:
                     86:                                case LF:
                     87:                                case 'Q':
                     88:                                        goto done;
                     89: 
                     90:                                case CTL(L):
                     91:                                        RedrawDisplay();
                     92:                                        goto reswitch;
                     93: 
                     94:                                default:
                     95:                                        rbell();
                     96: message("Space or Y, Period, Rubout or N, C-R or R, C-W, C-U or U, P or !, Return.");
                     97:                                        goto reswitch;
                     98:                                }
                     99:                        }
                    100:                        re_dosub(linebuf, NO);
                    101:                        numdone++;
                    102:                        modify();
                    103:                        offset = curchar = REeom;
                    104:                        makedirty(curline);
                    105:                        if (query) {
                    106:                                message(mesgbuf);       /* No blinking. */
                    107:                                redisplay();            /* Show the change. */
                    108:                        }
                    109:                        UNDO_da = curline->l_dline;
                    110:                        UNDO_lp = curline;
                    111:                        if (linebuf[offset] == 0)
                    112: nxtline:                       break;
                    113:                }
                    114:        }
                    115:        SetMark();
                    116: done:  s_mess("%d substitution%n.", numdone, numdone);
                    117: }
                    118: 
                    119: /* Prompt for search and replacement strings and do the substitution.  The
                    120:    point is restored when we're done. */
                    121: 
                    122: static
                    123: replace(query, inreg)
                    124: {
                    125:        Mark    *save = MakeMark(curline, curchar, FLOATER),
                    126:                *m;
                    127:        char    *rep_ptr;
                    128:        Line    *l1 = curline,
                    129:                *l2 = curbuf->b_last;
                    130:        int     char1 = curchar,
                    131:                char2 = length(curbuf->b_last);
                    132: 
                    133:        if (inreg) {
                    134:                m = CurMark();
                    135:                l2 = m->m_line;
                    136:                char2 = m->m_char;
                    137:                (void) fixorder(&l1, &char1, &l2, &char2);
                    138:        }
                    139: 
                    140:        /* Get search string. */
                    141:        strcpy(rep_search, ask(rep_search[0] ? rep_search : (char *) 0, ProcFmt));
                    142:        REcompile(rep_search, UseRE, compbuf, alternates);
                    143:        /* Now the replacement string.  Do_ask() so the user can play with
                    144:           the default (previous) replacement string by typing C-R in ask(),
                    145:           OR, he can just hit Return to replace with nothing. */
                    146:        rep_ptr = do_ask("\r\n", (int (*)()) 0, rep_str, ": %f %s with ", rep_search);
                    147:        if (rep_ptr == 0)
                    148:                rep_ptr = NullStr;
                    149:        strcpy(rep_str, rep_ptr);
                    150: 
                    151:        substitute(query, l1, char1, l2, char2);
                    152:        ToMark(save);
                    153:        DelMark(save);
                    154: }
                    155: 
                    156: RegReplace()
                    157: {
                    158:        replace(0, YES);
                    159: }
                    160: 
                    161: QRepSearch()
                    162: {
                    163:        replace(1, NO);
                    164: }
                    165: 
                    166: RepSearch()
                    167: {
                    168:        replace(0, NO);
                    169: }
                    170: 
                    171: /* C tags package. */
                    172: 
                    173: static
                    174: lookup(searchbuf, filebuf, tag, file)
                    175: char   *searchbuf,
                    176:        *filebuf,
                    177:        *tag,
                    178:        *file;
                    179: {
                    180:        register int    taglen = strlen(tag);
                    181:        char    line[128],
                    182:                pattern[100];
                    183:        File    *fp;
                    184: 
                    185:        fp = open_file(file, iobuff, F_READ, !COMPLAIN, QUIET);
                    186:        if (fp == NIL)
                    187:                return 0;
                    188:        sprintf(pattern, "^%s[^\t]*\t\\([^\t]*\\)\t[?/]\\(.*\\)[?/]$", tag);
                    189:        while (f_gets(fp, line, sizeof line) != EOF) {
                    190:                if (line[0] != *tag || strncmp(tag, line, taglen) != 0)
                    191:                        continue;
                    192:                if (!LookingAt(pattern, line, 0)) {
                    193:                        complain("I thought I saw it!");
                    194:                        break;
                    195:                } else {
                    196:                        putmatch(2, searchbuf, 100);
                    197:                        putmatch(1, filebuf, 100);
                    198:                        close_file(fp);
                    199:                        return 1;
                    200:                }
                    201:        }
                    202:        f_close(fp);
                    203:        s_mess("Can't find tag \"%s\".", tag);
                    204:        return 0;
                    205: }
                    206: 
                    207: char   TagFile[128] = "./tags";
                    208: 
                    209: find_tag(tag, localp)
                    210: char   *tag;
                    211: {
                    212:        char    filebuf[FILESIZE],
                    213:                sstr[100];
                    214:        register Bufpos *bp;
                    215:        register Buffer *b;
                    216:        char    *tagfname;
                    217: 
                    218:        if (!localp)
                    219:                tagfname = ask(TagFile, "With tag file (%s default): ", TagFile);
                    220:        else
                    221:                tagfname = TagFile;
                    222:        if (lookup(sstr, filebuf, tag, tagfname) == 0)
                    223:                return;
                    224:        SetMark();
                    225:        b = do_find(curwind, filebuf, 0);
                    226:        if (curbuf != b)
                    227:                SetABuf(curbuf);
                    228:        SetBuf(b);
                    229:        if ((bp = dosearch(sstr, BACKWARD, 0)) == 0 &&
                    230:            (WrapScan || ((bp = dosearch(sstr, FORWARD, 0)) == 0)))
                    231:                message("Well, I found the file, but the tag is missing.");
                    232:        else
                    233:                SetDot(bp);
                    234: }
                    235: 
                    236: FindTag()
                    237: {
                    238:        int     localp = !exp_p;
                    239:        char    tag[128];
                    240: 
                    241:        strcpy(tag, ask((char *) 0, ProcFmt));
                    242:        find_tag(tag, localp);
                    243: }
                    244: 
                    245: /* Find Tag at Dot. */
                    246: 
                    247: FDotTag()
                    248: {
                    249:        int     c1 = curchar,
                    250:                c2 = c1;
                    251:        char    tagname[50];
                    252: 
                    253:        if (!ismword(linebuf[curchar]))
                    254:                complain("Not a tag!");
                    255:        while (c1 > 0 && ismword(linebuf[c1 - 1]))
                    256:                c1--;
                    257:        while (ismword(linebuf[c2]))
                    258:                c2++;
                    259: 
                    260:        null_ncpy(tagname, linebuf + c1, c2 - c1);
                    261:        find_tag(tagname, !exp_p);
                    262: }
                    263: 
                    264: /* I-search returns a code saying what to do:
                    265:    STOP:       We found the match, so unwind the stack and leave
                    266:                where it is.
                    267:    DELETE:     Rubout the last command.
                    268:    BACKUP:     Back up to where the isearch was last NOT failing.
                    269: 
                    270:    When a character is typed it is appended to the search string, and
                    271:    then, isearch is called recursively.  When C-S or C-R is typed, isearch
                    272:    is again called recursively. */
                    273: 
                    274: #define STOP   1
                    275: #define DELETE 2
                    276: #define BACKUP 3
                    277: #define TOSTART        4
                    278: 
                    279: static char    ISbuf[128],
                    280:                *incp = 0;
                    281: int    SExitChar = CR;
                    282: 
                    283: #define cmp_char(a, b) ((a) == (b) || (CaseIgnore && (Upper(a) == Upper(b))))
                    284: 
                    285: static Bufpos *
                    286: doisearch(dir, c, failing)
                    287: register int   c,
                    288:                dir,
                    289:                failing;
                    290: {
                    291:        static Bufpos   buf;
                    292:        Bufpos  *bp;
                    293: 
                    294:        if (c == CTL(S) || c == CTL(R))
                    295:                goto dosrch;
                    296: 
                    297:        if (failing)
                    298:                return 0;
                    299:        DOTsave(&buf);
                    300:        if (dir == FORWARD) {
                    301:                if (cmp_char(linebuf[curchar], c)) {
                    302:                        buf.p_char = curchar + 1;
                    303:                        return &buf;
                    304:                }
                    305:        } else {
                    306:                if (look_at(ISbuf))
                    307:                        return &buf;
                    308:        }
                    309: dosrch:        if ((bp = dosearch(ISbuf, dir, 0)) == 0)
                    310:                rbell();        /* ring the first time there's no match */
                    311:        return bp;
                    312: }
                    313: 
                    314: IncFSearch()
                    315: {
                    316:        IncSearch(FORWARD);
                    317: }
                    318: 
                    319: IncRSearch()
                    320: {
                    321:        IncSearch(BACKWARD);
                    322: }
                    323: 
                    324: static
                    325: IncSearch(dir)
                    326: {
                    327:        Bufpos  save_env;
                    328: 
                    329:        DOTsave(&save_env);
                    330:        ISbuf[0] = 0;
                    331:        incp = ISbuf;
                    332:        if (isearch(dir, &save_env) == TOSTART)
                    333:                SetDot(&save_env);
                    334:        else {
                    335:                if (LineDist(curline, save_env.p_line) >= MarkThresh)
                    336:                        DoSetMark(save_env.p_line, save_env.p_char);
                    337:        }
                    338:        setsearch(ISbuf);
                    339:        message(ISbuf);
                    340: }
                    341: 
                    342: /* Nicely recursive. */
                    343: 
                    344: static
                    345: isearch(dir, bp)
                    346: Bufpos *bp;
                    347: {
                    348:        Bufpos  pushbp;
                    349:        int     c,
                    350:                ndir,
                    351:                failing;
                    352:        char    *orig_incp;
                    353: 
                    354:        if (bp != 0) {          /* Move to the new position. */
                    355:                pushbp.p_line = bp->p_line;
                    356:                pushbp.p_char = bp->p_char;
                    357:                SetDot(bp);
                    358:                failing = 0;
                    359:        } else {
                    360:                DOTsave(&pushbp);
                    361:                failing = 1;
                    362:        }
                    363:        orig_incp = incp;
                    364:        ndir = dir;             /* Same direction as when we got here, unless
                    365:                                   we change it with C-S or C-R. */
                    366:        for (;;) {
                    367:                SetDot(&pushbp);
                    368:                message(NullStr);
                    369:                if (failing)
                    370:                        add_mess("Failing ");
                    371:                if (dir == BACKWARD)
                    372:                        add_mess("reverse-");
                    373:                add_mess("I-search: %s", ISbuf);
                    374:                DrawMesg(NO);
                    375:                add_mess(NullStr);      /* tell me this is disgusting ... */
                    376:                c = getch();
                    377:                if (c == SExitChar)
                    378:                        return STOP;
                    379:                switch (c) {
                    380:                case RUBOUT:
                    381:                case BS:
                    382:                        return DELETE;
                    383: 
                    384:                case CTL(G):
                    385:                        /* If we're failing, we backup until we're no longer
                    386:                           failing or we've reached the beginning; else, we
                    387:                           just about the search and go back to the start. */
                    388:                        if (failing)
                    389:                                return BACKUP;
                    390:                        return TOSTART;
                    391: 
                    392:                case CTL(\\):
                    393:                        c = CTL(S);
                    394:                case CTL(S):
                    395:                case CTL(R):
                    396:                        /* If this is the first time through and we have a
                    397:                           search string left over from last time, use that
                    398:                           one now. */
                    399:                        if (incp == ISbuf) {
                    400:                                strcpy(ISbuf, getsearch());
                    401:                                incp = &ISbuf[strlen(ISbuf)];
                    402:                        }
                    403:                        ndir = (c == CTL(S)) ? FORWARD : BACKWARD;
                    404:                        /* If we're failing and we're not changing our
                    405:                           direction, don't recur since there's no way
                    406:                           the search can work. */
                    407:                        if (failing && ndir == dir) {
                    408:                                rbell();
                    409:                                continue;
                    410:                        }
                    411:                        break;
                    412: 
                    413:                case '\\':
                    414:                        if (incp > &ISbuf[(sizeof ISbuf) - 1]) {
                    415:                                rbell();
                    416:                                continue;
                    417:                        }
                    418:                        *incp++ = '\\';
                    419:                        add_mess("\\");
                    420:                        /* Fall into ... */
                    421: 
                    422:                case CTL(Q):
                    423:                case CTL(^):
                    424:                        add_mess("");
                    425:                        c = getch() | 0400;
                    426:                        /* Fall into ... */
                    427: 
                    428:                default:
                    429:                        if (c & 0400)
                    430:                                c &= 0177;
                    431:                        else {
                    432:                                if (c > RUBOUT || (c < ' ' && c != '\t')) {
                    433:                                        Ungetc(c);
                    434:                                        return STOP;
                    435:                                }
                    436:                        }
                    437:                        if (incp > &ISbuf[(sizeof ISbuf) - 1]) {
                    438:                                rbell();
                    439:                                continue;
                    440:                        }
                    441:                        *incp++ = c;
                    442:                        *incp = 0;
                    443:                        break;
                    444:                }
                    445:                add_mess("%s", orig_incp);
                    446:                add_mess(" ...");       /* so we know what's going on */
                    447:                DrawMesg(NO);           /* do it now */
                    448:                switch (isearch(ndir, doisearch(ndir, c, failing))) {
                    449:                case TOSTART:
                    450:                        return TOSTART;
                    451: 
                    452:                case STOP:
                    453:                        return STOP;
                    454: 
                    455:                case BACKUP:
                    456:                        /* If we're not failing, we just continue to to the
                    457:                           for loop; otherwise we keep returning to the 
                    458:                           previous levels until we find one that isn't
                    459:                           failing OR we reach the beginning. */
                    460:                        if (failing)
                    461:                                return BACKUP;
                    462:                        /* Fall into ... */
                    463: 
                    464:                case DELETE:
                    465:                        incp = orig_incp;
                    466:                        *incp = 0;
                    467:                        continue;
                    468:                }
                    469:        }
                    470: }

unix.superglobalmegacorp.com

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