home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / more / prim.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-03  |  16.8 KB  |  829 lines

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