blob: 194a52e8a1290043fef37b6b53e0f1411006f119 [file] [log] [blame]
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +05301/****************************************************************************
Steve Kondikae271bc2015-11-15 02:50:53 +01002 * Copyright (c) 1998-2012,2015 Free Software Foundation, Inc. *
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +05303 * *
4 * Permission is hereby granted, free of charge, to any person obtaining a *
5 * copy of this software and associated documentation files (the *
6 * "Software"), to deal in the Software without restriction, including *
7 * without limitation the rights to use, copy, modify, merge, publish, *
8 * distribute, distribute with modifications, sublicense, and/or sell *
9 * copies of the Software, and to permit persons to whom the Software is *
10 * furnished to do so, subject to the following conditions: *
11 * *
12 * The above copyright notice and this permission notice shall be included *
13 * in all copies or substantial portions of the Software. *
14 * *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
18 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
21 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
22 * *
23 * Except as contained in this notice, the name(s) of the above copyright *
24 * holders shall not be used in advertising or otherwise to promote the *
25 * sale, use or other dealings in this Software without prior written *
26 * authorization. *
27 ****************************************************************************/
28
29/***************************************************************************
30* *
31* Author : Juergen Pfeifer *
32* *
33***************************************************************************/
34
35#include "form.priv.h"
36
Steve Kondikae271bc2015-11-15 02:50:53 +010037MODULE_ID("$Id: fty_regex.c,v 1.26 2015/01/10 17:10:25 tom Exp $")
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +053038
39#if HAVE_REGEX_H_FUNCS /* We prefer POSIX regex */
40#include <regex.h>
41
42typedef struct
43 {
44 regex_t *pRegExp;
45 unsigned long *refCount;
46 }
47RegExp_Arg;
48
49#elif HAVE_REGEXP_H_FUNCS | HAVE_REGEXPR_H_FUNCS
50#undef RETURN
51static int reg_errno;
52
53static char *
54RegEx_Init(char *instring)
55{
56 reg_errno = 0;
57 return instring;
58}
59
60static char *
61RegEx_Error(int code)
62{
63 reg_errno = code;
64 return 0;
65}
66
67#define INIT register char *sp = RegEx_Init(instring);
68#define GETC() (*sp++)
69#define PEEKC() (*sp)
70#define UNGETC(c) (--sp)
71#define RETURN(c) return(c)
72#define ERROR(c) return RegEx_Error(c)
73
74#if HAVE_REGEXP_H_FUNCS
75#include <regexp.h>
76#else
77#include <regexpr.h>
78#endif
79
80typedef struct
81{
82 char *compiled_expression;
83 unsigned long *refCount;
84}
85RegExp_Arg;
86
87/* Maximum Length we allow for a compiled regular expression */
88#define MAX_RX_LEN (2048)
89#define RX_INCREMENT (256)
90
91#endif
92
Steve Kondikae271bc2015-11-15 02:50:53 +010093#if HAVE_REGEX_H_FUNCS | HAVE_REGEXP_H_FUNCS | HAVE_REGEXPR_H_FUNCS
94# define MAYBE_UNUSED
95#else
96# define MAYBE_UNUSED GCC_UNUSED
97#endif
98
99/*---------------------------------------------------------------------------
100| Facility : libnform
101| Function : static void *Generic_RegularExpression_Type(void * arg)
102|
103| Description : Allocate structure for regex type argument.
104|
105| Return Values : Pointer to argument structure or NULL on error
106+--------------------------------------------------------------------------*/
107static void *
108Generic_RegularExpression_Type(void *arg MAYBE_UNUSED)
109{
110#if HAVE_REGEX_H_FUNCS
111 char *rx = (char *)arg;
112 RegExp_Arg *preg = (RegExp_Arg *)0;
113
114 if (rx)
115 {
116 preg = typeCalloc(RegExp_Arg, 1);
117
118 if (preg)
119 {
120 T((T_CREATE("RegExp_Arg %p"), (void *)preg));
121 if (((preg->pRegExp = typeMalloc(regex_t, 1)) != 0)
122 && !regcomp(preg->pRegExp, rx,
123 (REG_EXTENDED | REG_NOSUB | REG_NEWLINE)))
124 {
125 T((T_CREATE("regex_t %p"), (void *)preg->pRegExp));
126 if ((preg->refCount = typeMalloc(unsigned long, 1)) != 0)
127 *(preg->refCount) = 1;
128 }
129 else
130 {
131 if (preg->pRegExp)
132 free(preg->pRegExp);
133 free(preg);
134 preg = (RegExp_Arg *)0;
135 }
136 }
137 }
138 return ((void *)preg);
139#elif HAVE_REGEXP_H_FUNCS | HAVE_REGEXPR_H_FUNCS
140 char *rx = (char *)arg;
141 RegExp_Arg *pArg = (RegExp_Arg *)0;
142
143 if (rx)
144 {
145 pArg = typeMalloc(RegExp_Arg, 1);
146
147 if (pArg)
148 {
149 int blen = RX_INCREMENT;
150
151 T((T_CREATE("RegExp_Arg %p"), pArg));
152 pArg->compiled_expression = NULL;
153 if ((pArg->refCount = typeMalloc(unsigned long, 1)) != 0)
154 *(pArg->refCount) = 1;
155
156 do
157 {
158 char *buf = typeMalloc(char, blen);
159
160 if (buf)
161 {
162#if HAVE_REGEXP_H_FUNCS
163 char *last_pos = compile(rx, buf, &buf[blen], '\0');
164
165#else /* HAVE_REGEXPR_H_FUNCS */
166 char *last_pos = compile(rx, buf, &buf[blen]);
167#endif
168 if (reg_errno)
169 {
170 free(buf);
171 if (reg_errno == 50)
172 blen += RX_INCREMENT;
173 else
174 {
175 free(pArg);
176 pArg = NULL;
177 break;
178 }
179 }
180 else
181 {
182 pArg->compiled_expression = buf;
183 break;
184 }
185 }
186 }
187 while (blen <= MAX_RX_LEN);
188 }
189 if (pArg && !pArg->compiled_expression)
190 {
191 free(pArg);
192 pArg = NULL;
193 }
194 }
195 return (void *)pArg;
196#else
197 return 0;
198#endif
199}
200
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530201/*---------------------------------------------------------------------------
202| Facility : libnform
203| Function : static void *Make_RegularExpression_Type(va_list * ap)
204|
205| Description : Allocate structure for regex type argument.
206|
207| Return Values : Pointer to argument structure or NULL on error
208+--------------------------------------------------------------------------*/
209static void *
210Make_RegularExpression_Type(va_list *ap)
211{
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530212 char *rx = va_arg(*ap, char *);
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530213
Steve Kondikae271bc2015-11-15 02:50:53 +0100214 return Generic_RegularExpression_Type((void *)rx);
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530215}
216
217/*---------------------------------------------------------------------------
218| Facility : libnform
219| Function : static void *Copy_RegularExpression_Type(
220| const void * argp)
221|
222| Description : Copy structure for regex type argument.
223|
224| Return Values : Pointer to argument structure or NULL on error.
225+--------------------------------------------------------------------------*/
226static void *
Steve Kondikae271bc2015-11-15 02:50:53 +0100227Copy_RegularExpression_Type(const void *argp MAYBE_UNUSED)
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530228{
229#if (HAVE_REGEX_H_FUNCS | HAVE_REGEXP_H_FUNCS | HAVE_REGEXPR_H_FUNCS)
230 const RegExp_Arg *ap = (const RegExp_Arg *)argp;
231 const RegExp_Arg *result = (const RegExp_Arg *)0;
232
233 if (ap)
234 {
235 *(ap->refCount) += 1;
236 result = ap;
237 }
238 return (void *)result;
239#else
240 return 0;
241#endif
242}
243
244/*---------------------------------------------------------------------------
245| Facility : libnform
246| Function : static void Free_RegularExpression_Type(void * argp)
247|
248| Description : Free structure for regex type argument.
249|
250| Return Values : -
251+--------------------------------------------------------------------------*/
252static void
Steve Kondikae271bc2015-11-15 02:50:53 +0100253Free_RegularExpression_Type(void *argp MAYBE_UNUSED)
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530254{
255#if HAVE_REGEX_H_FUNCS | HAVE_REGEXP_H_FUNCS | HAVE_REGEXPR_H_FUNCS
256 RegExp_Arg *ap = (RegExp_Arg *)argp;
257
258 if (ap)
259 {
260 if (--(*(ap->refCount)) == 0)
261 {
262#if HAVE_REGEX_H_FUNCS
263 if (ap->pRegExp)
264 {
265 free(ap->refCount);
266 regfree(ap->pRegExp);
Steve Kondikae271bc2015-11-15 02:50:53 +0100267 free(ap->pRegExp);
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530268 }
269#elif HAVE_REGEXP_H_FUNCS | HAVE_REGEXPR_H_FUNCS
270 if (ap->compiled_expression)
271 {
272 free(ap->refCount);
273 free(ap->compiled_expression);
274 }
275#endif
276 free(ap);
277 }
278 }
279#endif
280}
281
282/*---------------------------------------------------------------------------
283| Facility : libnform
284| Function : static bool Check_RegularExpression_Field(
285| FIELD * field,
286| const void * argp)
287|
288| Description : Validate buffer content to be a valid regular expression
289|
290| Return Values : TRUE - field is valid
291| FALSE - field is invalid
292+--------------------------------------------------------------------------*/
293static bool
Steve Kondikae271bc2015-11-15 02:50:53 +0100294Check_RegularExpression_Field(FIELD *field MAYBE_UNUSED,
295 const void *argp MAYBE_UNUSED)
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530296{
297 bool match = FALSE;
298
299#if HAVE_REGEX_H_FUNCS
300 const RegExp_Arg *ap = (const RegExp_Arg *)argp;
301
302 if (ap && ap->pRegExp)
303 match = (regexec(ap->pRegExp, field_buffer(field, 0), 0, NULL, 0)
304 ? FALSE
305 : TRUE);
306#elif HAVE_REGEXP_H_FUNCS | HAVE_REGEXPR_H_FUNCS
307 RegExp_Arg *ap = (RegExp_Arg *)argp;
308
309 if (ap && ap->compiled_expression)
310 match = (step(field_buffer(field, 0), ap->compiled_expression)
311 ? TRUE
312 : FALSE);
313#endif
314 return match;
315}
316
317static FIELDTYPE typeREGEXP =
318{
319 _HAS_ARGS | _RESIDENT,
320 1, /* this is mutable, so we can't be const */
321 (FIELDTYPE *)0,
322 (FIELDTYPE *)0,
323 Make_RegularExpression_Type,
324 Copy_RegularExpression_Type,
325 Free_RegularExpression_Type,
Steve Kondikae271bc2015-11-15 02:50:53 +0100326 INIT_FT_FUNC(Check_RegularExpression_Field),
327 INIT_FT_FUNC(NULL),
328 INIT_FT_FUNC(NULL),
329 INIT_FT_FUNC(NULL),
330#if NCURSES_INTEROP_FUNCS
331 Generic_RegularExpression_Type
332#endif
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530333};
334
335NCURSES_EXPORT_VAR(FIELDTYPE*) TYPE_REGEXP = &typeREGEXP;
336
Steve Kondikae271bc2015-11-15 02:50:53 +0100337#if NCURSES_INTEROP_FUNCS
338/* The next routines are to simplify the use of ncurses from
339 programming languages with restictions on interop with C level
340 constructs (e.g. variable access or va_list + ellipsis constructs)
341*/
342NCURSES_EXPORT(FIELDTYPE *)
343_nc_TYPE_REGEXP(void)
344{
345 return TYPE_REGEXP;
346}
347#endif
348
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530349/* fty_regex.c ends here */