1 /****************************************************************************
2 * Copyright (c) 1998-2010,2012 Free Software Foundation, Inc. *
3 * *
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
37 MODULE_ID("$Id: fty_regex.c,v 1.25 2012/10/27 20:12:53 tom Exp $")
38
39 #if HAVE_REGEX_H_FUNCS /* We prefer POSIX regex */
40 #include <regex.h>
41
42 typedef struct
43 {
44 regex_t *pRegExp;
45 unsigned long *refCount;
46 }
47 RegExp_Arg;
48
49 #elif HAVE_REGEXP_H_FUNCS | HAVE_REGEXPR_H_FUNCS
50 #undef RETURN
51 static int reg_errno;
52
53 static char *
54 RegEx_Init(char *instring)
55 {
56 reg_errno = 0;
57 return instring;
58 }
59
60 static char *
61 RegEx_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
80 typedef struct
81 {
82 char *compiled_expression;
83 unsigned long *refCount;
84 }
85 RegExp_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
93 #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 +--------------------------------------------------------------------------*/
107 static void *
Generic_RegularExpression_Type(void * arg MAYBE_UNUSED)108 Generic_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 = typeMalloc(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
201 /*---------------------------------------------------------------------------
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 +--------------------------------------------------------------------------*/
209 static void *
Make_RegularExpression_Type(va_list * ap)210 Make_RegularExpression_Type(va_list *ap)
211 {
212 char *rx = va_arg(*ap, char *);
213
214 return Generic_RegularExpression_Type((void *)rx);
215 }
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 +--------------------------------------------------------------------------*/
226 static void *
Copy_RegularExpression_Type(const void * argp MAYBE_UNUSED)227 Copy_RegularExpression_Type(const void *argp MAYBE_UNUSED)
228 {
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 +--------------------------------------------------------------------------*/
252 static void
Free_RegularExpression_Type(void * argp MAYBE_UNUSED)253 Free_RegularExpression_Type(void *argp MAYBE_UNUSED)
254 {
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);
267 }
268 #elif HAVE_REGEXP_H_FUNCS | HAVE_REGEXPR_H_FUNCS
269 if (ap->compiled_expression)
270 {
271 free(ap->refCount);
272 free(ap->compiled_expression);
273 }
274 #endif
275 free(ap);
276 }
277 }
278 #endif
279 }
280
281 /*---------------------------------------------------------------------------
282 | Facility : libnform
283 | Function : static bool Check_RegularExpression_Field(
284 | FIELD * field,
285 | const void * argp)
286 |
287 | Description : Validate buffer content to be a valid regular expression
288 |
289 | Return Values : TRUE - field is valid
290 | FALSE - field is invalid
291 +--------------------------------------------------------------------------*/
292 static bool
Check_RegularExpression_Field(FIELD * field MAYBE_UNUSED,const void * argp MAYBE_UNUSED)293 Check_RegularExpression_Field(FIELD *field MAYBE_UNUSED,
294 const void *argp MAYBE_UNUSED)
295 {
296 bool match = FALSE;
297
298 #if HAVE_REGEX_H_FUNCS
299 const RegExp_Arg *ap = (const RegExp_Arg *)argp;
300
301 if (ap && ap->pRegExp)
302 match = (regexec(ap->pRegExp, field_buffer(field, 0), 0, NULL, 0)
303 ? FALSE
304 : TRUE);
305 #elif HAVE_REGEXP_H_FUNCS | HAVE_REGEXPR_H_FUNCS
306 RegExp_Arg *ap = (RegExp_Arg *)argp;
307
308 if (ap && ap->compiled_expression)
309 match = (step(field_buffer(field, 0), ap->compiled_expression)
310 ? TRUE
311 : FALSE);
312 #endif
313 return match;
314 }
315
316 static FIELDTYPE typeREGEXP =
317 {
318 _HAS_ARGS | _RESIDENT,
319 1, /* this is mutable, so we can't be const */
320 (FIELDTYPE *)0,
321 (FIELDTYPE *)0,
322 Make_RegularExpression_Type,
323 Copy_RegularExpression_Type,
324 Free_RegularExpression_Type,
325 INIT_FT_FUNC(Check_RegularExpression_Field),
326 INIT_FT_FUNC(NULL),
327 INIT_FT_FUNC(NULL),
328 INIT_FT_FUNC(NULL),
329 #if NCURSES_INTEROP_FUNCS
330 Generic_RegularExpression_Type
331 #endif
332 };
333
334 NCURSES_EXPORT_VAR(FIELDTYPE*) TYPE_REGEXP = &typeREGEXP;
335
336 #if NCURSES_INTEROP_FUNCS
337 /* The next routines are to simplify the use of ncurses from
338 programming languages with restictions on interop with C level
339 constructs (e.g. variable access or va_list + ellipsis constructs)
340 */
341 NCURSES_EXPORT(FIELDTYPE *)
_nc_TYPE_REGEXP(void)342 _nc_TYPE_REGEXP(void)
343 {
344 return TYPE_REGEXP;
345 }
346 #endif
347
348 /* fty_regex.c ends here */
349