]>
git.saurik.com Git - wxWidgets.git/blob - src/regex/regc_nfa.c
   3  * This file is #included by regcomp.c. 
   5  * Copyright (c) 1998, 1999 Henry Spencer.      All rights reserved. 
   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 
  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. 
  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. 
  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. 
  34  * One or two things that technically ought to be in here 
  35  * are actually in color.c, thanks to some incestuous relationships in 
  39 #define NISERR()        VISERR(nfa->v) 
  40 #define NERR(e)         VERR(nfa->v, (e)) 
  44  * newnfa - set up an NFA 
  46 static struct nfa 
*                             /* the NFA, or NULL */ 
  47 newnfa(struct vars 
* v
, 
  49            struct nfa 
* parent
)         /* NULL if primary NFA */ 
  53         nfa 
= (struct nfa 
*) MALLOC(sizeof(struct nfa
)); 
  63         nfa
->bos
[0] = nfa
->bos
[1] = COLORLESS
; 
  64         nfa
->eos
[0] = nfa
->eos
[1] = COLORLESS
; 
  65         nfa
->post 
= newfstate(nfa
, '@');        /* number 0 */ 
  66         nfa
->pre 
= newfstate(nfa
, '>');         /* number 1 */ 
  69         nfa
->init 
= newstate(nfa
);      /* may become invalid later */ 
  70         nfa
->final 
= newstate(nfa
); 
  76         rainbow(nfa
, nfa
->cm
, PLAIN
, COLORLESS
, nfa
->pre
, nfa
->init
); 
  77         newarc(nfa
, '^', 1, nfa
->pre
, nfa
->init
); 
  78         newarc(nfa
, '^', 0, nfa
->pre
, nfa
->init
); 
  79         rainbow(nfa
, nfa
->cm
, PLAIN
, COLORLESS
, nfa
->final
, nfa
->post
); 
  80         newarc(nfa
, '$', 1, nfa
->final
, nfa
->post
); 
  81         newarc(nfa
, '$', 0, nfa
->final
, nfa
->post
); 
  92  * freenfa - free an entire NFA 
  95 freenfa(struct nfa 
* nfa
) 
  99         while ((s 
= nfa
->states
) != NULL
) 
 101                 s
->nins 
= s
->nouts 
= 0; /* don't worry about arcs */ 
 104         while ((s 
= nfa
->free
) != NULL
) 
 107                 destroystate(nfa
, s
); 
 118  * newstate - allocate an NFA state, with zero flag value 
 120 static struct state 
*                   /* NULL on error */ 
 121 newstate(struct nfa 
* nfa
) 
 125         if (nfa
->free 
!= NULL
) 
 132                 s 
= (struct state 
*) MALLOC(sizeof(struct state
)); 
 143         assert(nfa
->nstates 
>= 0); 
 144         s
->no 
= nfa
->nstates
++; 
 146         if (nfa
->states 
== NULL
) 
 154         if (nfa
->slast 
!= NULL
) 
 156                 assert(nfa
->slast
->next 
== NULL
); 
 157                 nfa
->slast
->next 
= s
; 
 159         s
->prev 
= nfa
->slast
; 
 165  * newfstate - allocate an NFA state with a specified flag value 
 167 static struct state 
*                   /* NULL on error */ 
 168 newfstate(struct nfa 
* nfa
, int flag
) 
 174                 s
->flag 
= (char) flag
; 
 179  * dropstate - delete a state's inarcs and outarcs and free it 
 182 dropstate(struct nfa 
* nfa
, 
 187         while ((a 
= s
->ins
) != NULL
) 
 189         while ((a 
= s
->outs
) != NULL
) 
 195  * freestate - free a state, which has no in-arcs or out-arcs 
 198 freestate(struct nfa 
* nfa
, 
 202         assert(s
->nins 
== 0 && s
->nouts 
== 0); 
 207                 s
->next
->prev 
= s
->prev
; 
 210                 assert(s 
== nfa
->slast
); 
 211                 nfa
->slast 
= s
->prev
; 
 214                 s
->prev
->next 
= s
->next
; 
 217                 assert(s 
== nfa
->states
); 
 218                 nfa
->states 
= s
->next
; 
 221         s
->next 
= nfa
->free
;            /* don't delete it, put it on the free 
 227  * destroystate - really get rid of an already-freed state 
 230 destroystate(struct nfa 
* nfa
, 
 234         struct arcbatch 
*abnext
; 
 236         assert(s
->no 
== FREESTATE
); 
 237         for (ab 
= s
->oas
.next
; ab 
!= NULL
; ab 
= abnext
) 
 249  * newarc - set up a new arc within an NFA 
 252 newarc(struct nfa 
* nfa
, 
 260         assert(from 
!= NULL 
&& to 
!= NULL
); 
 262         /* check for duplicates */ 
 263         for (a 
= from
->outs
; a 
!= NULL
; a 
= a
->outchain
) 
 264                 if (a
->to 
== to 
&& a
->co 
== co 
&& a
->type 
== t
) 
 267         a 
= allocarc(nfa
, from
); 
 278          * Put the new arc on the beginning, not the end, of the chains. Not 
 279          * only is this easier, it has the very useful side effect that 
 280          * deleting the most-recently-added arc is the cheapest case rather 
 281          * than the most expensive one. 
 283         a
->inchain 
= to
->ins
; 
 285         a
->outchain 
= from
->outs
; 
 291         if (COLORED(a
) && nfa
->parent 
== NULL
) 
 292                 colorchain(nfa
->cm
, a
); 
 298  * allocarc - allocate a new out-arc within a state 
 300 static struct arc 
*                             /* NULL for failure */ 
 301 allocarc(struct nfa 
* nfa
, 
 305         struct arcbatch 
*new; 
 309         if (s
->free 
== NULL 
&& s
->noas 
< ABSIZE
) 
 311                 a 
= &s
->oas
.a
[s
->noas
]; 
 316         /* if none at hand, get more */ 
 319                 new = (struct arcbatch 
*) MALLOC(sizeof(struct arcbatch
)); 
 325                 new->next 
= s
->oas
.next
; 
 328                 for (i 
= 0; i 
< ABSIZE
; i
++) 
 331                         new->a
[i
].freechain 
= &new->a
[i 
+ 1]; 
 333                 new->a
[ABSIZE 
- 1].freechain 
= NULL
; 
 334                 s
->free 
= &new->a
[0]; 
 336         assert(s
->free 
!= NULL
); 
 339         s
->free 
= a
->freechain
; 
 344  * freearc - free an arc 
 347 freearc(struct nfa 
* nfa
, 
 350         struct state 
*from 
= victim
->from
; 
 351         struct state 
*to 
= victim
->to
; 
 354         assert(victim
->type 
!= 0); 
 356         /* take it off color chain if necessary */ 
 357         if (COLORED(victim
) && nfa
->parent 
== NULL
) 
 358                 uncolorchain(nfa
->cm
, victim
); 
 360         /* take it off source's out-chain */ 
 361         assert(from 
!= NULL
); 
 362         assert(from
->outs 
!= NULL
); 
 364         if (a 
== victim
)                        /* simple case:  first in chain */ 
 365                 from
->outs 
= victim
->outchain
; 
 368                 for (; a 
!= NULL 
&& a
->outchain 
!= victim
; a 
= a
->outchain
) 
 371                 a
->outchain 
= victim
->outchain
; 
 375         /* take it off target's in-chain */ 
 377         assert(to
->ins 
!= NULL
); 
 379         if (a 
== victim
)                        /* simple case:  first in chain */ 
 380                 to
->ins 
= victim
->inchain
; 
 383                 for (; a 
!= NULL 
&& a
->inchain 
!= victim
; a 
= a
->inchain
) 
 386                 a
->inchain 
= victim
->inchain
; 
 390         /* clean up and place on free list */ 
 392         victim
->from 
= NULL
;            /* precautions... */ 
 394         victim
->inchain 
= NULL
; 
 395         victim
->outchain 
= NULL
; 
 396         victim
->freechain 
= from
->free
; 
 401  * findarc - find arc, if any, from given source with given type and color 
 402  * If there is more than one such arc, the result is random. 
 405 findarc(struct state 
* s
, 
 411         for (a 
= s
->outs
; a 
!= NULL
; a 
= a
->outchain
) 
 412                 if (a
->type 
== type 
&& a
->co 
== co
) 
 418  * cparc - allocate a new arc within an NFA, copying details from old one 
 421 cparc(struct nfa 
* nfa
, 
 426         newarc(nfa
, oa
->type
, oa
->co
, from
, to
); 
 430  * moveins - move all in arcs of a state to another state 
 432  * You might think this could be done better by just updating the 
 433  * existing arcs, and you would be right if it weren't for the desire 
 434  * for duplicate suppression, which makes it easier to just make new 
 435  * ones to exploit the suppression built into newarc. 
 438 moveins(struct nfa 
* nfa
, 
 446         while ((a 
= old
->ins
) != NULL
) 
 448                 cparc(nfa
, a
, a
->from
, new); 
 451         assert(old
->nins 
== 0); 
 452         assert(old
->ins 
== NULL
); 
 456  * copyins - copy all in arcs of a state to another state 
 459 copyins(struct nfa 
* nfa
, 
 467         for (a 
= old
->ins
; a 
!= NULL
; a 
= a
->inchain
) 
 468                 cparc(nfa
, a
, a
->from
, new); 
 472  * moveouts - move all out arcs of a state to another state 
 475 moveouts(struct nfa 
* nfa
, 
 483         while ((a 
= old
->outs
) != NULL
) 
 485                 cparc(nfa
, a
, new, a
->to
); 
 491  * copyouts - copy all out arcs of a state to another state 
 494 copyouts(struct nfa 
* nfa
, 
 502         for (a 
= old
->outs
; a 
!= NULL
; a 
= a
->outchain
) 
 503                 cparc(nfa
, a
, new, a
->to
); 
 507  * cloneouts - copy out arcs of a state to another state pair, modifying type 
 510 cloneouts(struct nfa 
* nfa
, 
 520         for (a 
= old
->outs
; a 
!= NULL
; a 
= a
->outchain
) 
 521                 newarc(nfa
, type
, a
->co
, from
, to
); 
 525  * delsub - delete a sub-NFA, updating subre pointers if necessary 
 527  * This uses a recursive traversal of the sub-NFA, marking already-seen 
 528  * states using their tmp pointer. 
 531 delsub(struct nfa 
* nfa
, 
 532            struct state 
* lp
,           /* the sub-NFA goes from here... */ 
 533            struct state 
* rp
)           /* ...to here, *not* inclusive */ 
 537         rp
->tmp 
= rp
;                           /* mark end */ 
 539         deltraverse(nfa
, lp
, lp
); 
 540         assert(lp
->nouts 
== 0 && rp
->nins 
== 0);        /* did the job */ 
 541         assert(lp
->no 
!= FREESTATE 
&& rp
->no 
!= FREESTATE
); /* no more */ 
 543         rp
->tmp 
= NULL
;                         /* unmark end */ 
 544         lp
->tmp 
= NULL
;                         /* and begin, marked by deltraverse */ 
 548  * deltraverse - the recursive heart of delsub 
 549  * This routine's basic job is to destroy all out-arcs of the state. 
 552 deltraverse(struct nfa 
* nfa
, 
 553                         struct state 
* leftend
, 
 560                 return;                                 /* nothing to do */ 
 562                 return;                                 /* already in progress */ 
 564         s
->tmp 
= s
;                                     /* mark as in progress */ 
 566         while ((a 
= s
->outs
) != NULL
) 
 569                 deltraverse(nfa
, leftend
, to
); 
 570                 assert(to
->nouts 
== 0 || to
->tmp 
!= NULL
); 
 572                 if (to
->nins 
== 0 && to
->tmp 
== NULL
) 
 574                         assert(to
->nouts 
== 0); 
 579         assert(s
->no 
!= FREESTATE
); /* we're still here */ 
 580         assert(s 
== leftend 
|| s
->nins 
!= 0);           /* and still reachable */ 
 581         assert(s
->nouts 
== 0);          /* but have no outarcs */ 
 583         s
->tmp 
= NULL
;                          /* we're done here */ 
 587  * dupnfa - duplicate sub-NFA 
 589  * Another recursive traversal, this time using tmp to point to duplicates 
 590  * as well as mark already-seen states.  (You knew there was a reason why 
 591  * it's a state pointer, didn't you? :-)) 
 594 dupnfa(struct nfa 
* nfa
, 
 595            struct state 
* start
,        /* duplicate of subNFA starting here */ 
 596            struct state 
* stop
,         /* and stopping here */ 
 597            struct state 
* from
,         /* stringing duplicate from here */ 
 598            struct state 
* to
)           /* to here */ 
 602                 newarc(nfa
, EMPTY
, 0, from
, to
); 
 607         duptraverse(nfa
, start
, from
); 
 608         /* done, except for clearing out the tmp pointers */ 
 611         cleartraverse(nfa
, start
); 
 615  * duptraverse - recursive heart of dupnfa 
 618 duptraverse(struct nfa 
* nfa
, 
 620                         struct state 
* stmp
)    /* s's duplicate, or NULL */ 
 625                 return;                                 /* already done */ 
 627         s
->tmp 
= (stmp 
== NULL
) ? newstate(nfa
) : stmp
; 
 634         for (a 
= s
->outs
; a 
!= NULL 
&& !NISERR(); a 
= a
->outchain
) 
 636                 duptraverse(nfa
, a
->to
, (struct state 
*) NULL
); 
 637                 assert(a
->to
->tmp 
!= NULL
); 
 638                 cparc(nfa
, a
, s
->tmp
, a
->to
->tmp
); 
 643  * cleartraverse - recursive cleanup for algorithms that leave tmp ptrs set 
 646 cleartraverse(struct nfa 
* nfa
, 
 655         for (a 
= s
->outs
; a 
!= NULL
; a 
= a
->outchain
) 
 656                 cleartraverse(nfa
, a
->to
); 
 660  * specialcolors - fill in special colors for an NFA 
 663 specialcolors(struct nfa 
* nfa
) 
 665         /* false colors for BOS, BOL, EOS, EOL */ 
 666         if (nfa
->parent 
== NULL
) 
 668                 nfa
->bos
[0] = pseudocolor(nfa
->cm
); 
 669                 nfa
->bos
[1] = pseudocolor(nfa
->cm
); 
 670                 nfa
->eos
[0] = pseudocolor(nfa
->cm
); 
 671                 nfa
->eos
[1] = pseudocolor(nfa
->cm
); 
 675                 assert(nfa
->parent
->bos
[0] != COLORLESS
); 
 676                 nfa
->bos
[0] = nfa
->parent
->bos
[0]; 
 677                 assert(nfa
->parent
->bos
[1] != COLORLESS
); 
 678                 nfa
->bos
[1] = nfa
->parent
->bos
[1]; 
 679                 assert(nfa
->parent
->eos
[0] != COLORLESS
); 
 680                 nfa
->eos
[0] = nfa
->parent
->eos
[0]; 
 681                 assert(nfa
->parent
->eos
[1] != COLORLESS
); 
 682                 nfa
->eos
[1] = nfa
->parent
->eos
[1]; 
 687  * optimize - optimize an NFA 
 689 static long                                             /* re_info bits */ 
 690 optimize(struct nfa 
* nfa
, 
 691                  FILE *f
)                               /* for debug output; NULL none */ 
 694         int                     verbose 
= (f 
!= NULL
) ? 1 : 0; 
 697                 fprintf(f
, "\ninitial cleanup:\n"); 
 699         cleanup(nfa
);                           /* may simplify situation */ 
 704                 fprintf(f
, "\nempties:\n"); 
 706         fixempties(nfa
, f
);                     /* get rid of EMPTY arcs */ 
 709                 fprintf(f
, "\nconstraints:\n"); 
 711         pullback(nfa
, f
);                       /* pull back constraints backward */ 
 712         pushfwd(nfa
, f
);                        /* push fwd constraints forward */ 
 715                 fprintf(f
, "\nfinal cleanup:\n"); 
 717         cleanup(nfa
);                           /* final tidying */ 
 718         return analyze(nfa
);            /* and analysis */ 
 722  * pullback - pull back constraints backward to (with luck) eliminate them 
 725 pullback(struct nfa 
* nfa
, 
 726                  FILE *f
)                               /* for debug output; NULL none */ 
 734         /* find and pull until there are no more */ 
 738                 for (s 
= nfa
->states
; s 
!= NULL 
&& !NISERR(); s 
= nexts
) 
 741                         for (a 
= s
->outs
; a 
!= NULL 
&& !NISERR(); a 
= nexta
) 
 744                                 if (a
->type 
== '^' || a
->type 
== BEHIND
) 
 747                                 assert(nexta 
== NULL 
|| s
->no 
!= FREESTATE
); 
 750                 if (progress 
&& f 
!= NULL
) 
 752         } while (progress 
&& !NISERR()); 
 756         for (a 
= nfa
->pre
->outs
; a 
!= NULL
; a 
= nexta
) 
 761                         assert(a
->co 
== 0 || a
->co 
== 1); 
 762                         newarc(nfa
, PLAIN
, nfa
->bos
[a
->co
], a
->from
, a
->to
); 
 769  * pull - pull a back constraint backward past its source state 
 770  * A significant property of this function is that it deletes at most 
 771  * one state -- the constraint's from state -- and only if the constraint 
 772  * was that state's last outarc. 
 774 static int                                              /* 0 couldn't, 1 could */ 
 775 pull(struct nfa 
* nfa
, 
 778         struct state 
*from 
= con
->from
; 
 779         struct state 
*to 
= con
->to
; 
 785         {                                                       /* circular constraint is pointless */ 
 789         if (from
->flag
)                         /* can't pull back beyond start */ 
 797         /* first, clone from state if necessary to avoid other outarcs */ 
 803                 assert(to 
!= from
);             /* con is not an inarc */ 
 804                 copyins(nfa
, from
, s
);  /* duplicate inarcs */ 
 805                 cparc(nfa
, con
, s
, to
); /* move constraint arc */ 
 810         assert(from
->nouts 
== 1); 
 812         /* propagate the constraint into the from state's inarcs */ 
 813         for (a 
= from
->ins
; a 
!= NULL
; a 
= nexta
) 
 816                 switch (combine(con
, a
)) 
 818                         case INCOMPATIBLE
:      /* destroy the arc */ 
 821                         case SATISFIED
:         /* no action needed */ 
 823                         case COMPATIBLE
:        /* swap the two arcs, more or less */ 
 827                                 cparc(nfa
, a
, s
, to
);   /* anticipate move */ 
 828                                 cparc(nfa
, con
, a
->from
, s
); 
 839         /* remaining inarcs, if any, incorporate the constraint */ 
 840         moveins(nfa
, from
, to
); 
 841         dropstate(nfa
, from
);           /* will free the constraint */ 
 846  * pushfwd - push forward constraints forward to (with luck) eliminate them 
 849 pushfwd(struct nfa 
* nfa
, 
 850                 FILE *f
)                                /* for debug output; NULL none */ 
 858         /* find and push until there are no more */ 
 862                 for (s 
= nfa
->states
; s 
!= NULL 
&& !NISERR(); s 
= nexts
) 
 865                         for (a 
= s
->ins
; a 
!= NULL 
&& !NISERR(); a 
= nexta
) 
 868                                 if (a
->type 
== '$' || a
->type 
== AHEAD
) 
 871                                 assert(nexta 
== NULL 
|| s
->no 
!= FREESTATE
); 
 874                 if (progress 
&& f 
!= NULL
) 
 876         } while (progress 
&& !NISERR()); 
 880         for (a 
= nfa
->post
->ins
; a 
!= NULL
; a 
= nexta
) 
 885                         assert(a
->co 
== 0 || a
->co 
== 1); 
 886                         newarc(nfa
, PLAIN
, nfa
->eos
[a
->co
], a
->from
, a
->to
); 
 893  * push - push a forward constraint forward past its destination state 
 894  * A significant property of this function is that it deletes at most 
 895  * one state -- the constraint's to state -- and only if the constraint 
 896  * was that state's last inarc. 
 898 static int                                              /* 0 couldn't, 1 could */ 
 899 push(struct nfa 
* nfa
, 
 902         struct state 
*from 
= con
->from
; 
 903         struct state 
*to 
= con
->to
; 
 909         {                                                       /* circular constraint is pointless */ 
 913         if (to
->flag
)                           /* can't push forward beyond end */ 
 921         /* first, clone to state if necessary to avoid other inarcs */ 
 927                 copyouts(nfa
, to
, s
);   /* duplicate outarcs */ 
 928                 cparc(nfa
, con
, from
, s
);               /* move constraint */ 
 933         assert(to
->nins 
== 1); 
 935         /* propagate the constraint into the to state's outarcs */ 
 936         for (a 
= to
->outs
; a 
!= NULL
; a 
= nexta
) 
 939                 switch (combine(con
, a
)) 
 941                         case INCOMPATIBLE
:      /* destroy the arc */ 
 944                         case SATISFIED
:         /* no action needed */ 
 946                         case COMPATIBLE
:        /* swap the two arcs, more or less */ 
 950                                 cparc(nfa
, con
, s
, a
->to
);              /* anticipate move */ 
 951                                 cparc(nfa
, a
, from
, s
); 
 962         /* remaining outarcs, if any, incorporate the constraint */ 
 963         moveouts(nfa
, to
, from
); 
 964         dropstate(nfa
, to
);                     /* will free the constraint */ 
 969  * combine - constraint lands on an arc, what happens? 
 971  * #def INCOMPATIBLE    1       // destroys arc 
 972  * #def SATISFIED               2       // constraint satisfied 
 973  * #def COMPATIBLE              3       // compatible but not satisfied yet 
 976 combine(struct arc 
* con
, 
 979 #define  CA(ct,at)       (((ct)<<CHAR_BIT) | (at)) 
 981         switch (CA(con
->type
, a
->type
)) 
 983                 case CA('^', PLAIN
):    /* newlines are handled separately */ 
 987                 case CA(AHEAD
, PLAIN
):  /* color constraints meet colors */ 
 988                 case CA(BEHIND
, PLAIN
): 
 989                         if (con
->co 
== a
->co
) 
 993                 case CA('^', '^'):              /* collision, similar constraints */ 
 995                 case CA(AHEAD
, AHEAD
): 
 996                 case CA(BEHIND
, BEHIND
): 
 997                         if (con
->co 
== a
->co
)           /* true duplication */ 
1001                 case CA('^', BEHIND
):   /* collision, dissimilar constraints */ 
1002                 case CA(BEHIND
, '^'): 
1003                 case CA('$', AHEAD
): 
1004                 case CA(AHEAD
, '$'): 
1005                         return INCOMPATIBLE
; 
1007                 case CA('^', '$'):              /* constraints passing each other */ 
1008                 case CA('^', AHEAD
): 
1009                 case CA(BEHIND
, '$'): 
1010                 case CA(BEHIND
, AHEAD
): 
1012                 case CA('$', BEHIND
): 
1013                 case CA(AHEAD
, '^'): 
1014                 case CA(AHEAD
, BEHIND
): 
1015                 case CA('^', LACON
): 
1016                 case CA(BEHIND
, LACON
): 
1017                 case CA('$', LACON
): 
1018                 case CA(AHEAD
, LACON
): 
1023         return INCOMPATIBLE
;            /* for benefit of blind compilers */ 
1027  * fixempties - get rid of EMPTY arcs 
1030 fixempties(struct nfa 
* nfa
, 
1031                    FILE *f
)                             /* for debug output; NULL none */ 
1034         struct state 
*nexts
; 
1039         /* find and eliminate empties until there are no more */ 
1043                 for (s 
= nfa
->states
; s 
!= NULL 
&& !NISERR(); s 
= nexts
) 
1046                         for (a 
= s
->outs
; a 
!= NULL 
&& !NISERR(); a 
= nexta
) 
1048                                 nexta 
= a
->outchain
; 
1049                                 if (a
->type 
== EMPTY 
&& unempty(nfa
, a
)) 
1051                                 assert(nexta 
== NULL 
|| s
->no 
!= FREESTATE
); 
1054                 if (progress 
&& f 
!= NULL
) 
1056         } while (progress 
&& !NISERR()); 
1060  * unempty - optimize out an EMPTY arc, if possible 
1062  * Actually, as it stands this function always succeeds, but the return 
1063  * value is kept with an eye on possible future changes. 
1065 static int                                              /* 0 couldn't, 1 could */ 
1066 unempty(struct nfa 
* nfa
, 
1069         struct state 
*from 
= a
->from
; 
1070         struct state 
*to 
= a
->to
; 
1071         int                     usefrom
;                /* work on from, as opposed to to? */ 
1073         assert(a
->type 
== EMPTY
); 
1074         assert(from 
!= nfa
->pre 
&& to 
!= nfa
->post
); 
1077         {                                                       /* vacuous loop */ 
1082         /* decide which end to work on */ 
1083         usefrom 
= 1;                            /* default:  attack from */ 
1084         if (from
->nouts 
> to
->nins
) 
1086         else if (from
->nouts 
== to
->nins
) 
1088                 /* decide on secondary issue:  move/copy fewest arcs */ 
1089                 if (from
->nins 
> to
->nouts
) 
1096                 if (from
->nouts 
== 0) 
1098                         /* was the state's only outarc */ 
1099                         moveins(nfa
, from
, to
); 
1100                         freestate(nfa
, from
); 
1103                         copyins(nfa
, from
, to
); 
1109                         /* was the state's only inarc */ 
1110                         moveouts(nfa
, to
, from
); 
1114                         copyouts(nfa
, to
, from
); 
1121  * cleanup - clean up NFA after optimizations 
1124 cleanup(struct nfa 
* nfa
) 
1127         struct state 
*nexts
; 
1130         /* clear out unreachable or dead-end states */ 
1131         /* use pre to mark reachable, then post to mark can-reach-post */ 
1132         markreachable(nfa
, nfa
->pre
, (struct state 
*) NULL
, nfa
->pre
); 
1133         markcanreach(nfa
, nfa
->post
, nfa
->pre
, nfa
->post
); 
1134         for (s 
= nfa
->states
; s 
!= NULL
; s 
= nexts
) 
1137                 if (s
->tmp 
!= nfa
->post 
&& !s
->flag
) 
1140         assert(nfa
->post
->nins 
== 0 || nfa
->post
->tmp 
== nfa
->post
); 
1141         cleartraverse(nfa
, nfa
->pre
); 
1142         assert(nfa
->post
->nins 
== 0 || nfa
->post
->tmp 
== NULL
); 
1143         /* the nins==0 (final unreachable) case will be caught later */ 
1145         /* renumber surviving states */ 
1147         for (s 
= nfa
->states
; s 
!= NULL
; s 
= s
->next
) 
1153  * markreachable - recursive marking of reachable states 
1156 markreachable(struct nfa 
* nfa
, 
1158                           struct state 
* okay
,          /* consider only states with this 
1160                           struct state 
* mark
)          /* the value to mark with */ 
1168         for (a 
= s
->outs
; a 
!= NULL
; a 
= a
->outchain
) 
1169                 markreachable(nfa
, a
->to
, okay
, mark
); 
1173  * markcanreach - recursive marking of states which can reach here 
1176 markcanreach(struct nfa 
* nfa
, 
1178                          struct state 
* okay
,           /* consider only states with this 
1180                          struct state 
* mark
)           /* the value to mark with */ 
1188         for (a 
= s
->ins
; a 
!= NULL
; a 
= a
->inchain
) 
1189                 markcanreach(nfa
, a
->from
, okay
, mark
); 
1193  * analyze - ascertain potentially-useful facts about an optimized NFA 
1195 static long                                             /* re_info bits to be ORed in */ 
1196 analyze(struct nfa 
* nfa
) 
1201         if (nfa
->pre
->outs 
== NULL
) 
1202                 return REG_UIMPOSSIBLE
; 
1203         for (a 
= nfa
->pre
->outs
; a 
!= NULL
; a 
= a
->outchain
) 
1204                 for (aa 
= a
->to
->outs
; aa 
!= NULL
; aa 
= aa
->outchain
) 
1205                         if (aa
->to 
== nfa
->post
) 
1206                                 return REG_UEMPTYMATCH
; 
1211  * compact - compact an NFA 
1214 compact(struct nfa 
* nfa
, 
1228         for (s 
= nfa
->states
; s 
!= NULL
; s 
= s
->next
) 
1231                 narcs 
+= 1 + s
->nouts 
+ 1; 
1232                 /* 1 as a fake for flags, nouts for arcs, 1 as endmarker */ 
1235         cnfa
->states 
= (struct carc 
**) MALLOC(nstates 
* sizeof(struct carc 
*)); 
1236         cnfa
->arcs 
= (struct carc 
*) MALLOC(narcs 
* sizeof(struct carc
)); 
1237         if (cnfa
->states 
== NULL 
|| cnfa
->arcs 
== NULL
) 
1239                 if (cnfa
->states 
!= NULL
) 
1241                 if (cnfa
->arcs 
!= NULL
) 
1246         cnfa
->nstates 
= nstates
; 
1247         cnfa
->pre 
= nfa
->pre
->no
; 
1248         cnfa
->post 
= nfa
->post
->no
; 
1249         cnfa
->bos
[0] = nfa
->bos
[0]; 
1250         cnfa
->bos
[1] = nfa
->bos
[1]; 
1251         cnfa
->eos
[0] = nfa
->eos
[0]; 
1252         cnfa
->eos
[1] = nfa
->eos
[1]; 
1253         cnfa
->ncolors 
= maxcolor(nfa
->cm
) + 1; 
1257         for (s 
= nfa
->states
; s 
!= NULL
; s 
= s
->next
) 
1259                 assert((size_t) s
->no 
< nstates
); 
1260                 cnfa
->states
[s
->no
] = ca
; 
1261                 ca
->co 
= 0;                             /* clear and skip flags "arc" */ 
1264                 for (a 
= s
->outs
; a 
!= NULL
; a 
= a
->outchain
) 
1273                                         assert(s
->no 
!= cnfa
->pre
); 
1274                                         ca
->co 
= (color
) (cnfa
->ncolors 
+ a
->co
); 
1277                                         cnfa
->flags 
|= HASLACONS
; 
1283                 carcsort(first
, ca 
- 1); 
1288         assert(ca 
== &cnfa
->arcs
[narcs
]); 
1289         assert(cnfa
->nstates 
!= 0); 
1291         /* mark no-progress states */ 
1292         for (a 
= nfa
->pre
->outs
; a 
!= NULL
; a 
= a
->outchain
) 
1293                 cnfa
->states
[a
->to
->no
]->co 
= 1; 
1294         cnfa
->states
[nfa
->pre
->no
]->co 
= 1; 
1298  * carcsort - sort compacted-NFA arcs by color 
1300  * Really dumb algorithm, but if the list is long enough for that to matter, 
1301  * you're in real trouble anyway. 
1304 carcsort(struct carc 
* first
, 
1311         if (last 
- first 
<= 1) 
1314         for (p 
= first
; p 
<= last
; p
++) 
1315                 for (q 
= p
; q 
<= last
; q
++) 
1316                         if (p
->co 
> q
->co 
|| 
1317                                 (p
->co 
== q
->co 
&& p
->to 
> q
->to
)) 
1327  * freecnfa - free a compacted NFA 
1330 freecnfa(struct cnfa 
* cnfa
) 
1332         assert(cnfa
->nstates 
!= 0); /* not empty already */ 
1339  * dumpnfa - dump an NFA in human-readable form 
1342 dumpnfa(struct nfa 
* nfa
, 
1348         fprintf(f
, "pre %d, post %d", nfa
->pre
->no
, nfa
->post
->no
); 
1349         if (nfa
->bos
[0] != COLORLESS
) 
1350                 fprintf(f
, ", bos [%ld]", (long) nfa
->bos
[0]); 
1351         if (nfa
->bos
[1] != COLORLESS
) 
1352                 fprintf(f
, ", bol [%ld]", (long) nfa
->bos
[1]); 
1353         if (nfa
->eos
[0] != COLORLESS
) 
1354                 fprintf(f
, ", eos [%ld]", (long) nfa
->eos
[0]); 
1355         if (nfa
->eos
[1] != COLORLESS
) 
1356                 fprintf(f
, ", eol [%ld]", (long) nfa
->eos
[1]); 
1358         for (s 
= nfa
->states
; s 
!= NULL
; s 
= s
->next
) 
1360         if (nfa
->parent 
== NULL
) 
1361                 dumpcolors(nfa
->cm
, f
); 
1366 #ifdef REG_DEBUG                                /* subordinates of dumpnfa */ 
1369  * dumpstate - dump an NFA state in human-readable form 
1372 dumpstate(struct state 
* s
, 
1377         fprintf(f
, "%d%s%c", s
->no
, (s
->tmp 
!= NULL
) ? "T" : "", 
1378                         (s
->flag
) ? s
->flag 
: '.'); 
1379         if (s
->prev 
!= NULL 
&& s
->prev
->next 
!= s
) 
1380                 fprintf(f
, "\tstate chain bad\n"); 
1382                 fprintf(f
, "\tno out arcs\n"); 
1386         for (a 
= s
->ins
; a 
!= NULL
; a 
= a
->inchain
) 
1389                         fprintf(f
, "\tlink from %d to %d on %d's in-chain\n", 
1390                                         a
->from
->no
, a
->to
->no
, s
->no
); 
1395  * dumparcs - dump out-arcs in human-readable form 
1398 dumparcs(struct state 
* s
, 
1403         assert(s
->nouts 
> 0); 
1404         /* printing arcs in reverse order is usually clearer */ 
1405         pos 
= dumprarcs(s
->outs
, s
, f
, 1); 
1411  * dumprarcs - dump remaining outarcs, recursively, in reverse order 
1413 static int                                              /* resulting print position */ 
1414 dumprarcs(struct arc 
* a
, 
1417                   int pos
)                              /* initial print position */ 
1419         if (a
->outchain 
!= NULL
) 
1420                 pos 
= dumprarcs(a
->outchain
, s
, f
, pos
); 
1433  * dumparc - dump one outarc in readable form, including prefixing tab 
1436 dumparc(struct arc 
* a
, 
1441         struct arcbatch 
*ab
; 
1447                         fprintf(f
, "[%ld]", (long) a
->co
); 
1450                         fprintf(f
, ">%ld>", (long) a
->co
); 
1453                         fprintf(f
, "<%ld<", (long) a
->co
); 
1456                         fprintf(f
, ":%ld:", (long) a
->co
); 
1460                         fprintf(f
, "%c%d", a
->type
, (int) a
->co
); 
1465                         fprintf(f
, "0x%x/0%lo", a
->type
, (long) a
->co
); 
1469                 fprintf(f
, "?%d?", a
->from
->no
); 
1470         for (ab 
= &a
->from
->oas
; ab 
!= NULL
; ab 
= ab
->next
) 
1472                 for (aa 
= &ab
->a
[0]; aa 
< &ab
->a
[ABSIZE
]; aa
++) 
1474                                 break;                  /* NOTE BREAK OUT */ 
1475                 if (aa 
< &ab
->a
[ABSIZE
])        /* propagate break */ 
1476                         break;                          /* NOTE BREAK OUT */ 
1479                 fprintf(f
, "?!?");              /* not in allocated space */ 
1486         fprintf(f
, "%d", a
->to
->no
); 
1487         for (aa 
= a
->to
->ins
; aa 
!= NULL
; aa 
= aa
->inchain
) 
1489                         break;                          /* NOTE BREAK OUT */ 
1491                 fprintf(f
, "?!?");              /* missing from in-chain */ 
1493 #endif   /* REG_DEBUG */ 
1496  * dumpcnfa - dump a compacted NFA in human-readable form 
1500 dumpcnfa(struct cnfa 
* cnfa
, 
1505         fprintf(f
, "pre %d, post %d", cnfa
->pre
, cnfa
->post
); 
1506         if (cnfa
->bos
[0] != COLORLESS
) 
1507                 fprintf(f
, ", bos [%ld]", (long) cnfa
->bos
[0]); 
1508         if (cnfa
->bos
[1] != COLORLESS
) 
1509                 fprintf(f
, ", bol [%ld]", (long) cnfa
->bos
[1]); 
1510         if (cnfa
->eos
[0] != COLORLESS
) 
1511                 fprintf(f
, ", eos [%ld]", (long) cnfa
->eos
[0]); 
1512         if (cnfa
->eos
[1] != COLORLESS
) 
1513                 fprintf(f
, ", eol [%ld]", (long) cnfa
->eos
[1]); 
1514         if (cnfa
->flags 
& HASLACONS
) 
1515                 fprintf(f
, ", haslacons"); 
1517         for (st 
= 0; st 
< cnfa
->nstates
; st
++) 
1518                 dumpcstate(st
, cnfa
->states
[st
], cnfa
, f
); 
1523 #ifdef REG_DEBUG                                /* subordinates of dumpcnfa */ 
1526  * dumpcstate - dump a compacted-NFA state in human-readable form 
1537         fprintf(f
, "%d%s", st
, (ca
[0].co
) ? ":" : "."); 
1539         for (i 
= 1; ca
[i
].co 
!= COLORLESS
; i
++) 
1541                 if (ca
[i
].co 
< cnfa
->ncolors
) 
1542                         fprintf(f
, "\t[%ld]->%d", (long) ca
[i
].co
, ca
[i
].to
); 
1544                         fprintf(f
, "\t:%ld:->%d", (long) ca
[i
].co 
- cnfa
->ncolors
, 
1554         if (i 
== 1 || pos 
!= 1) 
1559 #endif   /* REG_DEBUG */