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