[BACK]Return to re_search.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / mg

Diff for /src/usr.bin/mg/re_search.c between version 1.4 and 1.5

version 1.4, 2000/02/29 16:00:23 version 1.5, 2000/04/13 06:12:16
Line 1 
Line 1 
 /*  /*
  *              regular expression search commands for   *              regular expression search commands for Mg
  *                         MicroGnuEmacs  
  *   *
  * This file contains functions to implement several of gnuemacs'   * This file contains functions to implement several of gnuemacs'
  * regular expression functions for MicroGnuEmacs.  Several of   * regular expression functions for Mg.  Several of the routines
  * the routines below are just minor rearrangements of the MicroGnuEmacs   * below are just minor rearrangements of the Mg non-regular
  * non-regular expression search functions.  Hence some of them date back   * expression search functions.  Hence some of them date back in
  * in essential structure to the original MicroEMACS; others are modifications   * essential structure to the original MicroEMACS; others are modifications
  * of Rich Ellison's code.  I, Peter Newton, wrote about half from scratch.   * of Rich Ellison's code.  I, Peter Newton, wrote about half from scratch.
  */   */
   
Line 18 
Line 17 
 #include        "def.h"  #include        "def.h"
 #include        "macro.h"  #include        "macro.h"
   
 #define SRCH_BEGIN      (0)                     /* Search sub-codes.    */  #define SRCH_BEGIN      (0)     /* Search sub-codes.     */
 #define SRCH_FORW       (-1)  #define SRCH_FORW       (-1)
 #define SRCH_BACK       (-2)  #define SRCH_BACK       (-2)
 #define SRCH_NOPR       (-3)  #define SRCH_NOPR       (-3)
 #define SRCH_ACCM       (-4)  #define SRCH_ACCM       (-4)
 #define SRCH_MARK       (-5)  #define SRCH_MARK       (-5)
   
 #define RE_NMATCH       10              /* max number of matches */  #define RE_NMATCH       10      /* max number of matches */
   
 char    re_pat[NPAT];                   /* Regex pattern                */  char            re_pat[NPAT];   /* Regex pattern                 */
 int     re_srch_lastdir = SRCH_NOPR;     /* Last search flags. */  int             re_srch_lastdir = SRCH_NOPR;    /* Last search flags. */
 int     casefoldsearch = TRUE;           /* Does search ignore case ? */  int             casefoldsearch = TRUE;  /* Does search ignore case ? */
   
 /* Indexed by a character, gives the upper case equivalent of the character */  /* Indexed by a character, gives the upper case equivalent of the character */
   
 static char upcase[0400] =  static char     upcase[0400] =
   { 000, 001, 002, 003, 004, 005, 006, 007,  {000, 001, 002, 003, 004, 005, 006, 007,
     010, 011, 012, 013, 014, 015, 016, 017,          010, 011, 012, 013, 014, 015, 016, 017,
     020, 021, 022, 023, 024, 025, 026, 027,          020, 021, 022, 023, 024, 025, 026, 027,
     030, 031, 032, 033, 034, 035, 036, 037,          030, 031, 032, 033, 034, 035, 036, 037,
     040, 041, 042, 043, 044, 045, 046, 047,          040, 041, 042, 043, 044, 045, 046, 047,
     050, 051, 052, 053, 054, 055, 056, 057,          050, 051, 052, 053, 054, 055, 056, 057,
     060, 061, 062, 063, 064, 065, 066, 067,          060, 061, 062, 063, 064, 065, 066, 067,
     070, 071, 072, 073, 074, 075, 076, 077,          070, 071, 072, 073, 074, 075, 076, 077,
     0100, 0101, 0102, 0103, 0104, 0105, 0106, 0107,          0100, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
     0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117,          0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117,
     0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127,          0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
     0130, 0131, 0132, 0133, 0134, 0135, 0136, 0137,          0130, 0131, 0132, 0133, 0134, 0135, 0136, 0137,
     0140, 0101, 0102, 0103, 0104, 0105, 0106, 0107,          0140, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
     0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117,          0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117,
     0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127,          0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
     0130, 0131, 0132, 0173, 0174, 0175, 0176, 0177,          0130, 0131, 0132, 0173, 0174, 0175, 0176, 0177,
     0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207,          0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
     0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217,          0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217,
     0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227,          0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227,
     0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237,          0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237,
     0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247,          0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247,
     0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257,          0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
     0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,          0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
     0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,          0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
     0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307,          0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
     0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317,          0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317,
     0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327,          0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327,
     0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337,          0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337,
     0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347,          0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347,
     0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357,          0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357,
     0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,          0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
     0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377          0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377
   };  };
   
 /*  /*
  * Search forward.   * Search forward.
Line 75 
Line 74 
  * matched characters, and display does all the hard stuff.   * matched characters, and display does all the hard stuff.
  * If not found, it just prints a message.   * If not found, it just prints a message.
  */   */
 /*ARGSUSED*/  /* ARGSUSED */
 re_forwsearch(f, n) {  re_forwsearch(f, n)
         register int    s;  {
           register int    s;
   
         if ((s=re_readpattern("RE Search")) != TRUE)          if ((s = re_readpattern("RE Search")) != TRUE)
                 return (s);                  return (s);
         if (re_forwsrch() == FALSE) {          if (re_forwsrch() == FALSE) {
                 ewprintf("Search failed: \"%s\"", re_pat);                  ewprintf("Search failed: \"%s\"", re_pat);
Line 96 
Line 96 
  * pointing at the first character of the pattern [the last character that   * pointing at the first character of the pattern [the last character that
  * was matched].   * was matched].
  */   */
 /*ARGSUSED*/  /* ARGSUSED */
 re_backsearch(f, n) {  re_backsearch(f, n)
         register int    s;  {
           register int    s;
   
         if ((s=re_readpattern("RE Search backward")) != TRUE)          if ((s = re_readpattern("RE Search backward")) != TRUE)
                 return (s);                  return (s);
         if (re_backsrch() == FALSE) {          if (re_backsrch() == FALSE) {
                 ewprintf("Search failed: \"%s\"", re_pat);                  ewprintf("Search failed: \"%s\"", re_pat);
Line 118 
Line 119 
  * has been saved in "srch_lastdir", so you know which way   * has been saved in "srch_lastdir", so you know which way
  * to go.   * to go.
  */   */
 /*ARGSUSED*/  /* ARGSUSED */
 /*  This code has problems-- some incompatibility(?) with  /*
     extend.c causes match to fail when it should not.   * This code has problems-- some incompatibility(?) with extend.c causes
    * match to fail when it should not.
  */   */
 re_searchagain(f, n) {  re_searchagain(f, n)
   {
   
   if (re_srch_lastdir == SRCH_NOPR) {          if (re_srch_lastdir == SRCH_NOPR) {
     ewprintf("No last search");                  ewprintf("No last search");
     return (FALSE);                  return (FALSE);
   }          }
           if (re_srch_lastdir == SRCH_FORW) {
   if (re_srch_lastdir == SRCH_FORW) {                  if (re_forwsrch() == FALSE) {
     if (re_forwsrch() == FALSE) {                          ewprintf("Search failed: \"%s\"", re_pat);
       ewprintf("Search failed: \"%s\"", re_pat);                          return (FALSE);
       return (FALSE);                  }
     }                  return (TRUE);
     return (TRUE);          }
   }          if (re_srch_lastdir == SRCH_BACK) {
   if (re_srch_lastdir == SRCH_BACK) {                  if (re_backsrch() == FALSE) {
     if (re_backsrch() == FALSE) {                          ewprintf("Search failed: \"%s\"", re_pat);
       ewprintf("Search failed: \"%s\"", re_pat);                          return (FALSE);
       return (FALSE);                  }
     }                  return (TRUE);
     return (TRUE);          }
   }  
 }  }
   
   
 /* Compiled regex goes here-- changed only when new pattern read */  /* Compiled regex goes here-- changed only when new pattern read */
 static regex_t re_buff;  static regex_t  re_buff;
 static regmatch_t re_match[RE_NMATCH];  static regmatch_t re_match[RE_NMATCH];
   
 /*  /*
  * Re-Query Replace.   * Re-Query Replace.
  *      Replace strings selectively.  Does a search and replace operation.   *      Replace strings selectively.  Does a search and replace operation.
  */   */
 /*ARGSUSED*/  /* ARGSUSED */
 re_queryrepl(f, n) {  re_queryrepl(f, n)
         register int    s;  {
         register int    rcnt = 0;       /* Replacements made so far     */          register int    s;
         register int    plen;           /* length of found string       */          register int    rcnt = 0;       /* Replacements made so far      */
         char            news[NPAT];     /* replacement string           */          register int    plen;   /* length of found string        */
           char            news[NPAT];     /* replacement string            */
   
         /* Casefold check */          /* Casefold check */
         if (!casefoldsearch) f = TRUE;          if (!casefoldsearch)
                   f = TRUE;
   
         if ((s=re_readpattern("RE Query replace")) != TRUE)          if ((s = re_readpattern("RE Query replace")) != TRUE)
                 return (s);                  return (s);
         if ((s=ereply("Query replace %s with: ",news, NPAT, re_pat)) == ABORT)          if ((s = ereply("Query replace %s with: ", news, NPAT, re_pat)) == ABORT)
                 return (s);                  return (s);
         if (s == FALSE)          if (s == FALSE)
                 news[0] = '\0';                  news[0] = '\0';
Line 179 
Line 183 
          */           */
   
         while (re_forwsrch() == TRUE) {          while (re_forwsrch() == TRUE) {
         retry:  retry:
                 update();                  update();
                 switch (getkey(FALSE)) {                  switch (getkey(FALSE)) {
                 case ' ':                  case ' ':
Line 196 
Line 200 
                         rcnt++;                          rcnt++;
                         goto stopsearch;                          goto stopsearch;
   
                 case CCHR('G'): /* ^G */                  case CCHR('G'):/* ^G */
                         (VOID) ctrlg(FFRAND, 0);                          (VOID) ctrlg(FFRAND, 0);
                 case CCHR('['): /* ESC */                  case CCHR('['):/* ESC */
                 case '`':                  case '`':
                         goto stopsearch;                          goto stopsearch;
   
Line 211 
Line 215 
                         } while (re_forwsrch() == TRUE);                          } while (re_forwsrch() == TRUE);
                         goto stopsearch;                          goto stopsearch;
   
                 case CCHR('?'):         /* To not replace */                  case CCHR('?'):/* To not replace */
                         break;                          break;
   
                 default:                  default:
 ewprintf("<SP> replace, [.] rep-end, <DEL> don't, [!] repl rest <ESC> quit");                          ewprintf("<SP> replace, [.] rep-end, <DEL> don't, [!] repl rest <ESC> quit");
                         goto retry;                          goto retry;
                 }                  }
         }          }
Line 235 
Line 239 
   
   
   
 /* Routine re_doreplace calls lreplace to make replacements needed by  /*
  * re_query replace.  Its reason for existence is to deal with \1,   * Routine re_doreplace calls lreplace to make replacements needed by
  * \2. etc.   * re_query replace.  Its reason for existence is to deal with \1, \2. etc.
  */   */
   
 /* Maximum length of replacement string */  /* Maximum length of replacement string */
 #define REPLEN 256  #define REPLEN 256
   
 re_doreplace(plen, st, f)  re_doreplace(plen, st, f)
      register RSIZE  plen;                   /* length to remove             */          register RSIZE  plen;   /* length to remove          */
      char            *st;                    /* replacement string           */          char           *st;     /* replacement string        */
      int             f;                      /* case hack disable            */          int             f;      /* case hack disable         */
 {  {
   int s;          int             s;
   int num, k;          int             num, k;
   register int j;          register int    j;
   int more, state;          int             more, state;
   LINE *clp;          LINE           *clp;
   char repstr[REPLEN];          char            repstr[REPLEN];
   
   clp = curwp->w_dotp;          clp = curwp->w_dotp;
   more = TRUE;          more = TRUE;
   j = 0;          j = 0;
   state = 0;          state = 0;
   
   /* The following FSA parses the replacement string */          /* The following FSA parses the replacement string */
   while (more) {          while (more) {
     switch (state) {                  switch (state) {
   
     case 0: if (*st == '\\') {                  case 0:
               st++;                          if (*st == '\\') {
               state = 1;                                  st++;
             }                                  state = 1;
             else if (*st == '\0')                          } else if (*st == '\0')
               more = FALSE;                                  more = FALSE;
             else {                          else {
               repstr[j] = *st;                                  repstr[j] = *st;
               j++; if (j >= REPLEN) return(FALSE);                                  j++;
               st++;                                  if (j >= REPLEN)
             }                                          return (FALSE);
             break;                                  st++;
     case 1: if (*st >= '0' && *st <= '9') {                          }
               num = *st - '0';                          break;
               st++;                  case 1:
               state = 2;                          if (*st >= '0' && *st <= '9') {
             }                                  num = *st - '0';
             else if (*st == '\0')                                  st++;
               more = FALSE;                                  state = 2;
             else {                          } else if (*st == '\0')
               repstr[j] = *st;                                  more = FALSE;
               j++; if (j >= REPLEN) return(FALSE);                          else {
               st++;                                  repstr[j] = *st;
               state = 0;                                  j++;
             }                                  if (j >= REPLEN)
             break;                                          return (FALSE);
     case 2: if (*st >= '0' && *st <= '9') {                                  st++;
               num = 10*num + *st - '0';                                  state = 0;
               st++;                          }
             }                          break;
             else {                  case 2:
               if (num >= RE_NMATCH) return(FALSE);                          if (*st >= '0' && *st <= '9') {
               k = re_match[num].rm_eo - re_match[num].rm_so;                                  num = 10 * num + *st - '0';
               if (j+k >= REPLEN) return(FALSE);                                  st++;
               bcopy(&(clp->l_text[re_match[num].rm_so]), &repstr[j], k);                          } else {
               j += k;                                  if (num >= RE_NMATCH)
               if (*st == '\0')                                          return (FALSE);
                 more = FALSE;                                  k = re_match[num].rm_eo - re_match[num].rm_so;
               if (*st == '\\') {                                  if (j + k >= REPLEN)
                 st++;                                          return (FALSE);
                 state = 1;                                  bcopy(&(clp->l_text[re_match[num].rm_so]), &repstr[j], k);
               }                                  j += k;
               else {                                  if (*st == '\0')
                 repstr[j] = *st;                                          more = FALSE;
                 j++; if (j >= REPLEN) return(FALSE);                                  if (*st == '\\') {
                 st++;                                          st++;
                 state = 0;                                          state = 1;
               }                                  } else {
             }                                          repstr[j] = *st;
             break;                                          j++;
           } /* end case */                                          if (j >= REPLEN)
   } /* end while */                                                  return (FALSE);
                                           st++;
                                           state = 0;
                                   }
                           }
                           break;
                   }               /* end case */
           }                       /* end while */
   
   repstr[j] = '\0';          repstr[j] = '\0';
   
   s = lreplace(plen, repstr, f);          s = lreplace(plen, repstr, f);
   
   return(s);          return (s);
 }  }
   
   
Line 333 
Line 344 
  * is notified of the change, and TRUE is returned. If the   * is notified of the change, and TRUE is returned. If the
  * string isn't found, FALSE is returned.   * string isn't found, FALSE is returned.
  */   */
 re_forwsrch() {  re_forwsrch()
   {
   
   register LINE *clp;          register LINE  *clp;
   register int tbo;          register int    tbo;
   int error, plen;          int             error, plen;
   
   clp = curwp->w_dotp;          clp = curwp->w_dotp;
   tbo = curwp->w_doto;          tbo = curwp->w_doto;
   
   if (tbo == clp->l_used)          if (tbo == clp->l_used)
     /* Don't start matching off end of line-- must                  /*
      * move to beginning of next line, unless at end                   * Don't start matching off end of line-- must move to
      */                   * beginning of next line, unless at end
     if (clp != curbp->b_linep) {                   */
       clp = lforw(clp);                  if (clp != curbp->b_linep) {
       tbo = 0;                          clp = lforw(clp);
     }                          tbo = 0;
                   }
           /*
            * Note this loop does not process the last line, but this editor
            * always makes the last line empty so this is good.
            */
   
           while (clp != (curbp->b_linep)) {
   
   /* Note this loop does not process the last line, but this editor                  re_match[0].rm_so = tbo;
      always makes the last line empty so this is good.                  re_match[0].rm_eo = llength(clp);
    */                  error = regexec(&re_buff, ltext(clp), RE_NMATCH, re_match, REG_STARTEND);
   
   while (clp != (curbp->b_linep)) {                  if (error) {
                           clp = lforw(clp);
                           tbo = 0;
                   } else {
                           curwp->w_doto = re_match[0].rm_eo;
                           curwp->w_dotp = clp;
                           curwp->w_flag |= WFMOVE;
                           return (TRUE);
                   }
   
      re_match[0].rm_so = tbo;          }
      re_match[0].rm_eo = llength(clp);  
      error = regexec(&re_buff, ltext(clp), RE_NMATCH, re_match, REG_STARTEND);  
   
      if (error) {          return (FALSE);
        clp = lforw(clp);  
        tbo = 0;  
      } else {  
        curwp->w_doto = re_match[0].rm_eo;  
        curwp->w_dotp = clp;  
        curwp->w_flag |= WFMOVE;  
        return (TRUE);  
      }  
   
    }  
   
   return(FALSE);  
   
 }  }
   
   
Line 386 
Line 398 
  * is notified of the change, and TRUE is returned. If the   * is notified of the change, and TRUE is returned. If the
  * string isn't found, FALSE is returned.   * string isn't found, FALSE is returned.
  */   */
 re_backsrch() {  re_backsrch()
   {
   
   register LINE *clp;          register LINE  *clp;
   register int tbo;          register int    tbo;
   regmatch_t lastmatch;          regmatch_t      lastmatch;
   char m[1];          char            m[1];
   
   clp = curwp->w_dotp;          clp = curwp->w_dotp;
   tbo = curwp->w_doto;          tbo = curwp->w_doto;
   
   /* Start search one position to the left of dot */          /* Start search one position to the left of dot */
   tbo = tbo - 1;          tbo = tbo - 1;
   if (tbo < 0) {          if (tbo < 0) {
     /* must move up one line */                  /* must move up one line */
     clp = lback(clp);                  clp = lback(clp);
     tbo = llength(clp);                  tbo = llength(clp);
   }          }
           /*
            * Note this loop does not process the last line, but this editor
            * always makes the last line empty so this is good.
            */
   
   /* Note this loop does not process the last line, but this editor          while (clp != (curbp->b_linep)) {
      always makes the last line empty so this is good.  
    */  
   
   while (clp != (curbp->b_linep)) {                  re_match[0].rm_so = 0;
                   re_match[0].rm_eo = llength(clp);
                   lastmatch.rm_so = -1;
                   /*
                    * Keep searching until we don't match any longer.  Assumes a
                    * non-match does not modify the re_match array.  We have to
                    * do this character-by-character after the first match since
                    * POSIX regexps don't give you a way to do reverse matches.
                    */
                   while (!regexec(&re_buff, ltext(clp), RE_NMATCH, re_match,
                       REG_STARTEND) && re_match[0].rm_so < tbo) {
                           memcpy(&lastmatch, &re_match[0], sizeof(regmatch_t));
                           re_match[0].rm_so++;
                           re_match[0].rm_eo = llength(clp);
                   }
   
      re_match[0].rm_so = 0;                  if (lastmatch.rm_so == -1) {
      re_match[0].rm_eo = llength(clp);                          clp = lback(clp);
      lastmatch.rm_so = -1;                          tbo = llength(clp);
      /* Keep searching until we don't match any longer.  Assumes a non-match                  } else {
         does not modify the re_match array.  We have to do this                          memcpy(&re_match[0], &lastmatch, sizeof(regmatch_t));
         character-by-character after the first match since POSIX regexps don't                          curwp->w_doto = re_match[0].rm_so;
         give you a way to do reverse matches.                          curwp->w_dotp = clp;
      */                          curwp->w_flag |= WFMOVE;
      while (!regexec(&re_buff, ltext(clp), RE_NMATCH, re_match, REG_STARTEND) &&                          return (TRUE);
             re_match[0].rm_so < tbo) {                  }
        memcpy(&lastmatch, &re_match[0], sizeof(regmatch_t));  
        re_match[0].rm_so++;  
        re_match[0].rm_eo = llength(clp);  
      }  
   
      if (lastmatch.rm_so == -1) {          }
        clp = lback(clp);  
        tbo = llength(clp);  
      } else {  
        memcpy(&re_match[0], &lastmatch, sizeof(regmatch_t));  
        curwp->w_doto = re_match[0].rm_so;  
        curwp->w_dotp = clp;  
        curwp->w_flag |= WFMOVE;  
        return (TRUE);  
      }  
   
    }          return (FALSE);
   
   return(FALSE);  
   
 }  }
   
   
Line 451 
Line 465 
  * Display the old pattern, in the style of Jeff Lomicka. There is   * Display the old pattern, in the style of Jeff Lomicka. There is
  * some do-it-yourself control expansion.   * some do-it-yourself control expansion.
  */   */
 re_readpattern(prompt) char *prompt; {  re_readpattern(prompt)
         int s;          char           *prompt;
         int flags;  {
         int error;          int             s;
         char tpat[NPAT];          int             flags;
         static int dofree = 0;          int             error;
           char            tpat[NPAT];
           static int      dofree = 0;
   
         if (re_pat[0] == '\0') s = ereply("%s: ", tpat, NPAT, prompt);          if (re_pat[0] == '\0')
         else s = ereply("%s: (default %s) ", tpat, NPAT, prompt, re_pat);                  s = ereply("%s: ", tpat, NPAT, prompt);
           else
                   s = ereply("%s: (default %s) ", tpat, NPAT, prompt, re_pat);
   
         if (s == TRUE) {          if (s == TRUE) {
           /* New pattern given */                  /* New pattern given */
           (VOID) strcpy(re_pat, tpat);                  (VOID) strcpy(re_pat, tpat);
           if (casefoldsearch)                  if (casefoldsearch)
             flags = REG_EXTENDED|REG_ICASE;                          flags = REG_EXTENDED | REG_ICASE;
           else                  else
             flags = REG_EXTENDED;                          flags = REG_EXTENDED;
           if (dofree)                  if (dofree)
               regfree(&re_buff);                          regfree(&re_buff);
           error = regcomp(&re_buff, re_pat, flags);                  error = regcomp(&re_buff, re_pat, flags);
           if (error) {                  if (error) {
             char message[256];                          char            message[256];
             regerror(error, &re_buff, message, sizeof(message));                          regerror(error, &re_buff, message, sizeof(message));
             ewprintf("Regex Error: %s", message);                          ewprintf("Regex Error: %s", message);
             re_pat[0] = '\0';                          re_pat[0] = '\0';
             return(FALSE);                          return (FALSE);
           }                  }
           dofree = 1;                  dofree = 1;
         }          } else if (s == FALSE && re_pat[0] != '\0')
         else if (s==FALSE && re_pat[0]!='\0')                  /* Just using old pattern */
           /* Just using old pattern */                  s = TRUE;
           s = TRUE;  
         return (s);          return (s);
 }  }
   
   
   
 /* Cause case to not matter in searches.  This is the default.  If  /*
  * called with argument cause case to matter.   * Cause case to not matter in searches.  This is the default.  If called
    * with argument cause case to matter.
  */   */
 setcasefold(f, n) {  setcasefold(f, n)
   {
   
   if (f & FFARG) {          if (f & FFARG) {
     casefoldsearch = FALSE;                  casefoldsearch = FALSE;
     ewprintf("Case-fold-search unset");                  ewprintf("Case-fold-search unset");
   }          } else {
   else {                  casefoldsearch = TRUE;
     casefoldsearch = TRUE;                  ewprintf("Case-fold-search set");
     ewprintf("Case-fold-search set");          }
   }  
   
   /* Invalidate the regular expression pattern since I'm too lazy          /*
    * to recompile it.           * Invalidate the regular expression pattern since I'm too lazy to
    */           * recompile it.
            */
   
   re_pat[0] = '\0';          re_pat[0] = '\0';
   
   return(TRUE);          return (TRUE);
   
 } /* end setcasefold */  }                               /* end setcasefold */
   
   
 /* Delete all lines after dot that contain a string matching regex  /*
    * Delete all lines after dot that contain a string matching regex
  */   */
 delmatchlines(f, n) {  delmatchlines(f, n)
   int s;  {
           int             s;
   
   if ((s=re_readpattern("Flush lines (containing match for regexp)")) != TRUE)          if ((s = re_readpattern("Flush lines (containing match for regexp)")) != TRUE)
     return (s);                  return (s);
   
   s = killmatches(TRUE);          s = killmatches(TRUE);
   
   return(s);          return (s);
 }  }
   
   
   
 /* Delete all lines after dot that don't contain a string matching regex  /*
    * Delete all lines after dot that don't contain a string matching regex
  */   */
 delnonmatchlines(f, n) {  delnonmatchlines(f, n)
   int s;  {
           int             s;
   
   
   if ((s=re_readpattern("Keep lines (containing match for regexp)")) != TRUE)          if ((s = re_readpattern("Keep lines (containing match for regexp)")) != TRUE)
     return (s);                  return (s);
   
   s = killmatches(FALSE);          s = killmatches(FALSE);
   
   return(s);          return (s);
 }  }
   
   
   
 /* This function does the work of deleting matching lines */  /* This function does the work of deleting matching lines */
 killmatches(cond)  killmatches(cond)
    int cond;          int             cond;
 {  {
   int s, error;          int             s, error;
   int count = 0;          int             count = 0;
   LINE  *clp;          LINE           *clp;
   
   clp = curwp->w_dotp;          clp = curwp->w_dotp;
   if (curwp->w_doto == llength(clp))          if (curwp->w_doto == llength(clp))
     /* Consider dot on next line */                  /* Consider dot on next line */
     clp = lforw(clp);                  clp = lforw(clp);
   
   while (clp != (curbp->b_linep)) {          while (clp != (curbp->b_linep)) {
   
      /* see if line matches */                  /* see if line matches */
      re_match[0].rm_so = 0;                  re_match[0].rm_so = 0;
      re_match[0].rm_eo = llength(clp);                  re_match[0].rm_eo = llength(clp);
      error = regexec(&re_buff, ltext(clp), RE_NMATCH, re_match, REG_STARTEND);                  error = regexec(&re_buff, ltext(clp), RE_NMATCH, re_match, REG_STARTEND);
   
      /* Delete line when appropriate */                  /* Delete line when appropriate */
      if ((cond == FALSE && error) || (cond == TRUE && !error)) {                  if ((cond == FALSE && error) || (cond == TRUE && !error)) {
        curwp->w_doto = 0;                          curwp->w_doto = 0;
        curwp->w_dotp = clp;                          curwp->w_dotp = clp;
        count++;                          count++;
        s = ldelete(llength(clp)+1, KNONE);                          s = ldelete(llength(clp) + 1, KNONE);
        clp = curwp->w_dotp;                          clp = curwp->w_dotp;
        curwp->w_flag |= WFMOVE;                          curwp->w_flag |= WFMOVE;
        if (s == FALSE) return(FALSE);                          if (s == FALSE)
      }                                  return (FALSE);
      else                  } else
        clp = lforw(clp);                          clp = lforw(clp);
    }          }
   
   ewprintf("%d line(s) deleted", count);          ewprintf("%d line(s) deleted", count);
   if (count > 0) curwp->w_flag |= WFMOVE;          if (count > 0)
                   curwp->w_flag |= WFMOVE;
   
   return(TRUE);          return (TRUE);
 }  }
   
   
 petersfunc(f, n) {  petersfunc(f, n)
   {
   
   int s;          int             s;
   LINE  *clp;          LINE           *clp;
   char c;          char            c;
   
   curwp->w_doto = 0;          curwp->w_doto = 0;
   s = ldelete(llength(curwp->w_dotp)+1, KNONE);          s = ldelete(llength(curwp->w_dotp) + 1, KNONE);
   curwp->w_flag |= WFMOVE;          curwp->w_flag |= WFMOVE;
   return(s);          return (s);
   
 }  }
   
   
 /* Count lines matching regex  /*
    * Count lines matching regex
  */   */
 cntmatchlines(f, n) {  cntmatchlines(f, n)
   int s;  {
           int             s;
   
   if ((s=re_readpattern("Count lines (matching regexp)")) != TRUE)          if ((s = re_readpattern("Count lines (matching regexp)")) != TRUE)
     return (s);                  return (s);
   
   s = countmatches(TRUE);          s = countmatches(TRUE);
   
   return(s);          return (s);
 }  }
   
   
   
 /* Count lines that fail to match regex  /*
    * Count lines that fail to match regex
  */   */
 cntnonmatchlines(f, n) {  cntnonmatchlines(f, n)
   int s;  {
           int             s;
   
   
   if ((s=re_readpattern("Count lines (not matching regexp)")) != TRUE)          if ((s = re_readpattern("Count lines (not matching regexp)")) != TRUE)
     return (s);                  return (s);
   
   s = countmatches(FALSE);          s = countmatches(FALSE);
   
   return(s);          return (s);
 }  }
   
   
   
 /* This function does the work of counting matching lines */  /* This function does the work of counting matching lines */
 countmatches(cond)  countmatches(cond)
    int cond;          int             cond;
 {  {
   int s, error;          int             s, error;
   int count = 0;          int             count = 0;
   LINE  *clp;          LINE           *clp;
   
   clp = curwp->w_dotp;          clp = curwp->w_dotp;
   if (curwp->w_doto == llength(clp))          if (curwp->w_doto == llength(clp))
     /* Consider dot on next line */                  /* Consider dot on next line */
     clp = lforw(clp);                  clp = lforw(clp);
   
   while (clp != (curbp->b_linep)) {          while (clp != (curbp->b_linep)) {
   
      /* see if line matches */                  /* see if line matches */
      re_match[0].rm_so = 0;                  re_match[0].rm_so = 0;
      re_match[0].rm_eo = llength(clp);                  re_match[0].rm_eo = llength(clp);
      error = regexec(&re_buff, ltext(clp), RE_NMATCH, re_match, REG_STARTEND);                  error = regexec(&re_buff, ltext(clp), RE_NMATCH, re_match, REG_STARTEND);
   
      /*  Count line when appropriate */                  /* Count line when appropriate */
      if ((cond == FALSE && error) || (cond == TRUE && !error)) count++;                  if ((cond == FALSE && error) || (cond == TRUE && !error))
      clp = lforw(clp);                          count++;
    }                  clp = lforw(clp);
           }
   
   if (cond)          if (cond)
      ewprintf("Number of lines matching: %d", count);                  ewprintf("Number of lines matching: %d", count);
   else          else
      ewprintf("Number of lines not matching: %d", count);                  ewprintf("Number of lines not matching: %d", count);
   
   return(TRUE);          return (TRUE);
 }  }
 #endif  #endif

Legend:
Removed from v.1.4  
changed lines
  Added in v.1.5