LCOV - differential code coverage report
Current view: top level - src/backend/regex - regexec.c (source / functions) Coverage Total Hit UBC CBC
Current: Differential Code Coverage 16@8cea358b128 vs 17@8cea358b128 Lines: 86.3 % 553 477 76 477
Current Date: 2024-04-14 14:21:10 Functions: 100.0 % 16 16 16
Baseline: 16@8cea358b128 Branches: 68.4 % 491 336 155 336
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: 86.3 % 553 477 76 477
Function coverage date bins:
(240..) days: 100.0 % 16 16 16
Branch coverage date bins:
(240..) days: 68.4 % 491 336 155 336

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*
                                  2                 :                :  * re_*exec and friends - match REs
                                  3                 :                :  *
                                  4                 :                :  * Copyright (c) 1998, 1999 Henry Spencer.  All rights reserved.
                                  5                 :                :  *
                                  6                 :                :  * Development of this software was funded, in part, by Cray Research Inc.,
                                  7                 :                :  * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
                                  8                 :                :  * Corporation, none of whom are responsible for the results.  The author
                                  9                 :                :  * thanks all of them.
                                 10                 :                :  *
                                 11                 :                :  * Redistribution and use in source and binary forms -- with or without
                                 12                 :                :  * modification -- are permitted for any purpose, provided that
                                 13                 :                :  * redistributions in source form retain this entire copyright notice and
                                 14                 :                :  * indicate the origin and nature of any modifications.
                                 15                 :                :  *
                                 16                 :                :  * I'd appreciate being given credit for this package in the documentation
                                 17                 :                :  * of software which uses it, but that is not a requirement.
                                 18                 :                :  *
                                 19                 :                :  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
                                 20                 :                :  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
                                 21                 :                :  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
                                 22                 :                :  * HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
                                 23                 :                :  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
                                 24                 :                :  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
                                 25                 :                :  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
                                 26                 :                :  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
                                 27                 :                :  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
                                 28                 :                :  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                                 29                 :                :  *
                                 30                 :                :  * src/backend/regex/regexec.c
                                 31                 :                :  *
                                 32                 :                :  */
                                 33                 :                : 
                                 34                 :                : #include "regex/regguts.h"
                                 35                 :                : 
                                 36                 :                : 
                                 37                 :                : 
                                 38                 :                : /* lazy-DFA representation */
                                 39                 :                : struct arcp
                                 40                 :                : {                               /* "pointer" to an outarc */
                                 41                 :                :     struct sset *ss;
                                 42                 :                :     color       co;
                                 43                 :                : };
                                 44                 :                : 
                                 45                 :                : struct sset
                                 46                 :                : {                               /* state set */
                                 47                 :                :     unsigned   *states;         /* pointer to bitvector */
                                 48                 :                :     unsigned    hash;           /* hash of bitvector */
                                 49                 :                : #define  HASH(bv, nw)    (((nw) == 1) ? *(bv) : hash(bv, nw))
                                 50                 :                : #define  HIT(h,bv,ss,nw) ((ss)->hash == (h) && ((nw) == 1 || \
                                 51                 :                :         memcmp(VS(bv), VS((ss)->states), (nw)*sizeof(unsigned)) == 0))
                                 52                 :                :     int         flags;
                                 53                 :                : #define  STARTER     01         /* the initial state set */
                                 54                 :                : #define  POSTSTATE   02         /* includes the goal state */
                                 55                 :                : #define  LOCKED      04         /* locked in cache */
                                 56                 :                : #define  NOPROGRESS  010        /* zero-progress state set */
                                 57                 :                :     struct arcp ins;            /* chain of inarcs pointing here */
                                 58                 :                :     chr        *lastseen;       /* last entered on arrival here */
                                 59                 :                :     struct sset **outs;         /* outarc vector indexed by color */
                                 60                 :                :     struct arcp *inchain;       /* chain-pointer vector for outarcs */
                                 61                 :                : };
                                 62                 :                : 
                                 63                 :                : struct dfa
                                 64                 :                : {
                                 65                 :                :     int         nssets;         /* size of cache */
                                 66                 :                :     int         nssused;        /* how many entries occupied yet */
                                 67                 :                :     int         nstates;        /* number of states */
                                 68                 :                :     int         ncolors;        /* length of outarc and inchain vectors */
                                 69                 :                :     int         wordsper;       /* length of state-set bitvectors */
                                 70                 :                :     struct sset *ssets;         /* state-set cache */
                                 71                 :                :     unsigned   *statesarea;     /* bitvector storage */
                                 72                 :                :     unsigned   *work;           /* pointer to work area within statesarea */
                                 73                 :                :     struct sset **outsarea;     /* outarc-vector storage */
                                 74                 :                :     struct arcp *incarea;       /* inchain storage */
                                 75                 :                :     struct cnfa *cnfa;
                                 76                 :                :     struct colormap *cm;
                                 77                 :                :     chr        *lastpost;       /* location of last cache-flushed success */
                                 78                 :                :     chr        *lastnopr;       /* location of last cache-flushed NOPROGRESS */
                                 79                 :                :     struct sset *search;        /* replacement-search-pointer memory */
                                 80                 :                :     int         backno;         /* if DFA for a backref, subno it refers to */
                                 81                 :                :     short       backmin;        /* min repetitions for backref */
                                 82                 :                :     short       backmax;        /* max repetitions for backref */
                                 83                 :                :     bool        ismalloced;     /* should this struct dfa be freed? */
                                 84                 :                :     bool        arraysmalloced; /* should its subsidiary arrays be freed? */
                                 85                 :                : };
                                 86                 :                : 
                                 87                 :                : #define WORK    1               /* number of work bitvectors needed */
                                 88                 :                : 
                                 89                 :                : /* setup for non-malloc allocation for small cases */
                                 90                 :                : #define FEWSTATES   20          /* must be less than UBITS */
                                 91                 :                : #define FEWCOLORS   15
                                 92                 :                : struct smalldfa
                                 93                 :                : {
                                 94                 :                :     struct dfa  dfa;            /* must be first */
                                 95                 :                :     struct sset ssets[FEWSTATES * 2];
                                 96                 :                :     unsigned    statesarea[FEWSTATES * 2 + WORK];
                                 97                 :                :     struct sset *outsarea[FEWSTATES * 2 * FEWCOLORS];
                                 98                 :                :     struct arcp incarea[FEWSTATES * 2 * FEWCOLORS];
                                 99                 :                : };
                                100                 :                : 
                                101                 :                : #define DOMALLOC    ((struct smalldfa *)NULL)   /* force malloc */
                                102                 :                : 
                                103                 :                : 
                                104                 :                : 
                                105                 :                : /* internal variables, bundled for easy passing around */
                                106                 :                : struct vars
                                107                 :                : {
                                108                 :                :     regex_t    *re;
                                109                 :                :     struct guts *g;
                                110                 :                :     int         eflags;         /* copies of arguments */
                                111                 :                :     size_t      nmatch;
                                112                 :                :     regmatch_t *pmatch;
                                113                 :                :     rm_detail_t *details;
                                114                 :                :     chr        *start;          /* start of string */
                                115                 :                :     chr        *search_start;   /* search start of string */
                                116                 :                :     chr        *stop;           /* just past end of string */
                                117                 :                :     int         err;            /* error code if any (0 none) */
                                118                 :                :     struct dfa **subdfas;       /* per-tree-subre DFAs */
                                119                 :                :     struct dfa **ladfas;        /* per-lacon-subre DFAs */
                                120                 :                :     struct sset **lblastcss;    /* per-lacon-subre lookbehind restart data */
                                121                 :                :     chr       **lblastcp;       /* per-lacon-subre lookbehind restart data */
                                122                 :                :     struct smalldfa dfa1;
                                123                 :                :     struct smalldfa dfa2;
                                124                 :                : };
                                125                 :                : 
                                126                 :                : #define VISERR(vv)  ((vv)->err != 0) /* have we seen an error yet? */
                                127                 :                : #define ISERR() VISERR(v)
                                128                 :                : #define VERR(vv,e)  ((vv)->err = ((vv)->err ? (vv)->err : (e)))
                                129                 :                : #define ERR(e)  VERR(v, e)      /* record an error */
                                130                 :                : #define NOERR() {if (ISERR()) return v->err;}    /* if error seen, return it */
                                131                 :                : #define OFF(p)  ((p) - v->start)
                                132                 :                : #define LOFF(p) ((long)OFF(p))
                                133                 :                : 
                                134                 :                : 
                                135                 :                : 
                                136                 :                : /*
                                137                 :                :  * forward declarations
                                138                 :                :  */
                                139                 :                : /* === regexec.c === */
                                140                 :                : static struct dfa *getsubdfa(struct vars *v, struct subre *t);
                                141                 :                : static struct dfa *getladfa(struct vars *v, int n);
                                142                 :                : static int  find(struct vars *v, struct cnfa *cnfa, struct colormap *cm);
                                143                 :                : static int  cfind(struct vars *v, struct cnfa *cnfa, struct colormap *cm);
                                144                 :                : static int  cfindloop(struct vars *v, struct cnfa *cnfa, struct colormap *cm,
                                145                 :                :                       struct dfa *d, struct dfa *s, chr **coldp);
                                146                 :                : static void zapallsubs(regmatch_t *p, size_t n);
                                147                 :                : static void zaptreesubs(struct vars *v, struct subre *t);
                                148                 :                : static void subset(struct vars *v, struct subre *sub, chr *begin, chr *end);
                                149                 :                : static int  cdissect(struct vars *v, struct subre *t, chr *begin, chr *end);
                                150                 :                : static int  ccondissect(struct vars *v, struct subre *t, chr *begin, chr *end);
                                151                 :                : static int  crevcondissect(struct vars *v, struct subre *t, chr *begin, chr *end);
                                152                 :                : static int  cbrdissect(struct vars *v, struct subre *t, chr *begin, chr *end);
                                153                 :                : static int  caltdissect(struct vars *v, struct subre *t, chr *begin, chr *end);
                                154                 :                : static int  citerdissect(struct vars *v, struct subre *t, chr *begin, chr *end);
                                155                 :                : static int  creviterdissect(struct vars *v, struct subre *t, chr *begin, chr *end);
                                156                 :                : 
                                157                 :                : /* === rege_dfa.c === */
                                158                 :                : static chr *longest(struct vars *v, struct dfa *d,
                                159                 :                :                     chr *start, chr *stop, int *hitstopp);
                                160                 :                : static chr *shortest(struct vars *v, struct dfa *d, chr *start, chr *min,
                                161                 :                :                      chr *max, chr **coldp, int *hitstopp);
                                162                 :                : static int  matchuntil(struct vars *v, struct dfa *d, chr *probe,
                                163                 :                :                        struct sset **lastcss, chr **lastcp);
                                164                 :                : static chr *dfa_backref(struct vars *v, struct dfa *d, chr *start,
                                165                 :                :                         chr *min, chr *max, bool shortest);
                                166                 :                : static chr *lastcold(struct vars *v, struct dfa *d);
                                167                 :                : static struct dfa *newdfa(struct vars *v, struct cnfa *cnfa,
                                168                 :                :                           struct colormap *cm, struct smalldfa *sml);
                                169                 :                : static void freedfa(struct dfa *d);
                                170                 :                : static unsigned hash(unsigned *uv, int n);
                                171                 :                : static struct sset *initialize(struct vars *v, struct dfa *d, chr *start);
                                172                 :                : static struct sset *miss(struct vars *v, struct dfa *d, struct sset *css,
                                173                 :                :                          color co, chr *cp, chr *start);
                                174                 :                : static int  lacon(struct vars *v, struct cnfa *pcnfa, chr *cp, color co);
                                175                 :                : static struct sset *getvacant(struct vars *v, struct dfa *d, chr *cp,
                                176                 :                :                               chr *start);
                                177                 :                : static struct sset *pickss(struct vars *v, struct dfa *d, chr *cp,
                                178                 :                :                            chr *start);
                                179                 :                : 
                                180                 :                : 
                                181                 :                : /*
                                182                 :                :  * pg_regexec - match regular expression
                                183                 :                :  */
                                184                 :                : int
 7739 tgl@sss.pgh.pa.us         185                 :CBC      950652 : pg_regexec(regex_t *re,
                                186                 :                :            const chr *string,
                                187                 :                :            size_t len,
                                188                 :                :            size_t search_start,
                                189                 :                :            rm_detail_t *details,
                                190                 :                :            size_t nmatch,
                                191                 :                :            regmatch_t pmatch[],
                                192                 :                :            int flags)
                                193                 :                : {
                                194                 :                :     struct vars var;
  568 andres@anarazel.de        195                 :         950652 :     struct vars *v = &var;
                                196                 :                :     int         st;
                                197                 :                :     size_t      n;
                                198                 :                :     size_t      i;
                                199                 :                :     int         backref;
                                200                 :                : 
                                201                 :                : #define  LOCALMAT    20
                                202                 :                :     regmatch_t  mat[LOCALMAT];
                                203                 :                : 
                                204                 :                : #define  LOCALDFAS   40
                                205                 :                :     struct dfa *subdfas[LOCALDFAS];
                                206                 :                : 
                                207                 :                :     /* sanity checks */
 7739 tgl@sss.pgh.pa.us         208   [ +  -  +  -  :         950652 :     if (re == NULL || string == NULL || re->re_magic != REMAGIC)
                                              -  + ]
 7739 tgl@sss.pgh.pa.us         209                 :UBC           0 :         return REG_INVARG;
 7739 tgl@sss.pgh.pa.us         210         [ -  + ]:CBC      950652 :     if (re->re_csize != sizeof(chr))
 7739 tgl@sss.pgh.pa.us         211                 :UBC           0 :         return REG_MIXED;
  946 tgl@sss.pgh.pa.us         212         [ +  + ]:CBC      950652 :     if (search_start > len)
                                213                 :              3 :         return REG_NOMATCH;
                                214                 :                : 
                                215                 :                :     /* Initialize locale-dependent support */
 4753                           216                 :         950649 :     pg_set_regex_collation(re->re_collation);
                                217                 :                : 
                                218                 :                :     /* setup */
 7739                           219                 :         950649 :     v->re = re;
 7559 bruce@momjian.us          220                 :         950649 :     v->g = (struct guts *) re->re_guts;
                                221   [ +  +  -  + ]:         950649 :     if ((v->g->cflags & REG_EXPECT) && details == NULL)
 7739 tgl@sss.pgh.pa.us         222                 :UBC           0 :         return REG_INVARG;
 7559 bruce@momjian.us          223         [ +  + ]:CBC      950649 :     if (v->g->info & REG_UIMPOSSIBLE)
 7739 tgl@sss.pgh.pa.us         224                 :            715 :         return REG_NOMATCH;
 7559 bruce@momjian.us          225                 :         949934 :     backref = (v->g->info & REG_UBACKREF) ? 1 : 0;
 7739 tgl@sss.pgh.pa.us         226                 :         949934 :     v->eflags = flags;
  979                           227   [ +  +  +  + ]:         949934 :     if (backref && nmatch <= v->g->nsub)
                                228                 :                :     {
                                229                 :                :         /* need larger work area */
  965                           230                 :             91 :         v->nmatch = v->g->nsub + 1;
                                231         [ +  + ]:             91 :         if (v->nmatch <= LOCALMAT)
 7739                           232                 :             90 :             v->pmatch = mat;
                                233                 :                :         else
  965                           234                 :              1 :             v->pmatch = (regmatch_t *) MALLOC(v->nmatch * sizeof(regmatch_t));
 7739                           235         [ -  + ]:             91 :         if (v->pmatch == NULL)
 7739 tgl@sss.pgh.pa.us         236                 :UBC           0 :             return REG_ESPACE;
  965 tgl@sss.pgh.pa.us         237                 :CBC          91 :         zapallsubs(v->pmatch, v->nmatch);
                                238                 :                :     }
                                239                 :                :     else
                                240                 :                :     {
                                241                 :                :         /* we can store results directly in caller's array */
 7739                           242                 :         949843 :         v->pmatch = pmatch;
                                243                 :                :         /* ensure any extra entries in caller's array are filled with -1 */
  979                           244         [ +  + ]:         949843 :         if (nmatch > 0)
                                245                 :         557115 :             zapallsubs(pmatch, nmatch);
                                246                 :                :         /* then forget about extra entries, to avoid useless work in find() */
                                247         [ +  + ]:         949843 :         if (nmatch > v->g->nsub + 1)
                                248                 :            495 :             nmatch = v->g->nsub + 1;
                                249                 :         949843 :         v->nmatch = nmatch;
                                250                 :                :     }
 7739                           251                 :         949934 :     v->details = details;
 7559 bruce@momjian.us          252                 :         949934 :     v->start = (chr *) string;
 6853                           253                 :         949934 :     v->search_start = (chr *) string + search_start;
 7559                           254                 :         949934 :     v->stop = (chr *) string + len;
 7739 tgl@sss.pgh.pa.us         255                 :         949934 :     v->err = 0;
 3089                           256                 :         949934 :     v->subdfas = NULL;
                                257                 :         949934 :     v->ladfas = NULL;
                                258                 :         949934 :     v->lblastcss = NULL;
                                259                 :         949934 :     v->lblastcp = NULL;
                                260                 :                :     /* below this point, "goto cleanup" will behave sanely */
                                261                 :                : 
 4433                           262         [ -  + ]:         949934 :     assert(v->g->ntree >= 0);
                                263                 :         949934 :     n = (size_t) v->g->ntree;
                                264         [ +  + ]:         949934 :     if (n <= LOCALDFAS)
                                265                 :         949932 :         v->subdfas = subdfas;
                                266                 :                :     else
                                267                 :                :     {
 3089                           268                 :              2 :         v->subdfas = (struct dfa **) MALLOC(n * sizeof(struct dfa *));
                                269         [ -  + ]:              2 :         if (v->subdfas == NULL)
                                270                 :                :         {
 3089 tgl@sss.pgh.pa.us         271                 :UBC           0 :             st = REG_ESPACE;
                                272                 :              0 :             goto cleanup;
                                273                 :                :         }
                                274                 :                :     }
 4433 tgl@sss.pgh.pa.us         275         [ +  + ]:CBC     2866036 :     for (i = 0; i < n; i++)
                                276                 :        1916102 :         v->subdfas[i] = NULL;
                                277                 :                : 
 3089                           278         [ -  + ]:         949934 :     assert(v->g->nlacons >= 0);
                                279                 :         949934 :     n = (size_t) v->g->nlacons;
                                280         [ +  + ]:         949934 :     if (n > 0)
                                281                 :                :     {
                                282                 :            630 :         v->ladfas = (struct dfa **) MALLOC(n * sizeof(struct dfa *));
                                283         [ -  + ]:            630 :         if (v->ladfas == NULL)
                                284                 :                :         {
 3089 tgl@sss.pgh.pa.us         285                 :UBC           0 :             st = REG_ESPACE;
                                286                 :              0 :             goto cleanup;
                                287                 :                :         }
 3089 tgl@sss.pgh.pa.us         288         [ +  + ]:CBC        1922 :         for (i = 0; i < n; i++)
                                289                 :           1292 :             v->ladfas[i] = NULL;
                                290                 :            630 :         v->lblastcss = (struct sset **) MALLOC(n * sizeof(struct sset *));
                                291                 :            630 :         v->lblastcp = (chr **) MALLOC(n * sizeof(chr *));
                                292   [ +  -  -  + ]:            630 :         if (v->lblastcss == NULL || v->lblastcp == NULL)
                                293                 :                :         {
 3089 tgl@sss.pgh.pa.us         294                 :UBC           0 :             st = REG_ESPACE;
                                295                 :              0 :             goto cleanup;
                                296                 :                :         }
 3089 tgl@sss.pgh.pa.us         297         [ +  + ]:CBC        1922 :         for (i = 0; i < n; i++)
                                298                 :                :         {
                                299                 :           1292 :             v->lblastcss[i] = NULL;
                                300                 :           1292 :             v->lblastcp[i] = NULL;
                                301                 :                :         }
                                302                 :                :     }
                                303                 :                : 
                                304                 :                :     /* do it */
 7739                           305         [ -  + ]:         949934 :     assert(v->g->tree != NULL);
                                306         [ +  + ]:         949934 :     if (backref)
                                307                 :            145 :         st = cfind(v, &v->g->tree->cnfa, &v->g->cmap);
                                308                 :                :     else
                                309                 :         949789 :         st = find(v, &v->g->tree->cnfa, &v->g->cmap);
                                310                 :                : 
                                311                 :                :     /* on success, ensure caller's match vector is filled correctly */
  979                           312   [ +  +  +  + ]:         949934 :     if (st == REG_OKAY && nmatch > 0)
                                313                 :                :     {
                                314         [ +  + ]:         451723 :         if (v->pmatch != pmatch)
                                315                 :                :         {
                                316                 :                :             /* copy portion of match vector over from (larger) work area */
                                317         [ -  + ]:             21 :             assert(nmatch <= v->nmatch);
                                318                 :             21 :             memcpy(VS(pmatch), VS(v->pmatch), nmatch * sizeof(regmatch_t));
                                319                 :                :         }
                                320         [ +  + ]:         451723 :         if (v->g->cflags & REG_NOSUB)
                                321                 :                :         {
                                322                 :                :             /* don't expose possibly-partial sub-match results to caller */
                                323                 :         448879 :             zapallsubs(pmatch, nmatch);
                                324                 :                :         }
                                325                 :                :     }
                                326                 :                : 
                                327                 :                :     /* clean up */
 3089                           328                 :         501055 : cleanup:
 7739                           329   [ +  +  +  + ]:         949934 :     if (v->pmatch != pmatch && v->pmatch != mat)
                                330                 :              1 :         FREE(v->pmatch);
 3089                           331         [ +  - ]:         949934 :     if (v->subdfas != NULL)
                                332                 :                :     {
                                333                 :         949934 :         n = (size_t) v->g->ntree;
                                334         [ +  + ]:        2866036 :         for (i = 0; i < n; i++)
                                335                 :                :         {
                                336         [ +  + ]:        1916102 :             if (v->subdfas[i] != NULL)
                                337                 :          12512 :                 freedfa(v->subdfas[i]);
                                338                 :                :         }
                                339         [ +  + ]:         949934 :         if (v->subdfas != subdfas)
                                340                 :              2 :             FREE(v->subdfas);
                                341                 :                :     }
                                342         [ +  + ]:         949934 :     if (v->ladfas != NULL)
                                343                 :                :     {
                                344                 :            630 :         n = (size_t) v->g->nlacons;
                                345         [ +  + ]:           1922 :         for (i = 0; i < n; i++)
                                346                 :                :         {
                                347         [ +  + ]:           1292 :             if (v->ladfas[i] != NULL)
                                348                 :             53 :                 freedfa(v->ladfas[i]);
                                349                 :                :         }
                                350                 :            630 :         FREE(v->ladfas);
                                351                 :                :     }
                                352         [ +  + ]:         949934 :     if (v->lblastcss != NULL)
                                353                 :            630 :         FREE(v->lblastcss);
                                354         [ +  + ]:         949934 :     if (v->lblastcp != NULL)
                                355                 :            630 :         FREE(v->lblastcp);
                                356                 :                : 
                                357                 :                : #ifdef REG_DEBUG
                                358                 :                :     if (v->eflags & (REG_FTRACE | REG_MTRACE))
                                359                 :                :         fflush(stdout);
                                360                 :                : #endif
                                361                 :                : 
 7739                           362                 :         949934 :     return st;
                                363                 :                : }
                                364                 :                : 
                                365                 :                : /*
                                366                 :                :  * getsubdfa - create or re-fetch the DFA for a tree subre node
                                367                 :                :  *
                                368                 :                :  * We only need to create the DFA once per overall regex execution.
                                369                 :                :  * The DFA will be freed by the cleanup step in pg_regexec().
                                370                 :                :  */
                                371                 :                : static struct dfa *
 2489                           372                 :          13198 : getsubdfa(struct vars *v,
                                373                 :                :           struct subre *t)
                                374                 :                : {
 1139                           375                 :          13198 :     struct dfa *d = v->subdfas[t->id];
                                376                 :                : 
                                377         [ +  + ]:          13198 :     if (d == NULL)
                                378                 :                :     {
                                379                 :          12512 :         d = newdfa(v, &t->cnfa, &v->g->cmap, DOMALLOC);
 1133                           380         [ -  + ]:          12512 :         if (d == NULL)
 4433 tgl@sss.pgh.pa.us         381                 :UBC           0 :             return NULL;
                                382                 :                :         /* set up additional info if this is a backref node */
 1139 tgl@sss.pgh.pa.us         383         [ +  + ]:CBC       12512 :         if (t->op == 'b')
                                384                 :                :         {
                                385                 :            140 :             d->backno = t->backno;
                                386                 :            140 :             d->backmin = t->min;
                                387                 :            140 :             d->backmax = t->max;
                                388                 :                :         }
                                389                 :          12512 :         v->subdfas[t->id] = d;
                                390                 :                :     }
                                391                 :          13198 :     return d;
                                392                 :                : }
                                393                 :                : 
                                394                 :                : /*
                                395                 :                :  * getladfa - create or re-fetch the DFA for a LACON subre node
                                396                 :                :  *
                                397                 :                :  * Same as above, but for LACONs.
                                398                 :                :  */
                                399                 :                : static struct dfa *
 2489                           400                 :            120 : getladfa(struct vars *v,
                                401                 :                :          int n)
                                402                 :                : {
 3089                           403   [ +  -  +  -  :            120 :     assert(n > 0 && n < v->g->nlacons && v->g->lacons != NULL);
                                              -  + ]
                                404                 :                : 
                                405         [ +  + ]:            120 :     if (v->ladfas[n] == NULL)
                                406                 :                :     {
                                407                 :             53 :         struct subre *sub = &v->g->lacons[n];
                                408                 :                : 
                                409                 :             53 :         v->ladfas[n] = newdfa(v, &sub->cnfa, &v->g->cmap, DOMALLOC);
                                410                 :                :         /* a LACON can't contain a backref, so nothing else to do */
                                411                 :                :     }
                                412                 :            120 :     return v->ladfas[n];
                                413                 :                : }
                                414                 :                : 
                                415                 :                : /*
                                416                 :                :  * find - find a match for the main NFA (no-complications case)
                                417                 :                :  */
                                418                 :                : static int
 2489                           419                 :         949789 : find(struct vars *v,
                                420                 :                :      struct cnfa *cnfa,
                                421                 :                :      struct colormap *cm)
                                422                 :                : {
                                423                 :                :     struct dfa *s;
                                424                 :                :     struct dfa *d;
                                425                 :                :     chr        *begin;
 7559 bruce@momjian.us          426                 :         949789 :     chr        *end = NULL;
                                427                 :                :     chr        *cold;
                                428                 :                :     chr        *open;           /* open and close of range of possible starts */
                                429                 :                :     chr        *close;
                                430                 :                :     int         hitend;
                                431                 :         949789 :     int         shorter = (v->g->tree->flags & SHORTER) ? 1 : 0;
                                432                 :                : 
                                433                 :                :     /* first, a shot with the search RE */
 7739 tgl@sss.pgh.pa.us         434                 :         949789 :     s = newdfa(v, &v->g->search, cm, &v->dfa1);
 1133                           435         [ -  + ]:         949789 :     if (s == NULL)
 1133 tgl@sss.pgh.pa.us         436                 :UBC           0 :         return v->err;
                                437                 :                :     MDEBUG(("\nsearch at %ld\n", LOFF(v->start)));
 7739 tgl@sss.pgh.pa.us         438                 :CBC      949789 :     cold = NULL;
 6853 bruce@momjian.us          439                 :         949789 :     close = shortest(v, s, v->search_start, v->search_start, v->stop,
                                440                 :                :                      &cold, (int *) NULL);
 7739 tgl@sss.pgh.pa.us         441                 :         949789 :     freedfa(s);
                                442         [ -  + ]:         949789 :     NOERR();
 7559 bruce@momjian.us          443         [ +  + ]:         949789 :     if (v->g->cflags & REG_EXPECT)
                                444                 :                :     {
 7739 tgl@sss.pgh.pa.us         445         [ -  + ]:             27 :         assert(v->details != NULL);
                                446         [ +  - ]:             27 :         if (cold != NULL)
                                447                 :             27 :             v->details->rm_extend.rm_so = OFF(cold);
                                448                 :                :         else
 7739 tgl@sss.pgh.pa.us         449                 :UBC           0 :             v->details->rm_extend.rm_so = OFF(v->stop);
 2489 tgl@sss.pgh.pa.us         450                 :CBC          27 :         v->details->rm_extend.rm_eo = OFF(v->stop); /* unknown */
                                451                 :                :     }
 7559 bruce@momjian.us          452         [ +  + ]:         949789 :     if (close == NULL)          /* not found */
 7739 tgl@sss.pgh.pa.us         453                 :         375287 :         return REG_NOMATCH;
 7559 bruce@momjian.us          454         [ +  + ]:         574502 :     if (v->nmatch == 0)          /* found, don't need exact location */
 7739 tgl@sss.pgh.pa.us         455                 :         122837 :         return REG_OKAY;
                                456                 :                : 
                                457                 :                :     /* find starting point and match */
                                458         [ -  + ]:         451665 :     assert(cold != NULL);
                                459                 :         451665 :     open = cold;
                                460                 :         451665 :     cold = NULL;
                                461                 :                :     MDEBUG(("between %ld and %ld\n", LOFF(open), LOFF(close)));
                                462                 :         451665 :     d = newdfa(v, cnfa, cm, &v->dfa1);
 1133                           463         [ -  + ]:         451665 :     if (d == NULL)
 1133 tgl@sss.pgh.pa.us         464                 :UBC           0 :         return v->err;
 7559 bruce@momjian.us          465         [ +  - ]:CBC      451694 :     for (begin = open; begin <= close; begin++)
                                466                 :                :     {
                                467                 :                :         MDEBUG(("\nfind trying at %ld\n", LOFF(begin)));
 7739 tgl@sss.pgh.pa.us         468         [ +  + ]:         451694 :         if (shorter)
                                469                 :             62 :             end = shortest(v, d, begin, begin, v->stop,
                                470                 :                :                            (chr **) NULL, &hitend);
                                471                 :                :         else
                                472                 :         451632 :             end = longest(v, d, begin, v->stop, &hitend);
 3131                           473         [ -  + ]:         451694 :         if (ISERR())
                                474                 :                :         {
 3131 tgl@sss.pgh.pa.us         475                 :UBC           0 :             freedfa(d);
                                476                 :              0 :             return v->err;
                                477                 :                :         }
 7739 tgl@sss.pgh.pa.us         478   [ +  +  +  + ]:CBC      451694 :         if (hitend && cold == NULL)
                                479                 :           3148 :             cold = begin;
                                480         [ +  + ]:         451694 :         if (end != NULL)
 7559 bruce@momjian.us          481                 :         451665 :             break;              /* NOTE BREAK OUT */
                                482                 :                :     }
 7739 tgl@sss.pgh.pa.us         483         [ -  + ]:         451665 :     assert(end != NULL);        /* search RE succeeded so loop should */
                                484                 :         451665 :     freedfa(d);
                                485                 :                : 
                                486                 :                :     /* and pin down details */
                                487         [ -  + ]:         451665 :     assert(v->nmatch > 0);
                                488                 :         451665 :     v->pmatch[0].rm_so = OFF(begin);
                                489                 :         451665 :     v->pmatch[0].rm_eo = OFF(end);
 7559 bruce@momjian.us          490         [ +  + ]:         451665 :     if (v->g->cflags & REG_EXPECT)
                                491                 :                :     {
 7739 tgl@sss.pgh.pa.us         492         [ +  + ]:             10 :         if (cold != NULL)
                                493                 :              5 :             v->details->rm_extend.rm_so = OFF(cold);
                                494                 :                :         else
                                495                 :              5 :             v->details->rm_extend.rm_so = OFF(v->stop);
 2489                           496                 :             10 :         v->details->rm_extend.rm_eo = OFF(v->stop); /* unknown */
                                497                 :                :     }
 7559 bruce@momjian.us          498         [ +  + ]:         451665 :     if (v->nmatch == 1)          /* no need for submatches */
 7739 tgl@sss.pgh.pa.us         499                 :         449429 :         return REG_OKAY;
                                500                 :                : 
                                501                 :                :     /* find submatches */
 4433                           502                 :           2236 :     return cdissect(v, v->g->tree, begin, end);
                                503                 :                : }
                                504                 :                : 
                                505                 :                : /*
                                506                 :                :  * cfind - find a match for the main NFA (with complications)
                                507                 :                :  */
                                508                 :                : static int
 2489                           509                 :            145 : cfind(struct vars *v,
                                510                 :                :       struct cnfa *cnfa,
                                511                 :                :       struct colormap *cm)
                                512                 :                : {
                                513                 :                :     struct dfa *s;
                                514                 :                :     struct dfa *d;
                                515                 :                :     chr        *cold;
                                516                 :                :     int         ret;
                                517                 :                : 
 7739                           518                 :            145 :     s = newdfa(v, &v->g->search, cm, &v->dfa1);
 1133                           519         [ -  + ]:            145 :     if (s == NULL)
 1133 tgl@sss.pgh.pa.us         520                 :UBC           0 :         return v->err;
 7739 tgl@sss.pgh.pa.us         521                 :CBC         145 :     d = newdfa(v, cnfa, cm, &v->dfa2);
 1133                           522         [ -  + ]:            145 :     if (d == NULL)
                                523                 :                :     {
 7739 tgl@sss.pgh.pa.us         524                 :UBC           0 :         freedfa(s);
                                525                 :              0 :         return v->err;
                                526                 :                :     }
                                527                 :                : 
 7739 tgl@sss.pgh.pa.us         528                 :CBC         145 :     ret = cfindloop(v, cnfa, cm, d, s, &cold);
                                529                 :                : 
                                530                 :            145 :     freedfa(d);
                                531                 :            145 :     freedfa(s);
                                532         [ -  + ]:            145 :     NOERR();
 7559 bruce@momjian.us          533         [ -  + ]:            145 :     if (v->g->cflags & REG_EXPECT)
                                534                 :                :     {
 7739 tgl@sss.pgh.pa.us         535         [ #  # ]:UBC           0 :         assert(v->details != NULL);
                                536         [ #  # ]:              0 :         if (cold != NULL)
                                537                 :              0 :             v->details->rm_extend.rm_so = OFF(cold);
                                538                 :                :         else
                                539                 :              0 :             v->details->rm_extend.rm_so = OFF(v->stop);
 2489                           540                 :              0 :         v->details->rm_extend.rm_eo = OFF(v->stop); /* unknown */
                                541                 :                :     }
 7739 tgl@sss.pgh.pa.us         542                 :CBC         145 :     return ret;
                                543                 :                : }
                                544                 :                : 
                                545                 :                : /*
                                546                 :                :  * cfindloop - the heart of cfind
                                547                 :                :  */
                                548                 :                : static int
 2489                           549                 :            145 : cfindloop(struct vars *v,
                                550                 :                :           struct cnfa *cnfa,
                                551                 :                :           struct colormap *cm,
                                552                 :                :           struct dfa *d,
                                553                 :                :           struct dfa *s,
                                554                 :                :           chr **coldp)          /* where to put coldstart pointer */
                                555                 :                : {
                                556                 :                :     chr        *begin;
                                557                 :                :     chr        *end;
                                558                 :                :     chr        *cold;
                                559                 :                :     chr        *open;           /* open and close of range of possible starts */
                                560                 :                :     chr        *close;
                                561                 :                :     chr        *estart;
                                562                 :                :     chr        *estop;
                                563                 :                :     int         er;
 7559 bruce@momjian.us          564                 :            145 :     int         shorter = v->g->tree->flags & SHORTER;
                                565                 :                :     int         hitend;
                                566                 :                : 
 7739 tgl@sss.pgh.pa.us         567   [ +  -  -  + ]:            145 :     assert(d != NULL && s != NULL);
                                568                 :            145 :     cold = NULL;
 6853 bruce@momjian.us          569                 :            145 :     close = v->search_start;
                                570                 :                :     do
                                571                 :                :     {
                                572                 :                :         /* Search with the search RE for match range at/beyond "close" */
                                573                 :                :         MDEBUG(("\ncsearch at %ld\n", LOFF(close)));
 7559                           574                 :            161 :         close = shortest(v, s, close, close, v->stop, &cold, (int *) NULL);
 3117 tgl@sss.pgh.pa.us         575         [ -  + ]:            161 :         if (ISERR())
                                576                 :                :         {
 3117 tgl@sss.pgh.pa.us         577                 :UBC           0 :             *coldp = cold;
                                578                 :              0 :             return v->err;
                                579                 :                :         }
 7739 tgl@sss.pgh.pa.us         580         [ +  + ]:CBC         161 :         if (close == NULL)
 3117                           581                 :             15 :             break;              /* no more possible match anywhere */
 7739                           582         [ -  + ]:            146 :         assert(cold != NULL);
                                583                 :            146 :         open = cold;
                                584                 :            146 :         cold = NULL;
                                585                 :                :         /* Search for matches starting between "open" and "close" inclusive */
                                586                 :                :         MDEBUG(("cbetween %ld and %ld\n", LOFF(open), LOFF(close)));
 7559 bruce@momjian.us          587         [ +  + ]:            513 :         for (begin = open; begin <= close; begin++)
                                588                 :                :         {
                                589                 :                :             MDEBUG(("\ncfind trying at %ld\n", LOFF(begin)));
 7739 tgl@sss.pgh.pa.us         590                 :            452 :             estart = begin;
                                591                 :            452 :             estop = v->stop;
                                592                 :                :             for (;;)
                                593                 :                :             {
                                594                 :                :                 /* Here we use the top node's detailed RE */
                                595         [ +  + ]:            646 :                 if (shorter)
                                596                 :             97 :                     end = shortest(v, d, begin, estart,
                                597                 :                :                                    estop, (chr **) NULL, &hitend);
                                598                 :                :                 else
                                599                 :            549 :                     end = longest(v, d, begin, estop,
                                600                 :                :                                   &hitend);
 3117                           601         [ -  + ]:            646 :                 if (ISERR())
                                602                 :                :                 {
 3117 tgl@sss.pgh.pa.us         603                 :UBC           0 :                     *coldp = cold;
                                604                 :              0 :                     return v->err;
                                605                 :                :                 }
 7739 tgl@sss.pgh.pa.us         606   [ +  +  +  + ]:CBC         646 :                 if (hitend && cold == NULL)
                                607                 :            104 :                     cold = begin;
                                608         [ +  + ]:            646 :                 if (end == NULL)
 3117                           609                 :            349 :                     break;      /* no match with this begin point, try next */
                                610                 :                :                 MDEBUG(("tentative end %ld\n", LOFF(end)));
                                611                 :                :                 /* Dissect the potential match to see if it really matches */
 7739                           612                 :            297 :                 er = cdissect(v, v->g->tree, begin, end);
 7559 bruce@momjian.us          613         [ +  + ]:            297 :                 if (er == REG_OKAY)
                                614                 :                :                 {
                                615         [ +  - ]:             85 :                     if (v->nmatch > 0)
                                616                 :                :                     {
 7739 tgl@sss.pgh.pa.us         617                 :             85 :                         v->pmatch[0].rm_so = OFF(begin);
                                618                 :             85 :                         v->pmatch[0].rm_eo = OFF(end);
                                619                 :                :                     }
                                620                 :             85 :                     *coldp = cold;
                                621                 :             85 :                     return REG_OKAY;
                                622                 :                :                 }
 7559 bruce@momjian.us          623         [ -  + ]:            212 :                 if (er != REG_NOMATCH)
                                624                 :                :                 {
 7739 tgl@sss.pgh.pa.us         625         [ #  # ]:UBC           0 :                     ERR(er);
 6777                           626                 :              0 :                     *coldp = cold;
 7739                           627                 :              0 :                     return er;
                                628                 :                :                 }
                                629                 :                :                 /* Try next longer/shorter match with same begin point */
 7739 tgl@sss.pgh.pa.us         630         [ +  + ]:CBC         212 :                 if (shorter)
                                631                 :                :                 {
 3923                           632         [ +  + ]:             81 :                     if (end == estop)
 3117                           633                 :             12 :                         break;  /* no more, so try next begin point */
 7739                           634                 :             69 :                     estart = end + 1;
                                635                 :                :                 }
                                636                 :                :                 else
                                637                 :                :                 {
 3923                           638         [ +  + ]:            131 :                     if (end == begin)
 3117                           639                 :              6 :                         break;  /* no more, so try next begin point */
 7739                           640                 :            125 :                     estop = end - 1;
                                641                 :                :                 }
                                642                 :                :             }                   /* end loop over endpoint positions */
                                643                 :                :         }                       /* end loop over beginning positions */
                                644                 :                : 
                                645                 :                :         /*
                                646                 :                :          * If we get here, there is no possible match starting at or before
                                647                 :                :          * "close", so consider matches beyond that.  We'll do a fresh search
                                648                 :                :          * with the search RE to find a new promising match range.
                                649                 :                :          */
 3117                           650                 :             61 :         close++;
 7739                           651         [ +  + ]:             61 :     } while (close < v->stop);
                                652                 :                : 
                                653                 :             60 :     *coldp = cold;
                                654                 :             60 :     return REG_NOMATCH;
                                655                 :                : }
                                656                 :                : 
                                657                 :                : /*
                                658                 :                :  * zapallsubs - initialize all subexpression matches to "no match"
                                659                 :                :  *
                                660                 :                :  * Note that p[0], the overall-match location, is not touched.
                                661                 :                :  */
                                662                 :                : static void
 4433                           663                 :        1006085 : zapallsubs(regmatch_t *p,
                                664                 :                :            size_t n)
                                665                 :                : {
                                666                 :                :     size_t      i;
                                667                 :                : 
 7559 bruce@momjian.us          668         [ +  + ]:        1014317 :     for (i = n - 1; i > 0; i--)
                                669                 :                :     {
 7739 tgl@sss.pgh.pa.us         670                 :           8232 :         p[i].rm_so = -1;
                                671                 :           8232 :         p[i].rm_eo = -1;
                                672                 :                :     }
                                673                 :        1006085 : }
                                674                 :                : 
                                675                 :                : /*
                                676                 :                :  * zaptreesubs - initialize subexpressions within subtree to "no match"
                                677                 :                :  */
                                678                 :                : static void
 2489                           679                 :            520 : zaptreesubs(struct vars *v,
                                680                 :                :             struct subre *t)
                                681                 :                : {
 1149                           682                 :            520 :     int         n = t->capno;
                                683                 :                :     struct subre *t2;
                                684                 :                : 
                                685         [ +  + ]:            520 :     if (n > 0)
                                686                 :                :     {
 4343                           687         [ +  - ]:            243 :         if ((size_t) n < v->nmatch)
                                688                 :                :         {
                                689                 :            243 :             v->pmatch[n].rm_so = -1;
                                690                 :            243 :             v->pmatch[n].rm_eo = -1;
                                691                 :                :         }
                                692                 :                :     }
                                693                 :                : 
 1149                           694         [ +  + ]:            695 :     for (t2 = t->child; t2 != NULL; t2 = t2->sibling)
                                695                 :            175 :         zaptreesubs(v, t2);
 7739                           696                 :            520 : }
                                697                 :                : 
                                698                 :                : /*
                                699                 :                :  * subset - set subexpression match data for a successful subre
                                700                 :                :  */
                                701                 :                : static void
 2489                           702                 :           4089 : subset(struct vars *v,
                                703                 :                :        struct subre *sub,
                                704                 :                :        chr *begin,
                                705                 :                :        chr *end)
                                706                 :                : {
 1149                           707                 :           4089 :     int         n = sub->capno;
                                708                 :                : 
 7739                           709         [ -  + ]:           4089 :     assert(n > 0);
 7559 bruce@momjian.us          710         [ +  + ]:           4089 :     if ((size_t) n >= v->nmatch)
 7739 tgl@sss.pgh.pa.us         711                 :              9 :         return;
                                712                 :                : 
                                713                 :                :     MDEBUG(("%d: setting %d = %ld-%ld\n", sub->id, n, LOFF(begin), LOFF(end)));
                                714                 :           4080 :     v->pmatch[n].rm_so = OFF(begin);
                                715                 :           4080 :     v->pmatch[n].rm_eo = OFF(end);
                                716                 :                : }
                                717                 :                : 
                                718                 :                : /*
                                719                 :                :  * cdissect - check backrefs and determine subexpression matches
                                720                 :                :  *
                                721                 :                :  * cdissect recursively processes a subre tree to check matching of backrefs
                                722                 :                :  * and/or identify submatch boundaries for capture nodes.  The proposed match
                                723                 :                :  * runs from "begin" to "end" (not including "end"), and we are basically
                                724                 :                :  * "dissecting" it to see where the submatches are.
                                725                 :                :  *
                                726                 :                :  * Before calling any level of cdissect, the caller must have run the node's
                                727                 :                :  * DFA and found that the proposed substring satisfies the DFA.  (We make
                                728                 :                :  * the caller do that because in concatenation and iteration nodes, it's
                                729                 :                :  * much faster to check all the substrings against the child DFAs before we
                                730                 :                :  * recurse.)
                                731                 :                :  *
                                732                 :                :  * A side-effect of a successful match is to save match locations for
                                733                 :                :  * capturing subexpressions in v->pmatch[].  This is a little bit tricky,
                                734                 :                :  * so we make the following rules:
                                735                 :                :  * 1. Before initial entry to cdissect, all match data must have been
                                736                 :                :  *    cleared (this is seen to by zapallsubs).
                                737                 :                :  * 2. Before any recursive entry to cdissect, the match data for that
                                738                 :                :  *    subexpression tree must be guaranteed clear (see zaptreesubs).
                                739                 :                :  * 3. When returning REG_OKAY, each level of cdissect will have saved
                                740                 :                :  *    any relevant match locations.
                                741                 :                :  * 4. When returning REG_NOMATCH, each level of cdissect will guarantee
                                742                 :                :  *    that its subexpression match locations are again clear.
                                743                 :                :  * 5. No guarantees are made for error cases (i.e., other result codes).
                                744                 :                :  * 6. When a level of cdissect abandons a successful sub-match, it will
                                745                 :                :  *    clear that subtree's match locations with zaptreesubs before trying
                                746                 :                :  *    any new DFA match or cdissect call for that subtree or any subtree
                                747                 :                :  *    to its right (that is, any subtree that could have a backref into the
                                748                 :                :  *    abandoned match).
                                749                 :                :  * This may seem overly complicated, but it's difficult to simplify it
                                750                 :                :  * because of the provision that match locations must be reset before
                                751                 :                :  * any fresh DFA match (a rule that is needed to make dfa_backref safe).
                                752                 :                :  * That means it won't work to just reset relevant match locations at the
                                753                 :                :  * start of each cdissect level.
                                754                 :                :  */
                                755                 :                : static int                      /* regexec return code */
 2489                           756                 :          15410 : cdissect(struct vars *v,
                                757                 :                :          struct subre *t,
                                758                 :                :          chr *begin,            /* beginning of relevant substring */
                                759                 :                :          chr *end)              /* end of same */
                                760                 :                : {
                                761                 :                :     int         er;
                                762                 :                : 
 7739                           763         [ -  + ]:          15410 :     assert(t != NULL);
                                764                 :                :     MDEBUG(("%d: cdissect %c %ld-%ld\n", t->id, t->op, LOFF(begin), LOFF(end)));
                                765                 :                : 
                                766                 :                :     /* handy place to check for operation cancel */
  372 tmunro@postgresql.or      767         [ -  + ]:          15410 :     INTERRUPT(v->re);
                                768                 :                :     /* ... and stack overrun */
 3117 tgl@sss.pgh.pa.us         769         [ -  + ]:          15410 :     if (STACK_TOO_DEEP(v->re))
 3117 tgl@sss.pgh.pa.us         770                 :UBC           0 :         return REG_ETOOBIG;
                                771                 :                : 
 7559 bruce@momjian.us          772   [ +  +  +  +  :CBC       15410 :     switch (t->op)
                                           +  +  - ]
                                773                 :                :     {
                                774                 :           8485 :         case '=':               /* terminal node */
 1149 tgl@sss.pgh.pa.us         775         [ -  + ]:           8485 :             assert(t->child == NULL);
 4433                           776                 :           8485 :             er = REG_OKAY;      /* no action, parent did the work */
                                777                 :           8485 :             break;
 4437                           778                 :            209 :         case 'b':               /* back reference */
 1149                           779         [ -  + ]:            209 :             assert(t->child == NULL);
 4433                           780                 :            209 :             er = cbrdissect(v, t, begin, end);
                                781                 :            209 :             break;
 7559 bruce@momjian.us          782                 :           6482 :         case '.':               /* concatenation */
 1149 tgl@sss.pgh.pa.us         783         [ -  + ]:           6482 :             assert(t->child != NULL);
                                784         [ +  + ]:           6482 :             if (t->child->flags & SHORTER)    /* reverse scan */
 4433                           785                 :            164 :                 er = crevcondissect(v, t, begin, end);
                                786                 :                :             else
                                787                 :           6318 :                 er = ccondissect(v, t, begin, end);
                                788                 :           6482 :             break;
                                789                 :             80 :         case '|':               /* alternation */
 1149                           790         [ -  + ]:             80 :             assert(t->child != NULL);
 4433                           791                 :             80 :             er = caltdissect(v, t, begin, end);
                                792                 :             80 :             break;
                                793                 :            124 :         case '*':               /* iteration */
 1149                           794         [ -  + ]:            124 :             assert(t->child != NULL);
                                795         [ +  + ]:            124 :             if (t->child->flags & SHORTER)    /* reverse scan */
 4433                           796                 :              7 :                 er = creviterdissect(v, t, begin, end);
                                797                 :                :             else
                                798                 :            117 :                 er = citerdissect(v, t, begin, end);
                                799                 :            124 :             break;
 1149                           800                 :             30 :         case '(':               /* no-op capture node */
                                801         [ -  + ]:             30 :             assert(t->child != NULL);
                                802                 :             30 :             er = cdissect(v, t->child, begin, end);
 4433                           803                 :             30 :             break;
 7559 bruce@momjian.us          804                 :UBC           0 :         default:
 4433 tgl@sss.pgh.pa.us         805                 :              0 :             er = REG_ASSERT;
                                806                 :              0 :             break;
                                807                 :                :     }
                                808                 :                : 
                                809                 :                :     /*
                                810                 :                :      * We should never have a match failure unless backrefs lurk below;
                                811                 :                :      * otherwise, either caller failed to check the DFA, or there's some
                                812                 :                :      * inconsistency between the DFA and the node's innards.
                                813                 :                :      */
 4433 tgl@sss.pgh.pa.us         814   [ +  +  -  + ]:CBC       15410 :     assert(er != REG_NOMATCH || (t->flags & BACKR));
                                815                 :                : 
                                816                 :                :     /*
                                817                 :                :      * If this node is marked as capturing, save successful match's location.
                                818                 :                :      */
 1149                           819   [ +  +  +  + ]:          15410 :     if (t->capno > 0 && er == REG_OKAY)
                                820                 :           4089 :         subset(v, t, begin, end);
                                821                 :                : 
 4433                           822                 :          15410 :     return er;
                                823                 :                : }
                                824                 :                : 
                                825                 :                : /*
                                826                 :                :  * ccondissect - dissect match for concatenation node
                                827                 :                :  */
                                828                 :                : static int                      /* regexec return code */
 2489                           829                 :           6318 : ccondissect(struct vars *v,
                                830                 :                :             struct subre *t,
                                831                 :                :             chr *begin,         /* beginning of relevant substring */
                                832                 :                :             chr *end)           /* end of same */
                                833                 :                : {
 1149                           834                 :           6318 :     struct subre *left = t->child;
                                835                 :           6318 :     struct subre *right = left->sibling;
                                836                 :                :     struct dfa *d;
                                837                 :                :     struct dfa *d2;
                                838                 :                :     chr        *mid;
                                839                 :                :     int         er;
                                840                 :                : 
 7739                           841         [ -  + ]:           6318 :     assert(t->op == '.');
 1149                           842   [ +  -  -  + ]:           6318 :     assert(left != NULL && left->cnfa.nstates > 0);
                                843   [ +  -  -  + ]:           6318 :     assert(right != NULL && right->cnfa.nstates > 0);
                                844         [ -  + ]:           6318 :     assert(right->sibling == NULL);
                                845         [ -  + ]:           6318 :     assert(!(left->flags & SHORTER));
                                846                 :                : 
                                847                 :           6318 :     d = getsubdfa(v, left);
 4433                           848         [ -  + ]:           6318 :     NOERR();
 1149                           849                 :           6318 :     d2 = getsubdfa(v, right);
 4433                           850         [ -  + ]:           6318 :     NOERR();
                                851                 :                :     MDEBUG(("%d: ccondissect %ld-%ld\n", t->id, LOFF(begin), LOFF(end)));
                                852                 :                : 
                                853                 :                :     /* pick a tentative midpoint */
                                854                 :           6318 :     mid = longest(v, d, begin, end, (int *) NULL);
 3117                           855         [ -  + ]:           6318 :     NOERR();
 4433                           856         [ +  + ]:           6318 :     if (mid == NULL)
                                857                 :              8 :         return REG_NOMATCH;
                                858                 :                :     MDEBUG(("%d: tentative midpoint %ld\n", t->id, LOFF(mid)));
                                859                 :                : 
                                860                 :                :     /* iterate until satisfaction or failure */
                                861                 :                :     for (;;)
                                862                 :                :     {
                                863                 :                :         /* try this midpoint on for size */
 5186                           864         [ +  + ]:           8048 :         if (longest(v, d2, mid, end, (int *) NULL) == end)
                                865                 :                :         {
 1149                           866                 :           6269 :             er = cdissect(v, left, begin, mid);
 5186                           867         [ +  + ]:           6269 :             if (er == REG_OKAY)
                                868                 :                :             {
 1149                           869                 :           6219 :                 er = cdissect(v, right, mid, end);
 5186                           870         [ +  + ]:           6219 :                 if (er == REG_OKAY)
                                871                 :                :                 {
                                872                 :                :                     /* satisfaction */
                                873                 :                :                     MDEBUG(("%d: successful\n", t->id));
                                874                 :           5971 :                     return REG_OKAY;
                                875                 :                :                 }
                                876                 :                :                 /* Reset left's matches (right should have done so itself) */
  965                           877                 :            248 :                 zaptreesubs(v, left);
                                878                 :                :             }
 4433                           879         [ -  + ]:            298 :             if (er != REG_NOMATCH)
 5186 tgl@sss.pgh.pa.us         880                 :UBC           0 :                 return er;
                                881                 :                :         }
 3117 tgl@sss.pgh.pa.us         882         [ -  + ]:CBC        2077 :         NOERR();
                                883                 :                : 
                                884                 :                :         /* that midpoint didn't work, find a new one */
 7559 bruce@momjian.us          885         [ +  + ]:           2077 :         if (mid == begin)
                                886                 :                :         {
                                887                 :                :             /* all possibilities exhausted */
                                888                 :                :             MDEBUG(("%d: no midpoint\n", t->id));
 7739 tgl@sss.pgh.pa.us         889                 :             75 :             return REG_NOMATCH;
                                890                 :                :         }
 7559 bruce@momjian.us          891                 :           2002 :         mid = longest(v, d, begin, mid - 1, (int *) NULL);
 3117 tgl@sss.pgh.pa.us         892         [ -  + ]:           2002 :         NOERR();
 7559 bruce@momjian.us          893         [ +  + ]:           2002 :         if (mid == NULL)
                                894                 :                :         {
                                895                 :                :             /* failed to find a new one */
                                896                 :                :             MDEBUG(("%d: failed midpoint\n", t->id));
 7739 tgl@sss.pgh.pa.us         897                 :            264 :             return REG_NOMATCH;
                                898                 :                :         }
                                899                 :                :         MDEBUG(("%d: new midpoint %ld\n", t->id, LOFF(mid)));
                                900                 :                :     }
                                901                 :                : 
                                902                 :                :     /* can't get here */
                                903                 :                :     return REG_ASSERT;
                                904                 :                : }
                                905                 :                : 
                                906                 :                : /*
                                907                 :                :  * crevcondissect - dissect match for concatenation node, shortest-first
                                908                 :                :  */
                                909                 :                : static int                      /* regexec return code */
 2489                           910                 :            164 : crevcondissect(struct vars *v,
                                911                 :                :                struct subre *t,
                                912                 :                :                chr *begin,      /* beginning of relevant substring */
                                913                 :                :                chr *end)        /* end of same */
                                914                 :                : {
 1149                           915                 :            164 :     struct subre *left = t->child;
                                916                 :            164 :     struct subre *right = left->sibling;
                                917                 :                :     struct dfa *d;
                                918                 :                :     struct dfa *d2;
                                919                 :                :     chr        *mid;
                                920                 :                :     int         er;
                                921                 :                : 
 7739                           922         [ -  + ]:            164 :     assert(t->op == '.');
 1149                           923   [ +  -  -  + ]:            164 :     assert(left != NULL && left->cnfa.nstates > 0);
                                924   [ +  -  -  + ]:            164 :     assert(right != NULL && right->cnfa.nstates > 0);
                                925         [ -  + ]:            164 :     assert(right->sibling == NULL);
                                926         [ -  + ]:            164 :     assert(left->flags & SHORTER);
                                927                 :                : 
                                928                 :            164 :     d = getsubdfa(v, left);
 4433                           929         [ -  + ]:            164 :     NOERR();
 1149                           930                 :            164 :     d2 = getsubdfa(v, right);
 4433                           931         [ -  + ]:            164 :     NOERR();
                                932                 :                :     MDEBUG(("%d: crevcondissect %ld-%ld\n", t->id, LOFF(begin), LOFF(end)));
                                933                 :                : 
                                934                 :                :     /* pick a tentative midpoint */
                                935                 :            164 :     mid = shortest(v, d, begin, begin, end, (chr **) NULL, (int *) NULL);
 3117                           936         [ -  + ]:            164 :     NOERR();
 4433                           937         [ +  - ]:            164 :     if (mid == NULL)
 4433 tgl@sss.pgh.pa.us         938                 :UBC           0 :         return REG_NOMATCH;
                                939                 :                :     MDEBUG(("%d: tentative midpoint %ld\n", t->id, LOFF(mid)));
                                940                 :                : 
                                941                 :                :     /* iterate until satisfaction or failure */
                                942                 :                :     for (;;)
                                943                 :                :     {
                                944                 :                :         /* try this midpoint on for size */
 5186 tgl@sss.pgh.pa.us         945         [ +  + ]:CBC         605 :         if (longest(v, d2, mid, end, (int *) NULL) == end)
                                946                 :                :         {
 1149                           947                 :             93 :             er = cdissect(v, left, begin, mid);
 5186                           948         [ +  - ]:             93 :             if (er == REG_OKAY)
                                949                 :                :             {
 1149                           950                 :             93 :                 er = cdissect(v, right, mid, end);
 5186                           951         [ +  + ]:             93 :                 if (er == REG_OKAY)
                                952                 :                :                 {
                                953                 :                :                     /* satisfaction */
                                954                 :                :                     MDEBUG(("%d: successful\n", t->id));
                                955                 :             81 :                     return REG_OKAY;
                                956                 :                :                 }
                                957                 :                :                 /* Reset left's matches (right should have done so itself) */
  965                           958                 :             12 :                 zaptreesubs(v, left);
                                959                 :                :             }
 4433                           960         [ -  + ]:             12 :             if (er != REG_NOMATCH)
 5186 tgl@sss.pgh.pa.us         961                 :UBC           0 :                 return er;
                                962                 :                :         }
 3117 tgl@sss.pgh.pa.us         963         [ -  + ]:CBC         524 :         NOERR();
                                964                 :                : 
                                965                 :                :         /* that midpoint didn't work, find a new one */
 7559 bruce@momjian.us          966         [ +  + ]:            524 :         if (mid == end)
                                967                 :                :         {
                                968                 :                :             /* all possibilities exhausted */
                                969                 :                :             MDEBUG(("%d: no midpoint\n", t->id));
 7739 tgl@sss.pgh.pa.us         970                 :             83 :             return REG_NOMATCH;
                                971                 :                :         }
 7559 bruce@momjian.us          972                 :            441 :         mid = shortest(v, d, begin, mid + 1, end, (chr **) NULL, (int *) NULL);
 3117 tgl@sss.pgh.pa.us         973         [ -  + ]:            441 :         NOERR();
 7559 bruce@momjian.us          974         [ -  + ]:            441 :         if (mid == NULL)
                                975                 :                :         {
                                976                 :                :             /* failed to find a new one */
                                977                 :                :             MDEBUG(("%d: failed midpoint\n", t->id));
 7739 tgl@sss.pgh.pa.us         978                 :UBC           0 :             return REG_NOMATCH;
                                979                 :                :         }
                                980                 :                :         MDEBUG(("%d: new midpoint %ld\n", t->id, LOFF(mid)));
                                981                 :                :     }
                                982                 :                : 
                                983                 :                :     /* can't get here */
                                984                 :                :     return REG_ASSERT;
                                985                 :                : }
                                986                 :                : 
                                987                 :                : /*
                                988                 :                :  * cbrdissect - dissect match for backref node
                                989                 :                :  *
                                990                 :                :  * The backref match might already have been verified by dfa_backref(),
                                991                 :                :  * but we don't know that for sure so must check it here.
                                992                 :                :  */
                                993                 :                : static int                      /* regexec return code */
 2489 tgl@sss.pgh.pa.us         994                 :CBC         209 : cbrdissect(struct vars *v,
                                995                 :                :            struct subre *t,
                                996                 :                :            chr *begin,          /* beginning of relevant substring */
                                997                 :                :            chr *end)            /* end of same */
                                998                 :                : {
 1149                           999                 :            209 :     int         n = t->backno;
                               1000                 :                :     size_t      numreps;
                               1001                 :                :     size_t      tlen;
                               1002                 :                :     size_t      brlen;
                               1003                 :                :     chr        *brstring;
                               1004                 :                :     chr        *p;
 7559 bruce@momjian.us         1005                 :            209 :     int         min = t->min;
                               1006                 :            209 :     int         max = t->max;
                               1007                 :                : 
 7739 tgl@sss.pgh.pa.us        1008         [ -  + ]:            209 :     assert(t != NULL);
                               1009         [ -  + ]:            209 :     assert(t->op == 'b');
                               1010         [ -  + ]:            209 :     assert(n >= 0);
 7559 bruce@momjian.us         1011         [ -  + ]:            209 :     assert((size_t) n < v->nmatch);
                               1012                 :                : 
                               1013                 :                :     MDEBUG(("%d: cbrdissect %d{%d-%d} %ld-%ld\n", t->id, n, min, max,
                               1014                 :                :             LOFF(begin), LOFF(end)));
                               1015                 :                : 
                               1016                 :                :     /* get the backreferenced string */
 7739 tgl@sss.pgh.pa.us        1017         [ +  + ]:            209 :     if (v->pmatch[n].rm_so == -1)
                               1018                 :             55 :         return REG_NOMATCH;
 4437                          1019                 :            154 :     brstring = v->start + v->pmatch[n].rm_so;
                               1020                 :            154 :     brlen = v->pmatch[n].rm_eo - v->pmatch[n].rm_so;
                               1021                 :                : 
                               1022                 :                :     /* special cases for zero-length strings */
                               1023         [ +  + ]:            154 :     if (brlen == 0)
                               1024                 :                :     {
                               1025                 :                :         /*
                               1026                 :                :          * matches only if target is zero length, but any number of
                               1027                 :                :          * repetitions can be considered to be present
                               1028                 :                :          */
                               1029   [ +  -  +  - ]:              7 :         if (begin == end && min <= max)
                               1030                 :                :         {
                               1031                 :                :             MDEBUG(("%d: backref matched trivially\n", t->id));
                               1032                 :              7 :             return REG_OKAY;
                               1033                 :                :         }
 4437 tgl@sss.pgh.pa.us        1034                 :UBC           0 :         return REG_NOMATCH;
                               1035                 :                :     }
 4437 tgl@sss.pgh.pa.us        1036         [ +  + ]:CBC         147 :     if (begin == end)
                               1037                 :                :     {
                               1038                 :                :         /* matches only if zero repetitions are okay */
                               1039         [ +  + ]:              6 :         if (min == 0)
                               1040                 :                :         {
                               1041                 :                :             MDEBUG(("%d: backref matched trivially\n", t->id));
 7739                          1042                 :              5 :             return REG_OKAY;
                               1043                 :                :         }
                               1044                 :              1 :         return REG_NOMATCH;
                               1045                 :                :     }
                               1046                 :                : 
                               1047                 :                :     /*
                               1048                 :                :      * check target length to see if it could possibly be an allowed number of
                               1049                 :                :      * repetitions of brstring
                               1050                 :                :      */
 4437                          1051         [ -  + ]:            141 :     assert(end > begin);
                               1052                 :            141 :     tlen = end - begin;
                               1053         [ +  + ]:            141 :     if (tlen % brlen != 0)
                               1054                 :              5 :         return REG_NOMATCH;
                               1055                 :            136 :     numreps = tlen / brlen;
 3133                          1056   [ +  -  +  +  :            136 :     if (numreps < min || (numreps > max && max != DUPINF))
                                              +  - ]
 7739                          1057                 :              3 :         return REG_NOMATCH;
                               1058                 :                : 
                               1059                 :                :     /* okay, compare the actual string contents */
 4437                          1060                 :            133 :     p = begin;
                               1061         [ +  + ]:            236 :     while (numreps-- > 0)
                               1062                 :                :     {
                               1063         [ +  + ]:            151 :         if ((*v->g->compare) (brstring, p, brlen) != 0)
                               1064                 :             48 :             return REG_NOMATCH;
                               1065                 :            103 :         p += brlen;
                               1066                 :                :     }
                               1067                 :                : 
                               1068                 :                :     MDEBUG(("%d: backref matched\n", t->id));
                               1069                 :             85 :     return REG_OKAY;
                               1070                 :                : }
                               1071                 :                : 
                               1072                 :                : /*
                               1073                 :                :  * caltdissect - dissect match for alternation node
                               1074                 :                :  */
                               1075                 :                : static int                      /* regexec return code */
 2489                          1076                 :             80 : caltdissect(struct vars *v,
                               1077                 :                :             struct subre *t,
                               1078                 :                :             chr *begin,         /* beginning of relevant substring */
                               1079                 :                :             chr *end)           /* end of same */
                               1080                 :                : {
                               1081                 :                :     struct dfa *d;
                               1082                 :                :     int         er;
                               1083                 :                : 
 1149                          1084         [ -  + ]:             80 :     assert(t->op == '|');
                               1085                 :                : 
                               1086                 :             80 :     t = t->child;
                               1087                 :                :     /* there should be at least 2 alternatives */
                               1088   [ +  -  -  + ]:             80 :     assert(t != NULL && t->sibling != NULL);
                               1089                 :                : 
 4433                          1090         [ +  + ]:            137 :     while (t != NULL)
                               1091                 :                :     {
 1149                          1092         [ -  + ]:            111 :         assert(t->cnfa.nstates > 0);
                               1093                 :                : 
                               1094                 :                :         MDEBUG(("%d: caltdissect %ld-%ld\n", t->id, LOFF(begin), LOFF(end)));
                               1095                 :                : 
                               1096                 :            111 :         d = getsubdfa(v, t);
 4433                          1097         [ -  + ]:            111 :         NOERR();
                               1098         [ +  + ]:            111 :         if (longest(v, d, begin, end, (int *) NULL) == end)
                               1099                 :                :         {
                               1100                 :                :             MDEBUG(("%d: caltdissect matched\n", t->id));
 1149                          1101                 :             88 :             er = cdissect(v, t, begin, end);
 4433                          1102         [ +  + ]:             88 :             if (er != REG_NOMATCH)
                               1103                 :             54 :                 return er;
                               1104                 :                :         }
 3117                          1105         [ -  + ]:             57 :         NOERR();
                               1106                 :                : 
 1149                          1107                 :             57 :         t = t->sibling;
                               1108                 :                :     }
                               1109                 :                : 
 4433                          1110                 :             26 :     return REG_NOMATCH;
                               1111                 :                : }
                               1112                 :                : 
                               1113                 :                : /*
                               1114                 :                :  * citerdissect - dissect match for iteration node
                               1115                 :                :  */
                               1116                 :                : static int                      /* regexec return code */
 2489                          1117                 :            117 : citerdissect(struct vars *v,
                               1118                 :                :              struct subre *t,
                               1119                 :                :              chr *begin,        /* beginning of relevant substring */
                               1120                 :                :              chr *end)          /* end of same */
                               1121                 :                : {
                               1122                 :                :     struct dfa *d;
                               1123                 :                :     chr       **endpts;
                               1124                 :                :     chr        *limit;
                               1125                 :                :     int         min_matches;
                               1126                 :                :     size_t      max_matches;
                               1127                 :                :     int         nverified;
                               1128                 :                :     int         k;
                               1129                 :                :     int         i;
                               1130                 :                :     int         er;
                               1131                 :                : 
 4433                          1132         [ -  + ]:            117 :     assert(t->op == '*');
 1149                          1133   [ +  -  -  + ]:            117 :     assert(t->child != NULL && t->child->cnfa.nstates > 0);
                               1134         [ -  + ]:            117 :     assert(!(t->child->flags & SHORTER));
 4433                          1135         [ -  + ]:            117 :     assert(begin <= end);
                               1136                 :                : 
                               1137                 :                :     MDEBUG(("%d: citerdissect %ld-%ld\n", t->id, LOFF(begin), LOFF(end)));
                               1138                 :                : 
                               1139                 :                :     /*
                               1140                 :                :      * For the moment, assume the minimum number of matches is 1.  If zero
                               1141                 :                :      * matches are allowed, and the target string is empty, we are allowed to
                               1142                 :                :      * match regardless of the contents of the iter node --- but we would
                               1143                 :                :      * prefer to match once, so that capturing parens get set.  (An example of
                               1144                 :                :      * the concern here is a pattern like "()*\1", which historically this
                               1145                 :                :      * code has allowed to succeed.)  Therefore, we deal with the zero-matches
                               1146                 :                :      * case at the bottom, after failing to find any other way to match.
                               1147                 :                :      */
                               1148                 :            117 :     min_matches = t->min;
                               1149         [ +  + ]:            117 :     if (min_matches <= 0)
                               1150                 :             81 :         min_matches = 1;
                               1151                 :                : 
                               1152                 :                :     /*
                               1153                 :                :      * We need workspace to track the endpoints of each sub-match.  Normally
                               1154                 :                :      * we consider only nonzero-length sub-matches, so there can be at most
                               1155                 :                :      * end-begin of them.  However, if min is larger than that, we will also
                               1156                 :                :      * consider zero-length sub-matches in order to find enough matches.
                               1157                 :                :      *
                               1158                 :                :      * For convenience, endpts[0] contains the "begin" pointer and we store
                               1159                 :                :      * sub-match endpoints in endpts[1..max_matches].
                               1160                 :                :      */
                               1161                 :            117 :     max_matches = end - begin;
 3133                          1162   [ -  +  -  - ]:            117 :     if (max_matches > t->max && t->max != DUPINF)
 4433 tgl@sss.pgh.pa.us        1163                 :UBC           0 :         max_matches = t->max;
 4433 tgl@sss.pgh.pa.us        1164         [ +  + ]:CBC         117 :     if (max_matches < min_matches)
                               1165                 :             73 :         max_matches = min_matches;
                               1166                 :            117 :     endpts = (chr **) MALLOC((max_matches + 1) * sizeof(chr *));
                               1167         [ -  + ]:            117 :     if (endpts == NULL)
 4433 tgl@sss.pgh.pa.us        1168                 :UBC           0 :         return REG_ESPACE;
 4433 tgl@sss.pgh.pa.us        1169                 :CBC         117 :     endpts[0] = begin;
                               1170                 :                : 
 1149                          1171                 :            117 :     d = getsubdfa(v, t->child);
 4433                          1172         [ -  + ]:            117 :     if (ISERR())
                               1173                 :                :     {
 4433 tgl@sss.pgh.pa.us        1174                 :UBC           0 :         FREE(endpts);
                               1175                 :              0 :         return v->err;
                               1176                 :                :     }
                               1177                 :                : 
                               1178                 :                :     /*
                               1179                 :                :      * Our strategy is to first find a set of sub-match endpoints that are
                               1180                 :                :      * valid according to the child node's DFA, and then recursively dissect
                               1181                 :                :      * each sub-match to confirm validity.  If any validity check fails,
                               1182                 :                :      * backtrack that sub-match and try again.  And, when we next try for a
                               1183                 :                :      * validity check, we need not recheck any successfully verified
                               1184                 :                :      * sub-matches that we didn't move the endpoints of.  nverified remembers
                               1185                 :                :      * how many sub-matches are currently known okay.
                               1186                 :                :      */
                               1187                 :                : 
                               1188                 :                :     /* initialize to consider first sub-match */
 4433 tgl@sss.pgh.pa.us        1189                 :CBC         117 :     nverified = 0;
                               1190                 :            117 :     k = 1;
                               1191                 :            117 :     limit = end;
                               1192                 :                : 
                               1193                 :                :     /* iterate until satisfaction or failure */
                               1194         [ +  + ]:            503 :     while (k > 0)
                               1195                 :                :     {
                               1196                 :                :         /* try to find an endpoint for the k'th sub-match */
                               1197                 :            407 :         endpts[k] = longest(v, d, endpts[k - 1], limit, (int *) NULL);
 3117                          1198         [ -  + ]:            407 :         if (ISERR())
                               1199                 :                :         {
 3117 tgl@sss.pgh.pa.us        1200                 :UBC           0 :             FREE(endpts);
                               1201                 :              0 :             return v->err;
                               1202                 :                :         }
 4433 tgl@sss.pgh.pa.us        1203         [ +  + ]:CBC         407 :         if (endpts[k] == NULL)
                               1204                 :                :         {
                               1205                 :                :             /* no match possible, so see if we can shorten previous one */
                               1206                 :            212 :             k--;
                               1207                 :            212 :             goto backtrack;
                               1208                 :                :         }
                               1209                 :                :         MDEBUG(("%d: working endpoint %d: %ld\n",
                               1210                 :                :                 t->id, k, LOFF(endpts[k])));
                               1211                 :                : 
                               1212                 :                :         /* k'th sub-match can no longer be considered verified */
                               1213         [ +  + ]:            195 :         if (nverified >= k)
                               1214                 :              8 :             nverified = k - 1;
                               1215                 :                : 
                               1216         [ +  + ]:            195 :         if (endpts[k] != end)
                               1217                 :                :         {
                               1218                 :                :             /* haven't reached end yet, try another iteration if allowed */
                               1219         [ -  + ]:            134 :             if (k >= max_matches)
                               1220                 :                :             {
                               1221                 :                :                 /* must try to shorten some previous match */
 4433 tgl@sss.pgh.pa.us        1222                 :UBC           0 :                 k--;
                               1223                 :              0 :                 goto backtrack;
                               1224                 :                :             }
                               1225                 :                : 
                               1226                 :                :             /* reject zero-length match unless necessary to achieve min */
 4433 tgl@sss.pgh.pa.us        1227   [ -  +  -  - ]:CBC         134 :             if (endpts[k] == endpts[k - 1] &&
 4433 tgl@sss.pgh.pa.us        1228         [ #  # ]:UBC           0 :                 (k >= min_matches || min_matches - k < end - endpts[k]))
                               1229                 :              0 :                 goto backtrack;
                               1230                 :                : 
 4433 tgl@sss.pgh.pa.us        1231                 :CBC         134 :             k++;
                               1232                 :            134 :             limit = end;
                               1233                 :            134 :             continue;
                               1234                 :                :         }
                               1235                 :                : 
                               1236                 :                :         /*
                               1237                 :                :          * We've identified a way to divide the string into k sub-matches that
                               1238                 :                :          * works so far as the child DFA can tell.  If k is an allowed number
                               1239                 :                :          * of matches, start the slow part: recurse to verify each sub-match.
                               1240                 :                :          * We always have k <= max_matches, needn't check that.
                               1241                 :                :          */
                               1242         [ -  + ]:             61 :         if (k < min_matches)
 4433 tgl@sss.pgh.pa.us        1243                 :UBC           0 :             goto backtrack;
                               1244                 :                : 
                               1245                 :                :         MDEBUG(("%d: verifying %d..%d\n", t->id, nverified + 1, k));
                               1246                 :                : 
 4433 tgl@sss.pgh.pa.us        1247         [ +  + ]:CBC         100 :         for (i = nverified + 1; i <= k; i++)
                               1248                 :                :         {
                               1249                 :                :             /* zap any match data from a non-last iteration */
 1149                          1250                 :             79 :             zaptreesubs(v, t->child);
                               1251                 :             79 :             er = cdissect(v, t->child, endpts[i - 1], endpts[i]);
 4433                          1252         [ +  + ]:             79 :             if (er == REG_OKAY)
                               1253                 :                :             {
                               1254                 :             39 :                 nverified = i;
                               1255                 :             39 :                 continue;
                               1256                 :                :             }
                               1257         [ +  - ]:             40 :             if (er == REG_NOMATCH)
                               1258                 :             40 :                 break;
                               1259                 :                :             /* oops, something failed */
 4433 tgl@sss.pgh.pa.us        1260                 :UBC           0 :             FREE(endpts);
                               1261                 :              0 :             return er;
                               1262                 :                :         }
                               1263                 :                : 
 4433 tgl@sss.pgh.pa.us        1264         [ +  + ]:CBC          61 :         if (i > k)
                               1265                 :                :         {
                               1266                 :                :             /* satisfaction */
                               1267                 :                :             MDEBUG(("%d: successful\n", t->id));
                               1268                 :             21 :             FREE(endpts);
                               1269                 :             21 :             return REG_OKAY;
                               1270                 :                :         }
                               1271                 :                : 
                               1272                 :                :         /* i'th match failed to verify, so backtrack it */
  968                          1273                 :             40 :         k = i;
                               1274                 :                : 
 4433                          1275                 :            252 : backtrack:
                               1276                 :                : 
                               1277                 :                :         /*
                               1278                 :                :          * Must consider shorter versions of the k'th sub-match.  However,
                               1279                 :                :          * we'll only ask for a zero-length match if necessary.
                               1280                 :                :          */
                               1281         [ +  + ]:            252 :         while (k > 0)
                               1282                 :                :         {
 4326 bruce@momjian.us         1283                 :            156 :             chr        *prev_end = endpts[k - 1];
                               1284                 :                : 
 4433 tgl@sss.pgh.pa.us        1285         [ +  - ]:            156 :             if (endpts[k] > prev_end)
                               1286                 :                :             {
                               1287                 :            156 :                 limit = endpts[k] - 1;
                               1288   [ -  +  -  - ]:            156 :                 if (limit > prev_end ||
 4433 tgl@sss.pgh.pa.us        1289         [ #  # ]:UBC           0 :                     (k < min_matches && min_matches - k >= end - prev_end))
                               1290                 :                :                 {
                               1291                 :                :                     /* break out of backtrack loop, continue the outer one */
                               1292                 :                :                     break;
                               1293                 :                :                 }
                               1294                 :                :             }
                               1295                 :                :             /* can't shorten k'th sub-match any more, consider previous one */
                               1296                 :              0 :             k--;
                               1297                 :                :         }
                               1298                 :                :     }
                               1299                 :                : 
                               1300                 :                :     /* all possibilities exhausted */
 4433 tgl@sss.pgh.pa.us        1301                 :CBC          96 :     FREE(endpts);
                               1302                 :                : 
                               1303                 :                :     /*
                               1304                 :                :      * Now consider the possibility that we can match to a zero-length string
                               1305                 :                :      * by using zero repetitions.
                               1306                 :                :      */
 3117                          1307   [ +  +  +  - ]:             96 :     if (t->min == 0 && begin == end)
                               1308                 :                :     {
                               1309                 :                :         MDEBUG(("%d: allowing zero matches\n", t->id));
                               1310                 :             68 :         return REG_OKAY;
                               1311                 :                :     }
                               1312                 :                : 
                               1313                 :                :     MDEBUG(("%d: failed\n", t->id));
 4433                          1314                 :             28 :     return REG_NOMATCH;
                               1315                 :                : }
                               1316                 :                : 
                               1317                 :                : /*
                               1318                 :                :  * creviterdissect - dissect match for iteration node, shortest-first
                               1319                 :                :  */
                               1320                 :                : static int                      /* regexec return code */
 2489                          1321                 :              7 : creviterdissect(struct vars *v,
                               1322                 :                :                 struct subre *t,
                               1323                 :                :                 chr *begin,     /* beginning of relevant substring */
                               1324                 :                :                 chr *end)       /* end of same */
                               1325                 :                : {
                               1326                 :                :     struct dfa *d;
                               1327                 :                :     chr       **endpts;
                               1328                 :                :     chr        *limit;
                               1329                 :                :     int         min_matches;
                               1330                 :                :     size_t      max_matches;
                               1331                 :                :     int         nverified;
                               1332                 :                :     int         k;
                               1333                 :                :     int         i;
                               1334                 :                :     int         er;
                               1335                 :                : 
 4433                          1336         [ -  + ]:              7 :     assert(t->op == '*');
 1149                          1337   [ +  -  -  + ]:              7 :     assert(t->child != NULL && t->child->cnfa.nstates > 0);
                               1338         [ -  + ]:              7 :     assert(t->child->flags & SHORTER);
 4433                          1339         [ -  + ]:              7 :     assert(begin <= end);
                               1340                 :                : 
                               1341                 :                :     MDEBUG(("%d: creviterdissect %ld-%ld\n", t->id, LOFF(begin), LOFF(end)));
                               1342                 :                : 
                               1343                 :                :     /*
                               1344                 :                :      * If zero matches are allowed, and target string is empty, just declare
                               1345                 :                :      * victory.  OTOH, if target string isn't empty, zero matches can't work
                               1346                 :                :      * so we pretend the min is 1.
                               1347                 :                :      */
                               1348                 :              7 :     min_matches = t->min;
                               1349         [ +  - ]:              7 :     if (min_matches <= 0)
                               1350                 :                :     {
                               1351         [ +  + ]:              7 :         if (begin == end)
                               1352                 :                :         {
                               1353                 :                :             MDEBUG(("%d: allowing zero matches\n", t->id));
                               1354                 :              1 :             return REG_OKAY;
                               1355                 :                :         }
                               1356                 :              6 :         min_matches = 1;
                               1357                 :                :     }
                               1358                 :                : 
                               1359                 :                :     /*
                               1360                 :                :      * We need workspace to track the endpoints of each sub-match.  Normally
                               1361                 :                :      * we consider only nonzero-length sub-matches, so there can be at most
                               1362                 :                :      * end-begin of them.  However, if min is larger than that, we will also
                               1363                 :                :      * consider zero-length sub-matches in order to find enough matches.
                               1364                 :                :      *
                               1365                 :                :      * For convenience, endpts[0] contains the "begin" pointer and we store
                               1366                 :                :      * sub-match endpoints in endpts[1..max_matches].
                               1367                 :                :      */
                               1368                 :              6 :     max_matches = end - begin;
 3133                          1369   [ +  -  +  - ]:              6 :     if (max_matches > t->max && t->max != DUPINF)
 4433                          1370                 :              6 :         max_matches = t->max;
                               1371         [ -  + ]:              6 :     if (max_matches < min_matches)
 4433 tgl@sss.pgh.pa.us        1372                 :UBC           0 :         max_matches = min_matches;
 4433 tgl@sss.pgh.pa.us        1373                 :CBC           6 :     endpts = (chr **) MALLOC((max_matches + 1) * sizeof(chr *));
                               1374         [ -  + ]:              6 :     if (endpts == NULL)
 4433 tgl@sss.pgh.pa.us        1375                 :UBC           0 :         return REG_ESPACE;
 4433 tgl@sss.pgh.pa.us        1376                 :CBC           6 :     endpts[0] = begin;
                               1377                 :                : 
 1149                          1378                 :              6 :     d = getsubdfa(v, t->child);
 4433                          1379         [ -  + ]:              6 :     if (ISERR())
                               1380                 :                :     {
 4433 tgl@sss.pgh.pa.us        1381                 :UBC           0 :         FREE(endpts);
                               1382                 :              0 :         return v->err;
                               1383                 :                :     }
                               1384                 :                : 
                               1385                 :                :     /*
                               1386                 :                :      * Our strategy is to first find a set of sub-match endpoints that are
                               1387                 :                :      * valid according to the child node's DFA, and then recursively dissect
                               1388                 :                :      * each sub-match to confirm validity.  If any validity check fails,
                               1389                 :                :      * backtrack that sub-match and try again.  And, when we next try for a
                               1390                 :                :      * validity check, we need not recheck any successfully verified
                               1391                 :                :      * sub-matches that we didn't move the endpoints of.  nverified remembers
                               1392                 :                :      * how many sub-matches are currently known okay.
                               1393                 :                :      */
                               1394                 :                : 
                               1395                 :                :     /* initialize to consider first sub-match */
 4433 tgl@sss.pgh.pa.us        1396                 :CBC           6 :     nverified = 0;
                               1397                 :              6 :     k = 1;
                               1398                 :              6 :     limit = begin;
                               1399                 :                : 
                               1400                 :                :     /* iterate until satisfaction or failure */
                               1401         [ +  + ]:              8 :     while (k > 0)
                               1402                 :                :     {
                               1403                 :                :         /* disallow zero-length match unless necessary to achieve min */
                               1404   [ +  -  +  - ]:              6 :         if (limit == endpts[k - 1] &&
                               1405         [ -  + ]:              6 :             limit != end &&
 4433 tgl@sss.pgh.pa.us        1406         [ #  # ]:UBC           0 :             (k >= min_matches || min_matches - k < end - limit))
 4433 tgl@sss.pgh.pa.us        1407                 :CBC           6 :             limit++;
                               1408                 :                : 
                               1409                 :                :         /* if this is the last allowed sub-match, it must reach to the end */
 3491                          1410         [ +  - ]:              6 :         if (k >= max_matches)
                               1411                 :              6 :             limit = end;
                               1412                 :                : 
                               1413                 :                :         /* try to find an endpoint for the k'th sub-match */
 4433                          1414                 :              6 :         endpts[k] = shortest(v, d, endpts[k - 1], limit, end,
                               1415                 :                :                              (chr **) NULL, (int *) NULL);
 3117                          1416         [ -  + ]:              6 :         if (ISERR())
                               1417                 :                :         {
 3117 tgl@sss.pgh.pa.us        1418                 :UBC           0 :             FREE(endpts);
                               1419                 :              0 :             return v->err;
                               1420                 :                :         }
 4433 tgl@sss.pgh.pa.us        1421         [ -  + ]:CBC           6 :         if (endpts[k] == NULL)
                               1422                 :                :         {
                               1423                 :                :             /* no match possible, so see if we can lengthen previous one */
 4433 tgl@sss.pgh.pa.us        1424                 :UBC           0 :             k--;
                               1425                 :              0 :             goto backtrack;
                               1426                 :                :         }
                               1427                 :                :         MDEBUG(("%d: working endpoint %d: %ld\n",
                               1428                 :                :                 t->id, k, LOFF(endpts[k])));
                               1429                 :                : 
                               1430                 :                :         /* k'th sub-match can no longer be considered verified */
 4433 tgl@sss.pgh.pa.us        1431         [ -  + ]:CBC           6 :         if (nverified >= k)
 4433 tgl@sss.pgh.pa.us        1432                 :UBC           0 :             nverified = k - 1;
                               1433                 :                : 
 4433 tgl@sss.pgh.pa.us        1434         [ -  + ]:CBC           6 :         if (endpts[k] != end)
                               1435                 :                :         {
                               1436                 :                :             /* haven't reached end yet, try another iteration if allowed */
 4433 tgl@sss.pgh.pa.us        1437         [ #  # ]:UBC           0 :             if (k >= max_matches)
                               1438                 :                :             {
                               1439                 :                :                 /* must try to lengthen some previous match */
                               1440                 :              0 :                 k--;
                               1441                 :              0 :                 goto backtrack;
                               1442                 :                :             }
                               1443                 :                : 
                               1444                 :              0 :             k++;
                               1445                 :              0 :             limit = endpts[k - 1];
                               1446                 :              0 :             continue;
                               1447                 :                :         }
                               1448                 :                : 
                               1449                 :                :         /*
                               1450                 :                :          * We've identified a way to divide the string into k sub-matches that
                               1451                 :                :          * works so far as the child DFA can tell.  If k is an allowed number
                               1452                 :                :          * of matches, start the slow part: recurse to verify each sub-match.
                               1453                 :                :          * We always have k <= max_matches, needn't check that.
                               1454                 :                :          */
 4433 tgl@sss.pgh.pa.us        1455         [ -  + ]:CBC           6 :         if (k < min_matches)
 4433 tgl@sss.pgh.pa.us        1456                 :UBC           0 :             goto backtrack;
                               1457                 :                : 
                               1458                 :                :         MDEBUG(("%d: verifying %d..%d\n", t->id, nverified + 1, k));
                               1459                 :                : 
 4433 tgl@sss.pgh.pa.us        1460         [ +  + ]:CBC          10 :         for (i = nverified + 1; i <= k; i++)
                               1461                 :                :         {
                               1462                 :                :             /* zap any match data from a non-last iteration */
 1149                          1463                 :              6 :             zaptreesubs(v, t->child);
                               1464                 :              6 :             er = cdissect(v, t->child, endpts[i - 1], endpts[i]);
 4433                          1465         [ +  + ]:              6 :             if (er == REG_OKAY)
                               1466                 :                :             {
                               1467                 :              4 :                 nverified = i;
                               1468                 :              4 :                 continue;
                               1469                 :                :             }
                               1470         [ +  - ]:              2 :             if (er == REG_NOMATCH)
                               1471                 :              2 :                 break;
                               1472                 :                :             /* oops, something failed */
 4433 tgl@sss.pgh.pa.us        1473                 :UBC           0 :             FREE(endpts);
                               1474                 :              0 :             return er;
                               1475                 :                :         }
                               1476                 :                : 
 4433 tgl@sss.pgh.pa.us        1477         [ +  + ]:CBC           6 :         if (i > k)
                               1478                 :                :         {
                               1479                 :                :             /* satisfaction */
                               1480                 :                :             MDEBUG(("%d: successful\n", t->id));
                               1481                 :              4 :             FREE(endpts);
                               1482                 :              4 :             return REG_OKAY;
                               1483                 :                :         }
                               1484                 :                : 
                               1485                 :                :         /* i'th match failed to verify, so backtrack it */
  968                          1486                 :              2 :         k = i;
                               1487                 :                : 
 4433                          1488                 :              2 : backtrack:
                               1489                 :                : 
                               1490                 :                :         /*
                               1491                 :                :          * Must consider longer versions of the k'th sub-match.
                               1492                 :                :          */
                               1493         [ +  + ]:              4 :         while (k > 0)
                               1494                 :                :         {
                               1495         [ -  + ]:              2 :             if (endpts[k] < end)
                               1496                 :                :             {
 4433 tgl@sss.pgh.pa.us        1497                 :UBC           0 :                 limit = endpts[k] + 1;
                               1498                 :                :                 /* break out of backtrack loop, continue the outer one */
                               1499                 :              0 :                 break;
                               1500                 :                :             }
                               1501                 :                :             /* can't lengthen k'th sub-match any more, consider previous one */
 4433 tgl@sss.pgh.pa.us        1502                 :CBC           2 :             k--;
                               1503                 :                :         }
                               1504                 :                :     }
                               1505                 :                : 
                               1506                 :                :     /* all possibilities exhausted */
                               1507                 :                :     MDEBUG(("%d: failed\n", t->id));
                               1508                 :              2 :     FREE(endpts);
                               1509                 :              2 :     return REG_NOMATCH;
                               1510                 :                : }
                               1511                 :                : 
                               1512                 :                : 
                               1513                 :                : 
                               1514                 :                : #include "rege_dfa.c"
        

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