LCOV - differential code coverage report
Current view: top level - src/backend/regex - regc_nfa.c (source / functions) Coverage Total Hit UBC CBC
Current: Differential Code Coverage 16@8cea358b128 vs 17@8cea358b128 Lines: 91.0 % 1329 1209 120 1209
Current Date: 2024-04-14 14:21:10 Functions: 98.4 % 61 60 1 60
Baseline: 16@8cea358b128 Branches: 75.5 % 1166 880 286 880
Baseline Date: 2024-04-14 14:21:09 Line coverage date bins:
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed (240..) days: 91.0 % 1329 1209 120 1209
Function coverage date bins:
(240..) days: 98.4 % 61 60 1 60
Branch coverage date bins:
(240..) days: 75.5 % 1166 880 286 880

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

Generated by: LCOV version 2.1-beta2-3-g6141622