tin  2.4.4
About: TIN is a threaded NNTP and spool based UseNet newsreader.
  Fossies Dox: tin-2.4.4.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

regex.c
Go to the documentation of this file.
1 /*
2  * Project : tin - a Usenet reader
3  * Module : regex.c
4  * Author : Jason Faultless <jason@altarstone.com>
5  * Created : 1997-02-21
6  * Updated : 2017-02-17
7  * Notes : Regular expression subroutines
8  * Credits :
9  *
10  * Copyright (c) 1997-2020 Jason Faultless <jason@altarstone.com>
11  * All rights reserved.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  *
17  * 1. Redistributions of source code must retain the above copyright notice,
18  * this list of conditions and the following disclaimer.
19  *
20  * 2. Redistributions in binary form must reproduce the above copyright
21  * notice, this list of conditions and the following disclaimer in the
22  * documentation and/or other materials provided with the distribution.
23  *
24  * 3. Neither the name of the copyright holder nor the names of its
25  * contributors may be used to endorse or promote products derived from
26  * this software without specific prior written permission.
27  *
28  * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
32  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38  * POSSIBILITY OF SUCH DAMAGE.
39  */
40 
41 
42 #ifndef TIN_H
43 # include "tin.h"
44 #endif /* !TIN_H */
45 #ifndef TCURSES_H
46 # include "tcurses.h"
47 #endif /* !TCURSES_H */
48 
49 /*
50  * See if pattern is matched in string. Return TRUE or FALSE
51  * if icase=TRUE then ignore case in the compare
52  * if a precompiled regex is provided it will be used instead of pattern
53  *
54  * If you use match_regex() with full regexes within a loop you should always
55  * provide a precompiled error because if the compilation of the regex fails
56  * an error message will be display on each execution of match_regex()
57  */
58 t_bool
60  const char *string,
61  char *pattern,
62  struct regex_cache *cache,
63  t_bool icase)
64 {
65  int error;
66  struct regex_cache tmp_cache = { NULL, NULL };
67  struct regex_cache *ptr_cache;
68 
69  if (!tinrc.wildcard) /* wildmat matching */
70  return wildmat(string, pattern, icase);
71 
72  /* full regexes */
73  if (cache != NULL && cache->re != NULL)
74  ptr_cache = cache; /* use the provided regex cache */
75  else {
76  /* compile the regex internally */
77  if (!compile_regex(pattern, &tmp_cache, (icase ? PCRE_CASELESS : 0)))
78  return FALSE;
79  ptr_cache = &tmp_cache;
80  }
81 
82  if ((error = pcre_exec(ptr_cache->re, ptr_cache->extra, string, strlen(string), 0, 0, NULL, 0)) >= 0) {
83  if (ptr_cache == &tmp_cache) {
84  FreeIfNeeded(tmp_cache.re);
85  FreeIfNeeded(tmp_cache.extra);
86  }
87 
88  return TRUE;
89  }
90 
91 #if 0
92  /*
93  * match_regex() is mostly used within loops and we don't want to display
94  * an error message on each call
95  */
96  if (error != PCRE_ERROR_NOMATCH)
98 #endif /* 0 */
99 
100  FreeIfNeeded(tmp_cache.re);
101  FreeIfNeeded(tmp_cache.extra);
102 
103  return FALSE;
104 }
105 
106 
107 /*
108  * Compile and optimise 'regex'. Return TRUE if all went well
109  */
110 t_bool
112  const char *regex,
113  struct regex_cache *cache,
114  int options)
115 {
116  const char *regex_errmsg = NULL;
117  int regex_errpos, my_options = options;
118 
119 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE) && (defined(PCRE_MAJOR) && PCRE_MAJOR >= 4)
120  if (IS_LOCAL_CHARSET("UTF-8")) {
121  int i;
122 
124  if (i)
125  my_options |= PCRE_UTF8;
126  }
127 #endif /* MULTIBYTE_ABLE && !NO_LOCALE && PCRE_MAJOR && PCRE_MAJOR >= 4 */
128 
129  if ((cache->re = pcre_compile(regex, my_options, &regex_errmsg, &regex_errpos, NULL)) == NULL)
130  error_message(2, _(txt_pcre_error_at), regex_errmsg, regex_errpos, regex);
131  else {
132  cache->extra = pcre_study(cache->re, 0, &regex_errmsg);
133  if (regex_errmsg != NULL) {
134  /* we failed, clean up */
135  FreeAndNull(cache->re);
136  error_message(2, _(txt_pcre_error_text), regex_errmsg);
137  } else
138  return TRUE;
139  }
140  return FALSE;
141 }
142 
143 
144 /*
145  * Highlight any string on 'row' that match 'regex'
146  */
147 void
149  int row,
150  struct regex_cache *regex,
151  int color)
152 {
153  char *ptr;
154  int offsets[6]; /* we are not interested in any subpatterns, so 6 is sufficient */
155  int offsets_size = ARRAY_SIZE(offsets);
156 #ifdef USE_CURSES
157  char buf[LEN];
158 #else
159  char *buf;
160 #endif /* USE_CURSES */
161 
162  /* Get contents of line from the screen */
163 #ifdef USE_CURSES
164  screen_contents(row, 0, buf);
165 #else
166  buf = screen[row].col;
167 #endif /* USE_CURSES */
168  ptr = buf;
169 
170  /* also check for 0 as offsets[] might be too small to hold all captured subpatterns */
171  while (pcre_exec(regex->re, regex->extra, ptr, strlen(ptr), 0, 0, offsets, offsets_size) >= 0) {
172  /* we have a match */
173  if (color >= 0) /* color the matching text */
174  word_highlight_string(row, (ptr - buf) + offsets[0], offsets[1] - offsets[0], color);
175  else
176  /* inverse the matching text */
177  highlight_string(row, (ptr - buf) + offsets[0], offsets[1] - offsets[0]);
178 
180 #ifdef USE_CURSES
181  screen_contents(row, 0, buf);
182 #endif /* USE_CURSES */
183  ptr += offsets[1] - 2;
184  } else
185  ptr += offsets[1];
186  }
187 }
t_config::wildcard
int wildcard
Definition: tinrc.h:155
_
#define _(Text)
Definition: tin.h:94
pcre_exec
int pcre_exec(const pcre *, const pcre_extra *, const char *, int, int, int, int *, int)
Definition: pcre_exec.c:3690
pcre_compile
pcre * pcre_compile(const char *, int, const char **, int *, const unsigned char *)
Definition: pcre_compile.c:5043
screen
struct t_screen * screen
Definition: screen.c:51
PCRE_CONFIG_UTF8
#define PCRE_CONFIG_UTF8
Definition: pcre.h:169
t_config::word_h_display_marks
int word_h_display_marks
Definition: tinrc.h:188
tinrc
struct t_config tinrc
Definition: init.c:191
FreeAndNull
#define FreeAndNull(p)
Definition: tin.h:2204
regex_cache::extra
pcre_extra * extra
Definition: tin.h:1919
tcurses.h
tin.h
PCRE_UTF8
#define PCRE_UTF8
Definition: pcre.h:109
pcre_config
int pcre_config(int, void *)
Definition: pcre_config.c:62
pcre_study
pcre_extra * pcre_study(const pcre *, int, const char **)
Definition: pcre_study.c:491
match_regex
t_bool match_regex(const char *string, char *pattern, struct regex_cache *cache, t_bool icase)
Definition: regex.c:59
txt_pcre_error_text
constext txt_pcre_error_text[]
Definition: lang.c:717
txt_pcre_error_at
constext txt_pcre_error_at[]
Definition: lang.c:715
buf
static char buf[16]
Definition: langinfo.c:50
ARRAY_SIZE
#define ARRAY_SIZE(array)
Definition: tin.h:2201
FreeIfNeeded
#define FreeIfNeeded(p)
Definition: tin.h:2203
PCRE_CASELESS
#define PCRE_CASELESS
Definition: pcre.h:98
LEN
#define LEN
Definition: tin.h:854
regex_cache::re
pcre * re
Definition: tin.h:1918
highlight_string
void highlight_string(int row, int col, int size)
Definition: curses.c:733
wildmat
t_bool wildmat(const char *text, char *p, t_bool icase)
Definition: wildmat.c:128
word_highlight_string
void word_highlight_string(int row, int col, int size, int color)
Definition: curses.c:774
PCRE_ERROR_NOMATCH
#define PCRE_ERROR_NOMATCH
Definition: pcre.h:125
t_screen::col
char * col
Definition: tin.h:1930
FALSE
#define FALSE
Definition: bool.h:70
regex_cache
Definition: tin.h:1917
error_message
void error_message(unsigned int sdelay, const char *fmt,...)
Definition: screen.c:184
compile_regex
t_bool compile_regex(const char *regex, struct regex_cache *cache, int options)
Definition: regex.c:111
IS_LOCAL_CHARSET
#define IS_LOCAL_CHARSET(c)
Definition: tin.h:776
t_bool
unsigned t_bool
Definition: bool.h:77
TRUE
#define TRUE
Definition: bool.h:74
txt_pcre_error_num
constext txt_pcre_error_num[]
Definition: lang.c:716
highlight_regexes
void highlight_regexes(int row, struct regex_cache *regex, int color)
Definition: regex.c:148