# 2.11BSD#431 - /usr/src/new/jove/re1.c

##### Functions

    FDotTag           X
    FindTag           X
    IncFSearch        X
    IncRSearch        X
    IncSearch         X
    QRepSearch        X
    RegReplace        X
    RepSearch         X
    find_tag          X
    isearch           X
    lookup            X
    replace           X
    substitute        X

##### Variables

    SExitChar         X
    TagFile           X
    private           X

##### Macros

    BACKUP            X
    DELETE            X
    STOP              X
    TOSTART           X
    cmp_char          X
    private           X

       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:         tagfname = ask_file("With tag file: ", TagFile, tfbuf);
     324:     else
     325:         tagfname = TagFile;
     326:     if (lookup(sstr, filebuf, tag, tagfname) == 0)
     327:         return;
     328:     set_mark();
     329:     b = do_find(curwind, filebuf, 0);
     330:     if (curbuf != b)
     331:         SetABuf(curbuf);
     332:     SetBuf(b);
     333:     if ((bp = dosearch(sstr, BACKWARD, 0)) == 0 &&
     334:         ((bp = dosearch(sstr, FORWARD, 0)) == 0))
     335:         message("Well, I found the file, but the tag is missing.");
     336:     else
     337:         SetDot(bp);
     338: }
     339:
     340: void
     341: FindTag()
     342: {
     343:     int localp = !is_an_arg();
     344:     char    tag[128];
     345:
     346:     strcpy(tag, ask((char *) 0, ProcFmt));
     347:     find_tag(tag, localp);
     348: }
     349:
     350: /* Find Tag at Dot. */
     351:
     352: void
     353: FDotTag()
     354: {
     355:     int c1 = curchar,
     356:         c2 = c1;
     357:     char    tagname[50];
     358:
     359:     if (!ismword(linebuf[curchar]))
     360:         complain("Not a tag!");
     361:     while (c1 > 0 && ismword(linebuf[c1 - 1]))
     362:         c1 -= 1;
     363:     while (ismword(linebuf[c2]))
     364:         c2 += 1;
     365:
     366:     null_ncpy(tagname, linebuf + c1, c2 - c1);
     367:     find_tag(tagname, !is_an_arg());
     368: }
     369:
     370: /* I-search returns a code saying what to do:
     371:    STOP:	We found the match, so unwind the stack and leave
     372: 		where it is.
     373:    DELETE:	Rubout the last command.
     374:    BACKUP:	Back up to where the isearch was last NOT failing.
     375:
     376:    When a character is typed it is appended to the search string, and
     377:    then, isearch is called recursively.  When C-S or C-R is typed, isearch
     378:    is again called recursively. */
     379:
     380: #define STOP    1
     381: #define DELETE  2
     382: #define BACKUP  3
     383: #define TOSTART 4
     384:
     385: static char ISbuf[128],
     386:         *incp = 0;
     387: int SExitChar = CR;
     388:
     389: #define cmp_char(a, b)  ((a) == (b) || (CaseIgnore && (CharUpcase(a) == CharUpcase(b))))
     390:
     391: static Bufpos *
     392: doisearch(dir, c, failing)
     393: register int    c,
     394:         dir,
     395:         failing;
     396: {
     397:     static Bufpos   buf;
     398:     Bufpos  *bp;
     399:     extern int  okay_wrap;
     400:
     401:     if (c == CTL('S') || c == CTL('R'))
     402:         goto dosrch;
     403:
     404:     if (failing)
     405:         return 0;
     406:     DOTsave(&buf);
     407:     if (dir == FORWARD) {
     408:         if (cmp_char(linebuf[curchar], c)) {
     409:             buf.p_char = curchar + 1;
     410:             return &buf;
     411:         }
     412:     } else {
     413:         if (look_at(ISbuf))
     414:             return &buf;
     415:     }
     416: dosrch: okay_wrap = YES;
     417:     if ((bp = dosearch(ISbuf, dir, 0)) == 0)
     418:         rbell();    /* ring the first time there's no match */
     419:     okay_wrap = NO;
     420:     return bp;
     421: }
     422:
     423: void
     424: IncFSearch()
     425: {
     426:     IncSearch(FORWARD);
     427: }
     428:
     429: void
     430: IncRSearch()
     431: {
     432:     IncSearch(BACKWARD);
     433: }
     434:
     435: private void
     436: IncSearch(dir)
     437: {
     438:     Bufpos  save_env;
     439:
     440:     DOTsave(&save_env);
     441:     ISbuf[0] = 0;
     442:     incp = ISbuf;
     443:     if (isearch(dir, &save_env) == TOSTART)
     444:         SetDot(&save_env);
     445:     else {
     446:         if (LineDist(curline, save_env.p_line) >= MarkThresh)
     447:             do_set_mark(save_env.p_line, save_env.p_char);
     448:     }
     449:     setsearch(ISbuf);
     450: }
     451:
     452: /* Nicely recursive. */
     453:
     454: private int
     455: isearch(dir, bp)
     456: Bufpos  *bp;
     457: {
     458:     Bufpos  pushbp;
     459:     int c,
     460:         ndir,
     461:         failing;
     462:     char    *orig_incp;
     463:
     464:     if (bp != 0) {      /* Move to the new position. */
     465:         pushbp.p_line = bp->p_line;
     466:         pushbp.p_char = bp->p_char;
     467:         SetDot(bp);
     468:         failing = 0;
     469:     } else {
     470:         DOTsave(&pushbp);
     471:         failing = 1;
     472:     }
     473:     orig_incp = incp;
     474:     ndir = dir;     /* Same direction as when we got here, unless
     475: 				   we change it with C-S or C-R. */
     476:     for (;;) {
     477:         SetDot(&pushbp);
     478:         message(NullStr);
     479:         if (failing)
     480:             add_mess("Failing ");
     481:         if (dir == BACKWARD)
     482:             add_mess("reverse-");
     483:         add_mess("I-search: %s", ISbuf);
     484:         DrawMesg(NO);
     485:         add_mess(NullStr);  /* tell me this is disgusting ... */
     486:         c = getch();
     487:         if (c == SExitChar)
     488:             return STOP;
     489:         if (c == AbortChar) {
     490:             /* If we're failing, we backup until we're no longer
     491: 			   failing or we've reached the beginning; else, we
     492: 			   just about the search and go back to the start. */
     493:             if (failing)
     494:                 return BACKUP;
     495:             return TOSTART;
     496:         }
     497:         switch (c) {
     498:         case RUBOUT:
     499:         case BS:
     500:             return DELETE;
     501:
     502:         case CTL('\\'):
     503:             c = CTL('S');
     504:
     505:         case CTL('S'):
     506:         case CTL('R'):
     507:             /* If this is the first time through and we have a
     508: 			   search string left over from last time, use that
     509: 			   one now. */
     510:             if (incp == ISbuf) {
     511:                 strcpy(ISbuf, getsearch());
     512:                 incp = &ISbuf[strlen(ISbuf)];
     513:             }
     514:             ndir = (c == CTL('S')) ? FORWARD : BACKWARD;
     515:             /* If we're failing and we're not changing our
     516: 			   direction, don't recur since there's no way
     517: 			   the search can work. */
     518:             if (failing && ndir == dir) {
     519:                 rbell();
     520:                 continue;
     521:             }
     522:             break;
     523:
     524:         case '\\':
     525:             if (incp > &ISbuf[(sizeof ISbuf) - 1]) {
     526:                 rbell();
     527:                 continue;
     528:             }
     529:             *incp++ = '\\';
     530:             add_mess("\\");
     531:             /* Fall into ... */
     532:
     533:         case CTL('Q'):
     534:         case CTL('^'):
     535:             add_mess("");
     536:             c = getch() | 0400;
     537:             /* Fall into ... */
     538:
     539:         default:
     540:             if (c & 0400)
     541:                 c &= CHARMASK;
     542:             else {
     543: #ifdef IBMPC
     544:                 if (c == RUBOUT || c == 0xff || (c < ' ' && c != '\t')) {
     545: #else
     546:                 if (c > RUBOUT || (c < ' ' && c != '\t')) {
     547: #endif
     548:                     Ungetc(c);
     549:                     return STOP;
     550:                 }
     551:             }
     552:             if (incp > &ISbuf[(sizeof ISbuf) - 1]) {
     553:                 rbell();
     554:                 continue;
     555:             }
     556:             *incp++ = c;
     557:             *incp = 0;
     558:             break;
     559:         }
     560:         add_mess("%s", orig_incp);
     561:         add_mess(" ...");   /* so we know what's going on */
     562:         DrawMesg(NO);       /* do it now */
     563:         switch (isearch(ndir, doisearch(ndir, c, failing))) {
     564:         case TOSTART:
     565:             return TOSTART;
     566:
     567:         case STOP:
     568:             return STOP;
     569:
     570:         case BACKUP:
     571:             /* If we're not failing, we just continue to to the
     572: 			   for loop; otherwise we keep returning to the
     573: 			   previous levels until we find one that isn't
     574: 			   failing OR we reach the beginning. */
     575:             if (failing)
     576:                 return BACKUP;
     577:             /* Fall into ... */
     578:
     579:         case DELETE:
     580:             incp = orig_incp;
     581:             *incp = 0;
     582:             continue;
     583:         }
     584:     }
     585: }

#### Defined functions

FDotTag defined in line 352; used 4 times

- in /usr/src/new/jove/externs.h line 284, 892
- in /usr/src/new/jove/funcdefs.c line 110, 397

FindTag defined in line 340; used 6 times

- in /usr/src/new/jove/externs.h line 292, 900
- in /usr/src/new/jove/funcdefs.c line 109, 396
- in /usr/src/new/jove/wind.c line 246, 255

IncFSearch defined in line 423; used 4 times

- in /usr/src/new/jove/externs.h line 305, 913
- in /usr/src/new/jove/funcdefs.c line 118, 414

IncRSearch defined in line 429; used 4 times

- in /usr/src/new/jove/externs.h line 306, 914
- in /usr/src/new/jove/funcdefs.c line 119, 415

IncSearch defined in line 435; used 4 times

- in line 28, 38, 426, 432

QRepSearch defined in line 200; used 4 times

- in /usr/src/new/jove/externs.h line 350, 958
- in /usr/src/new/jove/funcdefs.c line 172, 495

RegReplace defined in line 194; used 4 times

- in /usr/src/new/jove/externs.h line 360, 968
- in /usr/src/new/jove/funcdefs.c line 171, 506

RepSearch defined in line 206; used 4 times

- in /usr/src/new/jove/externs.h line 363, 971
- in /usr/src/new/jove/funcdefs.c line 178, 507

doisearch defined in line 391; used 3 times

- in line 25, 35, 563

find_tag defined in line 311; used 6 times

- in line 347, 367
- in /usr/src/new/jove/externs.h line 461, 1069
- in /usr/src/new/jove/jove.c line 822-827(2)

isearch defined in line 454; used 4 times

- in line 31, 41, 443, 563

lookup defined in line 218; used 3 times

- in line 32, 42, 326

replace defined in line 156; used 5 times

- in line 29, 39, 197, 203, 209

substitute defined in line 51; used 3 times

- in line 33, 43, 185

#### Defined variables

ISbuf defined in line 385; used 14 times

- in line 413-417(2), 441-442(2), 449, 483, 510-512(4), 525(2), 552(2)

SExitChar defined in line 387; used 3 times

- in line 487
- in /usr/src/new/jove/re1.c line 487
- in /usr/src/new/jove/vars.c line 80

TagFile defined in line 308; used 5 times

- in line 323-325(2)
- in /usr/src/new/jove/re1.c line 323-325(2)
- in /usr/src/new/jove/vars.c line 89

incp defined in line 386; used 11 times

- in line 442, 473, 510-512(2), 525-529(2), 552-557(3), 580-581(2)

private defined in line 454; never used

#### Defined macros

BACKUP defined in line 382; used 2 times

- in line 494, 576

DELETE defined in line 381; used 1 times

- in line 500

STOP defined in line 380; used 3 times

- in line 488, 549, 568

TOSTART defined in line 383; used 3 times

- in line 443, 495, 565

cmp_char defined in line 389; used 1 times

- in line 408

private defined in line 48; used 10 times

- in line 20-40(7), 47-51(2), 156

Last modified: 1988-08-11 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1221 |