~vcs-imports/mammoth-replicator/trunk

« back to all changes in this revision

Viewing changes to src/backend/regex/regcomp.c

  • Committer: alvherre
  • Date: 2005-12-16 21:24:52 UTC
  • Revision ID: svn-v4:db760fc0-0f08-0410-9d63-cc6633f64896:trunk:1
Initial import of the REL8_0_3 sources from the Pgsql CVS repository.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * re_*comp and friends - compile REs
 
3
 * This file #includes several others (see the bottom).
 
4
 *
 
5
 * Copyright (c) 1998, 1999 Henry Spencer.      All rights reserved.
 
6
 *
 
7
 * Development of this software was funded, in part, by Cray Research Inc.,
 
8
 * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
 
9
 * Corporation, none of whom are responsible for the results.  The author
 
10
 * thanks all of them.
 
11
 *
 
12
 * Redistribution and use in source and binary forms -- with or without
 
13
 * modification -- are permitted for any purpose, provided that
 
14
 * redistributions in source form retain this entire copyright notice and
 
15
 * indicate the origin and nature of any modifications.
 
16
 *
 
17
 * I'd appreciate being given credit for this package in the documentation
 
18
 * of software which uses it, but that is not a requirement.
 
19
 *
 
20
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
 
21
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 
22
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
 
23
 * HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 
24
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 
25
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 
26
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 
27
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 
28
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 
29
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
30
 *
 
31
 * $PostgreSQL: pgsql/src/backend/regex/regcomp.c,v 1.42 2004-11-24 22:56:54 tgl Exp $
 
32
 *
 
33
 */
 
34
 
 
35
#include "regex/regguts.h"
 
36
 
 
37
/*
 
38
 * forward declarations, up here so forward datatypes etc. are defined early
 
39
 */
 
40
/* === regcomp.c === */
 
41
static void moresubs(struct vars *, int);
 
42
static int      freev(struct vars *, int);
 
43
static void makesearch(struct vars *, struct nfa *);
 
44
static struct subre *parse(struct vars *, int, int, struct state *, struct state *);
 
45
static struct subre *parsebranch(struct vars *, int, int, struct state *, struct state *, int);
 
46
static void parseqatom(struct vars *, int, int, struct state *, struct state *, struct subre *);
 
47
static void nonword(struct vars *, int, struct state *, struct state *);
 
48
static void word(struct vars *, int, struct state *, struct state *);
 
49
static int      scannum(struct vars *);
 
50
static void repeat(struct vars *, struct state *, struct state *, int, int);
 
51
static void bracket(struct vars *, struct state *, struct state *);
 
52
static void cbracket(struct vars *, struct state *, struct state *);
 
53
static void brackpart(struct vars *, struct state *, struct state *);
 
54
static chr *scanplain(struct vars *);
 
55
static void leaders(struct vars *, struct cvec *);
 
56
static void onechr(struct vars *, chr, struct state *, struct state *);
 
57
static void dovec(struct vars *, struct cvec *, struct state *, struct state *);
 
58
static celt nextleader(struct vars *, chr, chr);
 
59
static void wordchrs(struct vars *);
 
60
static struct subre *subre(struct vars *, int, int, struct state *, struct state *);
 
61
static void freesubre(struct vars *, struct subre *);
 
62
static void freesrnode(struct vars *, struct subre *);
 
63
static void optst(struct vars *, struct subre *);
 
64
static int      numst(struct subre *, int);
 
65
static void markst(struct subre *);
 
66
static void cleanst(struct vars *);
 
67
static long nfatree(struct vars *, struct subre *, FILE *);
 
68
static long nfanode(struct vars *, struct subre *, FILE *);
 
69
static int      newlacon(struct vars *, struct state *, struct state *, int);
 
70
static void freelacons(struct subre *, int);
 
71
static void rfree(regex_t *);
 
72
 
 
73
#ifdef REG_DEBUG
 
74
static void dump(regex_t *, FILE *);
 
75
static void dumpst(struct subre *, FILE *, int);
 
76
static void stdump(struct subre *, FILE *, int);
 
77
static char *stid(struct subre *, char *, size_t);
 
78
#endif
 
79
/* === regc_lex.c === */
 
80
static void lexstart(struct vars *);
 
81
static void prefixes(struct vars *);
 
82
static void lexnest(struct vars *, chr *, chr *);
 
83
static void lexword(struct vars *);
 
84
static int      next(struct vars *);
 
85
static int      lexescape(struct vars *);
 
86
static chr      lexdigits(struct vars *, int, int, int);
 
87
static int      brenext(struct vars *, chr);
 
88
static void skip(struct vars *);
 
89
static chr      newline(void);
 
90
static chr      chrnamed(struct vars *, chr *, chr *, chr);
 
91
 
 
92
/* === regc_color.c === */
 
93
static void initcm(struct vars *, struct colormap *);
 
94
static void freecm(struct colormap *);
 
95
static void cmtreefree(struct colormap *, union tree *, int);
 
96
static color setcolor(struct colormap *, chr, pcolor);
 
97
static color maxcolor(struct colormap *);
 
98
static color newcolor(struct colormap *);
 
99
static void freecolor(struct colormap *, pcolor);
 
100
static color pseudocolor(struct colormap *);
 
101
static color subcolor(struct colormap *, chr c);
 
102
static color newsub(struct colormap *, pcolor);
 
103
static void subrange(struct vars *, chr, chr, struct state *, struct state *);
 
104
static void subblock(struct vars *, chr, struct state *, struct state *);
 
105
static void okcolors(struct nfa *, struct colormap *);
 
106
static void colorchain(struct colormap *, struct arc *);
 
107
static void uncolorchain(struct colormap *, struct arc *);
 
108
static int      singleton(struct colormap *, chr c);
 
109
static void rainbow(struct nfa *, struct colormap *, int, pcolor, struct state *, struct state *);
 
110
static void colorcomplement(struct nfa *, struct colormap *, int, struct state *, struct state *, struct state *);
 
111
 
 
112
#ifdef REG_DEBUG
 
113
static void dumpcolors(struct colormap *, FILE *);
 
114
static void fillcheck(struct colormap *, union tree *, int, FILE *);
 
115
static void dumpchr(chr, FILE *);
 
116
#endif
 
117
/* === regc_nfa.c === */
 
118
static struct nfa *newnfa(struct vars *, struct colormap *, struct nfa *);
 
119
static void freenfa(struct nfa *);
 
120
static struct state *newstate(struct nfa *);
 
121
static struct state *newfstate(struct nfa *, int flag);
 
122
static void dropstate(struct nfa *, struct state *);
 
123
static void freestate(struct nfa *, struct state *);
 
124
static void destroystate(struct nfa *, struct state *);
 
125
static void newarc(struct nfa *, int, pcolor, struct state *, struct state *);
 
126
static struct arc *allocarc(struct nfa *, struct state *);
 
127
static void freearc(struct nfa *, struct arc *);
 
128
static struct arc *findarc(struct state *, int, pcolor);
 
129
static void cparc(struct nfa *, struct arc *, struct state *, struct state *);
 
130
static void moveins(struct nfa *, struct state *, struct state *);
 
131
static void copyins(struct nfa *, struct state *, struct state *);
 
132
static void moveouts(struct nfa *, struct state *, struct state *);
 
133
static void copyouts(struct nfa *, struct state *, struct state *);
 
134
static void cloneouts(struct nfa *, struct state *, struct state *, struct state *, int);
 
135
static void delsub(struct nfa *, struct state *, struct state *);
 
136
static void deltraverse(struct nfa *, struct state *, struct state *);
 
137
static void dupnfa(struct nfa *, struct state *, struct state *, struct state *, struct state *);
 
138
static void duptraverse(struct nfa *, struct state *, struct state *);
 
139
static void cleartraverse(struct nfa *, struct state *);
 
140
static void specialcolors(struct nfa *);
 
141
static long optimize(struct nfa *, FILE *);
 
142
static void pullback(struct nfa *, FILE *);
 
143
static int      pull(struct nfa *, struct arc *);
 
144
static void pushfwd(struct nfa *, FILE *);
 
145
static int      push(struct nfa *, struct arc *);
 
146
 
 
147
#define INCOMPATIBLE    1               /* destroys arc */
 
148
#define SATISFIED       2                       /* constraint satisfied */
 
149
#define COMPATIBLE      3                       /* compatible but not satisfied yet */
 
150
static int      combine(struct arc *, struct arc *);
 
151
static void fixempties(struct nfa *, FILE *);
 
152
static int      unempty(struct nfa *, struct arc *);
 
153
static void cleanup(struct nfa *);
 
154
static void markreachable(struct nfa *, struct state *, struct state *, struct state *);
 
155
static void markcanreach(struct nfa *, struct state *, struct state *, struct state *);
 
156
static long analyze(struct nfa *);
 
157
static void compact(struct nfa *, struct cnfa *);
 
158
static void carcsort(struct carc *, struct carc *);
 
159
static void freecnfa(struct cnfa *);
 
160
static void dumpnfa(struct nfa *, FILE *);
 
161
 
 
162
#ifdef REG_DEBUG
 
163
static void dumpstate(struct state *, FILE *);
 
164
static void dumparcs(struct state *, FILE *);
 
165
static int      dumprarcs(struct arc *, struct state *, FILE *, int);
 
166
static void dumparc(struct arc *, struct state *, FILE *);
 
167
static void dumpcnfa(struct cnfa *, FILE *);
 
168
static void dumpcstate(int, struct carc *, struct cnfa *, FILE *);
 
169
#endif
 
170
/* === regc_cvec.c === */
 
171
static struct cvec *newcvec(int, int, int);
 
172
static struct cvec *clearcvec(struct cvec *);
 
173
static void addchr(struct cvec *, chr);
 
174
static void addrange(struct cvec *, chr, chr);
 
175
static void addmcce(struct cvec *, chr *, chr *);
 
176
static int      haschr(struct cvec *, chr);
 
177
static struct cvec *getcvec(struct vars *, int, int, int);
 
178
static void freecvec(struct cvec *);
 
179
 
 
180
/* === regc_locale.c === */
 
181
static int      pg_wc_isdigit(pg_wchar c);
 
182
static int      pg_wc_isalpha(pg_wchar c);
 
183
static int      pg_wc_isalnum(pg_wchar c);
 
184
static int      pg_wc_isupper(pg_wchar c);
 
185
static int      pg_wc_islower(pg_wchar c);
 
186
static int      pg_wc_isgraph(pg_wchar c);
 
187
static int      pg_wc_isprint(pg_wchar c);
 
188
static int      pg_wc_ispunct(pg_wchar c);
 
189
static int      pg_wc_isspace(pg_wchar c);
 
190
static pg_wchar pg_wc_toupper(pg_wchar c);
 
191
static pg_wchar pg_wc_tolower(pg_wchar c);
 
192
static int      nmcces(struct vars *);
 
193
static int      nleaders(struct vars *);
 
194
static struct cvec *allmcces(struct vars *, struct cvec *);
 
195
static celt element(struct vars *, chr *, chr *);
 
196
static struct cvec *range(struct vars *, celt, celt, int);
 
197
static int      before(celt, celt);
 
198
static struct cvec *eclass(struct vars *, celt, int);
 
199
static struct cvec *cclass(struct vars *, chr *, chr *, int);
 
200
static struct cvec *allcases(struct vars *, chr);
 
201
static int      cmp(const chr *, const chr *, size_t);
 
202
static int      casecmp(const chr *, const chr *, size_t);
 
203
 
 
204
 
 
205
/* internal variables, bundled for easy passing around */
 
206
struct vars
 
207
{
 
208
        regex_t    *re;
 
209
        chr                *now;                        /* scan pointer into string */
 
210
        chr                *stop;                       /* end of string */
 
211
        chr                *savenow;            /* saved now and stop for "subroutine
 
212
                                                                 * call" */
 
213
        chr                *savestop;
 
214
        int                     err;                    /* error code (0 if none) */
 
215
        int                     cflags;                 /* copy of compile flags */
 
216
        int                     lasttype;               /* type of previous token */
 
217
        int                     nexttype;               /* type of next token */
 
218
        chr                     nextvalue;              /* value (if any) of next token */
 
219
        int                     lexcon;                 /* lexical context type (see lex.c) */
 
220
        int                     nsubexp;                /* subexpression count */
 
221
        struct subre **subs;            /* subRE pointer vector */
 
222
        size_t          nsubs;                  /* length of vector */
 
223
        struct subre *sub10[10];        /* initial vector, enough for most */
 
224
        struct nfa *nfa;                        /* the NFA */
 
225
        struct colormap *cm;            /* character color map */
 
226
        color           nlcolor;                /* color of newline */
 
227
        struct state *wordchrs;         /* state in nfa holding word-char outarcs */
 
228
        struct subre *tree;                     /* subexpression tree */
 
229
        struct subre *treechain;        /* all tree nodes allocated */
 
230
        struct subre *treefree;         /* any free tree nodes */
 
231
        int                     ntree;                  /* number of tree nodes */
 
232
        struct cvec *cv;                        /* interface cvec */
 
233
        struct cvec *cv2;                       /* utility cvec */
 
234
        struct cvec *mcces;                     /* collating-element information */
 
235
#define  ISCELEADER(v,c) (v->mcces != NULL && haschr(v->mcces, (c)))
 
236
        struct state *mccepbegin;       /* in nfa, start of MCCE prototypes */
 
237
        struct state *mccepend;         /* in nfa, end of MCCE prototypes */
 
238
        struct subre *lacons;           /* lookahead-constraint vector */
 
239
        int                     nlacons;                /* size of lacons */
 
240
};
 
241
 
 
242
/* parsing macros; most know that `v' is the struct vars pointer */
 
243
#define NEXT()  (next(v))               /* advance by one token */
 
244
#define SEE(t)  (v->nexttype == (t))    /* is next token this? */
 
245
#define EAT(t)  (SEE(t) && next(v))             /* if next is this, swallow it */
 
246
#define VISERR(vv)      ((vv)->err != 0)        /* have we seen an error yet? */
 
247
#define ISERR() VISERR(v)
 
248
#define VERR(vv,e)      ((vv)->nexttype = EOS, ((vv)->err) ? (vv)->err :\
 
249
                                                        ((vv)->err = (e)))
 
250
#define ERR(e)  VERR(v, e)              /* record an error */
 
251
#define NOERR() {if (ISERR()) return;}  /* if error seen, return */
 
252
#define NOERRN()        {if (ISERR()) return NULL;} /* NOERR with retval */
 
253
#define NOERRZ()        {if (ISERR()) return 0;}        /* NOERR with retval */
 
254
#define INSIST(c, e)    ((c) ? 0 : ERR(e))              /* if condition false,
 
255
                                                                                                 * error */
 
256
#define NOTE(b) (v->re->re_info |= (b)) /* note visible condition */
 
257
#define EMPTYARC(x, y)  newarc(v->nfa, EMPTY, 0, x, y)
 
258
 
 
259
/* token type codes, some also used as NFA arc types */
 
260
#define EMPTY   'n'                             /* no token present */
 
261
#define EOS 'e'                                 /* end of string */
 
262
#define PLAIN   'p'                             /* ordinary character */
 
263
#define DIGIT   'd'                             /* digit (in bound) */
 
264
#define BACKREF 'b'                             /* back reference */
 
265
#define COLLEL  'I'                             /* start of [. */
 
266
#define ECLASS  'E'                             /* start of [= */
 
267
#define CCLASS  'C'                             /* start of [: */
 
268
#define END 'X'                                 /* end of [. [= [: */
 
269
#define RANGE   'R'                             /* - within [] which might be range delim. */
 
270
#define LACON   'L'                             /* lookahead constraint subRE */
 
271
#define AHEAD   'a'                             /* color-lookahead arc */
 
272
#define BEHIND  'r'                             /* color-lookbehind arc */
 
273
#define WBDRY   'w'                             /* word boundary constraint */
 
274
#define NWBDRY  'W'                             /* non-word-boundary constraint */
 
275
#define SBEGIN  'A'                             /* beginning of string (even if not BOL) */
 
276
#define SEND    'Z'                             /* end of string (even if not EOL) */
 
277
#define PREFER  'P'                             /* length preference */
 
278
 
 
279
/* is an arc colored, and hence on a color chain? */
 
280
#define COLORED(a)      ((a)->type == PLAIN || (a)->type == AHEAD || \
 
281
                                                        (a)->type == BEHIND)
 
282
 
 
283
 
 
284
 
 
285
/* static function list */
 
286
static struct fns functions = {
 
287
        rfree,                                          /* regfree insides */
 
288
};
 
289
 
 
290
 
 
291
 
 
292
/*
 
293
 * pg_regcomp - compile regular expression
 
294
 */
 
295
int
 
296
pg_regcomp(regex_t *re,
 
297
                   const chr *string,
 
298
                   size_t len,
 
299
                   int flags)
 
300
{
 
301
        struct vars var;
 
302
        struct vars *v = &var;
 
303
        struct guts *g;
 
304
        int                     i;
 
305
        size_t          j;
 
306
 
 
307
#ifdef REG_DEBUG
 
308
        FILE       *debug = (flags & REG_PROGRESS) ? stdout : (FILE *) NULL;
 
309
 
 
310
#else
 
311
        FILE       *debug = (FILE *) NULL;
 
312
#endif
 
313
 
 
314
#define  CNOERR()        { if (ISERR()) return freev(v, v->err); }
 
315
 
 
316
        /* sanity checks */
 
317
 
 
318
        if (re == NULL || string == NULL)
 
319
                return REG_INVARG;
 
320
        if ((flags & REG_QUOTE) &&
 
321
                (flags & (REG_ADVANCED | REG_EXPANDED | REG_NEWLINE)))
 
322
                return REG_INVARG;
 
323
        if (!(flags & REG_EXTENDED) && (flags & REG_ADVF))
 
324
                return REG_INVARG;
 
325
 
 
326
        /* initial setup (after which freev() is callable) */
 
327
        v->re = re;
 
328
        v->now = (chr *) string;
 
329
        v->stop = v->now + len;
 
330
        v->savenow = v->savestop = NULL;
 
331
        v->err = 0;
 
332
        v->cflags = flags;
 
333
        v->nsubexp = 0;
 
334
        v->subs = v->sub10;
 
335
        v->nsubs = 10;
 
336
        for (j = 0; j < v->nsubs; j++)
 
337
                v->subs[j] = NULL;
 
338
        v->nfa = NULL;
 
339
        v->cm = NULL;
 
340
        v->nlcolor = COLORLESS;
 
341
        v->wordchrs = NULL;
 
342
        v->tree = NULL;
 
343
        v->treechain = NULL;
 
344
        v->treefree = NULL;
 
345
        v->cv = NULL;
 
346
        v->cv2 = NULL;
 
347
        v->mcces = NULL;
 
348
        v->lacons = NULL;
 
349
        v->nlacons = 0;
 
350
        re->re_magic = REMAGIC;
 
351
        re->re_info = 0;                        /* bits get set during parse */
 
352
        re->re_csize = sizeof(chr);
 
353
        re->re_guts = NULL;
 
354
        re->re_fns = VS(&functions);
 
355
 
 
356
        /* more complex setup, malloced things */
 
357
        re->re_guts = VS(MALLOC(sizeof(struct guts)));
 
358
        if (re->re_guts == NULL)
 
359
                return freev(v, REG_ESPACE);
 
360
        g = (struct guts *) re->re_guts;
 
361
        g->tree = NULL;
 
362
        initcm(v, &g->cmap);
 
363
        v->cm = &g->cmap;
 
364
        g->lacons = NULL;
 
365
        g->nlacons = 0;
 
366
        ZAPCNFA(g->search);
 
367
        v->nfa = newnfa(v, v->cm, (struct nfa *) NULL);
 
368
        CNOERR();
 
369
        v->cv = newcvec(100, 20, 10);
 
370
        if (v->cv == NULL)
 
371
                return freev(v, REG_ESPACE);
 
372
        i = nmcces(v);
 
373
        if (i > 0)
 
374
        {
 
375
                v->mcces = newcvec(nleaders(v), 0, i);
 
376
                CNOERR();
 
377
                v->mcces = allmcces(v, v->mcces);
 
378
                leaders(v, v->mcces);
 
379
                addmcce(v->mcces, (chr *) NULL, (chr *) NULL);  /* dummy */
 
380
        }
 
381
        CNOERR();
 
382
 
 
383
        /* parsing */
 
384
        lexstart(v);                            /* also handles prefixes */
 
385
        if ((v->cflags & REG_NLSTOP) || (v->cflags & REG_NLANCH))
 
386
        {
 
387
                /* assign newline a unique color */
 
388
                v->nlcolor = subcolor(v->cm, newline());
 
389
                okcolors(v->nfa, v->cm);
 
390
        }
 
391
        CNOERR();
 
392
        v->tree = parse(v, EOS, PLAIN, v->nfa->init, v->nfa->final);
 
393
        assert(SEE(EOS));                       /* even if error; ISERR() => SEE(EOS) */
 
394
        CNOERR();
 
395
        assert(v->tree != NULL);
 
396
 
 
397
        /* finish setup of nfa and its subre tree */
 
398
        specialcolors(v->nfa);
 
399
        CNOERR();
 
400
#ifdef REG_DEBUG
 
401
        if (debug != NULL)
 
402
        {
 
403
                fprintf(debug, "\n\n\n========= RAW ==========\n");
 
404
                dumpnfa(v->nfa, debug);
 
405
                dumpst(v->tree, debug, 1);
 
406
        }
 
407
#endif
 
408
        optst(v, v->tree);
 
409
        v->ntree = numst(v->tree, 1);
 
410
        markst(v->tree);
 
411
        cleanst(v);
 
412
#ifdef REG_DEBUG
 
413
        if (debug != NULL)
 
414
        {
 
415
                fprintf(debug, "\n\n\n========= TREE FIXED ==========\n");
 
416
                dumpst(v->tree, debug, 1);
 
417
        }
 
418
#endif
 
419
 
 
420
        /* build compacted NFAs for tree and lacons */
 
421
        re->re_info |= nfatree(v, v->tree, debug);
 
422
        CNOERR();
 
423
        assert(v->nlacons == 0 || v->lacons != NULL);
 
424
        for (i = 1; i < v->nlacons; i++)
 
425
        {
 
426
#ifdef REG_DEBUG
 
427
                if (debug != NULL)
 
428
                        fprintf(debug, "\n\n\n========= LA%d ==========\n", i);
 
429
#endif
 
430
                nfanode(v, &v->lacons[i], debug);
 
431
        }
 
432
        CNOERR();
 
433
        if (v->tree->flags & SHORTER)
 
434
                NOTE(REG_USHORTEST);
 
435
 
 
436
        /* build compacted NFAs for tree, lacons, fast search */
 
437
#ifdef REG_DEBUG
 
438
        if (debug != NULL)
 
439
                fprintf(debug, "\n\n\n========= SEARCH ==========\n");
 
440
#endif
 
441
        /* can sacrifice main NFA now, so use it as work area */
 
442
        (DISCARD) optimize(v->nfa, debug);
 
443
        CNOERR();
 
444
        makesearch(v, v->nfa);
 
445
        CNOERR();
 
446
        compact(v->nfa, &g->search);
 
447
        CNOERR();
 
448
 
 
449
        /* looks okay, package it up */
 
450
        re->re_nsub = v->nsubexp;
 
451
        v->re = NULL;                           /* freev no longer frees re */
 
452
        g->magic = GUTSMAGIC;
 
453
        g->cflags = v->cflags;
 
454
        g->info = re->re_info;
 
455
        g->nsub = re->re_nsub;
 
456
        g->tree = v->tree;
 
457
        v->tree = NULL;
 
458
        g->ntree = v->ntree;
 
459
        g->compare = (v->cflags & REG_ICASE) ? casecmp : cmp;
 
460
        g->lacons = v->lacons;
 
461
        v->lacons = NULL;
 
462
        g->nlacons = v->nlacons;
 
463
 
 
464
#ifdef REG_DEBUG
 
465
        if (flags & REG_DUMP)
 
466
                dump(re, stdout);
 
467
#endif
 
468
 
 
469
        assert(v->err == 0);
 
470
        return freev(v, 0);
 
471
}
 
472
 
 
473
/*
 
474
 * moresubs - enlarge subRE vector
 
475
 */
 
476
static void
 
477
moresubs(struct vars * v,
 
478
                 int wanted)                    /* want enough room for this one */
 
479
{
 
480
        struct subre **p;
 
481
        size_t          n;
 
482
 
 
483
        assert(wanted > 0 && (size_t) wanted >= v->nsubs);
 
484
        n = (size_t) wanted *3 / 2 + 1;
 
485
 
 
486
        if (v->subs == v->sub10)
 
487
        {
 
488
                p = (struct subre **) MALLOC(n * sizeof(struct subre *));
 
489
                if (p != NULL)
 
490
                        memcpy(VS(p), VS(v->subs),
 
491
                                   v->nsubs * sizeof(struct subre *));
 
492
        }
 
493
        else
 
494
                p = (struct subre **) REALLOC(v->subs, n * sizeof(struct subre *));
 
495
        if (p == NULL)
 
496
        {
 
497
                ERR(REG_ESPACE);
 
498
                return;
 
499
        }
 
500
        v->subs = p;
 
501
        for (p = &v->subs[v->nsubs]; v->nsubs < n; p++, v->nsubs++)
 
502
                *p = NULL;
 
503
        assert(v->nsubs == n);
 
504
        assert((size_t) wanted < v->nsubs);
 
505
}
 
506
 
 
507
/*
 
508
 * freev - free vars struct's substructures where necessary
 
509
 *
 
510
 * Optionally does error-number setting, and always returns error code
 
511
 * (if any), to make error-handling code terser.
 
512
 */
 
513
static int
 
514
freev(struct vars * v,
 
515
          int err)
 
516
{
 
517
        if (v->re != NULL)
 
518
                rfree(v->re);
 
519
        if (v->subs != v->sub10)
 
520
                FREE(v->subs);
 
521
        if (v->nfa != NULL)
 
522
                freenfa(v->nfa);
 
523
        if (v->tree != NULL)
 
524
                freesubre(v, v->tree);
 
525
        if (v->treechain != NULL)
 
526
                cleanst(v);
 
527
        if (v->cv != NULL)
 
528
                freecvec(v->cv);
 
529
        if (v->cv2 != NULL)
 
530
                freecvec(v->cv2);
 
531
        if (v->mcces != NULL)
 
532
                freecvec(v->mcces);
 
533
        if (v->lacons != NULL)
 
534
                freelacons(v->lacons, v->nlacons);
 
535
        ERR(err);                                       /* nop if err==0 */
 
536
 
 
537
        return v->err;
 
538
}
 
539
 
 
540
/*
 
541
 * makesearch - turn an NFA into a search NFA (implicit prepend of .*?)
 
542
 * NFA must have been optimize()d already.
 
543
 */
 
544
static void
 
545
makesearch(struct vars * v,
 
546
                   struct nfa * nfa)
 
547
{
 
548
        struct arc *a;
 
549
        struct arc *b;
 
550
        struct state *pre = nfa->pre;
 
551
        struct state *s;
 
552
        struct state *s2;
 
553
        struct state *slist;
 
554
 
 
555
        /* no loops are needed if it's anchored */
 
556
        for (a = pre->outs; a != NULL; a = a->outchain)
 
557
        {
 
558
                assert(a->type == PLAIN);
 
559
                if (a->co != nfa->bos[0] && a->co != nfa->bos[1])
 
560
                        break;
 
561
        }
 
562
        if (a != NULL)
 
563
        {
 
564
                /* add implicit .* in front */
 
565
                rainbow(nfa, v->cm, PLAIN, COLORLESS, pre, pre);
 
566
 
 
567
                /* and ^* and \A* too -- not always necessary, but harmless */
 
568
                newarc(nfa, PLAIN, nfa->bos[0], pre, pre);
 
569
                newarc(nfa, PLAIN, nfa->bos[1], pre, pre);
 
570
        }
 
571
 
 
572
        /*
 
573
         * Now here's the subtle part.  Because many REs have no lookback
 
574
         * constraints, often knowing when you were in the pre state tells you
 
575
         * little; it's the next state(s) that are informative.  But some of
 
576
         * them may have other inarcs, i.e. it may be possible to make actual
 
577
         * progress and then return to one of them.  We must de-optimize such
 
578
         * cases, splitting each such state into progress and no-progress
 
579
         * states.
 
580
         */
 
581
 
 
582
        /* first, make a list of the states */
 
583
        slist = NULL;
 
584
        for (a = pre->outs; a != NULL; a = a->outchain)
 
585
        {
 
586
                s = a->to;
 
587
                for (b = s->ins; b != NULL; b = b->inchain)
 
588
                        if (b->from != pre)
 
589
                                break;
 
590
                if (b != NULL)
 
591
                {                                               /* must be split */
 
592
                        if (s->tmp == NULL)
 
593
                        {                                       /* if not already in the list */
 
594
                                                                /* (fixes bugs 505048, 230589, */
 
595
                                                                /* 840258, 504785) */
 
596
                                s->tmp = slist;
 
597
                                slist = s;
 
598
                        }
 
599
                }
 
600
        }
 
601
 
 
602
        /* do the splits */
 
603
        for (s = slist; s != NULL; s = s2)
 
604
        {
 
605
                s2 = newstate(nfa);
 
606
                copyouts(nfa, s, s2);
 
607
                for (a = s->ins; a != NULL; a = b)
 
608
                {
 
609
                        b = a->inchain;
 
610
                        if (a->from != pre)
 
611
                        {
 
612
                                cparc(nfa, a, a->from, s2);
 
613
                                freearc(nfa, a);
 
614
                        }
 
615
                }
 
616
                s2 = s->tmp;
 
617
                s->tmp = NULL;                  /* clean up while we're at it */
 
618
        }
 
619
}
 
620
 
 
621
/*
 
622
 * parse - parse an RE
 
623
 *
 
624
 * This is actually just the top level, which parses a bunch of branches
 
625
 * tied together with '|'.      They appear in the tree as the left children
 
626
 * of a chain of '|' subres.
 
627
 */
 
628
static struct subre *
 
629
parse(struct vars * v,
 
630
          int stopper,                          /* EOS or ')' */
 
631
          int type,                                     /* LACON (lookahead subRE) or PLAIN */
 
632
          struct state * init,          /* initial state */
 
633
          struct state * final)         /* final state */
 
634
{
 
635
        struct state *left;                     /* scaffolding for branch */
 
636
        struct state *right;
 
637
        struct subre *branches;         /* top level */
 
638
        struct subre *branch;           /* current branch */
 
639
        struct subre *t;                        /* temporary */
 
640
        int                     firstbranch;    /* is this the first branch? */
 
641
 
 
642
        assert(stopper == ')' || stopper == EOS);
 
643
 
 
644
        branches = subre(v, '|', LONGER, init, final);
 
645
        NOERRN();
 
646
        branch = branches;
 
647
        firstbranch = 1;
 
648
        do
 
649
        {                                                       /* a branch */
 
650
                if (!firstbranch)
 
651
                {
 
652
                        /* need a place to hang it */
 
653
                        branch->right = subre(v, '|', LONGER, init, final);
 
654
                        NOERRN();
 
655
                        branch = branch->right;
 
656
                }
 
657
                firstbranch = 0;
 
658
                left = newstate(v->nfa);
 
659
                right = newstate(v->nfa);
 
660
                NOERRN();
 
661
                EMPTYARC(init, left);
 
662
                EMPTYARC(right, final);
 
663
                NOERRN();
 
664
                branch->left = parsebranch(v, stopper, type, left, right, 0);
 
665
                NOERRN();
 
666
                branch->flags |= UP(branch->flags | branch->left->flags);
 
667
                if ((branch->flags & ~branches->flags) != 0)    /* new flags */
 
668
                        for (t = branches; t != branch; t = t->right)
 
669
                                t->flags |= branch->flags;
 
670
        } while (EAT('|'));
 
671
        assert(SEE(stopper) || SEE(EOS));
 
672
 
 
673
        if (!SEE(stopper))
 
674
        {
 
675
                assert(stopper == ')' && SEE(EOS));
 
676
                ERR(REG_EPAREN);
 
677
        }
 
678
 
 
679
        /* optimize out simple cases */
 
680
        if (branch == branches)
 
681
        {                                                       /* only one branch */
 
682
                assert(branch->right == NULL);
 
683
                t = branch->left;
 
684
                branch->left = NULL;
 
685
                freesubre(v, branches);
 
686
                branches = t;
 
687
        }
 
688
        else if (!MESSY(branches->flags))
 
689
        {                                                       /* no interesting innards */
 
690
                freesubre(v, branches->left);
 
691
                branches->left = NULL;
 
692
                freesubre(v, branches->right);
 
693
                branches->right = NULL;
 
694
                branches->op = '=';
 
695
        }
 
696
 
 
697
        return branches;
 
698
}
 
699
 
 
700
/*
 
701
 * parsebranch - parse one branch of an RE
 
702
 *
 
703
 * This mostly manages concatenation, working closely with parseqatom().
 
704
 * Concatenated things are bundled up as much as possible, with separate
 
705
 * ',' nodes introduced only when necessary due to substructure.
 
706
 */
 
707
static struct subre *
 
708
parsebranch(struct vars * v,
 
709
                        int stopper,            /* EOS or ')' */
 
710
                        int type,                       /* LACON (lookahead subRE) or PLAIN */
 
711
                        struct state * left,    /* leftmost state */
 
712
                        struct state * right,           /* rightmost state */
 
713
                        int partial)            /* is this only part of a branch? */
 
714
{
 
715
        struct state *lp;                       /* left end of current construct */
 
716
        int                     seencontent;    /* is there anything in this branch yet? */
 
717
        struct subre *t;
 
718
 
 
719
        lp = left;
 
720
        seencontent = 0;
 
721
        t = subre(v, '=', 0, left, right);      /* op '=' is tentative */
 
722
        NOERRN();
 
723
        while (!SEE('|') && !SEE(stopper) && !SEE(EOS))
 
724
        {
 
725
                if (seencontent)
 
726
                {                                               /* implicit concat operator */
 
727
                        lp = newstate(v->nfa);
 
728
                        NOERRN();
 
729
                        moveins(v->nfa, right, lp);
 
730
                }
 
731
                seencontent = 1;
 
732
 
 
733
                /* NB, recursion in parseqatom() may swallow rest of branch */
 
734
                parseqatom(v, stopper, type, lp, right, t);
 
735
        }
 
736
 
 
737
        if (!seencontent)
 
738
        {                                                       /* empty branch */
 
739
                if (!partial)
 
740
                        NOTE(REG_UUNSPEC);
 
741
                assert(lp == left);
 
742
                EMPTYARC(left, right);
 
743
        }
 
744
 
 
745
        return t;
 
746
}
 
747
 
 
748
/*
 
749
 * parseqatom - parse one quantified atom or constraint of an RE
 
750
 *
 
751
 * The bookkeeping near the end cooperates very closely with parsebranch();
 
752
 * in particular, it contains a recursion that can involve parsing the rest
 
753
 * of the branch, making this function's name somewhat inaccurate.
 
754
 */
 
755
static void
 
756
parseqatom(struct vars * v,
 
757
                   int stopper,                 /* EOS or ')' */
 
758
                   int type,                    /* LACON (lookahead subRE) or PLAIN */
 
759
                   struct state * lp,   /* left state to hang it on */
 
760
                   struct state * rp,   /* right state to hang it on */
 
761
                   struct subre * top)  /* subtree top */
 
762
{
 
763
        struct state *s;                        /* temporaries for new states */
 
764
        struct state *s2;
 
765
 
 
766
#define  ARCV(t, val)    newarc(v->nfa, t, val, lp, rp)
 
767
        int                     m,
 
768
                                n;
 
769
        struct subre *atom;                     /* atom's subtree */
 
770
        struct subre *t;
 
771
        int                     cap;                    /* capturing parens? */
 
772
        int                     pos;                    /* positive lookahead? */
 
773
        int                     subno;                  /* capturing-parens or backref number */
 
774
        int                     atomtype;
 
775
        int                     qprefer;                /* quantifier short/long preference */
 
776
        int                     f;
 
777
        struct subre **atomp;           /* where the pointer to atom is */
 
778
 
 
779
        /* initial bookkeeping */
 
780
        atom = NULL;
 
781
        assert(lp->nouts == 0);         /* must string new code */
 
782
        assert(rp->nins == 0);          /* between lp and rp */
 
783
        subno = 0;                                      /* just to shut lint up */
 
784
 
 
785
        /* an atom or constraint... */
 
786
        atomtype = v->nexttype;
 
787
        switch (atomtype)
 
788
        {
 
789
                        /* first, constraints, which end by returning */
 
790
                case '^':
 
791
                        ARCV('^', 1);
 
792
                        if (v->cflags & REG_NLANCH)
 
793
                                ARCV(BEHIND, v->nlcolor);
 
794
                        NEXT();
 
795
                        return;
 
796
                        break;
 
797
                case '$':
 
798
                        ARCV('$', 1);
 
799
                        if (v->cflags & REG_NLANCH)
 
800
                                ARCV(AHEAD, v->nlcolor);
 
801
                        NEXT();
 
802
                        return;
 
803
                        break;
 
804
                case SBEGIN:
 
805
                        ARCV('^', 1);           /* BOL */
 
806
                        ARCV('^', 0);           /* or BOS */
 
807
                        NEXT();
 
808
                        return;
 
809
                        break;
 
810
                case SEND:
 
811
                        ARCV('$', 1);           /* EOL */
 
812
                        ARCV('$', 0);           /* or EOS */
 
813
                        NEXT();
 
814
                        return;
 
815
                        break;
 
816
                case '<':
 
817
                        wordchrs(v);            /* does NEXT() */
 
818
                        s = newstate(v->nfa);
 
819
                        NOERR();
 
820
                        nonword(v, BEHIND, lp, s);
 
821
                        word(v, AHEAD, s, rp);
 
822
                        return;
 
823
                        break;
 
824
                case '>':
 
825
                        wordchrs(v);            /* does NEXT() */
 
826
                        s = newstate(v->nfa);
 
827
                        NOERR();
 
828
                        word(v, BEHIND, lp, s);
 
829
                        nonword(v, AHEAD, s, rp);
 
830
                        return;
 
831
                        break;
 
832
                case WBDRY:
 
833
                        wordchrs(v);            /* does NEXT() */
 
834
                        s = newstate(v->nfa);
 
835
                        NOERR();
 
836
                        nonword(v, BEHIND, lp, s);
 
837
                        word(v, AHEAD, s, rp);
 
838
                        s = newstate(v->nfa);
 
839
                        NOERR();
 
840
                        word(v, BEHIND, lp, s);
 
841
                        nonword(v, AHEAD, s, rp);
 
842
                        return;
 
843
                        break;
 
844
                case NWBDRY:
 
845
                        wordchrs(v);            /* does NEXT() */
 
846
                        s = newstate(v->nfa);
 
847
                        NOERR();
 
848
                        word(v, BEHIND, lp, s);
 
849
                        word(v, AHEAD, s, rp);
 
850
                        s = newstate(v->nfa);
 
851
                        NOERR();
 
852
                        nonword(v, BEHIND, lp, s);
 
853
                        nonword(v, AHEAD, s, rp);
 
854
                        return;
 
855
                        break;
 
856
                case LACON:                             /* lookahead constraint */
 
857
                        pos = v->nextvalue;
 
858
                        NEXT();
 
859
                        s = newstate(v->nfa);
 
860
                        s2 = newstate(v->nfa);
 
861
                        NOERR();
 
862
                        t = parse(v, ')', LACON, s, s2);
 
863
                        freesubre(v, t);        /* internal structure irrelevant */
 
864
                        assert(SEE(')') || ISERR());
 
865
                        NEXT();
 
866
                        n = newlacon(v, s, s2, pos);
 
867
                        NOERR();
 
868
                        ARCV(LACON, n);
 
869
                        return;
 
870
                        break;
 
871
                        /* then errors, to get them out of the way */
 
872
                case '*':
 
873
                case '+':
 
874
                case '?':
 
875
                case '{':
 
876
                        ERR(REG_BADRPT);
 
877
                        return;
 
878
                        break;
 
879
                default:
 
880
                        ERR(REG_ASSERT);
 
881
                        return;
 
882
                        break;
 
883
                        /* then plain characters, and minor variants on that theme */
 
884
                case ')':                               /* unbalanced paren */
 
885
                        if ((v->cflags & REG_ADVANCED) != REG_EXTENDED)
 
886
                        {
 
887
                                ERR(REG_EPAREN);
 
888
                                return;
 
889
                        }
 
890
                        /* legal in EREs due to specification botch */
 
891
                        NOTE(REG_UPBOTCH);
 
892
                        /* fallthrough into case PLAIN */
 
893
                case PLAIN:
 
894
                        onechr(v, v->nextvalue, lp, rp);
 
895
                        okcolors(v->nfa, v->cm);
 
896
                        NOERR();
 
897
                        NEXT();
 
898
                        break;
 
899
                case '[':
 
900
                        if (v->nextvalue == 1)
 
901
                                bracket(v, lp, rp);
 
902
                        else
 
903
                                cbracket(v, lp, rp);
 
904
                        assert(SEE(']') || ISERR());
 
905
                        NEXT();
 
906
                        break;
 
907
                case '.':
 
908
                        rainbow(v->nfa, v->cm, PLAIN,
 
909
                                        (v->cflags & REG_NLSTOP) ? v->nlcolor : COLORLESS,
 
910
                                        lp, rp);
 
911
                        NEXT();
 
912
                        break;
 
913
                        /* and finally the ugly stuff */
 
914
                case '(':                               /* value flags as capturing or non */
 
915
                        cap = (type == LACON) ? 0 : v->nextvalue;
 
916
                        if (cap)
 
917
                        {
 
918
                                v->nsubexp++;
 
919
                                subno = v->nsubexp;
 
920
                                if ((size_t) subno >= v->nsubs)
 
921
                                        moresubs(v, subno);
 
922
                                assert((size_t) subno < v->nsubs);
 
923
                        }
 
924
                        else
 
925
                                atomtype = PLAIN;               /* something that's not '(' */
 
926
                        NEXT();
 
927
                        /* need new endpoints because tree will contain pointers */
 
928
                        s = newstate(v->nfa);
 
929
                        s2 = newstate(v->nfa);
 
930
                        NOERR();
 
931
                        EMPTYARC(lp, s);
 
932
                        EMPTYARC(s2, rp);
 
933
                        NOERR();
 
934
                        atom = parse(v, ')', PLAIN, s, s2);
 
935
                        assert(SEE(')') || ISERR());
 
936
                        NEXT();
 
937
                        NOERR();
 
938
                        if (cap)
 
939
                        {
 
940
                                v->subs[subno] = atom;
 
941
                                t = subre(v, '(', atom->flags | CAP, lp, rp);
 
942
                                NOERR();
 
943
                                t->subno = subno;
 
944
                                t->left = atom;
 
945
                                atom = t;
 
946
                        }
 
947
                        /* postpone everything else pending possible {0} */
 
948
                        break;
 
949
                case BACKREF:                   /* the Feature From The Black Lagoon */
 
950
                        INSIST(type != LACON, REG_ESUBREG);
 
951
                        INSIST(v->nextvalue < v->nsubs, REG_ESUBREG);
 
952
                        INSIST(v->subs[v->nextvalue] != NULL, REG_ESUBREG);
 
953
                        NOERR();
 
954
                        assert(v->nextvalue > 0);
 
955
                        atom = subre(v, 'b', BACKR, lp, rp);
 
956
                        subno = v->nextvalue;
 
957
                        atom->subno = subno;
 
958
                        EMPTYARC(lp, rp);       /* temporarily, so there's something */
 
959
                        NEXT();
 
960
                        break;
 
961
        }
 
962
 
 
963
        /* ...and an atom may be followed by a quantifier */
 
964
        switch (v->nexttype)
 
965
        {
 
966
                case '*':
 
967
                        m = 0;
 
968
                        n = INFINITY;
 
969
                        qprefer = (v->nextvalue) ? LONGER : SHORTER;
 
970
                        NEXT();
 
971
                        break;
 
972
                case '+':
 
973
                        m = 1;
 
974
                        n = INFINITY;
 
975
                        qprefer = (v->nextvalue) ? LONGER : SHORTER;
 
976
                        NEXT();
 
977
                        break;
 
978
                case '?':
 
979
                        m = 0;
 
980
                        n = 1;
 
981
                        qprefer = (v->nextvalue) ? LONGER : SHORTER;
 
982
                        NEXT();
 
983
                        break;
 
984
                case '{':
 
985
                        NEXT();
 
986
                        m = scannum(v);
 
987
                        if (EAT(','))
 
988
                        {
 
989
                                if (SEE(DIGIT))
 
990
                                        n = scannum(v);
 
991
                                else
 
992
                                        n = INFINITY;
 
993
                                if (m > n)
 
994
                                {
 
995
                                        ERR(REG_BADBR);
 
996
                                        return;
 
997
                                }
 
998
                                /* {m,n} exercises preference, even if it's {m,m} */
 
999
                                qprefer = (v->nextvalue) ? LONGER : SHORTER;
 
1000
                        }
 
1001
                        else
 
1002
                        {
 
1003
                                n = m;
 
1004
                                /* {m} passes operand's preference through */
 
1005
                                qprefer = 0;
 
1006
                        }
 
1007
                        if (!SEE('}'))
 
1008
                        {                                       /* catches errors too */
 
1009
                                ERR(REG_BADBR);
 
1010
                                return;
 
1011
                        }
 
1012
                        NEXT();
 
1013
                        break;
 
1014
                default:                                /* no quantifier */
 
1015
                        m = n = 1;
 
1016
                        qprefer = 0;
 
1017
                        break;
 
1018
        }
 
1019
 
 
1020
        /* annoying special case:  {0} or {0,0} cancels everything */
 
1021
        if (m == 0 && n == 0)
 
1022
        {
 
1023
                if (atom != NULL)
 
1024
                        freesubre(v, atom);
 
1025
                if (atomtype == '(')
 
1026
                        v->subs[subno] = NULL;
 
1027
                delsub(v->nfa, lp, rp);
 
1028
                EMPTYARC(lp, rp);
 
1029
                return;
 
1030
        }
 
1031
 
 
1032
        /* if not a messy case, avoid hard part */
 
1033
        assert(!MESSY(top->flags));
 
1034
        f = top->flags | qprefer | ((atom != NULL) ? atom->flags : 0);
 
1035
        if (atomtype != '(' && atomtype != BACKREF && !MESSY(UP(f)))
 
1036
        {
 
1037
                if (!(m == 1 && n == 1))
 
1038
                        repeat(v, lp, rp, m, n);
 
1039
                if (atom != NULL)
 
1040
                        freesubre(v, atom);
 
1041
                top->flags = f;
 
1042
                return;
 
1043
        }
 
1044
 
 
1045
        /*
 
1046
         * hard part:  something messy That is, capturing parens, back
 
1047
         * reference, short/long clash, or an atom with substructure
 
1048
         * containing one of those.
 
1049
         */
 
1050
 
 
1051
        /* now we'll need a subre for the contents even if they're boring */
 
1052
        if (atom == NULL)
 
1053
        {
 
1054
                atom = subre(v, '=', 0, lp, rp);
 
1055
                NOERR();
 
1056
        }
 
1057
 
 
1058
        /*
 
1059
         * prepare a general-purpose state skeleton
 
1060
         *
 
1061
         * ---> [s] ---prefix---> [begin] ---atom---> [end] ----rest---> [rp] / /
 
1062
         * [lp] ----> [s2] ----bypass---------------------
 
1063
         *
 
1064
         * where bypass is an empty, and prefix is some repetitions of atom
 
1065
         */
 
1066
        s = newstate(v->nfa);           /* first, new endpoints for the atom */
 
1067
        s2 = newstate(v->nfa);
 
1068
        NOERR();
 
1069
        moveouts(v->nfa, lp, s);
 
1070
        moveins(v->nfa, rp, s2);
 
1071
        NOERR();
 
1072
        atom->begin = s;
 
1073
        atom->end = s2;
 
1074
        s = newstate(v->nfa);           /* and spots for prefix and bypass */
 
1075
        s2 = newstate(v->nfa);
 
1076
        NOERR();
 
1077
        EMPTYARC(lp, s);
 
1078
        EMPTYARC(lp, s2);
 
1079
        NOERR();
 
1080
 
 
1081
        /* break remaining subRE into x{...} and what follows */
 
1082
        t = subre(v, '.', COMBINE(qprefer, atom->flags), lp, rp);
 
1083
        t->left = atom;
 
1084
        atomp = &t->left;
 
1085
        /* here we should recurse... but we must postpone that to the end */
 
1086
 
 
1087
        /* split top into prefix and remaining */
 
1088
        assert(top->op == '=' && top->left == NULL && top->right == NULL);
 
1089
        top->left = subre(v, '=', top->flags, top->begin, lp);
 
1090
        top->op = '.';
 
1091
        top->right = t;
 
1092
 
 
1093
        /* if it's a backref, now is the time to replicate the subNFA */
 
1094
        if (atomtype == BACKREF)
 
1095
        {
 
1096
                assert(atom->begin->nouts == 1);                /* just the EMPTY */
 
1097
                delsub(v->nfa, atom->begin, atom->end);
 
1098
                assert(v->subs[subno] != NULL);
 
1099
                /* and here's why the recursion got postponed:  it must */
 
1100
                /* wait until the skeleton is filled in, because it may */
 
1101
                /* hit a backref that wants to copy the filled-in skeleton */
 
1102
                dupnfa(v->nfa, v->subs[subno]->begin, v->subs[subno]->end,
 
1103
                           atom->begin, atom->end);
 
1104
                NOERR();
 
1105
        }
 
1106
 
 
1107
        /* it's quantifier time; first, turn x{0,...} into x{1,...}|empty */
 
1108
        if (m == 0)
 
1109
        {
 
1110
                EMPTYARC(s2, atom->end);        /* the bypass */
 
1111
                assert(PREF(qprefer) != 0);
 
1112
                f = COMBINE(qprefer, atom->flags);
 
1113
                t = subre(v, '|', f, lp, atom->end);
 
1114
                NOERR();
 
1115
                t->left = atom;
 
1116
                t->right = subre(v, '|', PREF(f), s2, atom->end);
 
1117
                NOERR();
 
1118
                t->right->left = subre(v, '=', 0, s2, atom->end);
 
1119
                NOERR();
 
1120
                *atomp = t;
 
1121
                atomp = &t->left;
 
1122
                m = 1;
 
1123
        }
 
1124
 
 
1125
        /* deal with the rest of the quantifier */
 
1126
        if (atomtype == BACKREF)
 
1127
        {
 
1128
                /* special case:  backrefs have internal quantifiers */
 
1129
                EMPTYARC(s, atom->begin);               /* empty prefix */
 
1130
                /* just stuff everything into atom */
 
1131
                repeat(v, atom->begin, atom->end, m, n);
 
1132
                atom->min = (short) m;
 
1133
                atom->max = (short) n;
 
1134
                atom->flags |= COMBINE(qprefer, atom->flags);
 
1135
        }
 
1136
        else if (m == 1 && n == 1)
 
1137
        {
 
1138
                /* no/vacuous quantifier:  done */
 
1139
                EMPTYARC(s, atom->begin);               /* empty prefix */
 
1140
        }
 
1141
        else
 
1142
        {
 
1143
                /* turn x{m,n} into x{m-1,n-1}x, with capturing */
 
1144
                /* parens in only second x */
 
1145
                dupnfa(v->nfa, atom->begin, atom->end, s, atom->begin);
 
1146
                assert(m >= 1 && m != INFINITY && n >= 1);
 
1147
                repeat(v, s, atom->begin, m - 1, (n == INFINITY) ? n : n - 1);
 
1148
                f = COMBINE(qprefer, atom->flags);
 
1149
                t = subre(v, '.', f, s, atom->end);             /* prefix and atom */
 
1150
                NOERR();
 
1151
                t->left = subre(v, '=', PREF(f), s, atom->begin);
 
1152
                NOERR();
 
1153
                t->right = atom;
 
1154
                *atomp = t;
 
1155
        }
 
1156
 
 
1157
        /* and finally, look after that postponed recursion */
 
1158
        t = top->right;
 
1159
        if (!(SEE('|') || SEE(stopper) || SEE(EOS)))
 
1160
                t->right = parsebranch(v, stopper, type, atom->end, rp, 1);
 
1161
        else
 
1162
        {
 
1163
                EMPTYARC(atom->end, rp);
 
1164
                t->right = subre(v, '=', 0, atom->end, rp);
 
1165
        }
 
1166
        assert(SEE('|') || SEE(stopper) || SEE(EOS));
 
1167
        t->flags |= COMBINE(t->flags, t->right->flags);
 
1168
        top->flags |= COMBINE(top->flags, t->flags);
 
1169
}
 
1170
 
 
1171
/*
 
1172
 * nonword - generate arcs for non-word-character ahead or behind
 
1173
 */
 
1174
static void
 
1175
nonword(struct vars * v,
 
1176
                int dir,                                /* AHEAD or BEHIND */
 
1177
                struct state * lp,
 
1178
                struct state * rp)
 
1179
{
 
1180
        int                     anchor = (dir == AHEAD) ? '$' : '^';
 
1181
 
 
1182
        assert(dir == AHEAD || dir == BEHIND);
 
1183
        newarc(v->nfa, anchor, 1, lp, rp);
 
1184
        newarc(v->nfa, anchor, 0, lp, rp);
 
1185
        colorcomplement(v->nfa, v->cm, dir, v->wordchrs, lp, rp);
 
1186
        /* (no need for special attention to \n) */
 
1187
}
 
1188
 
 
1189
/*
 
1190
 * word - generate arcs for word character ahead or behind
 
1191
 */
 
1192
static void
 
1193
word(struct vars * v,
 
1194
         int dir,                                       /* AHEAD or BEHIND */
 
1195
         struct state * lp,
 
1196
         struct state * rp)
 
1197
{
 
1198
        assert(dir == AHEAD || dir == BEHIND);
 
1199
        cloneouts(v->nfa, v->wordchrs, lp, rp, dir);
 
1200
        /* (no need for special attention to \n) */
 
1201
}
 
1202
 
 
1203
/*
 
1204
 * scannum - scan a number
 
1205
 */
 
1206
static int                                              /* value, <= DUPMAX */
 
1207
scannum(struct vars * v)
 
1208
{
 
1209
        int                     n = 0;
 
1210
 
 
1211
        while (SEE(DIGIT) && n < DUPMAX)
 
1212
        {
 
1213
                n = n * 10 + v->nextvalue;
 
1214
                NEXT();
 
1215
        }
 
1216
        if (SEE(DIGIT) || n > DUPMAX)
 
1217
        {
 
1218
                ERR(REG_BADBR);
 
1219
                return 0;
 
1220
        }
 
1221
        return n;
 
1222
}
 
1223
 
 
1224
/*
 
1225
 * repeat - replicate subNFA for quantifiers
 
1226
 *
 
1227
 * The duplication sequences used here are chosen carefully so that any
 
1228
 * pointers starting out pointing into the subexpression end up pointing into
 
1229
 * the last occurrence.  (Note that it may not be strung between the same
 
1230
 * left and right end states, however!)  This used to be important for the
 
1231
 * subRE tree, although the important bits are now handled by the in-line
 
1232
 * code in parse(), and when this is called, it doesn't matter any more.
 
1233
 */
 
1234
static void
 
1235
repeat(struct vars * v,
 
1236
           struct state * lp,
 
1237
           struct state * rp,
 
1238
           int m,
 
1239
           int n)
 
1240
{
 
1241
#define  SOME    2
 
1242
#define  INF 3
 
1243
#define  PAIR(x, y)  ((x)*4 + (y))
 
1244
#define  REDUCE(x)       ( ((x) == INFINITY) ? INF : (((x) > 1) ? SOME : (x)) )
 
1245
        const int       rm = REDUCE(m);
 
1246
        const int       rn = REDUCE(n);
 
1247
        struct state *s;
 
1248
        struct state *s2;
 
1249
 
 
1250
        switch (PAIR(rm, rn))
 
1251
        {
 
1252
                case PAIR(0, 0):                /* empty string */
 
1253
                        delsub(v->nfa, lp, rp);
 
1254
                        EMPTYARC(lp, rp);
 
1255
                        break;
 
1256
                case PAIR(0, 1):                /* do as x| */
 
1257
                        EMPTYARC(lp, rp);
 
1258
                        break;
 
1259
                case PAIR(0, SOME):             /* do as x{1,n}| */
 
1260
                        repeat(v, lp, rp, 1, n);
 
1261
                        NOERR();
 
1262
                        EMPTYARC(lp, rp);
 
1263
                        break;
 
1264
                case PAIR(0, INF):              /* loop x around */
 
1265
                        s = newstate(v->nfa);
 
1266
                        NOERR();
 
1267
                        moveouts(v->nfa, lp, s);
 
1268
                        moveins(v->nfa, rp, s);
 
1269
                        EMPTYARC(lp, s);
 
1270
                        EMPTYARC(s, rp);
 
1271
                        break;
 
1272
                case PAIR(1, 1):                /* no action required */
 
1273
                        break;
 
1274
                case PAIR(1, SOME):             /* do as x{0,n-1}x = (x{1,n-1}|)x */
 
1275
                        s = newstate(v->nfa);
 
1276
                        NOERR();
 
1277
                        moveouts(v->nfa, lp, s);
 
1278
                        dupnfa(v->nfa, s, rp, lp, s);
 
1279
                        NOERR();
 
1280
                        repeat(v, lp, s, 1, n - 1);
 
1281
                        NOERR();
 
1282
                        EMPTYARC(lp, s);
 
1283
                        break;
 
1284
                case PAIR(1, INF):              /* add loopback arc */
 
1285
                        s = newstate(v->nfa);
 
1286
                        s2 = newstate(v->nfa);
 
1287
                        NOERR();
 
1288
                        moveouts(v->nfa, lp, s);
 
1289
                        moveins(v->nfa, rp, s2);
 
1290
                        EMPTYARC(lp, s);
 
1291
                        EMPTYARC(s2, rp);
 
1292
                        EMPTYARC(s2, s);
 
1293
                        break;
 
1294
                case PAIR(SOME, SOME):  /* do as x{m-1,n-1}x */
 
1295
                        s = newstate(v->nfa);
 
1296
                        NOERR();
 
1297
                        moveouts(v->nfa, lp, s);
 
1298
                        dupnfa(v->nfa, s, rp, lp, s);
 
1299
                        NOERR();
 
1300
                        repeat(v, lp, s, m - 1, n - 1);
 
1301
                        break;
 
1302
                case PAIR(SOME, INF):   /* do as x{m-1,}x */
 
1303
                        s = newstate(v->nfa);
 
1304
                        NOERR();
 
1305
                        moveouts(v->nfa, lp, s);
 
1306
                        dupnfa(v->nfa, s, rp, lp, s);
 
1307
                        NOERR();
 
1308
                        repeat(v, lp, s, m - 1, n);
 
1309
                        break;
 
1310
                default:
 
1311
                        ERR(REG_ASSERT);
 
1312
                        break;
 
1313
        }
 
1314
}
 
1315
 
 
1316
/*
 
1317
 * bracket - handle non-complemented bracket expression
 
1318
 * Also called from cbracket for complemented bracket expressions.
 
1319
 */
 
1320
static void
 
1321
bracket(struct vars * v,
 
1322
                struct state * lp,
 
1323
                struct state * rp)
 
1324
{
 
1325
        assert(SEE('['));
 
1326
        NEXT();
 
1327
        while (!SEE(']') && !SEE(EOS))
 
1328
                brackpart(v, lp, rp);
 
1329
        assert(SEE(']') || ISERR());
 
1330
        okcolors(v->nfa, v->cm);
 
1331
}
 
1332
 
 
1333
/*
 
1334
 * cbracket - handle complemented bracket expression
 
1335
 * We do it by calling bracket() with dummy endpoints, and then complementing
 
1336
 * the result.  The alternative would be to invoke rainbow(), and then delete
 
1337
 * arcs as the b.e. is seen... but that gets messy.
 
1338
 */
 
1339
static void
 
1340
cbracket(struct vars * v,
 
1341
                 struct state * lp,
 
1342
                 struct state * rp)
 
1343
{
 
1344
        struct state *left = newstate(v->nfa);
 
1345
        struct state *right = newstate(v->nfa);
 
1346
        struct state *s;
 
1347
        struct arc *a;                          /* arc from lp */
 
1348
        struct arc *ba;                         /* arc from left, from bracket() */
 
1349
        struct arc *pa;                         /* MCCE-prototype arc */
 
1350
        color           co;
 
1351
        chr                *p;
 
1352
        int                     i;
 
1353
 
 
1354
        NOERR();
 
1355
        bracket(v, left, right);
 
1356
        if (v->cflags & REG_NLSTOP)
 
1357
                newarc(v->nfa, PLAIN, v->nlcolor, left, right);
 
1358
        NOERR();
 
1359
 
 
1360
        assert(lp->nouts == 0);         /* all outarcs will be ours */
 
1361
 
 
1362
        /* easy part of complementing */
 
1363
        colorcomplement(v->nfa, v->cm, PLAIN, left, lp, rp);
 
1364
        NOERR();
 
1365
        if (v->mcces == NULL)
 
1366
        {                                                       /* no MCCEs -- we're done */
 
1367
                dropstate(v->nfa, left);
 
1368
                assert(right->nins == 0);
 
1369
                freestate(v->nfa, right);
 
1370
                return;
 
1371
        }
 
1372
 
 
1373
        /* but complementing gets messy in the presence of MCCEs... */
 
1374
        NOTE(REG_ULOCALE);
 
1375
        for (p = v->mcces->chrs, i = v->mcces->nchrs; i > 0; p++, i--)
 
1376
        {
 
1377
                co = GETCOLOR(v->cm, *p);
 
1378
                a = findarc(lp, PLAIN, co);
 
1379
                ba = findarc(left, PLAIN, co);
 
1380
                if (ba == NULL)
 
1381
                {
 
1382
                        assert(a != NULL);
 
1383
                        freearc(v->nfa, a);
 
1384
                }
 
1385
                else
 
1386
                        assert(a == NULL);
 
1387
                s = newstate(v->nfa);
 
1388
                NOERR();
 
1389
                newarc(v->nfa, PLAIN, co, lp, s);
 
1390
                NOERR();
 
1391
                pa = findarc(v->mccepbegin, PLAIN, co);
 
1392
                assert(pa != NULL);
 
1393
                if (ba == NULL)
 
1394
                {                                               /* easy case, need all of them */
 
1395
                        cloneouts(v->nfa, pa->to, s, rp, PLAIN);
 
1396
                        newarc(v->nfa, '$', 1, s, rp);
 
1397
                        newarc(v->nfa, '$', 0, s, rp);
 
1398
                        colorcomplement(v->nfa, v->cm, AHEAD, pa->to, s, rp);
 
1399
                }
 
1400
                else
 
1401
                {                                               /* must be selective */
 
1402
                        if (findarc(ba->to, '$', 1) == NULL)
 
1403
                        {
 
1404
                                newarc(v->nfa, '$', 1, s, rp);
 
1405
                                newarc(v->nfa, '$', 0, s, rp);
 
1406
                                colorcomplement(v->nfa, v->cm, AHEAD, pa->to,
 
1407
                                                                s, rp);
 
1408
                        }
 
1409
                        for (pa = pa->to->outs; pa != NULL; pa = pa->outchain)
 
1410
                                if (findarc(ba->to, PLAIN, pa->co) == NULL)
 
1411
                                        newarc(v->nfa, PLAIN, pa->co, s, rp);
 
1412
                        if (s->nouts == 0)      /* limit of selectivity: none */
 
1413
                                dropstate(v->nfa, s);   /* frees arc too */
 
1414
                }
 
1415
                NOERR();
 
1416
        }
 
1417
 
 
1418
        delsub(v->nfa, left, right);
 
1419
        assert(left->nouts == 0);
 
1420
        freestate(v->nfa, left);
 
1421
        assert(right->nins == 0);
 
1422
        freestate(v->nfa, right);
 
1423
}
 
1424
 
 
1425
/*
 
1426
 * brackpart - handle one item (or range) within a bracket expression
 
1427
 */
 
1428
static void
 
1429
brackpart(struct vars * v,
 
1430
                  struct state * lp,
 
1431
                  struct state * rp)
 
1432
{
 
1433
        celt            startc;
 
1434
        celt            endc;
 
1435
        struct cvec *cv;
 
1436
        chr                *startp;
 
1437
        chr                *endp;
 
1438
        chr                     c[1];
 
1439
 
 
1440
        /* parse something, get rid of special cases, take shortcuts */
 
1441
        switch (v->nexttype)
 
1442
        {
 
1443
                case RANGE:                             /* a-b-c or other botch */
 
1444
                        ERR(REG_ERANGE);
 
1445
                        return;
 
1446
                        break;
 
1447
                case PLAIN:
 
1448
                        c[0] = v->nextvalue;
 
1449
                        NEXT();
 
1450
                        /* shortcut for ordinary chr (not range, not MCCE leader) */
 
1451
                        if (!SEE(RANGE) && !ISCELEADER(v, c[0]))
 
1452
                        {
 
1453
                                onechr(v, c[0], lp, rp);
 
1454
                                return;
 
1455
                        }
 
1456
                        startc = element(v, c, c + 1);
 
1457
                        NOERR();
 
1458
                        break;
 
1459
                case COLLEL:
 
1460
                        startp = v->now;
 
1461
                        endp = scanplain(v);
 
1462
                        INSIST(startp < endp, REG_ECOLLATE);
 
1463
                        NOERR();
 
1464
                        startc = element(v, startp, endp);
 
1465
                        NOERR();
 
1466
                        break;
 
1467
                case ECLASS:
 
1468
                        startp = v->now;
 
1469
                        endp = scanplain(v);
 
1470
                        INSIST(startp < endp, REG_ECOLLATE);
 
1471
                        NOERR();
 
1472
                        startc = element(v, startp, endp);
 
1473
                        NOERR();
 
1474
                        cv = eclass(v, startc, (v->cflags & REG_ICASE));
 
1475
                        NOERR();
 
1476
                        dovec(v, cv, lp, rp);
 
1477
                        return;
 
1478
                        break;
 
1479
                case CCLASS:
 
1480
                        startp = v->now;
 
1481
                        endp = scanplain(v);
 
1482
                        INSIST(startp < endp, REG_ECTYPE);
 
1483
                        NOERR();
 
1484
                        cv = cclass(v, startp, endp, (v->cflags & REG_ICASE));
 
1485
                        NOERR();
 
1486
                        dovec(v, cv, lp, rp);
 
1487
                        return;
 
1488
                        break;
 
1489
                default:
 
1490
                        ERR(REG_ASSERT);
 
1491
                        return;
 
1492
                        break;
 
1493
        }
 
1494
 
 
1495
        if (SEE(RANGE))
 
1496
        {
 
1497
                NEXT();
 
1498
                switch (v->nexttype)
 
1499
                {
 
1500
                        case PLAIN:
 
1501
                        case RANGE:
 
1502
                                c[0] = v->nextvalue;
 
1503
                                NEXT();
 
1504
                                endc = element(v, c, c + 1);
 
1505
                                NOERR();
 
1506
                                break;
 
1507
                        case COLLEL:
 
1508
                                startp = v->now;
 
1509
                                endp = scanplain(v);
 
1510
                                INSIST(startp < endp, REG_ECOLLATE);
 
1511
                                NOERR();
 
1512
                                endc = element(v, startp, endp);
 
1513
                                NOERR();
 
1514
                                break;
 
1515
                        default:
 
1516
                                ERR(REG_ERANGE);
 
1517
                                return;
 
1518
                                break;
 
1519
                }
 
1520
        }
 
1521
        else
 
1522
                endc = startc;
 
1523
 
 
1524
        /*
 
1525
         * Ranges are unportable.  Actually, standard C does guarantee that
 
1526
         * digits are contiguous, but making that an exception is just too
 
1527
         * complicated.
 
1528
         */
 
1529
        if (startc != endc)
 
1530
                NOTE(REG_UUNPORT);
 
1531
        cv = range(v, startc, endc, (v->cflags & REG_ICASE));
 
1532
        NOERR();
 
1533
        dovec(v, cv, lp, rp);
 
1534
}
 
1535
 
 
1536
/*
 
1537
 * scanplain - scan PLAIN contents of [. etc.
 
1538
 *
 
1539
 * Certain bits of trickery in lex.c know that this code does not try
 
1540
 * to look past the final bracket of the [. etc.
 
1541
 */
 
1542
static chr *                                    /* just after end of sequence */
 
1543
scanplain(struct vars * v)
 
1544
{
 
1545
        chr                *endp;
 
1546
 
 
1547
        assert(SEE(COLLEL) || SEE(ECLASS) || SEE(CCLASS));
 
1548
        NEXT();
 
1549
 
 
1550
        endp = v->now;
 
1551
        while (SEE(PLAIN))
 
1552
        {
 
1553
                endp = v->now;
 
1554
                NEXT();
 
1555
        }
 
1556
 
 
1557
        assert(SEE(END) || ISERR());
 
1558
        NEXT();
 
1559
 
 
1560
        return endp;
 
1561
}
 
1562
 
 
1563
/*
 
1564
 * leaders - process a cvec of collating elements to also include leaders
 
1565
 * Also gives all characters involved their own colors, which is almost
 
1566
 * certainly necessary, and sets up little disconnected subNFA.
 
1567
 */
 
1568
static void
 
1569
leaders(struct vars * v,
 
1570
                struct cvec * cv)
 
1571
{
 
1572
        int                     mcce;
 
1573
        chr                *p;
 
1574
        chr                     leader;
 
1575
        struct state *s;
 
1576
        struct arc *a;
 
1577
 
 
1578
        v->mccepbegin = newstate(v->nfa);
 
1579
        v->mccepend = newstate(v->nfa);
 
1580
        NOERR();
 
1581
 
 
1582
        for (mcce = 0; mcce < cv->nmcces; mcce++)
 
1583
        {
 
1584
                p = cv->mcces[mcce];
 
1585
                leader = *p;
 
1586
                if (!haschr(cv, leader))
 
1587
                {
 
1588
                        addchr(cv, leader);
 
1589
                        s = newstate(v->nfa);
 
1590
                        newarc(v->nfa, PLAIN, subcolor(v->cm, leader),
 
1591
                                   v->mccepbegin, s);
 
1592
                        okcolors(v->nfa, v->cm);
 
1593
                }
 
1594
                else
 
1595
                {
 
1596
                        a = findarc(v->mccepbegin, PLAIN,
 
1597
                                                GETCOLOR(v->cm, leader));
 
1598
                        assert(a != NULL);
 
1599
                        s = a->to;
 
1600
                        assert(s != v->mccepend);
 
1601
                }
 
1602
                p++;
 
1603
                assert(*p != 0 && *(p + 1) == 0);               /* only 2-char MCCEs for
 
1604
                                                                                                 * now */
 
1605
                newarc(v->nfa, PLAIN, subcolor(v->cm, *p), s, v->mccepend);
 
1606
                okcolors(v->nfa, v->cm);
 
1607
        }
 
1608
}
 
1609
 
 
1610
/*
 
1611
 * onechr - fill in arcs for a plain character, and possible case complements
 
1612
 * This is mostly a shortcut for efficient handling of the common case.
 
1613
 */
 
1614
static void
 
1615
onechr(struct vars * v,
 
1616
           chr c,
 
1617
           struct state * lp,
 
1618
           struct state * rp)
 
1619
{
 
1620
        if (!(v->cflags & REG_ICASE))
 
1621
        {
 
1622
                newarc(v->nfa, PLAIN, subcolor(v->cm, c), lp, rp);
 
1623
                return;
 
1624
        }
 
1625
 
 
1626
        /* rats, need general case anyway... */
 
1627
        dovec(v, allcases(v, c), lp, rp);
 
1628
}
 
1629
 
 
1630
/*
 
1631
 * dovec - fill in arcs for each element of a cvec
 
1632
 * This one has to handle the messy cases, like MCCEs and MCCE leaders.
 
1633
 */
 
1634
static void
 
1635
dovec(struct vars * v,
 
1636
          struct cvec * cv,
 
1637
          struct state * lp,
 
1638
          struct state * rp)
 
1639
{
 
1640
        chr                     ch,
 
1641
                                from,
 
1642
                                to;
 
1643
        celt            ce;
 
1644
        chr                *p;
 
1645
        int                     i;
 
1646
        color           co;
 
1647
        struct cvec *leads;
 
1648
        struct arc *a;
 
1649
        struct arc *pa;                         /* arc in prototype */
 
1650
        struct state *s;
 
1651
        struct state *ps;                       /* state in prototype */
 
1652
 
 
1653
        /* need a place to store leaders, if any */
 
1654
        if (nmcces(v) > 0)
 
1655
        {
 
1656
                assert(v->mcces != NULL);
 
1657
                if (v->cv2 == NULL || v->cv2->nchrs < v->mcces->nchrs)
 
1658
                {
 
1659
                        if (v->cv2 != NULL)
 
1660
                                free(v->cv2);
 
1661
                        v->cv2 = newcvec(v->mcces->nchrs, 0, v->mcces->nmcces);
 
1662
                        NOERR();
 
1663
                        leads = v->cv2;
 
1664
                }
 
1665
                else
 
1666
                        leads = clearcvec(v->cv2);
 
1667
        }
 
1668
        else
 
1669
                leads = NULL;
 
1670
 
 
1671
        /* first, get the ordinary characters out of the way */
 
1672
        for (p = cv->chrs, i = cv->nchrs; i > 0; p++, i--)
 
1673
        {
 
1674
                ch = *p;
 
1675
                if (!ISCELEADER(v, ch))
 
1676
                        newarc(v->nfa, PLAIN, subcolor(v->cm, ch), lp, rp);
 
1677
                else
 
1678
                {
 
1679
                        assert(singleton(v->cm, ch));
 
1680
                        assert(leads != NULL);
 
1681
                        if (!haschr(leads, ch))
 
1682
                                addchr(leads, ch);
 
1683
                }
 
1684
        }
 
1685
 
 
1686
        /* and the ranges */
 
1687
        for (p = cv->ranges, i = cv->nranges; i > 0; p += 2, i--)
 
1688
        {
 
1689
                from = *p;
 
1690
                to = *(p + 1);
 
1691
                while (from <= to && (ce = nextleader(v, from, to)) != NOCELT)
 
1692
                {
 
1693
                        if (from < ce)
 
1694
                                subrange(v, from, ce - 1, lp, rp);
 
1695
                        assert(singleton(v->cm, ce));
 
1696
                        assert(leads != NULL);
 
1697
                        if (!haschr(leads, ce))
 
1698
                                addchr(leads, ce);
 
1699
                        from = ce + 1;
 
1700
                }
 
1701
                if (from <= to)
 
1702
                        subrange(v, from, to, lp, rp);
 
1703
        }
 
1704
 
 
1705
        if ((leads == NULL || leads->nchrs == 0) && cv->nmcces == 0)
 
1706
                return;
 
1707
 
 
1708
        /* deal with the MCCE leaders */
 
1709
        NOTE(REG_ULOCALE);
 
1710
        for (p = leads->chrs, i = leads->nchrs; i > 0; p++, i--)
 
1711
        {
 
1712
                co = GETCOLOR(v->cm, *p);
 
1713
                a = findarc(lp, PLAIN, co);
 
1714
                if (a != NULL)
 
1715
                        s = a->to;
 
1716
                else
 
1717
                {
 
1718
                        s = newstate(v->nfa);
 
1719
                        NOERR();
 
1720
                        newarc(v->nfa, PLAIN, co, lp, s);
 
1721
                        NOERR();
 
1722
                }
 
1723
                pa = findarc(v->mccepbegin, PLAIN, co);
 
1724
                assert(pa != NULL);
 
1725
                ps = pa->to;
 
1726
                newarc(v->nfa, '$', 1, s, rp);
 
1727
                newarc(v->nfa, '$', 0, s, rp);
 
1728
                colorcomplement(v->nfa, v->cm, AHEAD, ps, s, rp);
 
1729
                NOERR();
 
1730
        }
 
1731
 
 
1732
        /* and the MCCEs */
 
1733
        for (i = 0; i < cv->nmcces; i++)
 
1734
        {
 
1735
                p = cv->mcces[i];
 
1736
                assert(singleton(v->cm, *p));
 
1737
                if (!singleton(v->cm, *p))
 
1738
                {
 
1739
                        ERR(REG_ASSERT);
 
1740
                        return;
 
1741
                }
 
1742
                ch = *p++;
 
1743
                co = GETCOLOR(v->cm, ch);
 
1744
                a = findarc(lp, PLAIN, co);
 
1745
                if (a != NULL)
 
1746
                        s = a->to;
 
1747
                else
 
1748
                {
 
1749
                        s = newstate(v->nfa);
 
1750
                        NOERR();
 
1751
                        newarc(v->nfa, PLAIN, co, lp, s);
 
1752
                        NOERR();
 
1753
                }
 
1754
                assert(*p != 0);                /* at least two chars */
 
1755
                assert(singleton(v->cm, *p));
 
1756
                ch = *p++;
 
1757
                co = GETCOLOR(v->cm, ch);
 
1758
                assert(*p == 0);                /* and only two, for now */
 
1759
                newarc(v->nfa, PLAIN, co, s, rp);
 
1760
                NOERR();
 
1761
        }
 
1762
}
 
1763
 
 
1764
/*
 
1765
 * nextleader - find next MCCE leader within range
 
1766
 */
 
1767
static celt                                             /* NOCELT means none */
 
1768
nextleader(struct vars * v,
 
1769
                   chr from,
 
1770
                   chr to)
 
1771
{
 
1772
        int                     i;
 
1773
        chr                *p;
 
1774
        chr                     ch;
 
1775
        celt            it = NOCELT;
 
1776
 
 
1777
        if (v->mcces == NULL)
 
1778
                return it;
 
1779
 
 
1780
        for (i = v->mcces->nchrs, p = v->mcces->chrs; i > 0; i--, p++)
 
1781
        {
 
1782
                ch = *p;
 
1783
                if (from <= ch && ch <= to)
 
1784
                        if (it == NOCELT || ch < it)
 
1785
                                it = ch;
 
1786
        }
 
1787
        return it;
 
1788
}
 
1789
 
 
1790
/*
 
1791
 * wordchrs - set up word-chr list for word-boundary stuff, if needed
 
1792
 *
 
1793
 * The list is kept as a bunch of arcs between two dummy states; it's
 
1794
 * disposed of by the unreachable-states sweep in NFA optimization.
 
1795
 * Does NEXT().  Must not be called from any unusual lexical context.
 
1796
 * This should be reconciled with the \w etc. handling in lex.c, and
 
1797
 * should be cleaned up to reduce dependencies on input scanning.
 
1798
 */
 
1799
static void
 
1800
wordchrs(struct vars * v)
 
1801
{
 
1802
        struct state *left;
 
1803
        struct state *right;
 
1804
 
 
1805
        if (v->wordchrs != NULL)
 
1806
        {
 
1807
                NEXT();                                 /* for consistency */
 
1808
                return;
 
1809
        }
 
1810
 
 
1811
        left = newstate(v->nfa);
 
1812
        right = newstate(v->nfa);
 
1813
        NOERR();
 
1814
        /* fine point:  implemented with [::], and lexer will set REG_ULOCALE */
 
1815
        lexword(v);
 
1816
        NEXT();
 
1817
        assert(v->savenow != NULL && SEE('['));
 
1818
        bracket(v, left, right);
 
1819
        assert((v->savenow != NULL && SEE(']')) || ISERR());
 
1820
        NEXT();
 
1821
        NOERR();
 
1822
        v->wordchrs = left;
 
1823
}
 
1824
 
 
1825
/*
 
1826
 * subre - allocate a subre
 
1827
 */
 
1828
static struct subre *
 
1829
subre(struct vars * v,
 
1830
          int op,
 
1831
          int flags,
 
1832
          struct state * begin,
 
1833
          struct state * end)
 
1834
{
 
1835
        struct subre *ret;
 
1836
 
 
1837
        ret = v->treefree;
 
1838
        if (ret != NULL)
 
1839
                v->treefree = ret->left;
 
1840
        else
 
1841
        {
 
1842
                ret = (struct subre *) MALLOC(sizeof(struct subre));
 
1843
                if (ret == NULL)
 
1844
                {
 
1845
                        ERR(REG_ESPACE);
 
1846
                        return NULL;
 
1847
                }
 
1848
                ret->chain = v->treechain;
 
1849
                v->treechain = ret;
 
1850
        }
 
1851
 
 
1852
        assert(strchr("|.b(=", op) != NULL);
 
1853
 
 
1854
        ret->op = op;
 
1855
        ret->flags = flags;
 
1856
        ret->retry = 0;
 
1857
        ret->subno = 0;
 
1858
        ret->min = ret->max = 1;
 
1859
        ret->left = NULL;
 
1860
        ret->right = NULL;
 
1861
        ret->begin = begin;
 
1862
        ret->end = end;
 
1863
        ZAPCNFA(ret->cnfa);
 
1864
 
 
1865
        return ret;
 
1866
}
 
1867
 
 
1868
/*
 
1869
 * freesubre - free a subRE subtree
 
1870
 */
 
1871
static void
 
1872
freesubre(struct vars * v,              /* might be NULL */
 
1873
                  struct subre * sr)
 
1874
{
 
1875
        if (sr == NULL)
 
1876
                return;
 
1877
 
 
1878
        if (sr->left != NULL)
 
1879
                freesubre(v, sr->left);
 
1880
        if (sr->right != NULL)
 
1881
                freesubre(v, sr->right);
 
1882
 
 
1883
        freesrnode(v, sr);
 
1884
}
 
1885
 
 
1886
/*
 
1887
 * freesrnode - free one node in a subRE subtree
 
1888
 */
 
1889
static void
 
1890
freesrnode(struct vars * v,             /* might be NULL */
 
1891
                   struct subre * sr)
 
1892
{
 
1893
        if (sr == NULL)
 
1894
                return;
 
1895
 
 
1896
        if (!NULLCNFA(sr->cnfa))
 
1897
                freecnfa(&sr->cnfa);
 
1898
        sr->flags = 0;
 
1899
 
 
1900
        if (v != NULL)
 
1901
        {
 
1902
                sr->left = v->treefree;
 
1903
                v->treefree = sr;
 
1904
        }
 
1905
        else
 
1906
                FREE(sr);
 
1907
}
 
1908
 
 
1909
/*
 
1910
 * optst - optimize a subRE subtree
 
1911
 */
 
1912
static void
 
1913
optst(struct vars * v,
 
1914
          struct subre * t)
 
1915
{
 
1916
        if (t == NULL)
 
1917
                return;
 
1918
 
 
1919
        /* recurse through children */
 
1920
        if (t->left != NULL)
 
1921
                optst(v, t->left);
 
1922
        if (t->right != NULL)
 
1923
                optst(v, t->right);
 
1924
}
 
1925
 
 
1926
/*
 
1927
 * numst - number tree nodes (assigning retry indexes)
 
1928
 */
 
1929
static int                                              /* next number */
 
1930
numst(struct subre * t,
 
1931
          int start)                            /* starting point for subtree numbers */
 
1932
{
 
1933
        int                     i;
 
1934
 
 
1935
        assert(t != NULL);
 
1936
 
 
1937
        i = start;
 
1938
        t->retry = (short) i++;
 
1939
        if (t->left != NULL)
 
1940
                i = numst(t->left, i);
 
1941
        if (t->right != NULL)
 
1942
                i = numst(t->right, i);
 
1943
        return i;
 
1944
}
 
1945
 
 
1946
/*
 
1947
 * markst - mark tree nodes as INUSE
 
1948
 */
 
1949
static void
 
1950
markst(struct subre * t)
 
1951
{
 
1952
        assert(t != NULL);
 
1953
 
 
1954
        t->flags |= INUSE;
 
1955
        if (t->left != NULL)
 
1956
                markst(t->left);
 
1957
        if (t->right != NULL)
 
1958
                markst(t->right);
 
1959
}
 
1960
 
 
1961
/*
 
1962
 * cleanst - free any tree nodes not marked INUSE
 
1963
 */
 
1964
static void
 
1965
cleanst(struct vars * v)
 
1966
{
 
1967
        struct subre *t;
 
1968
        struct subre *next;
 
1969
 
 
1970
        for (t = v->treechain; t != NULL; t = next)
 
1971
        {
 
1972
                next = t->chain;
 
1973
                if (!(t->flags & INUSE))
 
1974
                        FREE(t);
 
1975
        }
 
1976
        v->treechain = NULL;
 
1977
        v->treefree = NULL;                     /* just on general principles */
 
1978
}
 
1979
 
 
1980
/*
 
1981
 * nfatree - turn a subRE subtree into a tree of compacted NFAs
 
1982
 */
 
1983
static long                                             /* optimize results from top node */
 
1984
nfatree(struct vars * v,
 
1985
                struct subre * t,
 
1986
                FILE *f)                                /* for debug output */
 
1987
{
 
1988
        assert(t != NULL && t->begin != NULL);
 
1989
 
 
1990
        if (t->left != NULL)
 
1991
                (DISCARD) nfatree(v, t->left, f);
 
1992
        if (t->right != NULL)
 
1993
                (DISCARD) nfatree(v, t->right, f);
 
1994
 
 
1995
        return nfanode(v, t, f);
 
1996
}
 
1997
 
 
1998
/*
 
1999
 * nfanode - do one NFA for nfatree
 
2000
 */
 
2001
static long                                             /* optimize results */
 
2002
nfanode(struct vars * v,
 
2003
                struct subre * t,
 
2004
                FILE *f)                                /* for debug output */
 
2005
{
 
2006
        struct nfa *nfa;
 
2007
        long            ret = 0;
 
2008
 
 
2009
        assert(t->begin != NULL);
 
2010
 
 
2011
#ifdef REG_DEBUG
 
2012
        if (f != NULL)
 
2013
        {
 
2014
                char            idbuf[50];
 
2015
 
 
2016
                fprintf(f, "\n\n\n========= TREE NODE %s ==========\n",
 
2017
                                stid(t, idbuf, sizeof(idbuf)));
 
2018
        }
 
2019
#endif
 
2020
        nfa = newnfa(v, v->cm, v->nfa);
 
2021
        NOERRZ();
 
2022
        dupnfa(nfa, t->begin, t->end, nfa->init, nfa->final);
 
2023
        if (!ISERR())
 
2024
        {
 
2025
                specialcolors(nfa);
 
2026
                ret = optimize(nfa, f);
 
2027
        }
 
2028
        if (!ISERR())
 
2029
                compact(nfa, &t->cnfa);
 
2030
 
 
2031
        freenfa(nfa);
 
2032
        return ret;
 
2033
}
 
2034
 
 
2035
/*
 
2036
 * newlacon - allocate a lookahead-constraint subRE
 
2037
 */
 
2038
static int                                              /* lacon number */
 
2039
newlacon(struct vars * v,
 
2040
                 struct state * begin,
 
2041
                 struct state * end,
 
2042
                 int pos)
 
2043
{
 
2044
        int                     n;
 
2045
        struct subre *sub;
 
2046
 
 
2047
        if (v->nlacons == 0)
 
2048
        {
 
2049
                v->lacons = (struct subre *) MALLOC(2 * sizeof(struct subre));
 
2050
                n = 1;                                  /* skip 0th */
 
2051
                v->nlacons = 2;
 
2052
        }
 
2053
        else
 
2054
        {
 
2055
                v->lacons = (struct subre *) REALLOC(v->lacons,
 
2056
                                                                (v->nlacons + 1) * sizeof(struct subre));
 
2057
                n = v->nlacons++;
 
2058
        }
 
2059
        if (v->lacons == NULL)
 
2060
        {
 
2061
                ERR(REG_ESPACE);
 
2062
                return 0;
 
2063
        }
 
2064
        sub = &v->lacons[n];
 
2065
        sub->begin = begin;
 
2066
        sub->end = end;
 
2067
        sub->subno = pos;
 
2068
        ZAPCNFA(sub->cnfa);
 
2069
        return n;
 
2070
}
 
2071
 
 
2072
/*
 
2073
 * freelacons - free lookahead-constraint subRE vector
 
2074
 */
 
2075
static void
 
2076
freelacons(struct subre * subs,
 
2077
                   int n)
 
2078
{
 
2079
        struct subre *sub;
 
2080
        int                     i;
 
2081
 
 
2082
        assert(n > 0);
 
2083
        for (sub = subs + 1, i = n - 1; i > 0; sub++, i--)      /* no 0th */
 
2084
                if (!NULLCNFA(sub->cnfa))
 
2085
                        freecnfa(&sub->cnfa);
 
2086
        FREE(subs);
 
2087
}
 
2088
 
 
2089
/*
 
2090
 * rfree - free a whole RE (insides of regfree)
 
2091
 */
 
2092
static void
 
2093
rfree(regex_t *re)
 
2094
{
 
2095
        struct guts *g;
 
2096
 
 
2097
        if (re == NULL || re->re_magic != REMAGIC)
 
2098
                return;
 
2099
 
 
2100
        re->re_magic = 0;                       /* invalidate RE */
 
2101
        g = (struct guts *) re->re_guts;
 
2102
        re->re_guts = NULL;
 
2103
        re->re_fns = NULL;
 
2104
        g->magic = 0;
 
2105
        freecm(&g->cmap);
 
2106
        if (g->tree != NULL)
 
2107
                freesubre((struct vars *) NULL, g->tree);
 
2108
        if (g->lacons != NULL)
 
2109
                freelacons(g->lacons, g->nlacons);
 
2110
        if (!NULLCNFA(g->search))
 
2111
                freecnfa(&g->search);
 
2112
        FREE(g);
 
2113
}
 
2114
 
 
2115
#ifdef REG_DEBUG
 
2116
 
 
2117
/*
 
2118
 * dump - dump an RE in human-readable form
 
2119
 */
 
2120
static void
 
2121
dump(regex_t *re,
 
2122
         FILE *f)
 
2123
{
 
2124
        struct guts *g;
 
2125
        int                     i;
 
2126
 
 
2127
        if (re->re_magic != REMAGIC)
 
2128
                fprintf(f, "bad magic number (0x%x not 0x%x)\n", re->re_magic,
 
2129
                                REMAGIC);
 
2130
        if (re->re_guts == NULL)
 
2131
        {
 
2132
                fprintf(f, "NULL guts!!!\n");
 
2133
                return;
 
2134
        }
 
2135
        g = (struct guts *) re->re_guts;
 
2136
        if (g->magic != GUTSMAGIC)
 
2137
                fprintf(f, "bad guts magic number (0x%x not 0x%x)\n", g->magic,
 
2138
                                GUTSMAGIC);
 
2139
 
 
2140
        fprintf(f, "\n\n\n========= DUMP ==========\n");
 
2141
        fprintf(f, "nsub %d, info 0%lo, csize %d, ntree %d\n",
 
2142
                        re->re_nsub, re->re_info, re->re_csize, g->ntree);
 
2143
 
 
2144
        dumpcolors(&g->cmap, f);
 
2145
        if (!NULLCNFA(g->search))
 
2146
        {
 
2147
                printf("\nsearch:\n");
 
2148
                dumpcnfa(&g->search, f);
 
2149
        }
 
2150
        for (i = 1; i < g->nlacons; i++)
 
2151
        {
 
2152
                fprintf(f, "\nla%d (%s):\n", i,
 
2153
                                (g->lacons[i].subno) ? "positive" : "negative");
 
2154
                dumpcnfa(&g->lacons[i].cnfa, f);
 
2155
        }
 
2156
        fprintf(f, "\n");
 
2157
        dumpst(g->tree, f, 0);
 
2158
}
 
2159
 
 
2160
/*
 
2161
 * dumpst - dump a subRE tree
 
2162
 */
 
2163
static void
 
2164
dumpst(struct subre * t,
 
2165
           FILE *f,
 
2166
           int nfapresent)                      /* is the original NFA still around? */
 
2167
{
 
2168
        if (t == NULL)
 
2169
                fprintf(f, "null tree\n");
 
2170
        else
 
2171
                stdump(t, f, nfapresent);
 
2172
        fflush(f);
 
2173
}
 
2174
 
 
2175
/*
 
2176
 * stdump - recursive guts of dumpst
 
2177
 */
 
2178
static void
 
2179
stdump(struct subre * t,
 
2180
           FILE *f,
 
2181
           int nfapresent)                      /* is the original NFA still around? */
 
2182
{
 
2183
        char            idbuf[50];
 
2184
 
 
2185
        fprintf(f, "%s. `%c'", stid(t, idbuf, sizeof(idbuf)), t->op);
 
2186
        if (t->flags & LONGER)
 
2187
                fprintf(f, " longest");
 
2188
        if (t->flags & SHORTER)
 
2189
                fprintf(f, " shortest");
 
2190
        if (t->flags & MIXED)
 
2191
                fprintf(f, " hasmixed");
 
2192
        if (t->flags & CAP)
 
2193
                fprintf(f, " hascapture");
 
2194
        if (t->flags & BACKR)
 
2195
                fprintf(f, " hasbackref");
 
2196
        if (!(t->flags & INUSE))
 
2197
                fprintf(f, " UNUSED");
 
2198
        if (t->subno != 0)
 
2199
                fprintf(f, " (#%d)", t->subno);
 
2200
        if (t->min != 1 || t->max != 1)
 
2201
        {
 
2202
                fprintf(f, " {%d,", t->min);
 
2203
                if (t->max != INFINITY)
 
2204
                        fprintf(f, "%d", t->max);
 
2205
                fprintf(f, "}");
 
2206
        }
 
2207
        if (nfapresent)
 
2208
                fprintf(f, " %ld-%ld", (long) t->begin->no, (long) t->end->no);
 
2209
        if (t->left != NULL)
 
2210
                fprintf(f, " L:%s", stid(t->left, idbuf, sizeof(idbuf)));
 
2211
        if (t->right != NULL)
 
2212
                fprintf(f, " R:%s", stid(t->right, idbuf, sizeof(idbuf)));
 
2213
        if (!NULLCNFA(t->cnfa))
 
2214
        {
 
2215
                fprintf(f, "\n");
 
2216
                dumpcnfa(&t->cnfa, f);
 
2217
                fprintf(f, "\n");
 
2218
        }
 
2219
        if (t->left != NULL)
 
2220
                stdump(t->left, f, nfapresent);
 
2221
        if (t->right != NULL)
 
2222
                stdump(t->right, f, nfapresent);
 
2223
}
 
2224
 
 
2225
/*
 
2226
 * stid - identify a subtree node for dumping
 
2227
 */
 
2228
static char *                                   /* points to buf or constant string */
 
2229
stid(struct subre * t,
 
2230
         char *buf,
 
2231
         size_t bufsize)
 
2232
{
 
2233
        /* big enough for hex int or decimal t->retry? */
 
2234
        if (bufsize < sizeof(void *) * 2 + 3 || bufsize < sizeof(t->retry) * 3 + 1)
 
2235
                return "unable";
 
2236
        if (t->retry != 0)
 
2237
                sprintf(buf, "%d", t->retry);
 
2238
        else
 
2239
                sprintf(buf, "%p", t);
 
2240
        return buf;
 
2241
}
 
2242
#endif   /* REG_DEBUG */
 
2243
 
 
2244
 
 
2245
#include "regc_lex.c"
 
2246
#include "regc_color.c"
 
2247
#include "regc_nfa.c"
 
2248
#include "regc_cvec.c"
 
2249
#include "regc_locale.c"