LCOV - differential code coverage report
Current view: top level - src/backend/regex - regcomp.c (source / functions) Coverage Total Hit UBC CBC
Current: Differential Code Coverage 16@8cea358b128 vs 17@8cea358b128 Lines: 96.8 % 1003 971 32 971
Current Date: 2024-04-14 14:21:10 Functions: 100.0 % 35 35 35
Baseline: 16@8cea358b128 Branches: 73.7 % 788 581 207 581
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: 96.8 % 1003 971 32 971
Function coverage date bins:
(240..) days: 100.0 % 35 35 35
Branch coverage date bins:
(240..) days: 73.7 % 788 581 207 581

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*
                                  2                 :                :  * re_*comp and friends - compile REs
                                  3                 :                :  * This file #includes several others (see the bottom).
                                  4                 :                :  *
                                  5                 :                :  * Copyright (c) 1998, 1999 Henry Spencer.  All rights reserved.
                                  6                 :                :  *
                                  7                 :                :  * Development of this software was funded, in part, by Cray Research Inc.,
                                  8                 :                :  * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
                                  9                 :                :  * Corporation, none of whom are responsible for the results.  The author
                                 10                 :                :  * thanks all of them.
                                 11                 :                :  *
                                 12                 :                :  * Redistribution and use in source and binary forms -- with or without
                                 13                 :                :  * modification -- are permitted for any purpose, provided that
                                 14                 :                :  * redistributions in source form retain this entire copyright notice and
                                 15                 :                :  * indicate the origin and nature of any modifications.
                                 16                 :                :  *
                                 17                 :                :  * I'd appreciate being given credit for this package in the documentation
                                 18                 :                :  * of software which uses it, but that is not a requirement.
                                 19                 :                :  *
                                 20                 :                :  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
                                 21                 :                :  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
                                 22                 :                :  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
                                 23                 :                :  * HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
                                 24                 :                :  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
                                 25                 :                :  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
                                 26                 :                :  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
                                 27                 :                :  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
                                 28                 :                :  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
                                 29                 :                :  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                                 30                 :                :  *
                                 31                 :                :  * src/backend/regex/regcomp.c
                                 32                 :                :  *
                                 33                 :                :  */
                                 34                 :                : 
                                 35                 :                : #include "regex/regguts.h"
                                 36                 :                : 
                                 37                 :                : /*
                                 38                 :                :  * forward declarations, up here so forward datatypes etc. are defined early
                                 39                 :                :  */
                                 40                 :                : /* === regcomp.c === */
                                 41                 :                : static void moresubs(struct vars *v, int wanted);
                                 42                 :                : static int  freev(struct vars *v, int err);
                                 43                 :                : static void makesearch(struct vars *v, struct nfa *nfa);
                                 44                 :                : static struct subre *parse(struct vars *v, int stopper, int type,
                                 45                 :                :                            struct state *init, struct state *final);
                                 46                 :                : static struct subre *parsebranch(struct vars *v, int stopper, int type,
                                 47                 :                :                                  struct state *left, struct state *right,
                                 48                 :                :                                  int partial);
                                 49                 :                : static struct subre *parseqatom(struct vars *v, int stopper, int type,
                                 50                 :                :                                 struct state *lp, struct state *rp,
                                 51                 :                :                                 struct subre *top);
                                 52                 :                : static void nonword(struct vars *v, int dir, struct state *lp,
                                 53                 :                :                     struct state *rp);
                                 54                 :                : static void word(struct vars *v, int dir, struct state *lp, struct state *rp);
                                 55                 :                : static void charclass(struct vars *v, enum char_classes cls, struct state *lp,
                                 56                 :                :                       struct state *rp);
                                 57                 :                : static void charclasscomplement(struct vars *v, enum char_classes cls,
                                 58                 :                :                                 struct state *lp, struct state *rp);
                                 59                 :                : static int  scannum(struct vars *v);
                                 60                 :                : static void repeat(struct vars *v, struct state *lp, struct state *rp,
                                 61                 :                :                    int m, int n);
                                 62                 :                : static void bracket(struct vars *v, struct state *lp, struct state *rp);
                                 63                 :                : static void cbracket(struct vars *v, struct state *lp, struct state *rp);
                                 64                 :                : static void brackpart(struct vars *v, struct state *lp, struct state *rp,
                                 65                 :                :                       bool *have_cclassc);
                                 66                 :                : static const chr *scanplain(struct vars *v);
                                 67                 :                : static void onechr(struct vars *v, chr c, struct state *lp, struct state *rp);
                                 68                 :                : static void optimizebracket(struct vars *v, struct state *lp, struct state *rp);
                                 69                 :                : static void wordchrs(struct vars *v);
                                 70                 :                : static void processlacon(struct vars *v, struct state *begin,
                                 71                 :                :                          struct state *end, int latype,
                                 72                 :                :                          struct state *lp, struct state *rp);
                                 73                 :                : static struct subre *subre(struct vars *v, int op, int flags,
                                 74                 :                :                            struct state *begin, struct state *end);
                                 75                 :                : static void freesubre(struct vars *v, struct subre *sr);
                                 76                 :                : static void freesubreandsiblings(struct vars *v, struct subre *sr);
                                 77                 :                : static void freesrnode(struct vars *v, struct subre *sr);
                                 78                 :                : static void removecaptures(struct vars *v, struct subre *t);
                                 79                 :                : static int  numst(struct subre *t, int start);
                                 80                 :                : static void markst(struct subre *t);
                                 81                 :                : static void cleanst(struct vars *v);
                                 82                 :                : static long nfatree(struct vars *v, struct subre *t, FILE *f);
                                 83                 :                : static long nfanode(struct vars *v, struct subre *t,
                                 84                 :                :                     int converttosearch, FILE *f);
                                 85                 :                : static int  newlacon(struct vars *v, struct state *begin, struct state *end,
                                 86                 :                :                      int latype);
                                 87                 :                : static void freelacons(struct subre *subs, int n);
                                 88                 :                : static void rfree(regex_t *re);
                                 89                 :                : static int  rstacktoodeep(void);
                                 90                 :                : 
                                 91                 :                : #ifdef REG_DEBUG
                                 92                 :                : static void dump(regex_t *re, FILE *f);
                                 93                 :                : static void dumpst(struct subre *t, FILE *f, int nfapresent);
                                 94                 :                : static void stdump(struct subre *t, FILE *f, int nfapresent);
                                 95                 :                : static const char *stid(struct subre *t, char *buf, size_t bufsize);
                                 96                 :                : #endif
                                 97                 :                : /* === regc_lex.c === */
                                 98                 :                : static void lexstart(struct vars *v);
                                 99                 :                : static void prefixes(struct vars *v);
                                100                 :                : static int  next(struct vars *v);
                                101                 :                : static int  lexescape(struct vars *v);
                                102                 :                : static chr  lexdigits(struct vars *v, int base, int minlen, int maxlen);
                                103                 :                : static int  brenext(struct vars *v, chr c);
                                104                 :                : static void skip(struct vars *v);
                                105                 :                : static chr  newline(void);
                                106                 :                : static chr  chrnamed(struct vars *v, const chr *startp, const chr *endp,
                                107                 :                :                      chr lastresort);
                                108                 :                : 
                                109                 :                : /* === regc_color.c === */
                                110                 :                : static void initcm(struct vars *v, struct colormap *cm);
                                111                 :                : static void freecm(struct colormap *cm);
                                112                 :                : static color maxcolor(struct colormap *cm);
                                113                 :                : static color newcolor(struct colormap *cm);
                                114                 :                : static void freecolor(struct colormap *cm, color co);
                                115                 :                : static color pseudocolor(struct colormap *cm);
                                116                 :                : static color subcolor(struct colormap *cm, chr c);
                                117                 :                : static color subcolorhi(struct colormap *cm, color *pco);
                                118                 :                : static color newsub(struct colormap *cm, color co);
                                119                 :                : static int  newhicolorrow(struct colormap *cm, int oldrow);
                                120                 :                : static void newhicolorcols(struct colormap *cm);
                                121                 :                : static void subcolorcvec(struct vars *v, struct cvec *cv, struct state *lp,
                                122                 :                :                          struct state *rp);
                                123                 :                : static void subcoloronechr(struct vars *v, chr ch, struct state *lp,
                                124                 :                :                            struct state *rp, color *lastsubcolor);
                                125                 :                : static void subcoloronerange(struct vars *v, chr from, chr to,
                                126                 :                :                              struct state *lp, struct state *rp,
                                127                 :                :                              color *lastsubcolor);
                                128                 :                : static void subcoloronerow(struct vars *v, int rownum, struct state *lp,
                                129                 :                :                            struct state *rp, color *lastsubcolor);
                                130                 :                : static void okcolors(struct nfa *nfa, struct colormap *cm);
                                131                 :                : static void colorchain(struct colormap *cm, struct arc *a);
                                132                 :                : static void uncolorchain(struct colormap *cm, struct arc *a);
                                133                 :                : static void rainbow(struct nfa *nfa, struct colormap *cm, int type, color but,
                                134                 :                :                     struct state *from, struct state *to);
                                135                 :                : static void colorcomplement(struct nfa *nfa, struct colormap *cm, int type,
                                136                 :                :                             struct state *of, struct state *from,
                                137                 :                :                             struct state *to);
                                138                 :                : 
                                139                 :                : #ifdef REG_DEBUG
                                140                 :                : static void dumpcolors(struct colormap *cm, FILE *f);
                                141                 :                : static void dumpchr(chr c, FILE *f);
                                142                 :                : #endif
                                143                 :                : /* === regc_nfa.c === */
                                144                 :                : static struct nfa *newnfa(struct vars *v, struct colormap *cm,
                                145                 :                :                           struct nfa *parent);
                                146                 :                : static void freenfa(struct nfa *nfa);
                                147                 :                : static struct state *newstate(struct nfa *nfa);
                                148                 :                : static struct state *newfstate(struct nfa *nfa, int flag);
                                149                 :                : static void dropstate(struct nfa *nfa, struct state *s);
                                150                 :                : static void freestate(struct nfa *nfa, struct state *s);
                                151                 :                : static void newarc(struct nfa *nfa, int t, color co,
                                152                 :                :                    struct state *from, struct state *to);
                                153                 :                : static void createarc(struct nfa *nfa, int t, color co,
                                154                 :                :                       struct state *from, struct state *to);
                                155                 :                : static struct arc *allocarc(struct nfa *nfa);
                                156                 :                : static void freearc(struct nfa *nfa, struct arc *victim);
                                157                 :                : static void changearcsource(struct arc *a, struct state *newfrom);
                                158                 :                : static void changearctarget(struct arc *a, struct state *newto);
                                159                 :                : static int  hasnonemptyout(struct state *s);
                                160                 :                : static struct arc *findarc(struct state *s, int type, color co);
                                161                 :                : static void cparc(struct nfa *nfa, struct arc *oa,
                                162                 :                :                   struct state *from, struct state *to);
                                163                 :                : static void sortins(struct nfa *nfa, struct state *s);
                                164                 :                : static int  sortins_cmp(const void *a, const void *b);
                                165                 :                : static void sortouts(struct nfa *nfa, struct state *s);
                                166                 :                : static int  sortouts_cmp(const void *a, const void *b);
                                167                 :                : static void moveins(struct nfa *nfa, struct state *oldState,
                                168                 :                :                     struct state *newState);
                                169                 :                : static void copyins(struct nfa *nfa, struct state *oldState,
                                170                 :                :                     struct state *newState);
                                171                 :                : static void mergeins(struct nfa *nfa, struct state *s,
                                172                 :                :                      struct arc **arcarray, int arccount);
                                173                 :                : static void moveouts(struct nfa *nfa, struct state *oldState,
                                174                 :                :                      struct state *newState);
                                175                 :                : static void copyouts(struct nfa *nfa, struct state *oldState,
                                176                 :                :                      struct state *newState);
                                177                 :                : static void cloneouts(struct nfa *nfa, struct state *old, struct state *from,
                                178                 :                :                       struct state *to, int type);
                                179                 :                : static void delsub(struct nfa *nfa, struct state *lp, struct state *rp);
                                180                 :                : static void deltraverse(struct nfa *nfa, struct state *leftend,
                                181                 :                :                         struct state *s);
                                182                 :                : static void dupnfa(struct nfa *nfa, struct state *start, struct state *stop,
                                183                 :                :                    struct state *from, struct state *to);
                                184                 :                : static void duptraverse(struct nfa *nfa, struct state *s, struct state *stmp);
                                185                 :                : static void removeconstraints(struct nfa *nfa, struct state *start, struct state *stop);
                                186                 :                : static void removetraverse(struct nfa *nfa, struct state *s);
                                187                 :                : static void cleartraverse(struct nfa *nfa, struct state *s);
                                188                 :                : static struct state *single_color_transition(struct state *s1,
                                189                 :                :                                              struct state *s2);
                                190                 :                : static void specialcolors(struct nfa *nfa);
                                191                 :                : static long optimize(struct nfa *nfa, FILE *f);
                                192                 :                : static void pullback(struct nfa *nfa, FILE *f);
                                193                 :                : static int  pull(struct nfa *nfa, struct arc *con,
                                194                 :                :                  struct state **intermediates);
                                195                 :                : static void pushfwd(struct nfa *nfa, FILE *f);
                                196                 :                : static int  push(struct nfa *nfa, struct arc *con,
                                197                 :                :                  struct state **intermediates);
                                198                 :                : 
                                199                 :                : #define INCOMPATIBLE    1       /* destroys arc */
                                200                 :                : #define SATISFIED   2           /* constraint satisfied */
                                201                 :                : #define COMPATIBLE  3           /* compatible but not satisfied yet */
                                202                 :                : #define REPLACEARC  4           /* replace arc's color with constraint color */
                                203                 :                : static int  combine(struct nfa *nfa, struct arc *con, struct arc *a);
                                204                 :                : static void fixempties(struct nfa *nfa, FILE *f);
                                205                 :                : static struct state *emptyreachable(struct nfa *nfa, struct state *s,
                                206                 :                :                                     struct state *lastfound,
                                207                 :                :                                     struct arc **inarcsorig);
                                208                 :                : static int  isconstraintarc(struct arc *a);
                                209                 :                : static int  hasconstraintout(struct state *s);
                                210                 :                : static void fixconstraintloops(struct nfa *nfa, FILE *f);
                                211                 :                : static int  findconstraintloop(struct nfa *nfa, struct state *s);
                                212                 :                : static void breakconstraintloop(struct nfa *nfa, struct state *sinitial);
                                213                 :                : static void clonesuccessorstates(struct nfa *nfa, struct state *ssource,
                                214                 :                :                                  struct state *sclone,
                                215                 :                :                                  struct state *spredecessor,
                                216                 :                :                                  struct arc *refarc, char *curdonemap,
                                217                 :                :                                  char *outerdonemap, int nstates);
                                218                 :                : static void cleanup(struct nfa *nfa);
                                219                 :                : static void markreachable(struct nfa *nfa, struct state *s,
                                220                 :                :                           struct state *okay, struct state *mark);
                                221                 :                : static void markcanreach(struct nfa *nfa, struct state *s, struct state *okay,
                                222                 :                :                          struct state *mark);
                                223                 :                : static long analyze(struct nfa *nfa);
                                224                 :                : static void checkmatchall(struct nfa *nfa);
                                225                 :                : static bool checkmatchall_recurse(struct nfa *nfa, struct state *s,
                                226                 :                :                                   bool **haspaths);
                                227                 :                : static bool check_out_colors_match(struct state *s, color co1, color co2);
                                228                 :                : static bool check_in_colors_match(struct state *s, color co1, color co2);
                                229                 :                : static void compact(struct nfa *nfa, struct cnfa *cnfa);
                                230                 :                : static void carcsort(struct carc *first, size_t n);
                                231                 :                : static int  carc_cmp(const void *a, const void *b);
                                232                 :                : static void freecnfa(struct cnfa *cnfa);
                                233                 :                : static void dumpnfa(struct nfa *nfa, FILE *f);
                                234                 :                : 
                                235                 :                : #ifdef REG_DEBUG
                                236                 :                : static void dumpstate(struct state *s, FILE *f);
                                237                 :                : static void dumparcs(struct state *s, FILE *f);
                                238                 :                : static void dumparc(struct arc *a, struct state *s, FILE *f);
                                239                 :                : static void dumpcnfa(struct cnfa *cnfa, FILE *f);
                                240                 :                : static void dumpcstate(int st, struct cnfa *cnfa, FILE *f);
                                241                 :                : #endif
                                242                 :                : /* === regc_cvec.c === */
                                243                 :                : static struct cvec *newcvec(int nchrs, int nranges);
                                244                 :                : static struct cvec *clearcvec(struct cvec *cv);
                                245                 :                : static void addchr(struct cvec *cv, chr c);
                                246                 :                : static void addrange(struct cvec *cv, chr from, chr to);
                                247                 :                : static struct cvec *getcvec(struct vars *v, int nchrs, int nranges);
                                248                 :                : static void freecvec(struct cvec *cv);
                                249                 :                : 
                                250                 :                : /* === regc_pg_locale.c === */
                                251                 :                : static int  pg_wc_isdigit(pg_wchar c);
                                252                 :                : static int  pg_wc_isalpha(pg_wchar c);
                                253                 :                : static int  pg_wc_isalnum(pg_wchar c);
                                254                 :                : static int  pg_wc_isword(pg_wchar c);
                                255                 :                : static int  pg_wc_isupper(pg_wchar c);
                                256                 :                : static int  pg_wc_islower(pg_wchar c);
                                257                 :                : static int  pg_wc_isgraph(pg_wchar c);
                                258                 :                : static int  pg_wc_isprint(pg_wchar c);
                                259                 :                : static int  pg_wc_ispunct(pg_wchar c);
                                260                 :                : static int  pg_wc_isspace(pg_wchar c);
                                261                 :                : static pg_wchar pg_wc_toupper(pg_wchar c);
                                262                 :                : static pg_wchar pg_wc_tolower(pg_wchar c);
                                263                 :                : 
                                264                 :                : /* === regc_locale.c === */
                                265                 :                : static chr  element(struct vars *v, const chr *startp, const chr *endp);
                                266                 :                : static struct cvec *range(struct vars *v, chr a, chr b, int cases);
                                267                 :                : static int  before(chr x, chr y);
                                268                 :                : static struct cvec *eclass(struct vars *v, chr c, int cases);
                                269                 :                : static enum char_classes lookupcclass(struct vars *v, const chr *startp,
                                270                 :                :                                       const chr *endp);
                                271                 :                : static struct cvec *cclasscvec(struct vars *v, enum char_classes cclasscode,
                                272                 :                :                                int cases);
                                273                 :                : static int  cclass_column_index(struct colormap *cm, chr c);
                                274                 :                : static struct cvec *allcases(struct vars *v, chr c);
                                275                 :                : static int  cmp(const chr *x, const chr *y, size_t len);
                                276                 :                : static int  casecmp(const chr *x, const chr *y, size_t len);
                                277                 :                : 
                                278                 :                : 
                                279                 :                : /* internal variables, bundled for easy passing around */
                                280                 :                : struct vars
                                281                 :                : {
                                282                 :                :     regex_t    *re;
                                283                 :                :     const chr  *now;            /* scan pointer into string */
                                284                 :                :     const chr  *stop;           /* end of string */
                                285                 :                :     int         err;            /* error code (0 if none) */
                                286                 :                :     int         cflags;         /* copy of compile flags */
                                287                 :                :     int         lasttype;       /* type of previous token */
                                288                 :                :     int         nexttype;       /* type of next token */
                                289                 :                :     chr         nextvalue;      /* value (if any) of next token */
                                290                 :                :     int         lexcon;         /* lexical context type (see regc_lex.c) */
                                291                 :                :     int         nsubexp;        /* subexpression count */
                                292                 :                :     struct subre **subs;        /* subRE pointer vector */
                                293                 :                :     size_t      nsubs;          /* length of vector */
                                294                 :                :     struct subre *sub10[10];    /* initial vector, enough for most */
                                295                 :                :     struct nfa *nfa;            /* the NFA */
                                296                 :                :     struct colormap *cm;        /* character color map */
                                297                 :                :     color       nlcolor;        /* color of newline */
                                298                 :                :     struct state *wordchrs;     /* state in nfa holding word-char outarcs */
                                299                 :                :     struct subre *tree;         /* subexpression tree */
                                300                 :                :     struct subre *treechain;    /* all tree nodes allocated */
                                301                 :                :     struct subre *treefree;     /* any free tree nodes */
                                302                 :                :     int         ntree;          /* number of tree nodes, plus one */
                                303                 :                :     struct cvec *cv;            /* interface cvec */
                                304                 :                :     struct cvec *cv2;           /* utility cvec */
                                305                 :                :     struct subre *lacons;       /* lookaround-constraint vector */
                                306                 :                :     int         nlacons;        /* size of lacons[]; note that only slots
                                307                 :                :                                  * numbered 1 .. nlacons-1 are used */
                                308                 :                :     size_t      spaceused;      /* approx. space used for compilation */
                                309                 :                : };
                                310                 :                : 
                                311                 :                : /* parsing macros; most know that `v' is the struct vars pointer */
                                312                 :                : #define NEXT()  (next(v))       /* advance by one token */
                                313                 :                : #define SEE(t)  (v->nexttype == (t)) /* is next token this? */
                                314                 :                : #define EAT(t)  (SEE(t) && next(v)) /* if next is this, swallow it */
                                315                 :                : #define VISERR(vv)  ((vv)->err != 0) /* have we seen an error yet? */
                                316                 :                : #define ISERR() VISERR(v)
                                317                 :                : #define VERR(vv,e)  ((vv)->nexttype = EOS, \
                                318                 :                :                      (vv)->err = ((vv)->err ? (vv)->err : (e)))
                                319                 :                : #define ERR(e)  VERR(v, e)      /* record an error */
                                320                 :                : #define NOERR() {if (ISERR()) return;}  /* if error seen, return */
                                321                 :                : #define NOERRN()    {if (ISERR()) return NULL;} /* NOERR with retval */
                                322                 :                : #define NOERRZ()    {if (ISERR()) return 0;}    /* NOERR with retval */
                                323                 :                : #define INSIST(c, e) do { if (!(c)) ERR(e); } while (0) /* error if c false */
                                324                 :                : #define NOTE(b) (v->re->re_info |= (b)) /* note visible condition */
                                325                 :                : #define EMPTYARC(x, y)  newarc(v->nfa, EMPTY, 0, x, y)
                                326                 :                : 
                                327                 :                : /* token type codes, some also used as NFA arc types */
                                328                 :                : #define EMPTY   'n'             /* no token present */
                                329                 :                : #define EOS 'e'                 /* end of string */
                                330                 :                : #define PLAIN   'p'             /* ordinary character */
                                331                 :                : #define DIGIT   'd'             /* digit (in bound) */
                                332                 :                : #define BACKREF 'b'             /* back reference */
                                333                 :                : #define COLLEL  'I'             /* start of [. */
                                334                 :                : #define ECLASS  'E'             /* start of [= */
                                335                 :                : #define CCLASS  'C'             /* start of [: */
                                336                 :                : #define END 'X'                 /* end of [. [= [: */
                                337                 :                : #define CCLASSS 's'             /* char class shorthand escape */
                                338                 :                : #define CCLASSC 'c'             /* complement char class shorthand escape */
                                339                 :                : #define RANGE   'R'             /* - within [] which might be range delim. */
                                340                 :                : #define LACON   'L'             /* lookaround constraint subRE */
                                341                 :                : #define AHEAD   'a'             /* color-lookahead arc */
                                342                 :                : #define BEHIND  'r'             /* color-lookbehind arc */
                                343                 :                : #define WBDRY   'w'             /* word boundary constraint */
                                344                 :                : #define NWBDRY  'W'             /* non-word-boundary constraint */
                                345                 :                : #define SBEGIN  'A'             /* beginning of string (even if not BOL) */
                                346                 :                : #define SEND    'Z'             /* end of string (even if not EOL) */
                                347                 :                : 
                                348                 :                : /* is an arc colored, and hence should belong to a color chain? */
                                349                 :                : /* the test on "co" eliminates RAINBOW arcs, which we don't bother to chain */
                                350                 :                : #define COLORED(a) \
                                351                 :                :     ((a)->co >= 0 && \
                                352                 :                :      ((a)->type == PLAIN || (a)->type == AHEAD || (a)->type == BEHIND))
                                353                 :                : 
                                354                 :                : 
                                355                 :                : /* static function list */
                                356                 :                : static const struct fns functions = {
                                357                 :                :     rfree,                      /* regfree insides */
                                358                 :                :     rstacktoodeep               /* check for stack getting dangerously deep */
                                359                 :                : };
                                360                 :                : 
                                361                 :                : 
                                362                 :                : 
                                363                 :                : /*
                                364                 :                :  * pg_regcomp - compile regular expression
                                365                 :                :  *
                                366                 :                :  * Note: on failure, no resources remain allocated, so pg_regfree()
                                367                 :                :  * need not be applied to re.
                                368                 :                :  */
                                369                 :                : int
 7739 tgl@sss.pgh.pa.us         370                 :CBC        3627 : pg_regcomp(regex_t *re,
                                371                 :                :            const chr *string,
                                372                 :                :            size_t len,
                                373                 :                :            int flags,
                                374                 :                :            Oid collation)
                                375                 :                : {
                                376                 :                :     struct vars var;
                                377                 :           3627 :     struct vars *v = &var;
                                378                 :                :     struct guts *g;
                                379                 :                :     int         i;
                                380                 :                :     size_t      j;
                                381                 :                : 
                                382                 :                : #ifdef REG_DEBUG
                                383                 :                :     FILE       *debug = (flags & REG_PROGRESS) ? stdout : (FILE *) NULL;
                                384                 :                : #else
 7559 bruce@momjian.us          385                 :           3627 :     FILE       *debug = (FILE *) NULL;
                                386                 :                : #endif
                                387                 :                : 
                                388                 :                : #define  CNOERR()    { if (ISERR()) return freev(v, v->err); }
                                389                 :                : 
                                390                 :                :     /* sanity checks */
                                391                 :                : 
 7739 tgl@sss.pgh.pa.us         392   [ +  -  -  + ]:           3627 :     if (re == NULL || string == NULL)
 7739 tgl@sss.pgh.pa.us         393                 :UBC           0 :         return REG_INVARG;
 7559 bruce@momjian.us          394         [ +  + ]:CBC        3627 :     if ((flags & REG_QUOTE) &&
                                395         [ +  + ]:             45 :         (flags & (REG_ADVANCED | REG_EXPANDED | REG_NEWLINE)))
 7739 tgl@sss.pgh.pa.us         396                 :              4 :         return REG_INVARG;
 7559 bruce@momjian.us          397   [ +  +  +  + ]:           3623 :     if (!(flags & REG_EXTENDED) && (flags & REG_ADVF))
 7739 tgl@sss.pgh.pa.us         398                 :              1 :         return REG_INVARG;
                                399                 :                : 
                                400                 :                :     /* Initialize locale-dependent support */
 4753                           401                 :           3622 :     pg_set_regex_collation(collation);
                                402                 :                : 
                                403                 :                :     /* initial setup (after which freev() is callable) */
 7739                           404                 :           3610 :     v->re = re;
 5904                           405                 :           3610 :     v->now = string;
 7739                           406                 :           3610 :     v->stop = v->now + len;
                                407                 :           3610 :     v->err = 0;
                                408                 :           3610 :     v->cflags = flags;
                                409                 :           3610 :     v->nsubexp = 0;
                                410                 :           3610 :     v->subs = v->sub10;
                                411                 :           3610 :     v->nsubs = 10;
                                412         [ +  + ]:          39710 :     for (j = 0; j < v->nsubs; j++)
  980                           413                 :          36100 :         v->subs[j] = NULL;
 7739                           414                 :           3610 :     v->nfa = NULL;
                                415                 :           3610 :     v->cm = NULL;
                                416                 :           3610 :     v->nlcolor = COLORLESS;
                                417                 :           3610 :     v->wordchrs = NULL;
                                418                 :           3610 :     v->tree = NULL;
                                419                 :           3610 :     v->treechain = NULL;
                                420                 :           3610 :     v->treefree = NULL;
                                421                 :           3610 :     v->cv = NULL;
                                422                 :           3610 :     v->cv2 = NULL;
                                423                 :           3610 :     v->lacons = NULL;
                                424                 :           3610 :     v->nlacons = 0;
 3103                           425                 :           3610 :     v->spaceused = 0;
 7739                           426                 :           3610 :     re->re_magic = REMAGIC;
 7559 bruce@momjian.us          427                 :           3610 :     re->re_info = 0;         /* bits get set during parse */
 7739 tgl@sss.pgh.pa.us         428                 :           3610 :     re->re_csize = sizeof(chr);
 4753                           429                 :           3610 :     re->re_collation = collation;
 7739                           430                 :           3610 :     re->re_guts = NULL;
                                431                 :           3610 :     re->re_fns = VS(&functions);
                                432                 :                : 
                                433                 :                :     /* more complex setup, malloced things */
                                434                 :           3610 :     re->re_guts = VS(MALLOC(sizeof(struct guts)));
                                435         [ -  + ]:           3610 :     if (re->re_guts == NULL)
 7739 tgl@sss.pgh.pa.us         436                 :UBC           0 :         return freev(v, REG_ESPACE);
 7559 bruce@momjian.us          437                 :CBC        3610 :     g = (struct guts *) re->re_guts;
 7739 tgl@sss.pgh.pa.us         438                 :           3610 :     g->tree = NULL;
                                439                 :           3610 :     initcm(v, &g->cmap);
                                440                 :           3610 :     v->cm = &g->cmap;
                                441                 :           3610 :     g->lacons = NULL;
                                442                 :           3610 :     g->nlacons = 0;
                                443                 :           3610 :     ZAPCNFA(g->search);
 7559 bruce@momjian.us          444                 :           3610 :     v->nfa = newnfa(v, v->cm, (struct nfa *) NULL);
 7739 tgl@sss.pgh.pa.us         445         [ -  + ]:           3610 :     CNOERR();
                                446                 :                :     /* set up a reasonably-sized transient cvec for getcvec usage */
 5904                           447                 :           3610 :     v->cv = newcvec(100, 20);
 7739                           448         [ -  + ]:           3610 :     if (v->cv == NULL)
 7739 tgl@sss.pgh.pa.us         449                 :UBC           0 :         return freev(v, REG_ESPACE);
                                450                 :                : 
                                451                 :                :     /* parsing */
 7559 bruce@momjian.us          452                 :CBC        3610 :     lexstart(v);                /* also handles prefixes */
                                453   [ +  +  +  + ]:           3610 :     if ((v->cflags & REG_NLSTOP) || (v->cflags & REG_NLANCH))
                                454                 :                :     {
                                455                 :                :         /* assign newline a unique color */
 7739 tgl@sss.pgh.pa.us         456                 :            272 :         v->nlcolor = subcolor(v->cm, newline());
                                457                 :            272 :         okcolors(v->nfa, v->cm);
                                458                 :                :     }
                                459         [ +  + ]:           3610 :     CNOERR();
                                460                 :           3603 :     v->tree = parse(v, EOS, PLAIN, v->nfa->init, v->nfa->final);
 7559 bruce@momjian.us          461         [ -  + ]:           3603 :     assert(SEE(EOS));           /* even if error; ISERR() => SEE(EOS) */
 7739 tgl@sss.pgh.pa.us         462         [ +  + ]:           3603 :     CNOERR();
                                463         [ -  + ]:           3491 :     assert(v->tree != NULL);
                                464                 :                : 
                                465                 :                :     /* finish setup of nfa and its subre tree */
                                466                 :           3491 :     specialcolors(v->nfa);
                                467         [ -  + ]:           3491 :     CNOERR();
                                468                 :                : #ifdef REG_DEBUG
                                469                 :                :     if (debug != NULL)
                                470                 :                :     {
                                471                 :                :         fprintf(debug, "\n\n\n========= RAW ==========\n");
                                472                 :                :         dumpnfa(v->nfa, debug);
                                473                 :                :         dumpst(v->tree, debug, 1);
                                474                 :                :     }
                                475                 :                : #endif
  979                           476         [ +  + ]:           3491 :     if (v->cflags & REG_NOSUB)
                                477                 :           2540 :         removecaptures(v, v->tree);
 7739                           478                 :           3491 :     v->ntree = numst(v->tree, 1);
                                479                 :           3491 :     markst(v->tree);
                                480                 :           3491 :     cleanst(v);
                                481                 :                : #ifdef REG_DEBUG
                                482                 :                :     if (debug != NULL)
                                483                 :                :     {
                                484                 :                :         fprintf(debug, "\n\n\n========= TREE FIXED ==========\n");
                                485                 :                :         dumpst(v->tree, debug, 1);
                                486                 :                :     }
                                487                 :                : #endif
                                488                 :                : 
                                489                 :                :     /* build compacted NFAs for tree and lacons */
                                490                 :           3491 :     re->re_info |= nfatree(v, v->tree, debug);
                                491         [ +  + ]:           3491 :     CNOERR();
                                492   [ +  +  -  + ]:           3488 :     assert(v->nlacons == 0 || v->lacons != NULL);
 7559 bruce@momjian.us          493         [ +  + ]:           3531 :     for (i = 1; i < v->nlacons; i++)
                                494                 :                :     {
 3089 tgl@sss.pgh.pa.us         495                 :             43 :         struct subre *lasub = &v->lacons[i];
                                496                 :                : 
                                497                 :                : #ifdef REG_DEBUG
                                498                 :                :         if (debug != NULL)
                                499                 :                :             fprintf(debug, "\n\n\n========= LA%d ==========\n", i);
                                500                 :                : #endif
                                501                 :                : 
                                502                 :                :         /* Prepend .* to pattern if it's a lookbehind LACON */
 1149                           503                 :             43 :         nfanode(v, lasub, !LATYPE_IS_AHEAD(lasub->latype), debug);
                                504                 :                :     }
 7739                           505         [ -  + ]:           3488 :     CNOERR();
 7559 bruce@momjian.us          506         [ +  + ]:           3488 :     if (v->tree->flags & SHORTER)
 7739 tgl@sss.pgh.pa.us         507                 :             70 :         NOTE(REG_USHORTEST);
                                508                 :                : 
                                509                 :                :     /* build compacted NFAs for tree, lacons, fast search */
                                510                 :                : #ifdef REG_DEBUG
                                511                 :                :     if (debug != NULL)
                                512                 :                :         fprintf(debug, "\n\n\n========= SEARCH ==========\n");
                                513                 :                : #endif
                                514                 :                :     /* can sacrifice main NFA now, so use it as work area */
 7559 bruce@momjian.us          515                 :           3488 :     (DISCARD) optimize(v->nfa, debug);
 7739 tgl@sss.pgh.pa.us         516         [ -  + ]:           3488 :     CNOERR();
                                517                 :           3488 :     makesearch(v, v->nfa);
                                518         [ -  + ]:           3488 :     CNOERR();
                                519                 :           3488 :     compact(v->nfa, &g->search);
                                520         [ -  + ]:           3488 :     CNOERR();
                                521                 :                : 
                                522                 :                :     /* looks okay, package it up */
                                523                 :           3488 :     re->re_nsub = v->nsubexp;
 7559 bruce@momjian.us          524                 :           3488 :     v->re = NULL;                /* freev no longer frees re */
 7739 tgl@sss.pgh.pa.us         525                 :           3488 :     g->magic = GUTSMAGIC;
                                526                 :           3488 :     g->cflags = v->cflags;
                                527                 :           3488 :     g->info = re->re_info;
                                528                 :           3488 :     g->nsub = re->re_nsub;
                                529                 :           3488 :     g->tree = v->tree;
                                530                 :           3488 :     v->tree = NULL;
                                531                 :           3488 :     g->ntree = v->ntree;
 7559 bruce@momjian.us          532         [ +  + ]:           3488 :     g->compare = (v->cflags & REG_ICASE) ? casecmp : cmp;
 7739 tgl@sss.pgh.pa.us         533                 :           3488 :     g->lacons = v->lacons;
                                534                 :           3488 :     v->lacons = NULL;
                                535                 :           3488 :     g->nlacons = v->nlacons;
                                536                 :                : 
                                537                 :                : #ifdef REG_DEBUG
                                538                 :                :     if (flags & REG_DUMP)
                                539                 :                :     {
                                540                 :                :         dump(re, stdout);
                                541                 :                :         fflush(stdout);
                                542                 :                :     }
                                543                 :                : #endif
                                544                 :                : 
                                545         [ -  + ]:           3488 :     assert(v->err == 0);
                                546                 :           3488 :     return freev(v, 0);
                                547                 :                : }
                                548                 :                : 
                                549                 :                : /*
                                550                 :                :  * moresubs - enlarge subRE vector
                                551                 :                :  */
                                552                 :                : static void
 2489                           553                 :             12 : moresubs(struct vars *v,
                                554                 :                :          int wanted)            /* want enough room for this one */
                                555                 :                : {
                                556                 :                :     struct subre **p;
                                557                 :                :     size_t      n;
                                558                 :                : 
 7559 bruce@momjian.us          559   [ +  -  -  + ]:             12 :     assert(wanted > 0 && (size_t) wanted >= v->nsubs);
 2489 tgl@sss.pgh.pa.us         560                 :             12 :     n = (size_t) wanted * 3 / 2 + 1;
                                561                 :                : 
 7559 bruce@momjian.us          562         [ +  + ]:             12 :     if (v->subs == v->sub10)
                                563                 :                :     {
  980 tgl@sss.pgh.pa.us         564                 :              6 :         p = (struct subre **) MALLOC(n * sizeof(struct subre *));
 7739                           565         [ +  - ]:              6 :         if (p != NULL)
                                566                 :              6 :             memcpy(VS(p), VS(v->subs),
  980                           567                 :              6 :                    v->nsubs * sizeof(struct subre *));
                                568                 :                :     }
                                569                 :                :     else
                                570                 :              6 :         p = (struct subre **) REALLOC(v->subs, n * sizeof(struct subre *));
 7559 bruce@momjian.us          571         [ -  + ]:             12 :     if (p == NULL)
                                572                 :                :     {
 7739 tgl@sss.pgh.pa.us         573         [ #  # ]:UBC           0 :         ERR(REG_ESPACE);
10141 scrappy@hub.org           574                 :              0 :         return;
                                575                 :                :     }
 7739 tgl@sss.pgh.pa.us         576                 :CBC          12 :     v->subs = p;
                                577         [ +  + ]:            142 :     for (p = &v->subs[v->nsubs]; v->nsubs < n; p++, v->nsubs++)
  980                           578                 :            130 :         *p = NULL;
 7739                           579         [ -  + ]:             12 :     assert(v->nsubs == n);
 7559 bruce@momjian.us          580         [ -  + ]:             12 :     assert((size_t) wanted < v->nsubs);
                                581                 :                : }
                                582                 :                : 
                                583                 :                : /*
                                584                 :                :  * freev - free vars struct's substructures where necessary
                                585                 :                :  *
                                586                 :                :  * Optionally does error-number setting, and always returns error code
                                587                 :                :  * (if any), to make error-handling code terser.
                                588                 :                :  */
                                589                 :                : static int
 2489 tgl@sss.pgh.pa.us         590                 :           3610 : freev(struct vars *v,
                                591                 :                :       int err)
                                592                 :                : {
 7739                           593         [ +  + ]:           3610 :     if (v->re != NULL)
                                594                 :            122 :         rfree(v->re);
                                595         [ +  + ]:           3610 :     if (v->subs != v->sub10)
                                596                 :              6 :         FREE(v->subs);
                                597         [ +  - ]:           3610 :     if (v->nfa != NULL)
                                598                 :           3610 :         freenfa(v->nfa);
                                599         [ +  + ]:           3610 :     if (v->tree != NULL)
                                600                 :              3 :         freesubre(v, v->tree);
                                601         [ +  + ]:           3610 :     if (v->treechain != NULL)
                                602                 :            112 :         cleanst(v);
                                603         [ +  - ]:           3610 :     if (v->cv != NULL)
                                604                 :           3610 :         freecvec(v->cv);
                                605         [ -  + ]:           3610 :     if (v->cv2 != NULL)
 7739 tgl@sss.pgh.pa.us         606                 :UBC           0 :         freecvec(v->cv2);
 7739 tgl@sss.pgh.pa.us         607         [ -  + ]:CBC        3610 :     if (v->lacons != NULL)
 7739 tgl@sss.pgh.pa.us         608                 :UBC           0 :         freelacons(v->lacons, v->nlacons);
 7559 bruce@momjian.us          609         [ +  + ]:CBC        3610 :     ERR(err);                   /* nop if err==0 */
                                610                 :                : 
 7739 tgl@sss.pgh.pa.us         611                 :           3610 :     return v->err;
                                612                 :                : }
                                613                 :                : 
                                614                 :                : /*
                                615                 :                :  * makesearch - turn an NFA into a search NFA (implicit prepend of .*?)
                                616                 :                :  * NFA must have been optimize()d already.
                                617                 :                :  */
                                618                 :                : static void
 2489                           619                 :           3497 : makesearch(struct vars *v,
                                620                 :                :            struct nfa *nfa)
                                621                 :                : {
                                622                 :                :     struct arc *a;
                                623                 :                :     struct arc *b;
 7739                           624                 :           3497 :     struct state *pre = nfa->pre;
                                625                 :                :     struct state *s;
                                626                 :                :     struct state *s2;
                                627                 :                :     struct state *slist;
                                628                 :                : 
                                629                 :                :     /* no loops are needed if it's anchored */
 7559 bruce@momjian.us          630         [ +  + ]:          10355 :     for (a = pre->outs; a != NULL; a = a->outchain)
                                631                 :                :     {
 7739 tgl@sss.pgh.pa.us         632         [ -  + ]:           8279 :         assert(a->type == PLAIN);
                                633   [ +  +  +  + ]:           8279 :         if (a->co != nfa->bos[0] && a->co != nfa->bos[1])
                                634                 :           1421 :             break;
                                635                 :                :     }
 7559 bruce@momjian.us          636         [ +  + ]:           3497 :     if (a != NULL)
                                637                 :                :     {
                                638                 :                :         /* add implicit .* in front */
 7739 tgl@sss.pgh.pa.us         639                 :           1421 :         rainbow(nfa, v->cm, PLAIN, COLORLESS, pre, pre);
                                640                 :                : 
                                641                 :                :         /* and ^* and \A* too -- not always necessary, but harmless */
                                642                 :           1421 :         newarc(nfa, PLAIN, nfa->bos[0], pre, pre);
                                643                 :           1421 :         newarc(nfa, PLAIN, nfa->bos[1], pre, pre);
                                644                 :                : 
                                645                 :                :         /*
                                646                 :                :          * The pattern is still MATCHALL if it was before, but the max match
                                647                 :                :          * length is now infinity.
                                648                 :                :          */
  961                           649         [ +  + ]:           1421 :         if (nfa->flags & MATCHALL)
                                650                 :             65 :             nfa->maxmatchall = DUPINF;
                                651                 :                :     }
                                652                 :                : 
                                653                 :                :     /*
                                654                 :                :      * Now here's the subtle part.  Because many REs have no lookback
                                655                 :                :      * constraints, often knowing when you were in the pre state tells you
                                656                 :                :      * little; it's the next state(s) that are informative.  But some of them
                                657                 :                :      * may have other inarcs, i.e. it may be possible to make actual progress
                                658                 :                :      * and then return to one of them.  We must de-optimize such cases,
                                659                 :                :      * splitting each such state into progress and no-progress states.
                                660                 :                :      */
                                661                 :                : 
                                662                 :                :     /* first, make a list of the states reachable from pre and elsewhere */
 7739                           663                 :           3497 :     slist = NULL;
 7559 bruce@momjian.us          664         [ +  + ]:          17115 :     for (a = pre->outs; a != NULL; a = a->outchain)
                                665                 :                :     {
 7739 tgl@sss.pgh.pa.us         666                 :          13618 :         s = a->to;
                                667         [ +  + ]:          46550 :         for (b = s->ins; b != NULL; b = b->inchain)
                                668                 :                :         {
                                669         [ +  + ]:          36822 :             if (b->from != pre)
                                670                 :           3890 :                 break;
                                671                 :                :         }
                                672                 :                : 
                                673                 :                :         /*
                                674                 :                :          * We want to mark states as being in the list already by having non
                                675                 :                :          * NULL tmp fields, but we can't just store the old slist value in tmp
                                676                 :                :          * because that doesn't work for the first such state.  Instead, the
                                677                 :                :          * first list entry gets its own address in tmp.
                                678                 :                :          */
 5904                           679   [ +  +  +  + ]:          13618 :         if (b != NULL && s->tmp == NULL)
                                680                 :                :         {
 3140                           681         [ +  + ]:           1466 :             s->tmp = (slist != NULL) ? slist : s;
 5904                           682                 :           1466 :             slist = s;
                                683                 :                :         }
                                684                 :                :     }
                                685                 :                : 
                                686                 :                :     /* do the splits */
 7559 bruce@momjian.us          687         [ +  + ]:           4963 :     for (s = slist; s != NULL; s = s2)
                                688                 :                :     {
 7739 tgl@sss.pgh.pa.us         689                 :           1466 :         s2 = newstate(nfa);
 3103                           690         [ -  + ]:           1466 :         NOERR();
                                691                 :           1466 :         copyouts(nfa, s, s2);
                                692         [ -  + ]:           1466 :         NOERR();
 7559 bruce@momjian.us          693         [ +  + ]:         220914 :         for (a = s->ins; a != NULL; a = b)
                                694                 :                :         {
 7739 tgl@sss.pgh.pa.us         695                 :         219448 :             b = a->inchain;
 7559 bruce@momjian.us          696         [ +  + ]:         219448 :             if (a->from != pre)
                                697                 :                :             {
 7739 tgl@sss.pgh.pa.us         698                 :         215558 :                 cparc(nfa, a, a->from, s2);
                                699                 :         215558 :                 freearc(nfa, a);
                                700                 :                :             }
                                701                 :                :         }
 3140                           702         [ +  + ]:           1466 :         s2 = (s->tmp != s) ? s->tmp : NULL;
 7559 bruce@momjian.us          703                 :           1466 :         s->tmp = NULL;           /* clean up while we're at it */
                                704                 :                :     }
                                705                 :                : }
                                706                 :                : 
                                707                 :                : /*
                                708                 :                :  * parse - parse an RE
                                709                 :                :  *
                                710                 :                :  * This is actually just the top level, which parses a bunch of branches
                                711                 :                :  * tied together with '|'.  If there's more than one, they appear in the
                                712                 :                :  * tree as the children of a '|' subre.
                                713                 :                :  */
                                714                 :                : static struct subre *
 2489 tgl@sss.pgh.pa.us         715                 :           6185 : parse(struct vars *v,
                                716                 :                :       int stopper,              /* EOS or ')' */
                                717                 :                :       int type,                 /* LACON (lookaround subRE) or PLAIN */
                                718                 :                :       struct state *init,       /* initial state */
                                719                 :                :       struct state *final)      /* final state */
                                720                 :                : {
                                721                 :                :     struct subre *branches;     /* top level */
                                722                 :                :     struct subre *lastbranch;   /* latest branch */
                                723                 :                : 
 7739                           724   [ +  +  -  + ]:           6185 :     assert(stopper == ')' || stopper == EOS);
                                725                 :                : 
                                726                 :           6185 :     branches = subre(v, '|', LONGER, init, final);
                                727         [ -  + ]:           6185 :     NOERRN();
 1149                           728                 :           6185 :     lastbranch = NULL;
                                729                 :                :     do
                                730                 :                :     {                           /* a branch */
                                731                 :                :         struct subre *branch;
                                732                 :                :         struct state *left;     /* scaffolding for branch */
                                733                 :                :         struct state *right;
                                734                 :                : 
 7739                           735                 :           6494 :         left = newstate(v->nfa);
                                736                 :           6494 :         right = newstate(v->nfa);
                                737         [ -  + ]:           6494 :         NOERRN();
                                738                 :           6494 :         EMPTYARC(init, left);
                                739                 :           6494 :         EMPTYARC(right, final);
                                740         [ -  + ]:           6494 :         NOERRN();
 1149                           741                 :           6494 :         branch = parsebranch(v, stopper, type, left, right, 0);
 7739                           742         [ +  + ]:           6494 :         NOERRN();
 1149                           743         [ +  + ]:           6356 :         if (lastbranch)
                                744                 :            309 :             lastbranch->sibling = branch;
                                745                 :                :         else
                                746                 :           6047 :             branches->child = branch;
                                747                 :           6356 :         branches->flags |= UP(branches->flags | branch->flags);
                                748                 :           6356 :         lastbranch = branch;
 7739                           749   [ +  +  +  - ]:           6356 :     } while (EAT('|'));
                                750   [ +  +  -  + ]:           6047 :     assert(SEE(stopper) || SEE(EOS));
                                751                 :                : 
 7559 bruce@momjian.us          752         [ +  + ]:           6047 :     if (!SEE(stopper))
                                753                 :                :     {
 7739 tgl@sss.pgh.pa.us         754   [ +  -  -  + ]:              8 :         assert(stopper == ')' && SEE(EOS));
                                755         [ -  + ]:              8 :         ERR(REG_EPAREN);
                                756                 :                :     }
                                757                 :                : 
                                758                 :                :     /* optimize out simple cases */
 1149                           759         [ +  + ]:           6047 :     if (lastbranch == branches->child)
                                760                 :                :     {                           /* only one branch */
                                761         [ -  + ]:           5864 :         assert(lastbranch->sibling == NULL);
                                762                 :           5864 :         freesrnode(v, branches);
                                763                 :           5864 :         branches = lastbranch;
                                764                 :                :     }
 7559 bruce@momjian.us          765         [ +  + ]:            183 :     else if (!MESSY(branches->flags))
                                766                 :                :     {                           /* no interesting innards */
 1149 tgl@sss.pgh.pa.us         767                 :            101 :         freesubreandsiblings(v, branches->child);
                                768                 :            101 :         branches->child = NULL;
 7739                           769                 :            101 :         branches->op = '=';
                                770                 :                :     }
                                771                 :                : 
                                772                 :           6047 :     return branches;
                                773                 :                : }
                                774                 :                : 
                                775                 :                : /*
                                776                 :                :  * parsebranch - parse one branch of an RE
                                777                 :                :  *
                                778                 :                :  * This mostly manages concatenation, working closely with parseqatom().
                                779                 :                :  * Concatenated things are bundled up as much as possible, with separate
                                780                 :                :  * '.' nodes introduced only when necessary due to substructure.
                                781                 :                :  */
                                782                 :                : static struct subre *
 2489                           783                 :           8545 : parsebranch(struct vars *v,
                                784                 :                :             int stopper,        /* EOS or ')' */
                                785                 :                :             int type,           /* LACON (lookaround subRE) or PLAIN */
                                786                 :                :             struct state *left, /* leftmost state */
                                787                 :                :             struct state *right,    /* rightmost state */
                                788                 :                :             int partial)        /* is this only part of a branch? */
                                789                 :                : {
                                790                 :                :     struct state *lp;           /* left end of current construct */
                                791                 :                :     int         seencontent;    /* is there anything in this branch yet? */
                                792                 :                :     struct subre *t;
                                793                 :                : 
 7739                           794                 :           8545 :     lp = left;
                                795                 :           8545 :     seencontent = 0;
                                796                 :           8545 :     t = subre(v, '=', 0, left, right);  /* op '=' is tentative */
                                797         [ -  + ]:           8545 :     NOERRN();
 7559 bruce@momjian.us          798   [ +  +  +  +  :          54887 :     while (!SEE('|') && !SEE(stopper) && !SEE(EOS))
                                              +  + ]
                                799                 :                :     {
                                800         [ +  + ]:          46492 :         if (seencontent)
                                801                 :                :         {                       /* implicit concat operator */
 7739 tgl@sss.pgh.pa.us         802                 :          38047 :             lp = newstate(v->nfa);
                                803         [ -  + ]:          38047 :             NOERRN();
                                804                 :          38047 :             moveins(v->nfa, right, lp);
                                805                 :                :         }
                                806                 :          46492 :         seencontent = 1;
                                807                 :                : 
                                808                 :                :         /* NB, recursion in parseqatom() may swallow rest of branch */
  981                           809                 :          46492 :         t = parseqatom(v, stopper, type, lp, right, t);
 4064                           810         [ +  + ]:          46492 :         NOERRN();
                                811                 :                :     }
                                812                 :                : 
 7559 bruce@momjian.us          813         [ +  + ]:           8395 :     if (!seencontent)
                                814                 :                :     {                           /* empty branch */
 7739 tgl@sss.pgh.pa.us         815         [ +  - ]:            100 :         if (!partial)
                                816                 :            100 :             NOTE(REG_UUNSPEC);
                                817         [ -  + ]:            100 :         assert(lp == left);
                                818                 :            100 :         EMPTYARC(left, right);
                                819                 :                :     }
                                820                 :                : 
                                821                 :           8395 :     return t;
                                822                 :                : }
                                823                 :                : 
                                824                 :                : /*
                                825                 :                :  * parseqatom - parse one quantified atom or constraint of an RE
                                826                 :                :  *
                                827                 :                :  * The bookkeeping near the end cooperates very closely with parsebranch();
                                828                 :                :  * in particular, it contains a recursion that can involve parsing the rest
                                829                 :                :  * of the branch, making this function's name somewhat inaccurate.
                                830                 :                :  *
                                831                 :                :  * Usually, the return value is just "top", but in some cases where we
                                832                 :                :  * have parsed the rest of the branch, we may deem "top" redundant and
                                833                 :                :  * free it, returning some child subre instead.
                                834                 :                :  */
                                835                 :                : static struct subre *
 2489                           836                 :          46492 : parseqatom(struct vars *v,
                                837                 :                :            int stopper,         /* EOS or ')' */
                                838                 :                :            int type,            /* LACON (lookaround subRE) or PLAIN */
                                839                 :                :            struct state *lp,    /* left state to hang it on */
                                840                 :                :            struct state *rp,    /* right state to hang it on */
                                841                 :                :            struct subre *top)   /* subtree top */
                                842                 :                : {
                                843                 :                :     struct state *s;            /* temporaries for new states */
                                844                 :                :     struct state *s2;
                                845                 :                : 
                                846                 :                : #define  ARCV(t, val)    newarc(v->nfa, t, val, lp, rp)
                                847                 :                :     int         m,
                                848                 :                :                 n;
                                849                 :                :     struct subre *atom;         /* atom's subtree */
                                850                 :                :     struct subre *t;
                                851                 :                :     int         cap;            /* capturing parens? */
                                852                 :                :     int         latype;         /* lookaround constraint type */
                                853                 :                :     int         subno;          /* capturing-parens or backref number */
                                854                 :                :     int         atomtype;
                                855                 :                :     int         qprefer;        /* quantifier short/long preference */
                                856                 :                :     int         f;
                                857                 :                :     struct subre **atomp;       /* where the pointer to atom is */
                                858                 :                : 
                                859                 :                :     /* initial bookkeeping */
 7739                           860                 :          46492 :     atom = NULL;
 7559 bruce@momjian.us          861         [ -  + ]:          46492 :     assert(lp->nouts == 0);      /* must string new code */
                                862         [ -  + ]:          46492 :     assert(rp->nins == 0);       /* between lp and rp */
                                863                 :          46492 :     subno = 0;                  /* just to shut lint up */
                                864                 :                : 
                                865                 :                :     /* an atom or constraint... */
 7739 tgl@sss.pgh.pa.us         866                 :          46492 :     atomtype = v->nexttype;
 7559 bruce@momjian.us          867   [ +  +  +  +  :          46492 :     switch (atomtype)
                                     +  +  +  +  +  
                                     +  -  +  +  +  
                                        +  +  +  +  
                                                 + ]
                                868                 :                :     {
                                869                 :                :             /* first, constraints, which end by returning */
                                870                 :           2285 :         case '^':
                                871                 :           2285 :             ARCV('^', 1);
                                872         [ +  + ]:           2285 :             if (v->cflags & REG_NLANCH)
                                873                 :            193 :                 ARCV(BEHIND, v->nlcolor);
                                874                 :           2285 :             NEXT();
  981 tgl@sss.pgh.pa.us         875                 :           2285 :             return top;
                                876                 :                :             break;
 7559 bruce@momjian.us          877                 :           2007 :         case '$':
                                878                 :           2007 :             ARCV('$', 1);
                                879         [ +  + ]:           2007 :             if (v->cflags & REG_NLANCH)
                                880                 :            181 :                 ARCV(AHEAD, v->nlcolor);
                                881                 :           2007 :             NEXT();
  981 tgl@sss.pgh.pa.us         882                 :           2007 :             return top;
                                883                 :                :             break;
 7559 bruce@momjian.us          884                 :             13 :         case SBEGIN:
                                885                 :             13 :             ARCV('^', 1);       /* BOL */
                                886                 :             13 :             ARCV('^', 0);       /* or BOS */
                                887                 :             13 :             NEXT();
  981 tgl@sss.pgh.pa.us         888                 :             13 :             return top;
                                889                 :                :             break;
 7559 bruce@momjian.us          890                 :              5 :         case SEND:
                                891                 :              5 :             ARCV('$', 1);       /* EOL */
                                892                 :              5 :             ARCV('$', 0);       /* or EOS */
                                893                 :              5 :             NEXT();
  981 tgl@sss.pgh.pa.us         894                 :              5 :             return top;
                                895                 :                :             break;
 7559 bruce@momjian.us          896                 :             29 :         case '<':
 1144 tgl@sss.pgh.pa.us         897                 :             29 :             wordchrs(v);
 7559 bruce@momjian.us          898                 :             29 :             s = newstate(v->nfa);
  981 tgl@sss.pgh.pa.us         899         [ -  + ]:             29 :             NOERRN();
 7559 bruce@momjian.us          900                 :             29 :             nonword(v, BEHIND, lp, s);
                                901                 :             29 :             word(v, AHEAD, s, rp);
 1144 tgl@sss.pgh.pa.us         902                 :             29 :             NEXT();
  981                           903                 :             29 :             return top;
                                904                 :                :             break;
 7559 bruce@momjian.us          905                 :             26 :         case '>':
 1144 tgl@sss.pgh.pa.us         906                 :             26 :             wordchrs(v);
 7559 bruce@momjian.us          907                 :             26 :             s = newstate(v->nfa);
  981 tgl@sss.pgh.pa.us         908         [ -  + ]:             26 :             NOERRN();
 7559 bruce@momjian.us          909                 :             26 :             word(v, BEHIND, lp, s);
                                910                 :             26 :             nonword(v, AHEAD, s, rp);
 1144 tgl@sss.pgh.pa.us         911                 :             26 :             NEXT();
  981                           912                 :             26 :             return top;
                                913                 :                :             break;
 7559 bruce@momjian.us          914                 :              9 :         case WBDRY:
 1144 tgl@sss.pgh.pa.us         915                 :              9 :             wordchrs(v);
 7559 bruce@momjian.us          916                 :              9 :             s = newstate(v->nfa);
  981 tgl@sss.pgh.pa.us         917         [ -  + ]:              9 :             NOERRN();
 7559 bruce@momjian.us          918                 :              9 :             nonword(v, BEHIND, lp, s);
                                919                 :              9 :             word(v, AHEAD, s, rp);
                                920                 :              9 :             s = newstate(v->nfa);
  981 tgl@sss.pgh.pa.us         921         [ -  + ]:              9 :             NOERRN();
 7559 bruce@momjian.us          922                 :              9 :             word(v, BEHIND, lp, s);
                                923                 :              9 :             nonword(v, AHEAD, s, rp);
 1144 tgl@sss.pgh.pa.us         924                 :              9 :             NEXT();
  981                           925                 :              9 :             return top;
                                926                 :                :             break;
 7559 bruce@momjian.us          927                 :             19 :         case NWBDRY:
 1144 tgl@sss.pgh.pa.us         928                 :             19 :             wordchrs(v);
 7559 bruce@momjian.us          929                 :             19 :             s = newstate(v->nfa);
  981 tgl@sss.pgh.pa.us         930         [ -  + ]:             19 :             NOERRN();
 7559 bruce@momjian.us          931                 :             19 :             word(v, BEHIND, lp, s);
                                932                 :             19 :             word(v, AHEAD, s, rp);
                                933                 :             19 :             s = newstate(v->nfa);
  981 tgl@sss.pgh.pa.us         934         [ -  + ]:             19 :             NOERRN();
 7559 bruce@momjian.us          935                 :             19 :             nonword(v, BEHIND, lp, s);
                                936                 :             19 :             nonword(v, AHEAD, s, rp);
 1144 tgl@sss.pgh.pa.us         937                 :             19 :             NEXT();
  981                           938                 :             19 :             return top;
                                939                 :                :             break;
 3089                           940                 :            134 :         case LACON:             /* lookaround constraint */
                                941                 :            134 :             latype = v->nextvalue;
 7559 bruce@momjian.us          942                 :            134 :             NEXT();
                                943                 :            134 :             s = newstate(v->nfa);
                                944                 :            134 :             s2 = newstate(v->nfa);
  981 tgl@sss.pgh.pa.us         945         [ -  + ]:            134 :             NOERRN();
 7559 bruce@momjian.us          946                 :            134 :             t = parse(v, ')', LACON, s, s2);
                                947                 :            134 :             freesubre(v, t);    /* internal structure irrelevant */
  981 tgl@sss.pgh.pa.us         948         [ +  + ]:            134 :             NOERRN();
 3089                           949         [ -  + ]:            127 :             assert(SEE(')'));
                                950                 :            127 :             NEXT();
                                951                 :            127 :             processlacon(v, s, s2, latype, lp, rp);
  981                           952                 :            127 :             return top;
                                953                 :                :             break;
                                954                 :                :             /* then errors, to get them out of the way */
 7559 bruce@momjian.us          955                 :             34 :         case '*':
                                956                 :                :         case '+':
                                957                 :                :         case '?':
                                958                 :                :         case '{':
                                959         [ -  + ]:             34 :             ERR(REG_BADRPT);
  981 tgl@sss.pgh.pa.us         960                 :             34 :             return top;
                                961                 :                :             break;
 7559 bruce@momjian.us          962                 :UBC           0 :         default:
                                963         [ #  # ]:              0 :             ERR(REG_ASSERT);
  981 tgl@sss.pgh.pa.us         964                 :              0 :             return top;
                                965                 :                :             break;
                                966                 :                :             /* then plain characters, and minor variants on that theme */
 7559 bruce@momjian.us          967                 :CBC           3 :         case ')':               /* unbalanced paren */
                                968         [ +  + ]:              3 :             if ((v->cflags & REG_ADVANCED) != REG_EXTENDED)
                                969                 :                :             {
                                970         [ -  + ]:              2 :                 ERR(REG_EPAREN);
  981 tgl@sss.pgh.pa.us         971                 :              2 :                 return top;
                                972                 :                :             }
                                973                 :                :             /* legal in EREs due to specification botch */
 7559 bruce@momjian.us          974                 :              1 :             NOTE(REG_UPBOTCH);
                                975                 :                :             /* fall through into case PLAIN */
                                976                 :                :             /* FALLTHROUGH */
                                977                 :          37051 :         case PLAIN:
                                978                 :          37051 :             onechr(v, v->nextvalue, lp, rp);
                                979                 :          37051 :             okcolors(v->nfa, v->cm);
  981 tgl@sss.pgh.pa.us         980         [ -  + ]:          37051 :             NOERRN();
 7559 bruce@momjian.us          981                 :          37051 :             NEXT();
                                982                 :          37051 :             break;
                                983                 :            609 :         case '[':
                                984         [ +  + ]:            609 :             if (v->nextvalue == 1)
                                985                 :            495 :                 bracket(v, lp, rp);
                                986                 :                :             else
                                987                 :            114 :                 cbracket(v, lp, rp);
                                988   [ +  +  -  + ]:            609 :             assert(SEE(']') || ISERR());
                                989                 :            609 :             NEXT();
                                990                 :            609 :             break;
 1144 tgl@sss.pgh.pa.us         991                 :            160 :         case CCLASSS:
                                992                 :            160 :             charclass(v, (enum char_classes) v->nextvalue, lp, rp);
                                993                 :            160 :             okcolors(v->nfa, v->cm);
                                994                 :            160 :             NEXT();
                                995                 :            160 :             break;
                                996                 :             23 :         case CCLASSC:
                                997                 :             23 :             charclasscomplement(v, (enum char_classes) v->nextvalue, lp, rp);
                                998                 :                :             /* charclasscomplement() did okcolors() internally */
                                999                 :             23 :             NEXT();
                               1000                 :             23 :             break;
 7559 bruce@momjian.us         1001                 :           1525 :         case '.':
                               1002                 :           1525 :             rainbow(v->nfa, v->cm, PLAIN,
                               1003         [ +  + ]:           1525 :                     (v->cflags & REG_NLSTOP) ? v->nlcolor : COLORLESS,
                               1004                 :                :                     lp, rp);
                               1005                 :           1525 :             NEXT();
                               1006                 :           1525 :             break;
                               1007                 :                :             /* and finally the ugly stuff */
                               1008                 :           2448 :         case '(':               /* value flags as capturing or non */
                               1009         [ +  + ]:           2448 :             cap = (type == LACON) ? 0 : v->nextvalue;
                               1010         [ +  + ]:           2448 :             if (cap)
                               1011                 :                :             {
                               1012                 :           2336 :                 v->nsubexp++;
                               1013                 :           2336 :                 subno = v->nsubexp;
                               1014         [ +  + ]:           2336 :                 if ((size_t) subno >= v->nsubs)
                               1015                 :             12 :                     moresubs(v, subno);
                               1016                 :                :             }
                               1017                 :                :             else
 2489 tgl@sss.pgh.pa.us        1018                 :            112 :                 atomtype = PLAIN;   /* something that's not '(' */
 7559 bruce@momjian.us         1019                 :           2448 :             NEXT();
                               1020                 :                : 
                               1021                 :                :             /*
                               1022                 :                :              * Make separate endpoint states to keep this sub-NFA distinct
                               1023                 :                :              * from what surrounds it.  We need to be sure that when we
                               1024                 :                :              * duplicate the sub-NFA for a backref, we get the right
                               1025                 :                :              * states/arcs and no others.  In particular, letting a backref
                               1026                 :                :              * duplicate the sub-NFA from lp to rp would be quite wrong,
                               1027                 :                :              * because we may add quantification superstructure around this
                               1028                 :                :              * atom below.  (Perhaps we could skip the extra states for
                               1029                 :                :              * non-capturing parens, but it seems not worth the trouble.)
                               1030                 :                :              */
                               1031                 :           2448 :             s = newstate(v->nfa);
                               1032                 :           2448 :             s2 = newstate(v->nfa);
  981 tgl@sss.pgh.pa.us        1033         [ -  + ]:           2448 :             NOERRN();
                               1034                 :                :             /* We may not need these arcs, but keep things connected for now */
 7559 bruce@momjian.us         1035                 :           2448 :             EMPTYARC(lp, s);
                               1036                 :           2448 :             EMPTYARC(s2, rp);
  981 tgl@sss.pgh.pa.us        1037         [ -  + ]:           2448 :             NOERRN();
 3081                          1038                 :           2448 :             atom = parse(v, ')', type, s, s2);
 7559 bruce@momjian.us         1039   [ +  +  -  + ]:           2448 :             assert(SEE(')') || ISERR());
                               1040                 :           2448 :             NEXT();
  981 tgl@sss.pgh.pa.us        1041         [ +  + ]:           2448 :             NOERRN();
 7559 bruce@momjian.us         1042         [ +  + ]:           2421 :             if (cap)
                               1043                 :                :             {
 1149 tgl@sss.pgh.pa.us        1044         [ +  + ]:           2313 :                 if (atom->capno == 0)
                               1045                 :                :                 {
                               1046                 :                :                     /* normal case: just mark the atom as capturing */
                               1047                 :           2285 :                     atom->flags |= CAP;
                               1048                 :           2285 :                     atom->capno = subno;
                               1049                 :                :                 }
                               1050                 :                :                 else
                               1051                 :                :                 {
                               1052                 :                :                     /* generate no-op wrapper node to handle "((x))" */
  981                          1053                 :             28 :                     t = subre(v, '(', atom->flags | CAP, s, s2);
                               1054         [ -  + ]:             28 :                     NOERRN();
 1149                          1055                 :             28 :                     t->capno = subno;
                               1056                 :             28 :                     t->child = atom;
                               1057                 :             28 :                     atom = t;
                               1058                 :                :                 }
  980                          1059         [ -  + ]:           2313 :                 assert(v->subs[subno] == NULL);
                               1060                 :           2313 :                 v->subs[subno] = atom;
                               1061                 :                :             }
                               1062                 :                :             /* postpone everything else pending possible {0} */
 7559 bruce@momjian.us         1063                 :           2421 :             break;
                               1064                 :            113 :         case BACKREF:           /* the Feature From The Black Lagoon */
                               1065   [ +  +  -  + ]:            113 :             INSIST(type != LACON, REG_ESUBREG);
  979 tgl@sss.pgh.pa.us        1066                 :            113 :             subno = v->nextvalue;
                               1067         [ -  + ]:            113 :             assert(subno > 0);
                               1068   [ -  +  -  - ]:            113 :             INSIST(subno < v->nsubs, REG_ESUBREG);
                               1069         [ +  + ]:            113 :             NOERRN();
                               1070   [ +  +  -  + ]:            106 :             INSIST(v->subs[subno] != NULL, REG_ESUBREG);
  981                          1071         [ +  + ]:            106 :             NOERRN();
 7559 bruce@momjian.us         1072                 :            101 :             atom = subre(v, 'b', BACKR, lp, rp);
  981 tgl@sss.pgh.pa.us        1073         [ -  + ]:            101 :             NOERRN();
 1149                          1074                 :            101 :             atom->backno = subno;
  979                          1075                 :            101 :             v->subs[subno]->flags |= BRUSE;
 7559 bruce@momjian.us         1076                 :            101 :             EMPTYARC(lp, rp);   /* temporarily, so there's something */
                               1077                 :            101 :             NEXT();
                               1078                 :            101 :             break;
                               1079                 :                :     }
                               1080                 :                : 
                               1081                 :                :     /* ...and an atom may be followed by a quantifier */
                               1082   [ +  +  +  +  :          41890 :     switch (v->nexttype)
                                                 + ]
                               1083                 :                :     {
                               1084                 :          10551 :         case '*':
                               1085                 :          10551 :             m = 0;
 3133 tgl@sss.pgh.pa.us        1086                 :          10551 :             n = DUPINF;
 7559 bruce@momjian.us         1087         [ +  + ]:          10551 :             qprefer = (v->nextvalue) ? LONGER : SHORTER;
                               1088                 :          10551 :             NEXT();
                               1089                 :          10551 :             break;
                               1090                 :            438 :         case '+':
                               1091                 :            438 :             m = 1;
 3133 tgl@sss.pgh.pa.us        1092                 :            438 :             n = DUPINF;
 7559 bruce@momjian.us         1093         [ +  + ]:            438 :             qprefer = (v->nextvalue) ? LONGER : SHORTER;
                               1094                 :            438 :             NEXT();
                               1095                 :            438 :             break;
                               1096                 :             57 :         case '?':
                               1097                 :             57 :             m = 0;
                               1098                 :             57 :             n = 1;
                               1099         [ +  + ]:             57 :             qprefer = (v->nextvalue) ? LONGER : SHORTER;
                               1100                 :             57 :             NEXT();
                               1101                 :             57 :             break;
                               1102                 :            258 :         case '{':
                               1103                 :            258 :             NEXT();
                               1104                 :            258 :             m = scannum(v);
                               1105   [ +  +  +  - ]:            258 :             if (EAT(','))
                               1106                 :                :             {
                               1107         [ +  + ]:            121 :                 if (SEE(DIGIT))
                               1108                 :            114 :                     n = scannum(v);
                               1109                 :                :                 else
 3133 tgl@sss.pgh.pa.us        1110                 :              7 :                     n = DUPINF;
 7559 bruce@momjian.us         1111         [ +  + ]:            121 :                 if (m > n)
                               1112                 :                :                 {
                               1113         [ -  + ]:              4 :                     ERR(REG_BADBR);
  981 tgl@sss.pgh.pa.us        1114                 :              4 :                     return top;
                               1115                 :                :                 }
                               1116                 :                :                 /* {m,n} exercises preference, even if it's {m,m} */
 7559 bruce@momjian.us         1117         [ +  + ]:            117 :                 qprefer = (v->nextvalue) ? LONGER : SHORTER;
                               1118                 :                :             }
                               1119                 :                :             else
                               1120                 :                :             {
                               1121                 :            137 :                 n = m;
                               1122                 :                :                 /* {m} passes operand's preference through */
                               1123                 :            137 :                 qprefer = 0;
                               1124                 :                :             }
                               1125         [ +  + ]:            254 :             if (!SEE('}'))
                               1126                 :                :             {                   /* catches errors too */
 7739 tgl@sss.pgh.pa.us        1127         [ +  + ]:              7 :                 ERR(REG_BADBR);
  981                          1128                 :              7 :                 return top;
                               1129                 :                :             }
 7559 bruce@momjian.us         1130                 :            247 :             NEXT();
                               1131                 :            247 :             break;
                               1132                 :          30586 :         default:                /* no quantifier */
                               1133                 :          30586 :             m = n = 1;
 7739 tgl@sss.pgh.pa.us        1134                 :          30586 :             qprefer = 0;
 7559 bruce@momjian.us         1135                 :          30586 :             break;
                               1136                 :                :     }
                               1137                 :                : 
                               1138                 :                :     /* annoying special case:  {0} or {0,0} cancels everything */
                               1139   [ +  +  +  + ]:          41879 :     if (m == 0 && n == 0)
                               1140                 :                :     {
                               1141                 :                :         /*
                               1142                 :                :          * If we had capturing subexpression(s) within the atom, we don't want
                               1143                 :                :          * to destroy them, because it's legal (if useless) to back-ref them
                               1144                 :                :          * later.  Hence, just unlink the atom from lp/rp and then ignore it.
                               1145                 :                :          */
  964 tgl@sss.pgh.pa.us        1146   [ +  +  +  - ]:             20 :         if (atom != NULL && (atom->flags & CAP))
                               1147                 :                :         {
                               1148                 :             18 :             delsub(v->nfa, lp, atom->begin);
                               1149                 :             18 :             delsub(v->nfa, atom->end, rp);
                               1150                 :                :         }
                               1151                 :                :         else
                               1152                 :                :         {
                               1153                 :                :             /* Otherwise, we can clean up any subre infrastructure we made */
                               1154         [ -  + ]:              2 :             if (atom != NULL)
  964 tgl@sss.pgh.pa.us        1155                 :UBC           0 :                 freesubre(v, atom);
  964 tgl@sss.pgh.pa.us        1156                 :CBC           2 :             delsub(v->nfa, lp, rp);
                               1157                 :                :         }
 7739                          1158                 :             20 :         EMPTYARC(lp, rp);
  981                          1159                 :             20 :         return top;
                               1160                 :                :     }
                               1161                 :                : 
                               1162                 :                :     /* if not a messy case, avoid hard part */
 7739                          1163         [ -  + ]:          41859 :     assert(!MESSY(top->flags));
                               1164         [ +  + ]:          41859 :     f = top->flags | qprefer | ((atom != NULL) ? atom->flags : 0);
 7559 bruce@momjian.us         1165   [ +  +  +  +  :          41859 :     if (atomtype != '(' && atomtype != BACKREF && !MESSY(UP(f)))
                                              +  + ]
                               1166                 :                :     {
 7739 tgl@sss.pgh.pa.us        1167   [ +  +  +  + ]:          39447 :         if (!(m == 1 && n == 1))
                               1168                 :          10940 :             repeat(v, lp, rp, m, n);
                               1169         [ +  + ]:          39447 :         if (atom != NULL)
                               1170                 :             90 :             freesubre(v, atom);
                               1171                 :          39447 :         top->flags = f;
  981                          1172                 :          39447 :         return top;
                               1173                 :                :     }
                               1174                 :                : 
                               1175                 :                :     /*
                               1176                 :                :      * hard part:  something messy
                               1177                 :                :      *
                               1178                 :                :      * That is, capturing parens, back reference, short/long clash, or an atom
                               1179                 :                :      * with substructure containing one of those.
                               1180                 :                :      */
                               1181                 :                : 
                               1182                 :                :     /* now we'll need a subre for the contents even if they're boring */
 7559 bruce@momjian.us         1183         [ +  + ]:           2412 :     if (atom == NULL)
                               1184                 :                :     {
 7739 tgl@sss.pgh.pa.us        1185                 :              1 :         atom = subre(v, '=', 0, lp, rp);
  981                          1186         [ -  + ]:              1 :         NOERRN();
                               1187                 :                :     }
                               1188                 :                : 
                               1189                 :                :     /*
                               1190                 :                :      * For what follows, we need the atom to have its own begin/end states
                               1191                 :                :      * that are distinct from lp/rp, so that we can wrap iteration structure
                               1192                 :                :      * around it.  The parenthesized-atom case above already made suitable
                               1193                 :                :      * states (and we don't want to modify a capturing subre, since it's
                               1194                 :                :      * already recorded in v->subs[]).  Otherwise, we need more states.
                               1195                 :                :      */
  980                          1196   [ +  +  -  + ]:           2412 :     if (atom->begin == lp || atom->end == rp)
                               1197                 :                :     {
                               1198                 :            102 :         s = newstate(v->nfa);
                               1199                 :            102 :         s2 = newstate(v->nfa);
                               1200         [ -  + ]:            102 :         NOERRN();
                               1201                 :            102 :         moveouts(v->nfa, lp, s);
                               1202                 :            102 :         moveins(v->nfa, rp, s2);
                               1203                 :            102 :         atom->begin = s;
                               1204                 :            102 :         atom->end = s2;
                               1205                 :                :     }
                               1206                 :                :     else
                               1207                 :                :     {
                               1208                 :                :         /* The atom's OK, but we must temporarily disconnect it from lp/rp */
                               1209                 :                :         /* (this removes the EMPTY arcs we made above) */
                               1210                 :           2310 :         delsub(v->nfa, lp, atom->begin);
                               1211                 :           2310 :         delsub(v->nfa, atom->end, rp);
                               1212                 :                :     }
                               1213                 :                : 
                               1214                 :                :     /*----------
                               1215                 :                :      * Prepare a general-purpose state skeleton.
                               1216                 :                :      *
                               1217                 :                :      * In the no-backrefs case, we want this:
                               1218                 :                :      *
                               1219                 :                :      * [lp] ---> [s] ---prefix---> ---atom---> ---rest---> [rp]
                               1220                 :                :      *
                               1221                 :                :      * where prefix is some repetitions of atom, and "rest" is the remainder
                               1222                 :                :      * of the branch.  In the general case we need:
                               1223                 :                :      *
                               1224                 :                :      * [lp] ---> [s] ---iterator---> [s2] ---rest---> [rp]
                               1225                 :                :      *
                               1226                 :                :      * where the iterator wraps around the atom.
                               1227                 :                :      *
                               1228                 :                :      * We make the s state here for both cases; s2 is made below if needed
                               1229                 :                :      *----------
                               1230                 :                :      */
 4433                          1231                 :           2412 :     s = newstate(v->nfa);        /* set up starting state */
  981                          1232         [ -  + ]:           2412 :     NOERRN();
 7739                          1233                 :           2412 :     EMPTYARC(lp, s);
  981                          1234         [ -  + ]:           2412 :     NOERRN();
                               1235                 :                : 
                               1236                 :                :     /* break remaining subRE into x{...} and what follows */
 7739                          1237         [ +  + ]:           2412 :     t = subre(v, '.', COMBINE(qprefer, atom->flags), lp, rp);
  981                          1238         [ -  + ]:           2412 :     NOERRN();
 1149                          1239                 :           2412 :     t->child = atom;
                               1240                 :           2412 :     atomp = &t->child;
                               1241                 :                : 
                               1242                 :                :     /*
                               1243                 :                :      * Here we should recurse to fill t->child->sibling ... but we must
                               1244                 :                :      * postpone that to the end.  One reason is that t->child may be replaced
                               1245                 :                :      * below, and we don't want to worry about its sibling link.
                               1246                 :                :      */
                               1247                 :                : 
                               1248                 :                :     /*
                               1249                 :                :      * Convert top node to a concatenation of the prefix (top->child, covering
                               1250                 :                :      * whatever we parsed previously) and remaining (t).  Note that the prefix
                               1251                 :                :      * could be empty, in which case this concatenation node is unnecessary.
                               1252                 :                :      * To keep things simple, we operate in a general way for now, and get rid
                               1253                 :                :      * of unnecessary subres below.
                               1254                 :                :      */
                               1255   [ +  -  -  + ]:           2412 :     assert(top->op == '=' && top->child == NULL);
                               1256                 :           2412 :     top->child = subre(v, '=', top->flags, top->begin, lp);
  981                          1257         [ -  + ]:           2412 :     NOERRN();
 7739                          1258                 :           2412 :     top->op = '.';
 1149                          1259                 :           2412 :     top->child->sibling = t;
                               1260                 :                :     /* top->flags will get updated later */
                               1261                 :                : 
                               1262                 :                :     /* if it's a backref, now is the time to replicate the subNFA */
 7559 bruce@momjian.us         1263         [ +  + ]:           2412 :     if (atomtype == BACKREF)
                               1264                 :                :     {
 2489 tgl@sss.pgh.pa.us        1265         [ -  + ]:            101 :         assert(atom->begin->nouts == 1);  /* just the EMPTY */
 7739                          1266                 :            101 :         delsub(v->nfa, atom->begin, atom->end);
  980                          1267         [ -  + ]:            101 :         assert(v->subs[subno] != NULL);
                               1268                 :                : 
                               1269                 :                :         /*
                               1270                 :                :          * And here's why the recursion got postponed: it must wait until the
                               1271                 :                :          * skeleton is filled in, because it may hit a backref that wants to
                               1272                 :                :          * copy the filled-in skeleton.
                               1273                 :                :          */
                               1274                 :            101 :         dupnfa(v->nfa, v->subs[subno]->begin, v->subs[subno]->end,
                               1275                 :                :                atom->begin, atom->end);
  981                          1276         [ -  + ]:            101 :         NOERRN();
                               1277                 :                : 
                               1278                 :                :         /* The backref node's NFA should not enforce any constraints */
 1139                          1279                 :            101 :         removeconstraints(v->nfa, atom->begin, atom->end);
  981                          1280         [ -  + ]:            101 :         NOERRN();
                               1281                 :                :     }
                               1282                 :                : 
                               1283                 :                :     /*
                               1284                 :                :      * It's quantifier time.  If the atom is just a backref, we'll let it deal
                               1285                 :                :      * with quantifiers internally.
                               1286                 :                :      */
 7559 bruce@momjian.us         1287         [ +  + ]:           2412 :     if (atomtype == BACKREF)
                               1288                 :                :     {
                               1289                 :                :         /* special case:  backrefs have internal quantifiers */
 2489 tgl@sss.pgh.pa.us        1290                 :            101 :         EMPTYARC(s, atom->begin);    /* empty prefix */
                               1291                 :                :         /* just stuff everything into atom */
 7739                          1292                 :            101 :         repeat(v, atom->begin, atom->end, m, n);
 7559 bruce@momjian.us         1293                 :            101 :         atom->min = (short) m;
                               1294                 :            101 :         atom->max = (short) n;
 7739 tgl@sss.pgh.pa.us        1295         [ +  + ]:            101 :         atom->flags |= COMBINE(qprefer, atom->flags);
                               1296                 :                :         /* rest of branch can be strung starting from atom->end */
 4433                          1297                 :            101 :         s2 = atom->end;
                               1298                 :                :     }
 1799                          1299   [ +  +  +  +  :           2311 :     else if (m == 1 && n == 1 &&
                                              +  + ]
                               1300                 :             53 :              (qprefer == 0 ||
                               1301         [ +  + ]:             53 :               (atom->flags & (LONGER | SHORTER | MIXED)) == 0 ||
                               1302         [ +  + ]:             46 :               qprefer == (atom->flags & (LONGER | SHORTER | MIXED))))
                               1303                 :                :     {
                               1304                 :                :         /* no/vacuous quantifier:  done */
 2489                          1305                 :           2089 :         EMPTYARC(s, atom->begin);    /* empty prefix */
                               1306                 :                :         /* rest of branch can be strung starting from atom->end */
 4433                          1307                 :           2089 :         s2 = atom->end;
                               1308                 :                :     }
 1139                          1309         [ +  + ]:            222 :     else if (!(atom->flags & (CAP | BACKR)))
                               1310                 :                :     {
                               1311                 :                :         /*
                               1312                 :                :          * If there's no captures nor backrefs in the atom being repeated, we
                               1313                 :                :          * don't really care where the submatches of the iteration are, so we
                               1314                 :                :          * don't need an iteration node.  Make a plain DFA node instead.
                               1315                 :                :          */
                               1316                 :              8 :         EMPTYARC(s, atom->begin);    /* empty prefix */
                               1317                 :              8 :         repeat(v, atom->begin, atom->end, m, n);
                               1318         [ +  - ]:              8 :         f = COMBINE(qprefer, atom->flags);
                               1319                 :              8 :         t = subre(v, '=', f, atom->begin, atom->end);
  981                          1320         [ -  + ]:              8 :         NOERRN();
 1139                          1321                 :              8 :         freesubre(v, atom);
                               1322                 :              8 :         *atomp = t;
                               1323                 :                :         /* rest of branch can be strung starting from t->end */
                               1324                 :              8 :         s2 = t->end;
                               1325                 :                :     }
 4433                          1326   [ +  +  +  + ]:            214 :     else if (m > 0 && !(atom->flags & BACKR))
                               1327                 :                :     {
                               1328                 :                :         /*
                               1329                 :                :          * If there's no backrefs involved, we can turn x{m,n} into
                               1330                 :                :          * x{m-1,n-1}x, with capturing parens in only the second x.  This is
                               1331                 :                :          * valid because we only care about capturing matches from the final
                               1332                 :                :          * iteration of the quantifier.  It's a win because we can implement
                               1333                 :                :          * the backref-free left side as a plain DFA node, since we don't
                               1334                 :                :          * really care where its submatches are.
                               1335                 :                :          */
 7739                          1336                 :            134 :         dupnfa(v->nfa, atom->begin, atom->end, s, atom->begin);
 3133                          1337   [ +  -  +  -  :            134 :         assert(m >= 1 && m != DUPINF && n >= 1);
                                              -  + ]
                               1338         [ +  + ]:            134 :         repeat(v, s, atom->begin, m - 1, (n == DUPINF) ? n : n - 1);
 7739                          1339         [ +  + ]:            134 :         f = COMBINE(qprefer, atom->flags);
 2489                          1340                 :            134 :         t = subre(v, '.', f, s, atom->end); /* prefix and atom */
  981                          1341         [ -  + ]:            134 :         NOERRN();
 1149                          1342                 :            134 :         t->child = subre(v, '=', PREF(f), s, atom->begin);
  981                          1343         [ -  + ]:            134 :         NOERRN();
 1149                          1344                 :            134 :         t->child->sibling = atom;
 7739                          1345                 :            134 :         *atomp = t;
                               1346                 :                :         /* rest of branch can be strung starting from atom->end */
 4433                          1347                 :            134 :         s2 = atom->end;
                               1348                 :                :     }
                               1349                 :                :     else
                               1350                 :                :     {
                               1351                 :                :         /* general case: need an iteration node */
                               1352                 :             80 :         s2 = newstate(v->nfa);
  981                          1353         [ -  + ]:             80 :         NOERRN();
 4433                          1354                 :             80 :         moveouts(v->nfa, atom->end, s2);
  981                          1355         [ -  + ]:             80 :         NOERRN();
 4433                          1356                 :             80 :         dupnfa(v->nfa, atom->begin, atom->end, s, s2);
                               1357                 :             80 :         repeat(v, s, s2, m, n);
                               1358         [ +  - ]:             80 :         f = COMBINE(qprefer, atom->flags);
                               1359                 :             80 :         t = subre(v, '*', f, s, s2);
  981                          1360         [ -  + ]:             80 :         NOERRN();
 4433                          1361                 :             80 :         t->min = (short) m;
                               1362                 :             80 :         t->max = (short) n;
 1149                          1363                 :             80 :         t->child = atom;
 4433                          1364                 :             80 :         *atomp = t;
                               1365                 :                :         /* rest of branch is to be strung from iteration's end state */
                               1366                 :                :     }
                               1367                 :                : 
                               1368                 :                :     /* and finally, look after that postponed recursion */
 1149                          1369                 :           2412 :     t = top->child->sibling;
 7739                          1370   [ +  +  +  +  :           2412 :     if (!(SEE('|') || SEE(stopper) || SEE(EOS)))
                                              +  - ]
                               1371                 :                :     {
                               1372                 :                :         /* parse all the rest of the branch, and insert in t->child->sibling */
 1149                          1373                 :           2051 :         t->child->sibling = parsebranch(v, stopper, type, s2, rp, 1);
  981                          1374         [ +  + ]:           2051 :         NOERRN();
 1149                          1375   [ +  +  -  +  :           2039 :         assert(SEE('|') || SEE(stopper) || SEE(EOS));
                                              -  - ]
                               1376                 :                : 
                               1377                 :                :         /* here's the promised update of the flags */
                               1378         [ +  + ]:           2039 :         t->flags |= COMBINE(t->flags, t->child->sibling->flags);
                               1379         [ +  + ]:           2039 :         top->flags |= COMBINE(top->flags, t->flags);
                               1380                 :                : 
                               1381                 :                :         /* neither t nor top could be directly marked for capture as yet */
 1139                          1382         [ -  + ]:           2039 :         assert(t->capno == 0);
                               1383         [ -  + ]:           2039 :         assert(top->capno == 0);
                               1384                 :                : 
                               1385                 :                :         /*
                               1386                 :                :          * At this point both top and t are concatenation (op == '.') subres,
                               1387                 :                :          * and we have top->child = prefix of branch, top->child->sibling = t,
                               1388                 :                :          * t->child = messy atom (with quantification superstructure if
                               1389                 :                :          * needed), t->child->sibling = rest of branch.
                               1390                 :                :          *
                               1391                 :                :          * If the messy atom was the first thing in the branch, then
                               1392                 :                :          * top->child is vacuous and we can get rid of one level of
                               1393                 :                :          * concatenation.
                               1394                 :                :          */
 1149                          1395         [ -  + ]:           2039 :         assert(top->child->op == '=');
                               1396         [ +  + ]:           2039 :         if (top->child->begin == top->child->end)
                               1397                 :                :         {
                               1398         [ -  + ]:            333 :             assert(!MESSY(top->child->flags));
                               1399                 :            333 :             freesubre(v, top->child);
                               1400                 :            333 :             top->child = t->child;
                               1401                 :            333 :             freesrnode(v, t);
                               1402                 :                :         }
                               1403                 :                : 
                               1404                 :                :         /*
                               1405                 :                :          * Otherwise, it's possible that t->child is not messy in itself, but
                               1406                 :                :          * we considered it messy because its greediness conflicts with what
                               1407                 :                :          * preceded it.  Then it could be that the combination of t->child and
                               1408                 :                :          * the rest of the branch is also not messy, in which case we can get
                               1409                 :                :          * rid of the child concatenation by merging t->child and the rest of
                               1410                 :                :          * the branch into one plain DFA node.
                               1411                 :                :          */
 1139                          1412         [ +  + ]:           1706 :         else if (t->child->op == '=' &&
                               1413         [ +  + ]:           1655 :                  t->child->sibling->op == '=' &&
                               1414         [ -  + ]:           1557 :                  !MESSY(UP(t->child->flags | t->child->sibling->flags)))
                               1415                 :                :         {
 1139 tgl@sss.pgh.pa.us        1416                 :UBC           0 :             t->op = '=';
                               1417         [ #  # ]:              0 :             t->flags = COMBINE(t->child->flags, t->child->sibling->flags);
                               1418                 :              0 :             freesubreandsiblings(v, t->child);
                               1419                 :              0 :             t->child = NULL;
                               1420                 :                :         }
                               1421                 :                :     }
                               1422                 :                :     else
                               1423                 :                :     {
                               1424                 :                :         /*
                               1425                 :                :          * There's nothing left in the branch, so we don't need the second
                               1426                 :                :          * concatenation node 't'.  Just link s2 straight to rp.
                               1427                 :                :          */
 4433 tgl@sss.pgh.pa.us        1428                 :CBC         361 :         EMPTYARC(s2, rp);
 1149                          1429                 :            361 :         top->child->sibling = t->child;
                               1430         [ +  + ]:            361 :         top->flags |= COMBINE(top->flags, top->child->sibling->flags);
                               1431                 :            361 :         freesrnode(v, t);
                               1432                 :                : 
                               1433                 :                :         /*
                               1434                 :                :          * Again, it could be that top->child is vacuous (if the messy atom
                               1435                 :                :          * was in fact the only thing in the branch).  In that case we need no
                               1436                 :                :          * concatenation at all; just replace top with top->child->sibling.
                               1437                 :                :          */
                               1438         [ -  + ]:            361 :         assert(top->child->op == '=');
                               1439         [ +  + ]:            361 :         if (top->child->begin == top->child->end)
                               1440                 :                :         {
                               1441         [ -  + ]:            259 :             assert(!MESSY(top->child->flags));
                               1442                 :            259 :             t = top->child->sibling;
  981                          1443                 :            259 :             top->child->sibling = NULL;
                               1444                 :            259 :             freesubre(v, top);
                               1445                 :            259 :             top = t;
                               1446                 :                :         }
                               1447                 :                :     }
                               1448                 :                : 
                               1449                 :           2400 :     return top;
                               1450                 :                : }
                               1451                 :                : 
                               1452                 :                : /*
                               1453                 :                :  * nonword - generate arcs for non-word-character ahead or behind
                               1454                 :                :  */
                               1455                 :                : static void
 2489                          1456                 :            111 : nonword(struct vars *v,
                               1457                 :                :         int dir,                /* AHEAD or BEHIND */
                               1458                 :                :         struct state *lp,
                               1459                 :                :         struct state *rp)
                               1460                 :                : {
 7559 bruce@momjian.us         1461         [ +  + ]:            111 :     int         anchor = (dir == AHEAD) ? '$' : '^';
                               1462                 :                : 
 7739 tgl@sss.pgh.pa.us        1463   [ +  +  -  + ]:            111 :     assert(dir == AHEAD || dir == BEHIND);
                               1464                 :            111 :     newarc(v->nfa, anchor, 1, lp, rp);
                               1465                 :            111 :     newarc(v->nfa, anchor, 0, lp, rp);
                               1466                 :            111 :     colorcomplement(v->nfa, v->cm, dir, v->wordchrs, lp, rp);
                               1467                 :                :     /* (no need for special attention to \n) */
10141 scrappy@hub.org          1468                 :            111 : }
                               1469                 :                : 
                               1470                 :                : /*
                               1471                 :                :  * word - generate arcs for word character ahead or behind
                               1472                 :                :  */
                               1473                 :                : static void
 2489 tgl@sss.pgh.pa.us        1474                 :            111 : word(struct vars *v,
                               1475                 :                :      int dir,                   /* AHEAD or BEHIND */
                               1476                 :                :      struct state *lp,
                               1477                 :                :      struct state *rp)
                               1478                 :                : {
 7739                          1479   [ +  +  -  + ]:            111 :     assert(dir == AHEAD || dir == BEHIND);
                               1480                 :            111 :     cloneouts(v->nfa, v->wordchrs, lp, rp, dir);
                               1481                 :                :     /* (no need for special attention to \n) */
10141 scrappy@hub.org          1482                 :            111 : }
                               1483                 :                : 
                               1484                 :                : /*
                               1485                 :                :  * charclass - generate arcs for a character class
                               1486                 :                :  *
                               1487                 :                :  * This is used for both atoms (\w and sibling escapes) and for elements
                               1488                 :                :  * of bracket expressions.  The caller is responsible for calling okcolors()
                               1489                 :                :  * at the end of processing the atom or bracket.
                               1490                 :                :  */
                               1491                 :                : static void
 1144 tgl@sss.pgh.pa.us        1492                 :            283 : charclass(struct vars *v,
                               1493                 :                :           enum char_classes cls,
                               1494                 :                :           struct state *lp,
                               1495                 :                :           struct state *rp)
                               1496                 :                : {
                               1497                 :                :     struct cvec *cv;
                               1498                 :                : 
                               1499                 :                :     /* obtain possibly-cached cvec for char class */
                               1500                 :            283 :     NOTE(REG_ULOCALE);
                               1501                 :            283 :     cv = cclasscvec(v, cls, (v->cflags & REG_ICASE));
                               1502         [ -  + ]:            283 :     NOERR();
                               1503                 :                : 
                               1504                 :                :     /* build the arcs; this may cause color splitting */
                               1505                 :            283 :     subcolorcvec(v, cv, lp, rp);
                               1506                 :                : }
                               1507                 :                : 
                               1508                 :                : /*
                               1509                 :                :  * charclasscomplement - generate arcs for a complemented character class
                               1510                 :                :  *
                               1511                 :                :  * This is used for both atoms (\W and sibling escapes) and for elements
                               1512                 :                :  * of bracket expressions.  In bracket expressions, it is the caller's
                               1513                 :                :  * responsibility that there not be any open subcolors when this is called.
                               1514                 :                :  */
                               1515                 :                : static void
                               1516                 :             37 : charclasscomplement(struct vars *v,
                               1517                 :                :                     enum char_classes cls,
                               1518                 :                :                     struct state *lp,
                               1519                 :                :                     struct state *rp)
                               1520                 :                : {
                               1521                 :                :     struct state *cstate;
                               1522                 :                :     struct cvec *cv;
                               1523                 :                : 
                               1524                 :                :     /* make dummy state to hang temporary arcs on */
                               1525                 :             37 :     cstate = newstate(v->nfa);
                               1526         [ -  + ]:             37 :     NOERR();
                               1527                 :                : 
                               1528                 :                :     /* obtain possibly-cached cvec for char class */
                               1529                 :             37 :     NOTE(REG_ULOCALE);
                               1530                 :             37 :     cv = cclasscvec(v, cls, (v->cflags & REG_ICASE));
                               1531         [ -  + ]:             37 :     NOERR();
                               1532                 :                : 
                               1533                 :                :     /* build arcs for char class; this may cause color splitting */
                               1534                 :             37 :     subcolorcvec(v, cv, cstate, cstate);
                               1535         [ -  + ]:             37 :     NOERR();
                               1536                 :                : 
                               1537                 :                :     /* clean up any subcolors in the arc set */
                               1538                 :             37 :     okcolors(v->nfa, v->cm);
                               1539         [ -  + ]:             37 :     NOERR();
                               1540                 :                : 
                               1541                 :                :     /* now build output arcs for the complement of the char class */
                               1542                 :             37 :     colorcomplement(v->nfa, v->cm, PLAIN, cstate, lp, rp);
                               1543         [ -  + ]:             37 :     NOERR();
                               1544                 :                : 
                               1545                 :                :     /* clean up dummy state */
                               1546                 :             37 :     dropstate(v->nfa, cstate);
                               1547                 :                : }
                               1548                 :                : 
                               1549                 :                : /*
                               1550                 :                :  * scannum - scan a number
                               1551                 :                :  */
                               1552                 :                : static int                      /* value, <= DUPMAX */
 2489                          1553                 :            372 : scannum(struct vars *v)
                               1554                 :                : {
 7559 bruce@momjian.us         1555                 :            372 :     int         n = 0;
                               1556                 :                : 
                               1557   [ +  +  +  - ]:            786 :     while (SEE(DIGIT) && n < DUPMAX)
                               1558                 :                :     {
                               1559                 :            414 :         n = n * 10 + v->nextvalue;
10141 scrappy@hub.org          1560                 :            414 :         NEXT();
                               1561                 :                :     }
 7559 bruce@momjian.us         1562   [ +  -  +  + ]:            372 :     if (SEE(DIGIT) || n > DUPMAX)
                               1563                 :                :     {
 7739 tgl@sss.pgh.pa.us        1564         [ -  + ]:              2 :         ERR(REG_BADBR);
 9357 bruce@momjian.us         1565                 :              2 :         return 0;
                               1566                 :                :     }
 7739 tgl@sss.pgh.pa.us        1567                 :            370 :     return n;
                               1568                 :                : }
                               1569                 :                : 
                               1570                 :                : /*
                               1571                 :                :  * repeat - replicate subNFA for quantifiers
                               1572                 :                :  *
                               1573                 :                :  * The sub-NFA strung from lp to rp is modified to represent m to n
                               1574                 :                :  * repetitions of its initial contents.
                               1575                 :                :  *
                               1576                 :                :  * The duplication sequences used here are chosen carefully so that any
                               1577                 :                :  * pointers starting out pointing into the subexpression end up pointing into
                               1578                 :                :  * the last occurrence.  (Note that it may not be strung between the same
                               1579                 :                :  * left and right end states, however!)  This used to be important for the
                               1580                 :                :  * subRE tree, although the important bits are now handled by the in-line
                               1581                 :                :  * code in parse(), and when this is called, it doesn't matter any more.
                               1582                 :                :  */
                               1583                 :                : static void
 2489                          1584                 :          12506 : repeat(struct vars *v,
                               1585                 :                :        struct state *lp,
                               1586                 :                :        struct state *rp,
                               1587                 :                :        int m,
                               1588                 :                :        int n)
                               1589                 :                : {
                               1590                 :                : #define  SOME    2
                               1591                 :                : #define  INF     3
                               1592                 :                : #define  PAIR(x, y)  ((x)*4 + (y))
                               1593                 :                : #define  REDUCE(x)   ( ((x) == DUPINF) ? INF : (((x) > 1) ? SOME : (x)) )
 7559 bruce@momjian.us         1594         [ +  - ]:          12506 :     const int   rm = REDUCE(m);
                               1595         [ +  + ]:          12506 :     const int   rn = REDUCE(n);
                               1596                 :                :     struct state *s;
                               1597                 :                :     struct state *s2;
                               1598                 :                : 
                               1599   [ +  +  +  +  :          12506 :     switch (PAIR(rm, rn))
                                     +  +  +  +  +  
                                                 - ]
                               1600                 :                :     {
                               1601                 :             15 :         case PAIR(0, 0):        /* empty string */
                               1602                 :             15 :             delsub(v->nfa, lp, rp);
                               1603                 :             15 :             EMPTYARC(lp, rp);
                               1604                 :             15 :             break;
                               1605                 :             61 :         case PAIR(0, 1):        /* do as x| */
                               1606                 :             61 :             EMPTYARC(lp, rp);
                               1607                 :             61 :             break;
                               1608                 :              2 :         case PAIR(0, SOME):     /* do as x{1,n}| */
                               1609                 :              2 :             repeat(v, lp, rp, 1, n);
                               1610         [ -  + ]:              2 :             NOERR();
                               1611                 :              2 :             EMPTYARC(lp, rp);
                               1612                 :              2 :             break;
                               1613                 :          10664 :         case PAIR(0, INF):      /* loop x around */
                               1614                 :          10664 :             s = newstate(v->nfa);
                               1615         [ -  + ]:          10664 :             NOERR();
                               1616                 :          10664 :             moveouts(v->nfa, lp, s);
                               1617                 :          10664 :             moveins(v->nfa, rp, s);
                               1618                 :          10664 :             EMPTYARC(lp, s);
                               1619                 :          10664 :             EMPTYARC(s, rp);
                               1620                 :          10664 :             break;
                               1621                 :            191 :         case PAIR(1, 1):        /* no action required */
                               1622                 :            191 :             break;
                               1623                 :            349 :         case PAIR(1, SOME):     /* do as x{0,n-1}x = (x{1,n-1}|)x */
                               1624                 :            349 :             s = newstate(v->nfa);
                               1625         [ -  + ]:            349 :             NOERR();
                               1626                 :            349 :             moveouts(v->nfa, lp, s);
                               1627                 :            349 :             dupnfa(v->nfa, s, rp, lp, s);
                               1628         [ -  + ]:            349 :             NOERR();
                               1629                 :            349 :             repeat(v, lp, s, 1, n - 1);
                               1630         [ -  + ]:            349 :             NOERR();
                               1631                 :            349 :             EMPTYARC(lp, s);
                               1632                 :            349 :             break;
                               1633                 :            332 :         case PAIR(1, INF):      /* add loopback arc */
                               1634                 :            332 :             s = newstate(v->nfa);
                               1635                 :            332 :             s2 = newstate(v->nfa);
                               1636         [ -  + ]:            332 :             NOERR();
                               1637                 :            332 :             moveouts(v->nfa, lp, s);
                               1638                 :            332 :             moveins(v->nfa, rp, s2);
                               1639                 :            332 :             EMPTYARC(lp, s);
                               1640                 :            332 :             EMPTYARC(s2, rp);
                               1641                 :            332 :             EMPTYARC(s2, s);
                               1642                 :            332 :             break;
                               1643                 :            788 :         case PAIR(SOME, SOME):  /* do as x{m-1,n-1}x */
                               1644                 :            788 :             s = newstate(v->nfa);
                               1645         [ -  + ]:            788 :             NOERR();
                               1646                 :            788 :             moveouts(v->nfa, lp, s);
                               1647                 :            788 :             dupnfa(v->nfa, s, rp, lp, s);
                               1648         [ -  + ]:            788 :             NOERR();
                               1649                 :            788 :             repeat(v, lp, s, m - 1, n - 1);
                               1650                 :            788 :             break;
                               1651                 :            104 :         case PAIR(SOME, INF):   /* do as x{m-1,}x */
                               1652                 :            104 :             s = newstate(v->nfa);
                               1653         [ -  + ]:            104 :             NOERR();
                               1654                 :            104 :             moveouts(v->nfa, lp, s);
                               1655                 :            104 :             dupnfa(v->nfa, s, rp, lp, s);
                               1656         [ -  + ]:            104 :             NOERR();
                               1657                 :            104 :             repeat(v, lp, s, m - 1, n);
                               1658                 :            104 :             break;
 7559 bruce@momjian.us         1659                 :UBC           0 :         default:
                               1660         [ #  # ]:              0 :             ERR(REG_ASSERT);
                               1661                 :              0 :             break;
                               1662                 :                :     }
                               1663                 :                : }
                               1664                 :                : 
                               1665                 :                : /*
                               1666                 :                :  * bracket - handle non-complemented bracket expression
                               1667                 :                :  *
                               1668                 :                :  * Also called from cbracket for complemented bracket expressions.
                               1669                 :                :  */
                               1670                 :                : static void
 2489 tgl@sss.pgh.pa.us        1671                 :CBC         609 : bracket(struct vars *v,
                               1672                 :                :         struct state *lp,
                               1673                 :                :         struct state *rp)
                               1674                 :                : {
                               1675                 :                :     /*
                               1676                 :                :      * We can't process complemented char classes (e.g. \W) immediately while
                               1677                 :                :      * scanning the bracket expression, else color bookkeeping gets confused.
                               1678                 :                :      * Instead, remember whether we saw any in have_cclassc[], and process
                               1679                 :                :      * them at the end.
                               1680                 :                :      */
                               1681                 :                :     bool        have_cclassc[NUM_CCLASSES];
                               1682                 :                :     bool        any_cclassc;
                               1683                 :                :     int         i;
                               1684                 :                : 
 1144                          1685                 :            609 :     memset(have_cclassc, false, sizeof(have_cclassc));
                               1686                 :                : 
 7739                          1687         [ -  + ]:            609 :     assert(SEE('['));
                               1688                 :            609 :     NEXT();
                               1689   [ +  +  +  + ]:           1533 :     while (!SEE(']') && !SEE(EOS))
 1144                          1690                 :            924 :         brackpart(v, lp, rp, have_cclassc);
 7739                          1691   [ +  +  -  + ]:            609 :     assert(SEE(']') || ISERR());
                               1692                 :                : 
                               1693                 :                :     /* close up open subcolors from the positive bracket elements */
                               1694                 :            609 :     okcolors(v->nfa, v->cm);
 1144                          1695         [ +  + ]:            609 :     NOERR();
                               1696                 :                : 
                               1697                 :                :     /* now handle any complemented elements */
                               1698                 :            574 :     any_cclassc = false;
                               1699         [ +  + ]:           8610 :     for (i = 0; i < NUM_CCLASSES; i++)
                               1700                 :                :     {
                               1701         [ +  + ]:           8036 :         if (have_cclassc[i])
                               1702                 :                :         {
                               1703                 :             14 :             charclasscomplement(v, (enum char_classes) i, lp, rp);
                               1704         [ -  + ]:             14 :             NOERR();
                               1705                 :             14 :             any_cclassc = true;
                               1706                 :                :         }
                               1707                 :                :     }
                               1708                 :                : 
                               1709                 :                :     /*
                               1710                 :                :      * If we had any complemented elements, see if we can optimize the bracket
                               1711                 :                :      * into a rainbow.  Since a complemented element is the only way a WHITE
                               1712                 :                :      * arc could get into the result, there's no point in checking otherwise.
                               1713                 :                :      */
                               1714         [ +  + ]:            574 :     if (any_cclassc)
                               1715                 :             14 :         optimizebracket(v, lp, rp);
                               1716                 :                : }
                               1717                 :                : 
                               1718                 :                : /*
                               1719                 :                :  * cbracket - handle complemented bracket expression
                               1720                 :                :  *
                               1721                 :                :  * We do it by calling bracket() with dummy endpoints, and then complementing
                               1722                 :                :  * the result.  The alternative would be to invoke rainbow(), and then delete
                               1723                 :                :  * arcs as the b.e. is seen... but that gets messy, and is really quite
                               1724                 :                :  * infeasible now that rainbow() just puts out one RAINBOW arc.
                               1725                 :                :  */
                               1726                 :                : static void
 2489                          1727                 :            114 : cbracket(struct vars *v,
                               1728                 :                :          struct state *lp,
                               1729                 :                :          struct state *rp)
                               1730                 :                : {
 7739                          1731                 :            114 :     struct state *left = newstate(v->nfa);
                               1732                 :            114 :     struct state *right = newstate(v->nfa);
                               1733                 :                : 
                               1734         [ -  + ]:            114 :     NOERR();
                               1735                 :            114 :     bracket(v, left, right);
                               1736                 :                : 
                               1737                 :                :     /* in NLSTOP mode, ensure newline is not part of the result set */
 7559 bruce@momjian.us         1738         [ +  + ]:            114 :     if (v->cflags & REG_NLSTOP)
 7739 tgl@sss.pgh.pa.us        1739                 :              2 :         newarc(v->nfa, PLAIN, v->nlcolor, left, right);
                               1740         [ -  + ]:            114 :     NOERR();
                               1741                 :                : 
                               1742         [ -  + ]:            114 :     assert(lp->nouts == 0);      /* all outarcs will be ours */
                               1743                 :                : 
                               1744                 :                :     /*
                               1745                 :                :      * Easy part of complementing, and all there is to do since the MCCE code
                               1746                 :                :      * was removed.  Note that the result of colorcomplement() cannot be a
                               1747                 :                :      * rainbow, since we don't allow empty brackets; so there's no point in
                               1748                 :                :      * calling optimizebracket() again.
                               1749                 :                :      */
                               1750                 :            114 :     colorcomplement(v->nfa, v->cm, PLAIN, left, lp, rp);
                               1751         [ -  + ]:            114 :     NOERR();
 5904                          1752                 :            114 :     dropstate(v->nfa, left);
 7739                          1753         [ -  + ]:            114 :     assert(right->nins == 0);
                               1754                 :            114 :     freestate(v->nfa, right);
                               1755                 :                : }
                               1756                 :                : 
                               1757                 :                : /*
                               1758                 :                :  * brackpart - handle one item (or range) within a bracket expression
                               1759                 :                :  */
                               1760                 :                : static void
 2489                          1761                 :            924 : brackpart(struct vars *v,
                               1762                 :                :           struct state *lp,
                               1763                 :                :           struct state *rp,
                               1764                 :                :           bool *have_cclassc)
                               1765                 :                : {
                               1766                 :                :     chr         startc;
                               1767                 :                :     chr         endc;
                               1768                 :                :     struct cvec *cv;
                               1769                 :                :     enum char_classes cls;
                               1770                 :                :     const chr  *startp;
                               1771                 :                :     const chr  *endp;
                               1772                 :                : 
                               1773                 :                :     /* parse something, get rid of special cases, take shortcuts */
 7559 bruce@momjian.us         1774   [ +  +  +  +  :            924 :     switch (v->nexttype)
                                        +  +  +  - ]
                               1775                 :                :     {
                               1776                 :              4 :         case RANGE:             /* a-b-c or other botch */
                               1777         [ -  + ]:              4 :             ERR(REG_ERANGE);
 7739 tgl@sss.pgh.pa.us        1778                 :              4 :             return;
                               1779                 :                :             break;
                               1780                 :            753 :         case PLAIN:
 1144                          1781                 :            753 :             startc = v->nextvalue;
 7739                          1782                 :            753 :             NEXT();
                               1783                 :                :             /* shortcut for ordinary chr (not range) */
 5904                          1784         [ +  + ]:            753 :             if (!SEE(RANGE))
                               1785                 :                :             {
 1144                          1786                 :            471 :                 onechr(v, startc, lp, rp);
 7559 bruce@momjian.us         1787                 :            471 :                 return;
                               1788                 :                :             }
 7739 tgl@sss.pgh.pa.us        1789         [ -  + ]:            282 :             NOERR();
 9715 bruce@momjian.us         1790                 :            282 :             break;
 7739 tgl@sss.pgh.pa.us        1791                 :             10 :         case COLLEL:
                               1792                 :             10 :             startp = v->now;
                               1793                 :             10 :             endp = scanplain(v);
                               1794   [ -  +  -  - ]:             10 :             INSIST(startp < endp, REG_ECOLLATE);
                               1795         [ +  + ]:             10 :             NOERR();
 7559 bruce@momjian.us         1796                 :              8 :             startc = element(v, startp, endp);
                               1797         [ +  + ]:              8 :             NOERR();
                               1798                 :              6 :             break;
                               1799                 :             14 :         case ECLASS:
                               1800                 :             14 :             startp = v->now;
                               1801                 :             14 :             endp = scanplain(v);
                               1802   [ -  +  -  - ]:             14 :             INSIST(startp < endp, REG_ECOLLATE);
                               1803         [ +  + ]:             14 :             NOERR();
                               1804                 :             12 :             startc = element(v, startp, endp);
                               1805         [ +  + ]:             12 :             NOERR();
                               1806                 :             10 :             cv = eclass(v, startc, (v->cflags & REG_ICASE));
 7739 tgl@sss.pgh.pa.us        1807         [ -  + ]:             10 :             NOERR();
 2778                          1808                 :             10 :             subcolorcvec(v, cv, lp, rp);
 7559 bruce@momjian.us         1809                 :             10 :             return;
                               1810                 :                :             break;
                               1811                 :            118 :         case CCLASS:
                               1812                 :            118 :             startp = v->now;
                               1813                 :            118 :             endp = scanplain(v);
                               1814   [ -  +  -  - ]:            118 :             INSIST(startp < endp, REG_ECTYPE);
                               1815         [ +  + ]:            118 :             NOERR();
 1144 tgl@sss.pgh.pa.us        1816                 :            116 :             cls = lookupcclass(v, startp, endp);
 7559 bruce@momjian.us         1817         [ +  + ]:            116 :             NOERR();
 1144 tgl@sss.pgh.pa.us        1818                 :            112 :             charclass(v, cls, lp, rp);
                               1819                 :            112 :             return;
                               1820                 :                :             break;
                               1821                 :             11 :         case CCLASSS:
                               1822                 :             11 :             charclass(v, (enum char_classes) v->nextvalue, lp, rp);
                               1823                 :             11 :             NEXT();
                               1824                 :             11 :             return;
                               1825                 :                :             break;
                               1826                 :             14 :         case CCLASSC:
                               1827                 :                :             /* we cannot call charclasscomplement() immediately */
                               1828                 :             14 :             have_cclassc[v->nextvalue] = true;
                               1829                 :             14 :             NEXT();
 7559 bruce@momjian.us         1830                 :             14 :             return;
                               1831                 :                :             break;
 7739 tgl@sss.pgh.pa.us        1832                 :UBC           0 :         default:
 7559 bruce@momjian.us         1833         [ #  # ]:              0 :             ERR(REG_ASSERT);
 7739 tgl@sss.pgh.pa.us        1834                 :              0 :             return;
                               1835                 :                :             break;
                               1836                 :                :     }
                               1837                 :                : 
 7559 bruce@momjian.us         1838         [ +  + ]:CBC         288 :     if (SEE(RANGE))
                               1839                 :                :     {
                               1840                 :            284 :         NEXT();
                               1841      [ +  +  + ]:            284 :         switch (v->nexttype)
                               1842                 :                :         {
                               1843                 :            274 :             case PLAIN:
                               1844                 :                :             case RANGE:
 1144 tgl@sss.pgh.pa.us        1845                 :            274 :                 endc = v->nextvalue;
 7559 bruce@momjian.us         1846                 :            274 :                 NEXT();
                               1847         [ +  + ]:            274 :                 NOERR();
                               1848                 :            272 :                 break;
                               1849                 :              2 :             case COLLEL:
                               1850                 :              2 :                 startp = v->now;
                               1851                 :              2 :                 endp = scanplain(v);
                               1852   [ -  +  -  - ]:              2 :                 INSIST(startp < endp, REG_ECOLLATE);
                               1853         [ -  + ]:              2 :                 NOERR();
                               1854                 :              2 :                 endc = element(v, startp, endp);
                               1855         [ -  + ]:              2 :                 NOERR();
                               1856                 :              2 :                 break;
                               1857                 :              8 :             default:
                               1858         [ +  + ]:              8 :                 ERR(REG_ERANGE);
                               1859                 :              8 :                 return;
                               1860                 :                :                 break;
                               1861                 :                :         }
                               1862                 :                :     }
                               1863                 :                :     else
 7739 tgl@sss.pgh.pa.us        1864                 :              4 :         endc = startc;
                               1865                 :                : 
                               1866                 :                :     /*
                               1867                 :                :      * Ranges are unportable.  Actually, standard C does guarantee that digits
                               1868                 :                :      * are contiguous, but making that an exception is just too complicated.
                               1869                 :                :      */
                               1870         [ +  + ]:            278 :     if (startc != endc)
                               1871                 :            270 :         NOTE(REG_UUNPORT);
 7559 bruce@momjian.us         1872                 :            278 :     cv = range(v, startc, endc, (v->cflags & REG_ICASE));
 7739 tgl@sss.pgh.pa.us        1873         [ +  + ]:            278 :     NOERR();
 2778                          1874                 :            276 :     subcolorcvec(v, cv, lp, rp);
                               1875                 :                : }
                               1876                 :                : 
                               1877                 :                : /*
                               1878                 :                :  * scanplain - scan PLAIN contents of [. etc.
                               1879                 :                :  *
                               1880                 :                :  * Certain bits of trickery in regc_lex.c know that this code does not try
                               1881                 :                :  * to look past the final bracket of the [. etc.
                               1882                 :                :  */
                               1883                 :                : static const chr *              /* just after end of sequence */
 2489                          1884                 :            144 : scanplain(struct vars *v)
                               1885                 :                : {
                               1886                 :                :     const chr  *endp;
                               1887                 :                : 
 7739                          1888   [ +  +  +  +  :            144 :     assert(SEE(COLLEL) || SEE(ECLASS) || SEE(CCLASS));
                                              -  + ]
                               1889                 :            144 :     NEXT();
                               1890                 :                : 
                               1891                 :            144 :     endp = v->now;
 7559 bruce@momjian.us         1892         [ +  + ]:            755 :     while (SEE(PLAIN))
                               1893                 :                :     {
 7739 tgl@sss.pgh.pa.us        1894                 :            611 :         endp = v->now;
                               1895                 :            611 :         NEXT();
                               1896                 :                :     }
                               1897                 :                : 
                               1898   [ +  +  -  + ]:            144 :     assert(SEE(END) || ISERR());
                               1899                 :            144 :     NEXT();
                               1900                 :                : 
                               1901                 :            144 :     return endp;
                               1902                 :                : }
                               1903                 :                : 
                               1904                 :                : /*
                               1905                 :                :  * onechr - fill in arcs for a plain character, and possible case complements
                               1906                 :                :  * This is mostly a shortcut for efficient handling of the common case.
                               1907                 :                :  */
                               1908                 :                : static void
 2489                          1909                 :          37522 : onechr(struct vars *v,
                               1910                 :                :        chr c,
                               1911                 :                :        struct state *lp,
                               1912                 :                :        struct state *rp)
                               1913                 :                : {
 7559 bruce@momjian.us         1914         [ +  + ]:          37522 :     if (!(v->cflags & REG_ICASE))
                               1915                 :                :     {
 2778 tgl@sss.pgh.pa.us        1916                 :          36711 :         color       lastsubcolor = COLORLESS;
                               1917                 :                : 
                               1918                 :          36711 :         subcoloronechr(v, c, lp, rp, &lastsubcolor);
 7739                          1919                 :          36711 :         return;
                               1920                 :                :     }
                               1921                 :                : 
                               1922                 :                :     /* rats, need general case anyway... */
 2778                          1923                 :            811 :     subcolorcvec(v, allcases(v, c), lp, rp);
                               1924                 :                : }
                               1925                 :                : 
                               1926                 :                : /*
                               1927                 :                :  * optimizebracket - see if bracket expression can be converted to RAINBOW
                               1928                 :                :  *
                               1929                 :                :  * Cases such as "[\s\S]" can produce a set of arcs of all colors, which we
                               1930                 :                :  * can replace by a single RAINBOW arc for efficiency.  (This might seem
                               1931                 :                :  * like a silly way to write ".", but it's seemingly a common locution in
                               1932                 :                :  * some other flavors of regex, so take the trouble to support it well.)
                               1933                 :                :  */
                               1934                 :                : static void
 1144                          1935                 :             14 : optimizebracket(struct vars *v,
                               1936                 :                :                 struct state *lp,
                               1937                 :                :                 struct state *rp)
                               1938                 :                : {
                               1939                 :                :     struct colordesc *cd;
                               1940                 :             14 :     struct colordesc *end = CDEND(v->cm);
                               1941                 :                :     struct arc *a;
                               1942                 :                :     bool        israinbow;
                               1943                 :                : 
                               1944                 :                :     /*
                               1945                 :                :      * Scan lp's out-arcs and transiently mark the mentioned colors.  We
                               1946                 :                :      * expect that all of lp's out-arcs are plain, non-RAINBOW arcs to rp.
                               1947                 :                :      * (Note: there shouldn't be any pseudocolors yet, but check anyway.)
                               1948                 :                :      */
                               1949         [ +  + ]:             35 :     for (a = lp->outs; a != NULL; a = a->outchain)
                               1950                 :                :     {
                               1951         [ -  + ]:             21 :         assert(a->type == PLAIN);
                               1952         [ -  + ]:             21 :         assert(a->co >= 0);       /* i.e. not RAINBOW */
                               1953         [ -  + ]:             21 :         assert(a->to == rp);
                               1954                 :             21 :         cd = &v->cm->cd[a->co];
                               1955   [ +  -  -  + ]:             21 :         assert(!UNUSEDCOLOR(cd) && !(cd->flags & PSEUDO));
                               1956                 :             21 :         cd->flags |= COLMARK;
                               1957                 :                :     }
                               1958                 :                : 
                               1959                 :                :     /* Scan colors, clear transient marks, check for unmarked live colors */
                               1960                 :             14 :     israinbow = true;
                               1961         [ +  + ]:             54 :     for (cd = v->cm->cd; cd < end; cd++)
                               1962                 :                :     {
                               1963         [ +  + ]:             40 :         if (cd->flags & COLMARK)
                               1964                 :             21 :             cd->flags &= ~COLMARK;
                               1965   [ +  +  +  - ]:             19 :         else if (!UNUSEDCOLOR(cd) && !(cd->flags & PSEUDO))
                               1966                 :             14 :             israinbow = false;
                               1967                 :                :     }
                               1968                 :                : 
                               1969                 :                :     /* Can't do anything if not all colors have arcs */
                               1970         [ +  + ]:             14 :     if (!israinbow)
                               1971                 :             13 :         return;
                               1972                 :                : 
                               1973                 :                :     /* OK, drop existing arcs and replace with a rainbow */
                               1974         [ +  + ]:              3 :     while ((a = lp->outs) != NULL)
                               1975                 :              2 :         freearc(v->nfa, a);
                               1976                 :              1 :     newarc(v->nfa, PLAIN, RAINBOW, lp, rp);
                               1977                 :                : }
                               1978                 :                : 
                               1979                 :                : /*
                               1980                 :                :  * wordchrs - set up word-chr list for word-boundary stuff, if needed
                               1981                 :                :  *
                               1982                 :                :  * The list is kept as a bunch of circular arcs on an otherwise-unused state.
                               1983                 :                :  *
                               1984                 :                :  * Note that this must not be called while we have any open subcolors,
                               1985                 :                :  * else construction of the list would confuse color bookkeeping.
                               1986                 :                :  * Hence, we can't currently apply a similar optimization in
                               1987                 :                :  * charclass[complement](), as those need to be usable within bracket
                               1988                 :                :  * expressions.
                               1989                 :                :  */
                               1990                 :                : static void
 2489                          1991                 :             83 : wordchrs(struct vars *v)
                               1992                 :                : {
                               1993                 :                :     struct state *cstate;
                               1994                 :                :     struct cvec *cv;
                               1995                 :                : 
 7559 bruce@momjian.us         1996         [ +  + ]:             83 :     if (v->wordchrs != NULL)
 1144 tgl@sss.pgh.pa.us        1997                 :             13 :         return;                 /* done already */
                               1998                 :                : 
                               1999                 :                :     /* make dummy state to hang the cache arcs on */
                               2000                 :             70 :     cstate = newstate(v->nfa);
 7739                          2001         [ -  + ]:             70 :     NOERR();
                               2002                 :                : 
                               2003                 :                :     /* obtain possibly-cached cvec for \w characters */
 1144                          2004                 :             70 :     NOTE(REG_ULOCALE);
                               2005                 :             70 :     cv = cclasscvec(v, CC_WORD, (v->cflags & REG_ICASE));
 7739                          2006         [ -  + ]:             70 :     NOERR();
                               2007                 :                : 
                               2008                 :                :     /* build the arcs; this may cause color splitting */
 1144                          2009                 :             70 :     subcolorcvec(v, cv, cstate, cstate);
                               2010         [ -  + ]:             70 :     NOERR();
                               2011                 :                : 
                               2012                 :                :     /* close new open subcolors to ensure the cache entry is self-contained */
                               2013                 :             70 :     okcolors(v->nfa, v->cm);
                               2014         [ -  + ]:             70 :     NOERR();
                               2015                 :                : 
                               2016                 :                :     /* success! save the cache pointer */
                               2017                 :             70 :     v->wordchrs = cstate;
                               2018                 :                : }
                               2019                 :                : 
                               2020                 :                : /*
                               2021                 :                :  * processlacon - generate the NFA representation of a LACON
                               2022                 :                :  *
                               2023                 :                :  * In the general case this is just newlacon() + newarc(), but some cases
                               2024                 :                :  * can be optimized.
                               2025                 :                :  */
                               2026                 :                : static void
 2489                          2027                 :            127 : processlacon(struct vars *v,
                               2028                 :                :              struct state *begin,   /* start of parsed LACON sub-re */
                               2029                 :                :              struct state *end, /* end of parsed LACON sub-re */
                               2030                 :                :              int latype,
                               2031                 :                :              struct state *lp,  /* left state to hang it on */
                               2032                 :                :              struct state *rp)  /* right state to hang it on */
                               2033                 :                : {
                               2034                 :                :     struct state *s1;
                               2035                 :                :     int         n;
                               2036                 :                : 
                               2037                 :                :     /*
                               2038                 :                :      * Check for lookaround RE consisting of a single plain color arc (or set
                               2039                 :                :      * of arcs); this would typically be a simple chr or a bracket expression.
                               2040                 :                :      */
 3089                          2041                 :            127 :     s1 = single_color_transition(begin, end);
                               2042   [ +  +  +  +  :            127 :     switch (latype)
                                                 - ]
                               2043                 :                :     {
                               2044                 :             35 :         case LATYPE_AHEAD_POS:
                               2045                 :                :             /* If lookahead RE is just colorset C, convert to AHEAD(C) */
                               2046         [ +  + ]:             35 :             if (s1 != NULL)
                               2047                 :                :             {
                               2048                 :             30 :                 cloneouts(v->nfa, s1, lp, rp, AHEAD);
                               2049                 :             30 :                 return;
                               2050                 :                :             }
                               2051                 :              5 :             break;
                               2052                 :             39 :         case LATYPE_AHEAD_NEG:
                               2053                 :                :             /* If lookahead RE is just colorset C, convert to AHEAD(^C)|$ */
                               2054         [ +  + ]:             39 :             if (s1 != NULL)
                               2055                 :                :             {
                               2056                 :             10 :                 colorcomplement(v->nfa, v->cm, AHEAD, s1, lp, rp);
                               2057                 :             10 :                 newarc(v->nfa, '$', 1, lp, rp);
                               2058                 :             10 :                 newarc(v->nfa, '$', 0, lp, rp);
                               2059                 :             10 :                 return;
                               2060                 :                :             }
                               2061                 :             29 :             break;
                               2062                 :             39 :         case LATYPE_BEHIND_POS:
                               2063                 :                :             /* If lookbehind RE is just colorset C, convert to BEHIND(C) */
                               2064         [ +  + ]:             39 :             if (s1 != NULL)
                               2065                 :                :             {
                               2066                 :             30 :                 cloneouts(v->nfa, s1, lp, rp, BEHIND);
                               2067                 :             30 :                 return;
                               2068                 :                :             }
                               2069                 :              9 :             break;
                               2070                 :             14 :         case LATYPE_BEHIND_NEG:
                               2071                 :                :             /* If lookbehind RE is just colorset C, convert to BEHIND(^C)|^ */
                               2072         [ +  - ]:             14 :             if (s1 != NULL)
                               2073                 :                :             {
                               2074                 :             14 :                 colorcomplement(v->nfa, v->cm, BEHIND, s1, lp, rp);
                               2075                 :             14 :                 newarc(v->nfa, '^', 1, lp, rp);
                               2076                 :             14 :                 newarc(v->nfa, '^', 0, lp, rp);
                               2077                 :             14 :                 return;
                               2078                 :                :             }
 3089 tgl@sss.pgh.pa.us        2079                 :UBC           0 :             break;
                               2080                 :              0 :         default:
                               2081                 :              0 :             assert(NOTREACHED);
                               2082                 :                :     }
                               2083                 :                : 
                               2084                 :                :     /* General case: we need a LACON subre and arc */
 3089 tgl@sss.pgh.pa.us        2085                 :CBC          43 :     n = newlacon(v, begin, end, latype);
                               2086                 :             43 :     newarc(v->nfa, LACON, n, lp, rp);
                               2087                 :                : }
                               2088                 :                : 
                               2089                 :                : /*
                               2090                 :                :  * subre - allocate a subre
                               2091                 :                :  */
                               2092                 :                : static struct subre *
 2489                          2093                 :          20040 : subre(struct vars *v,
                               2094                 :                :       int op,
                               2095                 :                :       int flags,
                               2096                 :                :       struct state *begin,
                               2097                 :                :       struct state *end)
                               2098                 :                : {
 5904                          2099                 :          20040 :     struct subre *ret = v->treefree;
                               2100                 :                : 
                               2101                 :                :     /*
                               2102                 :                :      * Checking for stack overflow here is sufficient to protect parse() and
                               2103                 :                :      * its recursive subroutines.
                               2104                 :                :      */
 3117                          2105         [ -  + ]:          20040 :     if (STACK_TOO_DEEP(v->re))
                               2106                 :                :     {
 3117 tgl@sss.pgh.pa.us        2107         [ #  # ]:UBC           0 :         ERR(REG_ETOOBIG);
                               2108                 :              0 :         return NULL;
                               2109                 :                :     }
                               2110                 :                : 
 7739 tgl@sss.pgh.pa.us        2111         [ +  + ]:CBC       20040 :     if (ret != NULL)
 1149                          2112                 :           2870 :         v->treefree = ret->child;
                               2113                 :                :     else
                               2114                 :                :     {
 7559 bruce@momjian.us         2115                 :          17170 :         ret = (struct subre *) MALLOC(sizeof(struct subre));
                               2116         [ -  + ]:          17170 :         if (ret == NULL)
                               2117                 :                :         {
 7739 tgl@sss.pgh.pa.us        2118         [ #  # ]:UBC           0 :             ERR(REG_ESPACE);
                               2119                 :              0 :             return NULL;
                               2120                 :                :         }
 7739 tgl@sss.pgh.pa.us        2121                 :CBC       17170 :         ret->chain = v->treechain;
                               2122                 :          17170 :         v->treechain = ret;
                               2123                 :                :     }
                               2124                 :                : 
 4433                          2125         [ -  + ]:          20040 :     assert(strchr("=b|.*(", op) != NULL);
                               2126                 :                : 
 7739                          2127                 :          20040 :     ret->op = op;
                               2128                 :          20040 :     ret->flags = flags;
 1149                          2129                 :          20040 :     ret->latype = (char) -1;
 4433                          2130                 :          20040 :     ret->id = 0;             /* will be assigned later */
 1149                          2131                 :          20040 :     ret->capno = 0;
                               2132                 :          20040 :     ret->backno = 0;
 7739                          2133                 :          20040 :     ret->min = ret->max = 1;
 1149                          2134                 :          20040 :     ret->child = NULL;
                               2135                 :          20040 :     ret->sibling = NULL;
 7739                          2136                 :          20040 :     ret->begin = begin;
                               2137                 :          20040 :     ret->end = end;
                               2138                 :          20040 :     ZAPCNFA(ret->cnfa);
                               2139                 :                : 
                               2140                 :          20040 :     return ret;
                               2141                 :                : }
                               2142                 :                : 
                               2143                 :                : /*
                               2144                 :                :  * freesubre - free a subRE subtree
                               2145                 :                :  *
                               2146                 :                :  * This frees child node(s) of the given subRE too,
                               2147                 :                :  * but not its siblings.
                               2148                 :                :  */
                               2149                 :                : static void
 2489                          2150                 :           9254 : freesubre(struct vars *v,       /* might be NULL */
                               2151                 :                :           struct subre *sr)
                               2152                 :                : {
 7739                          2153         [ +  + ]:           9254 :     if (sr == NULL)
                               2154                 :              7 :         return;
                               2155                 :                : 
 1149                          2156         [ +  + ]:           9247 :     if (sr->child != NULL)
                               2157                 :            696 :         freesubreandsiblings(v, sr->child);
                               2158                 :                : 
 7739                          2159                 :           9247 :     freesrnode(v, sr);
                               2160                 :                : }
                               2161                 :                : 
                               2162                 :                : /*
                               2163                 :                :  * freesubreandsiblings - free a subRE subtree
                               2164                 :                :  *
                               2165                 :                :  * This frees child node(s) of the given subRE too,
                               2166                 :                :  * as well as any following siblings.
                               2167                 :                :  */
                               2168                 :                : static void
 1149                          2169                 :           3995 : freesubreandsiblings(struct vars *v,    /* might be NULL */
                               2170                 :                :                      struct subre *sr)
                               2171                 :                : {
                               2172         [ +  + ]:          11774 :     while (sr != NULL)
                               2173                 :                :     {
                               2174                 :           7779 :         struct subre *next = sr->sibling;
                               2175                 :                : 
                               2176                 :           7779 :         freesubre(v, sr);
                               2177                 :           7779 :         sr = next;
                               2178                 :                :     }
                               2179                 :           3995 : }
                               2180                 :                : 
                               2181                 :                : /*
                               2182                 :                :  * freesrnode - free one node in a subRE subtree
                               2183                 :                :  */
                               2184                 :                : static void
 2489                          2185                 :          15805 : freesrnode(struct vars *v,      /* might be NULL */
                               2186                 :                :            struct subre *sr)
                               2187                 :                : {
 7739                          2188         [ -  + ]:          15805 :     if (sr == NULL)
10141 scrappy@hub.org          2189                 :UBC           0 :         return;
                               2190                 :                : 
 7739 tgl@sss.pgh.pa.us        2191         [ +  + ]:CBC       15805 :     if (!NULLCNFA(sr->cnfa))
                               2192                 :           1478 :         freecnfa(&sr->cnfa);
  981                          2193                 :          15805 :     sr->flags = 0;               /* in particular, not INUSE */
                               2194                 :          15805 :     sr->child = sr->sibling = NULL;
                               2195                 :          15805 :     sr->begin = sr->end = NULL;
                               2196                 :                : 
 3558                          2197   [ +  +  +  + ]:          15805 :     if (v != NULL && v->treechain != NULL)
                               2198                 :                :     {
                               2199                 :                :         /* we're still parsing, maybe we can reuse the subre */
 1149                          2200                 :          14324 :         sr->child = v->treefree;
 7739                          2201                 :          14324 :         v->treefree = sr;
                               2202                 :                :     }
                               2203                 :                :     else
                               2204                 :           1481 :         FREE(sr);
                               2205                 :                : }
                               2206                 :                : 
                               2207                 :                : /*
                               2208                 :                :  * removecaptures - remove unnecessary capture subREs
                               2209                 :                :  *
                               2210                 :                :  * If the caller said that it doesn't care about subexpression match data,
                               2211                 :                :  * we may delete the "capture" markers on subREs that are not referenced
                               2212                 :                :  * by any backrefs, and then simplify anything that's become non-messy.
                               2213                 :                :  * Call this only if REG_NOSUB flag is set.
                               2214                 :                :  */
                               2215                 :                : static void
  979                          2216                 :           9118 : removecaptures(struct vars *v,
                               2217                 :                :                struct subre *t)
                               2218                 :                : {
                               2219                 :                :     struct subre *t2;
                               2220                 :                : 
                               2221         [ -  + ]:           9118 :     assert(t != NULL);
                               2222                 :                : 
                               2223                 :                :     /*
                               2224                 :                :      * If this isn't itself a backref target, clear capno and tentatively
                               2225                 :                :      * clear CAP flag.
                               2226                 :                :      */
                               2227         [ +  + ]:           9118 :     if (!(t->flags & BRUSE))
                               2228                 :                :     {
                               2229                 :           9081 :         t->capno = 0;
                               2230                 :           9081 :         t->flags &= ~CAP;
                               2231                 :                :     }
                               2232                 :                : 
                               2233                 :                :     /* Now recurse to children */
                               2234         [ +  + ]:          15696 :     for (t2 = t->child; t2 != NULL; t2 = t2->sibling)
                               2235                 :                :     {
                               2236                 :           6578 :         removecaptures(v, t2);
                               2237                 :                :         /* Propagate child CAP flag back up, if it's still set */
                               2238         [ +  + ]:           6578 :         if (t2->flags & CAP)
                               2239                 :             74 :             t->flags |= CAP;
                               2240                 :                :     }
                               2241                 :                : 
                               2242                 :                :     /*
                               2243                 :                :      * If t now contains neither captures nor backrefs, there's no longer any
                               2244                 :                :      * need to care where its sub-match boundaries are, so we can reduce it to
                               2245                 :                :      * a simple DFA node.  (Note in particular that MIXED child greediness is
                               2246                 :                :      * not a hindrance here, so we don't use the MESSY() macro.)
                               2247                 :                :      */
                               2248         [ +  + ]:           9118 :     if ((t->flags & (CAP | BACKR)) == 0)
                               2249                 :                :     {
                               2250         [ +  + ]:           8921 :         if (t->child)
                               2251                 :           3198 :             freesubreandsiblings(v, t->child);
                               2252                 :           8921 :         t->child = NULL;
                               2253                 :           8921 :         t->op = '=';
                               2254                 :           8921 :         t->flags &= ~MIXED;
                               2255                 :                :     }
10141 scrappy@hub.org          2256                 :           9118 : }
                               2257                 :                : 
                               2258                 :                : /*
                               2259                 :                :  * numst - number tree nodes (assigning "id" indexes)
                               2260                 :                :  */
                               2261                 :                : static int                      /* next number */
 2489 tgl@sss.pgh.pa.us        2262                 :           5355 : numst(struct subre *t,
                               2263                 :                :       int start)                /* starting point for subtree numbers */
                               2264                 :                : {
                               2265                 :                :     int         i;
                               2266                 :                :     struct subre *t2;
                               2267                 :                : 
 7739                          2268         [ -  + ]:           5355 :     assert(t != NULL);
                               2269                 :                : 
                               2270                 :           5355 :     i = start;
 1149                          2271                 :           5355 :     t->id = i++;
                               2272         [ +  + ]:           7219 :     for (t2 = t->child; t2 != NULL; t2 = t2->sibling)
                               2273                 :           1864 :         i = numst(t2, i);
 7739                          2274                 :           5355 :     return i;
                               2275                 :                : }
                               2276                 :                : 
                               2277                 :                : /*
                               2278                 :                :  * markst - mark tree nodes as INUSE
                               2279                 :                :  *
                               2280                 :                :  * Note: this is a great deal more subtle than it looks.  During initial
                               2281                 :                :  * parsing of a regex, all subres are linked into the treechain list;
                               2282                 :                :  * discarded ones are also linked into the treefree list for possible reuse.
                               2283                 :                :  * After we are done creating all subres required for a regex, we run markst()
                               2284                 :                :  * then cleanst(), which results in discarding all subres not reachable from
                               2285                 :                :  * v->tree.  We then clear v->treechain, indicating that subres must be found
                               2286                 :                :  * by descending from v->tree.  This changes the behavior of freesubre(): it
                               2287                 :                :  * will henceforth FREE() unwanted subres rather than sticking them into the
                               2288                 :                :  * treefree list.  (Doing that any earlier would result in dangling links in
                               2289                 :                :  * the treechain list.)  This all means that freev() will clean up correctly
                               2290                 :                :  * if invoked before or after markst()+cleanst(); but it would not work if
                               2291                 :                :  * called partway through this state conversion, so we mustn't error out
                               2292                 :                :  * in or between these two functions.
                               2293                 :                :  */
                               2294                 :                : static void
 2489                          2295                 :           5355 : markst(struct subre *t)
                               2296                 :                : {
                               2297                 :                :     struct subre *t2;
                               2298                 :                : 
 7739                          2299         [ -  + ]:           5355 :     assert(t != NULL);
                               2300                 :                : 
                               2301                 :           5355 :     t->flags |= INUSE;
 1149                          2302         [ +  + ]:           7219 :     for (t2 = t->child; t2 != NULL; t2 = t2->sibling)
                               2303                 :           1864 :         markst(t2);
10141 scrappy@hub.org          2304                 :           5355 : }
                               2305                 :                : 
                               2306                 :                : /*
                               2307                 :                :  * cleanst - free any tree nodes not marked INUSE
                               2308                 :                :  */
                               2309                 :                : static void
 2489 tgl@sss.pgh.pa.us        2310                 :           3603 : cleanst(struct vars *v)
                               2311                 :                : {
                               2312                 :                :     struct subre *t;
                               2313                 :                :     struct subre *next;
                               2314                 :                : 
 7559 bruce@momjian.us         2315         [ +  + ]:          20773 :     for (t = v->treechain; t != NULL; t = next)
                               2316                 :                :     {
 7739 tgl@sss.pgh.pa.us        2317                 :          17170 :         next = t->chain;
 7559 bruce@momjian.us         2318         [ +  + ]:          17170 :         if (!(t->flags & INUSE))
 7739 tgl@sss.pgh.pa.us        2319                 :          11815 :             FREE(t);
                               2320                 :                :     }
                               2321                 :           3603 :     v->treechain = NULL;
 7559 bruce@momjian.us         2322                 :           3603 :     v->treefree = NULL;          /* just on general principles */
10141 scrappy@hub.org          2323                 :           3603 : }
                               2324                 :                : 
                               2325                 :                : /*
                               2326                 :                :  * nfatree - turn a subRE subtree into a tree of compacted NFAs
                               2327                 :                :  */
                               2328                 :                : static long                     /* optimize results from top node */
 2489 tgl@sss.pgh.pa.us        2329                 :           5355 : nfatree(struct vars *v,
                               2330                 :                :         struct subre *t,
                               2331                 :                :         FILE *f)                /* for debug output */
                               2332                 :                : {
                               2333                 :                :     struct subre *t2;
                               2334                 :                : 
 7739                          2335   [ +  -  -  + ]:           5355 :     assert(t != NULL && t->begin != NULL);
                               2336                 :                : 
 1149                          2337         [ +  + ]:           7219 :     for (t2 = t->child; t2 != NULL; t2 = t2->sibling)
                               2338                 :           1864 :         (DISCARD) nfatree(v, t2, f);
                               2339                 :                : 
 3089                          2340                 :           5355 :     return nfanode(v, t, 0, f);
                               2341                 :                : }
                               2342                 :                : 
                               2343                 :                : /*
                               2344                 :                :  * nfanode - do one NFA for nfatree or lacons
                               2345                 :                :  *
                               2346                 :                :  * If converttosearch is true, apply makesearch() to the NFA.
                               2347                 :                :  */
                               2348                 :                : static long                     /* optimize results */
 2489                          2349                 :           5398 : nfanode(struct vars *v,
                               2350                 :                :         struct subre *t,
                               2351                 :                :         int converttosearch,
                               2352                 :                :         FILE *f)                /* for debug output */
                               2353                 :                : {
                               2354                 :                :     struct nfa *nfa;
 7559 bruce@momjian.us         2355                 :           5398 :     long        ret = 0;
                               2356                 :                : 
 7739 tgl@sss.pgh.pa.us        2357         [ -  + ]:           5398 :     assert(t->begin != NULL);
                               2358                 :                : 
                               2359                 :                : #ifdef REG_DEBUG
                               2360                 :                :     if (f != NULL)
                               2361                 :                :     {
                               2362                 :                :         char        idbuf[50];
                               2363                 :                : 
                               2364                 :                :         fprintf(f, "\n\n\n========= TREE NODE %s ==========\n",
                               2365                 :                :                 stid(t, idbuf, sizeof(idbuf)));
                               2366                 :                :     }
                               2367                 :                : #endif
                               2368                 :           5398 :     nfa = newnfa(v, v->cm, v->nfa);
                               2369         [ -  + ]:           5398 :     NOERRZ();
                               2370                 :           5398 :     dupnfa(nfa, t->begin, t->end, nfa->init, nfa->final);
 7559 bruce@momjian.us         2371         [ +  - ]:           5398 :     if (!ISERR())
 7739 tgl@sss.pgh.pa.us        2372                 :           5398 :         specialcolors(nfa);
 3089                          2373         [ +  - ]:           5398 :     if (!ISERR())
 7739                          2374                 :           5398 :         ret = optimize(nfa, f);
 3089                          2375   [ +  +  +  - ]:           5398 :     if (converttosearch && !ISERR())
                               2376                 :              9 :         makesearch(v, nfa);
 7739                          2377         [ +  + ]:           5398 :     if (!ISERR())
                               2378                 :           5395 :         compact(nfa, &t->cnfa);
                               2379                 :                : 
                               2380                 :           5398 :     freenfa(nfa);
                               2381                 :           5398 :     return ret;
                               2382                 :                : }
                               2383                 :                : 
                               2384                 :                : /*
                               2385                 :                :  * newlacon - allocate a lookaround-constraint subRE
                               2386                 :                :  */
                               2387                 :                : static int                      /* lacon number */
 2489                          2388                 :             43 : newlacon(struct vars *v,
                               2389                 :                :          struct state *begin,
                               2390                 :                :          struct state *end,
                               2391                 :                :          int latype)
                               2392                 :                : {
                               2393                 :                :     int         n;
                               2394                 :                :     struct subre *newlacons;
                               2395                 :                :     struct subre *sub;
                               2396                 :                : 
 7559 bruce@momjian.us         2397         [ +  + ]:             43 :     if (v->nlacons == 0)
                               2398                 :                :     {
                               2399                 :             29 :         n = 1;                  /* skip 0th */
 3558 tgl@sss.pgh.pa.us        2400                 :             29 :         newlacons = (struct subre *) MALLOC(2 * sizeof(struct subre));
                               2401                 :                :     }
                               2402                 :                :     else
                               2403                 :                :     {
                               2404                 :             14 :         n = v->nlacons;
                               2405                 :             14 :         newlacons = (struct subre *) REALLOC(v->lacons,
                               2406                 :                :                                              (n + 1) * sizeof(struct subre));
                               2407                 :                :     }
                               2408         [ -  + ]:             43 :     if (newlacons == NULL)
                               2409                 :                :     {
 7739 tgl@sss.pgh.pa.us        2410         [ #  # ]:UBC           0 :         ERR(REG_ESPACE);
                               2411                 :              0 :         return 0;
                               2412                 :                :     }
 3558 tgl@sss.pgh.pa.us        2413                 :CBC          43 :     v->lacons = newlacons;
                               2414                 :             43 :     v->nlacons = n + 1;
 7739                          2415                 :             43 :     sub = &v->lacons[n];
                               2416                 :             43 :     sub->begin = begin;
                               2417                 :             43 :     sub->end = end;
 1149                          2418                 :             43 :     sub->latype = latype;
 7739                          2419                 :             43 :     ZAPCNFA(sub->cnfa);
                               2420                 :             43 :     return n;
                               2421                 :                : }
                               2422                 :                : 
                               2423                 :                : /*
                               2424                 :                :  * freelacons - free lookaround-constraint subRE vector
                               2425                 :                :  */
                               2426                 :                : static void
 2489                          2427                 :             10 : freelacons(struct subre *subs,
                               2428                 :                :            int n)
                               2429                 :                : {
                               2430                 :                :     struct subre *sub;
                               2431                 :                :     int         i;
                               2432                 :                : 
 7739                          2433         [ -  + ]:             10 :     assert(n > 0);
                               2434         [ +  + ]:             28 :     for (sub = subs + 1, i = n - 1; i > 0; sub++, i--)   /* no 0th */
                               2435         [ +  - ]:             18 :         if (!NULLCNFA(sub->cnfa))
                               2436                 :             18 :             freecnfa(&sub->cnfa);
                               2437                 :             10 :     FREE(subs);
 9527 scrappy@hub.org          2438                 :             10 : }
                               2439                 :                : 
                               2440                 :                : /*
                               2441                 :                :  * rfree - free a whole RE (insides of regfree)
                               2442                 :                :  */
                               2443                 :                : static void
 7739 tgl@sss.pgh.pa.us        2444                 :            770 : rfree(regex_t *re)
                               2445                 :                : {
                               2446                 :                :     struct guts *g;
                               2447                 :                : 
                               2448   [ +  -  -  + ]:            770 :     if (re == NULL || re->re_magic != REMAGIC)
 7739 tgl@sss.pgh.pa.us        2449                 :UBC           0 :         return;
                               2450                 :                : 
 7559 bruce@momjian.us         2451                 :CBC         770 :     re->re_magic = 0;            /* invalidate RE */
                               2452                 :            770 :     g = (struct guts *) re->re_guts;
 7739 tgl@sss.pgh.pa.us        2453                 :            770 :     re->re_guts = NULL;
                               2454                 :            770 :     re->re_fns = NULL;
 4291                          2455         [ +  - ]:            770 :     if (g != NULL)
                               2456                 :                :     {
                               2457                 :            770 :         g->magic = 0;
                               2458                 :            770 :         freecm(&g->cmap);
                               2459         [ +  + ]:            770 :         if (g->tree != NULL)
                               2460                 :            648 :             freesubre((struct vars *) NULL, g->tree);
                               2461         [ +  + ]:            770 :         if (g->lacons != NULL)
                               2462                 :             10 :             freelacons(g->lacons, g->nlacons);
                               2463         [ +  + ]:            770 :         if (!NULLCNFA(g->search))
                               2464                 :            648 :             freecnfa(&g->search);
                               2465                 :            770 :         FREE(g);
                               2466                 :                :     }
                               2467                 :                : }
                               2468                 :                : 
                               2469                 :                : /*
                               2470                 :                :  * rstacktoodeep - check for stack getting dangerously deep
                               2471                 :                :  *
                               2472                 :                :  * Return nonzero to fail the operation with error code REG_ETOOBIG,
                               2473                 :                :  * zero to keep going
                               2474                 :                :  *
                               2475                 :                :  * The current implementation is Postgres-specific.  If we ever get around
                               2476                 :                :  * to splitting the regex code out as a standalone library, there will need
                               2477                 :                :  * to be some API to let applications define a callback function for this.
                               2478                 :                :  */
                               2479                 :                : static int
 3117                          2480                 :       10840225 : rstacktoodeep(void)
                               2481                 :                : {
                               2482                 :       10840225 :     return stack_is_too_deep();
                               2483                 :                : }
                               2484                 :                : 
                               2485                 :                : #ifdef REG_DEBUG
                               2486                 :                : 
                               2487                 :                : /*
                               2488                 :                :  * dump - dump an RE in human-readable form
                               2489                 :                :  */
                               2490                 :                : static void
                               2491                 :                : dump(regex_t *re,
                               2492                 :                :      FILE *f)
                               2493                 :                : {
                               2494                 :                :     struct guts *g;
                               2495                 :                :     int         i;
                               2496                 :                : 
                               2497                 :                :     if (re->re_magic != REMAGIC)
                               2498                 :                :         fprintf(f, "bad magic number (0x%x not 0x%x)\n", re->re_magic,
                               2499                 :                :                 REMAGIC);
                               2500                 :                :     if (re->re_guts == NULL)
                               2501                 :                :     {
                               2502                 :                :         fprintf(f, "NULL guts!!!\n");
                               2503                 :                :         return;
                               2504                 :                :     }
                               2505                 :                :     g = (struct guts *) re->re_guts;
                               2506                 :                :     if (g->magic != GUTSMAGIC)
                               2507                 :                :         fprintf(f, "bad guts magic number (0x%x not 0x%x)\n", g->magic,
                               2508                 :                :                 GUTSMAGIC);
                               2509                 :                : 
                               2510                 :                :     fprintf(f, "\n\n\n========= DUMP ==========\n");
                               2511                 :                :     fprintf(f, "nsub %d, info 0%lo, csize %d, ntree %d\n",
                               2512                 :                :             (int) re->re_nsub, re->re_info, re->re_csize, g->ntree);
                               2513                 :                : 
                               2514                 :                :     dumpcolors(&g->cmap, f);
                               2515                 :                :     if (!NULLCNFA(g->search))
                               2516                 :                :     {
                               2517                 :                :         fprintf(f, "\nsearch:\n");
                               2518                 :                :         dumpcnfa(&g->search, f);
                               2519                 :                :     }
                               2520                 :                :     for (i = 1; i < g->nlacons; i++)
                               2521                 :                :     {
                               2522                 :                :         struct subre *lasub = &g->lacons[i];
                               2523                 :                :         const char *latype;
                               2524                 :                : 
                               2525                 :                :         switch (lasub->latype)
                               2526                 :                :         {
                               2527                 :                :             case LATYPE_AHEAD_POS:
                               2528                 :                :                 latype = "positive lookahead";
                               2529                 :                :                 break;
                               2530                 :                :             case LATYPE_AHEAD_NEG:
                               2531                 :                :                 latype = "negative lookahead";
                               2532                 :                :                 break;
                               2533                 :                :             case LATYPE_BEHIND_POS:
                               2534                 :                :                 latype = "positive lookbehind";
                               2535                 :                :                 break;
                               2536                 :                :             case LATYPE_BEHIND_NEG:
                               2537                 :                :                 latype = "negative lookbehind";
                               2538                 :                :                 break;
                               2539                 :                :             default:
                               2540                 :                :                 latype = "???";
                               2541                 :                :                 break;
                               2542                 :                :         }
                               2543                 :                :         fprintf(f, "\nla%d (%s):\n", i, latype);
                               2544                 :                :         dumpcnfa(&lasub->cnfa, f);
                               2545                 :                :     }
                               2546                 :                :     fprintf(f, "\n");
                               2547                 :                :     dumpst(g->tree, f, 0);
                               2548                 :                : }
                               2549                 :                : 
                               2550                 :                : /*
                               2551                 :                :  * dumpst - dump a subRE tree
                               2552                 :                :  */
                               2553                 :                : static void
                               2554                 :                : dumpst(struct subre *t,
                               2555                 :                :        FILE *f,
                               2556                 :                :        int nfapresent)          /* is the original NFA still around? */
                               2557                 :                : {
                               2558                 :                :     if (t == NULL)
                               2559                 :                :         fprintf(f, "null tree\n");
                               2560                 :                :     else
                               2561                 :                :         stdump(t, f, nfapresent);
                               2562                 :                :     fflush(f);
                               2563                 :                : }
                               2564                 :                : 
                               2565                 :                : /*
                               2566                 :                :  * stdump - recursive guts of dumpst
                               2567                 :                :  */
                               2568                 :                : static void
                               2569                 :                : stdump(struct subre *t,
                               2570                 :                :        FILE *f,
                               2571                 :                :        int nfapresent)          /* is the original NFA still around? */
                               2572                 :                : {
                               2573                 :                :     char        idbuf[50];
                               2574                 :                :     struct subre *t2;
                               2575                 :                : 
                               2576                 :                :     fprintf(f, "%s. `%c'", stid(t, idbuf, sizeof(idbuf)), t->op);
                               2577                 :                :     if (t->flags & LONGER)
                               2578                 :                :         fprintf(f, " longest");
                               2579                 :                :     if (t->flags & SHORTER)
                               2580                 :                :         fprintf(f, " shortest");
                               2581                 :                :     if (t->flags & MIXED)
                               2582                 :                :         fprintf(f, " hasmixed");
                               2583                 :                :     if (t->flags & CAP)
                               2584                 :                :         fprintf(f, " hascapture");
                               2585                 :                :     if (t->flags & BACKR)
                               2586                 :                :         fprintf(f, " hasbackref");
                               2587                 :                :     if (t->flags & BRUSE)
                               2588                 :                :         fprintf(f, " isreferenced");
                               2589                 :                :     if (!(t->flags & INUSE))
                               2590                 :                :         fprintf(f, " UNUSED");
                               2591                 :                :     if (t->latype != (char) -1)
                               2592                 :                :         fprintf(f, " latype(%d)", t->latype);
                               2593                 :                :     if (t->capno != 0)
                               2594                 :                :         fprintf(f, " capture(%d)", t->capno);
                               2595                 :                :     if (t->backno != 0)
                               2596                 :                :         fprintf(f, " backref(%d)", t->backno);
                               2597                 :                :     if (t->min != 1 || t->max != 1)
                               2598                 :                :     {
                               2599                 :                :         fprintf(f, " {%d,", t->min);
                               2600                 :                :         if (t->max != DUPINF)
                               2601                 :                :             fprintf(f, "%d", t->max);
                               2602                 :                :         fprintf(f, "}");
                               2603                 :                :     }
                               2604                 :                :     if (nfapresent)
                               2605                 :                :         fprintf(f, " %ld-%ld", (long) t->begin->no, (long) t->end->no);
                               2606                 :                :     if (t->child != NULL)
                               2607                 :                :         fprintf(f, " C:%s", stid(t->child, idbuf, sizeof(idbuf)));
                               2608                 :                :     /* printing second child isn't necessary, but it is often helpful */
                               2609                 :                :     if (t->child != NULL && t->child->sibling != NULL)
                               2610                 :                :         fprintf(f, " C2:%s", stid(t->child->sibling, idbuf, sizeof(idbuf)));
                               2611                 :                :     if (t->sibling != NULL)
                               2612                 :                :         fprintf(f, " S:%s", stid(t->sibling, idbuf, sizeof(idbuf)));
                               2613                 :                :     if (!NULLCNFA(t->cnfa))
                               2614                 :                :     {
                               2615                 :                :         fprintf(f, "\n");
                               2616                 :                :         dumpcnfa(&t->cnfa, f);
                               2617                 :                :     }
                               2618                 :                :     fprintf(f, "\n");
                               2619                 :                :     for (t2 = t->child; t2 != NULL; t2 = t2->sibling)
                               2620                 :                :         stdump(t2, f, nfapresent);
                               2621                 :                : }
                               2622                 :                : 
                               2623                 :                : /*
                               2624                 :                :  * stid - identify a subtree node for dumping
                               2625                 :                :  */
                               2626                 :                : static const char *             /* points to buf or constant string */
                               2627                 :                : stid(struct subre *t,
                               2628                 :                :      char *buf,
                               2629                 :                :      size_t bufsize)
                               2630                 :                : {
                               2631                 :                :     /* big enough for hex int or decimal t->id? */
                               2632                 :                :     if (bufsize < sizeof(void *) * 2 + 3 || bufsize < sizeof(t->id) * 3 + 1)
                               2633                 :                :         return "unable";
                               2634                 :                :     if (t->id != 0)
                               2635                 :                :         sprintf(buf, "%d", t->id);
                               2636                 :                :     else
                               2637                 :                :         sprintf(buf, "%p", t);
                               2638                 :                :     return buf;
                               2639                 :                : }
                               2640                 :                : #endif                          /* REG_DEBUG */
                               2641                 :                : 
                               2642                 :                : 
                               2643                 :                : #include "regc_lex.c"
                               2644                 :                : #include "regc_color.c"
                               2645                 :                : #include "regc_nfa.c"
                               2646                 :                : #include "regc_cvec.c"
                               2647                 :                : #include "regc_pg_locale.c"
                               2648                 :                : #include "regc_locale.c"
        

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