Annotation of 43BSD/contrib/jove/re1.c, revision 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.