1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin * *
3da2e3ebdSchin * This software is part of the ast package *
4*3e14f97fSRoger A. Faulkner * Copyright (c) 1985-2010 AT&T Intellectual Property *
5da2e3ebdSchin * and is licensed under the *
6da2e3ebdSchin * Common Public License, Version 1.0 *
77c2fbfb3SApril Chin * by AT&T Intellectual Property *
8da2e3ebdSchin * *
9da2e3ebdSchin * A copy of the License is available at *
10da2e3ebdSchin * http://www.opensource.org/licenses/cpl1.0.txt *
11da2e3ebdSchin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
12da2e3ebdSchin * *
13da2e3ebdSchin * Information and Software Systems Research *
14da2e3ebdSchin * AT&T Research *
15da2e3ebdSchin * Florham Park NJ *
16da2e3ebdSchin * *
17da2e3ebdSchin * Glenn Fowler <gsf@research.att.com> *
18da2e3ebdSchin * David Korn <dgk@research.att.com> *
19da2e3ebdSchin * Phong Vo <kpv@research.att.com> *
20da2e3ebdSchin * *
21da2e3ebdSchin ***********************************************************************/
22da2e3ebdSchin #pragma prototyped
23da2e3ebdSchin
24da2e3ebdSchin /*
25da2e3ebdSchin * posix regex compiler
26da2e3ebdSchin */
27da2e3ebdSchin
28da2e3ebdSchin #include "reglib.h"
29da2e3ebdSchin
30da2e3ebdSchin #if _PACKAGE_ast
31da2e3ebdSchin #include "lclib.h"
32da2e3ebdSchin #endif
33da2e3ebdSchin
34da2e3ebdSchin #define serialize re_serialize /* hp.ia64 <unistd.h>! */
35da2e3ebdSchin
36da2e3ebdSchin #define C_ESC (-1)
37da2e3ebdSchin #define C_MB (-2)
38da2e3ebdSchin
39da2e3ebdSchin #if _AST_REGEX_DEBUG
40da2e3ebdSchin
41da2e3ebdSchin #define DEBUG_TEST(f,y,n) ((debug&(debug_flag=f))?(y):(n))
42da2e3ebdSchin #define DEBUG_CODE(f,y,n) do if(debug&(f)){y}else{n} while(0)
43da2e3ebdSchin #define DEBUG_INIT() do { char* t; if (!debug) { debug = 0x80000000; if (t = getenv("_AST_regex_comp_debug")) debug |= strtoul(t, NiL, 0); } } while (0)
44da2e3ebdSchin
45da2e3ebdSchin static unsigned long debug;
46da2e3ebdSchin static unsigned long debug_flag;
47da2e3ebdSchin
48da2e3ebdSchin #else
49da2e3ebdSchin
50da2e3ebdSchin #define DEBUG_INIT()
51da2e3ebdSchin #define DEBUG_TEST(f,y,n) (n)
52da2e3ebdSchin #define DEBUG_CODE(f,y,n) do {n} while(0)
53da2e3ebdSchin
54da2e3ebdSchin #endif
55da2e3ebdSchin
56da2e3ebdSchin #if _PACKAGE_ast
57da2e3ebdSchin
58da2e3ebdSchin typedef struct Cchr_s
59da2e3ebdSchin {
60da2e3ebdSchin Dtlink_t lnk;
61da2e3ebdSchin unsigned char nam[2];
62da2e3ebdSchin Ckey_t key;
63da2e3ebdSchin } Cchr_t;
64da2e3ebdSchin
65da2e3ebdSchin #endif
66da2e3ebdSchin
67da2e3ebdSchin #define eat(p) do{if ((p)->token.push)(p)->token.push=0;else (p)->cursor+=(p)->token.len;}while (0)
68da2e3ebdSchin
69da2e3ebdSchin /*
70da2e3ebdSchin * determine whether greedy matching will work, i.e. produce
71da2e3ebdSchin * the best match first. such expressions are "easy", and
72da2e3ebdSchin * need no backtracking once a complete match is found.
73da2e3ebdSchin * if an expression has backreferences or alts it's hard
74da2e3ebdSchin * else if it has only one closure it's easy
75da2e3ebdSchin * else if all closures are simple (i.e. one-character) it's easy
76da2e3ebdSchin * else it's hard.
77da2e3ebdSchin */
78da2e3ebdSchin
79da2e3ebdSchin typedef struct Stats_s
80da2e3ebdSchin {
81da2e3ebdSchin unsigned long l; /* min length to left of x */
82da2e3ebdSchin unsigned long k; /* min length to left of y */
83da2e3ebdSchin unsigned long m; /* min length */
84da2e3ebdSchin unsigned long n; /* max length */
85da2e3ebdSchin unsigned short a; /* number of alternations */
86da2e3ebdSchin unsigned short b; /* number of backrefs */
87da2e3ebdSchin unsigned short c; /* number of closures */
88*3e14f97fSRoger A. Faulkner unsigned short e; /* $ */
89da2e3ebdSchin unsigned short i; /* number of negations */
90da2e3ebdSchin unsigned short p; /* number of named subexpressions */
91da2e3ebdSchin unsigned short s; /* number of simple closures */
92da2e3ebdSchin unsigned short t; /* number of tries */
93da2e3ebdSchin unsigned short u; /* number of unnamed subexpressions */
94da2e3ebdSchin Rex_t* x; /* max length REX_STRING */
95da2e3ebdSchin Rex_t* y; /* max length REX_TRIE */
96da2e3ebdSchin } Stats_t;
97da2e3ebdSchin
98da2e3ebdSchin typedef struct Token_s
99da2e3ebdSchin {
100da2e3ebdSchin unsigned long min;
101da2e3ebdSchin unsigned long max;
102da2e3ebdSchin short lex;
103da2e3ebdSchin short len;
104da2e3ebdSchin short esc;
105da2e3ebdSchin short att;
106da2e3ebdSchin short push;
107da2e3ebdSchin } Token_t;
108da2e3ebdSchin
109da2e3ebdSchin typedef struct Cenv_s
110da2e3ebdSchin {
111da2e3ebdSchin int delimiter; /* pattern delimiter */
112da2e3ebdSchin int error; /* last error */
113da2e3ebdSchin int explicit; /* explicit match on this char */
114da2e3ebdSchin int mappeddot; /* inverse mapped '.' */
115da2e3ebdSchin int mappednewline; /* inverse mapped '\n' */
116da2e3ebdSchin int mappedslash; /* inverse mapped '/' */
117da2e3ebdSchin regflags_t flags; /* flags arg to regcomp */
118da2e3ebdSchin int type; /* BRE,ERE,ARE,SRE,KRE */
119da2e3ebdSchin unsigned char* cursor; /* curent point in re */
120da2e3ebdSchin unsigned char* pattern; /* the original pattern */
121da2e3ebdSchin unsigned char* literal; /* literal restart pattern */
122da2e3ebdSchin int parno; /* number of last open paren */
123da2e3ebdSchin int parnest; /* paren nest count */
124da2e3ebdSchin int posixkludge; /* to make * nonspecial */
12534f9b3eeSRoland Mainz int regexp; /* <regexp.h> compatibility */
126da2e3ebdSchin Token_t token; /* token lookahead */
127da2e3ebdSchin Stats_t stats; /* RE statistics */
128da2e3ebdSchin int terminator; /* pattern terminator */
129da2e3ebdSchin Rex_t* paren[2*(BACK_REF_MAX+2)];
130da2e3ebdSchin /* paren[i]!=0 if \i defined */
131da2e3ebdSchin regex_t* regex; /* user handle */
132da2e3ebdSchin regdisc_t* disc; /* user discipline */
133da2e3ebdSchin unsigned char* map; /* external to native ccode map */
134da2e3ebdSchin unsigned char* MAP; /* fold and/or map */
135da2e3ebdSchin } Cenv_t;
136da2e3ebdSchin
137da2e3ebdSchin /*
138da2e3ebdSchin * allocate a new Rex_t node
139da2e3ebdSchin */
140da2e3ebdSchin
141da2e3ebdSchin static Rex_t*
node(Cenv_t * env,int type,int lo,int hi,size_t extra)142da2e3ebdSchin node(Cenv_t* env, int type, int lo, int hi, size_t extra)
143da2e3ebdSchin {
144da2e3ebdSchin register Rex_t* e;
145da2e3ebdSchin
146da2e3ebdSchin if (e = (Rex_t*)alloc(env->disc, 0, sizeof(Rex_t) + extra))
147da2e3ebdSchin {
148da2e3ebdSchin memset(e, 0, sizeof(Rex_t) + extra);
149da2e3ebdSchin e->type = type;
150da2e3ebdSchin e->marked = 0;
151da2e3ebdSchin e->lo = lo;
152da2e3ebdSchin e->hi = hi;
153da2e3ebdSchin e->flags = env->flags;
154da2e3ebdSchin e->map = (e->flags & REG_ICASE) ? env->MAP : env->map;
155da2e3ebdSchin e->explicit = env->explicit;
156da2e3ebdSchin if (extra)
157da2e3ebdSchin e->re.data = (char*)e + sizeof(Rex_t);
158da2e3ebdSchin }
159da2e3ebdSchin return e;
160da2e3ebdSchin }
161da2e3ebdSchin
162da2e3ebdSchin /*
163da2e3ebdSchin * free a Trie_node_t node
164da2e3ebdSchin */
165da2e3ebdSchin
166da2e3ebdSchin static void
triedrop(regdisc_t * disc,Trie_node_t * e)167da2e3ebdSchin triedrop(regdisc_t* disc, Trie_node_t* e)
168da2e3ebdSchin {
169da2e3ebdSchin if (e)
170da2e3ebdSchin {
171da2e3ebdSchin triedrop(disc, e->son);
172da2e3ebdSchin triedrop(disc, e->sib);
173da2e3ebdSchin alloc(disc, e, 0);
174da2e3ebdSchin }
175da2e3ebdSchin }
176da2e3ebdSchin
177da2e3ebdSchin /*
178da2e3ebdSchin * free a Rex_t node
179da2e3ebdSchin */
180da2e3ebdSchin
181da2e3ebdSchin void
drop(regdisc_t * disc,Rex_t * e)182da2e3ebdSchin drop(regdisc_t* disc, Rex_t* e)
183da2e3ebdSchin {
184da2e3ebdSchin int i;
185da2e3ebdSchin Rex_t* x;
186da2e3ebdSchin
187da2e3ebdSchin if (e && !(disc->re_flags & REG_NOFREE))
188da2e3ebdSchin do
189da2e3ebdSchin {
190da2e3ebdSchin switch (e->type)
191da2e3ebdSchin {
192da2e3ebdSchin case REX_ALT:
193da2e3ebdSchin case REX_CONJ:
194da2e3ebdSchin drop(disc, e->re.group.expr.binary.left);
195da2e3ebdSchin drop(disc, e->re.group.expr.binary.right);
196da2e3ebdSchin break;
197da2e3ebdSchin case REX_GROUP:
198da2e3ebdSchin case REX_GROUP_AHEAD:
199da2e3ebdSchin case REX_GROUP_AHEAD_NOT:
200da2e3ebdSchin case REX_GROUP_BEHIND:
201da2e3ebdSchin case REX_GROUP_BEHIND_NOT:
202da2e3ebdSchin case REX_GROUP_CUT:
203da2e3ebdSchin case REX_NEG:
204da2e3ebdSchin case REX_REP:
205da2e3ebdSchin drop(disc, e->re.group.expr.rex);
206da2e3ebdSchin break;
207da2e3ebdSchin case REX_TRIE:
208da2e3ebdSchin for (i = 0; i <= UCHAR_MAX; i++)
209da2e3ebdSchin triedrop(disc, e->re.trie.root[i]);
210da2e3ebdSchin break;
211da2e3ebdSchin }
212da2e3ebdSchin x = e->next;
213da2e3ebdSchin alloc(disc, e, 0);
214da2e3ebdSchin } while (e = x);
215da2e3ebdSchin }
216da2e3ebdSchin
217da2e3ebdSchin /*
218da2e3ebdSchin * mark e and descendants minimal
219da2e3ebdSchin */
220da2e3ebdSchin
221da2e3ebdSchin static void
mark(register Rex_t * e,int set)222da2e3ebdSchin mark(register Rex_t* e, int set)
223da2e3ebdSchin {
224da2e3ebdSchin if (e && !e->marked)
225da2e3ebdSchin do
226da2e3ebdSchin {
227da2e3ebdSchin e->marked = 1;
228da2e3ebdSchin if (set)
229da2e3ebdSchin e->flags |= REG_MINIMAL;
230da2e3ebdSchin else
231da2e3ebdSchin e->flags &= ~REG_MINIMAL;
232da2e3ebdSchin switch (e->type)
233da2e3ebdSchin {
234da2e3ebdSchin case REX_ALT:
235da2e3ebdSchin case REX_CONJ:
236da2e3ebdSchin case REX_GROUP_COND:
237da2e3ebdSchin if (e->re.group.expr.binary.left)
238da2e3ebdSchin mark(e->re.group.expr.binary.left, set);
239da2e3ebdSchin if (e->re.group.expr.binary.right)
240da2e3ebdSchin mark(e->re.group.expr.binary.right, set);
241da2e3ebdSchin break;
242da2e3ebdSchin case REX_GROUP:
243da2e3ebdSchin case REX_GROUP_AHEAD:
244da2e3ebdSchin case REX_GROUP_AHEAD_NOT:
245da2e3ebdSchin case REX_GROUP_BEHIND:
246da2e3ebdSchin case REX_GROUP_BEHIND_NOT:
247da2e3ebdSchin case REX_GROUP_CUT:
248da2e3ebdSchin case REX_NEG:
249da2e3ebdSchin case REX_REP:
250da2e3ebdSchin case REX_TRIE:
251da2e3ebdSchin mark(e->re.group.expr.rex, set);
252da2e3ebdSchin break;
253da2e3ebdSchin }
254da2e3ebdSchin } while (e = e->next);
255da2e3ebdSchin }
256da2e3ebdSchin
257da2e3ebdSchin /*
258da2e3ebdSchin * assign subexpression numbers by a preorder tree walk
259da2e3ebdSchin */
260da2e3ebdSchin
261da2e3ebdSchin static int
serialize(Cenv_t * env,Rex_t * e,int n)262da2e3ebdSchin serialize(Cenv_t* env, Rex_t* e, int n)
263da2e3ebdSchin {
264da2e3ebdSchin do
265da2e3ebdSchin {
266da2e3ebdSchin e->serial = n++;
267da2e3ebdSchin switch (e->type)
268da2e3ebdSchin {
269da2e3ebdSchin case REX_ALT:
270da2e3ebdSchin case REX_GROUP_COND:
271da2e3ebdSchin if (e->re.group.expr.binary.left)
272da2e3ebdSchin n = serialize(env, e->re.group.expr.binary.left, n);
273da2e3ebdSchin e->re.group.expr.binary.serial = n++;
274da2e3ebdSchin if (e->re.group.expr.binary.right)
275da2e3ebdSchin n = serialize(env, e->re.group.expr.binary.right, n);
276da2e3ebdSchin break;
277da2e3ebdSchin case REX_CONJ:
278da2e3ebdSchin n = serialize(env, e->re.group.expr.binary.left, n);
279da2e3ebdSchin n = serialize(env, e->re.group.expr.binary.right, n);
280da2e3ebdSchin break;
281da2e3ebdSchin case REX_GROUP:
282da2e3ebdSchin case REX_GROUP_AHEAD:
283da2e3ebdSchin case REX_GROUP_AHEAD_NOT:
284da2e3ebdSchin case REX_GROUP_BEHIND:
285da2e3ebdSchin case REX_GROUP_BEHIND_NOT:
286da2e3ebdSchin case REX_GROUP_CUT:
287da2e3ebdSchin case REX_NEG:
288da2e3ebdSchin case REX_REP:
289da2e3ebdSchin n = serialize(env, e->re.group.expr.rex, n);
290da2e3ebdSchin break;
291da2e3ebdSchin }
292da2e3ebdSchin } while (e = e->next);
293da2e3ebdSchin return n;
294da2e3ebdSchin }
295da2e3ebdSchin
296da2e3ebdSchin /*
297da2e3ebdSchin * catenate e and f into a sequence, collapsing them if possible
298da2e3ebdSchin */
299da2e3ebdSchin
300da2e3ebdSchin static Rex_t*
cat(Cenv_t * env,Rex_t * e,Rex_t * f)301da2e3ebdSchin cat(Cenv_t* env, Rex_t* e, Rex_t* f)
302da2e3ebdSchin {
303da2e3ebdSchin Rex_t* g;
304da2e3ebdSchin
305da2e3ebdSchin if (!f)
306da2e3ebdSchin {
307da2e3ebdSchin drop(env->disc, e);
308da2e3ebdSchin return 0;
309da2e3ebdSchin }
310da2e3ebdSchin if (e->type == REX_NULL)
311da2e3ebdSchin {
312da2e3ebdSchin drop(env->disc, e);
313da2e3ebdSchin return f;
314da2e3ebdSchin }
315da2e3ebdSchin if (f->type == REX_NULL)
316da2e3ebdSchin {
317da2e3ebdSchin g = f->next;
318da2e3ebdSchin f->next = 0;
319da2e3ebdSchin drop(env->disc, f);
320da2e3ebdSchin f = g;
321da2e3ebdSchin }
322da2e3ebdSchin else if (e->type == REX_DOT && f->type == REX_DOT)
323da2e3ebdSchin {
324da2e3ebdSchin unsigned int m = e->lo + f->lo;
325da2e3ebdSchin unsigned int n = e->hi + f->hi;
326da2e3ebdSchin
327da2e3ebdSchin if (m <= RE_DUP_MAX)
328da2e3ebdSchin {
329da2e3ebdSchin if (e->hi > RE_DUP_MAX || f->hi > RE_DUP_MAX)
330da2e3ebdSchin {
331da2e3ebdSchin n = RE_DUP_INF;
332da2e3ebdSchin goto combine;
333da2e3ebdSchin }
334da2e3ebdSchin else if (n <= RE_DUP_MAX)
335da2e3ebdSchin {
336da2e3ebdSchin combine:
337da2e3ebdSchin e->lo = m;
338da2e3ebdSchin e->hi = n;
339da2e3ebdSchin g = f->next;
340da2e3ebdSchin f->next = 0;
341da2e3ebdSchin drop(env->disc, f);
342da2e3ebdSchin f = g;
343da2e3ebdSchin }
344da2e3ebdSchin }
345da2e3ebdSchin }
346da2e3ebdSchin e->next = f;
347da2e3ebdSchin return e;
348da2e3ebdSchin }
349da2e3ebdSchin
350da2e3ebdSchin /*
351da2e3ebdSchin * collect re statistics
352da2e3ebdSchin */
353da2e3ebdSchin
354da2e3ebdSchin static int
stats(register Cenv_t * env,register Rex_t * e)355da2e3ebdSchin stats(register Cenv_t* env, register Rex_t* e)
356da2e3ebdSchin {
357da2e3ebdSchin register unsigned long n;
358da2e3ebdSchin register unsigned long m;
359da2e3ebdSchin unsigned long cm;
360da2e3ebdSchin unsigned long nm;
361da2e3ebdSchin unsigned long cn;
362da2e3ebdSchin unsigned long nn;
363da2e3ebdSchin unsigned long l;
364da2e3ebdSchin unsigned long k;
365da2e3ebdSchin unsigned long t;
366da2e3ebdSchin Rex_t* q;
367da2e3ebdSchin Rex_t* x;
368da2e3ebdSchin Rex_t* y;
369da2e3ebdSchin unsigned char c;
370da2e3ebdSchin unsigned char b;
371da2e3ebdSchin
372da2e3ebdSchin do
373da2e3ebdSchin {
374da2e3ebdSchin switch (e->type)
375da2e3ebdSchin {
376da2e3ebdSchin case REX_ALT:
377da2e3ebdSchin x = env->stats.x;
378da2e3ebdSchin l = env->stats.l;
379da2e3ebdSchin y = env->stats.y;
380da2e3ebdSchin k = env->stats.k;
381da2e3ebdSchin t = env->stats.t;
382da2e3ebdSchin if (++env->stats.a <= 0)
383da2e3ebdSchin return 1;
384da2e3ebdSchin cm = env->stats.m;
385da2e3ebdSchin env->stats.m = 0;
386da2e3ebdSchin cn = env->stats.n;
387da2e3ebdSchin env->stats.n = 0;
388da2e3ebdSchin if (stats(env, e->re.group.expr.binary.left))
389da2e3ebdSchin return 1;
390da2e3ebdSchin m = env->stats.m;
391da2e3ebdSchin env->stats.m = 0;
392da2e3ebdSchin n = env->stats.n;
393da2e3ebdSchin env->stats.n = 0;
394da2e3ebdSchin if (e->re.group.expr.binary.right && stats(env, e->re.group.expr.binary.right))
395da2e3ebdSchin return 1;
396da2e3ebdSchin if (env->stats.m > m)
397da2e3ebdSchin env->stats.m = m;
398da2e3ebdSchin else
399da2e3ebdSchin m = env->stats.m;
400da2e3ebdSchin if ((env->stats.m += cm) < m)
401da2e3ebdSchin return 1;
402da2e3ebdSchin if (env->stats.n < n)
403da2e3ebdSchin env->stats.n = n;
404da2e3ebdSchin else
405da2e3ebdSchin n = env->stats.n;
406da2e3ebdSchin if ((env->stats.n += cn) < n)
407da2e3ebdSchin return 1;
408da2e3ebdSchin env->stats.x = x;
409da2e3ebdSchin env->stats.l = l;
410da2e3ebdSchin env->stats.y = y;
411da2e3ebdSchin env->stats.k = k;
412da2e3ebdSchin env->stats.t = t;
413da2e3ebdSchin break;
414da2e3ebdSchin case REX_BACK:
415da2e3ebdSchin if (++env->stats.b <= 0)
416da2e3ebdSchin return 1;
417da2e3ebdSchin break;
418da2e3ebdSchin case REX_CLASS:
419da2e3ebdSchin case REX_COLL_CLASS:
420da2e3ebdSchin case REX_DOT:
421da2e3ebdSchin case REX_ONECHAR:
422da2e3ebdSchin n = env->stats.m;
423da2e3ebdSchin if ((env->stats.m += e->lo) < n)
424da2e3ebdSchin return 1;
425da2e3ebdSchin if (e->hi != RE_DUP_INF)
426da2e3ebdSchin {
427da2e3ebdSchin n = env->stats.n;
428da2e3ebdSchin if ((env->stats.n += e->hi) < n)
429da2e3ebdSchin return 1;
430da2e3ebdSchin }
431da2e3ebdSchin if (e->lo != e->hi)
432da2e3ebdSchin {
433da2e3ebdSchin if (++env->stats.c <= 0)
434da2e3ebdSchin return 1;
435da2e3ebdSchin if (++env->stats.s <= 0)
436da2e3ebdSchin return 1;
437da2e3ebdSchin }
438da2e3ebdSchin break;
439da2e3ebdSchin case REX_CONJ:
440da2e3ebdSchin cm = env->stats.m;
441da2e3ebdSchin env->stats.m = 0;
442da2e3ebdSchin cn = env->stats.n;
443da2e3ebdSchin env->stats.n = 0;
444da2e3ebdSchin if (stats(env, e->re.group.expr.binary.left))
445da2e3ebdSchin return 1;
446da2e3ebdSchin nm = env->stats.m;
447da2e3ebdSchin env->stats.m = 0;
448da2e3ebdSchin nn = env->stats.n;
449da2e3ebdSchin env->stats.n = 0;
450da2e3ebdSchin if (stats(env, e->re.group.expr.binary.right))
451da2e3ebdSchin return 1;
452da2e3ebdSchin if (env->stats.m < nm)
453da2e3ebdSchin env->stats.m = nm;
454da2e3ebdSchin else
455da2e3ebdSchin nm = env->stats.m;
456da2e3ebdSchin if ((env->stats.m += cm) < nm)
457da2e3ebdSchin return 1;
458da2e3ebdSchin if (env->stats.n < nn)
459da2e3ebdSchin env->stats.n = nn;
460da2e3ebdSchin else
461da2e3ebdSchin nn = env->stats.n;
462da2e3ebdSchin if ((env->stats.n += cn) < nn)
463da2e3ebdSchin return 1;
464da2e3ebdSchin break;
465*3e14f97fSRoger A. Faulkner case REX_END:
466*3e14f97fSRoger A. Faulkner env->stats.e = 1;
467*3e14f97fSRoger A. Faulkner break;
468da2e3ebdSchin case REX_GROUP:
469da2e3ebdSchin if (e->re.group.number && ++env->stats.p <= 0 || !e->re.group.number && ++env->stats.u <= 0)
470da2e3ebdSchin return 1;
471da2e3ebdSchin if (stats(env, e->re.group.expr.rex))
472da2e3ebdSchin return 1;
473da2e3ebdSchin break;
474da2e3ebdSchin case REX_GROUP_AHEAD:
475da2e3ebdSchin case REX_GROUP_AHEAD_NOT:
476da2e3ebdSchin case REX_GROUP_BEHIND:
477da2e3ebdSchin case REX_GROUP_BEHIND_NOT:
478da2e3ebdSchin m = env->stats.m;
479da2e3ebdSchin n = env->stats.n;
480da2e3ebdSchin x = env->stats.x;
481da2e3ebdSchin y = env->stats.y;
482da2e3ebdSchin if (stats(env, e->re.group.expr.rex))
483da2e3ebdSchin return 1;
484da2e3ebdSchin env->stats.m = m;
485da2e3ebdSchin env->stats.n = n;
486da2e3ebdSchin env->stats.x = x;
487da2e3ebdSchin env->stats.y = y;
488da2e3ebdSchin switch (e->type)
489da2e3ebdSchin {
490da2e3ebdSchin case REX_GROUP_AHEAD:
491da2e3ebdSchin case REX_GROUP_BEHIND:
492da2e3ebdSchin if (++env->stats.u <= 0)
493da2e3ebdSchin return 1;
494da2e3ebdSchin break;
495da2e3ebdSchin }
496da2e3ebdSchin break;
497da2e3ebdSchin case REX_GROUP_COND:
498da2e3ebdSchin if (++env->stats.u <= 0)
499da2e3ebdSchin return 1;
500da2e3ebdSchin m = env->stats.m;
501da2e3ebdSchin n = env->stats.n;
502da2e3ebdSchin x = env->stats.x;
503da2e3ebdSchin y = env->stats.y;
504da2e3ebdSchin if (e->re.group.size > 0 && ++env->stats.b <= 0)
505da2e3ebdSchin return 1;
506da2e3ebdSchin if (e->re.group.expr.binary.left && stats(env, e->re.group.expr.binary.left))
507da2e3ebdSchin return 1;
508da2e3ebdSchin if (q = e->re.group.expr.binary.right)
509da2e3ebdSchin {
510da2e3ebdSchin if (q->re.group.expr.binary.left && stats(env, q->re.group.expr.binary.left))
511da2e3ebdSchin return 1;
512da2e3ebdSchin if (q->re.group.expr.binary.right && stats(env, q->re.group.expr.binary.right))
513da2e3ebdSchin return 1;
514da2e3ebdSchin }
515da2e3ebdSchin env->stats.m = m;
516da2e3ebdSchin env->stats.n = n;
517da2e3ebdSchin env->stats.x = x;
518da2e3ebdSchin env->stats.y = y;
519da2e3ebdSchin break;
520da2e3ebdSchin case REX_GROUP_CUT:
521da2e3ebdSchin if (++env->stats.u <= 0)
522da2e3ebdSchin return 1;
523da2e3ebdSchin m = env->stats.m;
524da2e3ebdSchin n = env->stats.n;
525da2e3ebdSchin x = env->stats.x;
526da2e3ebdSchin y = env->stats.y;
527da2e3ebdSchin if (stats(env, e->re.group.expr.rex))
528da2e3ebdSchin return 1;
529da2e3ebdSchin env->stats.m = m;
530da2e3ebdSchin env->stats.n = n;
531da2e3ebdSchin env->stats.x = x;
532da2e3ebdSchin env->stats.y = y;
533da2e3ebdSchin break;
534da2e3ebdSchin case REX_NEG:
535da2e3ebdSchin env->stats.i++;
536da2e3ebdSchin x = env->stats.x;
537da2e3ebdSchin l = env->stats.l;
538da2e3ebdSchin y = env->stats.y;
539da2e3ebdSchin k = env->stats.k;
540da2e3ebdSchin t = env->stats.t;
541da2e3ebdSchin cm = env->stats.m;
542da2e3ebdSchin env->stats.m = 0;
543da2e3ebdSchin if (stats(env, e->re.group.expr.rex))
544da2e3ebdSchin return 1;
545da2e3ebdSchin env->stats.m = !env->stats.m;
546da2e3ebdSchin if ((env->stats.m += cm) < cm)
547da2e3ebdSchin return 1;
548da2e3ebdSchin env->stats.x = x;
549da2e3ebdSchin env->stats.l = l;
550da2e3ebdSchin env->stats.y = y;
551da2e3ebdSchin env->stats.k = k;
552da2e3ebdSchin env->stats.t = t;
553da2e3ebdSchin break;
554da2e3ebdSchin case REX_REP:
555da2e3ebdSchin x = env->stats.x;
556da2e3ebdSchin l = env->stats.l;
557da2e3ebdSchin y = env->stats.y;
558da2e3ebdSchin k = env->stats.k;
559da2e3ebdSchin t = env->stats.t;
560da2e3ebdSchin if (++env->stats.c <= 0)
561da2e3ebdSchin return 1;
562da2e3ebdSchin b = env->stats.b;
563da2e3ebdSchin c = env->stats.c;
564da2e3ebdSchin cm = env->stats.m;
565da2e3ebdSchin env->stats.m = 0;
566da2e3ebdSchin if (stats(env, e->re.group.expr.rex))
567da2e3ebdSchin return 1;
568da2e3ebdSchin if (env->stats.m == 1 && b == env->stats.b && c == env->stats.c && ++env->stats.s <= 0)
569da2e3ebdSchin return 1;
570da2e3ebdSchin if (e->lo < 1)
571da2e3ebdSchin {
572da2e3ebdSchin env->stats.x = x;
573da2e3ebdSchin env->stats.l = l;
574da2e3ebdSchin env->stats.y = y;
575da2e3ebdSchin env->stats.k = k;
576da2e3ebdSchin env->stats.t = t;
577da2e3ebdSchin env->stats.m = cm;
578da2e3ebdSchin }
579da2e3ebdSchin else
580da2e3ebdSchin {
581da2e3ebdSchin m = env->stats.m;
582da2e3ebdSchin if ((env->stats.m *= e->lo) > 0 && env->stats.m < m)
583da2e3ebdSchin return 1;
584da2e3ebdSchin m = env->stats.m;
585da2e3ebdSchin if ((env->stats.m += cm) < m)
586da2e3ebdSchin return 1;
587da2e3ebdSchin if (env->stats.x != x)
588da2e3ebdSchin env->stats.l = cm;
589da2e3ebdSchin if (env->stats.y != y)
590da2e3ebdSchin env->stats.k = cm;
591da2e3ebdSchin }
592da2e3ebdSchin break;
593da2e3ebdSchin case REX_STRING:
5947c2fbfb3SApril Chin if (!e->map)
5957c2fbfb3SApril Chin {
596da2e3ebdSchin cm = env->stats.m;
597da2e3ebdSchin if ((env->stats.m += e->re.string.size) < cm)
598da2e3ebdSchin return 1;
599da2e3ebdSchin cn = env->stats.n;
600da2e3ebdSchin if ((env->stats.n += e->re.string.size) < cn)
601da2e3ebdSchin return 1;
602da2e3ebdSchin if (!env->stats.x || env->stats.x->re.string.size < e->re.string.size)
603da2e3ebdSchin {
604da2e3ebdSchin env->stats.x = e;
605da2e3ebdSchin env->stats.l = cm;
606da2e3ebdSchin }
6077c2fbfb3SApril Chin }
608da2e3ebdSchin break;
609da2e3ebdSchin case REX_TRIE:
610da2e3ebdSchin if (++env->stats.s <= 0)
611da2e3ebdSchin return 1;
612da2e3ebdSchin cm = env->stats.m;
613da2e3ebdSchin if ((env->stats.m += e->re.trie.min) < cm)
614da2e3ebdSchin return 1;
615da2e3ebdSchin cn = env->stats.n;
616da2e3ebdSchin if ((env->stats.n += e->re.trie.max) < cn)
617da2e3ebdSchin return 1;
618da2e3ebdSchin env->stats.t++;
619da2e3ebdSchin if (!env->stats.y || env->stats.y->re.trie.min < e->re.trie.min)
620da2e3ebdSchin {
621da2e3ebdSchin env->stats.y = e;
622da2e3ebdSchin env->stats.k = cm;
623da2e3ebdSchin }
624da2e3ebdSchin break;
625da2e3ebdSchin }
626da2e3ebdSchin } while (e = e->next);
627da2e3ebdSchin return 0;
628da2e3ebdSchin }
629da2e3ebdSchin
630da2e3ebdSchin static int token(Cenv_t*);
631da2e3ebdSchin
632da2e3ebdSchin static int
magic(register Cenv_t * env,register int c,int escaped)633da2e3ebdSchin magic(register Cenv_t* env, register int c, int escaped)
634da2e3ebdSchin {
635da2e3ebdSchin register char* sp;
636da2e3ebdSchin register int n;
637da2e3ebdSchin int o = c;
638da2e3ebdSchin int e = env->error;
639da2e3ebdSchin int l = env->token.len;
640da2e3ebdSchin short* mp;
641da2e3ebdSchin char* ep;
642da2e3ebdSchin
643da2e3ebdSchin if (mp = state.magic[c])
644da2e3ebdSchin {
645da2e3ebdSchin c = mp[env->type+escaped];
646da2e3ebdSchin if (c >= T_META)
647da2e3ebdSchin {
648da2e3ebdSchin sp = (char*)env->cursor + env->token.len;
649da2e3ebdSchin switch (c)
650da2e3ebdSchin {
651da2e3ebdSchin case T_LEFT:
652da2e3ebdSchin n = 0;
653da2e3ebdSchin ep = sp;
654da2e3ebdSchin while (*sp >= '0' && *sp <= '9')
655da2e3ebdSchin {
656da2e3ebdSchin if (n > (INT_MAX / 10))
657da2e3ebdSchin {
658da2e3ebdSchin env->error = REG_BADBR;
659da2e3ebdSchin goto bad;
660da2e3ebdSchin }
661da2e3ebdSchin n = n * 10 + *sp++ - '0';
662da2e3ebdSchin }
663da2e3ebdSchin if (sp == ep)
664da2e3ebdSchin {
6657c2fbfb3SApril Chin if (env->type < SRE || *sp != ',')
6667c2fbfb3SApril Chin {
667da2e3ebdSchin env->error = *sp ? REG_BADBR : REG_EBRACE;
668da2e3ebdSchin goto bad;
669da2e3ebdSchin }
6707c2fbfb3SApril Chin }
671da2e3ebdSchin else if (n > RE_DUP_MAX)
672da2e3ebdSchin {
673da2e3ebdSchin env->error = REG_BADBR;
674da2e3ebdSchin goto bad;
675da2e3ebdSchin }
676da2e3ebdSchin env->token.min = n;
677da2e3ebdSchin if (*sp == ',')
678da2e3ebdSchin {
679da2e3ebdSchin n = 0;
680da2e3ebdSchin ep = ++sp;
681da2e3ebdSchin while (*sp >= '0' && *sp <= '9')
682da2e3ebdSchin {
683da2e3ebdSchin if (n > (INT_MAX / 10))
684da2e3ebdSchin {
685da2e3ebdSchin env->error = REG_BADBR;
686da2e3ebdSchin goto bad;
687da2e3ebdSchin }
688da2e3ebdSchin n = n * 10 + *sp++ - '0';
689da2e3ebdSchin }
690da2e3ebdSchin if (sp == ep)
691da2e3ebdSchin n = RE_DUP_INF;
692da2e3ebdSchin else if (n < env->token.min)
693da2e3ebdSchin {
694da2e3ebdSchin env->error = REG_BADBR;
695da2e3ebdSchin goto bad;
696da2e3ebdSchin }
697da2e3ebdSchin }
698da2e3ebdSchin env->token.max = n;
699da2e3ebdSchin switch (*sp)
700da2e3ebdSchin {
701da2e3ebdSchin case 0:
702da2e3ebdSchin env->error = REG_EBRACE;
703da2e3ebdSchin goto bad;
704da2e3ebdSchin case '\\':
705da2e3ebdSchin if (!escaped)
706da2e3ebdSchin {
707da2e3ebdSchin env->error = REG_BADBR;
708da2e3ebdSchin goto bad;
709da2e3ebdSchin }
710da2e3ebdSchin sp++;
711da2e3ebdSchin break;
712da2e3ebdSchin default:
713da2e3ebdSchin if (escaped)
714da2e3ebdSchin {
715da2e3ebdSchin env->error = REG_BADBR;
716da2e3ebdSchin goto bad;
717da2e3ebdSchin }
718da2e3ebdSchin break;
719da2e3ebdSchin }
720da2e3ebdSchin switch (*sp++)
721da2e3ebdSchin {
722da2e3ebdSchin case 0:
723da2e3ebdSchin env->error = REG_EBRACE;
724da2e3ebdSchin goto bad;
725da2e3ebdSchin case '}':
726da2e3ebdSchin break;
727da2e3ebdSchin default:
728da2e3ebdSchin env->error = REG_BADBR;
729da2e3ebdSchin goto bad;
730da2e3ebdSchin }
731da2e3ebdSchin env->token.len = sp - (char*)env->cursor;
732da2e3ebdSchin break;
733da2e3ebdSchin case T_RIGHT:
734da2e3ebdSchin env->error = REG_EBRACE;
735da2e3ebdSchin goto bad;
736da2e3ebdSchin case T_OPEN:
737da2e3ebdSchin if (env->type < SRE && *sp == '?')
738da2e3ebdSchin {
739da2e3ebdSchin env->token.len++;
740da2e3ebdSchin env->token.lex = 0;
741da2e3ebdSchin goto group;
742da2e3ebdSchin }
743da2e3ebdSchin break;
744da2e3ebdSchin case T_ESCAPE:
745da2e3ebdSchin c = chresc(sp - 2, &ep);
746da2e3ebdSchin if (ep < sp)
747da2e3ebdSchin goto bad;
748da2e3ebdSchin env->token.len += ep - sp;
749da2e3ebdSchin if (c >= T_META)
750da2e3ebdSchin {
751da2e3ebdSchin env->token.lex = c;
752da2e3ebdSchin c = C_ESC;
753da2e3ebdSchin }
754da2e3ebdSchin return c;
755da2e3ebdSchin case T_BACK+0:
756da2e3ebdSchin case T_BACK+1:
757da2e3ebdSchin case T_BACK+2:
758da2e3ebdSchin case T_BACK+3:
759da2e3ebdSchin case T_BACK+4:
760da2e3ebdSchin case T_BACK+5:
761da2e3ebdSchin case T_BACK+6:
762da2e3ebdSchin case T_BACK+7:
763da2e3ebdSchin n = chresc(sp - 2, &ep);
764da2e3ebdSchin if (ep > sp + 1)
765da2e3ebdSchin {
766da2e3ebdSchin env->token.len += ep - sp;
767da2e3ebdSchin return n;
768da2e3ebdSchin }
769da2e3ebdSchin /*FALLTHROUGH*/
770da2e3ebdSchin case T_BACK+8:
771da2e3ebdSchin case T_BACK+9:
772da2e3ebdSchin if (env->type == SRE || c == T_BACK && !(env->flags & REG_LENIENT))
773da2e3ebdSchin {
774da2e3ebdSchin env->error = REG_BADESC;
775da2e3ebdSchin goto bad;
776da2e3ebdSchin }
777da2e3ebdSchin if ((env->flags & REG_MULTIREF) && isdigit(*sp))
778da2e3ebdSchin {
779da2e3ebdSchin c = (c - T_BACK) * 10 + (*sp - '0');
780da2e3ebdSchin if (c > 0 && c <= env->parno && env->paren[c])
781da2e3ebdSchin c += T_BACK;
782da2e3ebdSchin else
783da2e3ebdSchin c = chresc(sp - 2, &ep);
784da2e3ebdSchin env->token.len++;
785da2e3ebdSchin }
786da2e3ebdSchin if (c == T_BACK)
787da2e3ebdSchin c = 0;
788da2e3ebdSchin break;
789da2e3ebdSchin case T_BAD:
790da2e3ebdSchin if (escaped == 1 && (env->flags & REG_LENIENT) && (c = mp[env->type+escaped+2]) >= T_META)
791da2e3ebdSchin return c;
792da2e3ebdSchin goto bad;
793da2e3ebdSchin }
794da2e3ebdSchin if (env->type >= SRE)
795da2e3ebdSchin {
796da2e3ebdSchin if (c == T_DOT)
797da2e3ebdSchin c = '.';
798da2e3ebdSchin else if (c < T_OPEN)
799da2e3ebdSchin {
800da2e3ebdSchin if (env->type == KRE && *(env->cursor + env->token.len) == '-' && *(env->cursor + env->token.len + 1) == '(')
801da2e3ebdSchin {
802da2e3ebdSchin env->token.len++;
803da2e3ebdSchin env->token.att = 1;
804da2e3ebdSchin }
805da2e3ebdSchin if (env->type == KRE && *(env->cursor + env->token.len) == '(')
806da2e3ebdSchin {
807da2e3ebdSchin env->token.len++;
808da2e3ebdSchin switch (c)
809da2e3ebdSchin {
810da2e3ebdSchin case T_AT:
811da2e3ebdSchin break;
812da2e3ebdSchin case T_PERCENT:
813da2e3ebdSchin env->token.lex = c;
814da2e3ebdSchin goto group;
815da2e3ebdSchin case T_TILDE:
816da2e3ebdSchin env->token.lex = 0;
817da2e3ebdSchin goto group;
818da2e3ebdSchin default:
819da2e3ebdSchin env->token.lex = c;
820da2e3ebdSchin break;
821da2e3ebdSchin }
822da2e3ebdSchin c = T_OPEN;
823da2e3ebdSchin }
824da2e3ebdSchin else if (c == T_STAR)
825da2e3ebdSchin c = T_DOTSTAR;
826da2e3ebdSchin else if (c == T_QUES)
827da2e3ebdSchin c = T_DOT;
828da2e3ebdSchin else
829da2e3ebdSchin {
830da2e3ebdSchin c = o;
831da2e3ebdSchin env->token.len = l;
832da2e3ebdSchin }
833da2e3ebdSchin }
834da2e3ebdSchin else if (c > T_BACK)
835da2e3ebdSchin {
836da2e3ebdSchin c = (c - T_BACK) * 2 - 1;
837da2e3ebdSchin c = (c > env->parno || !env->paren[c]) ? o : T_BACK + c;
838da2e3ebdSchin }
839da2e3ebdSchin else if (env->type == KRE && !env->parnest && (env->flags & REG_SHELL_GROUP))
840da2e3ebdSchin {
841da2e3ebdSchin if (c == T_AND)
842da2e3ebdSchin c = '&';
843da2e3ebdSchin else if (c == T_BAR)
844da2e3ebdSchin c = '|';
845da2e3ebdSchin else if (c == T_OPEN)
846da2e3ebdSchin c = '(';
847da2e3ebdSchin }
848da2e3ebdSchin }
849da2e3ebdSchin }
850da2e3ebdSchin }
851da2e3ebdSchin else if (escaped == 2)
852da2e3ebdSchin {
853da2e3ebdSchin if (env->type >= SRE && !(env->flags & REG_SHELL_ESCAPED) || (env->flags & REG_ESCAPE) && (c == '[' || c == '-' || c == ']' || env->delimiter && c == env->delimiter))
854da2e3ebdSchin /*ok*/;
855da2e3ebdSchin else
856da2e3ebdSchin {
857da2e3ebdSchin env->error = REG_BADESC;
858da2e3ebdSchin goto bad;
859da2e3ebdSchin }
860da2e3ebdSchin }
861da2e3ebdSchin else if (escaped && !(env->flags & REG_LENIENT) && c != ']')
862da2e3ebdSchin {
863da2e3ebdSchin env->error = REG_BADESC;
864da2e3ebdSchin goto bad;
865da2e3ebdSchin }
866da2e3ebdSchin return c;
867da2e3ebdSchin group:
868da2e3ebdSchin sp = (char*)env->cursor + env->token.len;
869da2e3ebdSchin switch (*sp++)
870da2e3ebdSchin {
871da2e3ebdSchin case ')':
872da2e3ebdSchin break;
873da2e3ebdSchin case '#':
874da2e3ebdSchin for (;;)
875da2e3ebdSchin {
876da2e3ebdSchin switch (*sp++)
877da2e3ebdSchin {
878da2e3ebdSchin case 0:
879da2e3ebdSchin env->error = REG_EPAREN;
880da2e3ebdSchin return T_BAD;
881da2e3ebdSchin case ')':
882da2e3ebdSchin break;
883da2e3ebdSchin default:
884da2e3ebdSchin continue;
885da2e3ebdSchin }
886da2e3ebdSchin break;
887da2e3ebdSchin }
888da2e3ebdSchin break;
889da2e3ebdSchin default:
890da2e3ebdSchin return T_GROUP;
891da2e3ebdSchin }
892da2e3ebdSchin env->cursor = (unsigned char*)sp;
893da2e3ebdSchin return token(env);
894da2e3ebdSchin bad:
895da2e3ebdSchin if (escaped == 2)
896da2e3ebdSchin env->error = e;
897da2e3ebdSchin else if (env->flags & REG_LENIENT)
898da2e3ebdSchin return o;
899da2e3ebdSchin else if (escaped == 1 && !env->error)
900da2e3ebdSchin {
901da2e3ebdSchin if (mp || o == ']')
902da2e3ebdSchin return o;
903da2e3ebdSchin env->error = REG_BADESC;
904da2e3ebdSchin }
905da2e3ebdSchin return T_BAD;
906da2e3ebdSchin }
907da2e3ebdSchin
908da2e3ebdSchin static int
token(register Cenv_t * env)909da2e3ebdSchin token(register Cenv_t* env)
910da2e3ebdSchin {
911da2e3ebdSchin int c;
912da2e3ebdSchin int posixkludge;
913da2e3ebdSchin
914da2e3ebdSchin if (env->token.push)
915da2e3ebdSchin return env->token.lex;
916da2e3ebdSchin env->token.att = env->token.esc = 0;
917da2e3ebdSchin if ((env->token.len = MBSIZE(env->cursor)) > 1)
918da2e3ebdSchin return env->token.lex = C_MB;
919da2e3ebdSchin env->token.lex = 0;
920da2e3ebdSchin for (;;)
921da2e3ebdSchin {
922da2e3ebdSchin c = *env->cursor;
923da2e3ebdSchin if (c == 0 || c == env->delimiter || c == env->terminator)
924da2e3ebdSchin return T_END;
925da2e3ebdSchin if (!(env->flags & REG_COMMENT))
926da2e3ebdSchin break;
927da2e3ebdSchin if (c == '#')
928da2e3ebdSchin {
929da2e3ebdSchin do
930da2e3ebdSchin {
931da2e3ebdSchin c = *++env->cursor;
932da2e3ebdSchin if (c == 0 || c == env->delimiter)
933da2e3ebdSchin return T_END;
934da2e3ebdSchin } while (c != '\n');
935da2e3ebdSchin }
936da2e3ebdSchin else if (!isspace(c))
937da2e3ebdSchin break;
938da2e3ebdSchin env->cursor++;
939da2e3ebdSchin }
940da2e3ebdSchin if (c == '\n' && (env->flags & REG_MULTIPLE) && !env->delimiter)
941da2e3ebdSchin {
942da2e3ebdSchin if (env->parnest)
943da2e3ebdSchin {
944da2e3ebdSchin env->error = REG_EPAREN;
945da2e3ebdSchin return T_BAD;
946da2e3ebdSchin }
947da2e3ebdSchin env->parno = 0;
948da2e3ebdSchin env->pattern = env->cursor + 1;
949da2e3ebdSchin return T_BAR;
950da2e3ebdSchin }
951da2e3ebdSchin if (env->flags & REG_LITERAL)
952da2e3ebdSchin return c;
953da2e3ebdSchin if (posixkludge = env->posixkludge)
954da2e3ebdSchin {
955da2e3ebdSchin env->posixkludge = 0;
956da2e3ebdSchin if (c == '*')
957da2e3ebdSchin return c;
958da2e3ebdSchin }
959da2e3ebdSchin if (c == '\\')
960da2e3ebdSchin {
961da2e3ebdSchin if (env->flags & REG_SHELL_ESCAPED)
962da2e3ebdSchin return c;
963da2e3ebdSchin if (!(c = *(env->cursor + 1)) || c == env->terminator)
964da2e3ebdSchin {
965da2e3ebdSchin if (env->flags & REG_LENIENT)
966da2e3ebdSchin {
967da2e3ebdSchin if (c)
968da2e3ebdSchin {
969da2e3ebdSchin env->token.esc = env->token.len;
970da2e3ebdSchin env->token.len += MBSIZE(env->cursor + 1);
971da2e3ebdSchin return c;
972da2e3ebdSchin }
973da2e3ebdSchin return '\\';
974da2e3ebdSchin }
975da2e3ebdSchin env->error = REG_EESCAPE;
976da2e3ebdSchin return T_BAD;
977da2e3ebdSchin }
978da2e3ebdSchin env->token.esc = env->token.len;
979da2e3ebdSchin env->token.len += MBSIZE(env->cursor + 1);
980da2e3ebdSchin if (env->delimiter && c == 'n')
981da2e3ebdSchin return '\n';
982da2e3ebdSchin else if (c == env->delimiter)
983da2e3ebdSchin return magic(env, c, 0);
984da2e3ebdSchin else if (c == '(' && env->type == BRE)
985da2e3ebdSchin env->posixkludge = 1;
986da2e3ebdSchin else if (c == ')' && env->type == BRE && env->parnest <= 0)
987da2e3ebdSchin {
988da2e3ebdSchin env->error = REG_EPAREN;
989da2e3ebdSchin return T_BAD;
990da2e3ebdSchin }
991da2e3ebdSchin else if (isspace(c) && (env->flags & REG_COMMENT))
992da2e3ebdSchin return c;
993da2e3ebdSchin return magic(env, c, 1);
994da2e3ebdSchin }
995da2e3ebdSchin else if (c == '$')
996da2e3ebdSchin {
997da2e3ebdSchin if (env->type == BRE && (*(env->cursor + 1) == 0 || *(env->cursor + 1) == env->delimiter || *(env->cursor + 1) == env->terminator || *(env->cursor + 1) == '\\' && *(env->cursor + 2) == ')') || (env->flags & REG_MULTIPLE) && *(env->cursor + 1) == '\n')
998da2e3ebdSchin return T_DOLL;
999da2e3ebdSchin }
1000da2e3ebdSchin else if (c == '^')
1001da2e3ebdSchin {
1002*3e14f97fSRoger A. Faulkner if (env->type == BRE && (env->cursor == env->pattern || posixkludge == 1))
1003da2e3ebdSchin {
1004*3e14f97fSRoger A. Faulkner env->posixkludge = 2;
1005da2e3ebdSchin return T_CFLX;
1006da2e3ebdSchin }
1007da2e3ebdSchin }
1008da2e3ebdSchin else if (c == ')')
1009da2e3ebdSchin {
1010da2e3ebdSchin if (env->type != BRE && env->parnest <= 0)
1011da2e3ebdSchin return c;
1012da2e3ebdSchin }
1013da2e3ebdSchin else if (c == '/' && env->explicit == env->mappedslash)
1014da2e3ebdSchin {
1015da2e3ebdSchin while (*(env->cursor + env->token.len) == c)
1016da2e3ebdSchin env->token.len++;
1017da2e3ebdSchin return T_SLASHPLUS;
1018da2e3ebdSchin }
1019da2e3ebdSchin return magic(env, c, 0);
1020da2e3ebdSchin }
1021da2e3ebdSchin
1022da2e3ebdSchin static Celt_t*
col(Celt_t * ce,int ic,unsigned char * bp,int bw,int bc,unsigned char * ep,int ew,int ec)1023da2e3ebdSchin col(Celt_t* ce, int ic, unsigned char* bp, int bw, int bc, unsigned char* ep, int ew, int ec)
1024da2e3ebdSchin {
10257c2fbfb3SApril Chin register char* s;
1026da2e3ebdSchin register unsigned char* k;
1027da2e3ebdSchin register unsigned char* e;
1028da2e3ebdSchin register int c;
1029da2e3ebdSchin register int cc;
1030da2e3ebdSchin int bt;
1031da2e3ebdSchin int et;
1032da2e3ebdSchin Ckey_t key;
1033da2e3ebdSchin
1034da2e3ebdSchin cc = 0;
1035da2e3ebdSchin for (;;)
1036da2e3ebdSchin {
1037da2e3ebdSchin k = key;
1038da2e3ebdSchin if (bw == 1)
1039da2e3ebdSchin {
1040da2e3ebdSchin c = bc;
1041da2e3ebdSchin if (ic)
1042da2e3ebdSchin {
10437c2fbfb3SApril Chin if (isupper(c))
10447c2fbfb3SApril Chin {
10457c2fbfb3SApril Chin c = tolower(c);
10467c2fbfb3SApril Chin cc = -1;
10477c2fbfb3SApril Chin }
10487c2fbfb3SApril Chin else if (islower(c))
10497c2fbfb3SApril Chin {
10507c2fbfb3SApril Chin c = toupper(c);
10517c2fbfb3SApril Chin cc = -1;
10527c2fbfb3SApril Chin }
10537c2fbfb3SApril Chin }
10547c2fbfb3SApril Chin *k++ = c;
10557c2fbfb3SApril Chin }
10567c2fbfb3SApril Chin else if (bw < COLL_KEY_MAX)
10577c2fbfb3SApril Chin {
10587c2fbfb3SApril Chin s = (char*)bp;
10597c2fbfb3SApril Chin if (ic)
10607c2fbfb3SApril Chin {
10617c2fbfb3SApril Chin c = mbchar(s);
1062da2e3ebdSchin if (iswupper(c))
1063da2e3ebdSchin {
1064da2e3ebdSchin c = towlower(c);
1065da2e3ebdSchin cc = 1;
1066da2e3ebdSchin }
1067da2e3ebdSchin else if (iswlower(c))
1068da2e3ebdSchin {
1069da2e3ebdSchin c = towupper(c);
1070da2e3ebdSchin cc = 1;
1071da2e3ebdSchin }
1072da2e3ebdSchin }
10737c2fbfb3SApril Chin if (cc > 0)
1074da2e3ebdSchin {
10757c2fbfb3SApril Chin cc = -1;
1076*3e14f97fSRoger A. Faulkner k += mbconv((char*)k, c);
1077da2e3ebdSchin }
10787c2fbfb3SApril Chin else
10797c2fbfb3SApril Chin for (e = k + bw; k < e; *k++ = *s++);
1080da2e3ebdSchin }
1081da2e3ebdSchin *k = 0;
1082da2e3ebdSchin mbxfrm(ce->beg, key, COLL_KEY_MAX);
1083da2e3ebdSchin if (ep)
1084da2e3ebdSchin {
1085da2e3ebdSchin k = key;
1086da2e3ebdSchin c = mbchar(k);
1087da2e3ebdSchin if (iswupper(c))
1088da2e3ebdSchin bt = COLL_range_uc;
1089da2e3ebdSchin else if (iswlower(c))
1090da2e3ebdSchin bt = COLL_range_lc;
1091da2e3ebdSchin else
1092da2e3ebdSchin bt = COLL_range;
1093da2e3ebdSchin k = key;
1094da2e3ebdSchin if (ew == 1)
1095da2e3ebdSchin {
1096da2e3ebdSchin c = ec;
1097da2e3ebdSchin if (ic)
1098da2e3ebdSchin {
10997c2fbfb3SApril Chin if (isupper(c))
11007c2fbfb3SApril Chin {
11017c2fbfb3SApril Chin c = tolower(c);
11027c2fbfb3SApril Chin cc = -1;
11037c2fbfb3SApril Chin }
11047c2fbfb3SApril Chin else if (islower(c))
11057c2fbfb3SApril Chin {
11067c2fbfb3SApril Chin c = toupper(c);
11077c2fbfb3SApril Chin cc = -1;
11087c2fbfb3SApril Chin }
11097c2fbfb3SApril Chin }
11107c2fbfb3SApril Chin *k++ = c;
11117c2fbfb3SApril Chin }
11127c2fbfb3SApril Chin else if (ew < COLL_KEY_MAX)
11137c2fbfb3SApril Chin {
11147c2fbfb3SApril Chin s = (char*)ep;
11157c2fbfb3SApril Chin if (ic)
11167c2fbfb3SApril Chin {
11177c2fbfb3SApril Chin c = mbchar(s);
1118da2e3ebdSchin if (iswupper(c))
1119da2e3ebdSchin {
1120da2e3ebdSchin c = towlower(c);
1121da2e3ebdSchin cc = 1;
1122da2e3ebdSchin }
1123da2e3ebdSchin else if (iswlower(c))
1124da2e3ebdSchin {
1125da2e3ebdSchin c = towupper(c);
1126da2e3ebdSchin cc = 1;
1127da2e3ebdSchin }
1128da2e3ebdSchin }
11297c2fbfb3SApril Chin if (cc > 0)
1130da2e3ebdSchin {
11317c2fbfb3SApril Chin cc = -1;
1132*3e14f97fSRoger A. Faulkner k += mbconv((char*)k, c);
1133da2e3ebdSchin }
11347c2fbfb3SApril Chin else
11357c2fbfb3SApril Chin for (e = k + ew; k < e; *k++ = *s++);
1136da2e3ebdSchin }
1137da2e3ebdSchin *k = 0;
1138da2e3ebdSchin mbxfrm(ce->end, key, COLL_KEY_MAX);
1139da2e3ebdSchin k = key;
1140da2e3ebdSchin c = mbchar(k);
1141da2e3ebdSchin if (iswupper(c))
1142da2e3ebdSchin et = COLL_range_uc;
1143da2e3ebdSchin else if (iswlower(c))
1144da2e3ebdSchin et = COLL_range_lc;
1145da2e3ebdSchin else
1146da2e3ebdSchin et = COLL_range;
1147da2e3ebdSchin ce->typ = bt == et ? bt : COLL_range;
1148da2e3ebdSchin }
1149da2e3ebdSchin else
1150da2e3ebdSchin ce->typ = COLL_char;
1151da2e3ebdSchin ce++;
1152da2e3ebdSchin if (!ic || !cc)
1153da2e3ebdSchin break;
1154da2e3ebdSchin ic = 0;
1155da2e3ebdSchin }
1156da2e3ebdSchin return ce;
1157da2e3ebdSchin }
1158da2e3ebdSchin
1159da2e3ebdSchin static Rex_t*
bra(Cenv_t * env)1160da2e3ebdSchin bra(Cenv_t* env)
1161da2e3ebdSchin {
1162da2e3ebdSchin Rex_t* e;
1163da2e3ebdSchin int c;
1164da2e3ebdSchin int i;
1165da2e3ebdSchin int w;
1166da2e3ebdSchin int neg;
1167da2e3ebdSchin int last;
1168da2e3ebdSchin int inrange;
1169da2e3ebdSchin int complicated;
1170da2e3ebdSchin int collate;
1171da2e3ebdSchin int elements;
1172da2e3ebdSchin unsigned char* first;
1173da2e3ebdSchin unsigned char* start;
1174da2e3ebdSchin unsigned char* begin;
1175da2e3ebdSchin unsigned char* s;
1176da2e3ebdSchin regclass_t f;
1177da2e3ebdSchin unsigned char buf[4 * (COLL_KEY_MAX + 1)];
1178da2e3ebdSchin #if _PACKAGE_ast
1179da2e3ebdSchin int ic;
1180da2e3ebdSchin char mbc[COLL_KEY_MAX + 1];
1181da2e3ebdSchin #endif
1182da2e3ebdSchin
1183da2e3ebdSchin if (!(e = node(env, REX_CLASS, 1, 1, sizeof(Set_t))))
1184da2e3ebdSchin return 0;
1185da2e3ebdSchin collate = complicated = elements = 0;
1186da2e3ebdSchin if (*env->cursor == '^' || env->type >= SRE && *env->cursor == '!')
1187da2e3ebdSchin {
1188da2e3ebdSchin env->cursor++;
1189da2e3ebdSchin neg = 1;
1190da2e3ebdSchin }
1191da2e3ebdSchin else
1192da2e3ebdSchin neg = 0;
11937c2fbfb3SApril Chin first = env->cursor;
11947c2fbfb3SApril Chin start = first + MBSIZE(first);
1195da2e3ebdSchin if (*env->cursor == 0 || *(env->cursor + 1) == 0 || *env->cursor == env->terminator || *(env->cursor + 1) == env->terminator || (env->flags & REG_ESCAPE) && (*env->cursor == env->delimiter || *env->cursor != '\\' && *(env->cursor + 1) == env->delimiter))
1196da2e3ebdSchin goto error;
1197da2e3ebdSchin begin = env->cursor + MBSIZE(env->cursor);
1198da2e3ebdSchin
1199da2e3ebdSchin /*
1200da2e3ebdSchin * inrange: 0=no, 1=possibly, 2=definitely
1201da2e3ebdSchin */
1202da2e3ebdSchin
1203da2e3ebdSchin inrange = 0;
1204da2e3ebdSchin for (;;)
1205da2e3ebdSchin {
1206*3e14f97fSRoger A. Faulkner if (!(c = *env->cursor) || c == env->terminator || c == env->delimiter && (env->flags & REG_ESCAPE))
1207da2e3ebdSchin goto error;
1208da2e3ebdSchin env->cursor += (w = MBSIZE(env->cursor));
1209*3e14f97fSRoger A. Faulkner if (c == '\\' && ((env->flags & REG_CLASS_ESCAPE) || env->type >= SRE && env->parnest || *env->cursor == env->delimiter && (env->flags & REG_ESCAPE)))
1210da2e3ebdSchin {
1211da2e3ebdSchin if (*env->cursor)
1212da2e3ebdSchin {
1213da2e3ebdSchin if (*env->cursor == 'n')
1214da2e3ebdSchin {
1215da2e3ebdSchin env->cursor++;
1216da2e3ebdSchin c = '\n';
1217da2e3ebdSchin }
1218da2e3ebdSchin else if (env->type < SRE || !(env->flags & REG_SHELL_ESCAPED))
1219da2e3ebdSchin {
1220da2e3ebdSchin env->token.len = 1;
1221da2e3ebdSchin w = magic(env, *env->cursor, 2);
1222da2e3ebdSchin if (env->token.len > 1 || w != T_BAD)
1223da2e3ebdSchin {
1224da2e3ebdSchin if (env->token.len == 1 && (f = classfun(w)))
1225da2e3ebdSchin {
1226da2e3ebdSchin if (inrange > 1)
1227da2e3ebdSchin {
1228da2e3ebdSchin if (env->type < SRE && !(env->flags & REG_LENIENT))
1229da2e3ebdSchin goto erange;
1230da2e3ebdSchin inrange = 0;
1231da2e3ebdSchin }
1232da2e3ebdSchin env->cursor++;
1233da2e3ebdSchin for (c = 0; c <= UCHAR_MAX; c++)
1234da2e3ebdSchin if ((*f)(c))
1235da2e3ebdSchin setadd(e->re.charclass, c);
1236da2e3ebdSchin complicated++;
1237da2e3ebdSchin elements++;
1238da2e3ebdSchin continue;
1239da2e3ebdSchin }
1240da2e3ebdSchin if (env->token.len > 1 || w >= 0 && w < T_META)
1241da2e3ebdSchin {
1242da2e3ebdSchin c = w;
1243da2e3ebdSchin if (c > UCHAR_MAX)
1244da2e3ebdSchin {
1245da2e3ebdSchin if (env->type < SRE && !(env->flags & REG_LENIENT) && !mbwide())
1246da2e3ebdSchin goto erange;
1247da2e3ebdSchin c = UCHAR_MAX;
1248da2e3ebdSchin }
1249da2e3ebdSchin env->cursor += env->token.len;
1250da2e3ebdSchin }
1251da2e3ebdSchin }
1252da2e3ebdSchin }
1253da2e3ebdSchin }
1254da2e3ebdSchin }
1255da2e3ebdSchin else if (c == ']')
1256da2e3ebdSchin {
1257da2e3ebdSchin if (env->cursor == begin)
1258da2e3ebdSchin {
1259da2e3ebdSchin last = c;
1260da2e3ebdSchin inrange = 1;
1261da2e3ebdSchin continue;
1262da2e3ebdSchin }
1263da2e3ebdSchin if (inrange != 0)
1264da2e3ebdSchin {
1265da2e3ebdSchin setadd(e->re.charclass, last);
1266da2e3ebdSchin elements++;
1267da2e3ebdSchin if (inrange == 2)
1268da2e3ebdSchin {
1269da2e3ebdSchin setadd(e->re.charclass, '-');
1270da2e3ebdSchin elements++;
1271da2e3ebdSchin }
1272da2e3ebdSchin }
1273da2e3ebdSchin break;
1274da2e3ebdSchin }
1275da2e3ebdSchin else if (c == '-')
1276da2e3ebdSchin {
1277da2e3ebdSchin if (!inrange && env->cursor != begin && *env->cursor != ']')
1278da2e3ebdSchin {
1279da2e3ebdSchin if (env->type < SRE && !(env->flags & REG_LENIENT))
1280da2e3ebdSchin goto erange;
1281da2e3ebdSchin continue;
1282da2e3ebdSchin }
1283da2e3ebdSchin else if (inrange == 1)
1284da2e3ebdSchin {
1285da2e3ebdSchin inrange = 2;
1286da2e3ebdSchin complicated++;
1287da2e3ebdSchin continue;
1288da2e3ebdSchin }
1289da2e3ebdSchin }
1290da2e3ebdSchin else if (c == '[')
1291da2e3ebdSchin {
1292da2e3ebdSchin switch (*env->cursor)
1293da2e3ebdSchin {
1294da2e3ebdSchin case 0:
1295da2e3ebdSchin goto error;
1296da2e3ebdSchin case ':':
129734f9b3eeSRoland Mainz if (env->regexp)
129834f9b3eeSRoland Mainz goto normal;
1299da2e3ebdSchin if (inrange == 1)
1300da2e3ebdSchin {
1301da2e3ebdSchin setadd(e->re.charclass, last);
1302da2e3ebdSchin elements++;
1303da2e3ebdSchin }
1304da2e3ebdSchin if (!(f = regclass((char*)env->cursor, (char**)&env->cursor)))
1305da2e3ebdSchin {
1306da2e3ebdSchin if (env->cursor == start && (c = *(env->cursor + 1)))
1307da2e3ebdSchin {
1308da2e3ebdSchin s = start = env->cursor + 1;
1309da2e3ebdSchin while (*++s && *s != ':');
1310da2e3ebdSchin if (*s == ':' && *(s + 1) == ']' && *(s + 2) == ']')
1311da2e3ebdSchin {
1312da2e3ebdSchin if ((i = (s - start)) == 1)
1313da2e3ebdSchin {
1314da2e3ebdSchin switch (c)
1315da2e3ebdSchin {
1316da2e3ebdSchin case '<':
1317da2e3ebdSchin i = REX_WBEG;
1318da2e3ebdSchin break;
1319da2e3ebdSchin case '>':
1320da2e3ebdSchin i = REX_WEND;
1321da2e3ebdSchin break;
1322da2e3ebdSchin default:
1323da2e3ebdSchin i = 0;
1324da2e3ebdSchin break;
1325da2e3ebdSchin }
1326da2e3ebdSchin if (i)
1327da2e3ebdSchin {
1328da2e3ebdSchin env->cursor = s + 3;
1329da2e3ebdSchin drop(env->disc, e);
1330da2e3ebdSchin return node(env, i, 0, 0, 0);
1331da2e3ebdSchin }
1332da2e3ebdSchin }
1333da2e3ebdSchin }
1334da2e3ebdSchin }
1335da2e3ebdSchin env->error = REG_ECTYPE;
1336da2e3ebdSchin goto error;
1337da2e3ebdSchin }
1338da2e3ebdSchin for (c = 0; c <= UCHAR_MAX; c++)
1339da2e3ebdSchin if ((*f)(c))
1340da2e3ebdSchin setadd(e->re.charclass, c);
1341da2e3ebdSchin inrange = 0;
1342da2e3ebdSchin complicated++;
1343da2e3ebdSchin elements++;
1344da2e3ebdSchin continue;
1345da2e3ebdSchin case '=':
134634f9b3eeSRoland Mainz if (env->regexp)
134734f9b3eeSRoland Mainz goto normal;
1348da2e3ebdSchin if (inrange == 2)
1349da2e3ebdSchin goto erange;
1350da2e3ebdSchin if (inrange == 1)
1351da2e3ebdSchin {
1352da2e3ebdSchin setadd(e->re.charclass, last);
1353da2e3ebdSchin elements++;
1354da2e3ebdSchin }
1355da2e3ebdSchin if ((c = regcollate((char*)env->cursor, (char**)&env->cursor, (char*)buf, sizeof(buf))) < 0)
1356da2e3ebdSchin goto ecollate;
1357da2e3ebdSchin if (c > 1)
1358da2e3ebdSchin collate++;
1359da2e3ebdSchin else
1360da2e3ebdSchin setadd(e->re.charclass, buf[0]);
1361da2e3ebdSchin c = buf[0];
1362da2e3ebdSchin inrange = 0;
1363da2e3ebdSchin complicated++;
1364da2e3ebdSchin elements++;
1365da2e3ebdSchin continue;
1366da2e3ebdSchin case '.':
136734f9b3eeSRoland Mainz if (env->regexp)
136834f9b3eeSRoland Mainz goto normal;
1369da2e3ebdSchin if ((c = regcollate((char*)env->cursor, (char**)&env->cursor, (char*)buf, sizeof(buf))) < 0)
1370da2e3ebdSchin goto ecollate;
1371da2e3ebdSchin if (c > 1)
1372da2e3ebdSchin collate++;
1373da2e3ebdSchin c = buf[0];
1374da2e3ebdSchin complicated++;
1375da2e3ebdSchin break;
1376da2e3ebdSchin default:
137734f9b3eeSRoland Mainz normal:
1378da2e3ebdSchin if (*env->cursor == env->terminator || *env->cursor == env->delimiter && (env->flags & REG_ESCAPE))
1379da2e3ebdSchin goto error;
1380da2e3ebdSchin break;
1381da2e3ebdSchin }
1382da2e3ebdSchin }
1383da2e3ebdSchin else if (w > 1)
1384da2e3ebdSchin complicated++;
1385da2e3ebdSchin if (inrange == 2)
1386da2e3ebdSchin {
1387*3e14f97fSRoger A. Faulkner if (last <= c)
1388da2e3ebdSchin {
1389da2e3ebdSchin for (i = last; i <= c; i++)
1390da2e3ebdSchin setadd(e->re.charclass, i);
1391da2e3ebdSchin inrange = env->type >= SRE || (env->flags & REG_LENIENT);
1392da2e3ebdSchin elements += 2;
1393da2e3ebdSchin }
1394*3e14f97fSRoger A. Faulkner else if (env->type >= SRE)
1395*3e14f97fSRoger A. Faulkner {
1396*3e14f97fSRoger A. Faulkner setadd(e->re.charclass, last);
1397*3e14f97fSRoger A. Faulkner setadd(e->re.charclass, c);
1398*3e14f97fSRoger A. Faulkner elements += 2;
1399*3e14f97fSRoger A. Faulkner inrange = 1;
1400*3e14f97fSRoger A. Faulkner }
1401*3e14f97fSRoger A. Faulkner else if (!(env->flags & REG_LENIENT))
1402*3e14f97fSRoger A. Faulkner goto erange;
1403*3e14f97fSRoger A. Faulkner else
1404*3e14f97fSRoger A. Faulkner inrange = 0;
1405*3e14f97fSRoger A. Faulkner }
1406da2e3ebdSchin else if (inrange == 1)
1407da2e3ebdSchin {
1408da2e3ebdSchin setadd(e->re.charclass, last);
1409da2e3ebdSchin elements++;
1410da2e3ebdSchin }
1411da2e3ebdSchin else
1412da2e3ebdSchin inrange = 1;
1413da2e3ebdSchin last = c;
1414da2e3ebdSchin }
1415da2e3ebdSchin #if _PACKAGE_ast
1416da2e3ebdSchin if (complicated && mbcoll())
1417da2e3ebdSchin {
1418da2e3ebdSchin Dt_t* dt;
1419da2e3ebdSchin Cchr_t* cc;
1420da2e3ebdSchin Cchr_t* tc;
1421da2e3ebdSchin Cchr_t* xc;
1422da2e3ebdSchin Celt_t* ce;
1423da2e3ebdSchin Cchr_t key;
1424da2e3ebdSchin int rw;
1425da2e3ebdSchin int rc;
14267c2fbfb3SApril Chin int wc;
1427da2e3ebdSchin unsigned char* rp;
1428da2e3ebdSchin unsigned char* pp;
14297c2fbfb3SApril Chin char* wp;
14307c2fbfb3SApril Chin char cb[2][COLL_KEY_MAX+1];
1431da2e3ebdSchin
1432da2e3ebdSchin static Dtdisc_t disc;
1433da2e3ebdSchin
1434da2e3ebdSchin static const char primary[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
1435da2e3ebdSchin
1436da2e3ebdSchin if (!(dt = (Dt_t*)LCINFO(AST_LC_COLLATE)->data))
1437da2e3ebdSchin {
1438da2e3ebdSchin disc.key = offsetof(Cchr_t, key);
1439da2e3ebdSchin if ((cc = newof(0, Cchr_t, elementsof(primary), 0)) && (dt = dtopen(&disc, Dttree)))
1440da2e3ebdSchin {
1441da2e3ebdSchin for (i = 0; i < elementsof(primary) - 1; i++, cc++)
1442da2e3ebdSchin {
1443da2e3ebdSchin cc->nam[0] = primary[i];
1444da2e3ebdSchin mbxfrm(cc->key, cc->nam, COLL_KEY_MAX);
1445da2e3ebdSchin dtinsert(dt, cc);
1446da2e3ebdSchin }
1447da2e3ebdSchin for (i = 0; i < elementsof(cc->key); i++)
1448da2e3ebdSchin cc->key[i] = ~0;
1449da2e3ebdSchin dtinsert(dt, cc);
1450da2e3ebdSchin LCINFO(AST_LC_COLLATE)->data = (void*)dt;
1451da2e3ebdSchin }
1452da2e3ebdSchin else
1453da2e3ebdSchin {
1454da2e3ebdSchin if (cc)
1455da2e3ebdSchin free(cc);
1456da2e3ebdSchin drop(env->disc, e);
1457da2e3ebdSchin return 0;
1458da2e3ebdSchin }
1459da2e3ebdSchin }
1460da2e3ebdSchin if (dt)
1461da2e3ebdSchin {
1462da2e3ebdSchin drop(env->disc, e);
1463da2e3ebdSchin if (ic = env->flags & REG_ICASE)
1464da2e3ebdSchin elements *= 2;
14657c2fbfb3SApril Chin if (!(e = node(env, REX_COLL_CLASS, 1, 1, (elements + 2) * sizeof(Celt_t))))
1466da2e3ebdSchin return 0;
1467da2e3ebdSchin ce = (Celt_t*)e->re.data;
1468da2e3ebdSchin e->re.collate.invert = neg;
1469da2e3ebdSchin e->re.collate.elements = ce;
1470da2e3ebdSchin env->cursor = first;
1471da2e3ebdSchin inrange = 0;
1472da2e3ebdSchin for (;;)
1473da2e3ebdSchin {
1474da2e3ebdSchin if ((c = *env->cursor) == 0 || c == env->terminator || (env->flags & REG_ESCAPE) && c == env->delimiter)
1475da2e3ebdSchin goto error;
1476da2e3ebdSchin pp = env->cursor;
1477da2e3ebdSchin env->cursor += (w = MBSIZE(env->cursor));
1478*3e14f97fSRoger A. Faulkner if (c == '\\' && ((env->flags & REG_CLASS_ESCAPE) || env->type >= SRE && env->parnest || *env->cursor == env->delimiter && (env->flags & REG_ESCAPE)))
1479da2e3ebdSchin {
1480da2e3ebdSchin if (*env->cursor)
1481da2e3ebdSchin {
1482da2e3ebdSchin if (*env->cursor == 'n')
1483da2e3ebdSchin {
1484da2e3ebdSchin pp = env->cursor++;
1485da2e3ebdSchin c = '\n';
1486da2e3ebdSchin }
1487da2e3ebdSchin else if (env->type < SRE || !(env->flags & REG_SHELL_ESCAPED))
1488da2e3ebdSchin {
1489da2e3ebdSchin env->token.len = 1;
1490da2e3ebdSchin w = magic(env, *env->cursor, 2);
1491da2e3ebdSchin if (env->token.len > 1 || w != T_BAD)
1492da2e3ebdSchin {
1493da2e3ebdSchin if (env->token.len == 1 && (f = classfun(w)))
1494da2e3ebdSchin {
1495da2e3ebdSchin if (inrange > 1)
1496da2e3ebdSchin {
1497da2e3ebdSchin if (env->type < SRE && !(env->flags & REG_LENIENT))
1498da2e3ebdSchin goto erange;
1499da2e3ebdSchin inrange = 0;
1500da2e3ebdSchin }
1501da2e3ebdSchin env->cursor++;
1502da2e3ebdSchin ce->fun = f;
1503da2e3ebdSchin ce->typ = COLL_call;
1504da2e3ebdSchin ce++;
1505da2e3ebdSchin continue;
1506da2e3ebdSchin }
1507da2e3ebdSchin if (env->token.len > 1 || w >= 0 && w < T_META)
1508da2e3ebdSchin {
1509da2e3ebdSchin c = w;
1510*3e14f97fSRoger A. Faulkner w = mbconv(mbc, c);
1511da2e3ebdSchin pp = (unsigned char*)mbc;
1512da2e3ebdSchin env->cursor += env->token.len;
1513da2e3ebdSchin }
1514da2e3ebdSchin }
1515da2e3ebdSchin }
1516da2e3ebdSchin }
1517da2e3ebdSchin }
1518da2e3ebdSchin else if (c == ']')
1519da2e3ebdSchin {
1520da2e3ebdSchin if (env->cursor == begin)
1521da2e3ebdSchin {
1522da2e3ebdSchin rp = pp;
1523da2e3ebdSchin rw = w;
1524da2e3ebdSchin inrange = 1;
1525da2e3ebdSchin continue;
1526da2e3ebdSchin }
1527da2e3ebdSchin if (inrange != 0)
1528da2e3ebdSchin {
1529da2e3ebdSchin ce = col(ce, ic, rp, rw, rc, NiL, 0, 0);
1530da2e3ebdSchin if (inrange == 2)
1531da2e3ebdSchin ce = col(ce, ic, NiL, 1, '-', NiL, 0, 0);
1532da2e3ebdSchin }
1533da2e3ebdSchin break;
1534da2e3ebdSchin }
1535da2e3ebdSchin else if (c == '-')
1536da2e3ebdSchin {
1537da2e3ebdSchin if (!inrange && env->cursor != begin && *env->cursor != ']')
1538da2e3ebdSchin {
1539da2e3ebdSchin if (env->type < SRE && !(env->flags & REG_LENIENT))
1540da2e3ebdSchin goto erange;
1541da2e3ebdSchin continue;
1542da2e3ebdSchin }
1543da2e3ebdSchin else if (inrange == 1)
1544da2e3ebdSchin {
1545da2e3ebdSchin inrange = 2;
1546da2e3ebdSchin continue;
1547da2e3ebdSchin }
1548da2e3ebdSchin }
1549da2e3ebdSchin else if (c == '[')
1550da2e3ebdSchin {
1551da2e3ebdSchin switch (*env->cursor)
1552da2e3ebdSchin {
1553da2e3ebdSchin case 0:
1554da2e3ebdSchin goto error;
1555da2e3ebdSchin case ':':
155634f9b3eeSRoland Mainz if (env->regexp)
155734f9b3eeSRoland Mainz goto complicated_normal;
1558da2e3ebdSchin if (inrange == 1)
1559da2e3ebdSchin ce = col(ce, ic, rp, rw, rc, NiL, 0, 0);
1560da2e3ebdSchin if (!(f = regclass((char*)env->cursor, (char**)&env->cursor)))
1561da2e3ebdSchin {
1562da2e3ebdSchin if (env->cursor == start && (c = *(env->cursor + 1)) && *(env->cursor + 2) == ':' && *(env->cursor + 3) == ']' && *(env->cursor + 4) == ']')
1563da2e3ebdSchin {
1564da2e3ebdSchin switch (c)
1565da2e3ebdSchin {
1566da2e3ebdSchin case '<':
1567da2e3ebdSchin i = REX_WBEG;
1568da2e3ebdSchin break;
1569da2e3ebdSchin case '>':
1570da2e3ebdSchin i = REX_WEND;
1571da2e3ebdSchin break;
1572da2e3ebdSchin default:
1573da2e3ebdSchin i = 0;
1574da2e3ebdSchin break;
1575da2e3ebdSchin }
1576da2e3ebdSchin if (i)
1577da2e3ebdSchin {
1578da2e3ebdSchin env->cursor += 5;
1579da2e3ebdSchin drop(env->disc, e);
1580da2e3ebdSchin return node(env, i, 0, 0, 0);
1581da2e3ebdSchin }
1582da2e3ebdSchin }
1583da2e3ebdSchin env->error = REG_ECTYPE;
1584da2e3ebdSchin goto error;
1585da2e3ebdSchin }
1586da2e3ebdSchin ce->fun = f;
1587da2e3ebdSchin ce->typ = COLL_call;
1588da2e3ebdSchin ce++;
1589da2e3ebdSchin inrange = 0;
1590da2e3ebdSchin continue;
1591da2e3ebdSchin case '=':
159234f9b3eeSRoland Mainz if (env->regexp)
159334f9b3eeSRoland Mainz goto complicated_normal;
1594da2e3ebdSchin if (inrange == 2)
1595da2e3ebdSchin goto erange;
1596da2e3ebdSchin if (inrange == 1)
1597da2e3ebdSchin ce = col(ce, ic, rp, rw, rc, NiL, 0, 0);
15987c2fbfb3SApril Chin pp = (unsigned char*)cb[inrange];
1599da2e3ebdSchin rp = env->cursor + 1;
16007c2fbfb3SApril Chin if ((rw = regcollate((char*)env->cursor, (char**)&env->cursor, (char*)pp, COLL_KEY_MAX)) < 0)
1601da2e3ebdSchin goto ecollate;
16027c2fbfb3SApril Chin wp = (char*)pp;
16037c2fbfb3SApril Chin wc = mbchar(wp);
1604da2e3ebdSchin c = 0;
1605da2e3ebdSchin if (ic)
1606da2e3ebdSchin {
16077c2fbfb3SApril Chin if (iswupper(wc))
16087c2fbfb3SApril Chin {
16097c2fbfb3SApril Chin wc = towlower(wc);
1610*3e14f97fSRoger A. Faulkner rw = mbconv((char*)pp, wc);
16117c2fbfb3SApril Chin c = 'u';
1612da2e3ebdSchin }
16137c2fbfb3SApril Chin else if (iswlower(wc))
16147c2fbfb3SApril Chin c = 'l';
16157c2fbfb3SApril Chin }
1616da2e3ebdSchin for (;;)
1617da2e3ebdSchin {
16187c2fbfb3SApril Chin mbxfrm(key.key, (char*)pp, COLL_KEY_MAX);
16197c2fbfb3SApril Chin if (!(cc = (Cchr_t*)dtsearch(dt, &key)) && !(cc = (Cchr_t*)dtprev(dt, &key)))
1620da2e3ebdSchin goto ecollate;
16217c2fbfb3SApril Chin xc = (tc = (Cchr_t*)dtprev(dt, cc)) && !strcasecmp((char*)tc->nam, (char*)cc->nam) ? tc : cc;
16227c2fbfb3SApril Chin if (c == 'l' || c == 'L' && !(c = 0))
1623da2e3ebdSchin ce->typ = COLL_range_lc;
16247c2fbfb3SApril Chin else if (c == 'u' || c == 'U' && !(c = 0))
1625da2e3ebdSchin ce->typ = COLL_range_uc;
1626da2e3ebdSchin else
1627da2e3ebdSchin ce->typ = COLL_range;
1628da2e3ebdSchin strcpy((char*)ce->beg, (char*)xc->key);
1629da2e3ebdSchin if (!(cc = (Cchr_t*)dtnext(dt, cc)))
1630da2e3ebdSchin goto ecollate;
1631da2e3ebdSchin if (!strcasecmp((char*)xc->nam, (char*)cc->nam) && (tc = (Cchr_t*)dtnext(dt, cc)))
1632da2e3ebdSchin cc = tc;
1633da2e3ebdSchin strcpy((char*)ce->end, (char*)cc->key);
1634da2e3ebdSchin ce->max = -1;
1635da2e3ebdSchin ce++;
1636da2e3ebdSchin if (!c)
1637da2e3ebdSchin break;
16387c2fbfb3SApril Chin if (c == 'u')
16397c2fbfb3SApril Chin {
16407c2fbfb3SApril Chin wc = towlower(wc);
16417c2fbfb3SApril Chin c = 'L';
16427c2fbfb3SApril Chin }
16437c2fbfb3SApril Chin else
16447c2fbfb3SApril Chin {
16457c2fbfb3SApril Chin wc = towupper(wc);
16467c2fbfb3SApril Chin c = 'U';
16477c2fbfb3SApril Chin }
1648*3e14f97fSRoger A. Faulkner rw = mbconv((char*)pp, wc);
1649da2e3ebdSchin }
1650da2e3ebdSchin inrange = 0;
16517c2fbfb3SApril Chin c = *pp;
1652da2e3ebdSchin continue;
1653da2e3ebdSchin case '.':
165434f9b3eeSRoland Mainz if (env->regexp)
165534f9b3eeSRoland Mainz goto complicated_normal;
16567c2fbfb3SApril Chin pp = (unsigned char*)cb[inrange];
16577c2fbfb3SApril Chin if ((w = regcollate((char*)env->cursor, (char**)&env->cursor, (char*)pp, COLL_KEY_MAX)) < 0)
1658da2e3ebdSchin goto ecollate;
1659da2e3ebdSchin c = buf[0];
1660da2e3ebdSchin break;
1661da2e3ebdSchin default:
166234f9b3eeSRoland Mainz complicated_normal:
1663da2e3ebdSchin if (*env->cursor == env->terminator || *env->cursor == env->delimiter && (env->flags & REG_ESCAPE))
1664da2e3ebdSchin goto error;
1665da2e3ebdSchin break;
1666da2e3ebdSchin }
1667da2e3ebdSchin }
1668da2e3ebdSchin if (inrange == 2)
1669da2e3ebdSchin {
1670da2e3ebdSchin ce = col(ce, ic, rp, rw, rc, pp, w, c);
1671da2e3ebdSchin if (strcmp((char*)ce->beg, (char*)ce->end) > 0)
1672da2e3ebdSchin {
1673da2e3ebdSchin if (env->type < SRE && !(env->flags & REG_LENIENT))
1674da2e3ebdSchin goto erange;
1675da2e3ebdSchin (ce-1)->typ = COLL_char;
1676da2e3ebdSchin strcpy((char*)ce->beg, (char*)(ce-1)->end);
1677da2e3ebdSchin ce->typ = COLL_char;
1678da2e3ebdSchin ce++;
1679da2e3ebdSchin }
1680da2e3ebdSchin inrange = env->type >= SRE || (env->flags & REG_LENIENT);
1681da2e3ebdSchin }
1682da2e3ebdSchin else if (inrange == 1)
1683da2e3ebdSchin ce = col(ce, ic, rp, rw, rc, NiL, 0, 0);
1684da2e3ebdSchin else
1685da2e3ebdSchin inrange = 1;
1686da2e3ebdSchin rp = pp;
1687da2e3ebdSchin rw = w;
1688da2e3ebdSchin rc = c;
1689da2e3ebdSchin }
1690da2e3ebdSchin ce->typ = COLL_end;
1691da2e3ebdSchin return e;
1692da2e3ebdSchin }
1693da2e3ebdSchin }
1694da2e3ebdSchin #endif
1695da2e3ebdSchin if (collate)
1696da2e3ebdSchin goto ecollate;
1697da2e3ebdSchin if (env->flags & REG_ICASE)
1698da2e3ebdSchin for (i = 0; i <= UCHAR_MAX; i++)
1699da2e3ebdSchin if (settst(e->re.charclass, i))
1700da2e3ebdSchin {
1701da2e3ebdSchin if (isupper(i))
1702da2e3ebdSchin c = tolower(i);
1703da2e3ebdSchin else if (islower(i))
1704da2e3ebdSchin c = toupper(i);
1705da2e3ebdSchin else
1706da2e3ebdSchin continue;
1707da2e3ebdSchin setadd(e->re.charclass, c);
1708da2e3ebdSchin }
1709da2e3ebdSchin if (neg)
1710da2e3ebdSchin {
1711da2e3ebdSchin for (i = 0; i < elementsof(e->re.charclass->bits); i++)
1712da2e3ebdSchin e->re.charclass->bits[i] ^= ~0;
1713da2e3ebdSchin if (env->explicit >= 0)
1714da2e3ebdSchin setclr(e->re.charclass, env->explicit);
1715da2e3ebdSchin }
1716da2e3ebdSchin return e;
1717da2e3ebdSchin ecollate:
1718da2e3ebdSchin env->error = REG_ECOLLATE;
1719da2e3ebdSchin goto error;
1720da2e3ebdSchin erange:
1721da2e3ebdSchin env->error = REG_ERANGE;
1722da2e3ebdSchin error:
1723da2e3ebdSchin drop(env->disc, e);
1724da2e3ebdSchin if (!env->error)
1725da2e3ebdSchin env->error = REG_EBRACK;
1726da2e3ebdSchin return 0;
1727da2e3ebdSchin }
1728da2e3ebdSchin
1729da2e3ebdSchin static Rex_t*
ccl(Cenv_t * env,int type)1730da2e3ebdSchin ccl(Cenv_t* env, int type)
1731da2e3ebdSchin {
1732da2e3ebdSchin int i;
1733da2e3ebdSchin Rex_t* e;
1734da2e3ebdSchin Celt_t* ce;
1735da2e3ebdSchin regclass_t f;
1736da2e3ebdSchin
1737da2e3ebdSchin if (!(f = classfun(type)))
1738da2e3ebdSchin {
1739da2e3ebdSchin env->error = REG_BADESC;
1740da2e3ebdSchin return 0;
1741da2e3ebdSchin }
1742da2e3ebdSchin if (!mbcoll())
1743da2e3ebdSchin {
1744da2e3ebdSchin if (!(e = node(env, REX_CLASS, 1, 1, sizeof(Set_t))))
1745da2e3ebdSchin return 0;
1746da2e3ebdSchin for (i = 0; i <= UCHAR_MAX; i++)
1747da2e3ebdSchin if ((*f)(i))
1748da2e3ebdSchin setadd(e->re.charclass, i);
1749da2e3ebdSchin if (env->explicit >= 0)
1750da2e3ebdSchin setclr(e->re.charclass, env->explicit);
1751da2e3ebdSchin }
1752da2e3ebdSchin else
1753da2e3ebdSchin {
1754da2e3ebdSchin if (!(e = node(env, REX_COLL_CLASS, 1, 1, 2 * sizeof(Celt_t))))
1755da2e3ebdSchin return 0;
1756da2e3ebdSchin ce = (Celt_t*)e->re.data;
1757da2e3ebdSchin e->re.collate.invert = 0;
1758da2e3ebdSchin e->re.collate.elements = ce;
1759da2e3ebdSchin ce->fun = f;
17607c2fbfb3SApril Chin ce->typ = COLL_call;
1761da2e3ebdSchin ce++;
1762da2e3ebdSchin ce->typ = COLL_end;
1763da2e3ebdSchin }
1764da2e3ebdSchin return e;
1765da2e3ebdSchin }
1766da2e3ebdSchin
1767da2e3ebdSchin static Rex_t*
rep(Cenv_t * env,Rex_t * e,int number,int last)1768da2e3ebdSchin rep(Cenv_t* env, Rex_t* e, int number, int last)
1769da2e3ebdSchin {
1770da2e3ebdSchin Rex_t* f;
1771da2e3ebdSchin unsigned long m = 0;
1772da2e3ebdSchin unsigned long n = RE_DUP_INF;
1773da2e3ebdSchin int minimal = -1;
1774da2e3ebdSchin
1775da2e3ebdSchin if (!e)
1776da2e3ebdSchin return 0;
1777da2e3ebdSchin switch (token(env))
1778da2e3ebdSchin {
1779da2e3ebdSchin case T_BANG:
1780da2e3ebdSchin eat(env);
1781da2e3ebdSchin if (!(f = node(env, REX_NEG, m, n, 0)))
1782da2e3ebdSchin {
1783da2e3ebdSchin drop(env->disc, e);
1784da2e3ebdSchin return 0;
1785da2e3ebdSchin }
1786da2e3ebdSchin f->re.group.expr.rex = e;
1787da2e3ebdSchin return f;
1788da2e3ebdSchin case T_QUES:
1789da2e3ebdSchin eat(env);
1790da2e3ebdSchin n = 1;
1791da2e3ebdSchin break;
1792da2e3ebdSchin case T_STAR:
1793da2e3ebdSchin eat(env);
1794da2e3ebdSchin break;
1795da2e3ebdSchin case T_PLUS:
1796da2e3ebdSchin eat(env);
1797da2e3ebdSchin m = 1;
1798da2e3ebdSchin break;
1799da2e3ebdSchin case T_LEFT:
1800da2e3ebdSchin eat(env);
1801da2e3ebdSchin m = env->token.min;
1802da2e3ebdSchin n = env->token.max;
1803da2e3ebdSchin break;
1804da2e3ebdSchin default:
1805da2e3ebdSchin return e;
1806da2e3ebdSchin }
1807da2e3ebdSchin if (env->token.att)
1808da2e3ebdSchin minimal = 1;
1809da2e3ebdSchin else if (env->type < SRE)
1810da2e3ebdSchin switch (token(env))
1811da2e3ebdSchin {
1812da2e3ebdSchin case T_QUES:
1813da2e3ebdSchin eat(env);
1814da2e3ebdSchin minimal = !(env->flags & REG_MINIMAL);
1815da2e3ebdSchin break;
1816da2e3ebdSchin case T_STAR: /*AST*/
1817da2e3ebdSchin eat(env);
1818da2e3ebdSchin minimal = !!(env->flags & REG_MINIMAL);
1819da2e3ebdSchin break;
1820da2e3ebdSchin }
1821da2e3ebdSchin switch (e->type)
1822da2e3ebdSchin {
1823da2e3ebdSchin case REX_DOT:
1824da2e3ebdSchin case REX_CLASS:
1825da2e3ebdSchin case REX_COLL_CLASS:
1826da2e3ebdSchin case REX_ONECHAR:
1827da2e3ebdSchin e->lo = m;
1828da2e3ebdSchin e->hi = n;
1829da2e3ebdSchin if (minimal >= 0)
1830da2e3ebdSchin mark(e, minimal);
1831da2e3ebdSchin return e;
1832da2e3ebdSchin #if HUH_2002_08_07
1833da2e3ebdSchin case REX_BEG:
1834da2e3ebdSchin #endif
1835da2e3ebdSchin case REX_BEG_STR:
1836da2e3ebdSchin case REX_END_STR:
1837da2e3ebdSchin case REX_FIN_STR:
1838da2e3ebdSchin case REX_WBEG:
1839da2e3ebdSchin case REX_WEND:
1840da2e3ebdSchin case REX_WORD:
1841da2e3ebdSchin case REX_WORD_NOT:
1842da2e3ebdSchin env->error = REG_BADRPT;
1843da2e3ebdSchin drop(env->disc, e);
1844da2e3ebdSchin return 0;
1845da2e3ebdSchin }
1846da2e3ebdSchin if (m == 1 && n == 1)
1847da2e3ebdSchin {
1848da2e3ebdSchin if (minimal >= 0)
1849da2e3ebdSchin mark(e, minimal);
1850da2e3ebdSchin return e;
1851da2e3ebdSchin }
1852da2e3ebdSchin if (!(f = node(env, REX_REP, m, n, 0)))
1853da2e3ebdSchin {
1854da2e3ebdSchin drop(env->disc, e);
1855da2e3ebdSchin return 0;
1856da2e3ebdSchin }
1857da2e3ebdSchin f->re.group.expr.rex = e;
1858da2e3ebdSchin f->re.group.number = number;
1859da2e3ebdSchin f->re.group.last = last;
1860da2e3ebdSchin if (minimal >= 0)
1861da2e3ebdSchin mark(f, minimal);
1862da2e3ebdSchin if (m <= n && n)
1863da2e3ebdSchin {
1864da2e3ebdSchin for (; e && e->type >= REX_GROUP && e->type <= REX_GROUP_CUT; e = e->re.group.expr.rex);
1865da2e3ebdSchin if (e && e->type == REX_NEG)
1866da2e3ebdSchin f->type = REX_GROUP;
1867da2e3ebdSchin }
1868da2e3ebdSchin return f;
1869da2e3ebdSchin }
1870da2e3ebdSchin
1871da2e3ebdSchin static int
isstring(Rex_t * e)1872da2e3ebdSchin isstring(Rex_t* e)
1873da2e3ebdSchin {
1874da2e3ebdSchin switch (e->type)
1875da2e3ebdSchin {
1876da2e3ebdSchin case REX_ONECHAR:
1877da2e3ebdSchin return e->lo == 1 && e->hi == 1;
1878da2e3ebdSchin case REX_STRING:
1879da2e3ebdSchin return 1;
1880da2e3ebdSchin }
1881da2e3ebdSchin return 0;
1882da2e3ebdSchin }
1883da2e3ebdSchin
1884da2e3ebdSchin static Trie_node_t*
trienode(Cenv_t * env,int c)1885da2e3ebdSchin trienode(Cenv_t* env, int c)
1886da2e3ebdSchin {
1887da2e3ebdSchin Trie_node_t* t;
1888da2e3ebdSchin
1889da2e3ebdSchin if (t = (Trie_node_t*)alloc(env->disc, 0, sizeof(Trie_node_t)))
1890da2e3ebdSchin {
1891da2e3ebdSchin memset(t, 0, sizeof(Trie_node_t));
1892da2e3ebdSchin t->c = c;
1893da2e3ebdSchin }
1894da2e3ebdSchin return t;
1895da2e3ebdSchin }
1896da2e3ebdSchin
1897da2e3ebdSchin static int
insert(Cenv_t * env,Rex_t * f,Rex_t * g)1898da2e3ebdSchin insert(Cenv_t* env, Rex_t* f, Rex_t* g)
1899da2e3ebdSchin {
1900da2e3ebdSchin unsigned char* s;
1901da2e3ebdSchin unsigned char* e;
1902da2e3ebdSchin Trie_node_t* t;
1903da2e3ebdSchin int len;
1904da2e3ebdSchin unsigned char tmp[2];
1905da2e3ebdSchin
1906da2e3ebdSchin switch (f->type)
1907da2e3ebdSchin {
1908da2e3ebdSchin case REX_ONECHAR:
1909da2e3ebdSchin *(s = tmp) = f->re.onechar;
1910da2e3ebdSchin e = s + 1;
1911da2e3ebdSchin break;
1912da2e3ebdSchin case REX_STRING:
1913da2e3ebdSchin s = f->re.string.base;
1914da2e3ebdSchin e = s + f->re.string.size;
1915da2e3ebdSchin break;
1916da2e3ebdSchin default:
1917da2e3ebdSchin return 1;
1918da2e3ebdSchin }
1919da2e3ebdSchin if (!(t = g->re.trie.root[*s]) && !(t = g->re.trie.root[*s] = trienode(env, *s)))
1920da2e3ebdSchin return 1;
1921da2e3ebdSchin for (len = 1;;)
1922da2e3ebdSchin {
1923da2e3ebdSchin if (t->c == *s)
1924da2e3ebdSchin {
1925da2e3ebdSchin if (++s >= e)
1926da2e3ebdSchin break;
1927da2e3ebdSchin if (!t->son && !(t->son = trienode(env, *s)))
1928da2e3ebdSchin return 1;
1929da2e3ebdSchin t = t->son;
1930da2e3ebdSchin len++;
1931da2e3ebdSchin }
1932da2e3ebdSchin else
1933da2e3ebdSchin {
1934da2e3ebdSchin if (!t->sib && !(t->sib = trienode(env, *s)))
1935da2e3ebdSchin return 1;
1936da2e3ebdSchin t = t->sib;
1937da2e3ebdSchin }
1938da2e3ebdSchin }
1939da2e3ebdSchin if (g->re.trie.min > len)
1940da2e3ebdSchin g->re.trie.min = len;
1941da2e3ebdSchin if (g->re.trie.max < len)
1942da2e3ebdSchin g->re.trie.max = len;
1943da2e3ebdSchin t->end = 1;
1944da2e3ebdSchin return 0;
1945da2e3ebdSchin }
1946da2e3ebdSchin
1947da2e3ebdSchin /*
1948da2e3ebdSchin * trie() tries to combine nontrivial e and f into a REX_TRIE
1949da2e3ebdSchin * unless 0 is returned, e and f are deleted as far as possible
1950da2e3ebdSchin * also called by regcomb
1951da2e3ebdSchin */
1952da2e3ebdSchin
1953da2e3ebdSchin static Rex_t*
trie(Cenv_t * env,Rex_t * e,Rex_t * f)1954da2e3ebdSchin trie(Cenv_t* env, Rex_t* e, Rex_t* f)
1955da2e3ebdSchin {
1956da2e3ebdSchin Rex_t* g;
1957da2e3ebdSchin
1958da2e3ebdSchin if (e->next || f->next || !isstring(e) || e->flags != f->flags)
1959da2e3ebdSchin return 0;
1960da2e3ebdSchin if (isstring(f))
1961da2e3ebdSchin {
1962da2e3ebdSchin if (!(g = node(env, REX_TRIE, 0, 0, (UCHAR_MAX + 1) * sizeof(Trie_node_t*))))
1963da2e3ebdSchin return 0;
1964da2e3ebdSchin g->re.trie.min = INT_MAX;
1965da2e3ebdSchin if (insert(env, f, g))
1966da2e3ebdSchin goto nospace;
1967da2e3ebdSchin drop(env->disc, f);
1968da2e3ebdSchin }
1969da2e3ebdSchin else if (f->type != REX_TRIE)
1970da2e3ebdSchin return 0;
1971da2e3ebdSchin else
1972da2e3ebdSchin g = f;
1973da2e3ebdSchin if (insert(env, e, g))
1974da2e3ebdSchin goto nospace;
1975da2e3ebdSchin drop(env->disc, e);
1976da2e3ebdSchin return g;
1977da2e3ebdSchin nospace:
1978da2e3ebdSchin if (g != f)
1979da2e3ebdSchin drop(env->disc, g);
1980da2e3ebdSchin return 0;
1981da2e3ebdSchin }
1982da2e3ebdSchin
1983da2e3ebdSchin static Rex_t* alt(Cenv_t*, int, int);
1984da2e3ebdSchin
1985da2e3ebdSchin static int
chr(register Cenv_t * env,int * escaped)1986da2e3ebdSchin chr(register Cenv_t* env, int* escaped)
1987da2e3ebdSchin {
1988da2e3ebdSchin unsigned char* p;
1989da2e3ebdSchin int c;
1990da2e3ebdSchin
1991da2e3ebdSchin *escaped = 0;
1992da2e3ebdSchin if (!(c = *env->cursor))
1993da2e3ebdSchin return -1;
1994da2e3ebdSchin env->cursor++;
1995da2e3ebdSchin if (c == '\\')
1996da2e3ebdSchin {
1997da2e3ebdSchin if (env->flags & REG_SHELL_ESCAPED)
1998da2e3ebdSchin return c;
1999da2e3ebdSchin if (!(c = *(env->cursor + 1)) || c == env->terminator)
2000da2e3ebdSchin {
2001da2e3ebdSchin if (env->flags & REG_LENIENT)
2002da2e3ebdSchin return c ? c : '\\';
2003da2e3ebdSchin env->error = REG_EESCAPE;
2004da2e3ebdSchin return -1;
2005da2e3ebdSchin }
2006da2e3ebdSchin p = env->cursor;
2007da2e3ebdSchin c = chresc((char*)env->cursor - 1, (char**)&env->cursor);
2008da2e3ebdSchin *escaped = env->cursor - p;
2009da2e3ebdSchin }
2010da2e3ebdSchin return c;
2011da2e3ebdSchin }
2012da2e3ebdSchin
2013da2e3ebdSchin /*
2014da2e3ebdSchin * open the perly gates
2015da2e3ebdSchin */
2016da2e3ebdSchin
2017da2e3ebdSchin static Rex_t*
grp(Cenv_t * env,int parno)2018da2e3ebdSchin grp(Cenv_t* env, int parno)
2019da2e3ebdSchin {
2020da2e3ebdSchin Rex_t* e;
2021da2e3ebdSchin Rex_t* f;
2022da2e3ebdSchin int c;
2023da2e3ebdSchin int i;
2024da2e3ebdSchin int n;
2025da2e3ebdSchin int x;
2026da2e3ebdSchin int esc;
2027da2e3ebdSchin int typ;
2028da2e3ebdSchin int beg;
2029da2e3ebdSchin unsigned char* p;
2030da2e3ebdSchin
2031da2e3ebdSchin beg = env->pattern == env->cursor - env->token.len;
2032da2e3ebdSchin if (!(c = env->token.lex) && (c = *env->cursor))
2033da2e3ebdSchin env->cursor++;
2034da2e3ebdSchin env->token.len = 0;
2035da2e3ebdSchin env->parnest++;
2036da2e3ebdSchin typ = -1;
2037da2e3ebdSchin switch (c)
2038da2e3ebdSchin {
2039da2e3ebdSchin case '-':
2040da2e3ebdSchin case '+':
2041da2e3ebdSchin case 'a':
2042da2e3ebdSchin case 'g':
2043da2e3ebdSchin case 'i':
2044da2e3ebdSchin case 'l':
2045da2e3ebdSchin case 'm':
2046da2e3ebdSchin case 'p':
2047da2e3ebdSchin case 'r':
2048da2e3ebdSchin case 's':
2049da2e3ebdSchin case 'x':
2050da2e3ebdSchin case 'A':
2051da2e3ebdSchin case 'B':
2052da2e3ebdSchin case 'E':
2053da2e3ebdSchin case 'F':
2054da2e3ebdSchin case 'G':
2055da2e3ebdSchin case 'I':
2056da2e3ebdSchin case 'K':
20577c2fbfb3SApril Chin case 'L':
20587c2fbfb3SApril Chin case 'M': /* glob(3) */
20597c2fbfb3SApril Chin case 'N': /* glob(3) */
20607c2fbfb3SApril Chin case 'O': /* glob(3) */
2061*3e14f97fSRoger A. Faulkner case 'P':
20627c2fbfb3SApril Chin case 'R': /* pcre */
2063da2e3ebdSchin case 'S':
2064da2e3ebdSchin case 'U': /* pcre */
2065da2e3ebdSchin case 'X': /* pcre */
2066da2e3ebdSchin x = REX_GROUP;
2067da2e3ebdSchin i = 1;
2068da2e3ebdSchin env->token.push = 1;
2069da2e3ebdSchin for (;;)
2070da2e3ebdSchin {
2071da2e3ebdSchin switch (c)
2072da2e3ebdSchin {
20737c2fbfb3SApril Chin case ')':
20747c2fbfb3SApril Chin if (!(env->flags & REG_LITERAL))
20757c2fbfb3SApril Chin {
20767c2fbfb3SApril Chin env->error = REG_BADRPT;
20777c2fbfb3SApril Chin return 0;
20787c2fbfb3SApril Chin }
20797c2fbfb3SApril Chin /*FALLTHROUGH*/
2080da2e3ebdSchin case 0:
2081da2e3ebdSchin case T_CLOSE:
2082da2e3ebdSchin x = 0;
2083da2e3ebdSchin goto done;
2084da2e3ebdSchin case ':':
2085da2e3ebdSchin eat(env);
2086da2e3ebdSchin if (token(env) == T_CLOSE)
2087da2e3ebdSchin x = 0;
2088da2e3ebdSchin goto done;
2089da2e3ebdSchin case '-':
2090da2e3ebdSchin i = 0;
2091da2e3ebdSchin break;
2092da2e3ebdSchin case '+':
2093da2e3ebdSchin i = 1;
2094da2e3ebdSchin break;
2095da2e3ebdSchin case 'a':
2096da2e3ebdSchin if (i)
2097da2e3ebdSchin env->flags |= (REG_LEFT|REG_RIGHT);
2098da2e3ebdSchin else
2099da2e3ebdSchin env->flags &= ~(REG_LEFT|REG_RIGHT);
2100da2e3ebdSchin break;
2101da2e3ebdSchin case 'g':
2102da2e3ebdSchin if (i)
2103da2e3ebdSchin env->flags &= ~REG_MINIMAL;
2104da2e3ebdSchin else
2105da2e3ebdSchin env->flags |= REG_MINIMAL;
2106da2e3ebdSchin break;
2107da2e3ebdSchin case 'i':
2108da2e3ebdSchin if (i)
2109da2e3ebdSchin env->flags |= REG_ICASE;
2110da2e3ebdSchin else
2111da2e3ebdSchin env->flags &= ~REG_ICASE;
2112da2e3ebdSchin break;
2113da2e3ebdSchin case 'l':
2114da2e3ebdSchin if (i)
2115da2e3ebdSchin env->flags |= REG_LEFT;
2116da2e3ebdSchin else
2117da2e3ebdSchin env->flags &= ~REG_LEFT;
2118da2e3ebdSchin break;
2119da2e3ebdSchin case 'm':
2120da2e3ebdSchin if (i)
2121da2e3ebdSchin env->flags |= REG_NEWLINE;
2122da2e3ebdSchin else
2123da2e3ebdSchin env->flags &= ~REG_NEWLINE;
2124da2e3ebdSchin env->explicit = (env->flags & (REG_NEWLINE|REG_SPAN)) == REG_NEWLINE ? env->mappednewline : -1;
2125da2e3ebdSchin break;
2126da2e3ebdSchin case 'p':
2127da2e3ebdSchin if (i)
2128da2e3ebdSchin env->flags &= ~REG_LENIENT;
2129da2e3ebdSchin else
2130da2e3ebdSchin env->flags |= REG_LENIENT;
2131da2e3ebdSchin break;
2132da2e3ebdSchin case 'r':
2133da2e3ebdSchin if (i)
2134da2e3ebdSchin env->flags |= REG_RIGHT;
2135da2e3ebdSchin else
2136da2e3ebdSchin env->flags &= ~REG_RIGHT;
2137da2e3ebdSchin break;
2138da2e3ebdSchin case 's':
2139da2e3ebdSchin if (i)
2140da2e3ebdSchin env->flags |= REG_SPAN;
2141da2e3ebdSchin else
2142da2e3ebdSchin env->flags &= ~REG_SPAN;
2143da2e3ebdSchin env->explicit = (env->flags & (REG_NEWLINE|REG_SPAN)) == REG_NEWLINE ? env->mappednewline : -1;
2144da2e3ebdSchin break;
2145da2e3ebdSchin case 'x':
2146da2e3ebdSchin if (i)
2147da2e3ebdSchin env->flags |= REG_COMMENT;
2148da2e3ebdSchin else
2149da2e3ebdSchin env->flags &= ~REG_COMMENT;
2150da2e3ebdSchin break;
2151da2e3ebdSchin case 'A':
2152*3e14f97fSRoger A. Faulkner env->flags &= ~(REG_AUGMENTED|REG_EXTENDED|REG_LITERAL|REG_SHELL|REG_LEFT|REG_RIGHT|REG_CLASS_ESCAPE);
2153da2e3ebdSchin env->flags |= REG_AUGMENTED|REG_EXTENDED;
2154da2e3ebdSchin typ = ARE;
2155da2e3ebdSchin break;
2156da2e3ebdSchin case 'B':
2157da2e3ebdSchin case 'G':
2158*3e14f97fSRoger A. Faulkner env->flags &= ~(REG_AUGMENTED|REG_EXTENDED|REG_LITERAL|REG_SHELL|REG_LEFT|REG_RIGHT|REG_CLASS_ESCAPE);
2159da2e3ebdSchin typ = BRE;
2160da2e3ebdSchin break;
2161da2e3ebdSchin case 'E':
2162*3e14f97fSRoger A. Faulkner env->flags &= ~(REG_AUGMENTED|REG_EXTENDED|REG_LITERAL|REG_SHELL|REG_LEFT|REG_RIGHT|REG_CLASS_ESCAPE);
2163da2e3ebdSchin env->flags |= REG_EXTENDED;
2164da2e3ebdSchin typ = ERE;
2165da2e3ebdSchin break;
2166da2e3ebdSchin case 'F':
2167da2e3ebdSchin case 'L':
2168*3e14f97fSRoger A. Faulkner env->flags &= ~(REG_AUGMENTED|REG_EXTENDED|REG_LITERAL|REG_SHELL|REG_LEFT|REG_RIGHT|REG_CLASS_ESCAPE);
2169da2e3ebdSchin env->flags |= REG_LITERAL;
2170da2e3ebdSchin typ = ERE;
2171da2e3ebdSchin break;
2172da2e3ebdSchin case 'K':
2173*3e14f97fSRoger A. Faulkner env->flags &= ~(REG_AUGMENTED|REG_EXTENDED|REG_LITERAL|REG_SHELL|REG_LEFT|REG_RIGHT|REG_CLASS_ESCAPE);
2174da2e3ebdSchin env->flags |= REG_AUGMENTED|REG_SHELL|REG_LEFT|REG_RIGHT;
2175da2e3ebdSchin typ = KRE;
2176da2e3ebdSchin break;
2177da2e3ebdSchin case 'M':
2178da2e3ebdSchin /* used by caller to disable glob(3) GLOB_BRACE */
2179da2e3ebdSchin break;
2180da2e3ebdSchin case 'N':
2181da2e3ebdSchin /* used by caller to disable glob(3) GLOB_NOCHECK */
2182da2e3ebdSchin break;
21837c2fbfb3SApril Chin case 'O':
2184da2e3ebdSchin /* used by caller to disable glob(3) GLOB_STARSTAR */
2185da2e3ebdSchin break;
2186*3e14f97fSRoger A. Faulkner case 'P':
2187*3e14f97fSRoger A. Faulkner env->flags &= ~(REG_AUGMENTED|REG_EXTENDED|REG_LITERAL|REG_SHELL|REG_LEFT|REG_RIGHT|REG_CLASS_ESCAPE);
2188*3e14f97fSRoger A. Faulkner env->flags |= REG_EXTENDED|REG_CLASS_ESCAPE;
2189*3e14f97fSRoger A. Faulkner typ = ERE;
2190*3e14f97fSRoger A. Faulkner break;
2191da2e3ebdSchin case 'S':
2192*3e14f97fSRoger A. Faulkner env->flags &= ~(REG_AUGMENTED|REG_EXTENDED|REG_LITERAL|REG_SHELL|REG_LEFT|REG_RIGHT|REG_CLASS_ESCAPE);
2193da2e3ebdSchin env->flags |= REG_SHELL|REG_LEFT|REG_RIGHT;
2194da2e3ebdSchin typ = SRE;
2195da2e3ebdSchin break;
2196da2e3ebdSchin case 'U': /* PCRE_UNGREEDY */
2197da2e3ebdSchin if (i)
2198da2e3ebdSchin env->flags |= REG_MINIMAL;
2199da2e3ebdSchin else
2200da2e3ebdSchin env->flags &= ~REG_MINIMAL;
2201da2e3ebdSchin break;
2202da2e3ebdSchin case 'X': /* PCRE_EXTRA */
2203da2e3ebdSchin break;
2204da2e3ebdSchin default:
2205da2e3ebdSchin env->error = REG_BADRPT;
2206da2e3ebdSchin return 0;
2207da2e3ebdSchin }
2208da2e3ebdSchin eat(env);
2209da2e3ebdSchin c = token(env);
2210da2e3ebdSchin }
2211da2e3ebdSchin done:
2212da2e3ebdSchin break;
2213da2e3ebdSchin case ':':
2214da2e3ebdSchin x = REX_GROUP;
2215da2e3ebdSchin break;
2216da2e3ebdSchin case '=':
2217da2e3ebdSchin x = REX_GROUP_AHEAD;
2218da2e3ebdSchin break;
2219da2e3ebdSchin case '!':
2220da2e3ebdSchin x = REX_GROUP_AHEAD_NOT;
2221da2e3ebdSchin break;
2222da2e3ebdSchin case '<':
2223da2e3ebdSchin switch (token(env))
2224da2e3ebdSchin {
2225da2e3ebdSchin case '=':
2226da2e3ebdSchin x = REX_GROUP_BEHIND;
2227da2e3ebdSchin break;
2228da2e3ebdSchin case '!':
2229da2e3ebdSchin case T_BANG:
2230da2e3ebdSchin x = REX_GROUP_BEHIND_NOT;
2231da2e3ebdSchin break;
2232da2e3ebdSchin default:
2233da2e3ebdSchin env->error = REG_BADRPT;
2234da2e3ebdSchin return 0;
2235da2e3ebdSchin }
2236da2e3ebdSchin eat(env);
2237da2e3ebdSchin break;
2238da2e3ebdSchin case '>':
2239da2e3ebdSchin x = REX_GROUP_CUT;
2240da2e3ebdSchin break;
2241da2e3ebdSchin case '%':
2242da2e3ebdSchin case T_PERCENT:
2243da2e3ebdSchin e = node(env, REX_NEST, 0, 0, (UCHAR_MAX + 1) * sizeof(unsigned short));
2244da2e3ebdSchin e->re.nest.primary = isalnum(*env->cursor) ? -1 : *env->cursor;
2245da2e3ebdSchin n = 1;
2246da2e3ebdSchin for (;;)
2247da2e3ebdSchin {
2248da2e3ebdSchin switch (i = chr(env, &esc))
2249da2e3ebdSchin {
2250da2e3ebdSchin case -1:
2251da2e3ebdSchin case 0:
2252da2e3ebdSchin invalid:
2253da2e3ebdSchin env->cursor -= esc + 1;
2254da2e3ebdSchin env->error = REG_EPAREN;
2255da2e3ebdSchin return 0;
2256da2e3ebdSchin case 'D':
2257da2e3ebdSchin x = REX_NEST_delimiter;
2258da2e3ebdSchin /*FALLTHROUGH*/
2259da2e3ebdSchin delimiter:
2260da2e3ebdSchin if ((i = chr(env, &esc)) < 0)
2261da2e3ebdSchin goto invalid;
2262da2e3ebdSchin if (e->re.nest.type[i] & ~x)
2263da2e3ebdSchin goto invalid;
2264da2e3ebdSchin e->re.nest.type[i] = x;
2265da2e3ebdSchin continue;
2266da2e3ebdSchin case 'E':
2267da2e3ebdSchin x = REX_NEST_escape;
2268da2e3ebdSchin goto delimiter;
2269da2e3ebdSchin case 'L':
2270da2e3ebdSchin x = REX_NEST_literal;
2271da2e3ebdSchin goto quote;
2272da2e3ebdSchin case 'O':
2273da2e3ebdSchin switch (i = chr(env, &esc))
2274da2e3ebdSchin {
2275da2e3ebdSchin case 'T':
2276da2e3ebdSchin e->re.nest.type[UCHAR_MAX+1] |= REX_NEST_terminator;
2277da2e3ebdSchin break;
2278da2e3ebdSchin default:
2279da2e3ebdSchin goto invalid;
2280da2e3ebdSchin }
2281da2e3ebdSchin continue;
2282da2e3ebdSchin case 'Q':
2283da2e3ebdSchin x = REX_NEST_quote;
2284da2e3ebdSchin /*FALLTHROUGH*/
2285da2e3ebdSchin quote:
2286da2e3ebdSchin if ((i = chr(env, &esc)) < 0)
2287da2e3ebdSchin goto invalid;
2288da2e3ebdSchin if (e->re.nest.type[i] & ~x)
2289da2e3ebdSchin goto invalid;
2290da2e3ebdSchin e->re.nest.type[i] = x|REX_NEST_open|REX_NEST_close|(i<<REX_NEST_SHIFT);
2291da2e3ebdSchin continue;
2292da2e3ebdSchin case 'S':
2293da2e3ebdSchin x = REX_NEST_separator;
2294da2e3ebdSchin goto delimiter;
2295da2e3ebdSchin case 'T':
2296da2e3ebdSchin x = REX_NEST_terminator;
2297da2e3ebdSchin goto delimiter;
2298da2e3ebdSchin case '|':
2299da2e3ebdSchin case '&':
2300da2e3ebdSchin if (!esc)
2301da2e3ebdSchin goto invalid;
2302da2e3ebdSchin goto nesting;
2303da2e3ebdSchin case '(':
2304da2e3ebdSchin if (!esc)
2305da2e3ebdSchin n++;
2306da2e3ebdSchin goto nesting;
2307da2e3ebdSchin case ')':
2308da2e3ebdSchin if (!esc && !--n)
2309da2e3ebdSchin break;
2310da2e3ebdSchin goto nesting;
2311da2e3ebdSchin default:
2312da2e3ebdSchin nesting:
2313da2e3ebdSchin if (isalnum(i) || (e->re.nest.type[i] & (REX_NEST_close|REX_NEST_escape|REX_NEST_literal|REX_NEST_quote|REX_NEST_delimiter|REX_NEST_separator|REX_NEST_terminator)))
2314da2e3ebdSchin goto invalid;
2315da2e3ebdSchin e->re.nest.type[i] = REX_NEST_open;
2316da2e3ebdSchin if ((x = chr(env, &esc)) < 0 || (e->re.nest.type[x] & (REX_NEST_close|REX_NEST_escape|REX_NEST_delimiter|REX_NEST_separator|REX_NEST_terminator)))
2317da2e3ebdSchin goto invalid;
2318da2e3ebdSchin if (!esc)
2319da2e3ebdSchin {
2320da2e3ebdSchin if (x == ')' && !--n)
2321da2e3ebdSchin goto invalid;
2322da2e3ebdSchin else if (x == '(')
2323da2e3ebdSchin n++;
2324da2e3ebdSchin }
2325da2e3ebdSchin e->re.nest.type[x] |= REX_NEST_close;
2326da2e3ebdSchin e->re.nest.type[i] |= x << REX_NEST_SHIFT;
2327da2e3ebdSchin continue;
2328da2e3ebdSchin }
2329da2e3ebdSchin break;
2330da2e3ebdSchin }
2331da2e3ebdSchin env->parnest--;
2332da2e3ebdSchin if (c == T_PERCENT)
2333da2e3ebdSchin for (n = 0; n < 2; n++)
2334da2e3ebdSchin {
2335da2e3ebdSchin parno = ++env->parno;
2336da2e3ebdSchin if (!(f = node(env, REX_GROUP, 0, 0, 0)))
2337da2e3ebdSchin {
2338da2e3ebdSchin drop(env->disc, e);
2339da2e3ebdSchin return 0;
2340da2e3ebdSchin }
2341da2e3ebdSchin if (parno < elementsof(env->paren))
2342da2e3ebdSchin env->paren[parno] = f;
2343da2e3ebdSchin f->re.group.back = 0;
2344da2e3ebdSchin f->re.group.number = parno;
2345da2e3ebdSchin f->re.group.expr.rex = e;
2346da2e3ebdSchin e = f;
2347da2e3ebdSchin }
2348da2e3ebdSchin return e;
2349da2e3ebdSchin case '(':
2350da2e3ebdSchin c = 0;
2351da2e3ebdSchin if (isdigit(*env->cursor))
2352da2e3ebdSchin {
2353da2e3ebdSchin f = 0;
2354da2e3ebdSchin do
2355da2e3ebdSchin {
2356da2e3ebdSchin if (c > (INT_MAX / 10))
2357da2e3ebdSchin {
2358da2e3ebdSchin env->error = REG_BADRPT;
2359da2e3ebdSchin return 0;
2360da2e3ebdSchin }
2361da2e3ebdSchin c = c * 10 + (*env->cursor++ - '0');
2362da2e3ebdSchin } while (isdigit(*env->cursor));
2363da2e3ebdSchin if (*env->cursor++ != ')')
2364da2e3ebdSchin {
2365da2e3ebdSchin env->error = REG_BADRPT;
2366da2e3ebdSchin return 0;
2367da2e3ebdSchin }
2368da2e3ebdSchin if (c && env->type >= SRE)
2369da2e3ebdSchin c = c * 2 - 1;
2370da2e3ebdSchin if (!c || c > env->parno || !env->paren[c])
2371da2e3ebdSchin {
2372da2e3ebdSchin if (!(env->flags & REG_LENIENT))
2373da2e3ebdSchin {
2374da2e3ebdSchin env->error = REG_ESUBREG;
2375da2e3ebdSchin return 0;
2376da2e3ebdSchin }
2377da2e3ebdSchin if (c)
2378da2e3ebdSchin c = -1;
2379da2e3ebdSchin }
2380da2e3ebdSchin }
2381da2e3ebdSchin else
2382da2e3ebdSchin {
2383da2e3ebdSchin if (env->type < SRE && *env->cursor++ != '?')
2384da2e3ebdSchin {
2385da2e3ebdSchin env->error = REG_BADRPT;
2386da2e3ebdSchin return 0;
2387da2e3ebdSchin }
2388da2e3ebdSchin if (!(f = grp(env, parno + 1)) && env->error)
2389da2e3ebdSchin return 0;
2390da2e3ebdSchin }
2391da2e3ebdSchin if (!(e = node(env, REX_GROUP_COND, 0, 0, 0)))
2392da2e3ebdSchin {
2393da2e3ebdSchin drop(env->disc, f);
2394da2e3ebdSchin return 0;
2395da2e3ebdSchin }
2396da2e3ebdSchin e->re.group.size = c;
2397da2e3ebdSchin e->re.group.expr.binary.left = f;
2398da2e3ebdSchin if (!(e->re.group.expr.binary.right = alt(env, parno, 1)))
2399da2e3ebdSchin {
2400da2e3ebdSchin drop(env->disc, e);
2401da2e3ebdSchin return 0;
2402da2e3ebdSchin }
2403da2e3ebdSchin if (token(env) != T_CLOSE)
2404da2e3ebdSchin {
2405da2e3ebdSchin env->error = REG_EPAREN;
2406da2e3ebdSchin return 0;
2407da2e3ebdSchin }
2408da2e3ebdSchin eat(env);
2409da2e3ebdSchin env->parnest--;
2410da2e3ebdSchin return rep(env, e, parno, parno);
2411da2e3ebdSchin case '{':
2412da2e3ebdSchin p = env->cursor;
2413da2e3ebdSchin n = 1;
2414da2e3ebdSchin while (c = *env->cursor)
2415da2e3ebdSchin {
2416da2e3ebdSchin if (c == '\\' && *(env->cursor + 1))
2417da2e3ebdSchin env->cursor++;
2418da2e3ebdSchin else if (c == '{')
2419da2e3ebdSchin n++;
2420da2e3ebdSchin else if (c == '}' && !--n)
2421da2e3ebdSchin break;
2422da2e3ebdSchin else if (c == env->delimiter || c == env->terminator)
2423da2e3ebdSchin break;
2424da2e3ebdSchin env->cursor++;
2425da2e3ebdSchin }
2426da2e3ebdSchin if (c != '}')
2427da2e3ebdSchin {
2428da2e3ebdSchin env->error = REG_EBRACE;
2429da2e3ebdSchin return 0;
2430da2e3ebdSchin }
2431da2e3ebdSchin if (*++env->cursor != ')')
2432da2e3ebdSchin {
2433da2e3ebdSchin env->error = REG_EPAREN;
2434da2e3ebdSchin return 0;
2435da2e3ebdSchin }
2436da2e3ebdSchin env->cursor++;
2437da2e3ebdSchin env->parnest--;
2438da2e3ebdSchin if (env->disc->re_version < REG_VERSION_EXEC)
2439da2e3ebdSchin {
2440da2e3ebdSchin env->error = REG_BADRPT;
2441da2e3ebdSchin return 0;
2442da2e3ebdSchin }
2443da2e3ebdSchin if (!env->disc->re_execf)
2444da2e3ebdSchin return 0;
2445da2e3ebdSchin if (!(e = node(env, REX_EXEC, 0, 0, 0)))
2446da2e3ebdSchin return 0;
2447da2e3ebdSchin e->re.exec.text = (const char*)p;
2448da2e3ebdSchin e->re.exec.size = env->cursor - p - 2;
2449da2e3ebdSchin if (!env->disc->re_compf)
2450da2e3ebdSchin e->re.exec.data = 0;
2451da2e3ebdSchin else
2452da2e3ebdSchin e->re.exec.data = (*env->disc->re_compf)(env->regex, e->re.exec.text, e->re.exec.size, env->disc);
2453da2e3ebdSchin return e;
2454da2e3ebdSchin case '0': case '1': case '2': case '3': case '4':
2455da2e3ebdSchin case '5': case '6': case '7': case '8': case '9':
2456da2e3ebdSchin c -= '0';
2457da2e3ebdSchin while (isdigit(*env->cursor))
2458da2e3ebdSchin {
2459da2e3ebdSchin if (c > (INT_MAX / 10))
2460da2e3ebdSchin {
2461da2e3ebdSchin env->error = REG_ESUBREG;
2462da2e3ebdSchin return 0;
2463da2e3ebdSchin }
2464da2e3ebdSchin c = c * 10 + *env->cursor++ - '0';
2465da2e3ebdSchin }
2466da2e3ebdSchin if (*env->cursor == ')')
2467da2e3ebdSchin {
2468da2e3ebdSchin env->cursor++;
2469da2e3ebdSchin env->parnest--;
2470da2e3ebdSchin env->token.len = 1;
2471da2e3ebdSchin if (c > env->parno || !env->paren[c])
2472da2e3ebdSchin {
2473da2e3ebdSchin env->error = REG_ESUBREG;
2474da2e3ebdSchin return 0;
2475da2e3ebdSchin }
2476da2e3ebdSchin env->paren[c]->re.group.back = 1;
2477da2e3ebdSchin return rep(env, node(env, REX_BACK, c, 0, 0), 0, 0);
2478da2e3ebdSchin }
2479da2e3ebdSchin /*FALLTHROUGH*/
2480da2e3ebdSchin default:
2481da2e3ebdSchin env->error = REG_BADRPT;
2482da2e3ebdSchin return 0;
2483da2e3ebdSchin }
2484da2e3ebdSchin if (x && !(e = alt(env, parno, 0)))
2485da2e3ebdSchin return 0;
2486da2e3ebdSchin c = token(env);
2487da2e3ebdSchin env->parnest--;
24887c2fbfb3SApril Chin if (c != T_CLOSE && (!(env->flags & REG_LITERAL) || c != ')'))
2489da2e3ebdSchin {
2490da2e3ebdSchin env->error = REG_EPAREN;
2491da2e3ebdSchin return 0;
2492da2e3ebdSchin }
2493da2e3ebdSchin eat(env);
2494da2e3ebdSchin if (typ >= 0)
2495da2e3ebdSchin {
2496da2e3ebdSchin if (beg)
2497da2e3ebdSchin env->pattern = env->cursor;
2498da2e3ebdSchin env->type = typ;
2499da2e3ebdSchin }
2500da2e3ebdSchin if (!x)
2501da2e3ebdSchin return 0;
2502da2e3ebdSchin if (!(f = node(env, x, 0, 0, 0)))
2503da2e3ebdSchin {
2504da2e3ebdSchin drop(env->disc, e);
2505da2e3ebdSchin return 0;
2506da2e3ebdSchin }
2507da2e3ebdSchin f->re.group.expr.rex = e;
2508da2e3ebdSchin if (x == REX_GROUP_BEHIND || x == REX_GROUP_BEHIND_NOT)
2509da2e3ebdSchin {
2510da2e3ebdSchin if (stats(env, e))
2511da2e3ebdSchin {
2512da2e3ebdSchin drop(env->disc, f);
2513da2e3ebdSchin if (!env->error)
2514da2e3ebdSchin env->error = REG_ECOUNT;
2515da2e3ebdSchin return 0;
2516da2e3ebdSchin }
2517da2e3ebdSchin f->re.group.size = env->stats.m;
2518da2e3ebdSchin memset(&env->stats, 0, sizeof(env->stats));
2519da2e3ebdSchin }
2520da2e3ebdSchin switch (x)
2521da2e3ebdSchin {
2522da2e3ebdSchin case REX_GROUP:
2523da2e3ebdSchin case REX_GROUP_CUT:
2524da2e3ebdSchin f = rep(env, f, parno, env->parno);
2525da2e3ebdSchin break;
2526da2e3ebdSchin }
2527da2e3ebdSchin return f;
2528da2e3ebdSchin }
2529da2e3ebdSchin
2530da2e3ebdSchin static Rex_t*
seq(Cenv_t * env)2531da2e3ebdSchin seq(Cenv_t* env)
2532da2e3ebdSchin {
2533da2e3ebdSchin Rex_t* e;
2534da2e3ebdSchin Rex_t* f;
2535da2e3ebdSchin Token_t tok;
2536da2e3ebdSchin int c;
2537da2e3ebdSchin int i;
2538da2e3ebdSchin int n;
2539da2e3ebdSchin int x;
2540da2e3ebdSchin int parno;
2541da2e3ebdSchin int type;
2542da2e3ebdSchin regflags_t flags;
2543da2e3ebdSchin unsigned char* s;
2544da2e3ebdSchin unsigned char* p;
2545da2e3ebdSchin unsigned char* t;
2546da2e3ebdSchin unsigned char* u;
2547da2e3ebdSchin unsigned char buf[256];
2548da2e3ebdSchin
2549da2e3ebdSchin for (;;)
2550da2e3ebdSchin {
2551da2e3ebdSchin s = buf;
2552da2e3ebdSchin while ((c = token(env)) < T_META && s < &buf[sizeof(buf) - env->token.len])
2553da2e3ebdSchin {
2554da2e3ebdSchin x = c;
2555da2e3ebdSchin p = env->cursor;
2556da2e3ebdSchin if (c >= 0)
2557da2e3ebdSchin {
2558da2e3ebdSchin n = 1;
2559da2e3ebdSchin *s++ = (env->flags & REG_ICASE) ? toupper(c) : c;
2560da2e3ebdSchin }
25617c2fbfb3SApril Chin else if (c == C_ESC || (env->flags & REG_ICASE))
2562da2e3ebdSchin {
25637c2fbfb3SApril Chin c = (c == C_ESC) ? env->token.lex : mbchar(p);
25647c2fbfb3SApril Chin if (env->flags & REG_ICASE)
25657c2fbfb3SApril Chin c = towupper(c);
25667c2fbfb3SApril Chin if ((&buf[sizeof(buf)] - s) < MB_CUR_MAX)
25677c2fbfb3SApril Chin break;
2568*3e14f97fSRoger A. Faulkner if ((n = mbconv((char*)s, c)) < 0)
25697c2fbfb3SApril Chin *s++ = c;
25707c2fbfb3SApril Chin else if (n)
25717c2fbfb3SApril Chin s += n;
25727c2fbfb3SApril Chin else
2573da2e3ebdSchin {
2574da2e3ebdSchin n = 1;
2575da2e3ebdSchin *s++ = 0;
2576da2e3ebdSchin }
2577da2e3ebdSchin }
2578da2e3ebdSchin else
2579da2e3ebdSchin {
2580da2e3ebdSchin n = env->token.len - env->token.esc;
2581da2e3ebdSchin for (t = p, u = s + n; s < u; *s++ = *t++);
2582da2e3ebdSchin }
2583da2e3ebdSchin eat(env);
2584da2e3ebdSchin }
2585da2e3ebdSchin if (c == T_BAD)
2586da2e3ebdSchin return 0;
2587da2e3ebdSchin if (s > buf)
2588da2e3ebdSchin switch (c)
2589da2e3ebdSchin {
2590da2e3ebdSchin case T_STAR:
2591da2e3ebdSchin case T_PLUS:
2592da2e3ebdSchin case T_LEFT:
2593da2e3ebdSchin case T_QUES:
2594da2e3ebdSchin case T_BANG:
2595da2e3ebdSchin if ((s -= n) == buf)
2596da2e3ebdSchin e = 0;
2597da2e3ebdSchin else
2598da2e3ebdSchin {
2599da2e3ebdSchin i = s - buf;
2600da2e3ebdSchin if (!(e = node(env, REX_STRING, 0, 0, i)))
2601da2e3ebdSchin return 0;
2602da2e3ebdSchin memcpy((char*)(e->re.string.base = (unsigned char*)e->re.data), (char*)buf, i);
2603da2e3ebdSchin e->re.string.size = i;
2604da2e3ebdSchin }
2605da2e3ebdSchin if (x >= 0)
2606da2e3ebdSchin {
2607da2e3ebdSchin if (!(f = node(env, REX_ONECHAR, 1, 1, 0)))
2608da2e3ebdSchin {
2609da2e3ebdSchin drop(env->disc, e);
2610da2e3ebdSchin return 0;
2611da2e3ebdSchin }
2612da2e3ebdSchin f->re.onechar = (env->flags & REG_ICASE) ? toupper(x) : x;
2613da2e3ebdSchin }
2614da2e3ebdSchin else
2615da2e3ebdSchin {
26167c2fbfb3SApril Chin if (!(f = node(env, REX_STRING, 0, 0, n)))
2617da2e3ebdSchin return 0;
26187c2fbfb3SApril Chin memcpy((char*)(f->re.string.base = (unsigned char*)f->re.data), (char*)p, n);
26197c2fbfb3SApril Chin f->re.string.size = n;
2620da2e3ebdSchin }
2621da2e3ebdSchin if (!(f = rep(env, f, 0, 0)) || !(f = cat(env, f, seq(env))))
2622da2e3ebdSchin {
2623da2e3ebdSchin drop(env->disc, e);
2624da2e3ebdSchin return 0;
2625da2e3ebdSchin }
2626da2e3ebdSchin if (e)
2627da2e3ebdSchin f = cat(env, e, f);
2628da2e3ebdSchin return f;
2629da2e3ebdSchin default:
2630da2e3ebdSchin c = s - buf;
2631da2e3ebdSchin if (!(e = node(env, REX_STRING, 0, 0, c)))
2632da2e3ebdSchin return 0;
2633da2e3ebdSchin memcpy((char*)(e->re.string.base = (unsigned char*)e->re.data), (char*)buf, c);
2634da2e3ebdSchin e->re.string.size = c;
2635da2e3ebdSchin return cat(env, e, seq(env));
2636da2e3ebdSchin }
2637da2e3ebdSchin else if (c > T_BACK)
2638da2e3ebdSchin {
2639da2e3ebdSchin eat(env);
2640da2e3ebdSchin c -= T_BACK;
2641da2e3ebdSchin if (c > env->parno || !env->paren[c])
2642da2e3ebdSchin {
2643da2e3ebdSchin env->error = REG_ESUBREG;
2644da2e3ebdSchin return 0;
2645da2e3ebdSchin }
2646da2e3ebdSchin env->paren[c]->re.group.back = 1;
2647da2e3ebdSchin e = rep(env, node(env, REX_BACK, c, 0, 0), 0, 0);
2648da2e3ebdSchin }
2649da2e3ebdSchin else
2650da2e3ebdSchin switch (c)
2651da2e3ebdSchin {
2652da2e3ebdSchin case T_AND:
2653da2e3ebdSchin case T_CLOSE:
2654da2e3ebdSchin case T_BAR:
2655da2e3ebdSchin case T_END:
2656da2e3ebdSchin return node(env, REX_NULL, 0, 0, 0);
2657da2e3ebdSchin case T_DOLL:
2658da2e3ebdSchin eat(env);
2659da2e3ebdSchin e = rep(env, node(env, REX_END, 0, 0, 0), 0, 0);
2660da2e3ebdSchin break;
2661da2e3ebdSchin case T_CFLX:
2662da2e3ebdSchin eat(env);
2663da2e3ebdSchin if ((e = node(env, REX_BEG, 0, 0, 0)) && (env->flags & REG_EXTENDED))
2664da2e3ebdSchin e = rep(env, e, 0, 0);
2665da2e3ebdSchin break;
2666da2e3ebdSchin case T_OPEN:
2667da2e3ebdSchin tok = env->token;
2668da2e3ebdSchin eat(env);
2669da2e3ebdSchin flags = env->flags;
2670da2e3ebdSchin type = env->type;
2671da2e3ebdSchin if (env->token.att)
2672da2e3ebdSchin env->flags |= REG_MINIMAL;
2673da2e3ebdSchin env->parnest++;
2674da2e3ebdSchin if (env->type == KRE)
2675da2e3ebdSchin ++env->parno;
2676da2e3ebdSchin parno = ++env->parno;
2677da2e3ebdSchin if (!(e = alt(env, parno + 1, 0)))
2678da2e3ebdSchin break;
2679da2e3ebdSchin if (e->type == REX_NULL && env->type == ERE && !(env->flags & REG_NULL))
2680da2e3ebdSchin {
2681da2e3ebdSchin drop(env->disc, e);
2682da2e3ebdSchin env->error = (*env->cursor == 0 || *env->cursor == env->delimiter || *env->cursor == env->terminator) ? REG_EPAREN : REG_ENULL;
2683da2e3ebdSchin return 0;
2684da2e3ebdSchin }
2685da2e3ebdSchin if (token(env) != T_CLOSE)
2686da2e3ebdSchin {
2687da2e3ebdSchin drop(env->disc, e);
2688da2e3ebdSchin env->error = REG_EPAREN;
2689da2e3ebdSchin return 0;
2690da2e3ebdSchin }
2691da2e3ebdSchin env->parnest--;
2692da2e3ebdSchin eat(env);
2693da2e3ebdSchin if (!(f = node(env, REX_GROUP, 0, 0, 0)))
2694da2e3ebdSchin {
2695da2e3ebdSchin drop(env->disc, e);
2696da2e3ebdSchin return 0;
2697da2e3ebdSchin }
2698da2e3ebdSchin if (parno < elementsof(env->paren))
2699da2e3ebdSchin env->paren[parno] = f;
2700da2e3ebdSchin f->re.group.back = 0;
2701da2e3ebdSchin f->re.group.number = parno;
2702da2e3ebdSchin f->re.group.expr.rex = e;
2703da2e3ebdSchin if (tok.lex)
2704da2e3ebdSchin {
2705da2e3ebdSchin tok.push = 1;
2706da2e3ebdSchin env->token = tok;
2707da2e3ebdSchin }
2708da2e3ebdSchin if (!(e = rep(env, f, parno, env->parno)))
2709da2e3ebdSchin return 0;
2710da2e3ebdSchin if (env->type == KRE)
2711da2e3ebdSchin {
2712da2e3ebdSchin if (!(f = node(env, REX_GROUP, 0, 0, 0)))
2713da2e3ebdSchin {
2714da2e3ebdSchin drop(env->disc, e);
2715da2e3ebdSchin return 0;
2716da2e3ebdSchin }
2717da2e3ebdSchin if (--parno < elementsof(env->paren))
2718da2e3ebdSchin env->paren[parno] = f;
2719da2e3ebdSchin f->re.group.back = 0;
2720da2e3ebdSchin f->re.group.number = parno;
2721da2e3ebdSchin f->re.group.expr.rex = e;
2722da2e3ebdSchin e = f;
2723da2e3ebdSchin }
2724da2e3ebdSchin env->flags = flags;
2725da2e3ebdSchin env->type = type;
2726da2e3ebdSchin break;
2727da2e3ebdSchin case T_GROUP:
2728da2e3ebdSchin p = env->cursor;
2729da2e3ebdSchin eat(env);
2730da2e3ebdSchin flags = env->flags;
2731da2e3ebdSchin type = env->type;
2732da2e3ebdSchin if (!(e = grp(env, env->parno + 1)))
2733da2e3ebdSchin {
2734da2e3ebdSchin if (env->error)
2735da2e3ebdSchin return 0;
2736da2e3ebdSchin if (env->literal == env->pattern && env->literal == p)
2737da2e3ebdSchin env->literal = env->cursor;
2738da2e3ebdSchin continue;
2739da2e3ebdSchin }
2740da2e3ebdSchin env->flags = flags;
2741da2e3ebdSchin env->type = type;
2742da2e3ebdSchin break;
2743da2e3ebdSchin case T_BRA:
2744da2e3ebdSchin eat(env);
2745da2e3ebdSchin if (e = bra(env))
2746da2e3ebdSchin e = rep(env, e, 0, 0);
2747da2e3ebdSchin break;
2748da2e3ebdSchin case T_ALNUM:
2749da2e3ebdSchin case T_ALNUM_NOT:
2750da2e3ebdSchin case T_DIGIT:
2751da2e3ebdSchin case T_DIGIT_NOT:
2752da2e3ebdSchin case T_SPACE:
2753da2e3ebdSchin case T_SPACE_NOT:
2754da2e3ebdSchin eat(env);
2755da2e3ebdSchin if (e = ccl(env, c))
2756da2e3ebdSchin e = rep(env, e, 0, 0);
2757da2e3ebdSchin break;
2758da2e3ebdSchin case T_LT:
2759da2e3ebdSchin eat(env);
2760da2e3ebdSchin e = rep(env, node(env, REX_WBEG, 0, 0, 0), 0, 0);
2761da2e3ebdSchin break;
2762da2e3ebdSchin case T_GT:
2763da2e3ebdSchin eat(env);
2764da2e3ebdSchin e = rep(env, node(env, REX_WEND, 0, 0, 0), 0, 0);
2765da2e3ebdSchin break;
2766da2e3ebdSchin case T_DOT:
2767da2e3ebdSchin eat(env);
2768da2e3ebdSchin e = rep(env, node(env, REX_DOT, 1, 1, 0), 0, 0);
2769da2e3ebdSchin break;
2770da2e3ebdSchin case T_DOTSTAR:
2771da2e3ebdSchin eat(env);
2772da2e3ebdSchin env->token.lex = T_STAR;
2773da2e3ebdSchin env->token.push = 1;
2774da2e3ebdSchin e = rep(env, node(env, REX_DOT, 1, 1, 0), 0, 0);
2775da2e3ebdSchin break;
2776da2e3ebdSchin case T_SLASHPLUS:
2777da2e3ebdSchin eat(env);
2778da2e3ebdSchin env->token.lex = T_PLUS;
2779da2e3ebdSchin env->token.push = 1;
2780da2e3ebdSchin if (e = node(env, REX_ONECHAR, 1, 1, 0))
2781da2e3ebdSchin {
2782da2e3ebdSchin e->re.onechar = '/';
2783da2e3ebdSchin e = rep(env, e, 0, 0);
2784da2e3ebdSchin }
2785da2e3ebdSchin break;
2786da2e3ebdSchin case T_WORD:
2787da2e3ebdSchin eat(env);
2788da2e3ebdSchin e = rep(env, node(env, REX_WORD, 0, 0, 0), 0, 0);
2789da2e3ebdSchin break;
2790da2e3ebdSchin case T_WORD_NOT:
2791da2e3ebdSchin eat(env);
2792da2e3ebdSchin e = rep(env, node(env, REX_WORD_NOT, 0, 0, 0), 0, 0);
2793da2e3ebdSchin break;
2794da2e3ebdSchin case T_BEG_STR:
2795da2e3ebdSchin eat(env);
2796da2e3ebdSchin e = rep(env, node(env, REX_BEG_STR, 0, 0, 0), 0, 0);
2797da2e3ebdSchin break;
2798da2e3ebdSchin case T_END_STR:
2799da2e3ebdSchin eat(env);
2800da2e3ebdSchin e = rep(env, node(env, REX_END_STR, 0, 0, 0), 0, 0);
2801da2e3ebdSchin break;
2802da2e3ebdSchin case T_FIN_STR:
2803da2e3ebdSchin eat(env);
2804da2e3ebdSchin e = rep(env, node(env, REX_FIN_STR, 0, 0, 0), 0, 0);
2805da2e3ebdSchin break;
2806da2e3ebdSchin default:
2807da2e3ebdSchin env->error = REG_BADRPT;
2808da2e3ebdSchin return 0;
2809da2e3ebdSchin }
2810da2e3ebdSchin if (e && *env->cursor != 0 && *env->cursor != env->delimiter && *env->cursor != env->terminator)
2811da2e3ebdSchin e = cat(env, e, seq(env));
2812da2e3ebdSchin return e;
2813da2e3ebdSchin }
2814da2e3ebdSchin }
2815da2e3ebdSchin
2816da2e3ebdSchin static Rex_t*
con(Cenv_t * env)2817da2e3ebdSchin con(Cenv_t* env)
2818da2e3ebdSchin {
2819da2e3ebdSchin Rex_t* e;
2820da2e3ebdSchin Rex_t* f;
2821da2e3ebdSchin Rex_t* g;
2822da2e3ebdSchin
2823da2e3ebdSchin if (!(e = seq(env)) || !(env->flags & REG_AUGMENTED) || token(env) != T_AND)
2824da2e3ebdSchin return e;
2825da2e3ebdSchin eat(env);
2826da2e3ebdSchin if (!(f = con(env)))
2827da2e3ebdSchin {
2828da2e3ebdSchin drop(env->disc, e);
2829da2e3ebdSchin return 0;
2830da2e3ebdSchin }
2831da2e3ebdSchin if (!(g = node(env, REX_CONJ, 0, 0, 0)))
2832da2e3ebdSchin {
2833da2e3ebdSchin drop(env->disc, e);
2834da2e3ebdSchin drop(env->disc, f);
2835da2e3ebdSchin return 0;
2836da2e3ebdSchin }
2837da2e3ebdSchin g->re.group.expr.binary.left = e;
2838da2e3ebdSchin g->re.group.expr.binary.right = f;
2839da2e3ebdSchin return g;
2840da2e3ebdSchin }
2841da2e3ebdSchin
2842da2e3ebdSchin static Rex_t*
alt(Cenv_t * env,int number,int cond)2843da2e3ebdSchin alt(Cenv_t* env, int number, int cond)
2844da2e3ebdSchin {
2845da2e3ebdSchin Rex_t* e;
2846da2e3ebdSchin Rex_t* f;
2847da2e3ebdSchin Rex_t* g;
2848da2e3ebdSchin
2849da2e3ebdSchin if (!(e = con(env)))
2850da2e3ebdSchin return 0;
2851da2e3ebdSchin else if (token(env) != T_BAR)
2852da2e3ebdSchin {
2853da2e3ebdSchin if (!cond)
2854da2e3ebdSchin return e;
2855da2e3ebdSchin f = 0;
2856da2e3ebdSchin if (e->type == REX_NULL)
2857da2e3ebdSchin goto bad;
2858da2e3ebdSchin }
2859da2e3ebdSchin else
2860da2e3ebdSchin {
2861da2e3ebdSchin eat(env);
2862da2e3ebdSchin if (!(f = alt(env, number, 0)))
2863da2e3ebdSchin {
2864da2e3ebdSchin drop(env->disc, e);
2865da2e3ebdSchin return 0;
2866da2e3ebdSchin }
2867da2e3ebdSchin if ((e->type == REX_NULL || f->type == REX_NULL) && !(env->flags & REG_NULL))
2868da2e3ebdSchin goto bad;
2869da2e3ebdSchin if (!cond && (g = trie(env, e, f)))
2870da2e3ebdSchin return g;
2871da2e3ebdSchin }
2872da2e3ebdSchin if (!(g = node(env, REX_ALT, 0, 0, 0)))
2873da2e3ebdSchin {
2874da2e3ebdSchin env->error = REG_ESPACE;
2875da2e3ebdSchin goto bad;
2876da2e3ebdSchin }
2877da2e3ebdSchin g->re.group.number = number;
2878da2e3ebdSchin g->re.group.last = env->parno;
2879da2e3ebdSchin g->re.group.expr.binary.left = e;
2880da2e3ebdSchin g->re.group.expr.binary.right = f;
2881da2e3ebdSchin return g;
2882da2e3ebdSchin bad:
2883da2e3ebdSchin drop(env->disc, e);
2884da2e3ebdSchin drop(env->disc, f);
2885da2e3ebdSchin if (!env->error)
2886da2e3ebdSchin env->error = REG_ENULL;
2887da2e3ebdSchin return 0;
2888da2e3ebdSchin }
2889da2e3ebdSchin
2890da2e3ebdSchin /*
2891da2e3ebdSchin * add v to REX_BM tables
2892da2e3ebdSchin */
2893da2e3ebdSchin
2894da2e3ebdSchin static void
bmstr(Cenv_t * env,register Rex_t * a,unsigned char * v,int n,Bm_mask_t b)2895da2e3ebdSchin bmstr(Cenv_t* env, register Rex_t* a, unsigned char* v, int n, Bm_mask_t b)
2896da2e3ebdSchin {
2897da2e3ebdSchin int c;
2898da2e3ebdSchin int m;
2899da2e3ebdSchin size_t z;
2900da2e3ebdSchin
2901da2e3ebdSchin for (m = 0; m < n; m++)
2902da2e3ebdSchin {
2903da2e3ebdSchin if (!(z = n - m - 1))
2904da2e3ebdSchin z = HIT;
2905da2e3ebdSchin c = v[m];
2906da2e3ebdSchin a->re.bm.mask[m][c] |= b;
2907da2e3ebdSchin if (z == HIT || !a->re.bm.skip[c] || a->re.bm.skip[c] > z && a->re.bm.skip[c] < HIT)
2908da2e3ebdSchin a->re.bm.skip[c] = z;
2909da2e3ebdSchin if (a->flags & REG_ICASE)
2910da2e3ebdSchin {
2911da2e3ebdSchin if (isupper(c))
2912da2e3ebdSchin c = tolower(c);
2913da2e3ebdSchin else if (islower(c))
2914da2e3ebdSchin c = toupper(c);
2915da2e3ebdSchin else
2916da2e3ebdSchin continue;
2917da2e3ebdSchin a->re.bm.mask[m][c] |= b;
2918da2e3ebdSchin if (z == HIT || !a->re.bm.skip[c] || a->re.bm.skip[c] > z && a->re.bm.skip[c] < HIT)
2919da2e3ebdSchin a->re.bm.skip[c] = z;
2920da2e3ebdSchin }
2921da2e3ebdSchin }
2922da2e3ebdSchin }
2923da2e3ebdSchin
2924da2e3ebdSchin /*
2925da2e3ebdSchin * set up BM table from trie
2926da2e3ebdSchin */
2927da2e3ebdSchin
2928da2e3ebdSchin static int
bmtrie(Cenv_t * env,Rex_t * a,unsigned char * v,Trie_node_t * x,int n,int m,Bm_mask_t b)2929da2e3ebdSchin bmtrie(Cenv_t* env, Rex_t* a, unsigned char* v, Trie_node_t* x, int n, int m, Bm_mask_t b)
2930da2e3ebdSchin {
2931da2e3ebdSchin do
2932da2e3ebdSchin {
2933da2e3ebdSchin v[m] = x->c;
2934da2e3ebdSchin if (m >= (n - 1))
2935da2e3ebdSchin {
2936da2e3ebdSchin bmstr(env, a, v, n, b);
2937da2e3ebdSchin if (!(b <<= 1))
2938da2e3ebdSchin {
2939da2e3ebdSchin b = 1;
2940da2e3ebdSchin a->re.bm.complete = 0;
2941da2e3ebdSchin }
2942da2e3ebdSchin else if (x->son)
2943da2e3ebdSchin a->re.bm.complete = 0;
2944da2e3ebdSchin }
2945da2e3ebdSchin else if (x->son)
2946da2e3ebdSchin b = bmtrie(env, a, v, x->son, n, m + 1, b);
2947da2e3ebdSchin } while (x = x->sib);
2948da2e3ebdSchin return b;
2949da2e3ebdSchin }
2950da2e3ebdSchin
2951da2e3ebdSchin /*
2952da2e3ebdSchin * rewrite the expression tree for some special cases
2953da2e3ebdSchin * 1. it is a null expression - illegal
2954da2e3ebdSchin * 2. max length fixed string found -- use BM algorithm
2955da2e3ebdSchin * 3. it begins with an unanchored string - use KMP algorithm
2956da2e3ebdSchin * 0 returned on success
2957da2e3ebdSchin */
2958da2e3ebdSchin
2959da2e3ebdSchin static int
special(Cenv_t * env,regex_t * p)2960da2e3ebdSchin special(Cenv_t* env, regex_t* p)
2961da2e3ebdSchin {
2962da2e3ebdSchin Rex_t* a;
2963da2e3ebdSchin Rex_t* e;
2964da2e3ebdSchin Rex_t* t;
2965da2e3ebdSchin Rex_t* x;
2966da2e3ebdSchin Rex_t* y;
2967da2e3ebdSchin unsigned char* s;
2968da2e3ebdSchin int* f;
2969da2e3ebdSchin int n;
2970da2e3ebdSchin int m;
2971da2e3ebdSchin int k;
2972da2e3ebdSchin
2973da2e3ebdSchin DEBUG_INIT();
2974da2e3ebdSchin if (e = p->env->rex)
2975da2e3ebdSchin {
2976da2e3ebdSchin if ((x = env->stats.x) && x->re.string.size < 3)
2977da2e3ebdSchin x = 0;
2978da2e3ebdSchin if ((t = env->stats.y) && t->re.trie.min < 3)
2979da2e3ebdSchin t = 0;
2980da2e3ebdSchin if (x && t)
2981da2e3ebdSchin {
2982da2e3ebdSchin if (x->re.string.size >= t->re.trie.min)
2983da2e3ebdSchin t = 0;
2984da2e3ebdSchin else
2985da2e3ebdSchin x = 0;
2986da2e3ebdSchin }
29877c2fbfb3SApril Chin if (x || t)
2988da2e3ebdSchin {
2989da2e3ebdSchin Bm_mask_t** mask;
2990da2e3ebdSchin Bm_mask_t* h;
2991da2e3ebdSchin unsigned char* v;
2992da2e3ebdSchin size_t* q;
2993da2e3ebdSchin unsigned long l;
2994da2e3ebdSchin int i;
2995da2e3ebdSchin int j;
2996da2e3ebdSchin
2997da2e3ebdSchin if (x)
2998da2e3ebdSchin {
2999da2e3ebdSchin y = x;
3000da2e3ebdSchin n = m = x->re.string.size;
3001da2e3ebdSchin l = env->stats.l;
3002da2e3ebdSchin }
3003da2e3ebdSchin else
3004da2e3ebdSchin {
3005da2e3ebdSchin y = t;
3006da2e3ebdSchin n = t->re.trie.min;
3007da2e3ebdSchin m = t->re.trie.max;
3008da2e3ebdSchin l = env->stats.k;
3009da2e3ebdSchin }
3010da2e3ebdSchin if (!(q = (size_t*)alloc(env->disc, 0, (n + 1) * sizeof(size_t))))
3011da2e3ebdSchin return 1;
3012da2e3ebdSchin if (!(a = node(env, REX_BM, 0, 0, n * (sizeof(Bm_mask_t*) + (UCHAR_MAX + 1) * sizeof(Bm_mask_t)) + (UCHAR_MAX + n + 2) * sizeof(size_t))))
3013da2e3ebdSchin {
3014da2e3ebdSchin alloc(env->disc, q, 0);
3015da2e3ebdSchin return 1;
3016da2e3ebdSchin }
3017da2e3ebdSchin a->flags = y->flags;
3018da2e3ebdSchin a->map = y->map;
3019da2e3ebdSchin a->re.bm.size = n;
3020da2e3ebdSchin a->re.bm.back = (y == e || y == e->re.group.expr.rex) ? (m - n) : -1;
3021da2e3ebdSchin a->re.bm.left = l - 1;
3022da2e3ebdSchin a->re.bm.right = env->stats.m - l - n;
3023*3e14f97fSRoger A. Faulkner a->re.bm.complete = (env->stats.e || y != e && (e->type != REX_GROUP || y != e->re.group.expr.rex) || e->next || ((a->re.bm.left + a->re.bm.right) >= 0)) ? 0 : n;
3024da2e3ebdSchin h = (Bm_mask_t*)&a->re.bm.mask[n];
3025da2e3ebdSchin a->re.bm.skip = (size_t*)(h + n * (UCHAR_MAX + 1));
3026da2e3ebdSchin a->re.bm.fail = &a->re.bm.skip[UCHAR_MAX + 1];
3027da2e3ebdSchin for (m = 0; m <= UCHAR_MAX; m++)
3028da2e3ebdSchin a->re.bm.skip[m] = n;
3029da2e3ebdSchin a->re.bm.skip[0] = a->re.bm.skip[env->mappednewline] = (y->next && y->next->type == REX_END) ? HIT : (n + a->re.bm.left);
3030da2e3ebdSchin for (i = 1; i <= n; i++)
3031da2e3ebdSchin a->re.bm.fail[i] = 2 * n - i;
3032da2e3ebdSchin mask = a->re.bm.mask;
3033da2e3ebdSchin for (m = 0; m < n; m++)
3034da2e3ebdSchin {
3035da2e3ebdSchin mask[m] = h;
3036da2e3ebdSchin h += UCHAR_MAX + 1;
3037da2e3ebdSchin }
3038da2e3ebdSchin if (x)
3039da2e3ebdSchin bmstr(env, a, x->re.string.base, n, 1);
3040da2e3ebdSchin else
3041da2e3ebdSchin {
3042da2e3ebdSchin v = (unsigned char*)q;
3043da2e3ebdSchin memset(v, 0, n);
3044da2e3ebdSchin m = 1;
3045da2e3ebdSchin for (i = 0; i <= UCHAR_MAX; i++)
3046da2e3ebdSchin if (t->re.trie.root[i])
3047da2e3ebdSchin m = bmtrie(env, a, v, t->re.trie.root[i], n, 0, m);
3048da2e3ebdSchin }
3049da2e3ebdSchin mask--;
3050da2e3ebdSchin memset(q, 0, n * sizeof(*q));
3051da2e3ebdSchin for (k = (j = n) + 1; j > 0; j--, k--)
3052da2e3ebdSchin {
3053da2e3ebdSchin DEBUG_TEST(0x0010,(sfprintf(sfstderr, "BM#0: k=%d j=%d\n", k, j)),(0));
3054da2e3ebdSchin for (q[j] = k; k <= n; k = q[k])
3055da2e3ebdSchin {
3056da2e3ebdSchin for (m = 0; m <= UCHAR_MAX; m++)
3057da2e3ebdSchin if (mask[k][m] == mask[j][m])
3058da2e3ebdSchin {
3059da2e3ebdSchin DEBUG_TEST(0x0010,sfprintf(sfstderr, "CUT1: mask[%d][%c]=mask[%d][%c]\n", k, m, j, m), (0));
3060da2e3ebdSchin goto cut;
3061da2e3ebdSchin }
3062da2e3ebdSchin DEBUG_TEST(0x0010,sfprintf(sfstderr, "BM#2: fail[%d]=%d => %d\n", k, a->re.bm.fail[k], (a->re.bm.fail[k] > n - j) ? (n - j) : a->re.bm.fail[k]), (0));
3063da2e3ebdSchin if (a->re.bm.fail[k] > n - j)
3064da2e3ebdSchin a->re.bm.fail[k] = n - j;
3065da2e3ebdSchin }
3066da2e3ebdSchin cut: ;
3067da2e3ebdSchin }
3068da2e3ebdSchin for (i = 1; i <= n; i++)
3069da2e3ebdSchin if (a->re.bm.fail[i] > n + k - i)
3070da2e3ebdSchin {
3071da2e3ebdSchin DEBUG_TEST(0x0010,sfprintf(sfstderr, "BM#4: fail[%d]=%d => %d\n", i, a->re.bm.fail[i], n + k - i), (0));
3072da2e3ebdSchin a->re.bm.fail[i] = n + k - i;
3073da2e3ebdSchin }
3074da2e3ebdSchin #if _AST_REGEX_DEBUG
3075da2e3ebdSchin if (DEBUG_TEST(0x0020,(1),(0)))
3076da2e3ebdSchin {
3077da2e3ebdSchin sfprintf(sfstderr, "STAT: complete=%d n=%d k=%d l=%d r=%d y=%d:%d e=%d:%d\n", a->re.bm.complete, n, k, a->re.bm.left, a->re.bm.right, y->type, y->next ? y->next->type : 0, e->type, e->next ? e->next->type : 0);
3078da2e3ebdSchin for (m = 0; m < n; m++)
3079da2e3ebdSchin for (i = 1; i <= UCHAR_MAX; i++)
3080da2e3ebdSchin if (a->re.bm.mask[m][i])
3081da2e3ebdSchin sfprintf(sfstderr, "MASK: [%d]['%c'] = %032..2u\n", m, i, a->re.bm.mask[m][i]);
3082da2e3ebdSchin for (i = ' '; i <= UCHAR_MAX; i++)
3083da2e3ebdSchin if (a->re.bm.skip[i] >= HIT)
3084da2e3ebdSchin sfprintf(sfstderr, "SKIP: ['%c'] = *\n", i);
3085da2e3ebdSchin else if (a->re.bm.skip[i] > 0 && a->re.bm.skip[i] < n)
3086da2e3ebdSchin sfprintf(sfstderr, "SKIP: ['%c'] = %3d\n", i, a->re.bm.skip[i]);
3087da2e3ebdSchin for (j = 31; j >= 0; j--)
3088da2e3ebdSchin {
3089da2e3ebdSchin sfprintf(sfstderr, " ");
3090da2e3ebdSchin next:
3091da2e3ebdSchin for (m = 0; m < n; m++)
3092da2e3ebdSchin {
3093da2e3ebdSchin for (i = 0040; i < 0177; i++)
3094da2e3ebdSchin if (a->re.bm.mask[m][i] & (1 << j))
3095da2e3ebdSchin {
3096da2e3ebdSchin sfprintf(sfstderr, " %c", i);
3097da2e3ebdSchin break;
3098da2e3ebdSchin }
3099da2e3ebdSchin if (i >= 0177)
3100da2e3ebdSchin {
3101da2e3ebdSchin if (j > 0)
3102da2e3ebdSchin {
3103da2e3ebdSchin j--;
3104da2e3ebdSchin goto next;
3105da2e3ebdSchin }
3106da2e3ebdSchin sfprintf(sfstderr, " ?");
3107da2e3ebdSchin }
3108da2e3ebdSchin }
3109da2e3ebdSchin sfprintf(sfstderr, "\n");
3110da2e3ebdSchin }
3111da2e3ebdSchin sfprintf(sfstderr, "FAIL: ");
3112da2e3ebdSchin for (m = 1; m <= n; m++)
3113da2e3ebdSchin sfprintf(sfstderr, "%3d", a->re.bm.fail[m]);
3114da2e3ebdSchin sfprintf(sfstderr, "\n");
3115da2e3ebdSchin }
3116da2e3ebdSchin #endif
3117da2e3ebdSchin alloc(env->disc, q, 0);
3118da2e3ebdSchin a->next = e;
3119da2e3ebdSchin p->env->rex = a;
3120da2e3ebdSchin return 0;
3121da2e3ebdSchin }
3122da2e3ebdSchin switch (e->type)
3123da2e3ebdSchin {
3124da2e3ebdSchin case REX_BEG:
3125da2e3ebdSchin if (env->flags & REG_NEWLINE)
3126da2e3ebdSchin return 0;
3127da2e3ebdSchin break;
3128da2e3ebdSchin case REX_GROUP:
3129da2e3ebdSchin if (env->stats.b)
3130da2e3ebdSchin return 0;
3131da2e3ebdSchin e = e->re.group.expr.rex;
3132da2e3ebdSchin if (e->type != REX_DOT)
3133da2e3ebdSchin return 0;
3134da2e3ebdSchin /*FALLTHROUGH*/
3135da2e3ebdSchin case REX_DOT:
3136da2e3ebdSchin if (e->lo == 0 && e->hi == RE_DUP_INF)
3137da2e3ebdSchin break;
3138da2e3ebdSchin return 0;
3139da2e3ebdSchin case REX_NULL:
3140da2e3ebdSchin if (env->flags & REG_NULL)
3141da2e3ebdSchin break;
3142da2e3ebdSchin env->error = REG_ENULL;
3143da2e3ebdSchin return 1;
3144da2e3ebdSchin case REX_STRING:
31457c2fbfb3SApril Chin if ((env->flags & (REG_LEFT|REG_LITERAL|REG_RIGHT)) || e->map)
3146da2e3ebdSchin return 0;
3147da2e3ebdSchin s = e->re.string.base;
3148da2e3ebdSchin n = e->re.string.size;
3149da2e3ebdSchin if (!(a = node(env, REX_KMP, 0, 0, n * (sizeof(int*) + 1))))
3150da2e3ebdSchin return 1;
3151da2e3ebdSchin a->flags = e->flags;
3152da2e3ebdSchin a->map = e->map;
3153da2e3ebdSchin f = a->re.string.fail;
3154da2e3ebdSchin memcpy((char*)(a->re.string.base = (unsigned char*)&f[n]), (char*)s, n);
3155da2e3ebdSchin s = a->re.string.base;
3156da2e3ebdSchin a->re.string.size = n;
3157da2e3ebdSchin f[0] = m = -1;
3158da2e3ebdSchin for (k = 1; k < n; k++)
3159da2e3ebdSchin {
3160da2e3ebdSchin while (m >= 0 && s[m+1] != s[k])
3161da2e3ebdSchin m = f[m];
3162da2e3ebdSchin if (s[m+1] == s[k])
3163da2e3ebdSchin m++;
3164da2e3ebdSchin f[k] = m;
3165da2e3ebdSchin }
3166da2e3ebdSchin a->next = e->next;
3167da2e3ebdSchin p->env->rex = a;
3168da2e3ebdSchin e->next = 0;
3169da2e3ebdSchin drop(env->disc, e);
3170da2e3ebdSchin break;
3171da2e3ebdSchin default:
3172da2e3ebdSchin return 0;
3173da2e3ebdSchin }
3174da2e3ebdSchin }
3175da2e3ebdSchin p->env->once = 1;
3176da2e3ebdSchin return 0;
3177da2e3ebdSchin }
3178da2e3ebdSchin
3179da2e3ebdSchin int
regcomp(regex_t * p,const char * pattern,regflags_t flags)3180da2e3ebdSchin regcomp(regex_t* p, const char* pattern, regflags_t flags)
3181da2e3ebdSchin {
3182da2e3ebdSchin Rex_t* e;
3183da2e3ebdSchin Rex_t* f;
3184da2e3ebdSchin regdisc_t* disc;
3185da2e3ebdSchin unsigned char* fold;
3186da2e3ebdSchin int i;
3187da2e3ebdSchin Cenv_t env;
3188da2e3ebdSchin
3189da2e3ebdSchin if (!p)
3190da2e3ebdSchin return REG_BADPAT;
3191da2e3ebdSchin if (flags & REG_DISCIPLINE)
3192da2e3ebdSchin {
3193da2e3ebdSchin flags &= ~REG_DISCIPLINE;
3194da2e3ebdSchin disc = p->re_disc;
3195da2e3ebdSchin }
3196da2e3ebdSchin else
3197da2e3ebdSchin disc = &state.disc;
3198da2e3ebdSchin if (!disc->re_errorlevel)
3199da2e3ebdSchin disc->re_errorlevel = 2;
3200da2e3ebdSchin p->env = 0;
3201da2e3ebdSchin if (!pattern)
3202da2e3ebdSchin return fatal(disc, REG_BADPAT, pattern);
3203da2e3ebdSchin if (!state.initialized)
3204da2e3ebdSchin {
3205da2e3ebdSchin state.initialized = 1;
3206da2e3ebdSchin for (i = 0; i < elementsof(state.escape); i++)
3207da2e3ebdSchin state.magic[state.escape[i].key] = state.escape[i].val;
3208da2e3ebdSchin }
3209da2e3ebdSchin if (!(fold = (unsigned char*)LCINFO(AST_LC_CTYPE)->data))
3210da2e3ebdSchin {
3211da2e3ebdSchin if (!(fold = newof(0, unsigned char, UCHAR_MAX, 1)))
3212da2e3ebdSchin return fatal(disc, REG_ESPACE, pattern);
3213da2e3ebdSchin for (i = 0; i <= UCHAR_MAX; i++)
3214da2e3ebdSchin fold[i] = toupper(i);
3215da2e3ebdSchin LCINFO(AST_LC_CTYPE)->data = (void*)fold;
3216da2e3ebdSchin }
3217da2e3ebdSchin again:
3218da2e3ebdSchin if (!(p->env = (Env_t*)alloc(disc, 0, sizeof(Env_t))))
3219da2e3ebdSchin return fatal(disc, REG_ESPACE, pattern);
3220da2e3ebdSchin memset(p->env, 0, sizeof(*p->env));
3221da2e3ebdSchin memset(&env, 0, sizeof(env));
3222da2e3ebdSchin env.regex = p;
3223da2e3ebdSchin env.flags = flags;
3224da2e3ebdSchin env.disc = p->env->disc = disc;
3225da2e3ebdSchin if (env.flags & REG_AUGMENTED)
3226da2e3ebdSchin env.flags |= REG_EXTENDED;
3227da2e3ebdSchin env.mappeddot = '.';
3228da2e3ebdSchin env.mappednewline = '\n';
3229da2e3ebdSchin env.mappedslash = '/';
3230da2e3ebdSchin if (disc->re_version >= REG_VERSION_MAP && disc->re_map)
3231da2e3ebdSchin {
3232da2e3ebdSchin env.map = disc->re_map;
3233da2e3ebdSchin env.MAP = p->env->fold;
3234da2e3ebdSchin for (i = 0; i <= UCHAR_MAX; i++)
3235da2e3ebdSchin {
3236da2e3ebdSchin env.MAP[i] = fold[env.map[i]];
3237da2e3ebdSchin if (env.map[i] == '.')
3238da2e3ebdSchin env.mappeddot = i;
3239da2e3ebdSchin if (env.map[i] == '\n')
3240da2e3ebdSchin env.mappednewline = i;
3241da2e3ebdSchin if (env.map[i] == '/')
3242da2e3ebdSchin env.mappedslash = i;
3243da2e3ebdSchin }
3244da2e3ebdSchin }
3245da2e3ebdSchin else
3246da2e3ebdSchin env.MAP = fold;
3247da2e3ebdSchin env.type = (env.flags & REG_AUGMENTED) ? ARE : (env.flags & REG_EXTENDED) ? ERE : BRE;
3248da2e3ebdSchin env.explicit = -1;
3249da2e3ebdSchin if (env.flags & REG_SHELL)
3250da2e3ebdSchin {
3251da2e3ebdSchin if (env.flags & REG_SHELL_PATH)
3252da2e3ebdSchin env.explicit = env.mappedslash;
3253da2e3ebdSchin env.flags |= REG_LENIENT|REG_NULL;
3254da2e3ebdSchin env.type = env.type == BRE ? SRE : KRE;
3255da2e3ebdSchin }
3256da2e3ebdSchin if ((env.flags & (REG_NEWLINE|REG_SPAN)) == REG_NEWLINE)
3257da2e3ebdSchin env.explicit = env.mappednewline;
3258da2e3ebdSchin p->env->leading = (env.flags & REG_SHELL_DOT) ? env.mappeddot : -1;
3259da2e3ebdSchin env.posixkludge = !(env.flags & (REG_EXTENDED|REG_SHELL));
326034f9b3eeSRoland Mainz env.regexp = !!(env.flags & REG_REGEXP);
3261da2e3ebdSchin env.token.lex = 0;
3262da2e3ebdSchin env.token.push = 0;
3263da2e3ebdSchin if (env.flags & REG_DELIMITED)
3264da2e3ebdSchin {
3265da2e3ebdSchin switch (env.delimiter = *pattern++)
3266da2e3ebdSchin {
3267da2e3ebdSchin case 0:
3268da2e3ebdSchin case '\\':
3269da2e3ebdSchin case '\n':
3270da2e3ebdSchin case '\r':
3271da2e3ebdSchin env.error = REG_EDELIM;
3272da2e3ebdSchin goto bad;
3273da2e3ebdSchin }
3274da2e3ebdSchin env.terminator = '\n';
3275da2e3ebdSchin }
3276da2e3ebdSchin env.literal = env.pattern = env.cursor = (unsigned char*)pattern;
3277da2e3ebdSchin if (!(p->env->rex = alt(&env, 1, 0)))
3278da2e3ebdSchin goto bad;
3279da2e3ebdSchin if (env.parnest)
3280da2e3ebdSchin {
3281da2e3ebdSchin env.error = REG_EPAREN;
3282da2e3ebdSchin goto bad;
3283da2e3ebdSchin }
3284da2e3ebdSchin p->env->stats.re_flags = env.flags & (REG_EXTENDED|REG_AUGMENTED|REG_SHELL);
3285da2e3ebdSchin if (env.flags & REG_LEFT)
3286da2e3ebdSchin {
3287da2e3ebdSchin if (p->env->rex->type != REX_BEG)
3288da2e3ebdSchin {
3289da2e3ebdSchin if (p->env->rex->type == REX_ALT)
3290da2e3ebdSchin env.flags &= ~REG_FIRST;
3291da2e3ebdSchin if (!(e = node(&env, REX_BEG, 0, 0, 0)))
3292da2e3ebdSchin {
3293da2e3ebdSchin regfree(p);
3294da2e3ebdSchin return fatal(disc, REG_ESPACE, pattern);
3295da2e3ebdSchin }
3296da2e3ebdSchin e->next = p->env->rex;
3297da2e3ebdSchin p->env->rex = e;
3298da2e3ebdSchin p->env->once = 1;
3299da2e3ebdSchin }
3300da2e3ebdSchin p->env->stats.re_flags |= REG_LEFT;
3301da2e3ebdSchin }
3302da2e3ebdSchin for (e = p->env->rex; e->next; e = e->next);
3303da2e3ebdSchin p->env->done.type = REX_DONE;
3304da2e3ebdSchin p->env->done.flags = e->flags;
3305da2e3ebdSchin if (env.flags & REG_RIGHT)
3306da2e3ebdSchin {
3307da2e3ebdSchin if (e->type != REX_END)
3308da2e3ebdSchin {
3309da2e3ebdSchin if (p->env->rex->type == REX_ALT)
3310da2e3ebdSchin env.flags &= ~REG_FIRST;
3311da2e3ebdSchin if (!(f = node(&env, REX_END, 0, 0, 0)))
3312da2e3ebdSchin {
3313da2e3ebdSchin regfree(p);
3314da2e3ebdSchin return fatal(disc, REG_ESPACE, pattern);
3315da2e3ebdSchin }
3316da2e3ebdSchin f->flags = e->flags;
3317da2e3ebdSchin f->map = e->map;
3318da2e3ebdSchin e->next = f;
3319da2e3ebdSchin }
3320da2e3ebdSchin p->env->stats.re_flags |= REG_RIGHT;
3321da2e3ebdSchin }
3322da2e3ebdSchin if (stats(&env, p->env->rex))
3323da2e3ebdSchin {
3324da2e3ebdSchin if (!env.error)
3325da2e3ebdSchin env.error = REG_ECOUNT;
3326da2e3ebdSchin goto bad;
3327da2e3ebdSchin }
3328da2e3ebdSchin if (env.stats.b)
3329da2e3ebdSchin p->env->hard = p->env->separate = 1;
3330da2e3ebdSchin else if (!(env.flags & REG_FIRST) && (env.stats.a || env.stats.c > 1 && env.stats.c != env.stats.s || env.stats.t && (env.stats.t > 1 || env.stats.a || env.stats.c)))
3331da2e3ebdSchin p->env->hard = 1;
3332da2e3ebdSchin if (p->env->hard || env.stats.c || env.stats.i)
3333da2e3ebdSchin p->env->stats.re_min = p->env->stats.re_max = -1;
3334da2e3ebdSchin else
3335da2e3ebdSchin {
3336da2e3ebdSchin if (!(p->env->stats.re_min = env.stats.m))
3337da2e3ebdSchin p->env->stats.re_min = -1;
3338da2e3ebdSchin if (!(p->env->stats.re_max = env.stats.n))
3339da2e3ebdSchin p->env->stats.re_max = -1;
3340da2e3ebdSchin }
3341da2e3ebdSchin if (special(&env, p))
3342da2e3ebdSchin goto bad;
3343da2e3ebdSchin serialize(&env, p->env->rex, 1);
3344da2e3ebdSchin p->re_nsub = env.stats.p;
3345da2e3ebdSchin if (env.type == KRE)
3346da2e3ebdSchin p->re_nsub /= 2;
3347da2e3ebdSchin if (env.flags & REG_DELIMITED)
3348da2e3ebdSchin {
3349da2e3ebdSchin p->re_npat = env.cursor - env.pattern + 1;
3350da2e3ebdSchin if (*env.cursor == env.delimiter)
3351da2e3ebdSchin p->re_npat++;
3352da2e3ebdSchin else if (env.flags & REG_MUSTDELIM)
3353da2e3ebdSchin {
3354da2e3ebdSchin env.error = REG_EDELIM;
3355da2e3ebdSchin goto bad;
3356da2e3ebdSchin }
3357da2e3ebdSchin else
3358da2e3ebdSchin env.flags &= ~REG_DELIMITED;
3359da2e3ebdSchin }
3360da2e3ebdSchin p->env->explicit = env.explicit;
3361da2e3ebdSchin p->env->flags = env.flags & REG_COMP;
3362da2e3ebdSchin p->env->min = env.stats.m;
3363da2e3ebdSchin p->env->nsub = env.stats.p + env.stats.u;
3364da2e3ebdSchin p->env->refs = 1;
3365da2e3ebdSchin return 0;
3366da2e3ebdSchin bad:
3367da2e3ebdSchin regfree(p);
3368da2e3ebdSchin if (!env.error)
3369da2e3ebdSchin env.error = REG_ESPACE;
3370da2e3ebdSchin if (env.type >= SRE && env.error != REG_ESPACE && !(flags & REG_LITERAL))
3371da2e3ebdSchin {
3372da2e3ebdSchin flags |= REG_LITERAL;
3373da2e3ebdSchin pattern = (const char*)env.literal;
3374da2e3ebdSchin goto again;
3375da2e3ebdSchin }
3376da2e3ebdSchin return fatal(disc, env.error, pattern);
3377da2e3ebdSchin }
3378da2e3ebdSchin
3379da2e3ebdSchin /*
3380da2e3ebdSchin * regcomp() on sized pattern
3381da2e3ebdSchin * the lazy way around adding and checking env.end
3382da2e3ebdSchin */
3383da2e3ebdSchin
3384da2e3ebdSchin int
regncomp(regex_t * p,const char * pattern,size_t size,regflags_t flags)3385da2e3ebdSchin regncomp(regex_t* p, const char* pattern, size_t size, regflags_t flags)
3386da2e3ebdSchin {
3387da2e3ebdSchin char* s;
3388da2e3ebdSchin int r;
3389da2e3ebdSchin
3390da2e3ebdSchin if (!(s = malloc(size + 1)))
3391da2e3ebdSchin return fatal((flags & REG_DISCIPLINE) ? p->re_disc : &state.disc, REG_ESPACE, pattern);
3392da2e3ebdSchin memcpy(s, pattern, size);
3393da2e3ebdSchin s[size] = 0;
3394da2e3ebdSchin r = regcomp(p, s, flags);
3395da2e3ebdSchin free(s);
3396da2e3ebdSchin return r;
3397da2e3ebdSchin }
3398da2e3ebdSchin
3399da2e3ebdSchin /*
3400da2e3ebdSchin * combine two compiled regular expressions if possible,
3401da2e3ebdSchin * replacing first with the combination and freeing second.
3402da2e3ebdSchin * return 0 on success.
3403da2e3ebdSchin * the only combinations handled are building a Trie
3404da2e3ebdSchin * from String|Kmp|Trie and String|Kmp
3405da2e3ebdSchin */
3406da2e3ebdSchin
3407da2e3ebdSchin int
regcomb(regex_t * p,regex_t * q)3408da2e3ebdSchin regcomb(regex_t* p, regex_t* q)
3409da2e3ebdSchin {
3410da2e3ebdSchin Rex_t* e = p->env->rex;
3411da2e3ebdSchin Rex_t* f = q->env->rex;
3412da2e3ebdSchin Rex_t* g;
3413*3e14f97fSRoger A. Faulkner Rex_t* h;
3414da2e3ebdSchin Cenv_t env;
3415da2e3ebdSchin
3416da2e3ebdSchin if (!e || !f)
3417da2e3ebdSchin return fatal(p->env->disc, REG_BADPAT, NiL);
3418da2e3ebdSchin if (p->env->separate || q->env->separate)
3419da2e3ebdSchin return REG_ESUBREG;
3420da2e3ebdSchin memset(&env, 0, sizeof(env));
3421da2e3ebdSchin env.disc = p->env->disc;
3422da2e3ebdSchin if (e->type == REX_BM)
3423da2e3ebdSchin {
3424da2e3ebdSchin p->env->rex = e->next;
3425da2e3ebdSchin e->next = 0;
3426da2e3ebdSchin drop(env.disc, e);
3427da2e3ebdSchin e = p->env->rex;
3428da2e3ebdSchin }
3429da2e3ebdSchin if (f->type == REX_BM)
3430da2e3ebdSchin {
3431da2e3ebdSchin q->env->rex = f->next;
3432da2e3ebdSchin f->next = 0;
3433da2e3ebdSchin drop(env.disc, f);
3434da2e3ebdSchin f = q->env->rex;
3435da2e3ebdSchin }
3436da2e3ebdSchin if (e->type == REX_BEG && f->type == REX_BEG)
3437da2e3ebdSchin {
3438da2e3ebdSchin p->env->flags |= REG_LEFT;
3439da2e3ebdSchin p->env->rex = e->next;
3440da2e3ebdSchin e->next = 0;
3441da2e3ebdSchin drop(env.disc, e);
3442da2e3ebdSchin e = p->env->rex;
3443da2e3ebdSchin q->env->rex = f->next;
3444da2e3ebdSchin f->next = 0;
3445da2e3ebdSchin drop(env.disc, f);
3446da2e3ebdSchin f = q->env->rex;
3447da2e3ebdSchin }
3448*3e14f97fSRoger A. Faulkner for (g = e; g->next; g = g->next);
3449*3e14f97fSRoger A. Faulkner for (h = f; h->next; h = h->next);
3450*3e14f97fSRoger A. Faulkner if (g->next && g->next->type == REX_END && h->next && h->next->type == REX_END)
3451da2e3ebdSchin {
3452da2e3ebdSchin p->env->flags |= REG_RIGHT;
3453*3e14f97fSRoger A. Faulkner drop(env.disc, g->next);
3454*3e14f97fSRoger A. Faulkner g->next = 0;
3455*3e14f97fSRoger A. Faulkner drop(env.disc, h->next);
3456*3e14f97fSRoger A. Faulkner h->next = 0;
3457da2e3ebdSchin }
3458da2e3ebdSchin if (!(g = trie(&env, f, e)))
3459da2e3ebdSchin return fatal(p->env->disc, REG_BADPAT, NiL);
3460da2e3ebdSchin p->env->rex = g;
3461da2e3ebdSchin if (!q->env->once)
3462da2e3ebdSchin p->env->once = 0;
3463da2e3ebdSchin q->env->rex = 0;
3464da2e3ebdSchin if (p->env->flags & REG_LEFT)
3465da2e3ebdSchin {
3466da2e3ebdSchin if (!(e = node(&env, REX_BEG, 0, 0, 0)))
3467da2e3ebdSchin {
3468da2e3ebdSchin regfree(p);
3469da2e3ebdSchin return fatal(p->env->disc, REG_ESPACE, NiL);
3470da2e3ebdSchin }
3471da2e3ebdSchin e->next = p->env->rex;
3472da2e3ebdSchin p->env->rex = e;
3473da2e3ebdSchin p->env->once = 1;
3474da2e3ebdSchin }
3475da2e3ebdSchin if (p->env->flags & REG_RIGHT)
3476da2e3ebdSchin {
3477da2e3ebdSchin for (f = p->env->rex; f->next; f = f->next);
3478da2e3ebdSchin if (f->type != REX_END)
3479da2e3ebdSchin {
3480da2e3ebdSchin if (!(e = node(&env, REX_END, 0, 0, 0)))
3481da2e3ebdSchin {
3482da2e3ebdSchin regfree(p);
3483da2e3ebdSchin return fatal(p->env->disc, REG_ESPACE, NiL);
3484da2e3ebdSchin }
3485da2e3ebdSchin f->next = e;
3486da2e3ebdSchin }
3487da2e3ebdSchin }
3488da2e3ebdSchin env.explicit = p->env->explicit;
3489da2e3ebdSchin env.flags = p->env->flags;
3490da2e3ebdSchin env.disc = p->env->disc;
3491da2e3ebdSchin if (stats(&env, p->env->rex))
3492da2e3ebdSchin {
3493da2e3ebdSchin regfree(p);
3494da2e3ebdSchin return fatal(p->env->disc, env.error ? env.error : REG_ECOUNT, NiL);
3495da2e3ebdSchin }
3496da2e3ebdSchin if (special(&env, p))
3497da2e3ebdSchin {
3498da2e3ebdSchin regfree(p);
3499da2e3ebdSchin return fatal(p->env->disc, env.error ? env.error : REG_ESPACE, NiL);
3500da2e3ebdSchin }
3501da2e3ebdSchin p->env->min = g->re.trie.min;
3502da2e3ebdSchin return 0;
3503da2e3ebdSchin }
3504da2e3ebdSchin
3505da2e3ebdSchin /*
3506da2e3ebdSchin * copy a reference of p into q
3507da2e3ebdSchin * p and q may then have separate regsubcomp() instantiations
3508da2e3ebdSchin */
3509da2e3ebdSchin
3510da2e3ebdSchin int
regdup(regex_t * p,regex_t * q)3511da2e3ebdSchin regdup(regex_t* p, regex_t* q)
3512da2e3ebdSchin {
3513da2e3ebdSchin if (!p || !q)
3514da2e3ebdSchin return REG_BADPAT;
3515da2e3ebdSchin *q = *p;
3516da2e3ebdSchin p->env->refs++;
3517da2e3ebdSchin q->re_sub = 0;
3518da2e3ebdSchin return 0;
3519da2e3ebdSchin }
3520