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

Diff for /src/usr.bin/less/search.c between version 1.9 and 1.10

version 1.9, 2014/05/28 11:39:15 version 1.10, 2015/11/05 22:08:44
Line 6 
Line 6 
  *   *
  * For more information, see the README file.   * For more information, see the README file.
  */   */
   /*
    * Modified for use with illumos.
    * Copyright 2014 Garrett D'Amore <garrett@damore.org>
    */
   
   
 /*  /*
  * Routines to search a file for a pattern.   * Routines to search a file for a pattern.
  */   */
Line 17 
Line 20 
 #include "position.h"  #include "position.h"
 #include "charset.h"  #include "charset.h"
   
 #define MINPOS(a,b)     (((a) < (b)) ? (a) : (b))  #define MINPOS(a, b)    (((a) < (b)) ? (a) : (b))
 #define MAXPOS(a,b)     (((a) > (b)) ? (a) : (b))  #define MAXPOS(a, b)    (((a) > (b)) ? (a) : (b))
   
 extern volatile sig_atomic_t sigs;  extern volatile sig_atomic_t sigs;
 extern int how_search;  extern int how_search;
Line 29 
Line 32 
 extern int bs_mode;  extern int bs_mode;
 extern int ctldisp;  extern int ctldisp;
 extern int status_col;  extern int status_col;
 extern void * constant ml_search;  extern void *const ml_search;
 extern POSITION start_attnpos;  extern off_t start_attnpos;
 extern POSITION end_attnpos;  extern off_t end_attnpos;
 extern int utf_mode;  extern int utf_mode;
 extern int screen_trashed;  extern int screen_trashed;
 #if HILITE_SEARCH  
 extern int hilite_search;  extern int hilite_search;
 extern int size_linebuf;  extern int size_linebuf;
 extern int squished;  extern int squished;
 extern int can_goto_line;  extern int can_goto_line;
 extern int less_is_more;  
 static int hide_hilite;  static int hide_hilite;
 static POSITION prep_startpos;  static off_t prep_startpos;
 static POSITION prep_endpos;  static off_t prep_endpos;
 static int is_caseless;  static int is_caseless;
 static int is_ucase_pattern;  static int is_ucase_pattern;
   
 struct hilite  struct hilite {
 {  
         struct hilite *hl_next;          struct hilite *hl_next;
         POSITION hl_startpos;          off_t hl_startpos;
         POSITION hl_endpos;          off_t hl_endpos;
 };  };
 static struct hilite hilite_anchor = { NULL, NULL_POSITION, NULL_POSITION };  static struct hilite hilite_anchor = { NULL, -1, -1 };
 static struct hilite filter_anchor = { NULL, NULL_POSITION, NULL_POSITION };  static struct hilite filter_anchor = { NULL, -1, -1 };
 #define hl_first        hl_next  #define hl_first        hl_next
 #endif  
   
 /*  /*
  * These are the static variables that represent the "remembered"   * These are the static variables that represent the "remembered"
  * search pattern and filter pattern.   * search pattern and filter pattern.
  */   */
 struct pattern_info {  struct pattern_info {
         DEFINE_PATTERN(compiled);          regex_t *compiled;
         char* text;          char *text;
         int search_type;          int search_type;
 };  };
   
 #if NO_REGEX  #define info_compiled(info) ((info)->compiled)
 #define info_compiled(info) ((void*)0)  
 #else  
 #define info_compiled(info) ((info)->compiled)  
 #endif  
   
 static struct pattern_info search_info;  static struct pattern_info search_info;
 static struct pattern_info filter_info;  static struct pattern_info filter_info;
   
 /*  /*
  * Are there any uppercase letters in this string?   * Are there any uppercase letters in this string?
  */   */
         static int  static int
 is_ucase(str)  is_ucase(char *str)
         char *str;  
 {  {
         char *str_end = str + strlen(str);          char *str_end = str + strlen(str);
         LWCHAR ch;          LWCHAR ch;
   
         while (str < str_end)          while (str < str_end) {
         {  
                 ch = step_char(&str, +1, str_end);                  ch = step_char(&str, +1, str_end);
                 if (IS_UPPER(ch))                  if (isupper(ch))
                         return (1);                          return (1);
         }          }
         return (0);          return (0);
Line 98 
Line 91 
 /*  /*
  * Compile and save a search pattern.   * Compile and save a search pattern.
  */   */
         static int  static int
 set_pattern(info, pattern, search_type)  set_pattern(struct pattern_info *info, char *pattern, int search_type)
         struct pattern_info *info;  
         char *pattern;  
         int search_type;  
 {  {
 #if !NO_REGEX  
         if (pattern == NULL)          if (pattern == NULL)
                 CLEAR_PATTERN(info->compiled);                  info->compiled = NULL;
         else if (compile_pattern(pattern, search_type, &info->compiled) < 0)          else if (compile_pattern(pattern, search_type, &info->compiled) < 0)
                 return -1;                  return (-1);
 #endif  
         /* Pattern compiled successfully; save the text too. */          /* Pattern compiled successfully; save the text too. */
         if (info->text != NULL)          if (info->text != NULL)
                 free(info->text);                  free(info->text);
         info->text = NULL;          info->text = NULL;
         if (pattern != NULL)          if (pattern != NULL) {
                 info->text = save(pattern);                  info->text = estrdup(pattern);
           }
         info->search_type = search_type;          info->search_type = search_type;
   
         /*          /*
Line 123 
Line 112 
          * -i is set AND the pattern is all lowercase.           * -i is set AND the pattern is all lowercase.
          */           */
         is_ucase_pattern = is_ucase(pattern);          is_ucase_pattern = is_ucase(pattern);
         if (is_ucase_pattern && caseless != OPT_ONPLUS && (caseless != OPT_ON || !less_is_more))          if (is_ucase_pattern && caseless != OPT_ONPLUS)
                 is_caseless = 0;                  is_caseless = 0;
         else          else
                 is_caseless = caseless;                  is_caseless = caseless;
         return 0;          return (0);
 }  }
   
 /*  /*
  * Discard a saved pattern.   * Discard a saved pattern.
  */   */
         static void  static void
 clear_pattern(info)  clear_pattern(struct pattern_info *info)
         struct pattern_info *info;  
 {  {
         if (info->text != NULL)          if (info->text != NULL)
                 free(info->text);                  free(info->text);
         info->text = NULL;          info->text = NULL;
 #if !NO_REGEX  
         uncompile_pattern(&info->compiled);          uncompile_pattern(&info->compiled);
 #endif  
 }  }
   
 /*  /*
  * Initialize saved pattern to nothing.   * Initialize saved pattern to nothing.
  */   */
         static void  static void
 init_pattern(info)  init_pattern(struct pattern_info *info)
         struct pattern_info *info;  
 {  {
         CLEAR_PATTERN(info->compiled);          info->compiled = NULL;
         info->text = NULL;          info->text = NULL;
         info->search_type = 0;          info->search_type = 0;
 }  }
Line 160 
Line 145 
 /*  /*
  * Initialize search variables.   * Initialize search variables.
  */   */
         public void  void
 init_search()  init_search(void)
 {  {
         init_pattern(&search_info);          init_pattern(&search_info);
         init_pattern(&filter_info);          init_pattern(&filter_info);
Line 170 
Line 155 
 /*  /*
  * Determine which text conversions to perform before pattern matching.   * Determine which text conversions to perform before pattern matching.
  */   */
         static int  static int
 get_cvt_ops()  get_cvt_ops(void)
 {  {
         int ops = 0;          int ops = 0;
         if (is_caseless || bs_mode == BS_SPECIAL)          if (is_caseless || bs_mode == BS_SPECIAL) {
         {                  if (is_caseless)
                 if (is_caseless)  
                         ops |= CVT_TO_LC;                          ops |= CVT_TO_LC;
                 if (bs_mode == BS_SPECIAL)                  if (bs_mode == BS_SPECIAL)
                         ops |= CVT_BS;                          ops |= CVT_BS;
                 if (bs_mode != BS_CONTROL)                  if (bs_mode != BS_CONTROL)
                         ops |= CVT_CRLF;                          ops |= CVT_CRLF;
         } else if (bs_mode != BS_CONTROL)          } else if (bs_mode != BS_CONTROL) {
         {  
                 ops |= CVT_CRLF;                  ops |= CVT_CRLF;
         }          }
         if (ctldisp == OPT_ONPLUS)          if (ctldisp == OPT_ONPLUS)
Line 194 
Line 177 
 /*  /*
  * Is there a previous (remembered) search pattern?   * Is there a previous (remembered) search pattern?
  */   */
         static int  static int
 prev_pattern(info)  prev_pattern(struct pattern_info *info)
         struct pattern_info *info;  
 {  {
 #if !NO_REGEX  
         if ((info->search_type & SRCH_NO_REGEX) == 0)          if ((info->search_type & SRCH_NO_REGEX) == 0)
                 return (!is_null_pattern(info->compiled));                  return (!is_null_pattern(info->compiled));
 #endif  
         return (info->text != NULL);          return (info->text != NULL);
 }  }
   
 #if HILITE_SEARCH  
 /*  /*
  * Repaint the hilites currently displayed on the screen.   * Repaint the hilites currently displayed on the screen.
  * Repaint each line which contains highlighted text.   * Repaint each line which contains highlighted text.
  * If on==0, force all hilites off.   * If on==0, force all hilites off.
  */   */
         public void  void
 repaint_hilite(on)  repaint_hilite(int on)
         int on;  
 {  {
         int slinenum;          int slinenum;
         POSITION pos;          off_t pos;
         POSITION epos;  
         int save_hide_hilite;          int save_hide_hilite;
   
         if (squished)          if (squished)
                 repaint();                  repaint();
   
         save_hide_hilite = hide_hilite;          save_hide_hilite = hide_hilite;
         if (!on)          if (!on) {
         {  
                 if (hide_hilite)                  if (hide_hilite)
                         return;                          return;
                 hide_hilite = 1;                  hide_hilite = 1;
         }          }
   
         if (!can_goto_line)          if (!can_goto_line) {
         {  
                 repaint();                  repaint();
                 hide_hilite = save_hide_hilite;                  hide_hilite = save_hide_hilite;
                 return;                  return;
         }          }
   
         for (slinenum = TOP;  slinenum < TOP + sc_height-1;  slinenum++)          for (slinenum = TOP;  slinenum < TOP + sc_height-1;  slinenum++) {
         {  
                 pos = position(slinenum);                  pos = position(slinenum);
                 if (pos == NULL_POSITION)                  if (pos == -1)
                         continue;                          continue;
                 epos = position(slinenum+1);  
                 (void) forw_line(pos);                  (void) forw_line(pos);
                 goto_line(slinenum);                  goto_line(slinenum);
                 put_line();                  put_line();
Line 255 
Line 228 
 /*  /*
  * Clear the attn hilite.   * Clear the attn hilite.
  */   */
         public void  void
 clear_attn()  clear_attn(void)
 {  {
         int slinenum;          int slinenum;
         POSITION old_start_attnpos;          off_t old_start_attnpos;
         POSITION old_end_attnpos;          off_t old_end_attnpos;
         POSITION pos;          off_t pos;
         POSITION epos;          off_t epos;
         int moved = 0;          int moved = 0;
   
         if (start_attnpos == NULL_POSITION)          if (start_attnpos == -1)
                 return;                  return;
         old_start_attnpos = start_attnpos;          old_start_attnpos = start_attnpos;
         old_end_attnpos = end_attnpos;          old_end_attnpos = end_attnpos;
         start_attnpos = end_attnpos = NULL_POSITION;          start_attnpos = end_attnpos = -1;
   
         if (!can_goto_line)          if (!can_goto_line) {
         {  
                 repaint();                  repaint();
                 return;                  return;
         }          }
         if (squished)          if (squished)
                 repaint();                  repaint();
   
         for (slinenum = TOP;  slinenum < TOP + sc_height-1;  slinenum++)          for (slinenum = TOP; slinenum < TOP + sc_height-1; slinenum++) {
         {  
                 pos = position(slinenum);                  pos = position(slinenum);
                 if (pos == NULL_POSITION)                  if (pos == -1)
                         continue;                          continue;
                 epos = position(slinenum+1);                  epos = position(slinenum+1);
                 if (pos < old_end_attnpos &&                  if (pos < old_end_attnpos &&
                      (epos == NULL_POSITION || epos > old_start_attnpos))                      (epos == -1 || epos > old_start_attnpos)) {
                 {  
                         (void) forw_line(pos);                          (void) forw_line(pos);
                         goto_line(slinenum);                          goto_line(slinenum);
                         put_line();                          put_line();
Line 297 
Line 267 
         if (moved)          if (moved)
                 lower_left();                  lower_left();
 }  }
 #endif  
   
 /*  /*
  * Hide search string highlighting.   * Hide search string highlighting.
  */   */
         public void  void
 undo_search()  undo_search(void)
 {  {
         if (!prev_pattern(&search_info))          if (!prev_pattern(&search_info)) {
         {  
                 error("No previous regular expression", NULL_PARG);                  error("No previous regular expression", NULL_PARG);
                 return;                  return;
         }          }
 #if HILITE_SEARCH  
         hide_hilite = !hide_hilite;          hide_hilite = !hide_hilite;
         repaint_hilite(1);          repaint_hilite(1);
 #endif  
 }  }
   
 #if HILITE_SEARCH  
 /*  /*
  * Clear the hilite list.   * Clear the hilite list.
  */   */
         public void  static void
 clr_hlist(anchor)  clr_hlist(struct hilite *anchor)
         struct hilite *anchor;  
 {  {
         struct hilite *hl;          struct hilite *hl;
         struct hilite *nexthl;          struct hilite *nexthl;
   
         for (hl = anchor->hl_first;  hl != NULL;  hl = nexthl)          for (hl = anchor->hl_first; hl != NULL; hl = nexthl) {
         {  
                 nexthl = hl->hl_next;                  nexthl = hl->hl_next;
                 free((void*)hl);                  free((void*)hl);
         }          }
         anchor->hl_first = NULL;          anchor->hl_first = NULL;
         prep_startpos = prep_endpos = NULL_POSITION;          prep_startpos = prep_endpos = -1;
 }  }
   
         public void  void
 clr_hilite()  clr_hilite(void)
 {  {
         clr_hlist(&hilite_anchor);          clr_hlist(&hilite_anchor);
 }  }
   
         public void  static void
 clr_filter()  clr_filter(void)
 {  {
         clr_hlist(&filter_anchor);          clr_hlist(&filter_anchor);
 }  }
Line 352 
Line 315 
  * Should any characters in a specified range be highlighted?   * Should any characters in a specified range be highlighted?
  */   */
         static int          static int
 is_hilited_range(pos, epos)  is_hilited_range(off_t pos, off_t epos)
         POSITION pos;  
         POSITION epos;  
 {  {
         struct hilite *hl;          struct hilite *hl;
   
         /*          /*
          * Look at each highlight and see if any part of it falls in the range.           * Look at each highlight and see if any part of it falls in the range.
          */           */
         for (hl = hilite_anchor.hl_first;  hl != NULL;  hl = hl->hl_next)          for (hl = hilite_anchor.hl_first; hl != NULL; hl = hl->hl_next) {
         {  
                 if (hl->hl_endpos > pos &&                  if (hl->hl_endpos > pos &&
                     (epos == NULL_POSITION || epos > hl->hl_startpos))                      (epos == -1 || epos > hl->hl_startpos))
                         return (1);                          return (1);
         }          }
         return (0);          return (0);
 }  }
   
 /*  /*
  * Is a line "filtered" -- that is, should it be hidden?   * Is a line "filtered" -- that is, should it be hidden?
  */   */
         public int  int
 is_filtered(pos)  is_filtered(off_t pos)
         POSITION pos;  
 {  {
         struct hilite *hl;          struct hilite *hl;
   
Line 386 
Line 345 
          * Look at each filter and see if the start position           * Look at each filter and see if the start position
          * equals the start position of the line.           * equals the start position of the line.
          */           */
         for (hl = filter_anchor.hl_first;  hl != NULL;  hl = hl->hl_next)          for (hl = filter_anchor.hl_first; hl != NULL; hl = hl->hl_next) {
         {  
                 if (hl->hl_startpos == pos)                  if (hl->hl_startpos == pos)
                         return (1);                          return (1);
         }          }
Line 398 
Line 356 
  * Should any characters in a specified range be highlighted?   * Should any characters in a specified range be highlighted?
  * If nohide is nonzero, don't consider hide_hilite.   * If nohide is nonzero, don't consider hide_hilite.
  */   */
         public int  int
 is_hilited(pos, epos, nohide, p_matches)  is_hilited(off_t pos, off_t epos, int nohide, int *p_matches)
         POSITION pos;  
         POSITION epos;  
         int nohide;  
         int *p_matches;  
 {  {
         int match;          int match;
   
Line 411 
Line 365 
                 *p_matches = 0;                  *p_matches = 0;
   
         if (!status_col &&          if (!status_col &&
             start_attnpos != NULL_POSITION &&              start_attnpos != -1 &&
             pos < end_attnpos &&              pos < end_attnpos &&
              (epos == NULL_POSITION || epos > start_attnpos))              (epos == -1 || epos > start_attnpos))
                 /*                  /*
                  * The attn line overlaps this range.                   * The attn line overlaps this range.
                  */                   */
Line 447 
Line 401 
 /*  /*
  * Add a new hilite to a hilite list.   * Add a new hilite to a hilite list.
  */   */
         static void  static void
 add_hilite(anchor, hl)  add_hilite(struct hilite *anchor, struct hilite *hl)
         struct hilite *anchor;  
         struct hilite *hl;  
 {  {
         struct hilite *ihl;          struct hilite *ihl;
   
Line 471 
Line 423 
         if (ihl != anchor)          if (ihl != anchor)
                 hl->hl_startpos = MAXPOS(hl->hl_startpos, ihl->hl_endpos);                  hl->hl_startpos = MAXPOS(hl->hl_startpos, ihl->hl_endpos);
         if (ihl->hl_next != NULL)          if (ihl->hl_next != NULL)
                 hl->hl_endpos = MINPOS(hl->hl_endpos, ihl->hl_next->hl_startpos);                  hl->hl_endpos = MINPOS(hl->hl_endpos,
         if (hl->hl_startpos >= hl->hl_endpos)                      ihl->hl_next->hl_startpos);
         {          if (hl->hl_startpos >= hl->hl_endpos) {
                 /*                  /*
                  * Hilite was truncated out of existence.                   * Hilite was truncated out of existence.
                  */                   */
Line 487 
Line 439 
 /*  /*
  * Hilight every character in a range of displayed characters.   * Hilight every character in a range of displayed characters.
  */   */
         static void  static void
 create_hilites(linepos, start_index, end_index, chpos)  create_hilites(off_t linepos, int start_index, int end_index, int *chpos)
         POSITION linepos;  
         int start_index;  
         int end_index;  
         int *chpos;  
 {  {
         struct hilite *hl;          struct hilite *hl;
         int i;          int i;
   
         /* Start the first hilite. */          /* Start the first hilite. */
         hl = (struct hilite *) ecalloc(1, sizeof(struct hilite));          hl = ecalloc(1, sizeof (struct hilite));
         hl->hl_startpos = linepos + chpos[start_index];          hl->hl_startpos = linepos + chpos[start_index];
   
         /*          /*
Line 509 
Line 457 
          * Otherwise (there are backspaces or something involved),           * Otherwise (there are backspaces or something involved),
          * finish the current hilite and start a new one.           * finish the current hilite and start a new one.
          */           */
         for (i = start_index+1;  i <= end_index;  i++)          for (i = start_index+1; i <= end_index; i++) {
         {                  if (chpos[i] != chpos[i-1] + 1 || i == end_index) {
                 if (chpos[i] != chpos[i-1] + 1 || i == end_index)  
                 {  
                         hl->hl_endpos = linepos + chpos[i-1] + 1;                          hl->hl_endpos = linepos + chpos[i-1] + 1;
                         add_hilite(&hilite_anchor, hl);                          add_hilite(&hilite_anchor, hl);
                         /* Start new hilite unless this is the last char. */                          /* Start new hilite unless this is the last char. */
                         if (i < end_index)                          if (i < end_index) {
                         {                                  hl = ecalloc(1, sizeof (struct hilite));
                                 hl = (struct hilite *) ecalloc(1, sizeof(struct hilite));  
                                 hl->hl_startpos = linepos + chpos[i];                                  hl->hl_startpos = linepos + chpos[i];
                         }                          }
                 }                  }
Line 526 
Line 471 
 }  }
   
 /*  /*
  * Make a hilite for each string in a physical line which matches   * Make a hilite for each string in a physical line which matches
  * the current pattern.   * the current pattern.
  * sp,ep delimit the first match already found.   * sp,ep delimit the first match already found.
  */   */
         static void  static void
 hilite_line(linepos, line, line_len, chpos, sp, ep, cvt_ops)  hilite_line(off_t linepos, char *line, int line_len, int *chpos,
         POSITION linepos;      char *sp, char *ep)
         char *line;  
         int line_len;  
         int *chpos;  
         char *sp;  
         char *ep;  
         int cvt_ops;  
 {  {
         char *searchp;          char *searchp;
         char *line_end = line + line_len;          char *line_end = line + line_len;
Line 557 
Line 496 
          */           */
         searchp = line;          searchp = line;
         do {          do {
                 create_hilites(linepos, sp-line, ep-line, chpos);                  create_hilites(linepos, (intptr_t)sp - (intptr_t)line,
                       (intptr_t)ep - (intptr_t)line, chpos);
                 /*                  /*
                  * If we matched more than zero characters,                   * If we matched more than zero characters,
                  * move to the first char after the string we matched.                   * move to the first char after the string we matched.
Line 570 
Line 510 
                 else /* end of line */                  else /* end of line */
                         break;                          break;
         } while (match_pattern(info_compiled(&search_info), search_info.text,          } while (match_pattern(info_compiled(&search_info), search_info.text,
                         searchp, line_end - searchp, &sp, &ep, 1, search_info.search_type));              searchp, (intptr_t)line_end - (intptr_t)searchp, &sp, &ep, 1,
               search_info.search_type));
 }  }
 #endif  
   
 /*  /*
  * Change the caseless-ness of searches.   * Change the caseless-ness of searches.
  * Updates the internal search state to reflect a change in the -i flag.   * Updates the internal search state to reflect a change in the -i flag.
  */   */
         public void  void
 chg_caseless()  chg_caseless(void)
 {  {
         if (!is_ucase_pattern)          if (!is_ucase_pattern)
                 /*                  /*
Line 595 
Line 535 
                 clear_pattern(&search_info);                  clear_pattern(&search_info);
 }  }
   
 #if HILITE_SEARCH  
 /*  /*
  * Find matching text which is currently on screen and highlight it.   * Find matching text which is currently on screen and highlight it.
  */   */
         static void  static void
 hilite_screen()  hilite_screen(void)
 {  {
         struct scrpos scrpos;          struct scrpos scrpos;
   
         get_scrpos(&scrpos);          get_scrpos(&scrpos);
         if (scrpos.pos == NULL_POSITION)          if (scrpos.pos == -1)
                 return;                  return;
         prep_hilite(scrpos.pos, position(BOTTOM_PLUS_ONE), -1);          prep_hilite(scrpos.pos, position(BOTTOM_PLUS_ONE), -1);
         repaint_hilite(1);          repaint_hilite(1);
Line 614 
Line 553 
 /*  /*
  * Change highlighting parameters.   * Change highlighting parameters.
  */   */
         public void  void
 chg_hilite()  chg_hilite(void)
 {  {
         /*          /*
          * Erase any highlights currently on screen.           * Erase any highlights currently on screen.
Line 629 
Line 568 
                  */                   */
                 hilite_screen();                  hilite_screen();
 }  }
 #endif  
   
 /*  /*
  * Figure out where to start a search.   * Figure out where to start a search.
  */   */
         static POSITION  static off_t
 search_pos(search_type)  search_pos(int search_type)
         int search_type;  
 {  {
         POSITION pos;          off_t pos;
         int linenum;          int linenum;
   
         if (empty_screen())          if (empty_screen()) {
         {  
                 /*                  /*
                  * Start at the beginning (or end) of the file.                   * Start at the beginning (or end) of the file.
                  * The empty_screen() case is mainly for                   * The empty_screen() case is mainly for
                  * command line initiated searches;                   * command line initiated searches;
                  * for example, "+/xyz" on the command line.                   * for example, "+/xyz" on the command line.
                  * Also for multi-file (SRCH_PAST_EOF) searches.                   * Also for multi-file (SRCH_PAST_EOF) searches.
                  */                   */
                 if (search_type & SRCH_FORW)                  if (search_type & SRCH_FORW) {
                 {  
                         pos = ch_zero();                          pos = ch_zero();
                 } else                  } else {
                 {  
                         pos = ch_length();                          pos = ch_length();
                         if (pos == NULL_POSITION)                          if (pos == -1) {
                         {  
                                 (void) ch_end_seek();                                  (void) ch_end_seek();
                                 pos = ch_length();                                  pos = ch_length();
                         }                          }
                 }                  }
                 linenum = 0;                  linenum = 0;
         } else          } else {
         {  
                 int add_one = 0;                  int add_one = 0;
   
                 if (how_search == OPT_ON)                  if (how_search == OPT_ON) {
                 {  
                         /*                          /*
                          * Search does not include current screen.                           * Search does not include current screen.
                          */                           */
Line 676 
Line 607 
                                 linenum = BOTTOM_PLUS_ONE;                                  linenum = BOTTOM_PLUS_ONE;
                         else                          else
                                 linenum = TOP;                                  linenum = TOP;
                 } else if (how_search == OPT_ONPLUS && !(search_type & SRCH_AFTER_TARGET))                  } else if (how_search == OPT_ONPLUS &&
                 {                      !(search_type & SRCH_AFTER_TARGET)) {
                         /*                          /*
                          * Search includes all of displayed screen.                           * Search includes all of displayed screen.
                          */                           */
Line 685 
Line 616 
                                 linenum = TOP;                                  linenum = TOP;
                         else                          else
                                 linenum = BOTTOM_PLUS_ONE;                                  linenum = BOTTOM_PLUS_ONE;
                 } else                  } else {
                 {  
                         /*                          /*
                          * Search includes the part of current screen beyond the jump target.                           * Search includes the part of current screen beyond
                          * It starts at the jump target (if searching backwards),                           * the jump target.
                          * or at the jump target plus one (if forwards).                           * It starts at the jump target (if searching
                            * backwards), or at the jump target plus one
                            * (if forwards).
                          */                           */
                         linenum = jump_sline;                          linenum = jump_sline;
                         if (search_type & SRCH_FORW)                          if (search_type & SRCH_FORW)
                             add_one = 1;                                  add_one = 1;
                 }                  }
                 linenum = adjsline(linenum);                  linenum = adjsline(linenum);
                 pos = position(linenum);                  pos = position(linenum);
                 if (add_one)                  if (add_one)
                         pos = forw_raw_line(pos, (char **)NULL, (int *)NULL);                          pos = forw_raw_line(pos, NULL, NULL);
         }          }
   
         /*          /*
          * If the line is empty, look around for a plausible starting place.           * If the line is empty, look around for a plausible starting place.
          */           */
         if (search_type & SRCH_FORW)          if (search_type & SRCH_FORW) {
         {                  while (pos == -1) {
             while (pos == NULL_POSITION)                          if (++linenum >= sc_height)
             {                                  break;
                 if (++linenum >= sc_height)                          pos = position(linenum);
                     break;                  }
                 pos = position(linenum);          } else {
             }                  while (pos == -1) {
         } else                          if (--linenum < 0)
         {                                  break;
             while (pos == NULL_POSITION)                          pos = position(linenum);
             {                  }
                 if (--linenum < 0)  
                     break;  
                 pos = position(linenum);  
             }  
         }          }
         return (pos);          return (pos);
 }  }
Line 728 
Line 656 
 /*  /*
  * Search a subset of the file, specified by start/end position.   * Search a subset of the file, specified by start/end position.
  */   */
         static int  static int
 search_range(pos, endpos, search_type, matches, maxlines, plinepos, pendpos)  search_range(off_t pos, off_t endpos, int search_type, int matches,
         POSITION pos;      int maxlines, off_t *plinepos, off_t *pendpos)
         POSITION endpos;  
         int search_type;  
         int matches;  
         int maxlines;  
         POSITION *plinepos;  
         POSITION *pendpos;  
 {  {
         char *line;          char *line;
         char *cline;          char *cline;
Line 747 
Line 669 
         int cvt_ops;          int cvt_ops;
         int cvt_len;          int cvt_len;
         int *chpos;          int *chpos;
         POSITION linepos, oldpos;          off_t linepos, oldpos;
   
         linenum = find_linenum(pos);          linenum = find_linenum(pos);
         oldpos = pos;          oldpos = pos;
         for (;;)          for (;;) {
         {  
                 /*                  /*
                  * Get lines until we find a matching one or until                   * Get lines until we find a matching one or until
                  * we hit end-of-file (or beginning-of-file if we're                   * we hit end-of-file (or beginning-of-file if we're
                  * going backwards), or until we hit the end position.                   * going backwards), or until we hit the end position.
                  */                   */
                 if (ABORT_SIGS())                  if (ABORT_SIGS()) {
                 {  
                         /*                          /*
                          * A signal aborts the search.                           * A signal aborts the search.
                          */                           */
                         return (-1);                          return (-1);
                 }                  }
   
                 if ((endpos != NULL_POSITION && pos >= endpos) || maxlines == 0)                  if ((endpos != -1 && pos >= endpos) ||
                 {                      maxlines == 0) {
                         /*                          /*
                          * Reached end position without a match.                           * Reached end position without a match.
                          */                           */
Line 778 
Line 698 
                 if (maxlines > 0)                  if (maxlines > 0)
                         maxlines--;                          maxlines--;
   
                 if (search_type & SRCH_FORW)                  if (search_type & SRCH_FORW) {
                 {  
                         /*                          /*
                          * Read the next line, and save the                           * Read the next line, and save the
                          * starting position of that line in linepos.                           * starting position of that line in linepos.
                          */                           */
                         linepos = pos;                          linepos = pos;
                         pos = forw_raw_line(pos, &line, &line_len);                          pos = forw_raw_line(pos, &line, &line_len);
                         if (linenum != 0)                          if (linenum != 0)
                                 linenum++;                                  linenum++;
                 } else                  } else {
                 {  
                         /*                          /*
                          * Read the previous line and save the                           * Read the previous line and save the
                          * starting position of that line in linepos.                           * starting position of that line in linepos.
Line 800 
Line 718 
                                 linenum--;                                  linenum--;
                 }                  }
   
                 if (pos == NULL_POSITION)                  if (pos == -1) {
                 {  
                         /*                          /*
                          * Reached EOF/BOF without a match.                           * Reached EOF/BOF without a match.
                          */                           */
Line 830 
Line 747 
                  * If we're doing backspace processing, delete backspaces.                   * If we're doing backspace processing, delete backspaces.
                  */                   */
                 cvt_ops = get_cvt_ops();                  cvt_ops = get_cvt_ops();
                 cvt_len = cvt_length(line_len, cvt_ops);                  cvt_len = cvt_length(line_len);
                 cline = (char *) ecalloc(1, cvt_len);                  cline = ecalloc(1, cvt_len);
                 chpos = cvt_alloc_chpos(cvt_len);                  chpos = cvt_alloc_chpos(cvt_len);
                 cvt_text(cline, line, chpos, &line_len, cvt_ops);                  cvt_text(cline, line, chpos, &line_len, cvt_ops);
   
 #if HILITE_SEARCH  
                 /*                  /*
                  * Check to see if the line matches the filter pattern.                   * Check to see if the line matches the filter pattern.
                  * If so, add an entry to the filter list.                   * If so, add an entry to the filter list.
                  */                   */
                 if ((search_type & SRCH_FIND_ALL) && prev_pattern(&filter_info)) {                  if ((search_type & SRCH_FIND_ALL) &&
                         int line_filter = match_pattern(info_compiled(&filter_info), filter_info.text,                      prev_pattern(&filter_info)) {
                                 cline, line_len, &sp, &ep, 0, filter_info.search_type);                          int line_filter =
                         if (line_filter)                              match_pattern(info_compiled(&filter_info),
                         {                              filter_info.text, cline, line_len, &sp, &ep, 0,
                                 struct hilite *hl = (struct hilite *)                              filter_info.search_type);
                                         ecalloc(1, sizeof(struct hilite));                          if (line_filter) {
                                   struct hilite *hl =
                                       ecalloc(1, sizeof (struct hilite));
                                 hl->hl_startpos = linepos;                                  hl->hl_startpos = linepos;
                                 hl->hl_endpos = pos;                                  hl->hl_endpos = pos;
                                 add_hilite(&filter_anchor, hl);                                  add_hilite(&filter_anchor, hl);
                         }                          }
                 }                  }
 #endif  
   
                 /*                  /*
                  * Test the next line to see if we have a match.                   * Test the next line to see if we have a match.
                  * We are successful if we either want a match and got one,                   * We are successful if we either want a match and got one,
                  * or if we want a non-match and got one.                   * or if we want a non-match and got one.
                  */                   */
                 if (prev_pattern(&search_info))                  if (prev_pattern(&search_info)) {
                 {                          line_match = match_pattern(info_compiled(&search_info),
                         line_match = match_pattern(info_compiled(&search_info), search_info.text,                              search_info.text, cline, line_len, &sp, &ep, 0,
                                 cline, line_len, &sp, &ep, 0, search_type);                              search_type);
                         if (line_match)                          if (line_match) {
                         {  
                                 /*                                  /*
                                  * Got a match.                                   * Got a match.
                                  */                                   */
                                 if (search_type & SRCH_FIND_ALL)                                  if (search_type & SRCH_FIND_ALL) {
                                 {  
 #if HILITE_SEARCH  
                                         /*                                          /*
                                          * We are supposed to find all matches in the range.                                           * We are supposed to find all matches
                                          * Just add the matches in this line to the                                           * in the range.
                                          * hilite list and keep searching.                                           * Just add the matches in this line
                                            * to the hilite list and keep
                                            * searching.
                                          */                                           */
                                         hilite_line(linepos, cline, line_len, chpos, sp, ep, cvt_ops);                                          hilite_line(linepos, cline, line_len,
 #endif                                              chpos, sp, ep);
                                 } else if (--matches <= 0)                                  } else if (--matches <= 0) {
                                 {  
                                         /*                                          /*
                                          * Found the one match we're looking for.                                           * Found the one match we're looking
                                          * Return it.                                           * for.  Return it.
                                          */                                           */
 #if HILITE_SEARCH                                          if (hilite_search == OPT_ON) {
                                         if (hilite_search == OPT_ON)  
                                         {  
                                                 /*                                                  /*
                                                  * Clear the hilite list and add only                                                   * Clear the hilite list and
                                                    * add only
                                                  * the matches in this one line.                                                   * the matches in this one line.
                                                  */                                                   */
                                                 clr_hilite();                                                  clr_hilite();
                                                 hilite_line(linepos, cline, line_len, chpos, sp, ep, cvt_ops);                                                  hilite_line(linepos, cline,
                                                       line_len, chpos, sp, ep);
                                         }                                          }
 #endif  
                                         free(cline);                                          free(cline);
                                         free(chpos);                                          free(chpos);
                                         if (plinepos != NULL)                                          if (plinepos != NULL)
Line 911 
Line 825 
 /*  /*
  * search for a pattern in history. If found, compile that pattern.   * search for a pattern in history. If found, compile that pattern.
  */   */
         static int  static int
 hist_pattern(search_type)  hist_pattern(int search_type)
         int search_type;  
 {  {
 #if CMD_HISTORY  
         char *pattern;          char *pattern;
   
         set_mlist(ml_search, 0);          set_mlist(ml_search, 0);
Line 926 
Line 838 
         if (set_pattern(&search_info, pattern, search_type) < 0)          if (set_pattern(&search_info, pattern, search_type) < 0)
                 return (0);                  return (0);
   
 #if HILITE_SEARCH  
         if (hilite_search == OPT_ONPLUS && !hide_hilite)          if (hilite_search == OPT_ONPLUS && !hide_hilite)
                 hilite_screen();                  hilite_screen();
 #endif  
   
         return (1);          return (1);
 #else /* CMD_HISTORY */  
         return (0);  
 #endif /* CMD_HISTORY */  
 }  }
   
 /*  /*
  * Search for the n-th occurrence of a specified pattern,   * Search for the n-th occurrence of a specified pattern,
  * either forward or backward.   * either forward or backward.
  * Return the number of matches not yet found in this file   * Return the number of matches not yet found in this file
  * (that is, n minus the number of matches found).   * (that is, n minus the number of matches found).
  * Return -1 if the search should be aborted.   * Return -1 if the search should be aborted.
  * Caller may continue the search in another file   * Caller may continue the search in another file
  * if less than n matches are found in this file.   * if less than n matches are found in this file.
  */   */
         public int  int
 search(search_type, pattern, n)  search(int search_type, char *pattern, int n)
         int search_type;  
         char *pattern;  
         int n;  
 {  {
         POSITION pos;          off_t pos;
   
         if (pattern == NULL || *pattern == '\0')          if (pattern == NULL || *pattern == '\0') {
         {  
                 /*                  /*
                  * A null pattern means use the previously compiled pattern.                   * A null pattern means use the previously compiled pattern.
                  */                   */
                 search_type |= SRCH_AFTER_TARGET;                  search_type |= SRCH_AFTER_TARGET;
                 if (!prev_pattern(&search_info) && !hist_pattern(search_type))                  if (!prev_pattern(&search_info) && !hist_pattern(search_type)) {
                 {  
                         error("No previous regular expression", NULL_PARG);                          error("No previous regular expression", NULL_PARG);
                         return (-1);                          return (-1);
                 }                  }
                 if ((search_type & SRCH_NO_REGEX) !=                  if ((search_type & SRCH_NO_REGEX) !=
                       (search_info.search_type & SRCH_NO_REGEX))                      (search_info.search_type & SRCH_NO_REGEX)) {
                 {  
                         error("Please re-enter search pattern", NULL_PARG);                          error("Please re-enter search pattern", NULL_PARG);
                         return -1;                          return (-1);
                 }                  }
 #if HILITE_SEARCH                  if (hilite_search == OPT_ON) {
                 if (hilite_search == OPT_ON)  
                 {  
                         /*                          /*
                          * Erase the highlights currently on screen.                           * Erase the highlights currently on screen.
                          * If the search fails, we'll redisplay them later.                           * If the search fails, we'll redisplay them later.
                          */                           */
                         repaint_hilite(0);                          repaint_hilite(0);
                 }                  }
                 if (hilite_search == OPT_ONPLUS && hide_hilite)                  if (hilite_search == OPT_ONPLUS && hide_hilite) {
                 {  
                         /*                          /*
                          * Highlight any matches currently on screen,                           * Highlight any matches currently on screen,
                          * before we actually start the search.                           * before we actually start the search.
Line 990 
Line 888 
                         hilite_screen();                          hilite_screen();
                 }                  }
                 hide_hilite = 0;                  hide_hilite = 0;
 #endif          } else {
         } else  
         {  
                 /*                  /*
                  * Compile the pattern.                   * Compile the pattern.
                  */                   */
                 if (set_pattern(&search_info, pattern, search_type) < 0)                  if (set_pattern(&search_info, pattern, search_type) < 0)
                         return (-1);                          return (-1);
 #if HILITE_SEARCH                  if (hilite_search) {
                 if (hilite_search)  
                 {  
                         /*                          /*
                          * Erase the highlights currently on screen.                           * Erase the highlights currently on screen.
                          * Also permanently delete them from the hilite list.                           * Also permanently delete them from the hilite list.
Line 1009 
Line 903 
                         hide_hilite = 0;                          hide_hilite = 0;
                         clr_hilite();                          clr_hilite();
                 }                  }
                 if (hilite_search == OPT_ONPLUS)                  if (hilite_search == OPT_ONPLUS) {
                 {  
                         /*                          /*
                          * Highlight any matches currently on screen,                           * Highlight any matches currently on screen,
                          * before we actually start the search.                           * before we actually start the search.
                          */                           */
                         hilite_screen();                          hilite_screen();
                 }                  }
 #endif  
         }          }
   
         /*          /*
          * Figure out where to start the search.           * Figure out where to start the search.
          */           */
         pos = search_pos(search_type);          pos = search_pos(search_type);
         if (pos == NULL_POSITION)          if (pos == -1) {
         {  
                 /*                  /*
                  * Can't find anyplace to start searching from.                   * Can't find anyplace to start searching from.
                  */                   */
Line 1036 
Line 927 
                 return (-1);                  return (-1);
         }          }
   
         n = search_range(pos, NULL_POSITION, search_type, n, -1,          n = search_range(pos, -1, search_type, n, -1, &pos, NULL);
                         &pos, (POSITION*)NULL);          if (n != 0) {
         if (n != 0)  
         {  
                 /*                  /*
                  * Search was unsuccessful.                   * Search was unsuccessful.
                  */                   */
 #if HILITE_SEARCH  
                 if (hilite_search == OPT_ON && n > 0)                  if (hilite_search == OPT_ON && n > 0)
                         /*                          /*
                          * Redisplay old hilites.                           * Redisplay old hilites.
                          */                           */
                         repaint_hilite(1);                          repaint_hilite(1);
 #endif  
                 return (n);                  return (n);
         }          }
   
         if (!(search_type & SRCH_NO_MOVE))          if (!(search_type & SRCH_NO_MOVE)) {
         {  
                 /*                  /*
                  * Go to the matching line.                   * Go to the matching line.
                  */                   */
                 jump_loc(pos, jump_sline);                  jump_loc(pos, jump_sline);
         }          }
   
 #if HILITE_SEARCH  
         if (hilite_search == OPT_ON)          if (hilite_search == OPT_ON)
                 /*                  /*
                  * Display new hilites in the matching line.                   * Display new hilites in the matching line.
                  */                   */
                 repaint_hilite(1);                  repaint_hilite(1);
 #endif  
         return (0);          return (0);
 }  }
   
   
 #if HILITE_SEARCH  
 /*  /*
  * Prepare hilites in a given range of the file.   * Prepare hilites in a given range of the file.
  *   *
  * The pair (prep_startpos,prep_endpos) delimits a contiguous region   * The pair (prep_startpos,prep_endpos) delimits a contiguous region
  * of the file that has been "prepared"; that is, scanned for matches for   * of the file that has been "prepared"; that is, scanned for matches for
  * the current search pattern, and hilites have been created for such matches.   * the current search pattern, and hilites have been created for such matches.
  * If prep_startpos == NULL_POSITION, the prep region is empty.   * If prep_startpos == -1, the prep region is empty.
  * If prep_endpos == NULL_POSITION, the prep region extends to EOF.   * If prep_endpos == -1, the prep region extends to EOF.
  * prep_hilite asks that the range (spos,epos) be covered by the prep region.   * prep_hilite asks that the range (spos,epos) be covered by the prep region.
  */   */
         public void  void
 prep_hilite(spos, epos, maxlines)  prep_hilite(off_t spos, off_t epos, int maxlines)
         POSITION spos;  
         POSITION epos;  
         int maxlines;  
 {  {
         POSITION nprep_startpos = prep_startpos;          off_t nprep_startpos = prep_startpos;
         POSITION nprep_endpos = prep_endpos;          off_t nprep_endpos = prep_endpos;
         POSITION new_epos;          off_t new_epos;
         POSITION max_epos;          off_t max_epos;
         int result;          int result;
         int i;          int i;
   
Line 1109 
Line 989 
          * If we're limited to a max number of lines, figure out the           * If we're limited to a max number of lines, figure out the
          * file position we should stop at.           * file position we should stop at.
          */           */
         if (maxlines < 0)          if (maxlines < 0) {
                 max_epos = NULL_POSITION;                  max_epos = -1;
         else          } else {
         {  
                 max_epos = spos;                  max_epos = spos;
                 for (i = 0;  i < maxlines;  i++)                  for (i = 0; i < maxlines; i++)
                         max_epos = forw_raw_line(max_epos, (char **)NULL, (int *)NULL);                          max_epos = forw_raw_line(max_epos, NULL, NULL);
         }          }
   
         /*          /*
Line 1124 
Line 1003 
          * the "prep" region will then cover (nprep_startpos,nprep_endpos).           * the "prep" region will then cover (nprep_startpos,nprep_endpos).
          */           */
   
         if (prep_startpos == NULL_POSITION ||          if (prep_startpos == -1 ||
             (epos != NULL_POSITION && epos < prep_startpos) ||              (epos != -1 && epos < prep_startpos) ||
             spos > prep_endpos)              spos > prep_endpos) {
         {  
                 /*                  /*
                  * New range is not contiguous with old prep region.                   * New range is not contiguous with old prep region.
                  * Discard the old prep region and start a new one.                   * Discard the old prep region and start a new one.
                  */                   */
                 clr_hilite();                  clr_hilite();
                 clr_filter();                  clr_filter();
                 if (epos != NULL_POSITION)                  if (epos != -1)
                         epos += SEARCH_MORE;                          epos += SEARCH_MORE;
                 nprep_startpos = spos;                  nprep_startpos = spos;
         } else          } else {
         {  
                 /*                  /*
                  * New range partially or completely overlaps old prep region.                   * New range partially or completely overlaps old prep region.
                  */                   */
                 if (epos == NULL_POSITION)                  if (epos != -1) {
                 {                          if (epos > prep_endpos) {
                         /*                                  /*
                          * New range goes to end of file.                                   * New range ends after old prep region.
                          */                                   * Extend prep region to end at end of new
                         ;                                   * range.
                 } else if (epos > prep_endpos)                                   */
                 {                                  epos += SEARCH_MORE;
                         /*  
                          * New range ends after old prep region.                          } else {
                          * Extend prep region to end at end of new range.                                  /*
                          */                                   * New range ends within old prep region.
                         epos += SEARCH_MORE;                                   * Truncate search to end at start of old prep
                 } else /* (epos <= prep_endpos) */                                   * region.
                 {                                   */
                         /*                                  epos = prep_startpos;
                          * New range ends within old prep region.                          }
                          * Truncate search to end at start of old prep region.  
                          */  
                         epos = prep_startpos;  
                 }                  }
   
                 if (spos < prep_startpos)                  if (spos < prep_startpos) {
                 {  
                         /*                          /*
                          * New range starts before old prep region.                           * New range starts before old prep region.
                          * Extend old prep region backwards to start at                           * Extend old prep region backwards to start at
                          * start of new range.                           * start of new range.
                          */                           */
                         if (spos < SEARCH_MORE)                          if (spos < SEARCH_MORE)
Line 1176 
Line 1049 
                         else                          else
                                 spos -= SEARCH_MORE;                                  spos -= SEARCH_MORE;
                         nprep_startpos = spos;                          nprep_startpos = spos;
                 } else /* (spos >= prep_startpos) */                  } else { /* (spos >= prep_startpos) */
                 {  
                         /*                          /*
                          * New range starts within or after old prep region.                           * New range starts within or after old prep region.
                          * Trim search to start at end of old prep region.                           * Trim search to start at end of old prep region.
Line 1186 
Line 1058 
                 }                  }
         }          }
   
         if (epos != NULL_POSITION && max_epos != NULL_POSITION &&          if (epos != -1 && max_epos != -1 &&
             epos > max_epos)              epos > max_epos)
                 /*                  /*
                  * Don't go past the max position we're allowed.                   * Don't go past the max position we're allowed.
                  */                   */
                 epos = max_epos;                  epos = max_epos;
   
         if (epos == NULL_POSITION || epos > spos)          if (epos == -1 || epos > spos) {
         {  
                 int search_type = SRCH_FORW | SRCH_FIND_ALL;                  int search_type = SRCH_FORW | SRCH_FIND_ALL;
                 search_type |= (search_info.search_type & SRCH_NO_REGEX);                  search_type |= (search_info.search_type & SRCH_NO_REGEX);
                 result = search_range(spos, epos, search_type, 0,                  result = search_range(spos, epos, search_type, 0,
                                 maxlines, (POSITION*)NULL, &new_epos);                      maxlines, NULL, &new_epos);
                 if (result < 0)                  if (result < 0)
                         return;                          return;
                 if (prep_endpos == NULL_POSITION || new_epos > prep_endpos)                  if (prep_endpos == -1 || new_epos > prep_endpos)
                         nprep_endpos = new_epos;                          nprep_endpos = new_epos;
         }          }
         prep_startpos = nprep_startpos;          prep_startpos = nprep_startpos;
Line 1211 
Line 1082 
 /*  /*
  * Set the pattern to be used for line filtering.   * Set the pattern to be used for line filtering.
  */   */
         public void  void
 set_filter_pattern(pattern, search_type)  set_filter_pattern(char *pattern, int search_type)
         char *pattern;  
         int search_type;  
 {  {
         clr_filter();          clr_filter();
         if (pattern == NULL || *pattern == '\0')          if (pattern == NULL || *pattern == '\0')
                 clear_pattern(&filter_info);                  clear_pattern(&filter_info);
         else          else
                 set_pattern(&filter_info, pattern, search_type);                  (void) set_pattern(&filter_info, pattern, search_type);
         screen_trashed = 1;          screen_trashed = 1;
 }  }
   
 /*  /*
  * Is there a line filter in effect?   * Is there a line filter in effect?
  */   */
         public int  int
 is_filtering()  is_filtering(void)
 {  {
         if (ch_getflags() & CH_HELPFILE)          if (ch_getflags() & CH_HELPFILE)
                 return (0);                  return (0);
         return prev_pattern(&filter_info);          return (prev_pattern(&filter_info));
 }  }
 #endif  
   
 #if HAVE_V8_REGCOMP  
 /*  
  * This function is called by the V8 regcomp to report  
  * errors in regular expressions.  
  */  
         void  
 regerror(s)  
         char *s;  
 {  
         PARG parg;  
   
         parg.p_string = s;  
         error("%s", &parg);  
 }  
 #endif  
   

Legend:
Removed from v.1.9  
changed lines
  Added in v.1.10