xref: /openbsd-src/lib/libform/fty_regex.c (revision a28daedfc357b214be5c701aa8ba8adb29a7f1c2)
1 /*	$OpenBSD: fty_regex.c,v 1.7 2001/01/22 18:02:17 millert Exp $	*/
2 
3 
4 /*
5  * THIS CODE IS SPECIFICALLY EXEMPTED FROM THE NCURSES PACKAGE COPYRIGHT.
6  * You may freely copy it for use as a template for your own field types.
7  * If you develop a field type that might be of general use, please send
8  * it back to the ncurses maintainers for inclusion in the next version.
9  */
10 /***************************************************************************
11 *                                                                          *
12 *  Author : Juergen Pfeifer, juergen.pfeifer@gmx.net                       *
13 *                                                                          *
14 ***************************************************************************/
15 
16 #include "form.priv.h"
17 
18 MODULE_ID("$From: fty_regex.c,v 1.15 2000/12/09 23:46:12 tom Exp $")
19 
20 #if HAVE_REGEX_H_FUNCS	/* We prefer POSIX regex */
21 #include <regex.h>
22 
23 typedef struct
24 {
25   regex_t *pRegExp;
26   unsigned long *refCount;
27 } RegExp_Arg;
28 
29 #elif HAVE_REGEXP_H_FUNCS | HAVE_REGEXPR_H_FUNCS
30 #undef RETURN
31 static int reg_errno;
32 
33 static char *RegEx_Init(char *instring)
34 {
35 	reg_errno = 0;
36 	return instring;
37 }
38 
39 static char *RegEx_Error(int code)
40 {
41 	reg_errno = code;
42 	return 0;
43 }
44 
45 #define INIT 		register char *sp = RegEx_Init(instring);
46 #define GETC()		(*sp++)
47 #define PEEKC()		(*sp)
48 #define UNGETC(c)	(--sp)
49 #define RETURN(c)	return(c)
50 #define ERROR(c)	return RegEx_Error(c)
51 
52 #if HAVE_REGEXP_H_FUNCS
53 #include <regexp.h>
54 #else
55 #include <regexpr.h>
56 #endif
57 
58 typedef struct
59 {
60   char *compiled_expression;
61   unsigned long *refCount;
62 } RegExp_Arg;
63 
64 /* Maximum Length we allow for a compiled regular expression */
65 #define MAX_RX_LEN   (2048)
66 #define RX_INCREMENT (256)
67 
68 #endif
69 
70 /*---------------------------------------------------------------------------
71 |   Facility      :  libnform
72 |   Function      :  static void *Make_RegularExpression_Type(va_list * ap)
73 |
74 |   Description   :  Allocate structure for regex type argument.
75 |
76 |   Return Values :  Pointer to argument structure or NULL on error
77 +--------------------------------------------------------------------------*/
78 static void *Make_RegularExpression_Type(va_list * ap)
79 {
80 #if HAVE_REGEX_H_FUNCS
81   char *rx = va_arg(*ap,char *);
82   RegExp_Arg *preg;
83 
84   preg = (RegExp_Arg*)malloc(sizeof(RegExp_Arg));
85   if (preg)
86     {
87       if (((preg->pRegExp = (regex_t*)malloc(sizeof(regex_t))) != (regex_t*)0)
88        && !regcomp(preg->pRegExp,rx,
89 		   (REG_EXTENDED | REG_NOSUB | REG_NEWLINE) ))
90 	{
91 	  preg->refCount = (unsigned long *)malloc(sizeof(unsigned long));
92 	  *(preg->refCount) = 1;
93 	}
94       else
95 	{
96 	  if (preg->pRegExp)
97 	    free(preg->pRegExp);
98 	  free(preg);
99 	  preg = (RegExp_Arg*)0;
100 	}
101     }
102   return((void *)preg);
103 #elif HAVE_REGEXP_H_FUNCS | HAVE_REGEXPR_H_FUNCS
104   char *rx = va_arg(*ap,char *);
105   RegExp_Arg *pArg;
106 
107   pArg = (RegExp_Arg *)malloc(sizeof(RegExp_Arg));
108 
109   if (pArg)
110     {
111       int blen = RX_INCREMENT;
112       pArg->compiled_expression = NULL;
113       pArg->refCount = (unsigned long *)malloc(sizeof(unsigned long));
114       *(pArg->refCount) = 1;
115 
116       do {
117 	char *buf = (char *)malloc(blen);
118 	if (buf)
119 	  {
120 #if HAVE_REGEXP_H_FUNCS
121 	    char *last_pos = compile (rx, buf, &buf[blen], '\0');
122 #else /* HAVE_REGEXPR_H_FUNCS */
123 	    char *last_pos = compile (rx, buf, &buf[blen]);
124 #endif
125 	    if (reg_errno)
126 	      {
127 		free(buf);
128 		if (reg_errno==50)
129 		  blen += RX_INCREMENT;
130 		else
131 		  {
132 		    free(pArg);
133 		    pArg = NULL;
134 		    break;
135 		  }
136 	      }
137 	    else
138 	      {
139 		pArg->compiled_expression = buf;
140 		break;
141 	      }
142 	  }
143       } while( blen <= MAX_RX_LEN );
144     }
145   if (pArg && !pArg->compiled_expression)
146     {
147       free(pArg);
148       pArg = NULL;
149     }
150   return (void *)pArg;
151 #else
152   return 0;
153 #endif
154 }
155 
156 /*---------------------------------------------------------------------------
157 |   Facility      :  libnform
158 |   Function      :  static void *Copy_RegularExpression_Type(
159 |                                      const void * argp)
160 |
161 |   Description   :  Copy structure for regex type argument.
162 |
163 |   Return Values :  Pointer to argument structure or NULL on error.
164 +--------------------------------------------------------------------------*/
165 static void *Copy_RegularExpression_Type(const void * argp)
166 {
167 #if (HAVE_REGEX_H_FUNCS | HAVE_REGEXP_H_FUNCS | HAVE_REGEXPR_H_FUNCS)
168   const RegExp_Arg *ap = (const RegExp_Arg *)argp;
169   const RegExp_Arg *result = (const RegExp_Arg *)0;
170 
171   if (ap)
172     {
173       *(ap->refCount) += 1;
174       result = ap;
175     }
176   return (void *)result;
177 #else
178   return 0;
179 #endif
180 }
181 
182 /*---------------------------------------------------------------------------
183 |   Facility      :  libnform
184 |   Function      :  static void Free_RegularExpression_Type(void * argp)
185 |
186 |   Description   :  Free structure for regex type argument.
187 |
188 |   Return Values :  -
189 +--------------------------------------------------------------------------*/
190 static void Free_RegularExpression_Type(void * argp)
191 {
192 #if HAVE_REGEX_H_FUNCS | HAVE_REGEXP_H_FUNCS | HAVE_REGEXPR_H_FUNCS
193   RegExp_Arg *ap = (RegExp_Arg *)argp;
194   if (ap)
195     {
196       if (--(*(ap->refCount)) == 0)
197 	{
198 #if HAVE_REGEX_H_FUNCS
199 	  if (ap->pRegExp)
200 	    {
201 	      free(ap->refCount);
202 	      regfree(ap->pRegExp);
203 	    }
204 #elif HAVE_REGEXP_H_FUNCS | HAVE_REGEXPR_H_FUNCS
205 	  if (ap->compiled_expression)
206 	    {
207 	      free(ap->refCount);
208 	      free(ap->compiled_expression);
209 	    }
210 #endif
211 	  free(ap);
212 	}
213     }
214 #endif
215 }
216 
217 /*---------------------------------------------------------------------------
218 |   Facility      :  libnform
219 |   Function      :  static bool Check_RegularExpression_Field(
220 |                                      FIELD * field,
221 |                                      const void  * argp)
222 |
223 |   Description   :  Validate buffer content to be a valid regular expression
224 |
225 |   Return Values :  TRUE  - field is valid
226 |                    FALSE - field is invalid
227 +--------------------------------------------------------------------------*/
228 static bool Check_RegularExpression_Field(FIELD * field, const void  * argp)
229 {
230   bool match = FALSE;
231 #if HAVE_REGEX_H_FUNCS
232   const RegExp_Arg *ap = (const RegExp_Arg*)argp;
233   if (ap && ap->pRegExp)
234     match = (regexec(ap->pRegExp,field_buffer(field,0),0,NULL,0) ? FALSE:TRUE);
235 #elif HAVE_REGEXP_H_FUNCS | HAVE_REGEXPR_H_FUNCS
236   RegExp_Arg *ap = (RegExp_Arg *)argp;
237   if (ap && ap->compiled_expression)
238     match = (step(field_buffer(field,0),ap->compiled_expression) ? TRUE:FALSE);
239 #endif
240   return match;
241 }
242 
243 static FIELDTYPE typeREGEXP = {
244   _HAS_ARGS | _RESIDENT,
245   1,                           /* this is mutable, so we can't be const */
246   (FIELDTYPE *)0,
247   (FIELDTYPE *)0,
248   Make_RegularExpression_Type,
249   Copy_RegularExpression_Type,
250   Free_RegularExpression_Type,
251   Check_RegularExpression_Field,
252   NULL,
253   NULL,
254   NULL
255 };
256 
257 NCURSES_EXPORT_VAR(FIELDTYPE*) TYPE_REGEXP = &typeREGEXP;
258 
259 /* fty_regex.c ends here */
260