Coverage Report

Created: 2026-10-16 06:48

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/postgres/src/backend/regex/regc_nfa.c
Line
Count
Source
1
/*
2
 * NFA utilities.
3
 * This file is #included by regcomp.c.
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
 * src/backend/regex/regc_nfa.c
32
 *
33
 *
34
 * One or two things that technically ought to be in here
35
 * are actually in color.c, thanks to some incestuous relationships in
36
 * the color chains.
37
 */
38
39
0
#define NISERR()  VISERR(nfa->v)
40
0
#define NERR(e)   VERR(nfa->v, (e))
41
42
43
/*
44
 * newnfa - set up an NFA
45
 */
46
static struct nfa *       /* the NFA, or NULL */
47
newnfa(struct vars *v,
48
     struct colormap *cm,
49
     struct nfa *parent)    /* NULL if primary NFA */
50
0
{
51
0
  struct nfa *nfa;
52
53
0
  nfa = (struct nfa *) MALLOC(sizeof(struct nfa));
54
0
  if (nfa == NULL)
55
0
  {
56
0
    ERR(REG_ESPACE);
57
0
    return NULL;
58
0
  }
59
60
  /* Make the NFA minimally valid, so freenfa() will behave sanely */
61
0
  nfa->states = NULL;
62
0
  nfa->slast = NULL;
63
0
  nfa->freestates = NULL;
64
0
  nfa->freearcs = NULL;
65
0
  nfa->lastsb = NULL;
66
0
  nfa->lastab = NULL;
67
0
  nfa->lastsbused = 0;
68
0
  nfa->lastabused = 0;
69
0
  nfa->nstates = 0;
70
0
  nfa->cm = cm;
71
0
  nfa->v = v;
72
0
  nfa->bos[0] = nfa->bos[1] = COLORLESS;
73
0
  nfa->eos[0] = nfa->eos[1] = COLORLESS;
74
0
  nfa->flags = 0;
75
0
  nfa->minmatchall = nfa->maxmatchall = -1;
76
0
  nfa->parent = parent;   /* Precedes newfstate so parent is valid. */
77
78
  /* Create required infrastructure */
79
0
  nfa->post = newfstate(nfa, '@');  /* number 0 */
80
0
  nfa->pre = newfstate(nfa, '>'); /* number 1 */
81
0
  nfa->init = newstate(nfa);  /* may become invalid later */
82
0
  nfa->final = newstate(nfa);
83
0
  if (ISERR())
84
0
  {
85
0
    freenfa(nfa);
86
0
    return NULL;
87
0
  }
88
0
  rainbow(nfa, nfa->cm, PLAIN, COLORLESS, nfa->pre, nfa->init);
89
0
  newarc(nfa, '^', 1, nfa->pre, nfa->init);
90
0
  newarc(nfa, '^', 0, nfa->pre, nfa->init);
91
0
  rainbow(nfa, nfa->cm, PLAIN, COLORLESS, nfa->final, nfa->post);
92
0
  newarc(nfa, '$', 1, nfa->final, nfa->post);
93
0
  newarc(nfa, '$', 0, nfa->final, nfa->post);
94
95
0
  if (ISERR())
96
0
  {
97
0
    freenfa(nfa);
98
0
    return NULL;
99
0
  }
100
0
  return nfa;
101
0
}
102
103
/*
104
 * freenfa - free an entire NFA
105
 */
106
static void
107
freenfa(struct nfa *nfa)
108
0
{
109
0
  struct statebatch *sb;
110
0
  struct statebatch *sbnext;
111
0
  struct arcbatch *ab;
112
0
  struct arcbatch *abnext;
113
114
0
  for (sb = nfa->lastsb; sb != NULL; sb = sbnext)
115
0
  {
116
0
    sbnext = sb->next;
117
0
    nfa->v->spaceused -= STATEBATCHSIZE(sb->nstates);
118
0
    FREE(sb);
119
0
  }
120
0
  nfa->lastsb = NULL;
121
0
  for (ab = nfa->lastab; ab != NULL; ab = abnext)
122
0
  {
123
0
    abnext = ab->next;
124
0
    nfa->v->spaceused -= ARCBATCHSIZE(ab->narcs);
125
0
    FREE(ab);
126
0
  }
127
0
  nfa->lastab = NULL;
128
129
0
  nfa->nstates = -1;
130
0
  FREE(nfa);
131
0
}
132
133
/*
134
 * newstate - allocate an NFA state, with zero flag value
135
 */
136
static struct state *     /* NULL on error */
137
newstate(struct nfa *nfa)
138
0
{
139
0
  struct state *s;
140
141
  /*
142
   * This is a handy place to check for operation cancel during regex
143
   * compilation, since no code path will go very long without making a new
144
   * state or arc.
145
   */
146
0
  INTERRUPT(nfa->v->re);
147
148
  /* first, recycle anything that's on the freelist */
149
0
  if (nfa->freestates != NULL)
150
0
  {
151
0
    s = nfa->freestates;
152
0
    nfa->freestates = s->next;
153
0
  }
154
  /* otherwise, is there anything left in the last statebatch? */
155
0
  else if (nfa->lastsb != NULL && nfa->lastsbused < nfa->lastsb->nstates)
156
0
  {
157
0
    s = &nfa->lastsb->s[nfa->lastsbused++];
158
0
  }
159
  /* otherwise, need to allocate a new statebatch */
160
0
  else
161
0
  {
162
0
    struct statebatch *newSb;
163
0
    size_t    nstates;
164
165
0
    if (nfa->v->spaceused >= REG_MAX_COMPILE_SPACE)
166
0
    {
167
0
      NERR(REG_ETOOBIG);
168
0
      return NULL;
169
0
    }
170
0
    nstates = (nfa->lastsb != NULL) ? nfa->lastsb->nstates * 2 : FIRSTSBSIZE;
171
0
    if (nstates > MAXSBSIZE)
172
0
      nstates = MAXSBSIZE;
173
0
    newSb = (struct statebatch *) MALLOC(STATEBATCHSIZE(nstates));
174
0
    if (newSb == NULL)
175
0
    {
176
0
      NERR(REG_ESPACE);
177
0
      return NULL;
178
0
    }
179
0
    nfa->v->spaceused += STATEBATCHSIZE(nstates);
180
0
    newSb->nstates = nstates;
181
0
    newSb->next = nfa->lastsb;
182
0
    nfa->lastsb = newSb;
183
0
    nfa->lastsbused = 1;
184
0
    s = &newSb->s[0];
185
0
  }
186
187
0
  assert(nfa->nstates >= 0);
188
0
  s->no = nfa->nstates++;
189
0
  s->flag = 0;
190
0
  if (nfa->states == NULL)
191
0
    nfa->states = s;
192
0
  s->nins = 0;
193
0
  s->ins = NULL;
194
0
  s->nouts = 0;
195
0
  s->outs = NULL;
196
0
  s->tmp = NULL;
197
0
  s->next = NULL;
198
0
  if (nfa->slast != NULL)
199
0
  {
200
0
    assert(nfa->slast->next == NULL);
201
0
    nfa->slast->next = s;
202
0
  }
203
0
  s->prev = nfa->slast;
204
0
  nfa->slast = s;
205
0
  return s;
206
0
}
207
208
/*
209
 * newfstate - allocate an NFA state with a specified flag value
210
 */
211
static struct state *     /* NULL on error */
212
newfstate(struct nfa *nfa, int flag)
213
0
{
214
0
  struct state *s;
215
216
0
  s = newstate(nfa);
217
0
  if (s != NULL)
218
0
    s->flag = (char) flag;
219
0
  return s;
220
0
}
221
222
/*
223
 * dropstate - delete a state's inarcs and outarcs and free it
224
 */
225
static void
226
dropstate(struct nfa *nfa,
227
      struct state *s)
228
0
{
229
0
  struct arc *a;
230
231
0
  while ((a = s->ins) != NULL)
232
0
    freearc(nfa, a);
233
0
  while ((a = s->outs) != NULL)
234
0
    freearc(nfa, a);
235
0
  freestate(nfa, s);
236
0
}
237
238
/*
239
 * freestate - free a state, which has no in-arcs or out-arcs
240
 */
241
static void
242
freestate(struct nfa *nfa,
243
      struct state *s)
244
0
{
245
0
  assert(s != NULL);
246
0
  assert(s->nins == 0 && s->nouts == 0);
247
248
0
  s->no = FREESTATE;
249
0
  s->flag = 0;
250
0
  if (s->next != NULL)
251
0
    s->next->prev = s->prev;
252
0
  else
253
0
  {
254
0
    assert(s == nfa->slast);
255
0
    nfa->slast = s->prev;
256
0
  }
257
0
  if (s->prev != NULL)
258
0
    s->prev->next = s->next;
259
0
  else
260
0
  {
261
0
    assert(s == nfa->states);
262
0
    nfa->states = s->next;
263
0
  }
264
0
  s->prev = NULL;
265
0
  s->next = nfa->freestates;  /* don't delete it, put it on the free list */
266
0
  nfa->freestates = s;
267
0
}
268
269
/*
270
 * newarc - set up a new arc within an NFA
271
 *
272
 * This function checks to make sure that no duplicate arcs are created.
273
 * In general we never want duplicates.
274
 *
275
 * However: in principle, a RAINBOW arc is redundant with any plain arc
276
 * (unless that arc is for a pseudocolor).  But we don't try to recognize
277
 * that redundancy, either here or in allied operations such as moveins().
278
 * The pseudocolor consideration makes that more costly than it seems worth.
279
 */
280
static void
281
newarc(struct nfa *nfa,
282
     int t,
283
     color co,
284
     struct state *from,
285
     struct state *to)
286
0
{
287
0
  struct arc *a;
288
289
0
  assert(from != NULL && to != NULL);
290
291
  /*
292
   * This is a handy place to check for operation cancel during regex
293
   * compilation, since no code path will go very long without making a new
294
   * state or arc.
295
   */
296
0
  INTERRUPT(nfa->v->re);
297
298
  /* check for duplicate arc, using whichever chain is shorter */
299
0
  if (from->nouts <= to->nins)
300
0
  {
301
0
    for (a = from->outs; a != NULL; a = a->outchain)
302
0
      if (a->to == to && a->co == co && a->type == t)
303
0
        return;
304
0
  }
305
0
  else
306
0
  {
307
0
    for (a = to->ins; a != NULL; a = a->inchain)
308
0
      if (a->from == from && a->co == co && a->type == t)
309
0
        return;
310
0
  }
311
312
  /* no dup, so create the arc */
313
0
  createarc(nfa, t, co, from, to);
314
0
}
315
316
/*
317
 * createarc - create a new arc within an NFA
318
 *
319
 * This function must *only* be used after verifying that there is no existing
320
 * identical arc (same type/color/from/to).
321
 */
322
static void
323
createarc(struct nfa *nfa,
324
      int t,
325
      color co,
326
      struct state *from,
327
      struct state *to)
328
0
{
329
0
  struct arc *a;
330
331
0
  a = allocarc(nfa);
332
0
  if (NISERR())
333
0
    return;
334
0
  assert(a != NULL);
335
336
0
  a->type = t;
337
0
  a->co = co;
338
0
  a->to = to;
339
0
  a->from = from;
340
341
  /*
342
   * Put the new arc on the beginning, not the end, of the chains; it's
343
   * simpler here, and freearc() is the same cost either way.  See also the
344
   * logic in moveins() and its cohorts, as well as fixempties().
345
   */
346
0
  a->inchain = to->ins;
347
0
  a->inchainRev = NULL;
348
0
  if (to->ins)
349
0
    to->ins->inchainRev = a;
350
0
  to->ins = a;
351
0
  a->outchain = from->outs;
352
0
  a->outchainRev = NULL;
353
0
  if (from->outs)
354
0
    from->outs->outchainRev = a;
355
0
  from->outs = a;
356
357
0
  from->nouts++;
358
0
  to->nins++;
359
360
0
  if (COLORED(a) && nfa->parent == NULL)
361
0
    colorchain(nfa->cm, a);
362
0
}
363
364
/*
365
 * allocarc - allocate a new arc within an NFA
366
 */
367
static struct arc *       /* NULL for failure */
368
allocarc(struct nfa *nfa)
369
0
{
370
0
  struct arc *a;
371
372
  /* first, recycle anything that's on the freelist */
373
0
  if (nfa->freearcs != NULL)
374
0
  {
375
0
    a = nfa->freearcs;
376
0
    nfa->freearcs = a->freechain;
377
0
  }
378
  /* otherwise, is there anything left in the last arcbatch? */
379
0
  else if (nfa->lastab != NULL && nfa->lastabused < nfa->lastab->narcs)
380
0
  {
381
0
    a = &nfa->lastab->a[nfa->lastabused++];
382
0
  }
383
  /* otherwise, need to allocate a new arcbatch */
384
0
  else
385
0
  {
386
0
    struct arcbatch *newAb;
387
0
    size_t    narcs;
388
389
0
    if (nfa->v->spaceused >= REG_MAX_COMPILE_SPACE)
390
0
    {
391
0
      NERR(REG_ETOOBIG);
392
0
      return NULL;
393
0
    }
394
0
    narcs = (nfa->lastab != NULL) ? nfa->lastab->narcs * 2 : FIRSTABSIZE;
395
0
    if (narcs > MAXABSIZE)
396
0
      narcs = MAXABSIZE;
397
0
    newAb = (struct arcbatch *) MALLOC(ARCBATCHSIZE(narcs));
398
0
    if (newAb == NULL)
399
0
    {
400
0
      NERR(REG_ESPACE);
401
0
      return NULL;
402
0
    }
403
0
    nfa->v->spaceused += ARCBATCHSIZE(narcs);
404
0
    newAb->narcs = narcs;
405
0
    newAb->next = nfa->lastab;
406
0
    nfa->lastab = newAb;
407
0
    nfa->lastabused = 1;
408
0
    a = &newAb->a[0];
409
0
  }
410
411
0
  return a;
412
0
}
413
414
/*
415
 * freearc - free an arc
416
 */
417
static void
418
freearc(struct nfa *nfa,
419
    struct arc *victim)
420
0
{
421
0
  struct state *from = victim->from;
422
0
  struct state *to = victim->to;
423
0
  struct arc *predecessor;
424
425
0
  assert(victim->type != 0);
426
427
  /* take it off color chain if necessary */
428
0
  if (COLORED(victim) && nfa->parent == NULL)
429
0
    uncolorchain(nfa->cm, victim);
430
431
  /* take it off source's out-chain */
432
0
  assert(from != NULL);
433
0
  predecessor = victim->outchainRev;
434
0
  if (predecessor == NULL)
435
0
  {
436
0
    assert(from->outs == victim);
437
0
    from->outs = victim->outchain;
438
0
  }
439
0
  else
440
0
  {
441
0
    assert(predecessor->outchain == victim);
442
0
    predecessor->outchain = victim->outchain;
443
0
  }
444
0
  if (victim->outchain != NULL)
445
0
  {
446
0
    assert(victim->outchain->outchainRev == victim);
447
0
    victim->outchain->outchainRev = predecessor;
448
0
  }
449
0
  from->nouts--;
450
451
  /* take it off target's in-chain */
452
0
  assert(to != NULL);
453
0
  predecessor = victim->inchainRev;
454
0
  if (predecessor == NULL)
455
0
  {
456
0
    assert(to->ins == victim);
457
0
    to->ins = victim->inchain;
458
0
  }
459
0
  else
460
0
  {
461
0
    assert(predecessor->inchain == victim);
462
0
    predecessor->inchain = victim->inchain;
463
0
  }
464
0
  if (victim->inchain != NULL)
465
0
  {
466
0
    assert(victim->inchain->inchainRev == victim);
467
0
    victim->inchain->inchainRev = predecessor;
468
0
  }
469
0
  to->nins--;
470
471
  /* clean up and place on NFA's free list */
472
0
  victim->type = 0;
473
0
  victim->from = NULL;   /* precautions... */
474
0
  victim->to = NULL;
475
0
  victim->inchain = NULL;
476
0
  victim->inchainRev = NULL;
477
0
  victim->outchain = NULL;
478
0
  victim->outchainRev = NULL;
479
0
  victim->freechain = nfa->freearcs;
480
0
  nfa->freearcs = victim;
481
0
}
482
483
/*
484
 * changearcsource - flip an arc to have a different from state
485
 *
486
 * Caller must have verified that there is no pre-existing duplicate arc.
487
 */
488
static void
489
changearcsource(struct arc *a, struct state *newfrom)
490
0
{
491
0
  struct state *oldfrom = a->from;
492
0
  struct arc *predecessor;
493
494
0
  assert(oldfrom != newfrom);
495
496
  /* take it off old source's out-chain */
497
0
  assert(oldfrom != NULL);
498
0
  predecessor = a->outchainRev;
499
0
  if (predecessor == NULL)
500
0
  {
501
0
    assert(oldfrom->outs == a);
502
0
    oldfrom->outs = a->outchain;
503
0
  }
504
0
  else
505
0
  {
506
0
    assert(predecessor->outchain == a);
507
0
    predecessor->outchain = a->outchain;
508
0
  }
509
0
  if (a->outchain != NULL)
510
0
  {
511
0
    assert(a->outchain->outchainRev == a);
512
0
    a->outchain->outchainRev = predecessor;
513
0
  }
514
0
  oldfrom->nouts--;
515
516
0
  a->from = newfrom;
517
518
  /* prepend it to new source's out-chain */
519
0
  a->outchain = newfrom->outs;
520
0
  a->outchainRev = NULL;
521
0
  if (newfrom->outs)
522
0
    newfrom->outs->outchainRev = a;
523
0
  newfrom->outs = a;
524
0
  newfrom->nouts++;
525
0
}
526
527
/*
528
 * changearctarget - flip an arc to have a different to state
529
 *
530
 * Caller must have verified that there is no pre-existing duplicate arc.
531
 */
532
static void
533
changearctarget(struct arc *a, struct state *newto)
534
0
{
535
0
  struct state *oldto = a->to;
536
0
  struct arc *predecessor;
537
538
0
  assert(oldto != newto);
539
540
  /* take it off old target's in-chain */
541
0
  assert(oldto != NULL);
542
0
  predecessor = a->inchainRev;
543
0
  if (predecessor == NULL)
544
0
  {
545
0
    assert(oldto->ins == a);
546
0
    oldto->ins = a->inchain;
547
0
  }
548
0
  else
549
0
  {
550
0
    assert(predecessor->inchain == a);
551
0
    predecessor->inchain = a->inchain;
552
0
  }
553
0
  if (a->inchain != NULL)
554
0
  {
555
0
    assert(a->inchain->inchainRev == a);
556
0
    a->inchain->inchainRev = predecessor;
557
0
  }
558
0
  oldto->nins--;
559
560
0
  a->to = newto;
561
562
  /* prepend it to new target's in-chain */
563
0
  a->inchain = newto->ins;
564
0
  a->inchainRev = NULL;
565
0
  if (newto->ins)
566
0
    newto->ins->inchainRev = a;
567
0
  newto->ins = a;
568
0
  newto->nins++;
569
0
}
570
571
/*
572
 * hasnonemptyout - Does state have a non-EMPTY out arc?
573
 */
574
static int
575
hasnonemptyout(struct state *s)
576
0
{
577
0
  struct arc *a;
578
579
0
  for (a = s->outs; a != NULL; a = a->outchain)
580
0
  {
581
0
    if (a->type != EMPTY)
582
0
      return 1;
583
0
  }
584
0
  return 0;
585
0
}
586
587
/*
588
 * findarc - find arc, if any, from given source with given type and color
589
 * If there is more than one such arc, the result is random.
590
 */
591
static struct arc *
592
findarc(struct state *s,
593
    int type,
594
    color co)
595
0
{
596
0
  struct arc *a;
597
598
0
  for (a = s->outs; a != NULL; a = a->outchain)
599
0
    if (a->type == type && a->co == co)
600
0
      return a;
601
0
  return NULL;
602
0
}
603
604
/*
605
 * cparc - allocate a new arc within an NFA, copying details from old one
606
 */
607
static void
608
cparc(struct nfa *nfa,
609
    struct arc *oa,
610
    struct state *from,
611
    struct state *to)
612
0
{
613
0
  newarc(nfa, oa->type, oa->co, from, to);
614
0
}
615
616
/*
617
 * sortins - sort the in arcs of a state by from/color/type
618
 */
619
static void
620
sortins(struct nfa *nfa,
621
    struct state *s)
622
0
{
623
0
  struct arc **sortarray;
624
0
  struct arc *a;
625
0
  int     n = s->nins;
626
0
  int     i;
627
628
0
  if (n <= 1)
629
0
    return;         /* nothing to do */
630
  /* make an array of arc pointers ... */
631
0
  sortarray = (struct arc **) MALLOC(n * sizeof(struct arc *));
632
0
  if (sortarray == NULL)
633
0
  {
634
0
    NERR(REG_ESPACE);
635
0
    return;
636
0
  }
637
0
  i = 0;
638
0
  for (a = s->ins; a != NULL; a = a->inchain)
639
0
    sortarray[i++] = a;
640
0
  assert(i == n);
641
  /* ... sort the array */
642
0
  qsort(sortarray, n, sizeof(struct arc *), sortins_cmp);
643
  /* ... and rebuild arc list in order */
644
  /* it seems worth special-casing first and last items to simplify loop */
645
0
  a = sortarray[0];
646
0
  s->ins = a;
647
0
  a->inchain = sortarray[1];
648
0
  a->inchainRev = NULL;
649
0
  for (i = 1; i < n - 1; i++)
650
0
  {
651
0
    a = sortarray[i];
652
0
    a->inchain = sortarray[i + 1];
653
0
    a->inchainRev = sortarray[i - 1];
654
0
  }
655
0
  a = sortarray[i];
656
0
  a->inchain = NULL;
657
0
  a->inchainRev = sortarray[i - 1];
658
0
  FREE(sortarray);
659
0
}
660
661
static int
662
sortins_cmp(const void *a, const void *b)
663
0
{
664
0
  const struct arc *aa = *((const struct arc *const *) a);
665
0
  const struct arc *bb = *((const struct arc *const *) b);
666
667
  /* we check the fields in the order they are most likely to be different */
668
0
  if (aa->from->no < bb->from->no)
669
0
    return -1;
670
0
  if (aa->from->no > bb->from->no)
671
0
    return 1;
672
0
  if (aa->co < bb->co)
673
0
    return -1;
674
0
  if (aa->co > bb->co)
675
0
    return 1;
676
0
  if (aa->type < bb->type)
677
0
    return -1;
678
0
  if (aa->type > bb->type)
679
0
    return 1;
680
0
  return 0;
681
0
}
682
683
/*
684
 * sortouts - sort the out arcs of a state by to/color/type
685
 */
686
static void
687
sortouts(struct nfa *nfa,
688
     struct state *s)
689
0
{
690
0
  struct arc **sortarray;
691
0
  struct arc *a;
692
0
  int     n = s->nouts;
693
0
  int     i;
694
695
0
  if (n <= 1)
696
0
    return;         /* nothing to do */
697
  /* make an array of arc pointers ... */
698
0
  sortarray = (struct arc **) MALLOC(n * sizeof(struct arc *));
699
0
  if (sortarray == NULL)
700
0
  {
701
0
    NERR(REG_ESPACE);
702
0
    return;
703
0
  }
704
0
  i = 0;
705
0
  for (a = s->outs; a != NULL; a = a->outchain)
706
0
    sortarray[i++] = a;
707
0
  assert(i == n);
708
  /* ... sort the array */
709
0
  qsort(sortarray, n, sizeof(struct arc *), sortouts_cmp);
710
  /* ... and rebuild arc list in order */
711
  /* it seems worth special-casing first and last items to simplify loop */
712
0
  a = sortarray[0];
713
0
  s->outs = a;
714
0
  a->outchain = sortarray[1];
715
0
  a->outchainRev = NULL;
716
0
  for (i = 1; i < n - 1; i++)
717
0
  {
718
0
    a = sortarray[i];
719
0
    a->outchain = sortarray[i + 1];
720
0
    a->outchainRev = sortarray[i - 1];
721
0
  }
722
0
  a = sortarray[i];
723
0
  a->outchain = NULL;
724
0
  a->outchainRev = sortarray[i - 1];
725
0
  FREE(sortarray);
726
0
}
727
728
static int
729
sortouts_cmp(const void *a, const void *b)
730
0
{
731
0
  const struct arc *aa = *((const struct arc *const *) a);
732
0
  const struct arc *bb = *((const struct arc *const *) b);
733
734
  /* we check the fields in the order they are most likely to be different */
735
0
  if (aa->to->no < bb->to->no)
736
0
    return -1;
737
0
  if (aa->to->no > bb->to->no)
738
0
    return 1;
739
0
  if (aa->co < bb->co)
740
0
    return -1;
741
0
  if (aa->co > bb->co)
742
0
    return 1;
743
0
  if (aa->type < bb->type)
744
0
    return -1;
745
0
  if (aa->type > bb->type)
746
0
    return 1;
747
0
  return 0;
748
0
}
749
750
/*
751
 * Common decision logic about whether to use arc-by-arc operations or
752
 * sort/merge.  If there's just a few source arcs we cannot recoup the
753
 * cost of sorting the destination arc list, no matter how large it is.
754
 * Otherwise, limit the number of arc-by-arc comparisons to about 1000
755
 * (a somewhat arbitrary choice, but the breakeven point would probably
756
 * be machine dependent anyway).
757
 */
758
#define BULK_ARC_OP_USE_SORT(nsrcarcs, ndestarcs) \
759
0
  ((nsrcarcs) < 4 ? 0 : ((nsrcarcs) > 32 || (ndestarcs) > 32))
760
761
/*
762
 * moveins - move all in arcs of a state to another state
763
 *
764
 * You might think this could be done better by just updating the
765
 * existing arcs, and you would be right if it weren't for the need
766
 * for duplicate suppression, which makes it easier to just make new
767
 * ones to exploit the suppression built into newarc.
768
 *
769
 * However, if we have a whole lot of arcs to deal with, retail duplicate
770
 * checks become too slow.  In that case we proceed by sorting and merging
771
 * the arc lists, and then we can indeed just update the arcs in-place.
772
 *
773
 * On the other hand, it's also true that this is frequently called with
774
 * a brand-new newState that has no existing in-arcs.  In that case,
775
 * de-duplication is unnecessary, so we can just blindly move all the arcs.
776
 */
777
static void
778
moveins(struct nfa *nfa,
779
    struct state *oldState,
780
    struct state *newState)
781
0
{
782
0
  assert(oldState != newState);
783
784
0
  if (newState->nins == 0)
785
0
  {
786
    /* No need for de-duplication */
787
0
    struct arc *a;
788
789
0
    while ((a = oldState->ins) != NULL)
790
0
    {
791
0
      createarc(nfa, a->type, a->co, a->from, newState);
792
0
      freearc(nfa, a);
793
0
    }
794
0
  }
795
0
  else if (!BULK_ARC_OP_USE_SORT(oldState->nins, newState->nins))
796
0
  {
797
    /* With not too many arcs, just do them one at a time */
798
0
    struct arc *a;
799
800
0
    while ((a = oldState->ins) != NULL)
801
0
    {
802
0
      cparc(nfa, a, a->from, newState);
803
0
      freearc(nfa, a);
804
0
    }
805
0
  }
806
0
  else
807
0
  {
808
    /*
809
     * With many arcs, use a sort-merge approach.  Note changearctarget()
810
     * will put the arc onto the front of newState's chain, so it does not
811
     * break our walk through the sorted part of the chain.
812
     */
813
0
    struct arc *oa;
814
0
    struct arc *na;
815
816
    /*
817
     * Because we bypass newarc() in this code path, we'd better include a
818
     * cancel check.
819
     */
820
0
    INTERRUPT(nfa->v->re);
821
822
0
    sortins(nfa, oldState);
823
0
    sortins(nfa, newState);
824
0
    if (NISERR())
825
0
      return;       /* might have failed to sort */
826
0
    oa = oldState->ins;
827
0
    na = newState->ins;
828
0
    while (oa != NULL && na != NULL)
829
0
    {
830
0
      struct arc *a = oa;
831
832
0
      switch (sortins_cmp(&oa, &na))
833
0
      {
834
0
        case -1:
835
          /* newState does not have anything matching oa */
836
0
          oa = oa->inchain;
837
838
          /*
839
           * Rather than doing createarc+freearc, we can just unlink
840
           * and relink the existing arc struct.
841
           */
842
0
          changearctarget(a, newState);
843
0
          break;
844
0
        case 0:
845
          /* match, advance in both lists */
846
0
          oa = oa->inchain;
847
0
          na = na->inchain;
848
          /* ... and drop duplicate arc from oldState */
849
0
          freearc(nfa, a);
850
0
          break;
851
0
        case +1:
852
          /* advance only na; oa might have a match later */
853
0
          na = na->inchain;
854
0
          break;
855
0
        default:
856
0
          assert(NOTREACHED);
857
0
      }
858
0
    }
859
0
    while (oa != NULL)
860
0
    {
861
      /* newState does not have anything matching oa */
862
0
      struct arc *a = oa;
863
864
0
      oa = oa->inchain;
865
0
      changearctarget(a, newState);
866
0
    }
867
0
  }
868
869
0
  assert(oldState->nins == 0);
870
0
  assert(oldState->ins == NULL);
871
0
}
872
873
/*
874
 * copyins - copy in arcs of a state to another state
875
 *
876
 * The comments for moveins() apply here as well.  However, in current
877
 * usage, this is *only* called with brand-new target states, so that
878
 * only the "no need for de-duplication" code path is ever reached.
879
 * We keep the rest #ifdef'd out in case it's needed in the future.
880
 */
881
static void
882
copyins(struct nfa *nfa,
883
    struct state *oldState,
884
    struct state *newState)
885
0
{
886
0
  assert(oldState != newState);
887
0
  assert(newState->nins == 0);  /* see comment above */
888
889
0
  if (newState->nins == 0)
890
0
  {
891
    /* No need for de-duplication */
892
0
    struct arc *a;
893
894
0
    for (a = oldState->ins; a != NULL; a = a->inchain)
895
0
      createarc(nfa, a->type, a->co, a->from, newState);
896
0
  }
897
#ifdef NOT_USED         /* see comment above */
898
  else if (!BULK_ARC_OP_USE_SORT(oldState->nins, newState->nins))
899
  {
900
    /* With not too many arcs, just do them one at a time */
901
    struct arc *a;
902
903
    for (a = oldState->ins; a != NULL; a = a->inchain)
904
      cparc(nfa, a, a->from, newState);
905
  }
906
  else
907
  {
908
    /*
909
     * With many arcs, use a sort-merge approach.  Note that createarc()
910
     * will put new arcs onto the front of newState's chain, so it does
911
     * not break our walk through the sorted part of the chain.
912
     */
913
    struct arc *oa;
914
    struct arc *na;
915
916
    /*
917
     * Because we bypass newarc() in this code path, we'd better include a
918
     * cancel check.
919
     */
920
    INTERRUPT(nfa->v->re);
921
922
    sortins(nfa, oldState);
923
    sortins(nfa, newState);
924
    if (NISERR())
925
      return;       /* might have failed to sort */
926
    oa = oldState->ins;
927
    na = newState->ins;
928
    while (oa != NULL && na != NULL)
929
    {
930
      struct arc *a = oa;
931
932
      switch (sortins_cmp(&oa, &na))
933
      {
934
        case -1:
935
          /* newState does not have anything matching oa */
936
          oa = oa->inchain;
937
          createarc(nfa, a->type, a->co, a->from, newState);
938
          break;
939
        case 0:
940
          /* match, advance in both lists */
941
          oa = oa->inchain;
942
          na = na->inchain;
943
          break;
944
        case +1:
945
          /* advance only na; oa might have a match later */
946
          na = na->inchain;
947
          break;
948
        default:
949
          assert(NOTREACHED);
950
      }
951
    }
952
    while (oa != NULL)
953
    {
954
      /* newState does not have anything matching oa */
955
      struct arc *a = oa;
956
957
      oa = oa->inchain;
958
      createarc(nfa, a->type, a->co, a->from, newState);
959
    }
960
  }
961
#endif              /* NOT_USED */
962
0
}
963
964
/*
965
 * mergeins - merge a list of inarcs into a state
966
 *
967
 * This is much like copyins, but the source arcs are listed in an array,
968
 * and are not guaranteed unique.  It's okay to clobber the array contents.
969
 */
970
static void
971
mergeins(struct nfa *nfa,
972
     struct state *s,
973
     struct arc **arcarray,
974
     int arccount)
975
0
{
976
0
  struct arc *na;
977
0
  int     i;
978
0
  int     j;
979
980
0
  if (arccount <= 0)
981
0
    return;
982
983
  /*
984
   * Because we bypass newarc() in this code path, we'd better include a
985
   * cancel check.
986
   */
987
0
  INTERRUPT(nfa->v->re);
988
989
  /* Sort existing inarcs as well as proposed new ones */
990
0
  sortins(nfa, s);
991
0
  if (NISERR())
992
0
    return;         /* might have failed to sort */
993
994
0
  qsort(arcarray, arccount, sizeof(struct arc *), sortins_cmp);
995
996
  /*
997
   * arcarray very likely includes dups, so we must eliminate them.  (This
998
   * could be folded into the next loop, but it's not worth the trouble.)
999
   */
1000
0
  j = 0;
1001
0
  for (i = 1; i < arccount; i++)
1002
0
  {
1003
0
    switch (sortins_cmp(&arcarray[j], &arcarray[i]))
1004
0
    {
1005
0
      case -1:
1006
        /* non-dup */
1007
0
        arcarray[++j] = arcarray[i];
1008
0
        break;
1009
0
      case 0:
1010
        /* dup */
1011
0
        break;
1012
0
      default:
1013
        /* trouble */
1014
0
        assert(NOTREACHED);
1015
0
    }
1016
0
  }
1017
0
  arccount = j + 1;
1018
1019
  /*
1020
   * Now merge into s' inchain.  Note that createarc() will put new arcs
1021
   * onto the front of s's chain, so it does not break our walk through the
1022
   * sorted part of the chain.
1023
   */
1024
0
  i = 0;
1025
0
  na = s->ins;
1026
0
  while (i < arccount && na != NULL)
1027
0
  {
1028
0
    struct arc *a = arcarray[i];
1029
1030
0
    switch (sortins_cmp(&a, &na))
1031
0
    {
1032
0
      case -1:
1033
        /* s does not have anything matching a */
1034
0
        createarc(nfa, a->type, a->co, a->from, s);
1035
0
        i++;
1036
0
        break;
1037
0
      case 0:
1038
        /* match, advance in both lists */
1039
0
        i++;
1040
0
        na = na->inchain;
1041
0
        break;
1042
0
      case +1:
1043
        /* advance only na; array might have a match later */
1044
0
        na = na->inchain;
1045
0
        break;
1046
0
      default:
1047
0
        assert(NOTREACHED);
1048
0
    }
1049
0
  }
1050
0
  while (i < arccount)
1051
0
  {
1052
    /* s does not have anything matching a */
1053
0
    struct arc *a = arcarray[i];
1054
1055
0
    createarc(nfa, a->type, a->co, a->from, s);
1056
0
    i++;
1057
0
  }
1058
0
}
1059
1060
/*
1061
 * moveouts - move all out arcs of a state to another state
1062
 *
1063
 * See comments for moveins()
1064
 */
1065
static void
1066
moveouts(struct nfa *nfa,
1067
     struct state *oldState,
1068
     struct state *newState)
1069
0
{
1070
0
  assert(oldState != newState);
1071
1072
0
  if (newState->nouts == 0)
1073
0
  {
1074
    /* No need for de-duplication */
1075
0
    struct arc *a;
1076
1077
0
    while ((a = oldState->outs) != NULL)
1078
0
    {
1079
0
      createarc(nfa, a->type, a->co, newState, a->to);
1080
0
      freearc(nfa, a);
1081
0
    }
1082
0
  }
1083
0
  else if (!BULK_ARC_OP_USE_SORT(oldState->nouts, newState->nouts))
1084
0
  {
1085
    /* With not too many arcs, just do them one at a time */
1086
0
    struct arc *a;
1087
1088
0
    while ((a = oldState->outs) != NULL)
1089
0
    {
1090
0
      cparc(nfa, a, newState, a->to);
1091
0
      freearc(nfa, a);
1092
0
    }
1093
0
  }
1094
0
  else
1095
0
  {
1096
    /*
1097
     * With many arcs, use a sort-merge approach.  Note changearcsource()
1098
     * will put the arc onto the front of newState's chain, so it does not
1099
     * break our walk through the sorted part of the chain.
1100
     */
1101
0
    struct arc *oa;
1102
0
    struct arc *na;
1103
1104
    /*
1105
     * Because we bypass newarc() in this code path, we'd better include a
1106
     * cancel check.
1107
     */
1108
0
    INTERRUPT(nfa->v->re);
1109
1110
0
    sortouts(nfa, oldState);
1111
0
    sortouts(nfa, newState);
1112
0
    if (NISERR())
1113
0
      return;       /* might have failed to sort */
1114
0
    oa = oldState->outs;
1115
0
    na = newState->outs;
1116
0
    while (oa != NULL && na != NULL)
1117
0
    {
1118
0
      struct arc *a = oa;
1119
1120
0
      switch (sortouts_cmp(&oa, &na))
1121
0
      {
1122
0
        case -1:
1123
          /* newState does not have anything matching oa */
1124
0
          oa = oa->outchain;
1125
1126
          /*
1127
           * Rather than doing createarc+freearc, we can just unlink
1128
           * and relink the existing arc struct.
1129
           */
1130
0
          changearcsource(a, newState);
1131
0
          break;
1132
0
        case 0:
1133
          /* match, advance in both lists */
1134
0
          oa = oa->outchain;
1135
0
          na = na->outchain;
1136
          /* ... and drop duplicate arc from oldState */
1137
0
          freearc(nfa, a);
1138
0
          break;
1139
0
        case +1:
1140
          /* advance only na; oa might have a match later */
1141
0
          na = na->outchain;
1142
0
          break;
1143
0
        default:
1144
0
          assert(NOTREACHED);
1145
0
      }
1146
0
    }
1147
0
    while (oa != NULL)
1148
0
    {
1149
      /* newState does not have anything matching oa */
1150
0
      struct arc *a = oa;
1151
1152
0
      oa = oa->outchain;
1153
0
      changearcsource(a, newState);
1154
0
    }
1155
0
  }
1156
1157
0
  assert(oldState->nouts == 0);
1158
0
  assert(oldState->outs == NULL);
1159
0
}
1160
1161
/*
1162
 * copyouts - copy out arcs of a state to another state
1163
 *
1164
 * See comments for copyins()
1165
 */
1166
static void
1167
copyouts(struct nfa *nfa,
1168
     struct state *oldState,
1169
     struct state *newState)
1170
0
{
1171
0
  assert(oldState != newState);
1172
0
  assert(newState->nouts == 0); /* see comment above */
1173
1174
0
  if (newState->nouts == 0)
1175
0
  {
1176
    /* No need for de-duplication */
1177
0
    struct arc *a;
1178
1179
0
    for (a = oldState->outs; a != NULL; a = a->outchain)
1180
0
      createarc(nfa, a->type, a->co, newState, a->to);
1181
0
  }
1182
#ifdef NOT_USED         /* see comment above */
1183
  else if (!BULK_ARC_OP_USE_SORT(oldState->nouts, newState->nouts))
1184
  {
1185
    /* With not too many arcs, just do them one at a time */
1186
    struct arc *a;
1187
1188
    for (a = oldState->outs; a != NULL; a = a->outchain)
1189
      cparc(nfa, a, newState, a->to);
1190
  }
1191
  else
1192
  {
1193
    /*
1194
     * With many arcs, use a sort-merge approach.  Note that createarc()
1195
     * will put new arcs onto the front of newState's chain, so it does
1196
     * not break our walk through the sorted part of the chain.
1197
     */
1198
    struct arc *oa;
1199
    struct arc *na;
1200
1201
    /*
1202
     * Because we bypass newarc() in this code path, we'd better include a
1203
     * cancel check.
1204
     */
1205
    INTERRUPT(nfa->v->re);
1206
1207
    sortouts(nfa, oldState);
1208
    sortouts(nfa, newState);
1209
    if (NISERR())
1210
      return;       /* might have failed to sort */
1211
    oa = oldState->outs;
1212
    na = newState->outs;
1213
    while (oa != NULL && na != NULL)
1214
    {
1215
      struct arc *a = oa;
1216
1217
      switch (sortouts_cmp(&oa, &na))
1218
      {
1219
        case -1:
1220
          /* newState does not have anything matching oa */
1221
          oa = oa->outchain;
1222
          createarc(nfa, a->type, a->co, newState, a->to);
1223
          break;
1224
        case 0:
1225
          /* match, advance in both lists */
1226
          oa = oa->outchain;
1227
          na = na->outchain;
1228
          break;
1229
        case +1:
1230
          /* advance only na; oa might have a match later */
1231
          na = na->outchain;
1232
          break;
1233
        default:
1234
          assert(NOTREACHED);
1235
      }
1236
    }
1237
    while (oa != NULL)
1238
    {
1239
      /* newState does not have anything matching oa */
1240
      struct arc *a = oa;
1241
1242
      oa = oa->outchain;
1243
      createarc(nfa, a->type, a->co, newState, a->to);
1244
    }
1245
  }
1246
#endif              /* NOT_USED */
1247
0
}
1248
1249
/*
1250
 * cloneouts - copy out arcs of a state to another state pair, modifying type
1251
 *
1252
 * This is only used to convert PLAIN arcs to AHEAD/BEHIND arcs, which share
1253
 * the same interpretation of "co".  It wouldn't be sensible with LACONs.
1254
 */
1255
static void
1256
cloneouts(struct nfa *nfa,
1257
      struct state *old,
1258
      struct state *from,
1259
      struct state *to,
1260
      int type)
1261
0
{
1262
0
  struct arc *a;
1263
1264
0
  assert(old != from);
1265
0
  assert(type == AHEAD || type == BEHIND);
1266
1267
0
  for (a = old->outs; a != NULL; a = a->outchain)
1268
0
  {
1269
0
    assert(a->type == PLAIN);
1270
0
    newarc(nfa, type, a->co, from, to);
1271
0
  }
1272
0
}
1273
1274
/*
1275
 * delsub - delete a sub-NFA, updating subre pointers if necessary
1276
 *
1277
 * This uses a recursive traversal of the sub-NFA, marking already-seen
1278
 * states using their tmp pointer.
1279
 */
1280
static void
1281
delsub(struct nfa *nfa,
1282
     struct state *lp,    /* the sub-NFA goes from here... */
1283
     struct state *rp)    /* ...to here, *not* inclusive */
1284
0
{
1285
0
  assert(lp != rp);
1286
1287
0
  rp->tmp = rp;       /* mark end */
1288
1289
0
  deltraverse(nfa, lp, lp);
1290
0
  if (NISERR())
1291
0
    return;         /* asserts might not hold after failure */
1292
0
  assert(lp->nouts == 0 && rp->nins == 0);  /* did the job */
1293
0
  assert(lp->no != FREESTATE && rp->no != FREESTATE); /* no more */
1294
1295
0
  rp->tmp = NULL;       /* unmark end */
1296
0
  lp->tmp = NULL;       /* and begin, marked by deltraverse */
1297
0
}
1298
1299
/*
1300
 * deltraverse - the recursive heart of delsub
1301
 * This routine's basic job is to destroy all out-arcs of the state.
1302
 */
1303
static void
1304
deltraverse(struct nfa *nfa,
1305
      struct state *leftend,
1306
      struct state *s)
1307
0
{
1308
0
  struct arc *a;
1309
0
  struct state *to;
1310
1311
  /* Since this is recursive, it could be driven to stack overflow */
1312
0
  if (STACK_TOO_DEEP(nfa->v->re))
1313
0
  {
1314
0
    NERR(REG_ETOOBIG);
1315
0
    return;
1316
0
  }
1317
1318
0
  if (s->nouts == 0)
1319
0
    return;         /* nothing to do */
1320
0
  if (s->tmp != NULL)
1321
0
    return;         /* already in progress */
1322
1323
0
  s->tmp = s;         /* mark as in progress */
1324
1325
0
  while ((a = s->outs) != NULL)
1326
0
  {
1327
0
    to = a->to;
1328
0
    deltraverse(nfa, leftend, to);
1329
0
    if (NISERR())
1330
0
      return;       /* asserts might not hold after failure */
1331
0
    assert(to->nouts == 0 || to->tmp != NULL);
1332
0
    freearc(nfa, a);
1333
0
    if (to->nins == 0 && to->tmp == NULL)
1334
0
    {
1335
0
      assert(to->nouts == 0);
1336
0
      freestate(nfa, to);
1337
0
    }
1338
0
  }
1339
1340
0
  assert(s->no != FREESTATE); /* we're still here */
1341
0
  assert(s == leftend || s->nins != 0); /* and still reachable */
1342
0
  assert(s->nouts == 0);    /* but have no outarcs */
1343
1344
0
  s->tmp = NULL;       /* we're done here */
1345
0
}
1346
1347
/*
1348
 * dupnfa - duplicate sub-NFA
1349
 *
1350
 * Another recursive traversal, this time using tmp to point to duplicates
1351
 * as well as mark already-seen states.  (You knew there was a reason why
1352
 * it's a state pointer, didn't you? :-))
1353
 */
1354
static void
1355
dupnfa(struct nfa *nfa,
1356
     struct state *start,   /* duplicate of subNFA starting here */
1357
     struct state *stop,    /* and stopping here */
1358
     struct state *from,    /* stringing duplicate from here */
1359
     struct state *to)    /* to here */
1360
0
{
1361
0
  if (start == stop)
1362
0
  {
1363
0
    newarc(nfa, EMPTY, 0, from, to);
1364
0
    return;
1365
0
  }
1366
1367
0
  stop->tmp = to;
1368
0
  duptraverse(nfa, start, from);
1369
  /* done, except for clearing out the tmp pointers */
1370
1371
0
  stop->tmp = NULL;
1372
0
  cleartraverse(nfa, start);
1373
0
}
1374
1375
/*
1376
 * duptraverse - recursive heart of dupnfa
1377
 */
1378
static void
1379
duptraverse(struct nfa *nfa,
1380
      struct state *s,
1381
      struct state *stmp) /* s's duplicate, or NULL */
1382
0
{
1383
0
  struct arc *a;
1384
1385
  /* Since this is recursive, it could be driven to stack overflow */
1386
0
  if (STACK_TOO_DEEP(nfa->v->re))
1387
0
  {
1388
0
    NERR(REG_ETOOBIG);
1389
0
    return;
1390
0
  }
1391
1392
0
  if (s->tmp != NULL)
1393
0
    return;         /* already done */
1394
1395
0
  s->tmp = (stmp == NULL) ? newstate(nfa) : stmp;
1396
0
  if (s->tmp == NULL)
1397
0
  {
1398
0
    assert(NISERR());
1399
0
    return;
1400
0
  }
1401
1402
0
  for (a = s->outs; a != NULL && !NISERR(); a = a->outchain)
1403
0
  {
1404
0
    duptraverse(nfa, a->to, (struct state *) NULL);
1405
0
    if (NISERR())
1406
0
      break;
1407
0
    assert(a->to->tmp != NULL);
1408
0
    cparc(nfa, a, s->tmp, a->to->tmp);
1409
0
  }
1410
0
}
1411
1412
/*
1413
 * removeconstraints - remove any constraints in an NFA
1414
 *
1415
 * Constraint arcs are replaced by empty arcs, essentially treating all
1416
 * constraints as automatically satisfied.
1417
 */
1418
static void
1419
removeconstraints(struct nfa *nfa,
1420
          struct state *start,  /* process subNFA starting here */
1421
          struct state *stop) /* and stopping here */
1422
0
{
1423
0
  if (start == stop)
1424
0
    return;
1425
1426
0
  stop->tmp = stop;
1427
0
  removetraverse(nfa, start);
1428
  /* done, except for clearing out the tmp pointers */
1429
1430
0
  stop->tmp = NULL;
1431
0
  cleartraverse(nfa, start);
1432
0
}
1433
1434
/*
1435
 * removetraverse - recursive heart of removeconstraints
1436
 */
1437
static void
1438
removetraverse(struct nfa *nfa,
1439
         struct state *s)
1440
0
{
1441
0
  struct arc *a;
1442
0
  struct arc *oa;
1443
1444
  /* Since this is recursive, it could be driven to stack overflow */
1445
0
  if (STACK_TOO_DEEP(nfa->v->re))
1446
0
  {
1447
0
    NERR(REG_ETOOBIG);
1448
0
    return;
1449
0
  }
1450
1451
0
  if (s->tmp != NULL)
1452
0
    return;         /* already done */
1453
1454
0
  s->tmp = s;
1455
0
  for (a = s->outs; a != NULL && !NISERR(); a = oa)
1456
0
  {
1457
0
    removetraverse(nfa, a->to);
1458
0
    if (NISERR())
1459
0
      break;
1460
0
    oa = a->outchain;
1461
0
    switch (a->type)
1462
0
    {
1463
0
      case PLAIN:
1464
0
      case EMPTY:
1465
0
      case CANTMATCH:
1466
        /* nothing to do */
1467
0
        break;
1468
0
      case AHEAD:
1469
0
      case BEHIND:
1470
0
      case '^':
1471
0
      case '$':
1472
0
      case LACON:
1473
        /* replace it */
1474
0
        newarc(nfa, EMPTY, 0, s, a->to);
1475
0
        freearc(nfa, a);
1476
0
        break;
1477
0
      default:
1478
0
        NERR(REG_ASSERT);
1479
0
        break;
1480
0
    }
1481
0
  }
1482
0
}
1483
1484
/*
1485
 * cleartraverse - recursive cleanup for algorithms that leave tmp ptrs set
1486
 */
1487
static void
1488
cleartraverse(struct nfa *nfa,
1489
        struct state *s)
1490
0
{
1491
0
  struct arc *a;
1492
1493
  /* Since this is recursive, it could be driven to stack overflow */
1494
0
  if (STACK_TOO_DEEP(nfa->v->re))
1495
0
  {
1496
0
    NERR(REG_ETOOBIG);
1497
0
    return;
1498
0
  }
1499
1500
0
  if (s->tmp == NULL)
1501
0
    return;
1502
0
  s->tmp = NULL;
1503
1504
0
  for (a = s->outs; a != NULL; a = a->outchain)
1505
0
    cleartraverse(nfa, a->to);
1506
0
}
1507
1508
/*
1509
 * single_color_transition - does getting from s1 to s2 cross one PLAIN arc?
1510
 *
1511
 * If traversing from s1 to s2 requires a single PLAIN match (possibly of any
1512
 * of a set of colors), return a state whose outarc list contains only PLAIN
1513
 * arcs of those color(s).  Otherwise return NULL.
1514
 *
1515
 * This is used before optimizing the NFA, so there may be EMPTY arcs, which
1516
 * we should ignore; the possibility of an EMPTY is why the result state could
1517
 * be different from s1.
1518
 *
1519
 * It's worth troubling to handle multiple parallel PLAIN arcs here because a
1520
 * bracket construct such as [abc] might yield either one or several parallel
1521
 * PLAIN arcs depending on earlier atoms in the expression.  We'd rather that
1522
 * that implementation detail not create user-visible performance differences.
1523
 */
1524
static struct state *
1525
single_color_transition(struct state *s1, struct state *s2)
1526
0
{
1527
0
  struct arc *a;
1528
1529
  /* Ignore leading EMPTY arc, if any */
1530
0
  if (s1->nouts == 1 && s1->outs->type == EMPTY)
1531
0
    s1 = s1->outs->to;
1532
  /* Likewise for any trailing EMPTY arc */
1533
0
  if (s2->nins == 1 && s2->ins->type == EMPTY)
1534
0
    s2 = s2->ins->from;
1535
  /* Perhaps we could have a single-state loop in between, if so reject */
1536
0
  if (s1 == s2)
1537
0
    return NULL;
1538
  /* s1 must have at least one outarc... */
1539
0
  if (s1->outs == NULL)
1540
0
    return NULL;
1541
  /* ... and they must all be PLAIN arcs to s2 */
1542
0
  for (a = s1->outs; a != NULL; a = a->outchain)
1543
0
  {
1544
0
    if (a->type != PLAIN || a->to != s2)
1545
0
      return NULL;
1546
0
  }
1547
  /* OK, return s1 as the possessor of the relevant outarcs */
1548
0
  return s1;
1549
0
}
1550
1551
/*
1552
 * specialcolors - fill in special colors for an NFA
1553
 */
1554
static void
1555
specialcolors(struct nfa *nfa)
1556
0
{
1557
  /* false colors for BOS, BOL, EOS, EOL */
1558
0
  if (nfa->parent == NULL)
1559
0
  {
1560
0
    nfa->bos[0] = pseudocolor(nfa->cm);
1561
0
    nfa->bos[1] = pseudocolor(nfa->cm);
1562
0
    nfa->eos[0] = pseudocolor(nfa->cm);
1563
0
    nfa->eos[1] = pseudocolor(nfa->cm);
1564
0
  }
1565
0
  else
1566
0
  {
1567
0
    assert(nfa->parent->bos[0] != COLORLESS);
1568
0
    nfa->bos[0] = nfa->parent->bos[0];
1569
0
    assert(nfa->parent->bos[1] != COLORLESS);
1570
0
    nfa->bos[1] = nfa->parent->bos[1];
1571
0
    assert(nfa->parent->eos[0] != COLORLESS);
1572
0
    nfa->eos[0] = nfa->parent->eos[0];
1573
0
    assert(nfa->parent->eos[1] != COLORLESS);
1574
0
    nfa->eos[1] = nfa->parent->eos[1];
1575
0
  }
1576
0
}
1577
1578
/*
1579
 * optimize - optimize an NFA
1580
 *
1581
 * The main goal of this function is not so much "optimization" (though it
1582
 * does try to get rid of useless NFA states) as reducing the NFA to a form
1583
 * the regex executor can handle.  The executor, and indeed the cNFA format
1584
 * that is its input, can only handle PLAIN and LACON arcs.  The output of
1585
 * the regex parser also includes EMPTY (do-nothing) arcs, as well as
1586
 * ^, $, AHEAD, and BEHIND constraint arcs, which we must get rid of here.
1587
 * We first get rid of EMPTY arcs and then deal with the constraint arcs.
1588
 * The hardest part of either job is to get rid of circular loops of the
1589
 * target arc type.  We would have to do that in any case, though, as such a
1590
 * loop would otherwise allow the executor to cycle through the loop endlessly
1591
 * without making any progress in the input string.
1592
 */
1593
static long           /* re_info bits */
1594
optimize(struct nfa *nfa,
1595
     FILE *f)       /* for debug output; NULL none */
1596
0
{
1597
#ifdef REG_DEBUG
1598
  int     verbose = (f != NULL) ? 1 : 0;
1599
1600
  if (verbose)
1601
    fprintf(f, "\ninitial cleanup:\n");
1602
#endif
1603
  /* If we have any CANTMATCH arcs, drop them; but this is uncommon */
1604
0
  if (nfa->flags & HASCANTMATCH)
1605
0
  {
1606
0
    removecantmatch(nfa);
1607
0
    nfa->flags &= ~HASCANTMATCH;
1608
0
  }
1609
0
  cleanup(nfa);       /* may simplify situation */
1610
#ifdef REG_DEBUG
1611
  if (verbose)
1612
    dumpnfa(nfa, f);
1613
  if (verbose)
1614
    fprintf(f, "\nempties:\n");
1615
#endif
1616
0
  fixempties(nfa, f);     /* get rid of EMPTY arcs */
1617
#ifdef REG_DEBUG
1618
  if (verbose)
1619
    fprintf(f, "\nconstraints:\n");
1620
#endif
1621
0
  fixconstraintloops(nfa, f); /* get rid of constraint loops */
1622
0
  pullback(nfa, f);     /* pull back constraints backward */
1623
0
  pushfwd(nfa, f);      /* push fwd constraints forward */
1624
#ifdef REG_DEBUG
1625
  if (verbose)
1626
    fprintf(f, "\nfinal cleanup:\n");
1627
#endif
1628
0
  cleanup(nfa);       /* final tidying */
1629
#ifdef REG_DEBUG
1630
  if (verbose)
1631
    dumpnfa(nfa, f);
1632
#endif
1633
0
  return analyze(nfa);    /* and analysis */
1634
0
}
1635
1636
/*
1637
 * pullback - pull back constraints backward to eliminate them
1638
 */
1639
static void
1640
pullback(struct nfa *nfa,
1641
     FILE *f)       /* for debug output; NULL none */
1642
0
{
1643
0
  struct state *s;
1644
0
  struct state *nexts;
1645
0
  struct arc *a;
1646
0
  struct arc *nexta;
1647
0
  struct state *intermediates;
1648
0
  int     progress;
1649
1650
  /* find and pull until there are no more */
1651
0
  do
1652
0
  {
1653
0
    progress = 0;
1654
0
    for (s = nfa->states; s != NULL && !NISERR(); s = nexts)
1655
0
    {
1656
0
      nexts = s->next;
1657
0
      intermediates = NULL;
1658
0
      for (a = s->outs; a != NULL && !NISERR(); a = nexta)
1659
0
      {
1660
0
        nexta = a->outchain;
1661
0
        if (a->type == '^' || a->type == BEHIND)
1662
0
          if (pull(nfa, a, &intermediates))
1663
0
            progress = 1;
1664
0
      }
1665
      /* clear tmp fields of intermediate states created here */
1666
0
      while (intermediates != NULL)
1667
0
      {
1668
0
        struct state *ns = intermediates->tmp;
1669
1670
0
        intermediates->tmp = NULL;
1671
0
        intermediates = ns;
1672
0
      }
1673
      /* if s is now useless, get rid of it */
1674
0
      if ((s->nins == 0 || s->nouts == 0) && !s->flag)
1675
0
        dropstate(nfa, s);
1676
0
    }
1677
0
    if (progress && f != NULL)
1678
0
      dumpnfa(nfa, f);
1679
0
  } while (progress && !NISERR());
1680
0
  if (NISERR())
1681
0
    return;
1682
1683
  /*
1684
   * Any ^ constraints we were able to pull to the start state can now be
1685
   * replaced by PLAIN arcs referencing the BOS or BOL colors.  There should
1686
   * be no other ^ or BEHIND arcs left in the NFA, though we do not check
1687
   * that here (compact() will fail if so).
1688
   */
1689
0
  for (a = nfa->pre->outs; a != NULL; a = nexta)
1690
0
  {
1691
0
    nexta = a->outchain;
1692
0
    if (a->type == '^')
1693
0
    {
1694
0
      assert(a->co == 0 || a->co == 1);
1695
0
      newarc(nfa, PLAIN, nfa->bos[a->co], a->from, a->to);
1696
0
      freearc(nfa, a);
1697
0
    }
1698
0
  }
1699
0
}
1700
1701
/*
1702
 * pull - pull a back constraint backward past its source state
1703
 *
1704
 * Returns 1 if successful (which it always is unless the source is the
1705
 * start state or we have an internal error), 0 if nothing happened.
1706
 *
1707
 * A significant property of this function is that it deletes no pre-existing
1708
 * states, and no outarcs of the constraint's from state other than the given
1709
 * constraint arc.  This makes the loops in pullback() safe, at the cost that
1710
 * we may leave useless states behind.  Therefore, we leave it to pullback()
1711
 * to delete such states.
1712
 *
1713
 * If the from state has multiple back-constraint outarcs, and/or multiple
1714
 * compatible constraint inarcs, we only need to create one new intermediate
1715
 * state per combination of predecessor and successor states.  *intermediates
1716
 * points to a list of such intermediate states for this from state (chained
1717
 * through their tmp fields).
1718
 */
1719
static int
1720
pull(struct nfa *nfa,
1721
   struct arc *con,
1722
   struct state **intermediates)
1723
0
{
1724
0
  struct state *from = con->from;
1725
0
  struct state *to = con->to;
1726
0
  struct arc *a;
1727
0
  struct arc *nexta;
1728
0
  struct state *s;
1729
1730
0
  assert(from != to);     /* should have gotten rid of this earlier */
1731
0
  if (from->flag)       /* can't pull back beyond start */
1732
0
    return 0;
1733
0
  if (from->nins == 0)
1734
0
  {             /* unreachable */
1735
0
    freearc(nfa, con);
1736
0
    return 1;
1737
0
  }
1738
1739
  /*
1740
   * First, clone from state if necessary to avoid other outarcs.  This may
1741
   * seem wasteful, but it simplifies the logic, and we'll get rid of the
1742
   * clone state again at the bottom.
1743
   */
1744
0
  if (from->nouts > 1)
1745
0
  {
1746
0
    s = newstate(nfa);
1747
0
    if (NISERR())
1748
0
      return 0;
1749
0
    copyins(nfa, from, s);  /* duplicate inarcs */
1750
0
    cparc(nfa, con, s, to); /* move constraint arc */
1751
0
    freearc(nfa, con);
1752
0
    if (NISERR())
1753
0
      return 0;
1754
0
    from = s;
1755
0
    con = from->outs;
1756
0
  }
1757
0
  assert(from->nouts == 1);
1758
1759
  /* propagate the constraint into the from state's inarcs */
1760
0
  for (a = from->ins; a != NULL && !NISERR(); a = nexta)
1761
0
  {
1762
0
    nexta = a->inchain;
1763
0
    switch (combine(nfa, con, a))
1764
0
    {
1765
0
      case INCOMPATIBLE: /* destroy the arc */
1766
0
        freearc(nfa, a);
1767
0
        break;
1768
0
      case SATISFIED:   /* no action needed */
1769
0
        break;
1770
0
      case COMPATIBLE: /* swap the two arcs, more or less */
1771
        /* need an intermediate state, but might have one already */
1772
0
        for (s = *intermediates; s != NULL; s = s->tmp)
1773
0
        {
1774
0
          assert(s->nins > 0 && s->nouts > 0);
1775
0
          if (s->ins->from == a->from && s->outs->to == to)
1776
0
            break;
1777
0
        }
1778
0
        if (s == NULL)
1779
0
        {
1780
0
          s = newstate(nfa);
1781
0
          if (NISERR())
1782
0
            return 0;
1783
0
          s->tmp = *intermediates;
1784
0
          *intermediates = s;
1785
0
        }
1786
0
        cparc(nfa, con, a->from, s);
1787
0
        cparc(nfa, a, s, to);
1788
0
        freearc(nfa, a);
1789
0
        break;
1790
0
      case REPLACEARC: /* replace arc's color */
1791
0
        newarc(nfa, a->type, con->co, a->from, to);
1792
0
        freearc(nfa, a);
1793
0
        break;
1794
0
      default:
1795
0
        assert(NOTREACHED);
1796
0
        break;
1797
0
    }
1798
0
  }
1799
1800
  /* remaining inarcs, if any, incorporate the constraint */
1801
0
  moveins(nfa, from, to);
1802
0
  freearc(nfa, con);
1803
  /* from state is now useless, but we leave it to pullback() to clean up */
1804
0
  return 1;
1805
0
}
1806
1807
/*
1808
 * pushfwd - push forward constraints forward to eliminate them
1809
 */
1810
static void
1811
pushfwd(struct nfa *nfa,
1812
    FILE *f)        /* for debug output; NULL none */
1813
0
{
1814
0
  struct state *s;
1815
0
  struct state *nexts;
1816
0
  struct arc *a;
1817
0
  struct arc *nexta;
1818
0
  struct state *intermediates;
1819
0
  int     progress;
1820
1821
  /* find and push until there are no more */
1822
0
  do
1823
0
  {
1824
0
    progress = 0;
1825
0
    for (s = nfa->states; s != NULL && !NISERR(); s = nexts)
1826
0
    {
1827
0
      nexts = s->next;
1828
0
      intermediates = NULL;
1829
0
      for (a = s->ins; a != NULL && !NISERR(); a = nexta)
1830
0
      {
1831
0
        nexta = a->inchain;
1832
0
        if (a->type == '$' || a->type == AHEAD)
1833
0
          if (push(nfa, a, &intermediates))
1834
0
            progress = 1;
1835
0
      }
1836
      /* clear tmp fields of intermediate states created here */
1837
0
      while (intermediates != NULL)
1838
0
      {
1839
0
        struct state *ns = intermediates->tmp;
1840
1841
0
        intermediates->tmp = NULL;
1842
0
        intermediates = ns;
1843
0
      }
1844
      /* if s is now useless, get rid of it */
1845
0
      if ((s->nins == 0 || s->nouts == 0) && !s->flag)
1846
0
        dropstate(nfa, s);
1847
0
    }
1848
0
    if (progress && f != NULL)
1849
0
      dumpnfa(nfa, f);
1850
0
  } while (progress && !NISERR());
1851
0
  if (NISERR())
1852
0
    return;
1853
1854
  /*
1855
   * Any $ constraints we were able to push to the post state can now be
1856
   * replaced by PLAIN arcs referencing the EOS or EOL colors.  There should
1857
   * be no other $ or AHEAD arcs left in the NFA, though we do not check
1858
   * that here (compact() will fail if so).
1859
   */
1860
0
  for (a = nfa->post->ins; a != NULL; a = nexta)
1861
0
  {
1862
0
    nexta = a->inchain;
1863
0
    if (a->type == '$')
1864
0
    {
1865
0
      assert(a->co == 0 || a->co == 1);
1866
0
      newarc(nfa, PLAIN, nfa->eos[a->co], a->from, a->to);
1867
0
      freearc(nfa, a);
1868
0
    }
1869
0
  }
1870
0
}
1871
1872
/*
1873
 * push - push a forward constraint forward past its destination state
1874
 *
1875
 * Returns 1 if successful (which it always is unless the destination is the
1876
 * post state or we have an internal error), 0 if nothing happened.
1877
 *
1878
 * A significant property of this function is that it deletes no pre-existing
1879
 * states, and no inarcs of the constraint's to state other than the given
1880
 * constraint arc.  This makes the loops in pushfwd() safe, at the cost that
1881
 * we may leave useless states behind.  Therefore, we leave it to pushfwd()
1882
 * to delete such states.
1883
 *
1884
 * If the to state has multiple forward-constraint inarcs, and/or multiple
1885
 * compatible constraint outarcs, we only need to create one new intermediate
1886
 * state per combination of predecessor and successor states.  *intermediates
1887
 * points to a list of such intermediate states for this to state (chained
1888
 * through their tmp fields).
1889
 */
1890
static int
1891
push(struct nfa *nfa,
1892
   struct arc *con,
1893
   struct state **intermediates)
1894
0
{
1895
0
  struct state *from = con->from;
1896
0
  struct state *to = con->to;
1897
0
  struct arc *a;
1898
0
  struct arc *nexta;
1899
0
  struct state *s;
1900
1901
0
  assert(to != from);     /* should have gotten rid of this earlier */
1902
0
  if (to->flag)       /* can't push forward beyond end */
1903
0
    return 0;
1904
0
  if (to->nouts == 0)
1905
0
  {             /* dead end */
1906
0
    freearc(nfa, con);
1907
0
    return 1;
1908
0
  }
1909
1910
  /*
1911
   * First, clone to state if necessary to avoid other inarcs.  This may
1912
   * seem wasteful, but it simplifies the logic, and we'll get rid of the
1913
   * clone state again at the bottom.
1914
   */
1915
0
  if (to->nins > 1)
1916
0
  {
1917
0
    s = newstate(nfa);
1918
0
    if (NISERR())
1919
0
      return 0;
1920
0
    copyouts(nfa, to, s); /* duplicate outarcs */
1921
0
    cparc(nfa, con, from, s); /* move constraint arc */
1922
0
    freearc(nfa, con);
1923
0
    if (NISERR())
1924
0
      return 0;
1925
0
    to = s;
1926
0
    con = to->ins;
1927
0
  }
1928
0
  assert(to->nins == 1);
1929
1930
  /* propagate the constraint into the to state's outarcs */
1931
0
  for (a = to->outs; a != NULL && !NISERR(); a = nexta)
1932
0
  {
1933
0
    nexta = a->outchain;
1934
0
    switch (combine(nfa, con, a))
1935
0
    {
1936
0
      case INCOMPATIBLE: /* destroy the arc */
1937
0
        freearc(nfa, a);
1938
0
        break;
1939
0
      case SATISFIED:   /* no action needed */
1940
0
        break;
1941
0
      case COMPATIBLE: /* swap the two arcs, more or less */
1942
        /* need an intermediate state, but might have one already */
1943
0
        for (s = *intermediates; s != NULL; s = s->tmp)
1944
0
        {
1945
0
          assert(s->nins > 0 && s->nouts > 0);
1946
0
          if (s->ins->from == from && s->outs->to == a->to)
1947
0
            break;
1948
0
        }
1949
0
        if (s == NULL)
1950
0
        {
1951
0
          s = newstate(nfa);
1952
0
          if (NISERR())
1953
0
            return 0;
1954
0
          s->tmp = *intermediates;
1955
0
          *intermediates = s;
1956
0
        }
1957
0
        cparc(nfa, con, s, a->to);
1958
0
        cparc(nfa, a, from, s);
1959
0
        freearc(nfa, a);
1960
0
        break;
1961
0
      case REPLACEARC: /* replace arc's color */
1962
0
        newarc(nfa, a->type, con->co, from, a->to);
1963
0
        freearc(nfa, a);
1964
0
        break;
1965
0
      default:
1966
0
        assert(NOTREACHED);
1967
0
        break;
1968
0
    }
1969
0
  }
1970
1971
  /* remaining outarcs, if any, incorporate the constraint */
1972
0
  moveouts(nfa, to, from);
1973
0
  freearc(nfa, con);
1974
  /* to state is now useless, but we leave it to pushfwd() to clean up */
1975
0
  return 1;
1976
0
}
1977
1978
/*
1979
 * combine - constraint lands on an arc, what happens?
1980
 *
1981
 * #def INCOMPATIBLE  1 // destroys arc
1982
 * #def SATISFIED   2 // constraint satisfied
1983
 * #def COMPATIBLE    3 // compatible but not satisfied yet
1984
 * #def REPLACEARC    4 // replace arc's color with constraint color
1985
 */
1986
static int
1987
combine(struct nfa *nfa,
1988
    struct arc *con,
1989
    struct arc *a)
1990
0
{
1991
0
#define  CA(ct,at)   (((ct)<<CHAR_BIT) | (at))
1992
1993
0
  switch (CA(con->type, a->type))
1994
0
  {
1995
0
    case CA('^', PLAIN): /* newlines are handled separately */
1996
0
    case CA('$', PLAIN):
1997
0
      return INCOMPATIBLE;
1998
0
      break;
1999
0
    case CA(AHEAD, PLAIN): /* color constraints meet colors */
2000
0
    case CA(BEHIND, PLAIN):
2001
0
      if (con->co == a->co)
2002
0
        return SATISFIED;
2003
0
      if (con->co == RAINBOW)
2004
0
      {
2005
        /* con is satisfied unless arc's color is a pseudocolor */
2006
0
        if (!(nfa->cm->cd[a->co].flags & PSEUDO))
2007
0
          return SATISFIED;
2008
0
      }
2009
0
      else if (a->co == RAINBOW)
2010
0
      {
2011
        /* con is incompatible if it's for a pseudocolor */
2012
        /* (this is hypothetical; we make no such constraints today) */
2013
0
        if (nfa->cm->cd[con->co].flags & PSEUDO)
2014
0
          return INCOMPATIBLE;
2015
        /* otherwise, constraint constrains arc to be only its color */
2016
0
        return REPLACEARC;
2017
0
      }
2018
0
      return INCOMPATIBLE;
2019
0
      break;
2020
0
    case CA('^', '^'):   /* collision, similar constraints */
2021
0
    case CA('$', '$'):
2022
0
      if (con->co == a->co) /* true duplication */
2023
0
        return SATISFIED;
2024
0
      return INCOMPATIBLE;
2025
0
      break;
2026
0
    case CA(AHEAD, AHEAD): /* collision, similar constraints */
2027
0
    case CA(BEHIND, BEHIND):
2028
0
      if (con->co == a->co) /* true duplication */
2029
0
        return SATISFIED;
2030
0
      if (con->co == RAINBOW)
2031
0
      {
2032
        /* con is satisfied unless arc's color is a pseudocolor */
2033
0
        if (!(nfa->cm->cd[a->co].flags & PSEUDO))
2034
0
          return SATISFIED;
2035
0
      }
2036
0
      else if (a->co == RAINBOW)
2037
0
      {
2038
        /* con is incompatible if it's for a pseudocolor */
2039
        /* (this is hypothetical; we make no such constraints today) */
2040
0
        if (nfa->cm->cd[con->co].flags & PSEUDO)
2041
0
          return INCOMPATIBLE;
2042
        /* otherwise, constraint constrains arc to be only its color */
2043
0
        return REPLACEARC;
2044
0
      }
2045
0
      return INCOMPATIBLE;
2046
0
      break;
2047
0
    case CA('^', BEHIND):  /* collision, dissimilar constraints */
2048
0
    case CA(BEHIND, '^'):
2049
0
    case CA('$', AHEAD):
2050
0
    case CA(AHEAD, '$'):
2051
0
      return INCOMPATIBLE;
2052
0
      break;
2053
0
    case CA('^', '$'):   /* constraints passing each other */
2054
0
    case CA('^', AHEAD):
2055
0
    case CA(BEHIND, '$'):
2056
0
    case CA(BEHIND, AHEAD):
2057
0
    case CA('$', '^'):
2058
0
    case CA('$', BEHIND):
2059
0
    case CA(AHEAD, '^'):
2060
0
    case CA(AHEAD, BEHIND):
2061
0
    case CA('^', LACON):
2062
0
    case CA(BEHIND, LACON):
2063
0
    case CA('$', LACON):
2064
0
    case CA(AHEAD, LACON):
2065
0
      return COMPATIBLE;
2066
0
      break;
2067
0
  }
2068
0
  assert(NOTREACHED);
2069
0
  return INCOMPATIBLE;   /* for benefit of blind compilers */
2070
0
}
2071
2072
/*
2073
 * fixempties - get rid of EMPTY arcs
2074
 */
2075
static void
2076
fixempties(struct nfa *nfa,
2077
       FILE *f)       /* for debug output; NULL none */
2078
0
{
2079
0
  struct state *s;
2080
0
  struct state *s2;
2081
0
  struct state *nexts;
2082
0
  struct arc *a;
2083
0
  struct arc *nexta;
2084
0
  int     totalinarcs;
2085
0
  struct arc **inarcsorig;
2086
0
  struct arc **arcarray;
2087
0
  int     arccount;
2088
0
  int     prevnins;
2089
0
  int     nskip;
2090
2091
  /*
2092
   * First, get rid of any states whose sole out-arc is an EMPTY, since
2093
   * they're basically just aliases for their successor.  The parsing
2094
   * algorithm creates enough of these that it's worth special-casing this.
2095
   */
2096
0
  for (s = nfa->states; s != NULL && !NISERR(); s = nexts)
2097
0
  {
2098
0
    nexts = s->next;
2099
0
    if (s->flag || s->nouts != 1)
2100
0
      continue;
2101
0
    a = s->outs;
2102
0
    assert(a != NULL && a->outchain == NULL);
2103
0
    if (a->type != EMPTY)
2104
0
      continue;
2105
0
    if (s != a->to)
2106
0
      moveins(nfa, s, a->to);
2107
0
    dropstate(nfa, s);
2108
0
  }
2109
2110
  /*
2111
   * Similarly, get rid of any state with a single EMPTY in-arc, by folding
2112
   * it into its predecessor.
2113
   */
2114
0
  for (s = nfa->states; s != NULL && !NISERR(); s = nexts)
2115
0
  {
2116
0
    nexts = s->next;
2117
    /* while we're at it, ensure tmp fields are clear for next step */
2118
0
    assert(s->tmp == NULL);
2119
0
    if (s->flag || s->nins != 1)
2120
0
      continue;
2121
0
    a = s->ins;
2122
0
    assert(a != NULL && a->inchain == NULL);
2123
0
    if (a->type != EMPTY)
2124
0
      continue;
2125
0
    if (s != a->from)
2126
0
      moveouts(nfa, s, a->from);
2127
0
    dropstate(nfa, s);
2128
0
  }
2129
2130
0
  if (NISERR())
2131
0
    return;
2132
2133
  /*
2134
   * For each remaining NFA state, find all other states from which it is
2135
   * reachable by a chain of one or more EMPTY arcs.  Then generate new arcs
2136
   * that eliminate the need for each such chain.
2137
   *
2138
   * We could replace a chain of EMPTY arcs that leads from a "from" state
2139
   * to a "to" state either by pushing non-EMPTY arcs forward (linking
2140
   * directly from "from"'s predecessors to "to") or by pulling them back
2141
   * (linking directly from "from" to "to"'s successors).  We choose to
2142
   * always do the former; this choice is somewhat arbitrary, but the
2143
   * approach below requires that we uniformly do one or the other.
2144
   *
2145
   * Suppose we have a chain of N successive EMPTY arcs (where N can easily
2146
   * approach the size of the NFA).  All of the intermediate states must
2147
   * have additional inarcs and outarcs, else they'd have been removed by
2148
   * the steps above.  Assuming their inarcs are mostly not empties, we will
2149
   * add O(N^2) arcs to the NFA, since a non-EMPTY inarc leading to any one
2150
   * state in the chain must be duplicated to lead to all its successor
2151
   * states as well.  So there is no hope of doing less than O(N^2) work;
2152
   * however, we should endeavor to keep the big-O cost from being even
2153
   * worse than that, which it can easily become without care.  In
2154
   * particular, suppose we were to copy all S1's inarcs forward to S2, and
2155
   * then also to S3, and then later we consider pushing S2's inarcs forward
2156
   * to S3.  If we include the arcs already copied from S1 in that, we'd be
2157
   * doing O(N^3) work.  (The duplicate-arc elimination built into newarc()
2158
   * and its cohorts would get rid of the extra arcs, but not without cost.)
2159
   *
2160
   * We can avoid this cost by treating only arcs that existed at the start
2161
   * of this phase as candidates to be pushed forward.  To identify those,
2162
   * we remember the first inarc each state had to start with.  We rely on
2163
   * the fact that newarc() and friends put new arcs on the front of their
2164
   * to-states' inchains, and that this phase never deletes arcs, so that
2165
   * the original arcs must be the last arcs in their to-states' inchains.
2166
   *
2167
   * So the process here is that, for each state in the NFA, we gather up
2168
   * all non-EMPTY inarcs of states that can reach the target state via
2169
   * EMPTY arcs.  We then sort, de-duplicate, and merge these arcs into the
2170
   * target state's inchain.  (We can safely use sort-merge for this as long
2171
   * as we update each state's original-arcs pointer after we add arcs to
2172
   * it; the sort step of mergeins probably changed the order of the old
2173
   * arcs.)
2174
   *
2175
   * Another refinement worth making is that, because we only add non-EMPTY
2176
   * arcs during this phase, and all added arcs have the same from-state as
2177
   * the non-EMPTY arc they were cloned from, we know ahead of time that any
2178
   * states having only EMPTY outarcs will be useless for lack of outarcs
2179
   * after we drop the EMPTY arcs.  (They cannot gain non-EMPTY outarcs if
2180
   * they had none to start with.)  So we need not bother to update the
2181
   * inchains of such states at all.
2182
   */
2183
2184
  /* Remember the states' first original inarcs */
2185
  /* ... and while at it, count how many old inarcs there are altogether */
2186
0
  inarcsorig = (struct arc **) MALLOC(nfa->nstates * sizeof(struct arc *));
2187
0
  if (inarcsorig == NULL)
2188
0
  {
2189
0
    NERR(REG_ESPACE);
2190
0
    return;
2191
0
  }
2192
0
  totalinarcs = 0;
2193
0
  for (s = nfa->states; s != NULL; s = s->next)
2194
0
  {
2195
0
    inarcsorig[s->no] = s->ins;
2196
0
    totalinarcs += s->nins;
2197
0
  }
2198
2199
  /*
2200
   * Create a workspace for accumulating the inarcs to be added to the
2201
   * current target state.  totalinarcs is probably a considerable
2202
   * overestimate of the space needed, but the NFA is unlikely to be large
2203
   * enough at this point to make it worth being smarter.
2204
   */
2205
0
  arcarray = (struct arc **) MALLOC(totalinarcs * sizeof(struct arc *));
2206
0
  if (arcarray == NULL)
2207
0
  {
2208
0
    NERR(REG_ESPACE);
2209
0
    FREE(inarcsorig);
2210
0
    return;
2211
0
  }
2212
2213
  /* And iterate over the target states */
2214
0
  for (s = nfa->states; s != NULL && !NISERR(); s = s->next)
2215
0
  {
2216
    /* Ignore target states without non-EMPTY outarcs, per note above */
2217
0
    if (!s->flag && !hasnonemptyout(s))
2218
0
      continue;
2219
2220
    /* Find predecessor states and accumulate their original inarcs */
2221
0
    arccount = 0;
2222
0
    for (s2 = emptyreachable(nfa, s, s, inarcsorig); s2 != s; s2 = nexts)
2223
0
    {
2224
      /* Add s2's original inarcs to arcarray[], but ignore empties */
2225
0
      for (a = inarcsorig[s2->no]; a != NULL; a = a->inchain)
2226
0
      {
2227
0
        if (a->type != EMPTY)
2228
0
          arcarray[arccount++] = a;
2229
0
      }
2230
2231
      /* Reset the tmp fields as we walk back */
2232
0
      nexts = s2->tmp;
2233
0
      s2->tmp = NULL;
2234
0
    }
2235
0
    s->tmp = NULL;
2236
0
    assert(arccount <= totalinarcs);
2237
2238
    /* Remember how many original inarcs this state has */
2239
0
    prevnins = s->nins;
2240
2241
    /* Add non-duplicate inarcs to target state */
2242
0
    mergeins(nfa, s, arcarray, arccount);
2243
2244
    /* Now we must update the state's inarcsorig pointer */
2245
0
    nskip = s->nins - prevnins;
2246
0
    a = s->ins;
2247
0
    while (nskip-- > 0)
2248
0
      a = a->inchain;
2249
0
    inarcsorig[s->no] = a;
2250
0
  }
2251
2252
0
  FREE(arcarray);
2253
0
  FREE(inarcsorig);
2254
2255
0
  if (NISERR())
2256
0
    return;
2257
2258
  /*
2259
   * Now remove all the EMPTY arcs, since we don't need them anymore.
2260
   */
2261
0
  for (s = nfa->states; s != NULL; s = s->next)
2262
0
  {
2263
0
    for (a = s->outs; a != NULL; a = nexta)
2264
0
    {
2265
0
      nexta = a->outchain;
2266
0
      if (a->type == EMPTY)
2267
0
        freearc(nfa, a);
2268
0
    }
2269
0
  }
2270
2271
  /*
2272
   * And remove any states that have become useless.  (This cleanup is not
2273
   * very thorough, and would be even less so if we tried to combine it with
2274
   * the previous step; but cleanup() will take care of anything we miss.)
2275
   */
2276
0
  for (s = nfa->states; s != NULL; s = nexts)
2277
0
  {
2278
0
    nexts = s->next;
2279
0
    if ((s->nins == 0 || s->nouts == 0) && !s->flag)
2280
0
      dropstate(nfa, s);
2281
0
  }
2282
2283
0
  if (f != NULL)
2284
0
    dumpnfa(nfa, f);
2285
0
}
2286
2287
/*
2288
 * emptyreachable - recursively find all states that can reach s by EMPTY arcs
2289
 *
2290
 * The return value is the last such state found.  Its tmp field links back
2291
 * to the next-to-last such state, and so on back to s, so that all these
2292
 * states can be located without searching the whole NFA.
2293
 *
2294
 * Since this is only used in fixempties(), we pass in the inarcsorig[] array
2295
 * maintained by that function.  This lets us skip over all new inarcs, which
2296
 * are certainly not EMPTY arcs.
2297
 *
2298
 * The maximum recursion depth here is equal to the length of the longest
2299
 * loop-free chain of EMPTY arcs, which is surely no more than the size of
2300
 * the NFA ... but that could still be enough to cause trouble.
2301
 */
2302
static struct state *
2303
emptyreachable(struct nfa *nfa,
2304
         struct state *s,
2305
         struct state *lastfound,
2306
         struct arc **inarcsorig)
2307
0
{
2308
0
  struct arc *a;
2309
2310
  /* Since this is recursive, it could be driven to stack overflow */
2311
0
  if (STACK_TOO_DEEP(nfa->v->re))
2312
0
  {
2313
0
    NERR(REG_ETOOBIG);
2314
0
    return lastfound;
2315
0
  }
2316
2317
0
  s->tmp = lastfound;
2318
0
  lastfound = s;
2319
0
  for (a = inarcsorig[s->no]; a != NULL; a = a->inchain)
2320
0
  {
2321
0
    if (a->type == EMPTY && a->from->tmp == NULL)
2322
0
      lastfound = emptyreachable(nfa, a->from, lastfound, inarcsorig);
2323
0
  }
2324
0
  return lastfound;
2325
0
}
2326
2327
/*
2328
 * isconstraintarc - detect whether an arc is of a constraint type
2329
 */
2330
static inline int
2331
isconstraintarc(struct arc *a)
2332
0
{
2333
0
  switch (a->type)
2334
0
  {
2335
0
    case '^':
2336
0
    case '$':
2337
0
    case BEHIND:
2338
0
    case AHEAD:
2339
0
    case LACON:
2340
0
      return 1;
2341
0
  }
2342
0
  return 0;
2343
0
}
2344
2345
/*
2346
 * hasconstraintout - does state have a constraint out arc?
2347
 */
2348
static int
2349
hasconstraintout(struct state *s)
2350
0
{
2351
0
  struct arc *a;
2352
2353
0
  for (a = s->outs; a != NULL; a = a->outchain)
2354
0
  {
2355
0
    if (isconstraintarc(a))
2356
0
      return 1;
2357
0
  }
2358
0
  return 0;
2359
0
}
2360
2361
/*
2362
 * fixconstraintloops - get rid of loops containing only constraint arcs
2363
 *
2364
 * A loop of states that contains only constraint arcs is useless, since
2365
 * passing around the loop represents no forward progress.  Moreover, it
2366
 * would cause infinite looping in pullback/pushfwd, so we need to get rid
2367
 * of such loops before doing that.
2368
 */
2369
static void
2370
fixconstraintloops(struct nfa *nfa,
2371
           FILE *f)   /* for debug output; NULL none */
2372
0
{
2373
0
  struct state *s;
2374
0
  struct state *nexts;
2375
0
  struct arc *a;
2376
0
  struct arc *nexta;
2377
0
  int     hasconstraints;
2378
2379
  /*
2380
   * In the trivial case of a state that loops to itself, we can just drop
2381
   * the constraint arc altogether.  This is worth special-casing because
2382
   * such loops are far more common than loops containing multiple states.
2383
   * While we're at it, note whether any constraint arcs survive.
2384
   */
2385
0
  hasconstraints = 0;
2386
0
  for (s = nfa->states; s != NULL && !NISERR(); s = nexts)
2387
0
  {
2388
0
    nexts = s->next;
2389
    /* while we're at it, ensure tmp fields are clear for next step */
2390
0
    assert(s->tmp == NULL);
2391
0
    for (a = s->outs; a != NULL && !NISERR(); a = nexta)
2392
0
    {
2393
0
      nexta = a->outchain;
2394
0
      if (isconstraintarc(a))
2395
0
      {
2396
0
        if (a->to == s)
2397
0
          freearc(nfa, a);
2398
0
        else
2399
0
          hasconstraints = 1;
2400
0
      }
2401
0
    }
2402
    /* If we removed all the outarcs, the state is useless. */
2403
0
    if (s->nouts == 0 && !s->flag)
2404
0
      dropstate(nfa, s);
2405
0
  }
2406
2407
  /* Nothing to do if no remaining constraint arcs */
2408
0
  if (NISERR() || !hasconstraints)
2409
0
    return;
2410
2411
  /*
2412
   * Starting from each remaining NFA state, search outwards for a
2413
   * constraint loop.  If we find a loop, break the loop, then start the
2414
   * search over.  (We could possibly retain some state from the first scan,
2415
   * but it would complicate things greatly, and multi-state constraint
2416
   * loops are rare enough that it's not worth optimizing the case.)
2417
   */
2418
0
restart:
2419
0
  for (s = nfa->states; s != NULL && !NISERR(); s = s->next)
2420
0
  {
2421
0
    if (findconstraintloop(nfa, s))
2422
0
      goto restart;
2423
0
  }
2424
2425
0
  if (NISERR())
2426
0
    return;
2427
2428
  /*
2429
   * Now remove any states that have become useless.  (This cleanup is not
2430
   * very thorough, and would be even less so if we tried to combine it with
2431
   * the previous step; but cleanup() will take care of anything we miss.)
2432
   *
2433
   * Because findconstraintloop intentionally doesn't reset all tmp fields,
2434
   * we have to clear them after it's done.  This is a convenient place to
2435
   * do that, too.
2436
   */
2437
0
  for (s = nfa->states; s != NULL; s = nexts)
2438
0
  {
2439
0
    nexts = s->next;
2440
0
    s->tmp = NULL;
2441
0
    if ((s->nins == 0 || s->nouts == 0) && !s->flag)
2442
0
      dropstate(nfa, s);
2443
0
  }
2444
2445
0
  if (f != NULL)
2446
0
    dumpnfa(nfa, f);
2447
0
}
2448
2449
/*
2450
 * findconstraintloop - recursively find a loop of constraint arcs
2451
 *
2452
 * If we find a loop, break it by calling breakconstraintloop(), then
2453
 * return 1; otherwise return 0.
2454
 *
2455
 * State tmp fields are guaranteed all NULL on a success return, because
2456
 * breakconstraintloop does that.  After a failure return, any state that
2457
 * is known not to be part of a loop is marked with s->tmp == s; this allows
2458
 * us not to have to re-prove that fact on later calls.  (This convention is
2459
 * workable because we already eliminated single-state loops.)
2460
 *
2461
 * Note that the found loop doesn't necessarily include the first state we
2462
 * are called on.  Any loop reachable from that state will do.
2463
 *
2464
 * The maximum recursion depth here is one more than the length of the longest
2465
 * loop-free chain of constraint arcs, which is surely no more than the size
2466
 * of the NFA ... but that could still be enough to cause trouble.
2467
 */
2468
static int
2469
findconstraintloop(struct nfa *nfa, struct state *s)
2470
0
{
2471
0
  struct arc *a;
2472
2473
  /* Since this is recursive, it could be driven to stack overflow */
2474
0
  if (STACK_TOO_DEEP(nfa->v->re))
2475
0
  {
2476
0
    NERR(REG_ETOOBIG);
2477
0
    return 1;       /* to exit as quickly as possible */
2478
0
  }
2479
2480
0
  if (s->tmp != NULL)
2481
0
  {
2482
    /* Already proven uninteresting? */
2483
0
    if (s->tmp == s)
2484
0
      return 0;
2485
    /* Found a loop involving s */
2486
0
    breakconstraintloop(nfa, s);
2487
    /* The tmp fields have been cleaned up by breakconstraintloop */
2488
0
    return 1;
2489
0
  }
2490
0
  for (a = s->outs; a != NULL; a = a->outchain)
2491
0
  {
2492
0
    if (isconstraintarc(a))
2493
0
    {
2494
0
      struct state *sto = a->to;
2495
2496
0
      assert(sto != s);
2497
0
      s->tmp = sto;
2498
0
      if (findconstraintloop(nfa, sto))
2499
0
        return 1;
2500
0
    }
2501
0
  }
2502
2503
  /*
2504
   * If we get here, no constraint loop exists leading out from s.  Mark it
2505
   * with s->tmp == s so we need not rediscover that fact again later.
2506
   */
2507
0
  s->tmp = s;
2508
0
  return 0;
2509
0
}
2510
2511
/*
2512
 * breakconstraintloop - break a loop of constraint arcs
2513
 *
2514
 * sinitial is any one member state of the loop.  Each loop member's tmp
2515
 * field links to its successor within the loop.  (Note that this function
2516
 * will reset all the tmp fields to NULL.)
2517
 *
2518
 * We can break the loop by, for any one state S1 in the loop, cloning its
2519
 * loop successor state S2 (and possibly following states), and then moving
2520
 * all S1->S2 constraint arcs to point to the cloned S2.  The cloned S2 should
2521
 * copy any non-constraint outarcs of S2.  Constraint outarcs should be
2522
 * dropped if they point back to S1, else they need to be copied as arcs to
2523
 * similarly cloned states S3, S4, etc.  In general, each cloned state copies
2524
 * non-constraint outarcs, drops constraint outarcs that would lead to itself
2525
 * or any earlier cloned state, and sends other constraint outarcs to newly
2526
 * cloned states.  No cloned state will have any inarcs that aren't constraint
2527
 * arcs or do not lead from S1 or earlier-cloned states.  It's okay to drop
2528
 * constraint back-arcs since they would not take us to any state we've not
2529
 * already been in; therefore, no new constraint loop is created.  In this way
2530
 * we generate a modified NFA that can still represent every useful state
2531
 * sequence, but not sequences that represent state loops with no consumption
2532
 * of input data.  Note that the set of cloned states will certainly include
2533
 * all of the loop member states other than S1, and it may also include
2534
 * non-loop states that are reachable from S2 via constraint arcs.  This is
2535
 * important because there is no guarantee that findconstraintloop found a
2536
 * maximal loop (and searching for one would be NP-hard, so don't try).
2537
 * Frequently the "non-loop states" are actually part of a larger loop that
2538
 * we didn't notice, and indeed there may be several overlapping loops.
2539
 * This technique ensures convergence in such cases, while considering only
2540
 * the originally-found loop does not.
2541
 *
2542
 * If there is only one S1->S2 constraint arc, then that constraint is
2543
 * certainly satisfied when we enter any of the clone states.  This means that
2544
 * in the common case where many of the constraint arcs are identically
2545
 * labeled, we can merge together clone states linked by a similarly-labeled
2546
 * constraint: if we can get to the first one we can certainly get to the
2547
 * second, so there's no need to distinguish.  This greatly reduces the number
2548
 * of new states needed, so we preferentially break the given loop at a state
2549
 * pair where this is true.
2550
 *
2551
 * Furthermore, it's fairly common to find that a cloned successor state has
2552
 * no outarcs, especially if we're a bit aggressive about removing unnecessary
2553
 * outarcs.  If that happens, then there is simply not any interesting state
2554
 * that can be reached through the predecessor's loop arcs, which means we can
2555
 * break the loop just by removing those loop arcs, with no new states added.
2556
 */
2557
static void
2558
breakconstraintloop(struct nfa *nfa, struct state *sinitial)
2559
0
{
2560
0
  struct state *s;
2561
0
  struct state *shead;
2562
0
  struct state *stail;
2563
0
  struct state *sclone;
2564
0
  struct state *nexts;
2565
0
  struct arc *refarc;
2566
0
  struct arc *a;
2567
0
  struct arc *nexta;
2568
2569
  /*
2570
   * Start by identifying which loop step we want to break at.
2571
   * Preferentially this is one with only one constraint arc.  (XXX are
2572
   * there any other secondary heuristics we want to use here?)  Set refarc
2573
   * to point to the selected lone constraint arc, if there is one.
2574
   */
2575
0
  refarc = NULL;
2576
0
  s = sinitial;
2577
0
  do
2578
0
  {
2579
0
    nexts = s->tmp;
2580
0
    assert(nexts != s);   /* should not see any one-element loops */
2581
0
    if (refarc == NULL)
2582
0
    {
2583
0
      int     narcs = 0;
2584
2585
0
      for (a = s->outs; a != NULL; a = a->outchain)
2586
0
      {
2587
0
        if (a->to == nexts && isconstraintarc(a))
2588
0
        {
2589
0
          refarc = a;
2590
0
          narcs++;
2591
0
        }
2592
0
      }
2593
0
      assert(narcs > 0);
2594
0
      if (narcs > 1)
2595
0
        refarc = NULL; /* multiple constraint arcs here, no good */
2596
0
    }
2597
0
    s = nexts;
2598
0
  } while (s != sinitial);
2599
2600
0
  if (refarc)
2601
0
  {
2602
    /* break at the refarc */
2603
0
    shead = refarc->from;
2604
0
    stail = refarc->to;
2605
0
    assert(stail == shead->tmp);
2606
0
  }
2607
0
  else
2608
0
  {
2609
    /* for lack of a better idea, break after sinitial */
2610
0
    shead = sinitial;
2611
0
    stail = sinitial->tmp;
2612
0
  }
2613
2614
  /*
2615
   * Reset the tmp fields so that we can use them for local storage in
2616
   * clonesuccessorstates.  (findconstraintloop won't mind, since it's just
2617
   * going to abandon its search anyway.)
2618
   */
2619
0
  for (s = nfa->states; s != NULL; s = s->next)
2620
0
    s->tmp = NULL;
2621
2622
  /*
2623
   * Recursively build clone state(s) as needed.
2624
   */
2625
0
  sclone = newstate(nfa);
2626
0
  if (sclone == NULL)
2627
0
  {
2628
0
    assert(NISERR());
2629
0
    return;
2630
0
  }
2631
2632
0
  clonesuccessorstates(nfa, stail, sclone, shead, refarc,
2633
0
             NULL, NULL, nfa->nstates);
2634
2635
0
  if (NISERR())
2636
0
    return;
2637
2638
  /*
2639
   * It's possible that sclone has no outarcs at all, in which case it's
2640
   * useless.  (We don't try extremely hard to get rid of useless states
2641
   * here, but this is an easy and fairly common case.)
2642
   */
2643
0
  if (sclone->nouts == 0)
2644
0
  {
2645
0
    freestate(nfa, sclone);
2646
0
    sclone = NULL;
2647
0
  }
2648
2649
  /*
2650
   * Move shead's constraint-loop arcs to point to sclone, or just drop them
2651
   * if we discovered we don't need sclone.
2652
   */
2653
0
  for (a = shead->outs; a != NULL; a = nexta)
2654
0
  {
2655
0
    nexta = a->outchain;
2656
0
    if (a->to == stail && isconstraintarc(a))
2657
0
    {
2658
0
      if (sclone)
2659
0
        cparc(nfa, a, shead, sclone);
2660
0
      freearc(nfa, a);
2661
0
      if (NISERR())
2662
0
        break;
2663
0
    }
2664
0
  }
2665
0
}
2666
2667
/*
2668
 * clonesuccessorstates - create a tree of constraint-arc successor states
2669
 *
2670
 * ssource is the state to be cloned, and sclone is the state to copy its
2671
 * outarcs into.  sclone's inarcs, if any, should already be set up.
2672
 *
2673
 * spredecessor is the original predecessor state that we are trying to build
2674
 * successors for (it may not be the immediate predecessor of ssource).
2675
 * refarc, if not NULL, is the original constraint arc that is known to have
2676
 * been traversed out of spredecessor to reach the successor(s).
2677
 *
2678
 * For each cloned successor state, we transiently create a "donemap" that is
2679
 * a boolean array showing which source states we've already visited for this
2680
 * clone state.  This prevents infinite recursion as well as useless repeat
2681
 * visits to the same state subtree (which can add up fast, since typical NFAs
2682
 * have multiple redundant arc pathways).  Each donemap is a char array
2683
 * indexed by state number.  The donemaps are all of the same size "nstates",
2684
 * which is nfa->nstates as of the start of the recursion.  This is enough to
2685
 * have entries for all pre-existing states, but *not* entries for clone
2686
 * states created during the recursion.  That's okay since we have no need to
2687
 * mark those.
2688
 *
2689
 * curdonemap is NULL when recursing to a new sclone state, or sclone's
2690
 * donemap when we are recursing without having created a new state (which we
2691
 * do when we decide we can merge a successor state into the current clone
2692
 * state).  outerdonemap is NULL at the top level and otherwise the parent
2693
 * clone state's donemap.
2694
 *
2695
 * The successor states we create and fill here form a strict tree structure,
2696
 * with each state having exactly one predecessor, except that the toplevel
2697
 * state has no inarcs as yet (breakconstraintloop will add its inarcs from
2698
 * spredecessor after we're done).  Thus, we can examine sclone's inarcs back
2699
 * to the root, plus refarc if any, to identify the set of constraints already
2700
 * known valid at the current point.  This allows us to avoid generating extra
2701
 * successor states.
2702
 */
2703
static void
2704
clonesuccessorstates(struct nfa *nfa,
2705
           struct state *ssource,
2706
           struct state *sclone,
2707
           struct state *spredecessor,
2708
           struct arc *refarc,
2709
           char *curdonemap,
2710
           char *outerdonemap,
2711
           int nstates)
2712
0
{
2713
0
  char     *donemap;
2714
0
  struct arc *a;
2715
2716
  /* Since this is recursive, it could be driven to stack overflow */
2717
0
  if (STACK_TOO_DEEP(nfa->v->re))
2718
0
  {
2719
0
    NERR(REG_ETOOBIG);
2720
0
    return;
2721
0
  }
2722
2723
  /* If this state hasn't already got a donemap, create one */
2724
0
  donemap = curdonemap;
2725
0
  if (donemap == NULL)
2726
0
  {
2727
0
    donemap = (char *) MALLOC(nstates * sizeof(char));
2728
0
    if (donemap == NULL)
2729
0
    {
2730
0
      NERR(REG_ESPACE);
2731
0
      return;
2732
0
    }
2733
2734
0
    if (outerdonemap != NULL)
2735
0
    {
2736
      /*
2737
       * Not at outermost recursion level, so copy the outer level's
2738
       * donemap; this ensures that we see states in process of being
2739
       * visited at outer levels, or already merged into predecessor
2740
       * states, as ones we shouldn't traverse back to.
2741
       */
2742
0
      memcpy(donemap, outerdonemap, nstates * sizeof(char));
2743
0
    }
2744
0
    else
2745
0
    {
2746
      /* At outermost level, only spredecessor is off-limits */
2747
0
      memset(donemap, 0, nstates * sizeof(char));
2748
0
      assert(spredecessor->no < nstates);
2749
0
      donemap[spredecessor->no] = 1;
2750
0
    }
2751
0
  }
2752
2753
  /* Mark ssource as visited in the donemap */
2754
0
  assert(ssource->no < nstates);
2755
0
  assert(donemap[ssource->no] == 0);
2756
0
  donemap[ssource->no] = 1;
2757
2758
  /*
2759
   * We proceed by first cloning all of ssource's outarcs, creating new
2760
   * clone states as needed but not doing more with them than that.  Then in
2761
   * a second pass, recurse to process the child clone states.  This allows
2762
   * us to have only one child clone state per reachable source state, even
2763
   * when there are multiple outarcs leading to the same state.  Also, when
2764
   * we do visit a child state, its set of inarcs is known exactly, which
2765
   * makes it safe to apply the constraint-is-already-checked optimization.
2766
   * Also, this ensures that we've merged all the states we can into the
2767
   * current clone before we recurse to any children, thus possibly saving
2768
   * them from making extra images of those states.
2769
   *
2770
   * While this function runs, child clone states of the current state are
2771
   * marked by setting their tmp fields to point to the original state they
2772
   * were cloned from.  This makes it possible to detect multiple outarcs
2773
   * leading to the same state, and also makes it easy to distinguish clone
2774
   * states from original states (which will have tmp == NULL).
2775
   */
2776
0
  for (a = ssource->outs; a != NULL && !NISERR(); a = a->outchain)
2777
0
  {
2778
0
    struct state *sto = a->to;
2779
2780
    /*
2781
     * We do not consider cloning successor states that have no constraint
2782
     * outarcs; just link to them as-is.  They cannot be part of a
2783
     * constraint loop so there is no need to make copies.  In particular,
2784
     * this rule keeps us from trying to clone the post state, which would
2785
     * be a bad idea.
2786
     */
2787
0
    if (isconstraintarc(a) && hasconstraintout(sto))
2788
0
    {
2789
0
      struct state *prevclone;
2790
0
      int     canmerge;
2791
0
      struct arc *a2;
2792
2793
      /*
2794
       * Back-link constraint arcs must not be followed.  Nor is there a
2795
       * need to revisit states previously merged into this clone.
2796
       */
2797
0
      assert(sto->no < nstates);
2798
0
      if (donemap[sto->no] != 0)
2799
0
        continue;
2800
2801
      /*
2802
       * Check whether we already have a child clone state for this
2803
       * source state.
2804
       */
2805
0
      prevclone = NULL;
2806
0
      for (a2 = sclone->outs; a2 != NULL; a2 = a2->outchain)
2807
0
      {
2808
0
        if (a2->to->tmp == sto)
2809
0
        {
2810
0
          prevclone = a2->to;
2811
0
          break;
2812
0
        }
2813
0
      }
2814
2815
      /*
2816
       * If this arc is labeled the same as refarc, or the same as any
2817
       * arc we must have traversed to get to sclone, then no additional
2818
       * constraints need to be met to get to sto, so we should just
2819
       * merge its outarcs into sclone.
2820
       */
2821
0
      if (refarc && a->type == refarc->type && a->co == refarc->co)
2822
0
        canmerge = 1;
2823
0
      else
2824
0
      {
2825
0
        struct state *s;
2826
2827
0
        canmerge = 0;
2828
0
        for (s = sclone; s->ins; s = s->ins->from)
2829
0
        {
2830
0
          if (s->nins == 1 &&
2831
0
            a->type == s->ins->type && a->co == s->ins->co)
2832
0
          {
2833
0
            canmerge = 1;
2834
0
            break;
2835
0
          }
2836
0
        }
2837
0
      }
2838
2839
0
      if (canmerge)
2840
0
      {
2841
        /*
2842
         * We can merge into sclone.  If we previously made a child
2843
         * clone state, drop it; there's no need to visit it.  (This
2844
         * can happen if ssource has multiple pathways to sto, and we
2845
         * only just now found one that is provably a no-op.)
2846
         */
2847
0
        if (prevclone)
2848
0
          dropstate(nfa, prevclone); /* kills our outarc, too */
2849
2850
        /* Recurse to merge sto's outarcs into sclone */
2851
0
        clonesuccessorstates(nfa,
2852
0
                   sto,
2853
0
                   sclone,
2854
0
                   spredecessor,
2855
0
                   refarc,
2856
0
                   donemap,
2857
0
                   outerdonemap,
2858
0
                   nstates);
2859
        /* sto should now be marked as previously visited */
2860
0
        assert(NISERR() || donemap[sto->no] == 1);
2861
0
      }
2862
0
      else if (prevclone)
2863
0
      {
2864
        /*
2865
         * We already have a clone state for this successor, so just
2866
         * make another arc to it.
2867
         */
2868
0
        cparc(nfa, a, sclone, prevclone);
2869
0
      }
2870
0
      else
2871
0
      {
2872
        /*
2873
         * We need to create a new successor clone state.
2874
         */
2875
0
        struct state *stoclone;
2876
2877
0
        stoclone = newstate(nfa);
2878
0
        if (stoclone == NULL)
2879
0
        {
2880
0
          assert(NISERR());
2881
0
          break;
2882
0
        }
2883
        /* Mark it as to what it's a clone of */
2884
0
        stoclone->tmp = sto;
2885
        /* ... and add the outarc leading to it */
2886
0
        cparc(nfa, a, sclone, stoclone);
2887
0
      }
2888
0
    }
2889
0
    else
2890
0
    {
2891
      /*
2892
       * Non-constraint outarcs just get copied to sclone, as do outarcs
2893
       * leading to states with no constraint outarc.
2894
       */
2895
0
      cparc(nfa, a, sclone, sto);
2896
0
    }
2897
0
  }
2898
2899
  /*
2900
   * If we are at outer level for this clone state, recurse to all its child
2901
   * clone states, clearing their tmp fields as we go.  (If we're not
2902
   * outermost for sclone, leave this to be done by the outer call level.)
2903
   * Note that if we have multiple outarcs leading to the same clone state,
2904
   * it will only be recursed-to once.
2905
   */
2906
0
  if (curdonemap == NULL)
2907
0
  {
2908
0
    for (a = sclone->outs; a != NULL && !NISERR(); a = a->outchain)
2909
0
    {
2910
0
      struct state *stoclone = a->to;
2911
0
      struct state *sto = stoclone->tmp;
2912
2913
0
      if (sto != NULL)
2914
0
      {
2915
0
        stoclone->tmp = NULL;
2916
0
        clonesuccessorstates(nfa,
2917
0
                   sto,
2918
0
                   stoclone,
2919
0
                   spredecessor,
2920
0
                   refarc,
2921
0
                   NULL,
2922
0
                   donemap,
2923
0
                   nstates);
2924
0
      }
2925
0
    }
2926
2927
    /* Don't forget to free sclone's donemap when done with it */
2928
0
    FREE(donemap);
2929
0
  }
2930
0
}
2931
2932
/*
2933
 * removecantmatch - remove CANTMATCH arcs, which are no longer useful
2934
 * once we are done with the parsing phase.  (We need them only to
2935
 * preserve connectedness of NFA subgraphs during parsing.)
2936
 */
2937
static void
2938
removecantmatch(struct nfa *nfa)
2939
0
{
2940
0
  struct state *s;
2941
2942
0
  for (s = nfa->states; s != NULL; s = s->next)
2943
0
  {
2944
0
    struct arc *a;
2945
0
    struct arc *nexta;
2946
2947
0
    for (a = s->outs; a != NULL; a = nexta)
2948
0
    {
2949
0
      nexta = a->outchain;
2950
0
      if (a->type == CANTMATCH)
2951
0
      {
2952
0
        freearc(nfa, a);
2953
0
        if (NISERR())
2954
0
          return;
2955
0
      }
2956
0
    }
2957
0
  }
2958
0
}
2959
2960
/*
2961
 * cleanup - clean up NFA after optimizations
2962
 */
2963
static void
2964
cleanup(struct nfa *nfa)
2965
0
{
2966
0
  struct state *s;
2967
0
  struct state *nexts;
2968
0
  int     n;
2969
2970
0
  if (NISERR())
2971
0
    return;
2972
2973
  /* clear out unreachable or dead-end states */
2974
  /* use pre to mark reachable, then post to mark can-reach-post */
2975
0
  markreachable(nfa, nfa->pre, (struct state *) NULL, nfa->pre);
2976
0
  markcanreach(nfa, nfa->post, nfa->pre, nfa->post);
2977
0
  for (s = nfa->states; s != NULL && !NISERR(); s = nexts)
2978
0
  {
2979
0
    nexts = s->next;
2980
0
    if (s->tmp != nfa->post && !s->flag)
2981
0
      dropstate(nfa, s);
2982
0
  }
2983
0
  assert(NISERR() || nfa->post->nins == 0 || nfa->post->tmp == nfa->post);
2984
0
  cleartraverse(nfa, nfa->pre);
2985
0
  assert(NISERR() || nfa->post->nins == 0 || nfa->post->tmp == NULL);
2986
  /* the nins==0 (final unreachable) case will be caught later */
2987
2988
  /* renumber surviving states */
2989
0
  n = 0;
2990
0
  for (s = nfa->states; s != NULL; s = s->next)
2991
0
    s->no = n++;
2992
0
  nfa->nstates = n;
2993
0
}
2994
2995
/*
2996
 * markreachable - recursive marking of reachable states
2997
 */
2998
static void
2999
markreachable(struct nfa *nfa,
3000
        struct state *s,
3001
        struct state *okay, /* consider only states with this mark */
3002
        struct state *mark) /* the value to mark with */
3003
0
{
3004
0
  struct arc *a;
3005
3006
  /* Since this is recursive, it could be driven to stack overflow */
3007
0
  if (STACK_TOO_DEEP(nfa->v->re))
3008
0
  {
3009
0
    NERR(REG_ETOOBIG);
3010
0
    return;
3011
0
  }
3012
3013
0
  if (s->tmp != okay)
3014
0
    return;
3015
0
  s->tmp = mark;
3016
3017
0
  for (a = s->outs; a != NULL; a = a->outchain)
3018
0
    markreachable(nfa, a->to, okay, mark);
3019
0
}
3020
3021
/*
3022
 * markcanreach - recursive marking of states which can reach here
3023
 */
3024
static void
3025
markcanreach(struct nfa *nfa,
3026
       struct state *s,
3027
       struct state *okay,  /* consider only states with this mark */
3028
       struct state *mark)  /* the value to mark with */
3029
0
{
3030
0
  struct arc *a;
3031
3032
  /* Since this is recursive, it could be driven to stack overflow */
3033
0
  if (STACK_TOO_DEEP(nfa->v->re))
3034
0
  {
3035
0
    NERR(REG_ETOOBIG);
3036
0
    return;
3037
0
  }
3038
3039
0
  if (s->tmp != okay)
3040
0
    return;
3041
0
  s->tmp = mark;
3042
3043
0
  for (a = s->ins; a != NULL; a = a->inchain)
3044
0
    markcanreach(nfa, a->from, okay, mark);
3045
0
}
3046
3047
/*
3048
 * analyze - ascertain potentially-useful facts about an optimized NFA
3049
 */
3050
static long           /* re_info bits to be ORed in */
3051
analyze(struct nfa *nfa)
3052
0
{
3053
0
  struct arc *a;
3054
0
  struct arc *aa;
3055
3056
0
  if (NISERR())
3057
0
    return 0;
3058
3059
  /* Detect whether NFA can't match anything */
3060
0
  if (nfa->pre->outs == NULL)
3061
0
    return REG_UIMPOSSIBLE;
3062
3063
  /* Detect whether NFA matches all strings (possibly with length bounds) */
3064
0
  checkmatchall(nfa);
3065
3066
  /* Detect whether NFA can possibly match a zero-length string */
3067
0
  for (a = nfa->pre->outs; a != NULL; a = a->outchain)
3068
0
    for (aa = a->to->outs; aa != NULL; aa = aa->outchain)
3069
0
      if (aa->to == nfa->post)
3070
0
        return REG_UEMPTYMATCH;
3071
0
  return 0;
3072
0
}
3073
3074
/*
3075
 * checkmatchall - does the NFA represent no more than a string length test?
3076
 *
3077
 * If so, set nfa->minmatchall and nfa->maxmatchall correctly (they are -1
3078
 * to begin with) and set the MATCHALL bit in nfa->flags.
3079
 *
3080
 * To succeed, we require all arcs to be PLAIN RAINBOW arcs, except for those
3081
 * for pseudocolors (i.e., BOS/BOL/EOS/EOL).  We must be able to reach the
3082
 * post state via RAINBOW arcs, and if there are any loops in the graph, they
3083
 * must be loop-to-self arcs, ensuring that each loop iteration consumes
3084
 * exactly one character.  (Longer loops are problematic because they create
3085
 * non-consecutive possible match lengths; we have no good way to represent
3086
 * that situation for lengths beyond the DUPINF limit.)
3087
 *
3088
 * Pseudocolor arcs complicate things a little.  We know that they can only
3089
 * appear as pre-state outarcs (for BOS/BOL) or post-state inarcs (for
3090
 * EOS/EOL).  There, they must exactly replicate the parallel RAINBOW arcs,
3091
 * e.g. if the pre state has one RAINBOW outarc to state 2, it must have BOS
3092
 * and BOL outarcs to state 2, and no others.  Missing or extra pseudocolor
3093
 * arcs can occur, meaning that the NFA involves some constraint on the
3094
 * adjacent characters, which makes it not a matchall NFA.
3095
 */
3096
static void
3097
checkmatchall(struct nfa *nfa)
3098
0
{
3099
0
  bool    **haspaths;
3100
0
  struct state *s;
3101
0
  int     i;
3102
3103
  /*
3104
   * If there are too many states, don't bother trying to detect matchall.
3105
   * This limit serves to bound the time and memory we could consume below.
3106
   * Note that even if the graph is all-RAINBOW, if there are significantly
3107
   * more than DUPINF states then it's likely that there are paths of length
3108
   * more than DUPINF, which would force us to fail anyhow.  In practice,
3109
   * plausible ways of writing a matchall regex with maximum finite path
3110
   * length K tend not to have very many more than K states.
3111
   */
3112
0
  if (nfa->nstates > DUPINF * 2)
3113
0
    return;
3114
3115
  /*
3116
   * First, scan all the states to verify that only RAINBOW arcs appear,
3117
   * plus pseudocolor arcs adjacent to the pre and post states.  This lets
3118
   * us quickly eliminate most cases that aren't matchall NFAs.
3119
   */
3120
0
  for (s = nfa->states; s != NULL; s = s->next)
3121
0
  {
3122
0
    struct arc *a;
3123
3124
0
    for (a = s->outs; a != NULL; a = a->outchain)
3125
0
    {
3126
0
      if (a->type != PLAIN)
3127
0
        return;     /* any LACONs make it non-matchall */
3128
0
      if (a->co != RAINBOW)
3129
0
      {
3130
0
        if (nfa->cm->cd[a->co].flags & PSEUDO)
3131
0
        {
3132
          /*
3133
           * Pseudocolor arc: verify it's in a valid place (this
3134
           * seems quite unlikely to fail, but let's be sure).
3135
           */
3136
0
          if (s == nfa->pre &&
3137
0
            (a->co == nfa->bos[0] || a->co == nfa->bos[1]))
3138
0
             /* okay BOS/BOL arc */ ;
3139
0
          else if (a->to == nfa->post &&
3140
0
               (a->co == nfa->eos[0] || a->co == nfa->eos[1]))
3141
0
             /* okay EOS/EOL arc */ ;
3142
0
          else
3143
0
            return; /* unexpected pseudocolor arc */
3144
          /* We'll check these arcs some more below. */
3145
0
        }
3146
0
        else
3147
0
          return;   /* any other color makes it non-matchall */
3148
0
      }
3149
0
    }
3150
    /* Also, assert that the tmp fields are available for use. */
3151
0
    assert(s->tmp == NULL);
3152
0
  }
3153
3154
  /*
3155
   * The next cheapest check we can make is to verify that the BOS/BOL
3156
   * outarcs of the pre state reach the same states as its RAINBOW outarcs.
3157
   * If they don't, the NFA expresses some constraints on the character
3158
   * before the matched string, making it non-matchall.  Likewise, the
3159
   * EOS/EOL inarcs of the post state must match its RAINBOW inarcs.
3160
   */
3161
0
  if (!check_out_colors_match(nfa->pre, RAINBOW, nfa->bos[0]) ||
3162
0
    !check_out_colors_match(nfa->pre, RAINBOW, nfa->bos[1]) ||
3163
0
    !check_in_colors_match(nfa->post, RAINBOW, nfa->eos[0]) ||
3164
0
    !check_in_colors_match(nfa->post, RAINBOW, nfa->eos[1]))
3165
0
    return;
3166
3167
  /*
3168
   * Initialize an array of path-length arrays, in which
3169
   * checkmatchall_recurse will return per-state results.  This lets us
3170
   * memo-ize the recursive search and avoid exponential time consumption.
3171
   */
3172
0
  haspaths = (bool **) MALLOC(nfa->nstates * sizeof(bool *));
3173
0
  if (haspaths == NULL)
3174
0
    return;         /* fail quietly */
3175
0
  memset(haspaths, 0, nfa->nstates * sizeof(bool *));
3176
3177
  /*
3178
   * Recursively search the graph for all-RAINBOW paths to the "post" state,
3179
   * starting at the "pre" state, and computing the lengths of the paths.
3180
   * (Given the preceding checks, there should be at least one such path.
3181
   * However we could get back a false result anyway, in case there are
3182
   * multi-state loops, paths exceeding DUPINF+1 length, or non-algorithmic
3183
   * failures such as ENOMEM.)
3184
   */
3185
0
  if (checkmatchall_recurse(nfa, nfa->pre, haspaths))
3186
0
  {
3187
    /* The useful result is the path length array for the pre state */
3188
0
    bool     *haspath = haspaths[nfa->pre->no];
3189
0
    int     minmatch,
3190
0
          maxmatch,
3191
0
          morematch;
3192
3193
0
    assert(haspath != NULL);
3194
3195
    /*
3196
     * haspath[] now represents the set of possible path lengths; but we
3197
     * want to reduce that to a min and max value, because it doesn't seem
3198
     * worth complicating regexec.c to deal with nonconsecutive possible
3199
     * match lengths.  Find min and max of first run of lengths, then
3200
     * verify there are no nonconsecutive lengths.
3201
     */
3202
0
    for (minmatch = 0; minmatch <= DUPINF + 1; minmatch++)
3203
0
    {
3204
0
      if (haspath[minmatch])
3205
0
        break;
3206
0
    }
3207
0
    assert(minmatch <= DUPINF + 1); /* else checkmatchall_recurse lied */
3208
0
    for (maxmatch = minmatch; maxmatch < DUPINF + 1; maxmatch++)
3209
0
    {
3210
0
      if (!haspath[maxmatch + 1])
3211
0
        break;
3212
0
    }
3213
0
    for (morematch = maxmatch + 1; morematch <= DUPINF + 1; morematch++)
3214
0
    {
3215
0
      if (haspath[morematch])
3216
0
      {
3217
0
        haspath = NULL; /* fail, there are nonconsecutive lengths */
3218
0
        break;
3219
0
      }
3220
0
    }
3221
3222
0
    if (haspath != NULL)
3223
0
    {
3224
      /*
3225
       * Success, so record the info.  Here we have a fine point: the
3226
       * path length from the pre state includes the pre-to-initial
3227
       * transition, so it's one more than the actually matched string
3228
       * length.  (We avoided counting the final-to-post transition
3229
       * within checkmatchall_recurse, but not this one.)  This is why
3230
       * checkmatchall_recurse allows one more level of path length than
3231
       * might seem necessary.  This decrement also takes care of
3232
       * converting checkmatchall_recurse's definition of "infinity" as
3233
       * "DUPINF+1" to our normal representation as "DUPINF".
3234
       */
3235
0
      assert(minmatch > 0); /* else pre and post states were adjacent */
3236
0
      nfa->minmatchall = minmatch - 1;
3237
0
      nfa->maxmatchall = maxmatch - 1;
3238
0
      nfa->flags |= MATCHALL;
3239
0
    }
3240
0
  }
3241
3242
  /* Clean up */
3243
0
  for (i = 0; i < nfa->nstates; i++)
3244
0
  {
3245
0
    if (haspaths[i] != NULL)
3246
0
      FREE(haspaths[i]);
3247
0
  }
3248
0
  FREE(haspaths);
3249
0
}
3250
3251
/*
3252
 * checkmatchall_recurse - recursive search for checkmatchall
3253
 *
3254
 * s is the state to be examined in this recursion level.
3255
 * haspaths[] is an array of per-state exit path length arrays.
3256
 *
3257
 * We return true if the search was performed successfully, false if
3258
 * we had to fail because of multi-state loops or other internal reasons.
3259
 * (Because "dead" states that can't reach the post state have been
3260
 * eliminated, and we already verified that only RAINBOW and matching
3261
 * pseudocolor arcs exist, every state should have RAINBOW path(s) to
3262
 * the post state.  Hence we take a false result from recursive calls
3263
 * as meaning that we'd better fail altogether, not just that that
3264
 * particular state can't reach the post state.)
3265
 *
3266
 * On success, we store a malloc'd result array in haspaths[s->no],
3267
 * showing the possible path lengths from s to the post state.
3268
 * Each state's haspath[] array is of length DUPINF+2.  The entries from
3269
 * k = 0 to DUPINF are true if there is an all-RAINBOW path of length k
3270
 * from this state to the string end.  haspath[DUPINF+1] is true if all
3271
 * path lengths >= DUPINF+1 are possible.  (Situations that cannot be
3272
 * represented under these rules cause failure.)
3273
 *
3274
 * checkmatchall is responsible for eventually freeing the haspath[] arrays.
3275
 */
3276
static bool
3277
checkmatchall_recurse(struct nfa *nfa, struct state *s, bool **haspaths)
3278
0
{
3279
0
  bool    result = false;
3280
0
  bool    foundloop = false;
3281
0
  bool     *haspath;
3282
0
  struct arc *a;
3283
3284
  /*
3285
   * Since this is recursive, it could be driven to stack overflow.  But we
3286
   * need not treat that as a hard failure; just deem the NFA non-matchall.
3287
   */
3288
0
  if (STACK_TOO_DEEP(nfa->v->re))
3289
0
    return false;
3290
3291
  /* In case the search takes a long time, check for cancel */
3292
0
  INTERRUPT(nfa->v->re);
3293
3294
  /* Create a haspath array for this state */
3295
0
  haspath = (bool *) MALLOC((DUPINF + 2) * sizeof(bool));
3296
0
  if (haspath == NULL)
3297
0
    return false;     /* again, treat as non-matchall */
3298
0
  memset(haspath, 0, (DUPINF + 2) * sizeof(bool));
3299
3300
  /* Mark this state as being visited */
3301
0
  assert(s->tmp == NULL);
3302
0
  s->tmp = s;
3303
3304
0
  for (a = s->outs; a != NULL; a = a->outchain)
3305
0
  {
3306
0
    if (a->co != RAINBOW)
3307
0
      continue;     /* ignore pseudocolor arcs */
3308
0
    if (a->to == nfa->post)
3309
0
    {
3310
      /* We found an all-RAINBOW path to the post state */
3311
0
      result = true;
3312
3313
      /*
3314
       * Mark this state as being zero steps away from the string end
3315
       * (the transition to the post state isn't counted).
3316
       */
3317
0
      haspath[0] = true;
3318
0
    }
3319
0
    else if (a->to == s)
3320
0
    {
3321
      /* We found a cycle of length 1, which we'll deal with below. */
3322
0
      foundloop = true;
3323
0
    }
3324
0
    else if (a->to->tmp != NULL)
3325
0
    {
3326
      /* It's busy, so we found a cycle of length > 1, so fail. */
3327
0
      result = false;
3328
0
      break;
3329
0
    }
3330
0
    else
3331
0
    {
3332
      /* Consider paths forward through this to-state. */
3333
0
      bool     *nexthaspath;
3334
0
      int     i;
3335
3336
      /* If to-state was not already visited, recurse */
3337
0
      if (haspaths[a->to->no] == NULL)
3338
0
      {
3339
0
        result = checkmatchall_recurse(nfa, a->to, haspaths);
3340
        /* Fail if any recursive path fails */
3341
0
        if (!result)
3342
0
          break;
3343
0
      }
3344
0
      else
3345
0
      {
3346
        /* The previous visit must have found path(s) to the end */
3347
0
        result = true;
3348
0
      }
3349
0
      assert(a->to->tmp == NULL);
3350
0
      nexthaspath = haspaths[a->to->no];
3351
0
      assert(nexthaspath != NULL);
3352
3353
      /*
3354
       * Now, for every path of length i from a->to to the string end,
3355
       * there is a path of length i + 1 from s to the string end.
3356
       */
3357
0
      if (nexthaspath[DUPINF] != nexthaspath[DUPINF + 1])
3358
0
      {
3359
        /*
3360
         * a->to has a path of length exactly DUPINF, but not longer;
3361
         * or it has paths of all lengths > DUPINF but not one of
3362
         * exactly that length.  In either case, we cannot represent
3363
         * the possible path lengths from s correctly, so fail.
3364
         */
3365
0
        result = false;
3366
0
        break;
3367
0
      }
3368
      /* Merge knowledge of these path lengths into what we have */
3369
0
      for (i = 0; i < DUPINF; i++)
3370
0
        haspath[i + 1] |= nexthaspath[i];
3371
      /* Infinity + 1 is still infinity */
3372
0
      haspath[DUPINF + 1] |= nexthaspath[DUPINF + 1];
3373
0
    }
3374
0
  }
3375
3376
0
  if (result && foundloop)
3377
0
  {
3378
    /*
3379
     * If there is a length-1 loop at this state, then find the shortest
3380
     * known path length to the end.  The loop means that every larger
3381
     * path length is possible, too.  (It doesn't matter whether any of
3382
     * the longer lengths were already known possible.)
3383
     */
3384
0
    int     i;
3385
3386
0
    for (i = 0; i <= DUPINF; i++)
3387
0
    {
3388
0
      if (haspath[i])
3389
0
        break;
3390
0
    }
3391
0
    for (i++; i <= DUPINF + 1; i++)
3392
0
      haspath[i] = true;
3393
0
  }
3394
3395
  /* Report out the completed path length map */
3396
0
  assert(s->no < nfa->nstates);
3397
0
  assert(haspaths[s->no] == NULL);
3398
0
  haspaths[s->no] = haspath;
3399
3400
  /* Mark state no longer busy */
3401
0
  s->tmp = NULL;
3402
3403
0
  return result;
3404
0
}
3405
3406
/*
3407
 * check_out_colors_match - subroutine for checkmatchall
3408
 *
3409
 * Check whether the set of states reachable from s by arcs of color co1
3410
 * is equivalent to the set reachable by arcs of color co2.
3411
 * checkmatchall already verified that all of the NFA's arcs are PLAIN,
3412
 * so we need not examine arc types here.
3413
 */
3414
static bool
3415
check_out_colors_match(struct state *s, color co1, color co2)
3416
0
{
3417
0
  bool    result = true;
3418
0
  struct arc *a;
3419
3420
  /*
3421
   * To do this in linear time, we assume that the NFA contains no duplicate
3422
   * arcs.  Run through the out-arcs, marking states reachable by arcs of
3423
   * color co1.  Run through again, un-marking states reachable by arcs of
3424
   * color co2; if we see a not-marked state, we know this co2 arc is
3425
   * unmatched.  Then run through again, checking for still-marked states,
3426
   * and in any case leaving all the tmp fields reset to NULL.
3427
   */
3428
0
  for (a = s->outs; a != NULL; a = a->outchain)
3429
0
  {
3430
0
    if (a->co == co1)
3431
0
    {
3432
0
      assert(a->to->tmp == NULL);
3433
0
      a->to->tmp = a->to;
3434
0
    }
3435
0
  }
3436
0
  for (a = s->outs; a != NULL; a = a->outchain)
3437
0
  {
3438
0
    if (a->co == co2)
3439
0
    {
3440
0
      if (a->to->tmp != NULL)
3441
0
        a->to->tmp = NULL;
3442
0
      else
3443
0
        result = false; /* unmatched co2 arc */
3444
0
    }
3445
0
  }
3446
0
  for (a = s->outs; a != NULL; a = a->outchain)
3447
0
  {
3448
0
    if (a->co == co1)
3449
0
    {
3450
0
      if (a->to->tmp != NULL)
3451
0
      {
3452
0
        result = false; /* unmatched co1 arc */
3453
0
        a->to->tmp = NULL;
3454
0
      }
3455
0
    }
3456
0
  }
3457
0
  return result;
3458
0
}
3459
3460
/*
3461
 * check_in_colors_match - subroutine for checkmatchall
3462
 *
3463
 * Check whether the set of states that can reach s by arcs of color co1
3464
 * is equivalent to the set that can reach s by arcs of color co2.
3465
 * checkmatchall already verified that all of the NFA's arcs are PLAIN,
3466
 * so we need not examine arc types here.
3467
 */
3468
static bool
3469
check_in_colors_match(struct state *s, color co1, color co2)
3470
0
{
3471
0
  bool    result = true;
3472
0
  struct arc *a;
3473
3474
  /*
3475
   * Identical algorithm to check_out_colors_match, except examine the
3476
   * from-states of s' inarcs.
3477
   */
3478
0
  for (a = s->ins; a != NULL; a = a->inchain)
3479
0
  {
3480
0
    if (a->co == co1)
3481
0
    {
3482
0
      assert(a->from->tmp == NULL);
3483
0
      a->from->tmp = a->from;
3484
0
    }
3485
0
  }
3486
0
  for (a = s->ins; a != NULL; a = a->inchain)
3487
0
  {
3488
0
    if (a->co == co2)
3489
0
    {
3490
0
      if (a->from->tmp != NULL)
3491
0
        a->from->tmp = NULL;
3492
0
      else
3493
0
        result = false; /* unmatched co2 arc */
3494
0
    }
3495
0
  }
3496
0
  for (a = s->ins; a != NULL; a = a->inchain)
3497
0
  {
3498
0
    if (a->co == co1)
3499
0
    {
3500
0
      if (a->from->tmp != NULL)
3501
0
      {
3502
0
        result = false; /* unmatched co1 arc */
3503
0
        a->from->tmp = NULL;
3504
0
      }
3505
0
    }
3506
0
  }
3507
0
  return result;
3508
0
}
3509
3510
/*
3511
 * compact - construct the compact representation of an NFA
3512
 */
3513
static void
3514
compact(struct nfa *nfa,
3515
    struct cnfa *cnfa)
3516
0
{
3517
0
  struct state *s;
3518
0
  struct arc *a;
3519
0
  size_t    nstates;
3520
0
  size_t    narcs;
3521
0
  struct carc *ca;
3522
0
  struct carc *first;
3523
3524
0
  assert(!NISERR());
3525
3526
  /*
3527
   * The REG_MAX_COMPILE_SPACE restriction ensures that integer overflow
3528
   * can't occur in this loop nor in the allocation requests below.
3529
   */
3530
0
  nstates = 0;
3531
0
  narcs = 0;
3532
0
  for (s = nfa->states; s != NULL; s = s->next)
3533
0
  {
3534
0
    nstates++;
3535
0
    narcs += s->nouts + 1;  /* need one extra for endmarker */
3536
0
  }
3537
3538
0
  cnfa->stflags = (char *) MALLOC(nstates * sizeof(char));
3539
0
  cnfa->states = (struct carc **) MALLOC(nstates * sizeof(struct carc *));
3540
0
  cnfa->arcs = (struct carc *) MALLOC(narcs * sizeof(struct carc));
3541
0
  if (cnfa->stflags == NULL || cnfa->states == NULL || cnfa->arcs == NULL)
3542
0
  {
3543
0
    if (cnfa->stflags != NULL)
3544
0
      FREE(cnfa->stflags);
3545
0
    if (cnfa->states != NULL)
3546
0
      FREE(cnfa->states);
3547
0
    if (cnfa->arcs != NULL)
3548
0
      FREE(cnfa->arcs);
3549
0
    NERR(REG_ESPACE);
3550
0
    return;
3551
0
  }
3552
0
  cnfa->nstates = nstates;
3553
0
  cnfa->pre = nfa->pre->no;
3554
0
  cnfa->post = nfa->post->no;
3555
0
  cnfa->bos[0] = nfa->bos[0];
3556
0
  cnfa->bos[1] = nfa->bos[1];
3557
0
  cnfa->eos[0] = nfa->eos[0];
3558
0
  cnfa->eos[1] = nfa->eos[1];
3559
0
  cnfa->ncolors = maxcolor(nfa->cm) + 1;
3560
0
  cnfa->flags = nfa->flags;
3561
0
  cnfa->minmatchall = nfa->minmatchall;
3562
0
  cnfa->maxmatchall = nfa->maxmatchall;
3563
3564
0
  ca = cnfa->arcs;
3565
0
  for (s = nfa->states; s != NULL; s = s->next)
3566
0
  {
3567
0
    assert((size_t) s->no < nstates);
3568
0
    cnfa->stflags[s->no] = 0;
3569
0
    cnfa->states[s->no] = ca;
3570
0
    first = ca;
3571
0
    for (a = s->outs; a != NULL; a = a->outchain)
3572
0
      switch (a->type)
3573
0
      {
3574
0
        case PLAIN:
3575
0
          ca->co = a->co;
3576
0
          ca->to = a->to->no;
3577
0
          ca++;
3578
0
          break;
3579
0
        case LACON:
3580
0
          assert(s->no != cnfa->pre);
3581
0
          assert(a->co >= 0);
3582
          /* make sure the modified color number will fit */
3583
0
          if (a->co > MAX_COLOR - cnfa->ncolors)
3584
0
          {
3585
0
            NERR(REG_ECOLORS);
3586
0
            return;
3587
0
          }
3588
0
          ca->co = (color) (cnfa->ncolors + a->co);
3589
0
          ca->to = a->to->no;
3590
0
          ca++;
3591
0
          cnfa->flags |= HASLACONS;
3592
0
          break;
3593
0
        default:
3594
0
          NERR(REG_ASSERT);
3595
0
          return;
3596
0
      }
3597
0
    carcsort(first, ca - first);
3598
0
    ca->co = COLORLESS;
3599
0
    ca->to = 0;
3600
0
    ca++;
3601
0
  }
3602
0
  assert(ca == &cnfa->arcs[narcs]);
3603
0
  assert(cnfa->nstates != 0);
3604
3605
  /* mark no-progress states */
3606
0
  for (a = nfa->pre->outs; a != NULL; a = a->outchain)
3607
0
    cnfa->stflags[a->to->no] = CNFA_NOPROGRESS;
3608
0
  cnfa->stflags[nfa->pre->no] = CNFA_NOPROGRESS;
3609
0
}
3610
3611
/*
3612
 * carcsort - sort compacted-NFA arcs by color
3613
 */
3614
static void
3615
carcsort(struct carc *first, size_t n)
3616
0
{
3617
0
  if (n > 1)
3618
0
    qsort(first, n, sizeof(struct carc), carc_cmp);
3619
0
}
3620
3621
static int
3622
carc_cmp(const void *a, const void *b)
3623
0
{
3624
0
  const struct carc *aa = (const struct carc *) a;
3625
0
  const struct carc *bb = (const struct carc *) b;
3626
3627
0
  if (aa->co < bb->co)
3628
0
    return -1;
3629
0
  if (aa->co > bb->co)
3630
0
    return +1;
3631
0
  if (aa->to < bb->to)
3632
0
    return -1;
3633
0
  if (aa->to > bb->to)
3634
0
    return +1;
3635
  /* This is unreached, since there should be no duplicate arcs now: */
3636
0
  return 0;
3637
0
}
3638
3639
/*
3640
 * freecnfa - free a compacted NFA
3641
 */
3642
static void
3643
freecnfa(struct cnfa *cnfa)
3644
0
{
3645
0
  assert(!NULLCNFA(*cnfa)); /* not empty already */
3646
0
  FREE(cnfa->stflags);
3647
0
  FREE(cnfa->states);
3648
0
  FREE(cnfa->arcs);
3649
0
  ZAPCNFA(*cnfa);
3650
0
}
3651
3652
/*
3653
 * dumpnfa - dump an NFA in human-readable form
3654
 */
3655
static void
3656
dumpnfa(struct nfa *nfa,
3657
    FILE *f)
3658
0
{
3659
#ifdef REG_DEBUG
3660
  struct state *s;
3661
  int     nstates = 0;
3662
  int     narcs = 0;
3663
3664
  fprintf(f, "pre %d, post %d", nfa->pre->no, nfa->post->no);
3665
  if (nfa->bos[0] != COLORLESS)
3666
    fprintf(f, ", bos [%ld]", (long) nfa->bos[0]);
3667
  if (nfa->bos[1] != COLORLESS)
3668
    fprintf(f, ", bol [%ld]", (long) nfa->bos[1]);
3669
  if (nfa->eos[0] != COLORLESS)
3670
    fprintf(f, ", eos [%ld]", (long) nfa->eos[0]);
3671
  if (nfa->eos[1] != COLORLESS)
3672
    fprintf(f, ", eol [%ld]", (long) nfa->eos[1]);
3673
  if (nfa->flags & HASLACONS)
3674
    fprintf(f, ", haslacons");
3675
  if (nfa->flags & HASCANTMATCH)
3676
    fprintf(f, ", hascantmatch");
3677
  if (nfa->flags & MATCHALL)
3678
  {
3679
    fprintf(f, ", minmatchall %d", nfa->minmatchall);
3680
    if (nfa->maxmatchall == DUPINF)
3681
      fprintf(f, ", maxmatchall inf");
3682
    else
3683
      fprintf(f, ", maxmatchall %d", nfa->maxmatchall);
3684
  }
3685
  fprintf(f, "\n");
3686
  for (s = nfa->states; s != NULL; s = s->next)
3687
  {
3688
    dumpstate(s, f);
3689
    nstates++;
3690
    narcs += s->nouts;
3691
  }
3692
  fprintf(f, "total of %d states, %d arcs\n", nstates, narcs);
3693
  if (nfa->parent == NULL)
3694
    dumpcolors(nfa->cm, f);
3695
  fflush(f);
3696
#endif
3697
0
}
3698
3699
#ifdef REG_DEBUG        /* subordinates of dumpnfa */
3700
3701
/*
3702
 * dumpstate - dump an NFA state in human-readable form
3703
 */
3704
static void
3705
dumpstate(struct state *s,
3706
      FILE *f)
3707
{
3708
  struct arc *a;
3709
3710
  fprintf(f, "%d%s%c", s->no, (s->tmp != NULL) ? "T" : "",
3711
      (s->flag) ? s->flag : '.');
3712
  if (s->prev != NULL && s->prev->next != s)
3713
    fprintf(f, "\tstate chain bad\n");
3714
  if (s->nouts == 0)
3715
    fprintf(f, "\tno out arcs\n");
3716
  else
3717
    dumparcs(s, f);
3718
  for (a = s->ins; a != NULL; a = a->inchain)
3719
  {
3720
    if (a->to != s)
3721
      fprintf(f, "\tlink from %d to %d on %d's in-chain\n",
3722
          a->from->no, a->to->no, s->no);
3723
  }
3724
  fflush(f);
3725
}
3726
3727
/*
3728
 * dumparcs - dump out-arcs in human-readable form
3729
 */
3730
static void
3731
dumparcs(struct state *s,
3732
     FILE *f)
3733
{
3734
  int     pos;
3735
  struct arc *a;
3736
3737
  /* printing oldest arcs first is usually clearer */
3738
  a = s->outs;
3739
  assert(a != NULL);
3740
  while (a->outchain != NULL)
3741
    a = a->outchain;
3742
  pos = 1;
3743
  do
3744
  {
3745
    dumparc(a, s, f);
3746
    if (pos == 5)
3747
    {
3748
      fprintf(f, "\n");
3749
      pos = 1;
3750
    }
3751
    else
3752
      pos++;
3753
    a = a->outchainRev;
3754
  } while (a != NULL);
3755
  if (pos != 1)
3756
    fprintf(f, "\n");
3757
}
3758
3759
/*
3760
 * dumparc - dump one outarc in readable form, including prefixing tab
3761
 */
3762
static void
3763
dumparc(struct arc *a,
3764
    struct state *s,
3765
    FILE *f)
3766
{
3767
  struct arc *aa;
3768
3769
  fprintf(f, "\t");
3770
  switch (a->type)
3771
  {
3772
    case PLAIN:
3773
      if (a->co == RAINBOW)
3774
        fprintf(f, "[*]");
3775
      else
3776
        fprintf(f, "[%ld]", (long) a->co);
3777
      break;
3778
    case AHEAD:
3779
      if (a->co == RAINBOW)
3780
        fprintf(f, ">*>");
3781
      else
3782
        fprintf(f, ">%ld>", (long) a->co);
3783
      break;
3784
    case BEHIND:
3785
      if (a->co == RAINBOW)
3786
        fprintf(f, "<*<");
3787
      else
3788
        fprintf(f, "<%ld<", (long) a->co);
3789
      break;
3790
    case LACON:
3791
      fprintf(f, ":%ld:", (long) a->co);
3792
      break;
3793
    case '^':
3794
    case '$':
3795
      fprintf(f, "%c%d", a->type, (int) a->co);
3796
      break;
3797
    case EMPTY:
3798
      break;
3799
    case CANTMATCH:
3800
      fprintf(f, "X");
3801
      break;
3802
    default:
3803
      fprintf(f, "0x%x/0%lo", a->type, (long) a->co);
3804
      break;
3805
  }
3806
  if (a->from != s)
3807
    fprintf(f, "?%d?", a->from->no);
3808
  for (aa = a->from->outs; aa != NULL; aa = aa->outchain)
3809
    if (aa == a)
3810
      break;        /* NOTE BREAK OUT */
3811
  if (aa == NULL)
3812
    fprintf(f, "?!?");    /* missing from out-chain */
3813
  fprintf(f, "->");
3814
  if (a->to == NULL)
3815
  {
3816
    fprintf(f, "NULL");
3817
    return;
3818
  }
3819
  fprintf(f, "%d", a->to->no);
3820
  for (aa = a->to->ins; aa != NULL; aa = aa->inchain)
3821
    if (aa == a)
3822
      break;        /* NOTE BREAK OUT */
3823
  if (aa == NULL)
3824
    fprintf(f, "?!?");    /* missing from in-chain */
3825
}
3826
#endif              /* REG_DEBUG */
3827
3828
/*
3829
 * dumpcnfa - dump a compacted NFA in human-readable form
3830
 */
3831
#ifdef REG_DEBUG
3832
static void
3833
dumpcnfa(struct cnfa *cnfa,
3834
     FILE *f)
3835
{
3836
  int     st;
3837
3838
  fprintf(f, "pre %d, post %d", cnfa->pre, cnfa->post);
3839
  if (cnfa->bos[0] != COLORLESS)
3840
    fprintf(f, ", bos [%ld]", (long) cnfa->bos[0]);
3841
  if (cnfa->bos[1] != COLORLESS)
3842
    fprintf(f, ", bol [%ld]", (long) cnfa->bos[1]);
3843
  if (cnfa->eos[0] != COLORLESS)
3844
    fprintf(f, ", eos [%ld]", (long) cnfa->eos[0]);
3845
  if (cnfa->eos[1] != COLORLESS)
3846
    fprintf(f, ", eol [%ld]", (long) cnfa->eos[1]);
3847
  if (cnfa->flags & HASLACONS)
3848
    fprintf(f, ", haslacons");
3849
  if (cnfa->flags & MATCHALL)
3850
  {
3851
    fprintf(f, ", minmatchall %d", cnfa->minmatchall);
3852
    if (cnfa->maxmatchall == DUPINF)
3853
      fprintf(f, ", maxmatchall inf");
3854
    else
3855
      fprintf(f, ", maxmatchall %d", cnfa->maxmatchall);
3856
  }
3857
  fprintf(f, "\n");
3858
  for (st = 0; st < cnfa->nstates; st++)
3859
    dumpcstate(st, cnfa, f);
3860
  fflush(f);
3861
}
3862
#endif
3863
3864
#ifdef REG_DEBUG        /* subordinates of dumpcnfa */
3865
3866
/*
3867
 * dumpcstate - dump a compacted-NFA state in human-readable form
3868
 */
3869
static void
3870
dumpcstate(int st,
3871
       struct cnfa *cnfa,
3872
       FILE *f)
3873
{
3874
  struct carc *ca;
3875
  int     pos;
3876
3877
  fprintf(f, "%d%s", st, (cnfa->stflags[st] & CNFA_NOPROGRESS) ? ":" : ".");
3878
  pos = 1;
3879
  for (ca = cnfa->states[st]; ca->co != COLORLESS; ca++)
3880
  {
3881
    if (ca->co == RAINBOW)
3882
      fprintf(f, "\t[*]->%d", ca->to);
3883
    else if (ca->co < cnfa->ncolors)
3884
      fprintf(f, "\t[%ld]->%d", (long) ca->co, ca->to);
3885
    else
3886
      fprintf(f, "\t:%ld:->%d", (long) (ca->co - cnfa->ncolors), ca->to);
3887
    if (pos == 5)
3888
    {
3889
      fprintf(f, "\n");
3890
      pos = 1;
3891
    }
3892
    else
3893
      pos++;
3894
  }
3895
  if (ca == cnfa->states[st] || pos != 1)
3896
    fprintf(f, "\n");
3897
  fflush(f);
3898
}
3899
3900
#endif              /* REG_DEBUG */