ure.c revision 1.1.1.1.2.2 1 1.1.1.1.2.2 yamt /* $OpenLDAP: pkg/ldap/libraries/liblunicode/ure/ure.c,v 1.17.2.3 2008/02/11 23:26:42 kurt Exp $ */
2 1.1.1.1.2.2 yamt /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3 1.1.1.1.2.2 yamt *
4 1.1.1.1.2.2 yamt * Copyright 1998-2008 The OpenLDAP Foundation.
5 1.1.1.1.2.2 yamt * All rights reserved.
6 1.1.1.1.2.2 yamt *
7 1.1.1.1.2.2 yamt * Redistribution and use in source and binary forms, with or without
8 1.1.1.1.2.2 yamt * modification, are permitted only as authorized by the OpenLDAP
9 1.1.1.1.2.2 yamt * Public License.
10 1.1.1.1.2.2 yamt *
11 1.1.1.1.2.2 yamt * A copy of this license is available in file LICENSE in the
12 1.1.1.1.2.2 yamt * top-level directory of the distribution or, alternatively, at
13 1.1.1.1.2.2 yamt * <http://www.OpenLDAP.org/license.html>.
14 1.1.1.1.2.2 yamt */
15 1.1.1.1.2.2 yamt /* Copyright 1997, 1998, 1999 Computing Research Labs,
16 1.1.1.1.2.2 yamt * New Mexico State University
17 1.1.1.1.2.2 yamt *
18 1.1.1.1.2.2 yamt * Permission is hereby granted, free of charge, to any person obtaining a
19 1.1.1.1.2.2 yamt * copy of this software and associated documentation files (the "Software"),
20 1.1.1.1.2.2 yamt * to deal in the Software without restriction, including without limitation
21 1.1.1.1.2.2 yamt * the rights to use, copy, modify, merge, publish, distribute, sublicense,
22 1.1.1.1.2.2 yamt * and/or sell copies of the Software, and to permit persons to whom the
23 1.1.1.1.2.2 yamt * Software is furnished to do so, subject to the following conditions:
24 1.1.1.1.2.2 yamt *
25 1.1.1.1.2.2 yamt * The above copyright notice and this permission notice shall be included in
26 1.1.1.1.2.2 yamt * all copies or substantial portions of the Software.
27 1.1.1.1.2.2 yamt *
28 1.1.1.1.2.2 yamt * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
29 1.1.1.1.2.2 yamt * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
30 1.1.1.1.2.2 yamt * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
31 1.1.1.1.2.2 yamt * THE COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY
32 1.1.1.1.2.2 yamt * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
33 1.1.1.1.2.2 yamt * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
34 1.1.1.1.2.2 yamt * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 1.1.1.1.2.2 yamt */
36 1.1.1.1.2.2 yamt /* $Id: ure.c,v 1.1.1.1.2.2 2008/06/04 02:04:02 yamt Exp $" */
37 1.1.1.1.2.2 yamt
38 1.1.1.1.2.2 yamt #include "portable.h"
39 1.1.1.1.2.2 yamt
40 1.1.1.1.2.2 yamt #include <ac/stdlib.h>
41 1.1.1.1.2.2 yamt #include <ac/string.h>
42 1.1.1.1.2.2 yamt #include <ac/unistd.h>
43 1.1.1.1.2.2 yamt
44 1.1.1.1.2.2 yamt #include "ure.h"
45 1.1.1.1.2.2 yamt
46 1.1.1.1.2.2 yamt /*
47 1.1.1.1.2.2 yamt * Flags used internally in the DFA.
48 1.1.1.1.2.2 yamt */
49 1.1.1.1.2.2 yamt #define _URE_DFA_CASEFOLD 0x01
50 1.1.1.1.2.2 yamt #define _URE_DFA_BLANKLINE 0x02
51 1.1.1.1.2.2 yamt
52 1.1.1.1.2.2 yamt static unsigned long cclass_flags[] = {
53 1.1.1.1.2.2 yamt 0,
54 1.1.1.1.2.2 yamt _URE_NONSPACING,
55 1.1.1.1.2.2 yamt _URE_COMBINING,
56 1.1.1.1.2.2 yamt _URE_NUMDIGIT,
57 1.1.1.1.2.2 yamt _URE_NUMOTHER,
58 1.1.1.1.2.2 yamt _URE_SPACESEP,
59 1.1.1.1.2.2 yamt _URE_LINESEP,
60 1.1.1.1.2.2 yamt _URE_PARASEP,
61 1.1.1.1.2.2 yamt _URE_CNTRL,
62 1.1.1.1.2.2 yamt _URE_PUA,
63 1.1.1.1.2.2 yamt _URE_UPPER,
64 1.1.1.1.2.2 yamt _URE_LOWER,
65 1.1.1.1.2.2 yamt _URE_TITLE,
66 1.1.1.1.2.2 yamt _URE_MODIFIER,
67 1.1.1.1.2.2 yamt _URE_OTHERLETTER,
68 1.1.1.1.2.2 yamt _URE_DASHPUNCT,
69 1.1.1.1.2.2 yamt _URE_OPENPUNCT,
70 1.1.1.1.2.2 yamt _URE_CLOSEPUNCT,
71 1.1.1.1.2.2 yamt _URE_OTHERPUNCT,
72 1.1.1.1.2.2 yamt _URE_MATHSYM,
73 1.1.1.1.2.2 yamt _URE_CURRENCYSYM,
74 1.1.1.1.2.2 yamt _URE_OTHERSYM,
75 1.1.1.1.2.2 yamt _URE_LTR,
76 1.1.1.1.2.2 yamt _URE_RTL,
77 1.1.1.1.2.2 yamt _URE_EURONUM,
78 1.1.1.1.2.2 yamt _URE_EURONUMSEP,
79 1.1.1.1.2.2 yamt _URE_EURONUMTERM,
80 1.1.1.1.2.2 yamt _URE_ARABNUM,
81 1.1.1.1.2.2 yamt _URE_COMMONSEP,
82 1.1.1.1.2.2 yamt _URE_BLOCKSEP,
83 1.1.1.1.2.2 yamt _URE_SEGMENTSEP,
84 1.1.1.1.2.2 yamt _URE_WHITESPACE,
85 1.1.1.1.2.2 yamt _URE_OTHERNEUT,
86 1.1.1.1.2.2 yamt };
87 1.1.1.1.2.2 yamt
88 1.1.1.1.2.2 yamt /*
89 1.1.1.1.2.2 yamt * Symbol types for the DFA.
90 1.1.1.1.2.2 yamt */
91 1.1.1.1.2.2 yamt #define _URE_ANY_CHAR 1
92 1.1.1.1.2.2 yamt #define _URE_CHAR 2
93 1.1.1.1.2.2 yamt #define _URE_CCLASS 3
94 1.1.1.1.2.2 yamt #define _URE_NCCLASS 4
95 1.1.1.1.2.2 yamt #define _URE_BOL_ANCHOR 5
96 1.1.1.1.2.2 yamt #define _URE_EOL_ANCHOR 6
97 1.1.1.1.2.2 yamt
98 1.1.1.1.2.2 yamt /*
99 1.1.1.1.2.2 yamt * Op codes for converting the NFA to a DFA.
100 1.1.1.1.2.2 yamt */
101 1.1.1.1.2.2 yamt #define _URE_SYMBOL 10
102 1.1.1.1.2.2 yamt #define _URE_PAREN 11
103 1.1.1.1.2.2 yamt #define _URE_QUEST 12
104 1.1.1.1.2.2 yamt #define _URE_STAR 13
105 1.1.1.1.2.2 yamt #define _URE_PLUS 14
106 1.1.1.1.2.2 yamt #define _URE_ONE 15
107 1.1.1.1.2.2 yamt #define _URE_AND 16
108 1.1.1.1.2.2 yamt #define _URE_OR 17
109 1.1.1.1.2.2 yamt
110 1.1.1.1.2.2 yamt #define _URE_NOOP 0xffff
111 1.1.1.1.2.2 yamt
112 1.1.1.1.2.2 yamt #define _URE_REGSTART 0x8000
113 1.1.1.1.2.2 yamt #define _URE_REGEND 0x4000
114 1.1.1.1.2.2 yamt
115 1.1.1.1.2.2 yamt /*
116 1.1.1.1.2.2 yamt * Structure used to handle a compacted range of characters.
117 1.1.1.1.2.2 yamt */
118 1.1.1.1.2.2 yamt typedef struct {
119 1.1.1.1.2.2 yamt ucs4_t min_code;
120 1.1.1.1.2.2 yamt ucs4_t max_code;
121 1.1.1.1.2.2 yamt } _ure_range_t;
122 1.1.1.1.2.2 yamt
123 1.1.1.1.2.2 yamt typedef struct {
124 1.1.1.1.2.2 yamt _ure_range_t *ranges;
125 1.1.1.1.2.2 yamt ucs2_t ranges_used;
126 1.1.1.1.2.2 yamt ucs2_t ranges_size;
127 1.1.1.1.2.2 yamt } _ure_ccl_t;
128 1.1.1.1.2.2 yamt
129 1.1.1.1.2.2 yamt typedef union {
130 1.1.1.1.2.2 yamt ucs4_t chr;
131 1.1.1.1.2.2 yamt _ure_ccl_t ccl;
132 1.1.1.1.2.2 yamt } _ure_sym_t;
133 1.1.1.1.2.2 yamt
134 1.1.1.1.2.2 yamt /*
135 1.1.1.1.2.2 yamt * This is a general element structure used for expressions and stack
136 1.1.1.1.2.2 yamt * elements.
137 1.1.1.1.2.2 yamt */
138 1.1.1.1.2.2 yamt typedef struct {
139 1.1.1.1.2.2 yamt ucs2_t reg;
140 1.1.1.1.2.2 yamt ucs2_t onstack;
141 1.1.1.1.2.2 yamt ucs2_t type;
142 1.1.1.1.2.2 yamt ucs2_t lhs;
143 1.1.1.1.2.2 yamt ucs2_t rhs;
144 1.1.1.1.2.2 yamt } _ure_elt_t;
145 1.1.1.1.2.2 yamt
146 1.1.1.1.2.2 yamt /*
147 1.1.1.1.2.2 yamt * This is a structure used to track a list or a stack of states.
148 1.1.1.1.2.2 yamt */
149 1.1.1.1.2.2 yamt typedef struct {
150 1.1.1.1.2.2 yamt ucs2_t *slist;
151 1.1.1.1.2.2 yamt ucs2_t slist_size;
152 1.1.1.1.2.2 yamt ucs2_t slist_used;
153 1.1.1.1.2.2 yamt } _ure_stlist_t;
154 1.1.1.1.2.2 yamt
155 1.1.1.1.2.2 yamt /*
156 1.1.1.1.2.2 yamt * Structure to track the list of unique states for a symbol
157 1.1.1.1.2.2 yamt * during reduction.
158 1.1.1.1.2.2 yamt */
159 1.1.1.1.2.2 yamt typedef struct {
160 1.1.1.1.2.2 yamt ucs2_t id;
161 1.1.1.1.2.2 yamt ucs2_t type;
162 1.1.1.1.2.2 yamt unsigned long mods;
163 1.1.1.1.2.2 yamt unsigned long props;
164 1.1.1.1.2.2 yamt _ure_sym_t sym;
165 1.1.1.1.2.2 yamt _ure_stlist_t states;
166 1.1.1.1.2.2 yamt } _ure_symtab_t;
167 1.1.1.1.2.2 yamt
168 1.1.1.1.2.2 yamt /*
169 1.1.1.1.2.2 yamt * Structure to hold a single state.
170 1.1.1.1.2.2 yamt */
171 1.1.1.1.2.2 yamt typedef struct {
172 1.1.1.1.2.2 yamt ucs2_t id;
173 1.1.1.1.2.2 yamt ucs2_t accepting;
174 1.1.1.1.2.2 yamt ucs2_t pad;
175 1.1.1.1.2.2 yamt _ure_stlist_t st;
176 1.1.1.1.2.2 yamt _ure_elt_t *trans;
177 1.1.1.1.2.2 yamt ucs2_t trans_size;
178 1.1.1.1.2.2 yamt ucs2_t trans_used;
179 1.1.1.1.2.2 yamt } _ure_state_t;
180 1.1.1.1.2.2 yamt
181 1.1.1.1.2.2 yamt /*
182 1.1.1.1.2.2 yamt * Structure used for keeping lists of states.
183 1.1.1.1.2.2 yamt */
184 1.1.1.1.2.2 yamt typedef struct {
185 1.1.1.1.2.2 yamt _ure_state_t *states;
186 1.1.1.1.2.2 yamt ucs2_t states_size;
187 1.1.1.1.2.2 yamt ucs2_t states_used;
188 1.1.1.1.2.2 yamt } _ure_statetable_t;
189 1.1.1.1.2.2 yamt
190 1.1.1.1.2.2 yamt /*
191 1.1.1.1.2.2 yamt * Structure to track pairs of DFA states when equivalent states are
192 1.1.1.1.2.2 yamt * merged.
193 1.1.1.1.2.2 yamt */
194 1.1.1.1.2.2 yamt typedef struct {
195 1.1.1.1.2.2 yamt ucs2_t l;
196 1.1.1.1.2.2 yamt ucs2_t r;
197 1.1.1.1.2.2 yamt } _ure_equiv_t;
198 1.1.1.1.2.2 yamt
199 1.1.1.1.2.2 yamt /*
200 1.1.1.1.2.2 yamt * Structure used for constructing the NFA and reducing to a minimal DFA.
201 1.1.1.1.2.2 yamt */
202 1.1.1.1.2.2 yamt typedef struct _ure_buffer_t {
203 1.1.1.1.2.2 yamt int reducing;
204 1.1.1.1.2.2 yamt int error;
205 1.1.1.1.2.2 yamt unsigned long flags;
206 1.1.1.1.2.2 yamt
207 1.1.1.1.2.2 yamt _ure_stlist_t stack;
208 1.1.1.1.2.2 yamt
209 1.1.1.1.2.2 yamt /*
210 1.1.1.1.2.2 yamt * Table of unique symbols encountered.
211 1.1.1.1.2.2 yamt */
212 1.1.1.1.2.2 yamt _ure_symtab_t *symtab;
213 1.1.1.1.2.2 yamt ucs2_t symtab_size;
214 1.1.1.1.2.2 yamt ucs2_t symtab_used;
215 1.1.1.1.2.2 yamt
216 1.1.1.1.2.2 yamt /*
217 1.1.1.1.2.2 yamt * Tracks the unique expressions generated for the NFA and when the NFA is
218 1.1.1.1.2.2 yamt * reduced.
219 1.1.1.1.2.2 yamt */
220 1.1.1.1.2.2 yamt _ure_elt_t *expr;
221 1.1.1.1.2.2 yamt ucs2_t expr_used;
222 1.1.1.1.2.2 yamt ucs2_t expr_size;
223 1.1.1.1.2.2 yamt
224 1.1.1.1.2.2 yamt /*
225 1.1.1.1.2.2 yamt * The reduced table of unique groups of NFA states.
226 1.1.1.1.2.2 yamt */
227 1.1.1.1.2.2 yamt _ure_statetable_t states;
228 1.1.1.1.2.2 yamt
229 1.1.1.1.2.2 yamt /*
230 1.1.1.1.2.2 yamt * Tracks states when equivalent states are merged.
231 1.1.1.1.2.2 yamt */
232 1.1.1.1.2.2 yamt _ure_equiv_t *equiv;
233 1.1.1.1.2.2 yamt ucs2_t equiv_used;
234 1.1.1.1.2.2 yamt ucs2_t equiv_size;
235 1.1.1.1.2.2 yamt } _ure_buffer_t;
236 1.1.1.1.2.2 yamt
237 1.1.1.1.2.2 yamt typedef struct {
238 1.1.1.1.2.2 yamt ucs2_t symbol;
239 1.1.1.1.2.2 yamt ucs2_t next_state;
240 1.1.1.1.2.2 yamt } _ure_trans_t;
241 1.1.1.1.2.2 yamt
242 1.1.1.1.2.2 yamt typedef struct {
243 1.1.1.1.2.2 yamt ucs2_t accepting;
244 1.1.1.1.2.2 yamt ucs2_t ntrans;
245 1.1.1.1.2.2 yamt _ure_trans_t *trans;
246 1.1.1.1.2.2 yamt } _ure_dstate_t;
247 1.1.1.1.2.2 yamt
248 1.1.1.1.2.2 yamt typedef struct _ure_dfa_t {
249 1.1.1.1.2.2 yamt unsigned long flags;
250 1.1.1.1.2.2 yamt
251 1.1.1.1.2.2 yamt _ure_symtab_t *syms;
252 1.1.1.1.2.2 yamt ucs2_t nsyms;
253 1.1.1.1.2.2 yamt
254 1.1.1.1.2.2 yamt _ure_dstate_t *states;
255 1.1.1.1.2.2 yamt ucs2_t nstates;
256 1.1.1.1.2.2 yamt
257 1.1.1.1.2.2 yamt _ure_trans_t *trans;
258 1.1.1.1.2.2 yamt ucs2_t ntrans;
259 1.1.1.1.2.2 yamt } _ure_dfa_t;
260 1.1.1.1.2.2 yamt
261 1.1.1.1.2.2 yamt /*************************************************************************
262 1.1.1.1.2.2 yamt *
263 1.1.1.1.2.2 yamt * Functions.
264 1.1.1.1.2.2 yamt *
265 1.1.1.1.2.2 yamt *************************************************************************/
266 1.1.1.1.2.2 yamt
267 1.1.1.1.2.2 yamt static void
268 1.1.1.1.2.2 yamt _ure_memmove(char *dest, char *src, unsigned long bytes)
269 1.1.1.1.2.2 yamt {
270 1.1.1.1.2.2 yamt long i, j;
271 1.1.1.1.2.2 yamt
272 1.1.1.1.2.2 yamt i = (long) bytes;
273 1.1.1.1.2.2 yamt j = i & 7;
274 1.1.1.1.2.2 yamt i = (i + 7) >> 3;
275 1.1.1.1.2.2 yamt
276 1.1.1.1.2.2 yamt /*
277 1.1.1.1.2.2 yamt * Do a memmove using Ye Olde Duff's Device for efficiency.
278 1.1.1.1.2.2 yamt */
279 1.1.1.1.2.2 yamt if (src < dest) {
280 1.1.1.1.2.2 yamt src += bytes;
281 1.1.1.1.2.2 yamt dest += bytes;
282 1.1.1.1.2.2 yamt
283 1.1.1.1.2.2 yamt switch (j) {
284 1.1.1.1.2.2 yamt case 0: do {
285 1.1.1.1.2.2 yamt *--dest = *--src;
286 1.1.1.1.2.2 yamt case 7: *--dest = *--src;
287 1.1.1.1.2.2 yamt case 6: *--dest = *--src;
288 1.1.1.1.2.2 yamt case 5: *--dest = *--src;
289 1.1.1.1.2.2 yamt case 4: *--dest = *--src;
290 1.1.1.1.2.2 yamt case 3: *--dest = *--src;
291 1.1.1.1.2.2 yamt case 2: *--dest = *--src;
292 1.1.1.1.2.2 yamt case 1: *--dest = *--src;
293 1.1.1.1.2.2 yamt } while (--i > 0);
294 1.1.1.1.2.2 yamt }
295 1.1.1.1.2.2 yamt } else if (src > dest) {
296 1.1.1.1.2.2 yamt switch (j) {
297 1.1.1.1.2.2 yamt case 0: do {
298 1.1.1.1.2.2 yamt *dest++ = *src++;
299 1.1.1.1.2.2 yamt case 7: *dest++ = *src++;
300 1.1.1.1.2.2 yamt case 6: *dest++ = *src++;
301 1.1.1.1.2.2 yamt case 5: *dest++ = *src++;
302 1.1.1.1.2.2 yamt case 4: *dest++ = *src++;
303 1.1.1.1.2.2 yamt case 3: *dest++ = *src++;
304 1.1.1.1.2.2 yamt case 2: *dest++ = *src++;
305 1.1.1.1.2.2 yamt case 1: *dest++ = *src++;
306 1.1.1.1.2.2 yamt } while (--i > 0);
307 1.1.1.1.2.2 yamt }
308 1.1.1.1.2.2 yamt }
309 1.1.1.1.2.2 yamt }
310 1.1.1.1.2.2 yamt
311 1.1.1.1.2.2 yamt static void
312 1.1.1.1.2.2 yamt _ure_push(ucs2_t v, _ure_buffer_t *b)
313 1.1.1.1.2.2 yamt {
314 1.1.1.1.2.2 yamt _ure_stlist_t *s;
315 1.1.1.1.2.2 yamt
316 1.1.1.1.2.2 yamt if (b == 0)
317 1.1.1.1.2.2 yamt return;
318 1.1.1.1.2.2 yamt
319 1.1.1.1.2.2 yamt /*
320 1.1.1.1.2.2 yamt * If the `reducing' parameter is non-zero, check to see if the value
321 1.1.1.1.2.2 yamt * passed is already on the stack.
322 1.1.1.1.2.2 yamt */
323 1.1.1.1.2.2 yamt if (b->reducing != 0 && b->expr[v].onstack != 0)
324 1.1.1.1.2.2 yamt return;
325 1.1.1.1.2.2 yamt
326 1.1.1.1.2.2 yamt s = &b->stack;
327 1.1.1.1.2.2 yamt if (s->slist_used == s->slist_size) {
328 1.1.1.1.2.2 yamt if (s->slist_size == 0)
329 1.1.1.1.2.2 yamt s->slist = (ucs2_t *) malloc(sizeof(ucs2_t) << 3);
330 1.1.1.1.2.2 yamt else
331 1.1.1.1.2.2 yamt s->slist = (ucs2_t *) realloc((char *) s->slist,
332 1.1.1.1.2.2 yamt sizeof(ucs2_t) * (s->slist_size + 8));
333 1.1.1.1.2.2 yamt s->slist_size += 8;
334 1.1.1.1.2.2 yamt }
335 1.1.1.1.2.2 yamt s->slist[s->slist_used++] = v;
336 1.1.1.1.2.2 yamt
337 1.1.1.1.2.2 yamt /*
338 1.1.1.1.2.2 yamt * If the `reducing' parameter is non-zero, flag the element as being on
339 1.1.1.1.2.2 yamt * the stack.
340 1.1.1.1.2.2 yamt */
341 1.1.1.1.2.2 yamt if (b->reducing != 0)
342 1.1.1.1.2.2 yamt b->expr[v].onstack = 1;
343 1.1.1.1.2.2 yamt }
344 1.1.1.1.2.2 yamt
345 1.1.1.1.2.2 yamt static ucs2_t
346 1.1.1.1.2.2 yamt _ure_peek(_ure_buffer_t *b)
347 1.1.1.1.2.2 yamt {
348 1.1.1.1.2.2 yamt if (b == 0 || b->stack.slist_used == 0)
349 1.1.1.1.2.2 yamt return _URE_NOOP;
350 1.1.1.1.2.2 yamt
351 1.1.1.1.2.2 yamt return b->stack.slist[b->stack.slist_used - 1];
352 1.1.1.1.2.2 yamt }
353 1.1.1.1.2.2 yamt
354 1.1.1.1.2.2 yamt static ucs2_t
355 1.1.1.1.2.2 yamt _ure_pop(_ure_buffer_t *b)
356 1.1.1.1.2.2 yamt {
357 1.1.1.1.2.2 yamt ucs2_t v;
358 1.1.1.1.2.2 yamt
359 1.1.1.1.2.2 yamt if (b == 0 || b->stack.slist_used == 0)
360 1.1.1.1.2.2 yamt return _URE_NOOP;
361 1.1.1.1.2.2 yamt
362 1.1.1.1.2.2 yamt v = b->stack.slist[--b->stack.slist_used];
363 1.1.1.1.2.2 yamt if (b->reducing)
364 1.1.1.1.2.2 yamt b->expr[v].onstack = 0;
365 1.1.1.1.2.2 yamt
366 1.1.1.1.2.2 yamt return v;
367 1.1.1.1.2.2 yamt }
368 1.1.1.1.2.2 yamt
369 1.1.1.1.2.2 yamt /*************************************************************************
370 1.1.1.1.2.2 yamt *
371 1.1.1.1.2.2 yamt * Start symbol parse functions.
372 1.1.1.1.2.2 yamt *
373 1.1.1.1.2.2 yamt *************************************************************************/
374 1.1.1.1.2.2 yamt
375 1.1.1.1.2.2 yamt /*
376 1.1.1.1.2.2 yamt * Parse a comma-separated list of integers that represent character
377 1.1.1.1.2.2 yamt * properties. Combine them into a mask that is returned in the `mask'
378 1.1.1.1.2.2 yamt * variable, and return the number of characters consumed.
379 1.1.1.1.2.2 yamt */
380 1.1.1.1.2.2 yamt static unsigned long
381 1.1.1.1.2.2 yamt _ure_prop_list(ucs2_t *pp, unsigned long limit, unsigned long *mask,
382 1.1.1.1.2.2 yamt _ure_buffer_t *b)
383 1.1.1.1.2.2 yamt {
384 1.1.1.1.2.2 yamt unsigned long n, m;
385 1.1.1.1.2.2 yamt ucs2_t *sp, *ep;
386 1.1.1.1.2.2 yamt
387 1.1.1.1.2.2 yamt sp = pp;
388 1.1.1.1.2.2 yamt ep = sp + limit;
389 1.1.1.1.2.2 yamt
390 1.1.1.1.2.2 yamt for (m = n = 0; b->error == _URE_OK && sp < ep; sp++) {
391 1.1.1.1.2.2 yamt if (*sp == ',') {
392 1.1.1.1.2.2 yamt /*
393 1.1.1.1.2.2 yamt * Encountered a comma, so select the next character property flag
394 1.1.1.1.2.2 yamt * and reset the number.
395 1.1.1.1.2.2 yamt */
396 1.1.1.1.2.2 yamt m |= cclass_flags[n];
397 1.1.1.1.2.2 yamt n = 0;
398 1.1.1.1.2.2 yamt } else if (*sp >= '0' && *sp <= '9')
399 1.1.1.1.2.2 yamt /*
400 1.1.1.1.2.2 yamt * Encountered a digit, so start or continue building the cardinal
401 1.1.1.1.2.2 yamt * that represents the character property flag.
402 1.1.1.1.2.2 yamt */
403 1.1.1.1.2.2 yamt n = (n * 10) + (*sp - '0');
404 1.1.1.1.2.2 yamt else
405 1.1.1.1.2.2 yamt /*
406 1.1.1.1.2.2 yamt * Encountered something that is not part of the property list.
407 1.1.1.1.2.2 yamt * Indicate that we are done.
408 1.1.1.1.2.2 yamt */
409 1.1.1.1.2.2 yamt break;
410 1.1.1.1.2.2 yamt
411 1.1.1.1.2.2 yamt /*
412 1.1.1.1.2.2 yamt * If a property number greater than 32 occurs, then there is a
413 1.1.1.1.2.2 yamt * problem. Most likely a missing comma separator.
414 1.1.1.1.2.2 yamt */
415 1.1.1.1.2.2 yamt if (n > 32)
416 1.1.1.1.2.2 yamt b->error = _URE_INVALID_PROPERTY;
417 1.1.1.1.2.2 yamt }
418 1.1.1.1.2.2 yamt
419 1.1.1.1.2.2 yamt if (n != 0)
420 1.1.1.1.2.2 yamt m |= cclass_flags[n];
421 1.1.1.1.2.2 yamt
422 1.1.1.1.2.2 yamt /*
423 1.1.1.1.2.2 yamt * Set the mask that represents the group of character properties.
424 1.1.1.1.2.2 yamt */
425 1.1.1.1.2.2 yamt *mask = m;
426 1.1.1.1.2.2 yamt
427 1.1.1.1.2.2 yamt /*
428 1.1.1.1.2.2 yamt * Return the number of characters consumed.
429 1.1.1.1.2.2 yamt */
430 1.1.1.1.2.2 yamt return sp - pp;
431 1.1.1.1.2.2 yamt }
432 1.1.1.1.2.2 yamt
433 1.1.1.1.2.2 yamt /*
434 1.1.1.1.2.2 yamt * Collect a hex number with 1 to 4 digits and return the number
435 1.1.1.1.2.2 yamt * of characters used.
436 1.1.1.1.2.2 yamt */
437 1.1.1.1.2.2 yamt static unsigned long
438 1.1.1.1.2.2 yamt _ure_hex(ucs2_t *np, unsigned long limit, ucs4_t *n)
439 1.1.1.1.2.2 yamt {
440 1.1.1.1.2.2 yamt ucs2_t i;
441 1.1.1.1.2.2 yamt ucs2_t *sp, *ep;
442 1.1.1.1.2.2 yamt ucs4_t nn;
443 1.1.1.1.2.2 yamt
444 1.1.1.1.2.2 yamt sp = np;
445 1.1.1.1.2.2 yamt ep = sp + limit;
446 1.1.1.1.2.2 yamt
447 1.1.1.1.2.2 yamt for (nn = 0, i = 0; i < 4 && sp < ep; i++, sp++) {
448 1.1.1.1.2.2 yamt if (*sp >= '0' && *sp <= '9')
449 1.1.1.1.2.2 yamt nn = (nn << 4) + (*sp - '0');
450 1.1.1.1.2.2 yamt else if (*sp >= 'A' && *sp <= 'F')
451 1.1.1.1.2.2 yamt nn = (nn << 4) + ((*sp - 'A') + 10);
452 1.1.1.1.2.2 yamt else if (*sp >= 'a' && *sp <= 'f')
453 1.1.1.1.2.2 yamt nn = (nn << 4) + ((*sp - 'a') + 10);
454 1.1.1.1.2.2 yamt else
455 1.1.1.1.2.2 yamt /*
456 1.1.1.1.2.2 yamt * Encountered something that is not a hex digit.
457 1.1.1.1.2.2 yamt */
458 1.1.1.1.2.2 yamt break;
459 1.1.1.1.2.2 yamt }
460 1.1.1.1.2.2 yamt
461 1.1.1.1.2.2 yamt /*
462 1.1.1.1.2.2 yamt * Assign the character code collected and return the number of
463 1.1.1.1.2.2 yamt * characters used.
464 1.1.1.1.2.2 yamt */
465 1.1.1.1.2.2 yamt *n = nn;
466 1.1.1.1.2.2 yamt
467 1.1.1.1.2.2 yamt return sp - np;
468 1.1.1.1.2.2 yamt }
469 1.1.1.1.2.2 yamt
470 1.1.1.1.2.2 yamt /*
471 1.1.1.1.2.2 yamt * Insert a range into a character class, removing duplicates and ordering
472 1.1.1.1.2.2 yamt * them in increasing range-start order.
473 1.1.1.1.2.2 yamt */
474 1.1.1.1.2.2 yamt static void
475 1.1.1.1.2.2 yamt _ure_add_range(_ure_ccl_t *ccl, _ure_range_t *r, _ure_buffer_t *b)
476 1.1.1.1.2.2 yamt {
477 1.1.1.1.2.2 yamt ucs2_t i;
478 1.1.1.1.2.2 yamt ucs4_t tmp;
479 1.1.1.1.2.2 yamt _ure_range_t *rp;
480 1.1.1.1.2.2 yamt
481 1.1.1.1.2.2 yamt /*
482 1.1.1.1.2.2 yamt * If the `casefold' flag is set, then make sure both endpoints of the
483 1.1.1.1.2.2 yamt * range are converted to lower case.
484 1.1.1.1.2.2 yamt */
485 1.1.1.1.2.2 yamt if (b->flags & _URE_DFA_CASEFOLD) {
486 1.1.1.1.2.2 yamt r->min_code = _ure_tolower(r->min_code);
487 1.1.1.1.2.2 yamt r->max_code = _ure_tolower(r->max_code);
488 1.1.1.1.2.2 yamt }
489 1.1.1.1.2.2 yamt
490 1.1.1.1.2.2 yamt /*
491 1.1.1.1.2.2 yamt * Swap the range endpoints if they are not in increasing order.
492 1.1.1.1.2.2 yamt */
493 1.1.1.1.2.2 yamt if (r->min_code > r->max_code) {
494 1.1.1.1.2.2 yamt tmp = r->min_code;
495 1.1.1.1.2.2 yamt r->min_code = r->max_code;
496 1.1.1.1.2.2 yamt r->max_code = tmp;
497 1.1.1.1.2.2 yamt }
498 1.1.1.1.2.2 yamt
499 1.1.1.1.2.2 yamt for (i = 0, rp = ccl->ranges;
500 1.1.1.1.2.2 yamt i < ccl->ranges_used && r->min_code < rp->min_code; i++, rp++) ;
501 1.1.1.1.2.2 yamt
502 1.1.1.1.2.2 yamt /*
503 1.1.1.1.2.2 yamt * Check for a duplicate.
504 1.1.1.1.2.2 yamt */
505 1.1.1.1.2.2 yamt if (i < ccl->ranges_used &&
506 1.1.1.1.2.2 yamt r->min_code == rp->min_code && r->max_code == rp->max_code)
507 1.1.1.1.2.2 yamt return;
508 1.1.1.1.2.2 yamt
509 1.1.1.1.2.2 yamt if (ccl->ranges_used == ccl->ranges_size) {
510 1.1.1.1.2.2 yamt if (ccl->ranges_size == 0)
511 1.1.1.1.2.2 yamt ccl->ranges = (_ure_range_t *) malloc(sizeof(_ure_range_t) << 3);
512 1.1.1.1.2.2 yamt else
513 1.1.1.1.2.2 yamt ccl->ranges = (_ure_range_t *)
514 1.1.1.1.2.2 yamt realloc((char *) ccl->ranges,
515 1.1.1.1.2.2 yamt sizeof(_ure_range_t) * (ccl->ranges_size + 8));
516 1.1.1.1.2.2 yamt ccl->ranges_size += 8;
517 1.1.1.1.2.2 yamt }
518 1.1.1.1.2.2 yamt
519 1.1.1.1.2.2 yamt rp = ccl->ranges + ccl->ranges_used;
520 1.1.1.1.2.2 yamt
521 1.1.1.1.2.2 yamt if (i < ccl->ranges_used)
522 1.1.1.1.2.2 yamt _ure_memmove((char *) (rp + 1), (char *) rp,
523 1.1.1.1.2.2 yamt sizeof(_ure_range_t) * (ccl->ranges_used - i));
524 1.1.1.1.2.2 yamt
525 1.1.1.1.2.2 yamt ccl->ranges_used++;
526 1.1.1.1.2.2 yamt rp->min_code = r->min_code;
527 1.1.1.1.2.2 yamt rp->max_code = r->max_code;
528 1.1.1.1.2.2 yamt }
529 1.1.1.1.2.2 yamt
530 1.1.1.1.2.2 yamt #define _URE_ALPHA_MASK (_URE_UPPER|_URE_LOWER|_URE_OTHERLETTER|\
531 1.1.1.1.2.2 yamt _URE_MODIFIER|_URE_TITLE|_URE_NONSPACING|_URE_COMBINING)
532 1.1.1.1.2.2 yamt #define _URE_ALNUM_MASK (_URE_ALPHA_MASK|_URE_NUMDIGIT)
533 1.1.1.1.2.2 yamt #define _URE_PUNCT_MASK (_URE_DASHPUNCT|_URE_OPENPUNCT|_URE_CLOSEPUNCT|\
534 1.1.1.1.2.2 yamt _URE_OTHERPUNCT)
535 1.1.1.1.2.2 yamt #define _URE_GRAPH_MASK (_URE_NUMDIGIT|_URE_NUMOTHER|_URE_ALPHA_MASK|\
536 1.1.1.1.2.2 yamt _URE_MATHSYM|_URE_CURRENCYSYM|_URE_OTHERSYM)
537 1.1.1.1.2.2 yamt #define _URE_PRINT_MASK (_URE_GRAPH_MASK|_URE_SPACESEP)
538 1.1.1.1.2.2 yamt #define _URE_SPACE_MASK (_URE_SPACESEP|_URE_LINESEP|_URE_PARASEP)
539 1.1.1.1.2.2 yamt
540 1.1.1.1.2.2 yamt typedef void (*_ure_cclsetup_t)(
541 1.1.1.1.2.2 yamt _ure_symtab_t *sym,
542 1.1.1.1.2.2 yamt unsigned long mask,
543 1.1.1.1.2.2 yamt _ure_buffer_t *b
544 1.1.1.1.2.2 yamt );
545 1.1.1.1.2.2 yamt
546 1.1.1.1.2.2 yamt typedef struct {
547 1.1.1.1.2.2 yamt ucs2_t key;
548 1.1.1.1.2.2 yamt unsigned long len;
549 1.1.1.1.2.2 yamt unsigned long next;
550 1.1.1.1.2.2 yamt _ure_cclsetup_t func;
551 1.1.1.1.2.2 yamt unsigned long mask;
552 1.1.1.1.2.2 yamt } _ure_trie_t;
553 1.1.1.1.2.2 yamt
554 1.1.1.1.2.2 yamt static void
555 1.1.1.1.2.2 yamt _ure_ccl_setup(_ure_symtab_t *sym, unsigned long mask, _ure_buffer_t *b)
556 1.1.1.1.2.2 yamt {
557 1.1.1.1.2.2 yamt sym->props |= mask;
558 1.1.1.1.2.2 yamt }
559 1.1.1.1.2.2 yamt
560 1.1.1.1.2.2 yamt static void
561 1.1.1.1.2.2 yamt _ure_space_setup(_ure_symtab_t *sym, unsigned long mask, _ure_buffer_t *b)
562 1.1.1.1.2.2 yamt {
563 1.1.1.1.2.2 yamt _ure_range_t range;
564 1.1.1.1.2.2 yamt
565 1.1.1.1.2.2 yamt sym->props |= mask;
566 1.1.1.1.2.2 yamt
567 1.1.1.1.2.2 yamt /*
568 1.1.1.1.2.2 yamt * Add the additional characters needed for handling isspace().
569 1.1.1.1.2.2 yamt */
570 1.1.1.1.2.2 yamt range.min_code = range.max_code = '\t';
571 1.1.1.1.2.2 yamt _ure_add_range(&sym->sym.ccl, &range, b);
572 1.1.1.1.2.2 yamt range.min_code = range.max_code = '\r';
573 1.1.1.1.2.2 yamt _ure_add_range(&sym->sym.ccl, &range, b);
574 1.1.1.1.2.2 yamt range.min_code = range.max_code = '\n';
575 1.1.1.1.2.2 yamt _ure_add_range(&sym->sym.ccl, &range, b);
576 1.1.1.1.2.2 yamt range.min_code = range.max_code = '\f';
577 1.1.1.1.2.2 yamt _ure_add_range(&sym->sym.ccl, &range, b);
578 1.1.1.1.2.2 yamt range.min_code = range.max_code = 0xfeff;
579 1.1.1.1.2.2 yamt _ure_add_range(&sym->sym.ccl, &range, b);
580 1.1.1.1.2.2 yamt }
581 1.1.1.1.2.2 yamt
582 1.1.1.1.2.2 yamt static void
583 1.1.1.1.2.2 yamt _ure_xdigit_setup(_ure_symtab_t *sym, unsigned long mask, _ure_buffer_t *b)
584 1.1.1.1.2.2 yamt {
585 1.1.1.1.2.2 yamt _ure_range_t range;
586 1.1.1.1.2.2 yamt
587 1.1.1.1.2.2 yamt /*
588 1.1.1.1.2.2 yamt * Add the additional characters needed for handling isxdigit().
589 1.1.1.1.2.2 yamt */
590 1.1.1.1.2.2 yamt range.min_code = '0';
591 1.1.1.1.2.2 yamt range.max_code = '9';
592 1.1.1.1.2.2 yamt _ure_add_range(&sym->sym.ccl, &range, b);
593 1.1.1.1.2.2 yamt range.min_code = 'A';
594 1.1.1.1.2.2 yamt range.max_code = 'F';
595 1.1.1.1.2.2 yamt _ure_add_range(&sym->sym.ccl, &range, b);
596 1.1.1.1.2.2 yamt range.min_code = 'a';
597 1.1.1.1.2.2 yamt range.max_code = 'f';
598 1.1.1.1.2.2 yamt _ure_add_range(&sym->sym.ccl, &range, b);
599 1.1.1.1.2.2 yamt }
600 1.1.1.1.2.2 yamt
601 1.1.1.1.2.2 yamt static _ure_trie_t cclass_trie[] = {
602 1.1.1.1.2.2 yamt {0x003a, 1, 1, 0, 0},
603 1.1.1.1.2.2 yamt {0x0061, 9, 10, 0, 0},
604 1.1.1.1.2.2 yamt {0x0063, 8, 19, 0, 0},
605 1.1.1.1.2.2 yamt {0x0064, 7, 24, 0, 0},
606 1.1.1.1.2.2 yamt {0x0067, 6, 29, 0, 0},
607 1.1.1.1.2.2 yamt {0x006c, 5, 34, 0, 0},
608 1.1.1.1.2.2 yamt {0x0070, 4, 39, 0, 0},
609 1.1.1.1.2.2 yamt {0x0073, 3, 49, 0, 0},
610 1.1.1.1.2.2 yamt {0x0075, 2, 54, 0, 0},
611 1.1.1.1.2.2 yamt {0x0078, 1, 59, 0, 0},
612 1.1.1.1.2.2 yamt {0x006c, 1, 11, 0, 0},
613 1.1.1.1.2.2 yamt {0x006e, 2, 13, 0, 0},
614 1.1.1.1.2.2 yamt {0x0070, 1, 16, 0, 0},
615 1.1.1.1.2.2 yamt {0x0075, 1, 14, 0, 0},
616 1.1.1.1.2.2 yamt {0x006d, 1, 15, 0, 0},
617 1.1.1.1.2.2 yamt {0x003a, 1, 16, _ure_ccl_setup, _URE_ALNUM_MASK},
618 1.1.1.1.2.2 yamt {0x0068, 1, 17, 0, 0},
619 1.1.1.1.2.2 yamt {0x0061, 1, 18, 0, 0},
620 1.1.1.1.2.2 yamt {0x003a, 1, 19, _ure_ccl_setup, _URE_ALPHA_MASK},
621 1.1.1.1.2.2 yamt {0x006e, 1, 20, 0, 0},
622 1.1.1.1.2.2 yamt {0x0074, 1, 21, 0, 0},
623 1.1.1.1.2.2 yamt {0x0072, 1, 22, 0, 0},
624 1.1.1.1.2.2 yamt {0x006c, 1, 23, 0, 0},
625 1.1.1.1.2.2 yamt {0x003a, 1, 24, _ure_ccl_setup, _URE_CNTRL},
626 1.1.1.1.2.2 yamt {0x0069, 1, 25, 0, 0},
627 1.1.1.1.2.2 yamt {0x0067, 1, 26, 0, 0},
628 1.1.1.1.2.2 yamt {0x0069, 1, 27, 0, 0},
629 1.1.1.1.2.2 yamt {0x0074, 1, 28, 0, 0},
630 1.1.1.1.2.2 yamt {0x003a, 1, 29, _ure_ccl_setup, _URE_NUMDIGIT},
631 1.1.1.1.2.2 yamt {0x0072, 1, 30, 0, 0},
632 1.1.1.1.2.2 yamt {0x0061, 1, 31, 0, 0},
633 1.1.1.1.2.2 yamt {0x0070, 1, 32, 0, 0},
634 1.1.1.1.2.2 yamt {0x0068, 1, 33, 0, 0},
635 1.1.1.1.2.2 yamt {0x003a, 1, 34, _ure_ccl_setup, _URE_GRAPH_MASK},
636 1.1.1.1.2.2 yamt {0x006f, 1, 35, 0, 0},
637 1.1.1.1.2.2 yamt {0x0077, 1, 36, 0, 0},
638 1.1.1.1.2.2 yamt {0x0065, 1, 37, 0, 0},
639 1.1.1.1.2.2 yamt {0x0072, 1, 38, 0, 0},
640 1.1.1.1.2.2 yamt {0x003a, 1, 39, _ure_ccl_setup, _URE_LOWER},
641 1.1.1.1.2.2 yamt {0x0072, 2, 41, 0, 0},
642 1.1.1.1.2.2 yamt {0x0075, 1, 45, 0, 0},
643 1.1.1.1.2.2 yamt {0x0069, 1, 42, 0, 0},
644 1.1.1.1.2.2 yamt {0x006e, 1, 43, 0, 0},
645 1.1.1.1.2.2 yamt {0x0074, 1, 44, 0, 0},
646 1.1.1.1.2.2 yamt {0x003a, 1, 45, _ure_ccl_setup, _URE_PRINT_MASK},
647 1.1.1.1.2.2 yamt {0x006e, 1, 46, 0, 0},
648 1.1.1.1.2.2 yamt {0x0063, 1, 47, 0, 0},
649 1.1.1.1.2.2 yamt {0x0074, 1, 48, 0, 0},
650 1.1.1.1.2.2 yamt {0x003a, 1, 49, _ure_ccl_setup, _URE_PUNCT_MASK},
651 1.1.1.1.2.2 yamt {0x0070, 1, 50, 0, 0},
652 1.1.1.1.2.2 yamt {0x0061, 1, 51, 0, 0},
653 1.1.1.1.2.2 yamt {0x0063, 1, 52, 0, 0},
654 1.1.1.1.2.2 yamt {0x0065, 1, 53, 0, 0},
655 1.1.1.1.2.2 yamt {0x003a, 1, 54, _ure_space_setup, _URE_SPACE_MASK},
656 1.1.1.1.2.2 yamt {0x0070, 1, 55, 0, 0},
657 1.1.1.1.2.2 yamt {0x0070, 1, 56, 0, 0},
658 1.1.1.1.2.2 yamt {0x0065, 1, 57, 0, 0},
659 1.1.1.1.2.2 yamt {0x0072, 1, 58, 0, 0},
660 1.1.1.1.2.2 yamt {0x003a, 1, 59, _ure_ccl_setup, _URE_UPPER},
661 1.1.1.1.2.2 yamt {0x0064, 1, 60, 0, 0},
662 1.1.1.1.2.2 yamt {0x0069, 1, 61, 0, 0},
663 1.1.1.1.2.2 yamt {0x0067, 1, 62, 0, 0},
664 1.1.1.1.2.2 yamt {0x0069, 1, 63, 0, 0},
665 1.1.1.1.2.2 yamt {0x0074, 1, 64, 0, 0},
666 1.1.1.1.2.2 yamt {0x003a, 1, 65, _ure_xdigit_setup, 0},
667 1.1.1.1.2.2 yamt };
668 1.1.1.1.2.2 yamt
669 1.1.1.1.2.2 yamt /*
670 1.1.1.1.2.2 yamt * Probe for one of the POSIX colon delimited character classes in the static
671 1.1.1.1.2.2 yamt * trie.
672 1.1.1.1.2.2 yamt */
673 1.1.1.1.2.2 yamt static unsigned long
674 1.1.1.1.2.2 yamt _ure_posix_ccl(ucs2_t *cp, unsigned long limit, _ure_symtab_t *sym,
675 1.1.1.1.2.2 yamt _ure_buffer_t *b)
676 1.1.1.1.2.2 yamt {
677 1.1.1.1.2.2 yamt int i;
678 1.1.1.1.2.2 yamt unsigned long n;
679 1.1.1.1.2.2 yamt _ure_trie_t *tp;
680 1.1.1.1.2.2 yamt ucs2_t *sp, *ep;
681 1.1.1.1.2.2 yamt
682 1.1.1.1.2.2 yamt /*
683 1.1.1.1.2.2 yamt * If the number of characters left is less than 7, then this cannot be
684 1.1.1.1.2.2 yamt * interpreted as one of the colon delimited classes.
685 1.1.1.1.2.2 yamt */
686 1.1.1.1.2.2 yamt if (limit < 7)
687 1.1.1.1.2.2 yamt return 0;
688 1.1.1.1.2.2 yamt
689 1.1.1.1.2.2 yamt sp = cp;
690 1.1.1.1.2.2 yamt ep = sp + limit;
691 1.1.1.1.2.2 yamt tp = cclass_trie;
692 1.1.1.1.2.2 yamt for (i = 0; sp < ep && i < 8; i++, sp++) {
693 1.1.1.1.2.2 yamt n = tp->len;
694 1.1.1.1.2.2 yamt
695 1.1.1.1.2.2 yamt for (; n > 0 && tp->key != *sp; tp++, n--) ;
696 1.1.1.1.2.2 yamt
697 1.1.1.1.2.2 yamt if (n == 0)
698 1.1.1.1.2.2 yamt return 0;
699 1.1.1.1.2.2 yamt
700 1.1.1.1.2.2 yamt if (*sp == ':' && (i == 6 || i == 7)) {
701 1.1.1.1.2.2 yamt sp++;
702 1.1.1.1.2.2 yamt break;
703 1.1.1.1.2.2 yamt }
704 1.1.1.1.2.2 yamt if (sp + 1 < ep)
705 1.1.1.1.2.2 yamt tp = cclass_trie + tp->next;
706 1.1.1.1.2.2 yamt }
707 1.1.1.1.2.2 yamt if (tp->func == 0)
708 1.1.1.1.2.2 yamt return 0;
709 1.1.1.1.2.2 yamt
710 1.1.1.1.2.2 yamt (*tp->func)(sym, tp->mask, b);
711 1.1.1.1.2.2 yamt
712 1.1.1.1.2.2 yamt return sp - cp;
713 1.1.1.1.2.2 yamt }
714 1.1.1.1.2.2 yamt
715 1.1.1.1.2.2 yamt /*
716 1.1.1.1.2.2 yamt * Construct a list of ranges and return the number of characters consumed.
717 1.1.1.1.2.2 yamt */
718 1.1.1.1.2.2 yamt static unsigned long
719 1.1.1.1.2.2 yamt _ure_cclass(ucs2_t *cp, unsigned long limit, _ure_symtab_t *symp,
720 1.1.1.1.2.2 yamt _ure_buffer_t *b)
721 1.1.1.1.2.2 yamt {
722 1.1.1.1.2.2 yamt int range_end;
723 1.1.1.1.2.2 yamt unsigned long n;
724 1.1.1.1.2.2 yamt ucs2_t *sp, *ep;
725 1.1.1.1.2.2 yamt ucs4_t c, last;
726 1.1.1.1.2.2 yamt _ure_ccl_t *cclp;
727 1.1.1.1.2.2 yamt _ure_range_t range;
728 1.1.1.1.2.2 yamt
729 1.1.1.1.2.2 yamt sp = cp;
730 1.1.1.1.2.2 yamt ep = sp + limit;
731 1.1.1.1.2.2 yamt
732 1.1.1.1.2.2 yamt if (*sp == '^') {
733 1.1.1.1.2.2 yamt symp->type = _URE_NCCLASS;
734 1.1.1.1.2.2 yamt sp++;
735 1.1.1.1.2.2 yamt } else
736 1.1.1.1.2.2 yamt symp->type = _URE_CCLASS;
737 1.1.1.1.2.2 yamt
738 1.1.1.1.2.2 yamt for (last = 0, range_end = 0;
739 1.1.1.1.2.2 yamt b->error == _URE_OK && sp < ep && *sp != ']'; ) {
740 1.1.1.1.2.2 yamt c = *sp++;
741 1.1.1.1.2.2 yamt if (c == '\\') {
742 1.1.1.1.2.2 yamt if (sp == ep) {
743 1.1.1.1.2.2 yamt /*
744 1.1.1.1.2.2 yamt * The EOS was encountered when expecting the reverse solidus
745 1.1.1.1.2.2 yamt * to be followed by the character it is escaping. Set an
746 1.1.1.1.2.2 yamt * error code and return the number of characters consumed up
747 1.1.1.1.2.2 yamt * to this point.
748 1.1.1.1.2.2 yamt */
749 1.1.1.1.2.2 yamt b->error = _URE_UNEXPECTED_EOS;
750 1.1.1.1.2.2 yamt return sp - cp;
751 1.1.1.1.2.2 yamt }
752 1.1.1.1.2.2 yamt
753 1.1.1.1.2.2 yamt c = *sp++;
754 1.1.1.1.2.2 yamt switch (c) {
755 1.1.1.1.2.2 yamt case 'a':
756 1.1.1.1.2.2 yamt c = 0x07;
757 1.1.1.1.2.2 yamt break;
758 1.1.1.1.2.2 yamt case 'b':
759 1.1.1.1.2.2 yamt c = 0x08;
760 1.1.1.1.2.2 yamt break;
761 1.1.1.1.2.2 yamt case 'f':
762 1.1.1.1.2.2 yamt c = 0x0c;
763 1.1.1.1.2.2 yamt break;
764 1.1.1.1.2.2 yamt case 'n':
765 1.1.1.1.2.2 yamt c = 0x0a;
766 1.1.1.1.2.2 yamt break;
767 1.1.1.1.2.2 yamt case 'r':
768 1.1.1.1.2.2 yamt c = 0x0d;
769 1.1.1.1.2.2 yamt break;
770 1.1.1.1.2.2 yamt case 't':
771 1.1.1.1.2.2 yamt c = 0x09;
772 1.1.1.1.2.2 yamt break;
773 1.1.1.1.2.2 yamt case 'v':
774 1.1.1.1.2.2 yamt c = 0x0b;
775 1.1.1.1.2.2 yamt break;
776 1.1.1.1.2.2 yamt case 'p':
777 1.1.1.1.2.2 yamt case 'P':
778 1.1.1.1.2.2 yamt sp += _ure_prop_list(sp, ep - sp, &symp->props, b);
779 1.1.1.1.2.2 yamt /*
780 1.1.1.1.2.2 yamt * Invert the bit mask of the properties if this is a negated
781 1.1.1.1.2.2 yamt * character class or if 'P' is used to specify a list of
782 1.1.1.1.2.2 yamt * character properties that should *not* match in a
783 1.1.1.1.2.2 yamt * character class.
784 1.1.1.1.2.2 yamt */
785 1.1.1.1.2.2 yamt if (c == 'P')
786 1.1.1.1.2.2 yamt symp->props = ~symp->props;
787 1.1.1.1.2.2 yamt continue;
788 1.1.1.1.2.2 yamt break;
789 1.1.1.1.2.2 yamt case 'x':
790 1.1.1.1.2.2 yamt case 'X':
791 1.1.1.1.2.2 yamt case 'u':
792 1.1.1.1.2.2 yamt case 'U':
793 1.1.1.1.2.2 yamt if (sp < ep &&
794 1.1.1.1.2.2 yamt ((*sp >= '0' && *sp <= '9') ||
795 1.1.1.1.2.2 yamt (*sp >= 'A' && *sp <= 'F') ||
796 1.1.1.1.2.2 yamt (*sp >= 'a' && *sp <= 'f')))
797 1.1.1.1.2.2 yamt sp += _ure_hex(sp, ep - sp, &c);
798 1.1.1.1.2.2 yamt }
799 1.1.1.1.2.2 yamt } else if (c == ':') {
800 1.1.1.1.2.2 yamt /*
801 1.1.1.1.2.2 yamt * Probe for a POSIX colon delimited character class.
802 1.1.1.1.2.2 yamt */
803 1.1.1.1.2.2 yamt sp--;
804 1.1.1.1.2.2 yamt if ((n = _ure_posix_ccl(sp, ep - sp, symp, b)) == 0)
805 1.1.1.1.2.2 yamt sp++;
806 1.1.1.1.2.2 yamt else {
807 1.1.1.1.2.2 yamt sp += n;
808 1.1.1.1.2.2 yamt continue;
809 1.1.1.1.2.2 yamt }
810 1.1.1.1.2.2 yamt }
811 1.1.1.1.2.2 yamt
812 1.1.1.1.2.2 yamt cclp = &symp->sym.ccl;
813 1.1.1.1.2.2 yamt
814 1.1.1.1.2.2 yamt /*
815 1.1.1.1.2.2 yamt * Check to see if the current character is a low surrogate that needs
816 1.1.1.1.2.2 yamt * to be combined with a preceding high surrogate.
817 1.1.1.1.2.2 yamt */
818 1.1.1.1.2.2 yamt if (last != 0) {
819 1.1.1.1.2.2 yamt if (c >= 0xdc00 && c <= 0xdfff)
820 1.1.1.1.2.2 yamt /*
821 1.1.1.1.2.2 yamt * Construct the UTF16 character code.
822 1.1.1.1.2.2 yamt */
823 1.1.1.1.2.2 yamt c = 0x10000 + (((last & 0x03ff) << 10) | (c & 0x03ff));
824 1.1.1.1.2.2 yamt else {
825 1.1.1.1.2.2 yamt /*
826 1.1.1.1.2.2 yamt * Add the isolated high surrogate to the range.
827 1.1.1.1.2.2 yamt */
828 1.1.1.1.2.2 yamt if (range_end == 1)
829 1.1.1.1.2.2 yamt range.max_code = last & 0xffff;
830 1.1.1.1.2.2 yamt else
831 1.1.1.1.2.2 yamt range.min_code = range.max_code = last & 0xffff;
832 1.1.1.1.2.2 yamt
833 1.1.1.1.2.2 yamt _ure_add_range(cclp, &range, b);
834 1.1.1.1.2.2 yamt range_end = 0;
835 1.1.1.1.2.2 yamt }
836 1.1.1.1.2.2 yamt }
837 1.1.1.1.2.2 yamt
838 1.1.1.1.2.2 yamt /*
839 1.1.1.1.2.2 yamt * Clear the last character code.
840 1.1.1.1.2.2 yamt */
841 1.1.1.1.2.2 yamt last = 0;
842 1.1.1.1.2.2 yamt
843 1.1.1.1.2.2 yamt /*
844 1.1.1.1.2.2 yamt * This slightly awkward code handles the different cases needed to
845 1.1.1.1.2.2 yamt * construct a range.
846 1.1.1.1.2.2 yamt */
847 1.1.1.1.2.2 yamt if (c >= 0xd800 && c <= 0xdbff) {
848 1.1.1.1.2.2 yamt /*
849 1.1.1.1.2.2 yamt * If the high surrogate is followed by a range indicator, simply
850 1.1.1.1.2.2 yamt * add it as the range start. Otherwise, save it in case the next
851 1.1.1.1.2.2 yamt * character is a low surrogate.
852 1.1.1.1.2.2 yamt */
853 1.1.1.1.2.2 yamt if (*sp == '-') {
854 1.1.1.1.2.2 yamt sp++;
855 1.1.1.1.2.2 yamt range.min_code = c;
856 1.1.1.1.2.2 yamt range_end = 1;
857 1.1.1.1.2.2 yamt } else
858 1.1.1.1.2.2 yamt last = c;
859 1.1.1.1.2.2 yamt } else if (range_end == 1) {
860 1.1.1.1.2.2 yamt range.max_code = c;
861 1.1.1.1.2.2 yamt _ure_add_range(cclp, &range, b);
862 1.1.1.1.2.2 yamt range_end = 0;
863 1.1.1.1.2.2 yamt } else {
864 1.1.1.1.2.2 yamt range.min_code = range.max_code = c;
865 1.1.1.1.2.2 yamt if (*sp == '-') {
866 1.1.1.1.2.2 yamt sp++;
867 1.1.1.1.2.2 yamt range_end = 1;
868 1.1.1.1.2.2 yamt } else
869 1.1.1.1.2.2 yamt _ure_add_range(cclp, &range, b);
870 1.1.1.1.2.2 yamt }
871 1.1.1.1.2.2 yamt }
872 1.1.1.1.2.2 yamt
873 1.1.1.1.2.2 yamt if (sp < ep && *sp == ']')
874 1.1.1.1.2.2 yamt sp++;
875 1.1.1.1.2.2 yamt else
876 1.1.1.1.2.2 yamt /*
877 1.1.1.1.2.2 yamt * The parse was not terminated by the character class close symbol
878 1.1.1.1.2.2 yamt * (']'), so set an error code.
879 1.1.1.1.2.2 yamt */
880 1.1.1.1.2.2 yamt b->error = _URE_CCLASS_OPEN;
881 1.1.1.1.2.2 yamt
882 1.1.1.1.2.2 yamt return sp - cp;
883 1.1.1.1.2.2 yamt }
884 1.1.1.1.2.2 yamt
885 1.1.1.1.2.2 yamt /*
886 1.1.1.1.2.2 yamt * Probe for a low surrogate hex code.
887 1.1.1.1.2.2 yamt */
888 1.1.1.1.2.2 yamt static unsigned long
889 1.1.1.1.2.2 yamt _ure_probe_ls(ucs2_t *ls, unsigned long limit, ucs4_t *c)
890 1.1.1.1.2.2 yamt {
891 1.1.1.1.2.2 yamt ucs4_t i, code;
892 1.1.1.1.2.2 yamt ucs2_t *sp, *ep;
893 1.1.1.1.2.2 yamt
894 1.1.1.1.2.2 yamt for (i = code = 0, sp = ls, ep = sp + limit; i < 4 && sp < ep; sp++) {
895 1.1.1.1.2.2 yamt if (*sp >= '0' && *sp <= '9')
896 1.1.1.1.2.2 yamt code = (code << 4) + (*sp - '0');
897 1.1.1.1.2.2 yamt else if (*sp >= 'A' && *sp <= 'F')
898 1.1.1.1.2.2 yamt code = (code << 4) + ((*sp - 'A') + 10);
899 1.1.1.1.2.2 yamt else if (*sp >= 'a' && *sp <= 'f')
900 1.1.1.1.2.2 yamt code = (code << 4) + ((*sp - 'a') + 10);
901 1.1.1.1.2.2 yamt else
902 1.1.1.1.2.2 yamt break;
903 1.1.1.1.2.2 yamt }
904 1.1.1.1.2.2 yamt
905 1.1.1.1.2.2 yamt *c = code;
906 1.1.1.1.2.2 yamt return (0xdc00 <= code && code <= 0xdfff) ? sp - ls : 0;
907 1.1.1.1.2.2 yamt }
908 1.1.1.1.2.2 yamt
909 1.1.1.1.2.2 yamt static unsigned long
910 1.1.1.1.2.2 yamt _ure_compile_symbol(ucs2_t *sym, unsigned long limit, _ure_symtab_t *symp,
911 1.1.1.1.2.2 yamt _ure_buffer_t *b)
912 1.1.1.1.2.2 yamt {
913 1.1.1.1.2.2 yamt ucs4_t c;
914 1.1.1.1.2.2 yamt ucs2_t *sp, *ep;
915 1.1.1.1.2.2 yamt
916 1.1.1.1.2.2 yamt sp = sym;
917 1.1.1.1.2.2 yamt ep = sym + limit;
918 1.1.1.1.2.2 yamt
919 1.1.1.1.2.2 yamt if ((c = *sp++) == '\\') {
920 1.1.1.1.2.2 yamt
921 1.1.1.1.2.2 yamt if (sp == ep) {
922 1.1.1.1.2.2 yamt /*
923 1.1.1.1.2.2 yamt * The EOS was encountered when expecting the reverse solidus to
924 1.1.1.1.2.2 yamt * be followed by the character it is escaping. Set an error code
925 1.1.1.1.2.2 yamt * and return the number of characters consumed up to this point.
926 1.1.1.1.2.2 yamt */
927 1.1.1.1.2.2 yamt b->error = _URE_UNEXPECTED_EOS;
928 1.1.1.1.2.2 yamt return sp - sym;
929 1.1.1.1.2.2 yamt }
930 1.1.1.1.2.2 yamt
931 1.1.1.1.2.2 yamt c = *sp++;
932 1.1.1.1.2.2 yamt switch (c) {
933 1.1.1.1.2.2 yamt case 'p':
934 1.1.1.1.2.2 yamt case 'P':
935 1.1.1.1.2.2 yamt symp->type = (c == 'p') ? _URE_CCLASS : _URE_NCCLASS;
936 1.1.1.1.2.2 yamt sp += _ure_prop_list(sp, ep - sp, &symp->props, b);
937 1.1.1.1.2.2 yamt break;
938 1.1.1.1.2.2 yamt case 'a':
939 1.1.1.1.2.2 yamt symp->type = _URE_CHAR;
940 1.1.1.1.2.2 yamt symp->sym.chr = 0x07;
941 1.1.1.1.2.2 yamt break;
942 1.1.1.1.2.2 yamt case 'b':
943 1.1.1.1.2.2 yamt symp->type = _URE_CHAR;
944 1.1.1.1.2.2 yamt symp->sym.chr = 0x08;
945 1.1.1.1.2.2 yamt break;
946 1.1.1.1.2.2 yamt case 'f':
947 1.1.1.1.2.2 yamt symp->type = _URE_CHAR;
948 1.1.1.1.2.2 yamt symp->sym.chr = 0x0c;
949 1.1.1.1.2.2 yamt break;
950 1.1.1.1.2.2 yamt case 'n':
951 1.1.1.1.2.2 yamt symp->type = _URE_CHAR;
952 1.1.1.1.2.2 yamt symp->sym.chr = 0x0a;
953 1.1.1.1.2.2 yamt break;
954 1.1.1.1.2.2 yamt case 'r':
955 1.1.1.1.2.2 yamt symp->type = _URE_CHAR;
956 1.1.1.1.2.2 yamt symp->sym.chr = 0x0d;
957 1.1.1.1.2.2 yamt break;
958 1.1.1.1.2.2 yamt case 't':
959 1.1.1.1.2.2 yamt symp->type = _URE_CHAR;
960 1.1.1.1.2.2 yamt symp->sym.chr = 0x09;
961 1.1.1.1.2.2 yamt break;
962 1.1.1.1.2.2 yamt case 'v':
963 1.1.1.1.2.2 yamt symp->type = _URE_CHAR;
964 1.1.1.1.2.2 yamt symp->sym.chr = 0x0b;
965 1.1.1.1.2.2 yamt break;
966 1.1.1.1.2.2 yamt case 'x':
967 1.1.1.1.2.2 yamt case 'X':
968 1.1.1.1.2.2 yamt case 'u':
969 1.1.1.1.2.2 yamt case 'U':
970 1.1.1.1.2.2 yamt /*
971 1.1.1.1.2.2 yamt * Collect between 1 and 4 digits representing a UCS2 code. Fall
972 1.1.1.1.2.2 yamt * through to the next case.
973 1.1.1.1.2.2 yamt */
974 1.1.1.1.2.2 yamt if (sp < ep &&
975 1.1.1.1.2.2 yamt ((*sp >= '0' && *sp <= '9') ||
976 1.1.1.1.2.2 yamt (*sp >= 'A' && *sp <= 'F') ||
977 1.1.1.1.2.2 yamt (*sp >= 'a' && *sp <= 'f')))
978 1.1.1.1.2.2 yamt sp += _ure_hex(sp, ep - sp, &c);
979 1.1.1.1.2.2 yamt /* FALLTHROUGH */
980 1.1.1.1.2.2 yamt default:
981 1.1.1.1.2.2 yamt /*
982 1.1.1.1.2.2 yamt * Simply add an escaped character here.
983 1.1.1.1.2.2 yamt */
984 1.1.1.1.2.2 yamt symp->type = _URE_CHAR;
985 1.1.1.1.2.2 yamt symp->sym.chr = c;
986 1.1.1.1.2.2 yamt }
987 1.1.1.1.2.2 yamt } else if (c == '^' || c == '$')
988 1.1.1.1.2.2 yamt /*
989 1.1.1.1.2.2 yamt * Handle the BOL and EOL anchors. This actually consists simply of
990 1.1.1.1.2.2 yamt * setting a flag that indicates that the user supplied anchor match
991 1.1.1.1.2.2 yamt * function should be called. This needs to be done instead of simply
992 1.1.1.1.2.2 yamt * matching line/paragraph separators because beginning-of-text and
993 1.1.1.1.2.2 yamt * end-of-text tests are needed as well.
994 1.1.1.1.2.2 yamt */
995 1.1.1.1.2.2 yamt symp->type = (c == '^') ? _URE_BOL_ANCHOR : _URE_EOL_ANCHOR;
996 1.1.1.1.2.2 yamt else if (c == '[')
997 1.1.1.1.2.2 yamt /*
998 1.1.1.1.2.2 yamt * Construct a character class.
999 1.1.1.1.2.2 yamt */
1000 1.1.1.1.2.2 yamt sp += _ure_cclass(sp, ep - sp, symp, b);
1001 1.1.1.1.2.2 yamt else if (c == '.')
1002 1.1.1.1.2.2 yamt symp->type = _URE_ANY_CHAR;
1003 1.1.1.1.2.2 yamt else {
1004 1.1.1.1.2.2 yamt symp->type = _URE_CHAR;
1005 1.1.1.1.2.2 yamt symp->sym.chr = c;
1006 1.1.1.1.2.2 yamt }
1007 1.1.1.1.2.2 yamt
1008 1.1.1.1.2.2 yamt /*
1009 1.1.1.1.2.2 yamt * If the symbol type happens to be a character and is a high surrogate,
1010 1.1.1.1.2.2 yamt * then probe forward to see if it is followed by a low surrogate that
1011 1.1.1.1.2.2 yamt * needs to be added.
1012 1.1.1.1.2.2 yamt */
1013 1.1.1.1.2.2 yamt if (sp < ep && symp->type == _URE_CHAR &&
1014 1.1.1.1.2.2 yamt 0xd800 <= symp->sym.chr && symp->sym.chr <= 0xdbff) {
1015 1.1.1.1.2.2 yamt
1016 1.1.1.1.2.2 yamt if (0xdc00 <= *sp && *sp <= 0xdfff) {
1017 1.1.1.1.2.2 yamt symp->sym.chr = 0x10000 + (((symp->sym.chr & 0x03ff) << 10) |
1018 1.1.1.1.2.2 yamt (*sp & 0x03ff));
1019 1.1.1.1.2.2 yamt sp++;
1020 1.1.1.1.2.2 yamt } else if (*sp == '\\' && (*(sp + 1) == 'x' || *(sp + 1) == 'X' ||
1021 1.1.1.1.2.2 yamt *(sp + 1) == 'u' || *(sp + 1) == 'U')) {
1022 1.1.1.1.2.2 yamt sp += _ure_probe_ls(sp + 2, ep - (sp + 2), &c);
1023 1.1.1.1.2.2 yamt if (0xdc00 <= c && c <= 0xdfff) {
1024 1.1.1.1.2.2 yamt /*
1025 1.1.1.1.2.2 yamt * Take into account the \[xu] in front of the hex code.
1026 1.1.1.1.2.2 yamt */
1027 1.1.1.1.2.2 yamt sp += 2;
1028 1.1.1.1.2.2 yamt symp->sym.chr = 0x10000 + (((symp->sym.chr & 0x03ff) << 10) |
1029 1.1.1.1.2.2 yamt (c & 0x03ff));
1030 1.1.1.1.2.2 yamt }
1031 1.1.1.1.2.2 yamt }
1032 1.1.1.1.2.2 yamt }
1033 1.1.1.1.2.2 yamt
1034 1.1.1.1.2.2 yamt /*
1035 1.1.1.1.2.2 yamt * Last, make sure any _URE_CHAR type symbols are changed to lower case if
1036 1.1.1.1.2.2 yamt * the `casefold' flag is set.
1037 1.1.1.1.2.2 yamt */
1038 1.1.1.1.2.2 yamt if ((b->flags & _URE_DFA_CASEFOLD) && symp->type == _URE_CHAR)
1039 1.1.1.1.2.2 yamt symp->sym.chr = _ure_tolower(symp->sym.chr);
1040 1.1.1.1.2.2 yamt
1041 1.1.1.1.2.2 yamt /*
1042 1.1.1.1.2.2 yamt * If the symbol constructed is anything other than one of the anchors,
1043 1.1.1.1.2.2 yamt * make sure the _URE_DFA_BLANKLINE flag is removed.
1044 1.1.1.1.2.2 yamt */
1045 1.1.1.1.2.2 yamt if (symp->type != _URE_BOL_ANCHOR && symp->type != _URE_EOL_ANCHOR)
1046 1.1.1.1.2.2 yamt b->flags &= ~_URE_DFA_BLANKLINE;
1047 1.1.1.1.2.2 yamt
1048 1.1.1.1.2.2 yamt /*
1049 1.1.1.1.2.2 yamt * Return the number of characters consumed.
1050 1.1.1.1.2.2 yamt */
1051 1.1.1.1.2.2 yamt return sp - sym;
1052 1.1.1.1.2.2 yamt }
1053 1.1.1.1.2.2 yamt
1054 1.1.1.1.2.2 yamt static int
1055 1.1.1.1.2.2 yamt _ure_sym_neq(_ure_symtab_t *a, _ure_symtab_t *b)
1056 1.1.1.1.2.2 yamt {
1057 1.1.1.1.2.2 yamt if (a->type != b->type || a->mods != b->mods || a->props != b->props)
1058 1.1.1.1.2.2 yamt return 1;
1059 1.1.1.1.2.2 yamt
1060 1.1.1.1.2.2 yamt if (a->type == _URE_CCLASS || a->type == _URE_NCCLASS) {
1061 1.1.1.1.2.2 yamt if (a->sym.ccl.ranges_used != b->sym.ccl.ranges_used)
1062 1.1.1.1.2.2 yamt return 1;
1063 1.1.1.1.2.2 yamt if (a->sym.ccl.ranges_used > 0 &&
1064 1.1.1.1.2.2 yamt memcmp((char *) a->sym.ccl.ranges, (char *) b->sym.ccl.ranges,
1065 1.1.1.1.2.2 yamt sizeof(_ure_range_t) * a->sym.ccl.ranges_used) != 0)
1066 1.1.1.1.2.2 yamt return 1;
1067 1.1.1.1.2.2 yamt } else if (a->type == _URE_CHAR && a->sym.chr != b->sym.chr)
1068 1.1.1.1.2.2 yamt return 1;
1069 1.1.1.1.2.2 yamt return 0;
1070 1.1.1.1.2.2 yamt }
1071 1.1.1.1.2.2 yamt
1072 1.1.1.1.2.2 yamt /*
1073 1.1.1.1.2.2 yamt * Construct a symbol, but only keep unique symbols.
1074 1.1.1.1.2.2 yamt */
1075 1.1.1.1.2.2 yamt static ucs2_t
1076 1.1.1.1.2.2 yamt _ure_make_symbol(ucs2_t *sym, unsigned long limit, unsigned long *consumed,
1077 1.1.1.1.2.2 yamt _ure_buffer_t *b)
1078 1.1.1.1.2.2 yamt {
1079 1.1.1.1.2.2 yamt ucs2_t i;
1080 1.1.1.1.2.2 yamt _ure_symtab_t *sp, symbol;
1081 1.1.1.1.2.2 yamt
1082 1.1.1.1.2.2 yamt /*
1083 1.1.1.1.2.2 yamt * Build the next symbol so we can test to see if it is already in the
1084 1.1.1.1.2.2 yamt * symbol table.
1085 1.1.1.1.2.2 yamt */
1086 1.1.1.1.2.2 yamt (void) memset((char *) &symbol, '\0', sizeof(_ure_symtab_t));
1087 1.1.1.1.2.2 yamt *consumed = _ure_compile_symbol(sym, limit, &symbol, b);
1088 1.1.1.1.2.2 yamt
1089 1.1.1.1.2.2 yamt /*
1090 1.1.1.1.2.2 yamt * Check to see if the symbol exists.
1091 1.1.1.1.2.2 yamt */
1092 1.1.1.1.2.2 yamt for (i = 0, sp = b->symtab;
1093 1.1.1.1.2.2 yamt i < b->symtab_used && _ure_sym_neq(&symbol, sp); i++, sp++) ;
1094 1.1.1.1.2.2 yamt
1095 1.1.1.1.2.2 yamt if (i < b->symtab_used) {
1096 1.1.1.1.2.2 yamt /*
1097 1.1.1.1.2.2 yamt * Free up any ranges used for the symbol.
1098 1.1.1.1.2.2 yamt */
1099 1.1.1.1.2.2 yamt if ((symbol.type == _URE_CCLASS || symbol.type == _URE_NCCLASS) &&
1100 1.1.1.1.2.2 yamt symbol.sym.ccl.ranges_size > 0)
1101 1.1.1.1.2.2 yamt free((char *) symbol.sym.ccl.ranges);
1102 1.1.1.1.2.2 yamt
1103 1.1.1.1.2.2 yamt return b->symtab[i].id;
1104 1.1.1.1.2.2 yamt }
1105 1.1.1.1.2.2 yamt
1106 1.1.1.1.2.2 yamt /*
1107 1.1.1.1.2.2 yamt * Need to add the new symbol.
1108 1.1.1.1.2.2 yamt */
1109 1.1.1.1.2.2 yamt if (b->symtab_used == b->symtab_size) {
1110 1.1.1.1.2.2 yamt if (b->symtab_size == 0)
1111 1.1.1.1.2.2 yamt b->symtab = (_ure_symtab_t *) malloc(sizeof(_ure_symtab_t) << 3);
1112 1.1.1.1.2.2 yamt else
1113 1.1.1.1.2.2 yamt b->symtab = (_ure_symtab_t *)
1114 1.1.1.1.2.2 yamt realloc((char *) b->symtab,
1115 1.1.1.1.2.2 yamt sizeof(_ure_symtab_t) * (b->symtab_size + 8));
1116 1.1.1.1.2.2 yamt sp = b->symtab + b->symtab_size;
1117 1.1.1.1.2.2 yamt (void) memset((char *) sp, '\0', sizeof(_ure_symtab_t) << 3);
1118 1.1.1.1.2.2 yamt b->symtab_size += 8;
1119 1.1.1.1.2.2 yamt }
1120 1.1.1.1.2.2 yamt
1121 1.1.1.1.2.2 yamt symbol.id = b->symtab_used++;
1122 1.1.1.1.2.2 yamt (void) AC_MEMCPY((char *) &b->symtab[symbol.id], (char *) &symbol,
1123 1.1.1.1.2.2 yamt sizeof(_ure_symtab_t));
1124 1.1.1.1.2.2 yamt
1125 1.1.1.1.2.2 yamt return symbol.id;
1126 1.1.1.1.2.2 yamt }
1127 1.1.1.1.2.2 yamt
1128 1.1.1.1.2.2 yamt /*************************************************************************
1129 1.1.1.1.2.2 yamt *
1130 1.1.1.1.2.2 yamt * End symbol parse functions.
1131 1.1.1.1.2.2 yamt *
1132 1.1.1.1.2.2 yamt *************************************************************************/
1133 1.1.1.1.2.2 yamt
1134 1.1.1.1.2.2 yamt static ucs2_t
1135 1.1.1.1.2.2 yamt _ure_make_expr(ucs2_t type, ucs2_t lhs, ucs2_t rhs, _ure_buffer_t *b)
1136 1.1.1.1.2.2 yamt {
1137 1.1.1.1.2.2 yamt ucs2_t i;
1138 1.1.1.1.2.2 yamt
1139 1.1.1.1.2.2 yamt if (b == 0)
1140 1.1.1.1.2.2 yamt return _URE_NOOP;
1141 1.1.1.1.2.2 yamt
1142 1.1.1.1.2.2 yamt /*
1143 1.1.1.1.2.2 yamt * Determine if the expression already exists or not.
1144 1.1.1.1.2.2 yamt */
1145 1.1.1.1.2.2 yamt for (i = 0; i < b->expr_used; i++) {
1146 1.1.1.1.2.2 yamt if (b->expr[i].type == type && b->expr[i].lhs == lhs &&
1147 1.1.1.1.2.2 yamt b->expr[i].rhs == rhs)
1148 1.1.1.1.2.2 yamt break;
1149 1.1.1.1.2.2 yamt }
1150 1.1.1.1.2.2 yamt if (i < b->expr_used)
1151 1.1.1.1.2.2 yamt return i;
1152 1.1.1.1.2.2 yamt
1153 1.1.1.1.2.2 yamt /*
1154 1.1.1.1.2.2 yamt * Need to add a new expression.
1155 1.1.1.1.2.2 yamt */
1156 1.1.1.1.2.2 yamt if (b->expr_used == b->expr_size) {
1157 1.1.1.1.2.2 yamt if (b->expr_size == 0)
1158 1.1.1.1.2.2 yamt b->expr = (_ure_elt_t *) malloc(sizeof(_ure_elt_t) << 3);
1159 1.1.1.1.2.2 yamt else
1160 1.1.1.1.2.2 yamt b->expr = (_ure_elt_t *)
1161 1.1.1.1.2.2 yamt realloc((char *) b->expr,
1162 1.1.1.1.2.2 yamt sizeof(_ure_elt_t) * (b->expr_size + 8));
1163 1.1.1.1.2.2 yamt b->expr_size += 8;
1164 1.1.1.1.2.2 yamt }
1165 1.1.1.1.2.2 yamt
1166 1.1.1.1.2.2 yamt b->expr[b->expr_used].onstack = 0;
1167 1.1.1.1.2.2 yamt b->expr[b->expr_used].type = type;
1168 1.1.1.1.2.2 yamt b->expr[b->expr_used].lhs = lhs;
1169 1.1.1.1.2.2 yamt b->expr[b->expr_used].rhs = rhs;
1170 1.1.1.1.2.2 yamt
1171 1.1.1.1.2.2 yamt return b->expr_used++;
1172 1.1.1.1.2.2 yamt }
1173 1.1.1.1.2.2 yamt
1174 1.1.1.1.2.2 yamt static unsigned char spmap[] = {
1175 1.1.1.1.2.2 yamt 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
1176 1.1.1.1.2.2 yamt 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1177 1.1.1.1.2.2 yamt 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1178 1.1.1.1.2.2 yamt };
1179 1.1.1.1.2.2 yamt
1180 1.1.1.1.2.2 yamt #define _ure_isspecial(cc) ((cc) > 0x20 && (cc) < 0x7f && \
1181 1.1.1.1.2.2 yamt (spmap[(cc) >> 3] & (1 << ((cc) & 7))))
1182 1.1.1.1.2.2 yamt
1183 1.1.1.1.2.2 yamt /*
1184 1.1.1.1.2.2 yamt * Convert the regular expression into an NFA in a form that will be easy to
1185 1.1.1.1.2.2 yamt * reduce to a DFA. The starting state for the reduction will be returned.
1186 1.1.1.1.2.2 yamt */
1187 1.1.1.1.2.2 yamt static ucs2_t
1188 1.1.1.1.2.2 yamt _ure_re2nfa(ucs2_t *re, unsigned long relen, _ure_buffer_t *b)
1189 1.1.1.1.2.2 yamt {
1190 1.1.1.1.2.2 yamt ucs2_t c, state, top, sym, *sp, *ep;
1191 1.1.1.1.2.2 yamt unsigned long used;
1192 1.1.1.1.2.2 yamt
1193 1.1.1.1.2.2 yamt state = _URE_NOOP;
1194 1.1.1.1.2.2 yamt
1195 1.1.1.1.2.2 yamt sp = re;
1196 1.1.1.1.2.2 yamt ep = sp + relen;
1197 1.1.1.1.2.2 yamt while (b->error == _URE_OK && sp < ep) {
1198 1.1.1.1.2.2 yamt c = *sp++;
1199 1.1.1.1.2.2 yamt switch (c) {
1200 1.1.1.1.2.2 yamt case '(':
1201 1.1.1.1.2.2 yamt _ure_push(_URE_PAREN, b);
1202 1.1.1.1.2.2 yamt break;
1203 1.1.1.1.2.2 yamt case ')':
1204 1.1.1.1.2.2 yamt /*
1205 1.1.1.1.2.2 yamt * Check for the case of too many close parentheses.
1206 1.1.1.1.2.2 yamt */
1207 1.1.1.1.2.2 yamt if (_ure_peek(b) == _URE_NOOP) {
1208 1.1.1.1.2.2 yamt b->error = _URE_UNBALANCED_GROUP;
1209 1.1.1.1.2.2 yamt break;
1210 1.1.1.1.2.2 yamt }
1211 1.1.1.1.2.2 yamt
1212 1.1.1.1.2.2 yamt while ((top = _ure_peek(b)) == _URE_AND || top == _URE_OR)
1213 1.1.1.1.2.2 yamt /*
1214 1.1.1.1.2.2 yamt * Make an expression with the AND or OR operator and its right
1215 1.1.1.1.2.2 yamt * hand side.
1216 1.1.1.1.2.2 yamt */
1217 1.1.1.1.2.2 yamt state = _ure_make_expr(_ure_pop(b), _ure_pop(b), state, b);
1218 1.1.1.1.2.2 yamt
1219 1.1.1.1.2.2 yamt /*
1220 1.1.1.1.2.2 yamt * Remove the _URE_PAREN off the stack.
1221 1.1.1.1.2.2 yamt */
1222 1.1.1.1.2.2 yamt (void) _ure_pop(b);
1223 1.1.1.1.2.2 yamt break;
1224 1.1.1.1.2.2 yamt case '*':
1225 1.1.1.1.2.2 yamt state = _ure_make_expr(_URE_STAR, state, _URE_NOOP, b);
1226 1.1.1.1.2.2 yamt break;
1227 1.1.1.1.2.2 yamt case '+':
1228 1.1.1.1.2.2 yamt state = _ure_make_expr(_URE_PLUS, state, _URE_NOOP, b);
1229 1.1.1.1.2.2 yamt break;
1230 1.1.1.1.2.2 yamt case '?':
1231 1.1.1.1.2.2 yamt state = _ure_make_expr(_URE_QUEST, state, _URE_NOOP, b);
1232 1.1.1.1.2.2 yamt break;
1233 1.1.1.1.2.2 yamt case '|':
1234 1.1.1.1.2.2 yamt while ((top = _ure_peek(b)) == _URE_AND || top == _URE_OR)
1235 1.1.1.1.2.2 yamt /*
1236 1.1.1.1.2.2 yamt * Make an expression with the AND or OR operator and its right
1237 1.1.1.1.2.2 yamt * hand side.
1238 1.1.1.1.2.2 yamt */
1239 1.1.1.1.2.2 yamt state = _ure_make_expr(_ure_pop(b), _ure_pop(b), state, b);
1240 1.1.1.1.2.2 yamt
1241 1.1.1.1.2.2 yamt _ure_push(state, b);
1242 1.1.1.1.2.2 yamt _ure_push(_URE_OR, b);
1243 1.1.1.1.2.2 yamt break;
1244 1.1.1.1.2.2 yamt default:
1245 1.1.1.1.2.2 yamt sp--;
1246 1.1.1.1.2.2 yamt sym = _ure_make_symbol(sp, ep - sp, &used, b);
1247 1.1.1.1.2.2 yamt sp += used;
1248 1.1.1.1.2.2 yamt state = _ure_make_expr(_URE_SYMBOL, sym, _URE_NOOP, b);
1249 1.1.1.1.2.2 yamt break;
1250 1.1.1.1.2.2 yamt }
1251 1.1.1.1.2.2 yamt
1252 1.1.1.1.2.2 yamt if (c != '(' && c != '|' && sp < ep &&
1253 1.1.1.1.2.2 yamt (!_ure_isspecial(*sp) || *sp == '(')) {
1254 1.1.1.1.2.2 yamt _ure_push(state, b);
1255 1.1.1.1.2.2 yamt _ure_push(_URE_AND, b);
1256 1.1.1.1.2.2 yamt }
1257 1.1.1.1.2.2 yamt }
1258 1.1.1.1.2.2 yamt while ((top = _ure_peek(b)) == _URE_AND || top == _URE_OR)
1259 1.1.1.1.2.2 yamt /*
1260 1.1.1.1.2.2 yamt * Make an expression with the AND or OR operator and its right
1261 1.1.1.1.2.2 yamt * hand side.
1262 1.1.1.1.2.2 yamt */
1263 1.1.1.1.2.2 yamt state = _ure_make_expr(_ure_pop(b), _ure_pop(b), state, b);
1264 1.1.1.1.2.2 yamt
1265 1.1.1.1.2.2 yamt if (b->stack.slist_used > 0)
1266 1.1.1.1.2.2 yamt b->error = _URE_UNBALANCED_GROUP;
1267 1.1.1.1.2.2 yamt
1268 1.1.1.1.2.2 yamt return (b->error == _URE_OK) ? state : _URE_NOOP;
1269 1.1.1.1.2.2 yamt }
1270 1.1.1.1.2.2 yamt
1271 1.1.1.1.2.2 yamt static void
1272 1.1.1.1.2.2 yamt _ure_add_symstate(ucs2_t sym, ucs2_t state, _ure_buffer_t *b)
1273 1.1.1.1.2.2 yamt {
1274 1.1.1.1.2.2 yamt ucs2_t i, *stp;
1275 1.1.1.1.2.2 yamt _ure_symtab_t *sp;
1276 1.1.1.1.2.2 yamt
1277 1.1.1.1.2.2 yamt /*
1278 1.1.1.1.2.2 yamt * Locate the symbol in the symbol table so the state can be added.
1279 1.1.1.1.2.2 yamt * If the symbol doesn't exist, then a real problem exists.
1280 1.1.1.1.2.2 yamt */
1281 1.1.1.1.2.2 yamt for (i = 0, sp = b->symtab; i < b->symtab_used && sym != sp->id;
1282 1.1.1.1.2.2 yamt i++, sp++) ;
1283 1.1.1.1.2.2 yamt
1284 1.1.1.1.2.2 yamt /*
1285 1.1.1.1.2.2 yamt * Now find out if the state exists in the symbol's state list.
1286 1.1.1.1.2.2 yamt */
1287 1.1.1.1.2.2 yamt for (i = 0, stp = sp->states.slist;
1288 1.1.1.1.2.2 yamt i < sp->states.slist_used && state > *stp; i++, stp++) ;
1289 1.1.1.1.2.2 yamt
1290 1.1.1.1.2.2 yamt if (i == sp->states.slist_used || state < *stp) {
1291 1.1.1.1.2.2 yamt /*
1292 1.1.1.1.2.2 yamt * Need to add the state in order.
1293 1.1.1.1.2.2 yamt */
1294 1.1.1.1.2.2 yamt if (sp->states.slist_used == sp->states.slist_size) {
1295 1.1.1.1.2.2 yamt if (sp->states.slist_size == 0)
1296 1.1.1.1.2.2 yamt sp->states.slist = (ucs2_t *) malloc(sizeof(ucs2_t) << 3);
1297 1.1.1.1.2.2 yamt else
1298 1.1.1.1.2.2 yamt sp->states.slist = (ucs2_t *)
1299 1.1.1.1.2.2 yamt realloc((char *) sp->states.slist,
1300 1.1.1.1.2.2 yamt sizeof(ucs2_t) * (sp->states.slist_size + 8));
1301 1.1.1.1.2.2 yamt sp->states.slist_size += 8;
1302 1.1.1.1.2.2 yamt }
1303 1.1.1.1.2.2 yamt if (i < sp->states.slist_used)
1304 1.1.1.1.2.2 yamt (void) _ure_memmove((char *) (sp->states.slist + i + 1),
1305 1.1.1.1.2.2 yamt (char *) (sp->states.slist + i),
1306 1.1.1.1.2.2 yamt sizeof(ucs2_t) * (sp->states.slist_used - i));
1307 1.1.1.1.2.2 yamt sp->states.slist[i] = state;
1308 1.1.1.1.2.2 yamt sp->states.slist_used++;
1309 1.1.1.1.2.2 yamt }
1310 1.1.1.1.2.2 yamt }
1311 1.1.1.1.2.2 yamt
1312 1.1.1.1.2.2 yamt static ucs2_t
1313 1.1.1.1.2.2 yamt _ure_add_state(ucs2_t nstates, ucs2_t *states, _ure_buffer_t *b)
1314 1.1.1.1.2.2 yamt {
1315 1.1.1.1.2.2 yamt ucs2_t i;
1316 1.1.1.1.2.2 yamt _ure_state_t *sp;
1317 1.1.1.1.2.2 yamt
1318 1.1.1.1.2.2 yamt for (i = 0, sp = b->states.states; i < b->states.states_used; i++, sp++) {
1319 1.1.1.1.2.2 yamt if (sp->st.slist_used == nstates &&
1320 1.1.1.1.2.2 yamt memcmp((char *) states, (char *) sp->st.slist,
1321 1.1.1.1.2.2 yamt sizeof(ucs2_t) * nstates) == 0)
1322 1.1.1.1.2.2 yamt break;
1323 1.1.1.1.2.2 yamt }
1324 1.1.1.1.2.2 yamt
1325 1.1.1.1.2.2 yamt if (i == b->states.states_used) {
1326 1.1.1.1.2.2 yamt /*
1327 1.1.1.1.2.2 yamt * Need to add a new DFA state (set of NFA states).
1328 1.1.1.1.2.2 yamt */
1329 1.1.1.1.2.2 yamt if (b->states.states_used == b->states.states_size) {
1330 1.1.1.1.2.2 yamt if (b->states.states_size == 0)
1331 1.1.1.1.2.2 yamt b->states.states = (_ure_state_t *)
1332 1.1.1.1.2.2 yamt malloc(sizeof(_ure_state_t) << 3);
1333 1.1.1.1.2.2 yamt else
1334 1.1.1.1.2.2 yamt b->states.states = (_ure_state_t *)
1335 1.1.1.1.2.2 yamt realloc((char *) b->states.states,
1336 1.1.1.1.2.2 yamt sizeof(_ure_state_t) * (b->states.states_size + 8));
1337 1.1.1.1.2.2 yamt sp = b->states.states + b->states.states_size;
1338 1.1.1.1.2.2 yamt (void) memset((char *) sp, '\0', sizeof(_ure_state_t) << 3);
1339 1.1.1.1.2.2 yamt b->states.states_size += 8;
1340 1.1.1.1.2.2 yamt }
1341 1.1.1.1.2.2 yamt
1342 1.1.1.1.2.2 yamt sp = b->states.states + b->states.states_used++;
1343 1.1.1.1.2.2 yamt sp->id = i;
1344 1.1.1.1.2.2 yamt
1345 1.1.1.1.2.2 yamt if (sp->st.slist_used + nstates > sp->st.slist_size) {
1346 1.1.1.1.2.2 yamt if (sp->st.slist_size == 0)
1347 1.1.1.1.2.2 yamt sp->st.slist = (ucs2_t *)
1348 1.1.1.1.2.2 yamt malloc(sizeof(ucs2_t) * (sp->st.slist_used + nstates));
1349 1.1.1.1.2.2 yamt else
1350 1.1.1.1.2.2 yamt sp->st.slist = (ucs2_t *)
1351 1.1.1.1.2.2 yamt realloc((char *) sp->st.slist,
1352 1.1.1.1.2.2 yamt sizeof(ucs2_t) * (sp->st.slist_used + nstates));
1353 1.1.1.1.2.2 yamt sp->st.slist_size = sp->st.slist_used + nstates;
1354 1.1.1.1.2.2 yamt }
1355 1.1.1.1.2.2 yamt sp->st.slist_used = nstates;
1356 1.1.1.1.2.2 yamt (void) AC_MEMCPY((char *) sp->st.slist, (char *) states,
1357 1.1.1.1.2.2 yamt sizeof(ucs2_t) * nstates);
1358 1.1.1.1.2.2 yamt }
1359 1.1.1.1.2.2 yamt
1360 1.1.1.1.2.2 yamt /*
1361 1.1.1.1.2.2 yamt * Return the ID of the DFA state representing a group of NFA states.
1362 1.1.1.1.2.2 yamt */
1363 1.1.1.1.2.2 yamt return i;
1364 1.1.1.1.2.2 yamt }
1365 1.1.1.1.2.2 yamt
1366 1.1.1.1.2.2 yamt static void
1367 1.1.1.1.2.2 yamt _ure_reduce(ucs2_t start, _ure_buffer_t *b)
1368 1.1.1.1.2.2 yamt {
1369 1.1.1.1.2.2 yamt ucs2_t i, j, state, eval, syms, rhs;
1370 1.1.1.1.2.2 yamt ucs2_t s1, s2, ns1, ns2;
1371 1.1.1.1.2.2 yamt _ure_state_t *sp;
1372 1.1.1.1.2.2 yamt _ure_symtab_t *smp;
1373 1.1.1.1.2.2 yamt
1374 1.1.1.1.2.2 yamt b->reducing = 1;
1375 1.1.1.1.2.2 yamt
1376 1.1.1.1.2.2 yamt /*
1377 1.1.1.1.2.2 yamt * Add the starting state for the reduction.
1378 1.1.1.1.2.2 yamt */
1379 1.1.1.1.2.2 yamt _ure_add_state(1, &start, b);
1380 1.1.1.1.2.2 yamt
1381 1.1.1.1.2.2 yamt /*
1382 1.1.1.1.2.2 yamt * Process each set of NFA states that get created.
1383 1.1.1.1.2.2 yamt */
1384 1.1.1.1.2.2 yamt for (i = 0; i < b->states.states_used; i++) {
1385 1.1.1.1.2.2 yamt sp = b->states.states + i;
1386 1.1.1.1.2.2 yamt
1387 1.1.1.1.2.2 yamt /*
1388 1.1.1.1.2.2 yamt * Push the current states on the stack.
1389 1.1.1.1.2.2 yamt */
1390 1.1.1.1.2.2 yamt for (j = 0; j < sp->st.slist_used; j++)
1391 1.1.1.1.2.2 yamt _ure_push(sp->st.slist[j], b);
1392 1.1.1.1.2.2 yamt
1393 1.1.1.1.2.2 yamt /*
1394 1.1.1.1.2.2 yamt * Reduce the NFA states.
1395 1.1.1.1.2.2 yamt */
1396 1.1.1.1.2.2 yamt for (j = sp->accepting = syms = 0; j < b->stack.slist_used; j++) {
1397 1.1.1.1.2.2 yamt state = b->stack.slist[j];
1398 1.1.1.1.2.2 yamt eval = 1;
1399 1.1.1.1.2.2 yamt
1400 1.1.1.1.2.2 yamt /*
1401 1.1.1.1.2.2 yamt * This inner loop is the iterative equivalent of recursively
1402 1.1.1.1.2.2 yamt * reducing subexpressions generated as a result of a reduction.
1403 1.1.1.1.2.2 yamt */
1404 1.1.1.1.2.2 yamt while (eval) {
1405 1.1.1.1.2.2 yamt switch (b->expr[state].type) {
1406 1.1.1.1.2.2 yamt case _URE_SYMBOL:
1407 1.1.1.1.2.2 yamt ns1 = _ure_make_expr(_URE_ONE, _URE_NOOP, _URE_NOOP, b);
1408 1.1.1.1.2.2 yamt _ure_add_symstate(b->expr[state].lhs, ns1, b);
1409 1.1.1.1.2.2 yamt syms++;
1410 1.1.1.1.2.2 yamt eval = 0;
1411 1.1.1.1.2.2 yamt break;
1412 1.1.1.1.2.2 yamt case _URE_ONE:
1413 1.1.1.1.2.2 yamt sp->accepting = 1;
1414 1.1.1.1.2.2 yamt eval = 0;
1415 1.1.1.1.2.2 yamt break;
1416 1.1.1.1.2.2 yamt case _URE_QUEST:
1417 1.1.1.1.2.2 yamt s1 = b->expr[state].lhs;
1418 1.1.1.1.2.2 yamt ns1 = _ure_make_expr(_URE_ONE, _URE_NOOP, _URE_NOOP, b);
1419 1.1.1.1.2.2 yamt state = _ure_make_expr(_URE_OR, ns1, s1, b);
1420 1.1.1.1.2.2 yamt break;
1421 1.1.1.1.2.2 yamt case _URE_PLUS:
1422 1.1.1.1.2.2 yamt s1 = b->expr[state].lhs;
1423 1.1.1.1.2.2 yamt ns1 = _ure_make_expr(_URE_STAR, s1, _URE_NOOP, b);
1424 1.1.1.1.2.2 yamt state = _ure_make_expr(_URE_AND, s1, ns1, b);
1425 1.1.1.1.2.2 yamt break;
1426 1.1.1.1.2.2 yamt case _URE_STAR:
1427 1.1.1.1.2.2 yamt s1 = b->expr[state].lhs;
1428 1.1.1.1.2.2 yamt ns1 = _ure_make_expr(_URE_ONE, _URE_NOOP, _URE_NOOP, b);
1429 1.1.1.1.2.2 yamt ns2 = _ure_make_expr(_URE_PLUS, s1, _URE_NOOP, b);
1430 1.1.1.1.2.2 yamt state = _ure_make_expr(_URE_OR, ns1, ns2, b);
1431 1.1.1.1.2.2 yamt break;
1432 1.1.1.1.2.2 yamt case _URE_OR:
1433 1.1.1.1.2.2 yamt s1 = b->expr[state].lhs;
1434 1.1.1.1.2.2 yamt s2 = b->expr[state].rhs;
1435 1.1.1.1.2.2 yamt _ure_push(s1, b);
1436 1.1.1.1.2.2 yamt _ure_push(s2, b);
1437 1.1.1.1.2.2 yamt eval = 0;
1438 1.1.1.1.2.2 yamt break;
1439 1.1.1.1.2.2 yamt case _URE_AND:
1440 1.1.1.1.2.2 yamt s1 = b->expr[state].lhs;
1441 1.1.1.1.2.2 yamt s2 = b->expr[state].rhs;
1442 1.1.1.1.2.2 yamt switch (b->expr[s1].type) {
1443 1.1.1.1.2.2 yamt case _URE_SYMBOL:
1444 1.1.1.1.2.2 yamt _ure_add_symstate(b->expr[s1].lhs, s2, b);
1445 1.1.1.1.2.2 yamt syms++;
1446 1.1.1.1.2.2 yamt eval = 0;
1447 1.1.1.1.2.2 yamt break;
1448 1.1.1.1.2.2 yamt case _URE_ONE:
1449 1.1.1.1.2.2 yamt state = s2;
1450 1.1.1.1.2.2 yamt break;
1451 1.1.1.1.2.2 yamt case _URE_QUEST:
1452 1.1.1.1.2.2 yamt ns1 = b->expr[s1].lhs;
1453 1.1.1.1.2.2 yamt ns2 = _ure_make_expr(_URE_AND, ns1, s2, b);
1454 1.1.1.1.2.2 yamt state = _ure_make_expr(_URE_OR, s2, ns2, b);
1455 1.1.1.1.2.2 yamt break;
1456 1.1.1.1.2.2 yamt case _URE_PLUS:
1457 1.1.1.1.2.2 yamt ns1 = b->expr[s1].lhs;
1458 1.1.1.1.2.2 yamt ns2 = _ure_make_expr(_URE_OR, s2, state, b);
1459 1.1.1.1.2.2 yamt state = _ure_make_expr(_URE_AND, ns1, ns2, b);
1460 1.1.1.1.2.2 yamt break;
1461 1.1.1.1.2.2 yamt case _URE_STAR:
1462 1.1.1.1.2.2 yamt ns1 = b->expr[s1].lhs;
1463 1.1.1.1.2.2 yamt ns2 = _ure_make_expr(_URE_AND, ns1, state, b);
1464 1.1.1.1.2.2 yamt state = _ure_make_expr(_URE_OR, s2, ns2, b);
1465 1.1.1.1.2.2 yamt break;
1466 1.1.1.1.2.2 yamt case _URE_OR:
1467 1.1.1.1.2.2 yamt ns1 = b->expr[s1].lhs;
1468 1.1.1.1.2.2 yamt ns2 = b->expr[s1].rhs;
1469 1.1.1.1.2.2 yamt ns1 = _ure_make_expr(_URE_AND, ns1, s2, b);
1470 1.1.1.1.2.2 yamt ns2 = _ure_make_expr(_URE_AND, ns2, s2, b);
1471 1.1.1.1.2.2 yamt state = _ure_make_expr(_URE_OR, ns1, ns2, b);
1472 1.1.1.1.2.2 yamt break;
1473 1.1.1.1.2.2 yamt case _URE_AND:
1474 1.1.1.1.2.2 yamt ns1 = b->expr[s1].lhs;
1475 1.1.1.1.2.2 yamt ns2 = b->expr[s1].rhs;
1476 1.1.1.1.2.2 yamt ns2 = _ure_make_expr(_URE_AND, ns2, s2, b);
1477 1.1.1.1.2.2 yamt state = _ure_make_expr(_URE_AND, ns1, ns2, b);
1478 1.1.1.1.2.2 yamt break;
1479 1.1.1.1.2.2 yamt }
1480 1.1.1.1.2.2 yamt }
1481 1.1.1.1.2.2 yamt }
1482 1.1.1.1.2.2 yamt }
1483 1.1.1.1.2.2 yamt
1484 1.1.1.1.2.2 yamt /*
1485 1.1.1.1.2.2 yamt * Clear the state stack.
1486 1.1.1.1.2.2 yamt */
1487 1.1.1.1.2.2 yamt while (_ure_pop(b) != _URE_NOOP) ;
1488 1.1.1.1.2.2 yamt
1489 1.1.1.1.2.2 yamt /*
1490 1.1.1.1.2.2 yamt * Reset the state pointer because the reduction may have moved it
1491 1.1.1.1.2.2 yamt * during a reallocation.
1492 1.1.1.1.2.2 yamt */
1493 1.1.1.1.2.2 yamt sp = b->states.states + i;
1494 1.1.1.1.2.2 yamt
1495 1.1.1.1.2.2 yamt /*
1496 1.1.1.1.2.2 yamt * Generate the DFA states for the symbols collected during the
1497 1.1.1.1.2.2 yamt * current reduction.
1498 1.1.1.1.2.2 yamt */
1499 1.1.1.1.2.2 yamt if (sp->trans_used + syms > sp->trans_size) {
1500 1.1.1.1.2.2 yamt if (sp->trans_size == 0)
1501 1.1.1.1.2.2 yamt sp->trans = (_ure_elt_t *)
1502 1.1.1.1.2.2 yamt malloc(sizeof(_ure_elt_t) * (sp->trans_used + syms));
1503 1.1.1.1.2.2 yamt else
1504 1.1.1.1.2.2 yamt sp->trans = (_ure_elt_t *)
1505 1.1.1.1.2.2 yamt realloc((char *) sp->trans,
1506 1.1.1.1.2.2 yamt sizeof(_ure_elt_t) * (sp->trans_used + syms));
1507 1.1.1.1.2.2 yamt sp->trans_size = sp->trans_used + syms;
1508 1.1.1.1.2.2 yamt }
1509 1.1.1.1.2.2 yamt
1510 1.1.1.1.2.2 yamt /*
1511 1.1.1.1.2.2 yamt * Go through the symbol table and generate the DFA state transitions
1512 1.1.1.1.2.2 yamt * for each symbol that has collected NFA states.
1513 1.1.1.1.2.2 yamt */
1514 1.1.1.1.2.2 yamt for (j = syms = 0, smp = b->symtab; j < b->symtab_used; j++, smp++) {
1515 1.1.1.1.2.2 yamt sp = b->states.states + i;
1516 1.1.1.1.2.2 yamt
1517 1.1.1.1.2.2 yamt if (smp->states.slist_used > 0) {
1518 1.1.1.1.2.2 yamt sp->trans[syms].lhs = smp->id;
1519 1.1.1.1.2.2 yamt rhs = _ure_add_state(smp->states.slist_used,
1520 1.1.1.1.2.2 yamt smp->states.slist, b);
1521 1.1.1.1.2.2 yamt /*
1522 1.1.1.1.2.2 yamt * Reset the state pointer in case the reallocation moves it
1523 1.1.1.1.2.2 yamt * in memory.
1524 1.1.1.1.2.2 yamt */
1525 1.1.1.1.2.2 yamt sp = b->states.states + i;
1526 1.1.1.1.2.2 yamt sp->trans[syms].rhs = rhs;
1527 1.1.1.1.2.2 yamt
1528 1.1.1.1.2.2 yamt smp->states.slist_used = 0;
1529 1.1.1.1.2.2 yamt syms++;
1530 1.1.1.1.2.2 yamt }
1531 1.1.1.1.2.2 yamt }
1532 1.1.1.1.2.2 yamt
1533 1.1.1.1.2.2 yamt /*
1534 1.1.1.1.2.2 yamt * Set the number of transitions actually used.
1535 1.1.1.1.2.2 yamt */
1536 1.1.1.1.2.2 yamt sp->trans_used = syms;
1537 1.1.1.1.2.2 yamt }
1538 1.1.1.1.2.2 yamt b->reducing = 0;
1539 1.1.1.1.2.2 yamt }
1540 1.1.1.1.2.2 yamt
1541 1.1.1.1.2.2 yamt static void
1542 1.1.1.1.2.2 yamt _ure_add_equiv(ucs2_t l, ucs2_t r, _ure_buffer_t *b)
1543 1.1.1.1.2.2 yamt {
1544 1.1.1.1.2.2 yamt ucs2_t tmp;
1545 1.1.1.1.2.2 yamt
1546 1.1.1.1.2.2 yamt l = b->states.states[l].id;
1547 1.1.1.1.2.2 yamt r = b->states.states[r].id;
1548 1.1.1.1.2.2 yamt
1549 1.1.1.1.2.2 yamt if (l == r)
1550 1.1.1.1.2.2 yamt return;
1551 1.1.1.1.2.2 yamt
1552 1.1.1.1.2.2 yamt if (l > r) {
1553 1.1.1.1.2.2 yamt tmp = l;
1554 1.1.1.1.2.2 yamt l = r;
1555 1.1.1.1.2.2 yamt r = tmp;
1556 1.1.1.1.2.2 yamt }
1557 1.1.1.1.2.2 yamt
1558 1.1.1.1.2.2 yamt /*
1559 1.1.1.1.2.2 yamt * Check to see if the equivalence pair already exists.
1560 1.1.1.1.2.2 yamt */
1561 1.1.1.1.2.2 yamt for (tmp = 0; tmp < b->equiv_used &&
1562 1.1.1.1.2.2 yamt (b->equiv[tmp].l != l || b->equiv[tmp].r != r);
1563 1.1.1.1.2.2 yamt tmp++) ;
1564 1.1.1.1.2.2 yamt
1565 1.1.1.1.2.2 yamt if (tmp < b->equiv_used)
1566 1.1.1.1.2.2 yamt return;
1567 1.1.1.1.2.2 yamt
1568 1.1.1.1.2.2 yamt if (b->equiv_used == b->equiv_size) {
1569 1.1.1.1.2.2 yamt if (b->equiv_size == 0)
1570 1.1.1.1.2.2 yamt b->equiv = (_ure_equiv_t *) malloc(sizeof(_ure_equiv_t) << 3);
1571 1.1.1.1.2.2 yamt else
1572 1.1.1.1.2.2 yamt b->equiv = (_ure_equiv_t *) realloc((char *) b->equiv,
1573 1.1.1.1.2.2 yamt sizeof(_ure_equiv_t) *
1574 1.1.1.1.2.2 yamt (b->equiv_size + 8));
1575 1.1.1.1.2.2 yamt b->equiv_size += 8;
1576 1.1.1.1.2.2 yamt }
1577 1.1.1.1.2.2 yamt b->equiv[b->equiv_used].l = l;
1578 1.1.1.1.2.2 yamt b->equiv[b->equiv_used].r = r;
1579 1.1.1.1.2.2 yamt b->equiv_used++;
1580 1.1.1.1.2.2 yamt }
1581 1.1.1.1.2.2 yamt
1582 1.1.1.1.2.2 yamt /*
1583 1.1.1.1.2.2 yamt * Merge the DFA states that are equivalent.
1584 1.1.1.1.2.2 yamt */
1585 1.1.1.1.2.2 yamt static void
1586 1.1.1.1.2.2 yamt _ure_merge_equiv(_ure_buffer_t *b)
1587 1.1.1.1.2.2 yamt {
1588 1.1.1.1.2.2 yamt ucs2_t i, j, k, eq, done;
1589 1.1.1.1.2.2 yamt _ure_state_t *sp1, *sp2, *ls, *rs;
1590 1.1.1.1.2.2 yamt
1591 1.1.1.1.2.2 yamt for (i = 0; i < b->states.states_used; i++) {
1592 1.1.1.1.2.2 yamt sp1 = b->states.states + i;
1593 1.1.1.1.2.2 yamt if (sp1->id != i)
1594 1.1.1.1.2.2 yamt continue;
1595 1.1.1.1.2.2 yamt for (j = 0; j < i; j++) {
1596 1.1.1.1.2.2 yamt sp2 = b->states.states + j;
1597 1.1.1.1.2.2 yamt if (sp2->id != j)
1598 1.1.1.1.2.2 yamt continue;
1599 1.1.1.1.2.2 yamt b->equiv_used = 0;
1600 1.1.1.1.2.2 yamt _ure_add_equiv(i, j, b);
1601 1.1.1.1.2.2 yamt for (eq = 0, done = 0; eq < b->equiv_used; eq++) {
1602 1.1.1.1.2.2 yamt ls = b->states.states + b->equiv[eq].l;
1603 1.1.1.1.2.2 yamt rs = b->states.states + b->equiv[eq].r;
1604 1.1.1.1.2.2 yamt if (ls->accepting != rs->accepting ||
1605 1.1.1.1.2.2 yamt ls->trans_used != rs->trans_used) {
1606 1.1.1.1.2.2 yamt done = 1;
1607 1.1.1.1.2.2 yamt break;
1608 1.1.1.1.2.2 yamt }
1609 1.1.1.1.2.2 yamt for (k = 0; k < ls->trans_used &&
1610 1.1.1.1.2.2 yamt ls->trans[k].lhs == rs->trans[k].lhs; k++) ;
1611 1.1.1.1.2.2 yamt if (k < ls->trans_used) {
1612 1.1.1.1.2.2 yamt done = 1;
1613 1.1.1.1.2.2 yamt break;
1614 1.1.1.1.2.2 yamt }
1615 1.1.1.1.2.2 yamt
1616 1.1.1.1.2.2 yamt for (k = 0; k < ls->trans_used; k++)
1617 1.1.1.1.2.2 yamt _ure_add_equiv(ls->trans[k].rhs, rs->trans[k].rhs, b);
1618 1.1.1.1.2.2 yamt }
1619 1.1.1.1.2.2 yamt if (done == 0)
1620 1.1.1.1.2.2 yamt break;
1621 1.1.1.1.2.2 yamt }
1622 1.1.1.1.2.2 yamt for (eq = 0; j < i && eq < b->equiv_used; eq++)
1623 1.1.1.1.2.2 yamt b->states.states[b->equiv[eq].r].id =
1624 1.1.1.1.2.2 yamt b->states.states[b->equiv[eq].l].id;
1625 1.1.1.1.2.2 yamt }
1626 1.1.1.1.2.2 yamt
1627 1.1.1.1.2.2 yamt /*
1628 1.1.1.1.2.2 yamt * Renumber the states appropriately.
1629 1.1.1.1.2.2 yamt */
1630 1.1.1.1.2.2 yamt for (i = eq = 0, sp1 = b->states.states; i < b->states.states_used;
1631 1.1.1.1.2.2 yamt sp1++, i++)
1632 1.1.1.1.2.2 yamt sp1->id = (sp1->id == i) ? eq++ : b->states.states[sp1->id].id;
1633 1.1.1.1.2.2 yamt }
1634 1.1.1.1.2.2 yamt
1635 1.1.1.1.2.2 yamt /*************************************************************************
1636 1.1.1.1.2.2 yamt *
1637 1.1.1.1.2.2 yamt * API.
1638 1.1.1.1.2.2 yamt *
1639 1.1.1.1.2.2 yamt *************************************************************************/
1640 1.1.1.1.2.2 yamt
1641 1.1.1.1.2.2 yamt ure_buffer_t
1642 1.1.1.1.2.2 yamt ure_buffer_create(void)
1643 1.1.1.1.2.2 yamt {
1644 1.1.1.1.2.2 yamt ure_buffer_t b;
1645 1.1.1.1.2.2 yamt
1646 1.1.1.1.2.2 yamt b = (ure_buffer_t) calloc(1, sizeof(_ure_buffer_t));
1647 1.1.1.1.2.2 yamt
1648 1.1.1.1.2.2 yamt return b;
1649 1.1.1.1.2.2 yamt }
1650 1.1.1.1.2.2 yamt
1651 1.1.1.1.2.2 yamt void
1652 1.1.1.1.2.2 yamt ure_buffer_free(ure_buffer_t buf)
1653 1.1.1.1.2.2 yamt {
1654 1.1.1.1.2.2 yamt unsigned long i;
1655 1.1.1.1.2.2 yamt
1656 1.1.1.1.2.2 yamt if (buf == 0)
1657 1.1.1.1.2.2 yamt return;
1658 1.1.1.1.2.2 yamt
1659 1.1.1.1.2.2 yamt if (buf->stack.slist_size > 0)
1660 1.1.1.1.2.2 yamt free((char *) buf->stack.slist);
1661 1.1.1.1.2.2 yamt
1662 1.1.1.1.2.2 yamt if (buf->expr_size > 0)
1663 1.1.1.1.2.2 yamt free((char *) buf->expr);
1664 1.1.1.1.2.2 yamt
1665 1.1.1.1.2.2 yamt for (i = 0; i < buf->symtab_size; i++) {
1666 1.1.1.1.2.2 yamt if (buf->symtab[i].states.slist_size > 0)
1667 1.1.1.1.2.2 yamt free((char *) buf->symtab[i].states.slist);
1668 1.1.1.1.2.2 yamt }
1669 1.1.1.1.2.2 yamt
1670 1.1.1.1.2.2 yamt if (buf->symtab_size > 0)
1671 1.1.1.1.2.2 yamt free((char *) buf->symtab);
1672 1.1.1.1.2.2 yamt
1673 1.1.1.1.2.2 yamt for (i = 0; i < buf->states.states_size; i++) {
1674 1.1.1.1.2.2 yamt if (buf->states.states[i].trans_size > 0)
1675 1.1.1.1.2.2 yamt free((char *) buf->states.states[i].trans);
1676 1.1.1.1.2.2 yamt if (buf->states.states[i].st.slist_size > 0)
1677 1.1.1.1.2.2 yamt free((char *) buf->states.states[i].st.slist);
1678 1.1.1.1.2.2 yamt }
1679 1.1.1.1.2.2 yamt
1680 1.1.1.1.2.2 yamt if (buf->states.states_size > 0)
1681 1.1.1.1.2.2 yamt free((char *) buf->states.states);
1682 1.1.1.1.2.2 yamt
1683 1.1.1.1.2.2 yamt if (buf->equiv_size > 0)
1684 1.1.1.1.2.2 yamt free((char *) buf->equiv);
1685 1.1.1.1.2.2 yamt
1686 1.1.1.1.2.2 yamt free((char *) buf);
1687 1.1.1.1.2.2 yamt }
1688 1.1.1.1.2.2 yamt
1689 1.1.1.1.2.2 yamt ure_dfa_t
1690 1.1.1.1.2.2 yamt ure_compile(ucs2_t *re, unsigned long relen, int casefold, ure_buffer_t buf)
1691 1.1.1.1.2.2 yamt {
1692 1.1.1.1.2.2 yamt ucs2_t i, j, state;
1693 1.1.1.1.2.2 yamt _ure_state_t *sp;
1694 1.1.1.1.2.2 yamt _ure_dstate_t *dsp;
1695 1.1.1.1.2.2 yamt _ure_trans_t *tp;
1696 1.1.1.1.2.2 yamt ure_dfa_t dfa;
1697 1.1.1.1.2.2 yamt
1698 1.1.1.1.2.2 yamt if (re == 0 || *re == 0 || relen == 0 || buf == 0)
1699 1.1.1.1.2.2 yamt return 0;
1700 1.1.1.1.2.2 yamt
1701 1.1.1.1.2.2 yamt /*
1702 1.1.1.1.2.2 yamt * Reset the various fields of the compilation buffer. Default the flags
1703 1.1.1.1.2.2 yamt * to indicate the presense of the "^$" pattern. If any other pattern
1704 1.1.1.1.2.2 yamt * occurs, then this flag will be removed. This is done to catch this
1705 1.1.1.1.2.2 yamt * special pattern and handle it specially when matching.
1706 1.1.1.1.2.2 yamt */
1707 1.1.1.1.2.2 yamt buf->flags = _URE_DFA_BLANKLINE | ((casefold) ? _URE_DFA_CASEFOLD : 0);
1708 1.1.1.1.2.2 yamt buf->reducing = 0;
1709 1.1.1.1.2.2 yamt buf->stack.slist_used = 0;
1710 1.1.1.1.2.2 yamt buf->expr_used = 0;
1711 1.1.1.1.2.2 yamt
1712 1.1.1.1.2.2 yamt for (i = 0; i < buf->symtab_used; i++)
1713 1.1.1.1.2.2 yamt buf->symtab[i].states.slist_used = 0;
1714 1.1.1.1.2.2 yamt buf->symtab_used = 0;
1715 1.1.1.1.2.2 yamt
1716 1.1.1.1.2.2 yamt for (i = 0; i < buf->states.states_used; i++) {
1717 1.1.1.1.2.2 yamt buf->states.states[i].st.slist_used = 0;
1718 1.1.1.1.2.2 yamt buf->states.states[i].trans_used = 0;
1719 1.1.1.1.2.2 yamt }
1720 1.1.1.1.2.2 yamt buf->states.states_used = 0;
1721 1.1.1.1.2.2 yamt
1722 1.1.1.1.2.2 yamt /*
1723 1.1.1.1.2.2 yamt * Construct the NFA. If this stage returns a 0, then an error occured or
1724 1.1.1.1.2.2 yamt * an empty expression was passed.
1725 1.1.1.1.2.2 yamt */
1726 1.1.1.1.2.2 yamt if ((state = _ure_re2nfa(re, relen, buf)) == _URE_NOOP)
1727 1.1.1.1.2.2 yamt return 0;
1728 1.1.1.1.2.2 yamt
1729 1.1.1.1.2.2 yamt /*
1730 1.1.1.1.2.2 yamt * Do the expression reduction to get the initial DFA.
1731 1.1.1.1.2.2 yamt */
1732 1.1.1.1.2.2 yamt _ure_reduce(state, buf);
1733 1.1.1.1.2.2 yamt
1734 1.1.1.1.2.2 yamt /*
1735 1.1.1.1.2.2 yamt * Merge all the equivalent DFA states.
1736 1.1.1.1.2.2 yamt */
1737 1.1.1.1.2.2 yamt _ure_merge_equiv(buf);
1738 1.1.1.1.2.2 yamt
1739 1.1.1.1.2.2 yamt /*
1740 1.1.1.1.2.2 yamt * Construct the minimal DFA.
1741 1.1.1.1.2.2 yamt */
1742 1.1.1.1.2.2 yamt dfa = (ure_dfa_t) malloc(sizeof(_ure_dfa_t));
1743 1.1.1.1.2.2 yamt (void) memset((char *) dfa, '\0', sizeof(_ure_dfa_t));
1744 1.1.1.1.2.2 yamt
1745 1.1.1.1.2.2 yamt dfa->flags = buf->flags & (_URE_DFA_CASEFOLD|_URE_DFA_BLANKLINE);
1746 1.1.1.1.2.2 yamt
1747 1.1.1.1.2.2 yamt /*
1748 1.1.1.1.2.2 yamt * Free up the NFA state groups and transfer the symbols from the buffer
1749 1.1.1.1.2.2 yamt * to the DFA.
1750 1.1.1.1.2.2 yamt */
1751 1.1.1.1.2.2 yamt for (i = 0; i < buf->symtab_size; i++) {
1752 1.1.1.1.2.2 yamt if (buf->symtab[i].states.slist_size > 0)
1753 1.1.1.1.2.2 yamt free((char *) buf->symtab[i].states.slist);
1754 1.1.1.1.2.2 yamt }
1755 1.1.1.1.2.2 yamt dfa->syms = buf->symtab;
1756 1.1.1.1.2.2 yamt dfa->nsyms = buf->symtab_used;
1757 1.1.1.1.2.2 yamt
1758 1.1.1.1.2.2 yamt buf->symtab_used = buf->symtab_size = 0;
1759 1.1.1.1.2.2 yamt
1760 1.1.1.1.2.2 yamt /*
1761 1.1.1.1.2.2 yamt * Collect the total number of states and transitions needed for the DFA.
1762 1.1.1.1.2.2 yamt */
1763 1.1.1.1.2.2 yamt for (i = state = 0, sp = buf->states.states; i < buf->states.states_used;
1764 1.1.1.1.2.2 yamt i++, sp++) {
1765 1.1.1.1.2.2 yamt if (sp->id == state) {
1766 1.1.1.1.2.2 yamt dfa->nstates++;
1767 1.1.1.1.2.2 yamt dfa->ntrans += sp->trans_used;
1768 1.1.1.1.2.2 yamt state++;
1769 1.1.1.1.2.2 yamt }
1770 1.1.1.1.2.2 yamt }
1771 1.1.1.1.2.2 yamt
1772 1.1.1.1.2.2 yamt /*
1773 1.1.1.1.2.2 yamt * Allocate enough space for the states and transitions.
1774 1.1.1.1.2.2 yamt */
1775 1.1.1.1.2.2 yamt dfa->states = (_ure_dstate_t *) malloc(sizeof(_ure_dstate_t) *
1776 1.1.1.1.2.2 yamt dfa->nstates);
1777 1.1.1.1.2.2 yamt dfa->trans = (_ure_trans_t *) malloc(sizeof(_ure_trans_t) * dfa->ntrans);
1778 1.1.1.1.2.2 yamt
1779 1.1.1.1.2.2 yamt /*
1780 1.1.1.1.2.2 yamt * Actually transfer the DFA states from the buffer.
1781 1.1.1.1.2.2 yamt */
1782 1.1.1.1.2.2 yamt dsp = dfa->states;
1783 1.1.1.1.2.2 yamt tp = dfa->trans;
1784 1.1.1.1.2.2 yamt for (i = state = 0, sp = buf->states.states; i < buf->states.states_used;
1785 1.1.1.1.2.2 yamt i++, sp++) {
1786 1.1.1.1.2.2 yamt if (sp->id == state) {
1787 1.1.1.1.2.2 yamt dsp->trans = tp;
1788 1.1.1.1.2.2 yamt dsp->ntrans = sp->trans_used;
1789 1.1.1.1.2.2 yamt dsp->accepting = sp->accepting;
1790 1.1.1.1.2.2 yamt
1791 1.1.1.1.2.2 yamt /*
1792 1.1.1.1.2.2 yamt * Add the transitions for the state.
1793 1.1.1.1.2.2 yamt */
1794 1.1.1.1.2.2 yamt for (j = 0; j < dsp->ntrans; j++, tp++) {
1795 1.1.1.1.2.2 yamt tp->symbol = sp->trans[j].lhs;
1796 1.1.1.1.2.2 yamt tp->next_state = buf->states.states[sp->trans[j].rhs].id;
1797 1.1.1.1.2.2 yamt }
1798 1.1.1.1.2.2 yamt
1799 1.1.1.1.2.2 yamt dsp++;
1800 1.1.1.1.2.2 yamt state++;
1801 1.1.1.1.2.2 yamt }
1802 1.1.1.1.2.2 yamt }
1803 1.1.1.1.2.2 yamt
1804 1.1.1.1.2.2 yamt return dfa;
1805 1.1.1.1.2.2 yamt }
1806 1.1.1.1.2.2 yamt
1807 1.1.1.1.2.2 yamt void
1808 1.1.1.1.2.2 yamt ure_dfa_free(ure_dfa_t dfa)
1809 1.1.1.1.2.2 yamt {
1810 1.1.1.1.2.2 yamt ucs2_t i;
1811 1.1.1.1.2.2 yamt
1812 1.1.1.1.2.2 yamt if (dfa == 0)
1813 1.1.1.1.2.2 yamt return;
1814 1.1.1.1.2.2 yamt
1815 1.1.1.1.2.2 yamt for (i = 0; i < dfa->nsyms; i++) {
1816 1.1.1.1.2.2 yamt if ((dfa->syms[i].type == _URE_CCLASS ||
1817 1.1.1.1.2.2 yamt dfa->syms[i].type == _URE_NCCLASS) &&
1818 1.1.1.1.2.2 yamt dfa->syms[i].sym.ccl.ranges_size > 0)
1819 1.1.1.1.2.2 yamt free((char *) dfa->syms[i].sym.ccl.ranges);
1820 1.1.1.1.2.2 yamt }
1821 1.1.1.1.2.2 yamt if (dfa->nsyms > 0)
1822 1.1.1.1.2.2 yamt free((char *) dfa->syms);
1823 1.1.1.1.2.2 yamt
1824 1.1.1.1.2.2 yamt if (dfa->nstates > 0)
1825 1.1.1.1.2.2 yamt free((char *) dfa->states);
1826 1.1.1.1.2.2 yamt if (dfa->ntrans > 0)
1827 1.1.1.1.2.2 yamt free((char *) dfa->trans);
1828 1.1.1.1.2.2 yamt free((char *) dfa);
1829 1.1.1.1.2.2 yamt }
1830 1.1.1.1.2.2 yamt
1831 1.1.1.1.2.2 yamt void
1832 1.1.1.1.2.2 yamt ure_write_dfa(ure_dfa_t dfa, FILE *out)
1833 1.1.1.1.2.2 yamt {
1834 1.1.1.1.2.2 yamt ucs2_t i, j, k, h, l;
1835 1.1.1.1.2.2 yamt _ure_dstate_t *sp;
1836 1.1.1.1.2.2 yamt _ure_symtab_t *sym;
1837 1.1.1.1.2.2 yamt _ure_range_t *rp;
1838 1.1.1.1.2.2 yamt
1839 1.1.1.1.2.2 yamt if (dfa == 0 || out == 0)
1840 1.1.1.1.2.2 yamt return;
1841 1.1.1.1.2.2 yamt
1842 1.1.1.1.2.2 yamt /*
1843 1.1.1.1.2.2 yamt * Write all the different character classes.
1844 1.1.1.1.2.2 yamt */
1845 1.1.1.1.2.2 yamt for (i = 0, sym = dfa->syms; i < dfa->nsyms; i++, sym++) {
1846 1.1.1.1.2.2 yamt if (sym->type == _URE_CCLASS || sym->type == _URE_NCCLASS) {
1847 1.1.1.1.2.2 yamt fprintf(out, "C%hd = ", sym->id);
1848 1.1.1.1.2.2 yamt if (sym->sym.ccl.ranges_used > 0) {
1849 1.1.1.1.2.2 yamt putc('[', out);
1850 1.1.1.1.2.2 yamt if (sym->type == _URE_NCCLASS)
1851 1.1.1.1.2.2 yamt putc('^', out);
1852 1.1.1.1.2.2 yamt }
1853 1.1.1.1.2.2 yamt if (sym->props != 0) {
1854 1.1.1.1.2.2 yamt if (sym->type == _URE_NCCLASS)
1855 1.1.1.1.2.2 yamt fprintf(out, "\\P");
1856 1.1.1.1.2.2 yamt else
1857 1.1.1.1.2.2 yamt fprintf(out, "\\p");
1858 1.1.1.1.2.2 yamt for (k = h = 0; k < 32; k++) {
1859 1.1.1.1.2.2 yamt if (sym->props & (1 << k)) {
1860 1.1.1.1.2.2 yamt if (h != 0)
1861 1.1.1.1.2.2 yamt putc(',', out);
1862 1.1.1.1.2.2 yamt fprintf(out, "%hd", k + 1);
1863 1.1.1.1.2.2 yamt h = 1;
1864 1.1.1.1.2.2 yamt }
1865 1.1.1.1.2.2 yamt }
1866 1.1.1.1.2.2 yamt }
1867 1.1.1.1.2.2 yamt /*
1868 1.1.1.1.2.2 yamt * Dump the ranges.
1869 1.1.1.1.2.2 yamt */
1870 1.1.1.1.2.2 yamt for (k = 0, rp = sym->sym.ccl.ranges;
1871 1.1.1.1.2.2 yamt k < sym->sym.ccl.ranges_used; k++, rp++) {
1872 1.1.1.1.2.2 yamt /*
1873 1.1.1.1.2.2 yamt * Check for UTF16 characters.
1874 1.1.1.1.2.2 yamt */
1875 1.1.1.1.2.2 yamt if (0x10000 <= rp->min_code &&
1876 1.1.1.1.2.2 yamt rp->min_code <= 0x10ffff) {
1877 1.1.1.1.2.2 yamt h = (ucs2_t) (((rp->min_code - 0x10000) >> 10) + 0xd800);
1878 1.1.1.1.2.2 yamt l = (ucs2_t) (((rp->min_code - 0x10000) & 1023) + 0xdc00);
1879 1.1.1.1.2.2 yamt fprintf(out, "\\x%04hX\\x%04hX", h, l);
1880 1.1.1.1.2.2 yamt } else
1881 1.1.1.1.2.2 yamt fprintf(out, "\\x%04lX", rp->min_code & 0xffff);
1882 1.1.1.1.2.2 yamt if (rp->max_code != rp->min_code) {
1883 1.1.1.1.2.2 yamt putc('-', out);
1884 1.1.1.1.2.2 yamt if (rp->max_code >= 0x10000 &&
1885 1.1.1.1.2.2 yamt rp->max_code <= 0x10ffff) {
1886 1.1.1.1.2.2 yamt h = (ucs2_t) (((rp->max_code - 0x10000) >> 10) + 0xd800);
1887 1.1.1.1.2.2 yamt l = (ucs2_t) (((rp->max_code - 0x10000) & 1023) + 0xdc00);
1888 1.1.1.1.2.2 yamt fprintf(out, "\\x%04hX\\x%04hX", h, l);
1889 1.1.1.1.2.2 yamt } else
1890 1.1.1.1.2.2 yamt fprintf(out, "\\x%04lX", rp->max_code & 0xffff);
1891 1.1.1.1.2.2 yamt }
1892 1.1.1.1.2.2 yamt }
1893 1.1.1.1.2.2 yamt if (sym->sym.ccl.ranges_used > 0)
1894 1.1.1.1.2.2 yamt putc(']', out);
1895 1.1.1.1.2.2 yamt putc('\n', out);
1896 1.1.1.1.2.2 yamt }
1897 1.1.1.1.2.2 yamt }
1898 1.1.1.1.2.2 yamt
1899 1.1.1.1.2.2 yamt for (i = 0, sp = dfa->states; i < dfa->nstates; i++, sp++) {
1900 1.1.1.1.2.2 yamt fprintf(out, "S%hd = ", i);
1901 1.1.1.1.2.2 yamt if (sp->accepting) {
1902 1.1.1.1.2.2 yamt fprintf(out, "1 ");
1903 1.1.1.1.2.2 yamt if (sp->ntrans)
1904 1.1.1.1.2.2 yamt fprintf(out, "| ");
1905 1.1.1.1.2.2 yamt }
1906 1.1.1.1.2.2 yamt for (j = 0; j < sp->ntrans; j++) {
1907 1.1.1.1.2.2 yamt if (j > 0)
1908 1.1.1.1.2.2 yamt fprintf(out, "| ");
1909 1.1.1.1.2.2 yamt
1910 1.1.1.1.2.2 yamt sym = dfa->syms + sp->trans[j].symbol;
1911 1.1.1.1.2.2 yamt switch (sym->type) {
1912 1.1.1.1.2.2 yamt case _URE_CHAR:
1913 1.1.1.1.2.2 yamt if (0x10000 <= sym->sym.chr && sym->sym.chr <= 0x10ffff) {
1914 1.1.1.1.2.2 yamt /*
1915 1.1.1.1.2.2 yamt * Take care of UTF16 characters.
1916 1.1.1.1.2.2 yamt */
1917 1.1.1.1.2.2 yamt h = (ucs2_t) (((sym->sym.chr - 0x10000) >> 10) + 0xd800);
1918 1.1.1.1.2.2 yamt l = (ucs2_t) (((sym->sym.chr - 0x10000) & 1023) + 0xdc00);
1919 1.1.1.1.2.2 yamt fprintf(out, "\\x%04hX\\x%04hX ", h, l);
1920 1.1.1.1.2.2 yamt } else
1921 1.1.1.1.2.2 yamt fprintf(out, "\\x%04lX ", sym->sym.chr & 0xffff);
1922 1.1.1.1.2.2 yamt break;
1923 1.1.1.1.2.2 yamt case _URE_ANY_CHAR:
1924 1.1.1.1.2.2 yamt fprintf(out, "<any> ");
1925 1.1.1.1.2.2 yamt break;
1926 1.1.1.1.2.2 yamt case _URE_BOL_ANCHOR:
1927 1.1.1.1.2.2 yamt fprintf(out, "<bol-anchor> ");
1928 1.1.1.1.2.2 yamt break;
1929 1.1.1.1.2.2 yamt case _URE_EOL_ANCHOR:
1930 1.1.1.1.2.2 yamt fprintf(out, "<eol-anchor> ");
1931 1.1.1.1.2.2 yamt break;
1932 1.1.1.1.2.2 yamt case _URE_CCLASS:
1933 1.1.1.1.2.2 yamt case _URE_NCCLASS:
1934 1.1.1.1.2.2 yamt fprintf(out, "[C%hd] ", sym->id);
1935 1.1.1.1.2.2 yamt break;
1936 1.1.1.1.2.2 yamt }
1937 1.1.1.1.2.2 yamt fprintf(out, "S%hd", sp->trans[j].next_state);
1938 1.1.1.1.2.2 yamt if (j + 1 < sp->ntrans)
1939 1.1.1.1.2.2 yamt putc(' ', out);
1940 1.1.1.1.2.2 yamt }
1941 1.1.1.1.2.2 yamt putc('\n', out);
1942 1.1.1.1.2.2 yamt }
1943 1.1.1.1.2.2 yamt }
1944 1.1.1.1.2.2 yamt
1945 1.1.1.1.2.2 yamt #define _ure_issep(cc) ((cc) == '\n' || (cc) == '\r' || (cc) == 0x2028 ||\
1946 1.1.1.1.2.2 yamt (cc) == 0x2029)
1947 1.1.1.1.2.2 yamt
1948 1.1.1.1.2.2 yamt int
1949 1.1.1.1.2.2 yamt ure_exec(ure_dfa_t dfa, int flags, ucs2_t *text, unsigned long textlen,
1950 1.1.1.1.2.2 yamt unsigned long *match_start, unsigned long *match_end)
1951 1.1.1.1.2.2 yamt {
1952 1.1.1.1.2.2 yamt int i, j, matched, found, skip;
1953 1.1.1.1.2.2 yamt unsigned long ms, me;
1954 1.1.1.1.2.2 yamt ucs4_t c;
1955 1.1.1.1.2.2 yamt ucs2_t *sp, *ep, *lp;
1956 1.1.1.1.2.2 yamt _ure_dstate_t *stp;
1957 1.1.1.1.2.2 yamt _ure_symtab_t *sym;
1958 1.1.1.1.2.2 yamt _ure_range_t *rp;
1959 1.1.1.1.2.2 yamt
1960 1.1.1.1.2.2 yamt if (dfa == 0 || text == 0)
1961 1.1.1.1.2.2 yamt return 0;
1962 1.1.1.1.2.2 yamt
1963 1.1.1.1.2.2 yamt /*
1964 1.1.1.1.2.2 yamt * Handle the special case of an empty string matching the "^$" pattern.
1965 1.1.1.1.2.2 yamt */
1966 1.1.1.1.2.2 yamt if (textlen == 0 && (dfa->flags & _URE_DFA_BLANKLINE)) {
1967 1.1.1.1.2.2 yamt *match_start = *match_end = 0;
1968 1.1.1.1.2.2 yamt return 1;
1969 1.1.1.1.2.2 yamt }
1970 1.1.1.1.2.2 yamt
1971 1.1.1.1.2.2 yamt sp = text;
1972 1.1.1.1.2.2 yamt ep = sp + textlen;
1973 1.1.1.1.2.2 yamt
1974 1.1.1.1.2.2 yamt ms = me = ~0;
1975 1.1.1.1.2.2 yamt
1976 1.1.1.1.2.2 yamt stp = dfa->states;
1977 1.1.1.1.2.2 yamt
1978 1.1.1.1.2.2 yamt for (found = skip = 0; found == 0 && sp < ep; ) {
1979 1.1.1.1.2.2 yamt lp = sp;
1980 1.1.1.1.2.2 yamt c = *sp++;
1981 1.1.1.1.2.2 yamt
1982 1.1.1.1.2.2 yamt /*
1983 1.1.1.1.2.2 yamt * Check to see if this is a high surrogate that should be
1984 1.1.1.1.2.2 yamt * combined with a following low surrogate.
1985 1.1.1.1.2.2 yamt */
1986 1.1.1.1.2.2 yamt if (sp < ep && 0xd800 <= c && c <= 0xdbff &&
1987 1.1.1.1.2.2 yamt 0xdc00 <= *sp && *sp <= 0xdfff)
1988 1.1.1.1.2.2 yamt c = 0x10000 + (((c & 0x03ff) << 10) | (*sp++ & 0x03ff));
1989 1.1.1.1.2.2 yamt
1990 1.1.1.1.2.2 yamt /*
1991 1.1.1.1.2.2 yamt * Determine if the character is non-spacing and should be skipped.
1992 1.1.1.1.2.2 yamt */
1993 1.1.1.1.2.2 yamt if (_ure_matches_properties(_URE_NONSPACING, c) &&
1994 1.1.1.1.2.2 yamt (flags & URE_IGNORE_NONSPACING)) {
1995 1.1.1.1.2.2 yamt sp++;
1996 1.1.1.1.2.2 yamt continue;
1997 1.1.1.1.2.2 yamt }
1998 1.1.1.1.2.2 yamt
1999 1.1.1.1.2.2 yamt if (dfa->flags & _URE_DFA_CASEFOLD)
2000 1.1.1.1.2.2 yamt c = _ure_tolower(c);
2001 1.1.1.1.2.2 yamt
2002 1.1.1.1.2.2 yamt /*
2003 1.1.1.1.2.2 yamt * See if one of the transitions matches.
2004 1.1.1.1.2.2 yamt */
2005 1.1.1.1.2.2 yamt for (i = 0, matched = 0; matched == 0 && i < stp->ntrans; i++) {
2006 1.1.1.1.2.2 yamt sym = dfa->syms + stp->trans[i].symbol;
2007 1.1.1.1.2.2 yamt switch (sym->type) {
2008 1.1.1.1.2.2 yamt case _URE_ANY_CHAR:
2009 1.1.1.1.2.2 yamt if ((flags & URE_DOT_MATCHES_SEPARATORS) ||
2010 1.1.1.1.2.2 yamt !_ure_issep(c))
2011 1.1.1.1.2.2 yamt matched = 1;
2012 1.1.1.1.2.2 yamt break;
2013 1.1.1.1.2.2 yamt case _URE_CHAR:
2014 1.1.1.1.2.2 yamt if (c == sym->sym.chr)
2015 1.1.1.1.2.2 yamt matched = 1;
2016 1.1.1.1.2.2 yamt break;
2017 1.1.1.1.2.2 yamt case _URE_BOL_ANCHOR:
2018 1.1.1.1.2.2 yamt if (lp == text) {
2019 1.1.1.1.2.2 yamt sp = lp;
2020 1.1.1.1.2.2 yamt matched = 1;
2021 1.1.1.1.2.2 yamt } else if (_ure_issep(c)) {
2022 1.1.1.1.2.2 yamt if (c == '\r' && sp < ep && *sp == '\n')
2023 1.1.1.1.2.2 yamt sp++;
2024 1.1.1.1.2.2 yamt lp = sp;
2025 1.1.1.1.2.2 yamt matched = 1;
2026 1.1.1.1.2.2 yamt }
2027 1.1.1.1.2.2 yamt break;
2028 1.1.1.1.2.2 yamt case _URE_EOL_ANCHOR:
2029 1.1.1.1.2.2 yamt if (_ure_issep(c)) {
2030 1.1.1.1.2.2 yamt /*
2031 1.1.1.1.2.2 yamt * Put the pointer back before the separator so the match
2032 1.1.1.1.2.2 yamt * end position will be correct. This case will also
2033 1.1.1.1.2.2 yamt * cause the `sp' pointer to be advanced over the current
2034 1.1.1.1.2.2 yamt * separator once the match end point has been recorded.
2035 1.1.1.1.2.2 yamt */
2036 1.1.1.1.2.2 yamt sp = lp;
2037 1.1.1.1.2.2 yamt matched = 1;
2038 1.1.1.1.2.2 yamt }
2039 1.1.1.1.2.2 yamt break;
2040 1.1.1.1.2.2 yamt case _URE_CCLASS:
2041 1.1.1.1.2.2 yamt case _URE_NCCLASS:
2042 1.1.1.1.2.2 yamt if (sym->props != 0)
2043 1.1.1.1.2.2 yamt matched = _ure_matches_properties(sym->props, c);
2044 1.1.1.1.2.2 yamt for (j = 0, rp = sym->sym.ccl.ranges;
2045 1.1.1.1.2.2 yamt j < sym->sym.ccl.ranges_used; j++, rp++) {
2046 1.1.1.1.2.2 yamt if (rp->min_code <= c && c <= rp->max_code)
2047 1.1.1.1.2.2 yamt matched = 1;
2048 1.1.1.1.2.2 yamt }
2049 1.1.1.1.2.2 yamt if (sym->type == _URE_NCCLASS)
2050 1.1.1.1.2.2 yamt matched = !matched;
2051 1.1.1.1.2.2 yamt break;
2052 1.1.1.1.2.2 yamt }
2053 1.1.1.1.2.2 yamt
2054 1.1.1.1.2.2 yamt if (matched) {
2055 1.1.1.1.2.2 yamt if (ms == ~0UL)
2056 1.1.1.1.2.2 yamt ms = lp - text;
2057 1.1.1.1.2.2 yamt else
2058 1.1.1.1.2.2 yamt me = sp - text;
2059 1.1.1.1.2.2 yamt stp = dfa->states + stp->trans[i].next_state;
2060 1.1.1.1.2.2 yamt
2061 1.1.1.1.2.2 yamt /*
2062 1.1.1.1.2.2 yamt * If the match was an EOL anchor, adjust the pointer past the
2063 1.1.1.1.2.2 yamt * separator that caused the match. The correct match
2064 1.1.1.1.2.2 yamt * position has been recorded already.
2065 1.1.1.1.2.2 yamt */
2066 1.1.1.1.2.2 yamt if (sym->type == _URE_EOL_ANCHOR) {
2067 1.1.1.1.2.2 yamt /*
2068 1.1.1.1.2.2 yamt * Skip the character that caused the match.
2069 1.1.1.1.2.2 yamt */
2070 1.1.1.1.2.2 yamt sp++;
2071 1.1.1.1.2.2 yamt
2072 1.1.1.1.2.2 yamt /*
2073 1.1.1.1.2.2 yamt * Handle the infamous CRLF situation.
2074 1.1.1.1.2.2 yamt */
2075 1.1.1.1.2.2 yamt if (sp < ep && c == '\r' && *sp == '\n')
2076 1.1.1.1.2.2 yamt sp++;
2077 1.1.1.1.2.2 yamt }
2078 1.1.1.1.2.2 yamt }
2079 1.1.1.1.2.2 yamt }
2080 1.1.1.1.2.2 yamt
2081 1.1.1.1.2.2 yamt if (matched == 0) {
2082 1.1.1.1.2.2 yamt if (stp->accepting == 0) {
2083 1.1.1.1.2.2 yamt /*
2084 1.1.1.1.2.2 yamt * If the last state was not accepting, then reset
2085 1.1.1.1.2.2 yamt * and start over.
2086 1.1.1.1.2.2 yamt */
2087 1.1.1.1.2.2 yamt stp = dfa->states;
2088 1.1.1.1.2.2 yamt ms = me = ~0;
2089 1.1.1.1.2.2 yamt } else
2090 1.1.1.1.2.2 yamt /*
2091 1.1.1.1.2.2 yamt * The last state was accepting, so terminate the matching
2092 1.1.1.1.2.2 yamt * loop to avoid more work.
2093 1.1.1.1.2.2 yamt */
2094 1.1.1.1.2.2 yamt found = 1;
2095 1.1.1.1.2.2 yamt } else if (sp == ep) {
2096 1.1.1.1.2.2 yamt if (!stp->accepting) {
2097 1.1.1.1.2.2 yamt /*
2098 1.1.1.1.2.2 yamt * This ugly hack is to make sure the end-of-line anchors
2099 1.1.1.1.2.2 yamt * match when the source text hits the end. This is only done
2100 1.1.1.1.2.2 yamt * if the last subexpression matches.
2101 1.1.1.1.2.2 yamt */
2102 1.1.1.1.2.2 yamt for (i = 0; found == 0 && i < stp->ntrans; i++) {
2103 1.1.1.1.2.2 yamt sym = dfa->syms + stp->trans[i].symbol;
2104 1.1.1.1.2.2 yamt if (sym->type ==_URE_EOL_ANCHOR) {
2105 1.1.1.1.2.2 yamt stp = dfa->states + stp->trans[i].next_state;
2106 1.1.1.1.2.2 yamt if (stp->accepting) {
2107 1.1.1.1.2.2 yamt me = sp - text;
2108 1.1.1.1.2.2 yamt found = 1;
2109 1.1.1.1.2.2 yamt } else
2110 1.1.1.1.2.2 yamt break;
2111 1.1.1.1.2.2 yamt }
2112 1.1.1.1.2.2 yamt }
2113 1.1.1.1.2.2 yamt } else {
2114 1.1.1.1.2.2 yamt /*
2115 1.1.1.1.2.2 yamt * Make sure any conditions that match all the way to the end
2116 1.1.1.1.2.2 yamt * of the string match.
2117 1.1.1.1.2.2 yamt */
2118 1.1.1.1.2.2 yamt found = 1;
2119 1.1.1.1.2.2 yamt me = sp - text;
2120 1.1.1.1.2.2 yamt }
2121 1.1.1.1.2.2 yamt }
2122 1.1.1.1.2.2 yamt }
2123 1.1.1.1.2.2 yamt
2124 1.1.1.1.2.2 yamt if (found == 0)
2125 1.1.1.1.2.2 yamt ms = me = ~0;
2126 1.1.1.1.2.2 yamt
2127 1.1.1.1.2.2 yamt *match_start = ms;
2128 1.1.1.1.2.2 yamt *match_end = me;
2129 1.1.1.1.2.2 yamt
2130 1.1.1.1.2.2 yamt return (ms != ~0UL) ? 1 : 0;
2131 1.1.1.1.2.2 yamt }
2132