Annotation of src/usr.bin/more/prim.c, Revision 1.1
1.1 ! deraadt 1: /*
! 2: * Copyright (c) 1988 Mark Nudleman
! 3: * Copyright (c) 1988 Regents of the University of California.
! 4: * All rights reserved.
! 5: *
! 6: * Redistribution and use in source and binary forms, with or without
! 7: * modification, are permitted provided that the following conditions
! 8: * are met:
! 9: * 1. Redistributions of source code must retain the above copyright
! 10: * notice, this list of conditions and the following disclaimer.
! 11: * 2. Redistributions in binary form must reproduce the above copyright
! 12: * notice, this list of conditions and the following disclaimer in the
! 13: * documentation and/or other materials provided with the distribution.
! 14: * 3. All advertising materials mentioning features or use of this software
! 15: * must display the following acknowledgement:
! 16: * This product includes software developed by the University of
! 17: * California, Berkeley and its contributors.
! 18: * 4. Neither the name of the University nor the names of its contributors
! 19: * may be used to endorse or promote products derived from this software
! 20: * without specific prior written permission.
! 21: *
! 22: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 23: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 24: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 25: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 26: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 27: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 28: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 29: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 30: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 31: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 32: * SUCH DAMAGE.
! 33: */
! 34:
! 35: #ifndef lint
! 36: /* from: static char sccsid[] = "@(#)prim.c 5.8 (Berkeley) 6/1/90"; */
! 37: static char *rcsid = "$Id: prim.c,v 1.4 1994/12/24 17:17:12 cgd Exp $";
! 38: #endif /* not lint */
! 39:
! 40: /*
! 41: * Primitives for displaying the file on the screen.
! 42: */
! 43:
! 44: #include <sys/types.h>
! 45: #include <stdio.h>
! 46: #include <stdlib.h>
! 47: #include <ctype.h>
! 48: #include <less.h>
! 49:
! 50: #ifdef REGEX
! 51: #include <regex.h>
! 52: #endif
! 53:
! 54: int back_scroll = -1;
! 55: int hit_eof; /* keeps track of how many times we hit end of file */
! 56: int screen_trashed;
! 57:
! 58: static int squished;
! 59:
! 60: extern int sigs;
! 61: extern int top_scroll;
! 62: extern int sc_width, sc_height;
! 63: extern int caseless;
! 64: extern int linenums;
! 65: extern int tagoption;
! 66: extern char *line;
! 67:
! 68: off_t position(), forw_line(), back_line(), forw_raw_line(), back_raw_line();
! 69: off_t ch_length(), ch_tell();
! 70:
! 71: /*
! 72: * Check to see if the end of file is currently "displayed".
! 73: */
! 74: eof_check()
! 75: {
! 76: off_t pos;
! 77:
! 78: if (sigs)
! 79: return;
! 80: /*
! 81: * If the bottom line is empty, we are at EOF.
! 82: * If the bottom line ends at the file length,
! 83: * we must be just at EOF.
! 84: */
! 85: pos = position(BOTTOM_PLUS_ONE);
! 86: if (pos == NULL_POSITION || pos == ch_length())
! 87: hit_eof++;
! 88: }
! 89:
! 90: /*
! 91: * If the screen is "squished", repaint it.
! 92: * "Squished" means the first displayed line is not at the top
! 93: * of the screen; this can happen when we display a short file
! 94: * for the first time.
! 95: */
! 96: squish_check()
! 97: {
! 98: if (squished) {
! 99: squished = 0;
! 100: repaint();
! 101: }
! 102: }
! 103:
! 104: /*
! 105: * Display n lines, scrolling forward, starting at position pos in the
! 106: * input file. "only_last" means display only the last screenful if
! 107: * n > screen size.
! 108: */
! 109: forw(n, pos, only_last)
! 110: register int n;
! 111: off_t pos;
! 112: int only_last;
! 113: {
! 114: extern int short_file;
! 115: static int first_time = 1;
! 116: int eof = 0, do_repaint;
! 117:
! 118: squish_check();
! 119:
! 120: /*
! 121: * do_repaint tells us not to display anything till the end,
! 122: * then just repaint the entire screen.
! 123: */
! 124: do_repaint = (only_last && n > sc_height-1);
! 125:
! 126: if (!do_repaint) {
! 127: if (top_scroll && n >= sc_height - 1) {
! 128: /*
! 129: * Start a new screen.
! 130: * {{ This is not really desirable if we happen
! 131: * to hit eof in the middle of this screen,
! 132: * but we don't yet know if that will happen. }}
! 133: */
! 134: clear();
! 135: home();
! 136: } else {
! 137: lower_left();
! 138: clear_eol();
! 139: }
! 140:
! 141: /*
! 142: * This is not contiguous with what is currently displayed.
! 143: * Clear the screen image (position table) and start a new
! 144: * screen.
! 145: */
! 146: if (pos != position(BOTTOM_PLUS_ONE)) {
! 147: pos_clear();
! 148: add_forw_pos(pos);
! 149: if (top_scroll) {
! 150: clear();
! 151: home();
! 152: } else if (!first_time)
! 153: putstr("...skipping...\n");
! 154: }
! 155: }
! 156:
! 157: for (short_file = 0; --n >= 0;) {
! 158: /*
! 159: * Read the next line of input.
! 160: */
! 161: pos = forw_line(pos);
! 162: if (pos == NULL_POSITION) {
! 163: /*
! 164: * end of file; copy the table if the file was
! 165: * too small for an entire screen.
! 166: */
! 167: eof = 1;
! 168: if (position(TOP) == NULL_POSITION) {
! 169: copytable();
! 170: if (!position(TOP))
! 171: short_file = 1;
! 172: }
! 173: break;
! 174: }
! 175: /*
! 176: * Add the position of the next line to the position table.
! 177: * Display the current line on the screen.
! 178: */
! 179: add_forw_pos(pos);
! 180: if (do_repaint)
! 181: continue;
! 182: /*
! 183: * If this is the first screen displayed and we hit an early
! 184: * EOF (i.e. before the requested number of lines), we
! 185: * "squish" the display down at the bottom of the screen.
! 186: * But don't do this if a -t option was given; it can cause
! 187: * us to start the display after the beginning of the file,
! 188: * and it is not appropriate to squish in that case.
! 189: */
! 190: if (first_time && line == NULL && !top_scroll && !tagoption) {
! 191: squished = 1;
! 192: continue;
! 193: }
! 194: put_line();
! 195: }
! 196:
! 197: if (eof && !sigs)
! 198: hit_eof++;
! 199: else
! 200: eof_check();
! 201: if (do_repaint)
! 202: repaint();
! 203: first_time = 0;
! 204: (void) currline(BOTTOM);
! 205: }
! 206:
! 207: /*
! 208: * Display n lines, scrolling backward.
! 209: */
! 210: back(n, pos, only_last)
! 211: register int n;
! 212: off_t pos;
! 213: int only_last;
! 214: {
! 215: int do_repaint;
! 216:
! 217: squish_check();
! 218: do_repaint = (n > get_back_scroll() || (only_last && n > sc_height-1));
! 219: hit_eof = 0;
! 220: while (--n >= 0)
! 221: {
! 222: /*
! 223: * Get the previous line of input.
! 224: */
! 225: pos = back_line(pos);
! 226: if (pos == NULL_POSITION)
! 227: break;
! 228: /*
! 229: * Add the position of the previous line to the position table.
! 230: * Display the line on the screen.
! 231: */
! 232: add_back_pos(pos);
! 233: if (!do_repaint)
! 234: {
! 235: home();
! 236: add_line();
! 237: put_line();
! 238: }
! 239: }
! 240:
! 241: eof_check();
! 242: if (do_repaint)
! 243: repaint();
! 244: (void) currline(BOTTOM);
! 245: }
! 246:
! 247: /*
! 248: * Display n more lines, forward.
! 249: * Start just after the line currently displayed at the bottom of the screen.
! 250: */
! 251: forward(n, only_last)
! 252: int n;
! 253: int only_last;
! 254: {
! 255: off_t pos;
! 256:
! 257: if (hit_eof) {
! 258: /*
! 259: * If we're trying to go forward from end-of-file,
! 260: * go on to the next file.
! 261: */
! 262: next_file(1);
! 263: return;
! 264: }
! 265:
! 266: pos = position(BOTTOM_PLUS_ONE);
! 267: if (pos == NULL_POSITION)
! 268: {
! 269: hit_eof++;
! 270: return;
! 271: }
! 272: forw(n, pos, only_last);
! 273: }
! 274:
! 275: /*
! 276: * Display n more lines, backward.
! 277: * Start just before the line currently displayed at the top of the screen.
! 278: */
! 279: backward(n, only_last)
! 280: int n;
! 281: int only_last;
! 282: {
! 283: off_t pos;
! 284:
! 285: pos = position(TOP);
! 286: /*
! 287: * This will almost never happen, because the top line is almost
! 288: * never empty.
! 289: */
! 290: if (pos == NULL_POSITION)
! 291: return;
! 292: back(n, pos, only_last);
! 293: }
! 294:
! 295: /*
! 296: * Repaint the screen, starting from a specified position.
! 297: */
! 298: prepaint(pos)
! 299: off_t pos;
! 300: {
! 301: hit_eof = 0;
! 302: forw(sc_height-1, pos, 0);
! 303: screen_trashed = 0;
! 304: }
! 305:
! 306: /*
! 307: * Repaint the screen.
! 308: */
! 309: repaint()
! 310: {
! 311: /*
! 312: * Start at the line currently at the top of the screen
! 313: * and redisplay the screen.
! 314: */
! 315: prepaint(position(TOP));
! 316: }
! 317:
! 318: /*
! 319: * Jump to the end of the file.
! 320: * It is more convenient to paint the screen backward,
! 321: * from the end of the file toward the beginning.
! 322: */
! 323: jump_forw()
! 324: {
! 325: off_t pos;
! 326:
! 327: if (ch_end_seek())
! 328: {
! 329: error("Cannot seek to end of file");
! 330: return;
! 331: }
! 332: lastmark();
! 333: pos = ch_tell();
! 334: clear();
! 335: pos_clear();
! 336: add_back_pos(pos);
! 337: back(sc_height - 1, pos, 0);
! 338: }
! 339:
! 340: /*
! 341: * Jump to line n in the file.
! 342: */
! 343: jump_back(n)
! 344: register int n;
! 345: {
! 346: register int c, nlines;
! 347:
! 348: /*
! 349: * This is done the slow way, by starting at the beginning
! 350: * of the file and counting newlines.
! 351: *
! 352: * {{ Now that we have line numbering (in linenum.c),
! 353: * we could improve on this by starting at the
! 354: * nearest known line rather than at the beginning. }}
! 355: */
! 356: if (ch_seek((off_t)0)) {
! 357: /*
! 358: * Probably a pipe with beginning of file no longer buffered.
! 359: * If he wants to go to line 1, we do the best we can,
! 360: * by going to the first line which is still buffered.
! 361: */
! 362: if (n <= 1 && ch_beg_seek() == 0)
! 363: jump_loc(ch_tell());
! 364: error("Cannot get to beginning of file");
! 365: return;
! 366: }
! 367:
! 368: /*
! 369: * Start counting lines.
! 370: */
! 371: for (nlines = 1; nlines < n; nlines++)
! 372: while ((c = ch_forw_get()) != '\n')
! 373: if (c == EOI) {
! 374: char message[40];
! 375: (void)sprintf(message, "File has only %d lines",
! 376: nlines - 1);
! 377: error(message);
! 378: return;
! 379: }
! 380: jump_loc(ch_tell());
! 381: }
! 382:
! 383: /*
! 384: * Jump to a specified percentage into the file.
! 385: * This is a poor compensation for not being able to
! 386: * quickly jump to a specific line number.
! 387: */
! 388: jump_percent(percent)
! 389: int percent;
! 390: {
! 391: off_t pos, len, ch_length();
! 392: register int c;
! 393:
! 394: /*
! 395: * Determine the position in the file
! 396: * (the specified percentage of the file's length).
! 397: */
! 398: if ((len = ch_length()) == NULL_POSITION)
! 399: {
! 400: error("Don't know length of file");
! 401: return;
! 402: }
! 403: pos = (percent * len) / 100;
! 404:
! 405: /*
! 406: * Back up to the beginning of the line.
! 407: */
! 408: if (ch_seek(pos) == 0)
! 409: {
! 410: while ((c = ch_back_get()) != '\n' && c != EOI)
! 411: ;
! 412: if (c == '\n')
! 413: (void) ch_forw_get();
! 414: pos = ch_tell();
! 415: }
! 416: jump_loc(pos);
! 417: }
! 418:
! 419: /*
! 420: * Jump to a specified position in the file.
! 421: */
! 422: jump_loc(pos)
! 423: off_t pos;
! 424: {
! 425: register int nline;
! 426: off_t tpos;
! 427:
! 428: if ((nline = onscreen(pos)) >= 0) {
! 429: /*
! 430: * The line is currently displayed.
! 431: * Just scroll there.
! 432: */
! 433: forw(nline, position(BOTTOM_PLUS_ONE), 0);
! 434: return;
! 435: }
! 436:
! 437: /*
! 438: * Line is not on screen.
! 439: * Seek to the desired location.
! 440: */
! 441: if (ch_seek(pos)) {
! 442: error("Cannot seek to that position");
! 443: return;
! 444: }
! 445:
! 446: /*
! 447: * See if the desired line is BEFORE the currently displayed screen.
! 448: * If so, then move forward far enough so the line we're on will be
! 449: * at the bottom of the screen, in order to be able to call back()
! 450: * to make the screen scroll backwards & put the line at the top of
! 451: * the screen.
! 452: * {{ This seems inefficient, but it's not so bad,
! 453: * since we can never move forward more than a
! 454: * screenful before we stop to redraw the screen. }}
! 455: */
! 456: tpos = position(TOP);
! 457: if (tpos != NULL_POSITION && pos < tpos) {
! 458: off_t npos = pos;
! 459: /*
! 460: * Note that we can't forw_line() past tpos here,
! 461: * so there should be no EOI at this stage.
! 462: */
! 463: for (nline = 0; npos < tpos && nline < sc_height - 1; nline++)
! 464: npos = forw_line(npos);
! 465:
! 466: if (npos < tpos) {
! 467: /*
! 468: * More than a screenful back.
! 469: */
! 470: lastmark();
! 471: clear();
! 472: pos_clear();
! 473: add_back_pos(npos);
! 474: }
! 475:
! 476: /*
! 477: * Note that back() will repaint() if nline > back_scroll.
! 478: */
! 479: back(nline, npos, 0);
! 480: return;
! 481: }
! 482: /*
! 483: * Remember where we were; clear and paint the screen.
! 484: */
! 485: lastmark();
! 486: prepaint(pos);
! 487: }
! 488:
! 489: /*
! 490: * The table of marks.
! 491: * A mark is simply a position in the file.
! 492: */
! 493: #define NMARKS (27) /* 26 for a-z plus one for quote */
! 494: #define LASTMARK (NMARKS-1) /* For quote */
! 495: static off_t marks[NMARKS];
! 496:
! 497: /*
! 498: * Initialize the mark table to show no marks are set.
! 499: */
! 500: init_mark()
! 501: {
! 502: int i;
! 503:
! 504: for (i = 0; i < NMARKS; i++)
! 505: marks[i] = NULL_POSITION;
! 506: }
! 507:
! 508: /*
! 509: * See if a mark letter is valid (between a and z).
! 510: */
! 511: static int
! 512: badmark(c)
! 513: int c;
! 514: {
! 515: if (c < 'a' || c > 'z')
! 516: {
! 517: error("Choose a letter between 'a' and 'z'");
! 518: return (1);
! 519: }
! 520: return (0);
! 521: }
! 522:
! 523: /*
! 524: * Set a mark.
! 525: */
! 526: setmark(c)
! 527: int c;
! 528: {
! 529: if (badmark(c))
! 530: return;
! 531: marks[c-'a'] = position(TOP);
! 532: }
! 533:
! 534: lastmark()
! 535: {
! 536: marks[LASTMARK] = position(TOP);
! 537: }
! 538:
! 539: /*
! 540: * Go to a previously set mark.
! 541: */
! 542: gomark(c)
! 543: int c;
! 544: {
! 545: off_t pos;
! 546:
! 547: if (c == '\'') {
! 548: pos = marks[LASTMARK];
! 549: if (pos == NULL_POSITION)
! 550: pos = 0;
! 551: }
! 552: else {
! 553: if (badmark(c))
! 554: return;
! 555: pos = marks[c-'a'];
! 556: if (pos == NULL_POSITION) {
! 557: error("mark not set");
! 558: return;
! 559: }
! 560: }
! 561: jump_loc(pos);
! 562: }
! 563:
! 564: /*
! 565: * Get the backwards scroll limit.
! 566: * Must call this function instead of just using the value of
! 567: * back_scroll, because the default case depends on sc_height and
! 568: * top_scroll, as well as back_scroll.
! 569: */
! 570: get_back_scroll()
! 571: {
! 572: if (back_scroll >= 0)
! 573: return (back_scroll);
! 574: if (top_scroll)
! 575: return (sc_height - 2);
! 576: return (sc_height - 1);
! 577: }
! 578:
! 579: /*
! 580: * Search for the n-th occurence of a specified pattern,
! 581: * either forward or backward.
! 582: */
! 583: search(search_forward, pattern, n, wantmatch)
! 584: register int search_forward;
! 585: register char *pattern;
! 586: register int n;
! 587: int wantmatch;
! 588: {
! 589: off_t pos, linepos;
! 590: register char *p;
! 591: register char *q;
! 592: int linenum;
! 593: int linematch;
! 594: #ifdef REGEX
! 595: static regex_t *cpattern = NULL;
! 596: #else
! 597: #ifdef RECOMP
! 598: char *re_comp();
! 599: char *errmsg;
! 600: #else
! 601: #ifdef REGCMP
! 602: char *regcmp();
! 603: static char *cpattern = NULL;
! 604: #else
! 605: static char lpbuf[100];
! 606: static char *last_pattern = NULL;
! 607: char *strcpy();
! 608: #endif
! 609: #endif
! 610: #endif /*REGEX */
! 611: /*
! 612: * For a caseless search, convert any uppercase in the pattern to
! 613: * lowercase.
! 614: */
! 615: if (caseless && pattern != NULL)
! 616: for (p = pattern; *p; p++)
! 617: if (isupper(*p))
! 618: *p = tolower(*p);
! 619: #ifdef REGEX
! 620: if (pattern == NULL || *pattern == '\0')
! 621: {
! 622: /*
! 623: * A null pattern means use the previous pattern.
! 624: * The compiled previous pattern is in cpattern, so just use it.
! 625: */
! 626: if (cpattern == NULL)
! 627: {
! 628: error("No previous regular expression");
! 629: return(0);
! 630: }
! 631: } else
! 632: {
! 633: /*
! 634: * Otherwise compile the given pattern.
! 635: */
! 636: if (cpattern == NULL
! 637: && (cpattern = (regex_t *) malloc(sizeof(regex_t))) == NULL) {
! 638: error("cannot allocate memory");
! 639: quit();
! 640: }
! 641: else
! 642: regfree(cpattern);
! 643: if (regcomp(cpattern, pattern, 0))
! 644: {
! 645: error("Invalid pattern");
! 646: return(0);
! 647: }
! 648: }
! 649: #else
! 650: #ifdef RECOMP
! 651:
! 652: /*
! 653: * (re_comp handles a null pattern internally,
! 654: * so there is no need to check for a null pattern here.)
! 655: */
! 656: if ((errmsg = re_comp(pattern)) != NULL)
! 657: {
! 658: error(errmsg);
! 659: return(0);
! 660: }
! 661: #else
! 662: #ifdef REGCMP
! 663: if (pattern == NULL || *pattern == '\0')
! 664: {
! 665: /*
! 666: * A null pattern means use the previous pattern.
! 667: * The compiled previous pattern is in cpattern, so just use it.
! 668: */
! 669: if (cpattern == NULL)
! 670: {
! 671: error("No previous regular expression");
! 672: return(0);
! 673: }
! 674: } else
! 675: {
! 676: /*
! 677: * Otherwise compile the given pattern.
! 678: */
! 679: char *s;
! 680: if ((s = regcmp(pattern, 0)) == NULL)
! 681: {
! 682: error("Invalid pattern");
! 683: return(0);
! 684: }
! 685: if (cpattern != NULL)
! 686: free(cpattern);
! 687: cpattern = s;
! 688: }
! 689: #else
! 690: if (pattern == NULL || *pattern == '\0')
! 691: {
! 692: /*
! 693: * Null pattern means use the previous pattern.
! 694: */
! 695: if (last_pattern == NULL)
! 696: {
! 697: error("No previous regular expression");
! 698: return(0);
! 699: }
! 700: pattern = last_pattern;
! 701: } else
! 702: {
! 703: (void)strcpy(lpbuf, pattern);
! 704: last_pattern = lpbuf;
! 705: }
! 706: #endif
! 707: #endif
! 708: #endif /* REGEX */
! 709:
! 710: /*
! 711: * Figure out where to start the search.
! 712: */
! 713:
! 714: if (position(TOP) == NULL_POSITION) {
! 715: /*
! 716: * Nothing is currently displayed. Start at the beginning
! 717: * of the file. (This case is mainly for searches from the
! 718: * command line.
! 719: */
! 720: pos = (off_t)0;
! 721: } else if (!search_forward) {
! 722: /*
! 723: * Backward search: start just before the top line
! 724: * displayed on the screen.
! 725: */
! 726: pos = position(TOP);
! 727: } else {
! 728: /*
! 729: * Start at the second screen line displayed on the screen.
! 730: */
! 731: pos = position(TOP_PLUS_ONE);
! 732: }
! 733:
! 734: if (pos == NULL_POSITION)
! 735: {
! 736: /*
! 737: * Can't find anyplace to start searching from.
! 738: */
! 739: error("Nothing to search");
! 740: return(0);
! 741: }
! 742:
! 743: linenum = find_linenum(pos);
! 744: for (;;)
! 745: {
! 746: /*
! 747: * Get lines until we find a matching one or
! 748: * until we hit end-of-file (or beginning-of-file
! 749: * if we're going backwards).
! 750: */
! 751: if (sigs)
! 752: /*
! 753: * A signal aborts the search.
! 754: */
! 755: return(0);
! 756:
! 757: if (search_forward)
! 758: {
! 759: /*
! 760: * Read the next line, and save the
! 761: * starting position of that line in linepos.
! 762: */
! 763: linepos = pos;
! 764: pos = forw_raw_line(pos);
! 765: if (linenum != 0)
! 766: linenum++;
! 767: } else
! 768: {
! 769: /*
! 770: * Read the previous line and save the
! 771: * starting position of that line in linepos.
! 772: */
! 773: pos = back_raw_line(pos);
! 774: linepos = pos;
! 775: if (linenum != 0)
! 776: linenum--;
! 777: }
! 778:
! 779: if (pos == NULL_POSITION)
! 780: {
! 781: /*
! 782: * We hit EOF/BOF without a match.
! 783: */
! 784: error("Pattern not found");
! 785: return(0);
! 786: }
! 787:
! 788: /*
! 789: * If we're using line numbers, we might as well
! 790: * remember the information we have now (the position
! 791: * and line number of the current line).
! 792: */
! 793: if (linenums)
! 794: add_lnum(linenum, pos);
! 795:
! 796: /*
! 797: * If this is a caseless search, convert uppercase in the
! 798: * input line to lowercase.
! 799: */
! 800: if (caseless)
! 801: for (p = q = line; *p; p++, q++)
! 802: *q = isupper(*p) ? tolower(*p) : *p;
! 803:
! 804: /*
! 805: * Remove any backspaces along with the preceeding char.
! 806: * This allows us to match text which is underlined or
! 807: * overstruck.
! 808: */
! 809: for (p = q = line; *p; p++, q++)
! 810: if (q > line && *p == '\b')
! 811: /* Delete BS and preceeding char. */
! 812: q -= 2;
! 813: else
! 814: /* Otherwise, just copy. */
! 815: *q = *p;
! 816:
! 817: /*
! 818: * Test the next line to see if we have a match.
! 819: * This is done in a variety of ways, depending
! 820: * on what pattern matching functions are available.
! 821: */
! 822: #ifdef REGEX
! 823: linematch = !regexec(cpattern, line, 0, NULL, 0);
! 824: #else
! 825: #ifdef REGCMP
! 826: linematch = (regex(cpattern, line) != NULL);
! 827: #else
! 828: #ifdef RECOMP
! 829: linematch = (re_exec(line) == 1);
! 830: #else
! 831: linematch = match(pattern, line);
! 832: #endif
! 833: #endif
! 834: #endif /* REGEX */
! 835: /*
! 836: * We are successful if wantmatch and linematch are
! 837: * both true (want a match and got it),
! 838: * or both false (want a non-match and got it).
! 839: */
! 840: if (((wantmatch && linematch) || (!wantmatch && !linematch)) &&
! 841: --n <= 0)
! 842: /*
! 843: * Found the line.
! 844: */
! 845: break;
! 846: }
! 847: jump_loc(linepos);
! 848: return(1);
! 849: }
! 850:
! 851: #if !defined(REGCMP) && !defined(RECOMP) && !defined(REGEX)
! 852: /*
! 853: * We have neither regcmp() nor re_comp().
! 854: * We use this function to do simple pattern matching.
! 855: * It supports no metacharacters like *, etc.
! 856: */
! 857: static
! 858: match(pattern, buf)
! 859: char *pattern, *buf;
! 860: {
! 861: register char *pp, *lp;
! 862:
! 863: for ( ; *buf != '\0'; buf++)
! 864: {
! 865: for (pp = pattern, lp = buf; *pp == *lp; pp++, lp++)
! 866: if (*pp == '\0' || *lp == '\0')
! 867: break;
! 868: if (*pp == '\0')
! 869: return (1);
! 870: }
! 871: return (0);
! 872: }
! 873: #endif