home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume16 / less5 / part03 / prim.c < prev   
Encoding:
C/C++ Source or Header  |  1988-09-22  |  16.3 KB  |  895 lines

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