Annotation of 43BSDTahoe/new/jove/re1.c, revision 1.1

1.1     ! root        1: /***************************************************************************
        !             2:  * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
        !             3:  * is provided to you without charge, and with no warranty.  You may give  *
        !             4:  * away copies of JOVE, including sources, provided that this notice is    *
        !             5:  * included in all the files.                                              *
        !             6:  ***************************************************************************/
        !             7: 
        !             8: #include "jove.h"
        !             9: #include "io.h"
        !            10: #include "re.h"
        !            11: #include "ctype.h"
        !            12: 
        !            13: #ifdef MAC
        !            14: #      include "mac.h"
        !            15: #else
        !            16: #      include <sys/stat.h>
        !            17: #endif
        !            18: 
        !            19: #ifdef MAC
        !            20: #      undef private
        !            21: #      define private
        !            22: #endif
        !            23: 
        !            24: #ifdef LINT_ARGS
        !            25: private Bufpos * doisearch(int, int, int);
        !            26: 
        !            27: private void
        !            28:        IncSearch(int),
        !            29:        replace(int, int);
        !            30: private int
        !            31:        isearch(int, Bufpos *),
        !            32:        lookup(char *, char *, char *, char *),
        !            33:        substitute(int, Line *, int, Line *, int);
        !            34: #else
        !            35: private Bufpos * doisearch();
        !            36: 
        !            37: private void
        !            38:        IncSearch(),
        !            39:        replace();
        !            40: private int
        !            41:        isearch(),
        !            42:        lookup(),
        !            43:        substitute();
        !            44: #endif /* LINT_ARGS */
        !            45: 
        !            46: #ifdef MAC
        !            47: #      undef private
        !            48: #      define private static
        !            49: #endif
        !            50: 
        !            51: private int
        !            52: substitute(query, l1, char1, l2, char2)
        !            53: Line   *l1,
        !            54:        *l2;
        !            55: {
        !            56:        Line    *lp;
        !            57:        int     numdone = 0,
        !            58:                offset = curchar,
        !            59:                stop = NO;
        !            60:        disk_line       UNDO_da = 0;
        !            61:        Line            *UNDO_lp = 0;
        !            62: 
        !            63:        lsave();
        !            64:        REdirection = FORWARD;
        !            65: 
        !            66:        lp = l1;
        !            67:        for (lp = l1; (lp != l2->l_next) && !stop; lp = lp->l_next) {
        !            68:                offset = (lp == l1) ? char1 : 0;
        !            69:                while (!stop && re_lindex(lp, offset, compbuf, alternates, 0)) {
        !            70:                        if (lp == l2 && REeom > char2)  /* nope, leave this alone */
        !            71:                                break;
        !            72:                        DotTo(lp, REeom);
        !            73:                        offset = curchar;
        !            74:                        if (query) {
        !            75:                                message("Replace (Type '?' for help)? ");
        !            76: reswitch:                      redisplay();
        !            77:                                switch (CharUpcase(getchar())) {
        !            78:                                case '.':
        !            79:                                        stop = YES;
        !            80:                                        /* Fall into ... */
        !            81: 
        !            82:                                case ' ':
        !            83:                                case 'Y':
        !            84:                                        break;
        !            85: 
        !            86:                                case BS:
        !            87:                                case RUBOUT:
        !            88:                                case 'N':
        !            89:                                        if (linebuf[offset++] == '\0')
        !            90:                                                goto nxtline;
        !            91:                                        continue;
        !            92: 
        !            93:                                case CTL('W'):
        !            94:                                        re_dosub(linebuf, YES);
        !            95:                                        numdone += 1;
        !            96:                                        offset = curchar = REbom;
        !            97:                                        makedirty(curline);
        !            98:                                        /* Fall into ... */
        !            99: 
        !           100:                                case CTL('R'):
        !           101:                                case 'R':
        !           102:                                        RErecur();
        !           103:                                        offset = curchar;
        !           104:                                        lp = curline;
        !           105:                                        continue;
        !           106: 
        !           107:                                case CTL('U'):
        !           108:                                case 'U':
        !           109:                                        if (UNDO_lp == 0)
        !           110:                                                continue;
        !           111:                                        lp = UNDO_lp;
        !           112:                                        lp->l_dline = UNDO_da | DIRTY;
        !           113:                                        offset = 0;
        !           114:                                        numdone -= 1;
        !           115:                                        continue;
        !           116: 
        !           117:                                case 'P':
        !           118:                                case '!':
        !           119:                                        query = 0;
        !           120:                                        break;
        !           121: 
        !           122:                                case CR:
        !           123:                                case LF:
        !           124:                                case 'Q':
        !           125:                                        goto done;
        !           126: 
        !           127:                                case CTL('L'):
        !           128:                                        RedrawDisplay();
        !           129:                                        goto reswitch;
        !           130: 
        !           131:                                default:
        !           132:                                        rbell();
        !           133: message("Space or Y, Period, Rubout or N, C-R or R, C-W, C-U or U, P or !, Return.");
        !           134:                                        goto reswitch;
        !           135:                                }
        !           136:                        }
        !           137:                        re_dosub(linebuf, NO);
        !           138:                        numdone += 1;
        !           139:                        modify();
        !           140:                        offset = curchar = REeom;
        !           141:                        makedirty(curline);
        !           142:                        if (query) {
        !           143:                                message(mesgbuf);       /* no blinking */
        !           144:                                redisplay();            /* show the change */
        !           145:                        }
        !           146:                        UNDO_da = curline->l_dline;
        !           147:                        UNDO_lp = curline;
        !           148:                        if (linebuf[offset] == 0)
        !           149: nxtline:                       break;
        !           150:                }
        !           151:        }
        !           152: done:  return numdone;
        !           153: }
        !           154: 
        !           155: /* prompt for search and replacement strings and do the substitution */
        !           156: private void
        !           157: replace(query, inreg)
        !           158: {
        !           159:        Mark    *m;
        !           160:        char    *rep_ptr;
        !           161:        Line    *l1 = curline,
        !           162:                *l2 = curbuf->b_last;
        !           163:        int     char1 = curchar,
        !           164:                char2 = length(curbuf->b_last),
        !           165:                numdone;
        !           166: 
        !           167:        if (inreg) {
        !           168:                m = CurMark();
        !           169:                l2 = m->m_line;
        !           170:                char2 = m->m_char;
        !           171:                (void) fixorder(&l1, &char1, &l2, &char2);
        !           172:        }
        !           173: 
        !           174:        /* get search string */
        !           175:        strcpy(rep_search, ask(rep_search[0] ? rep_search : (char *) 0, ProcFmt));
        !           176:        REcompile(rep_search, UseRE, compbuf, alternates);
        !           177:        /* Now the replacement string.  Do_ask() so the user can play with
        !           178:           the default (previous) replacement string by typing C-R in ask(),
        !           179:           OR, he can just hit Return to replace with nothing. */
        !           180:        rep_ptr = do_ask("\r\n", (int (*)()) 0, rep_str, ": %f %s with ", rep_search);
        !           181:        if (rep_ptr == 0)
        !           182:                rep_ptr = NullStr;
        !           183:        strcpy(rep_str, rep_ptr);
        !           184: 
        !           185:        if (((numdone = substitute(query, l1, char1, l2, char2)) != 0) &&
        !           186:            (inreg == NO)) {
        !           187:                do_set_mark(l1, char1);
        !           188:                add_mess(" ");          /* just making things pretty */
        !           189:        } else
        !           190:                message("");
        !           191:        add_mess("(%d substitution%n)", numdone, numdone);
        !           192: }
        !           193: 
        !           194: void
        !           195: RegReplace()
        !           196: {
        !           197:        replace(0, YES);
        !           198: }
        !           199: 
        !           200: void
        !           201: QRepSearch()
        !           202: {
        !           203:        replace(1, NO);
        !           204: }
        !           205: 
        !           206: void
        !           207: RepSearch()
        !           208: {
        !           209:        replace(0, NO);
        !           210: }
        !           211: 
        !           212: /* Lookup a tag in tag file FILE.  FILE is assumed to be sorted
        !           213:    alphabetically.  The FASTTAGS code, which is implemented with
        !           214:    a binary search, depends on this assumption.  If it's not true
        !           215:    it is possible to comment out the fast tag code (which is clearly
        !           216:    labeled) and everything else will just work. */
        !           217: 
        !           218: private int
        !           219: lookup(searchbuf, filebuf, tag, file)
        !           220: char   *searchbuf,
        !           221:        *filebuf,
        !           222:        *tag,
        !           223:        *file;
        !           224: {
        !           225:        register int    taglen = strlen(tag);
        !           226:        char    line[BUFSIZ],
        !           227:                pattern[128];
        !           228:        register File   *fp;
        !           229:        struct stat     stbuf;
        !           230:        int     fast = YES,
        !           231:                success = NO;
        !           232:        register off_t  lower, upper;
        !           233: 
        !           234:        sprintf(pattern, "^%s[^\t]*\t*\\([^\t]*\\)\t*[?/]\\([^?/]*\\)[?/]", tag);
        !           235:        fp = open_file(file, iobuff, F_READ, !COMPLAIN, QUIET);
        !           236:        if (fp == NIL)
        !           237:                return 0;
        !           238: 
        !           239:        /* ********BEGIN FAST TAG CODE******** */
        !           240: 
        !           241:        if (stat(file, &stbuf) < 0)
        !           242:                fast = NO;
        !           243:        else {
        !           244:                lower = 0;
        !           245:                upper = stbuf.st_size;
        !           246:                if (upper - lower < BUFSIZ)
        !           247:                        fast = NO;
        !           248:        }
        !           249:        if (fast == YES) for (;;) {
        !           250:                off_t   mid;
        !           251:                int     whichway,
        !           252:                        chars_eq;
        !           253: 
        !           254:                if (upper - lower < BUFSIZ) {
        !           255:                        f_seek(fp, lower);
        !           256:                        break;                  /* stop this nonsense */
        !           257:                }
        !           258:                mid = (lower + upper) / 2;
        !           259:                f_seek(fp, mid);
        !           260:                f_toNL(fp);
        !           261:                if (f_gets(fp, line, sizeof line) == EOF)
        !           262:                        break;
        !           263:                chars_eq = numcomp(line, tag);
        !           264:                if (chars_eq == taglen && iswhite(line[chars_eq]))
        !           265:                        goto found;
        !           266:                whichway = line[chars_eq] - tag[chars_eq];
        !           267:                if (whichway < 0) {             /* line is BEFORE tag */
        !           268:                        lower = mid;
        !           269:                        continue;
        !           270:                } else if (whichway > 0) {      /* line is AFTER tag */
        !           271:                        upper = mid;
        !           272:                        continue;
        !           273:                }
        !           274:        }
        !           275:        f_toNL(fp);
        !           276:        /* END FAST TAG CODE */
        !           277: 
        !           278:        while (f_gets(fp, line, sizeof line) != EOF) {
        !           279:                int     cmp;
        !           280: 
        !           281:                if (line[0] > *tag)
        !           282:                        break;
        !           283:                else if ((cmp = strncmp(line, tag, taglen)) > 0)
        !           284:                        break;
        !           285:                else if (cmp < 0)
        !           286:                        continue;
        !           287:                /* if we get here, we've found the match */
        !           288: found:         if (!LookingAt(pattern, line, 0)) {
        !           289:                        complain("I thought I saw it!");
        !           290:                        break;
        !           291:                } else {
        !           292:                        putmatch(1, filebuf, FILESIZE);
        !           293:                        putmatch(2, searchbuf, 100);
        !           294:                        success = YES;
        !           295:                        break;
        !           296:                }
        !           297:        }
        !           298:        close_file(fp);
        !           299:                
        !           300:        if (success == NO)
        !           301:                s_mess("Can't find tag \"%s\".", tag);
        !           302:        return success;
        !           303: }
        !           304: 
        !           305: #ifndef MSDOS
        !           306: char   TagFile[FILESIZE] = "./tags";
        !           307: #else /* MSDOS */
        !           308: char   TagFile[FILESIZE] = "tags";
        !           309: #endif /* MSDOS */
        !           310: 
        !           311: void
        !           312: find_tag(tag, localp)
        !           313: char   *tag;
        !           314: {
        !           315:        char    filebuf[FILESIZE],
        !           316:                sstr[100],
        !           317:                tfbuf[FILESIZE];
        !           318:        register Bufpos *bp;
        !           319:        register Buffer *b;
        !           320:        char    *tagfname;
        !           321: 
        !           322:        if (!localp) {
        !           323:                char    prompt[128];
        !           324: 
        !           325:                sprintf(prompt, "With tag file (%s default): ", TagFile);
        !           326:                tagfname = ask_file(prompt, TagFile, tfbuf);
        !           327:        } else
        !           328:                tagfname = TagFile;
        !           329:        if (lookup(sstr, filebuf, tag, tagfname) == 0)
        !           330:                return;
        !           331:        set_mark();
        !           332:        b = do_find(curwind, filebuf, 0);
        !           333:        if (curbuf != b)
        !           334:                SetABuf(curbuf);
        !           335:        SetBuf(b);
        !           336:        if ((bp = dosearch(sstr, BACKWARD, 0)) == 0 &&
        !           337:            ((bp = dosearch(sstr, FORWARD, 0)) == 0))
        !           338:                message("Well, I found the file, but the tag is missing.");
        !           339:        else
        !           340:                SetDot(bp);
        !           341: }
        !           342: 
        !           343: void
        !           344: FindTag()
        !           345: {
        !           346:        int     localp = !is_an_arg();
        !           347:        char    tag[128];
        !           348: 
        !           349:        strcpy(tag, ask((char *) 0, ProcFmt));
        !           350:        find_tag(tag, localp);
        !           351: }
        !           352: 
        !           353: /* Find Tag at Dot. */
        !           354: 
        !           355: void
        !           356: FDotTag()
        !           357: {
        !           358:        int     c1 = curchar,
        !           359:                c2 = c1;
        !           360:        char    tagname[50];
        !           361: 
        !           362:        if (!ismword(linebuf[curchar]))
        !           363:                complain("Not a tag!");
        !           364:        while (c1 > 0 && ismword(linebuf[c1 - 1]))
        !           365:                c1 -= 1;
        !           366:        while (ismword(linebuf[c2]))
        !           367:                c2 += 1;
        !           368: 
        !           369:        null_ncpy(tagname, linebuf + c1, c2 - c1);
        !           370:        find_tag(tagname, !is_an_arg());
        !           371: }
        !           372: 
        !           373: /* I-search returns a code saying what to do:
        !           374:    STOP:       We found the match, so unwind the stack and leave
        !           375:                where it is.
        !           376:    DELETE:     Rubout the last command.
        !           377:    BACKUP:     Back up to where the isearch was last NOT failing.
        !           378: 
        !           379:    When a character is typed it is appended to the search string, and
        !           380:    then, isearch is called recursively.  When C-S or C-R is typed, isearch
        !           381:    is again called recursively. */
        !           382: 
        !           383: #define STOP   1
        !           384: #define DELETE 2
        !           385: #define BACKUP 3
        !           386: #define TOSTART        4
        !           387: 
        !           388: static char    ISbuf[128],
        !           389:                *incp = 0;
        !           390: int    SExitChar = CR;
        !           391: 
        !           392: #define cmp_char(a, b) ((a) == (b) || (CaseIgnore && (CharUpcase(a) == CharUpcase(b))))
        !           393: 
        !           394: static Bufpos *
        !           395: doisearch(dir, c, failing)
        !           396: register int   c,
        !           397:                dir,
        !           398:                failing;
        !           399: {
        !           400:        static Bufpos   buf;
        !           401:        Bufpos  *bp;
        !           402:        extern int      okay_wrap;
        !           403: 
        !           404:        if (c == CTL('S') || c == CTL('R'))
        !           405:                goto dosrch;
        !           406: 
        !           407:        if (failing)
        !           408:                return 0;
        !           409:        DOTsave(&buf);
        !           410:        if (dir == FORWARD) {
        !           411:                if (cmp_char(linebuf[curchar], c)) {
        !           412:                        buf.p_char = curchar + 1;
        !           413:                        return &buf;
        !           414:                }
        !           415:        } else {
        !           416:                if (look_at(ISbuf))
        !           417:                        return &buf;
        !           418:        }
        !           419: dosrch:        okay_wrap = YES;
        !           420:        if ((bp = dosearch(ISbuf, dir, 0)) == 0)
        !           421:                rbell();        /* ring the first time there's no match */
        !           422:        okay_wrap = NO;
        !           423:        return bp;
        !           424: }
        !           425: 
        !           426: void
        !           427: IncFSearch()
        !           428: {
        !           429:        IncSearch(FORWARD);
        !           430: }
        !           431: 
        !           432: void
        !           433: IncRSearch()
        !           434: {
        !           435:        IncSearch(BACKWARD);
        !           436: }
        !           437: 
        !           438: private void
        !           439: IncSearch(dir)
        !           440: {
        !           441:        Bufpos  save_env;
        !           442: 
        !           443:        DOTsave(&save_env);
        !           444:        ISbuf[0] = 0;
        !           445:        incp = ISbuf;
        !           446:        if (isearch(dir, &save_env) == TOSTART)
        !           447:                SetDot(&save_env);
        !           448:        else {
        !           449:                if (LineDist(curline, save_env.p_line) >= MarkThresh)
        !           450:                        do_set_mark(save_env.p_line, save_env.p_char);
        !           451:        }
        !           452:        setsearch(ISbuf);
        !           453: }
        !           454: 
        !           455: /* Nicely recursive. */
        !           456: 
        !           457: private int
        !           458: isearch(dir, bp)
        !           459: Bufpos *bp;
        !           460: {
        !           461:        Bufpos  pushbp;
        !           462:        int     c,
        !           463:                ndir,
        !           464:                failing;
        !           465:        char    *orig_incp;
        !           466: 
        !           467:        if (bp != 0) {          /* Move to the new position. */
        !           468:                pushbp.p_line = bp->p_line;
        !           469:                pushbp.p_char = bp->p_char;
        !           470:                SetDot(bp);
        !           471:                failing = 0;
        !           472:        } else {
        !           473:                DOTsave(&pushbp);
        !           474:                failing = 1;
        !           475:        }
        !           476:        orig_incp = incp;
        !           477:        ndir = dir;             /* Same direction as when we got here, unless
        !           478:                                   we change it with C-S or C-R. */
        !           479:        for (;;) {
        !           480:                SetDot(&pushbp);
        !           481:                message(NullStr);
        !           482:                if (failing)
        !           483:                        add_mess("Failing ");
        !           484:                if (dir == BACKWARD)
        !           485:                        add_mess("reverse-");
        !           486:                add_mess("I-search: %s", ISbuf);
        !           487:                DrawMesg(NO);
        !           488:                add_mess(NullStr);      /* tell me this is disgusting ... */
        !           489:                c = getch();
        !           490:                if (c == SExitChar)
        !           491:                        return STOP;
        !           492:                if (c == AbortChar) {
        !           493:                        /* If we're failing, we backup until we're no longer
        !           494:                           failing or we've reached the beginning; else, we
        !           495:                           just about the search and go back to the start. */
        !           496:                        if (failing)
        !           497:                                return BACKUP;
        !           498:                        return TOSTART;
        !           499:                }
        !           500:                switch (c) {
        !           501:                case RUBOUT:
        !           502:                case BS:
        !           503:                        return DELETE;
        !           504: 
        !           505:                case CTL('\\'):
        !           506:                        c = CTL('S');
        !           507: 
        !           508:                case CTL('S'):
        !           509:                case CTL('R'):
        !           510:                        /* If this is the first time through and we have a
        !           511:                           search string left over from last time, use that
        !           512:                           one now. */
        !           513:                        if (incp == ISbuf) {
        !           514:                                strcpy(ISbuf, getsearch());
        !           515:                                incp = &ISbuf[strlen(ISbuf)];
        !           516:                        }
        !           517:                        ndir = (c == CTL('S')) ? FORWARD : BACKWARD;
        !           518:                        /* If we're failing and we're not changing our
        !           519:                           direction, don't recur since there's no way
        !           520:                           the search can work. */
        !           521:                        if (failing && ndir == dir) {
        !           522:                                rbell();
        !           523:                                continue;
        !           524:                        }
        !           525:                        break;
        !           526: 
        !           527:                case '\\':
        !           528:                        if (incp > &ISbuf[(sizeof ISbuf) - 1]) {
        !           529:                                rbell();
        !           530:                                continue;
        !           531:                        }
        !           532:                        *incp++ = '\\';
        !           533:                        add_mess("\\");
        !           534:                        /* Fall into ... */
        !           535: 
        !           536:                case CTL('Q'):
        !           537:                case CTL('^'):
        !           538:                        add_mess("");
        !           539:                        c = getch() | 0400;
        !           540:                        /* Fall into ... */
        !           541: 
        !           542:                default:
        !           543:                        if (c & 0400)
        !           544:                                c &= CHARMASK;
        !           545:                        else {
        !           546: #ifdef IBMPC
        !           547:                                if (c == RUBOUT || c == 0xff || (c < ' ' && c != '\t')) {
        !           548: #else
        !           549:                                if (c > RUBOUT || (c < ' ' && c != '\t')) {
        !           550: #endif
        !           551:                                        Ungetc(c);
        !           552:                                        return STOP;
        !           553:                                }
        !           554:                        }
        !           555:                        if (incp > &ISbuf[(sizeof ISbuf) - 1]) {
        !           556:                                rbell();
        !           557:                                continue;
        !           558:                        }
        !           559:                        *incp++ = c;
        !           560:                        *incp = 0;
        !           561:                        break;
        !           562:                }
        !           563:                add_mess("%s", orig_incp);
        !           564:                add_mess(" ...");       /* so we know what's going on */
        !           565:                DrawMesg(NO);           /* do it now */
        !           566:                switch (isearch(ndir, doisearch(ndir, c, failing))) {
        !           567:                case TOSTART:
        !           568:                        return TOSTART;
        !           569: 
        !           570:                case STOP:
        !           571:                        return STOP;
        !           572: 
        !           573:                case BACKUP:
        !           574:                        /* If we're not failing, we just continue to to the
        !           575:                           for loop; otherwise we keep returning to the 
        !           576:                           previous levels until we find one that isn't
        !           577:                           failing OR we reach the beginning. */
        !           578:                        if (failing)
        !           579:                                return BACKUP;
        !           580:                        /* Fall into ... */
        !           581: 
        !           582:                case DELETE:
        !           583:                        incp = orig_incp;
        !           584:                        *incp = 0;
        !           585:                        continue;
        !           586:                }
        !           587:        }
        !           588: }

unix.superglobalmegacorp.com

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