tin  2.6.1
About: TIN is a threaded NNTP and spool based UseNet newsreader.
  Fossies Dox: tin-2.6.1.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 : 2021-02-23
7 * Notes : Regular expression subroutines
8 * Credits :
9 *
10 * Copyright (c) 1997-2022 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 */
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, (int) 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 */
110t_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
123 pcre_config(PCRE_CONFIG_UTF8, &i);
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 */
147void
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, (int) 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, (int) ((ptr - buf) + offsets[0]), offsets[1] - offsets[0], color);
175 else
176 /* inverse the matching text */
177 highlight_string(row, (int) ((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}
unsigned t_bool
Definition: bool.h:77
#define TRUE
Definition: bool.h:74
#define FALSE
Definition: bool.h:70
constext txt_pcre_error_at[]
Definition: lang.c:726
constext txt_pcre_error_num[]
Definition: lang.c:727
constext txt_pcre_error_text[]
Definition: lang.c:728
struct t_config tinrc
Definition: init.c:192
struct t_screen * screen
Definition: screen.c:51
static char buf[16]
Definition: langinfo.c:50
void word_highlight_string(int row, int col, int size, int color)
Definition: curses.c:774
void error_message(unsigned int sdelay, const char *fmt,...)
Definition: screen.c:224
t_bool wildmat(const char *text, char *p, t_bool icase)
Definition: wildmat.c:128
void highlight_string(int row, int col, int size)
Definition: curses.c:733
t_bool match_regex(const char *string, char *pattern, struct regex_cache *cache, t_bool icase)
Definition: regex.c:59
t_bool compile_regex(const char *regex, struct regex_cache *cache, int options)
Definition: regex.c:111
void highlight_regexes(int row, struct regex_cache *regex, int color)
Definition: regex.c:148
pcre_extra * extra
Definition: tin.h:1963
pcre * re
Definition: tin.h:1962
int word_h_display_marks
Definition: tinrc.h:200
int wildcard
Definition: tinrc.h:167
char * col
Definition: tin.h:1974
#define LEN
Definition: tin.h:860
#define IS_LOCAL_CHARSET(c)
Definition: tin.h:782
#define ARRAY_SIZE(array)
Definition: tin.h:2250
#define FreeIfNeeded(p)
Definition: tin.h:2252
#define _(Text)
Definition: tin.h:94
#define FreeAndNull(p)
Definition: tin.h:2253