LCOV - code coverage report
Current view: top level - src/backend/regex - regc_lex.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 48.2 % 469 226
Test Date: 2026-01-26 10:56:24 Functions: 88.9 % 9 8
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 37.5 % 461 173

             Branch data     Line data    Source code
       1                 :             : /*
       2                 :             :  * lexical analyzer
       3                 :             :  * This file is #included by regcomp.c.
       4                 :             :  *
       5                 :             :  * Copyright (c) 1998, 1999 Henry Spencer.  All rights reserved.
       6                 :             :  *
       7                 :             :  * Development of this software was funded, in part, by Cray Research Inc.,
       8                 :             :  * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
       9                 :             :  * Corporation, none of whom are responsible for the results.  The author
      10                 :             :  * thanks all of them.
      11                 :             :  *
      12                 :             :  * Redistribution and use in source and binary forms -- with or without
      13                 :             :  * modification -- are permitted for any purpose, provided that
      14                 :             :  * redistributions in source form retain this entire copyright notice and
      15                 :             :  * indicate the origin and nature of any modifications.
      16                 :             :  *
      17                 :             :  * I'd appreciate being given credit for this package in the documentation
      18                 :             :  * of software which uses it, but that is not a requirement.
      19                 :             :  *
      20                 :             :  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
      21                 :             :  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
      22                 :             :  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
      23                 :             :  * HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
      24                 :             :  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
      25                 :             :  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
      26                 :             :  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
      27                 :             :  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      28                 :             :  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
      29                 :             :  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      30                 :             :  *
      31                 :             :  * src/backend/regex/regc_lex.c
      32                 :             :  *
      33                 :             :  */
      34                 :             : 
      35                 :             : /* scanning macros (know about v) */
      36                 :             : #define ATEOS()         (v->now >= v->stop)
      37                 :             : #define HAVE(n)         (v->stop - v->now >= (n))
      38                 :             : #define NEXT1(c)        (!ATEOS() && *v->now == CHR(c))
      39                 :             : #define NEXT2(a,b)      (HAVE(2) && *v->now == CHR(a) && *(v->now+1) == CHR(b))
      40                 :             : #define NEXT3(a,b,c)    (HAVE(3) && *v->now == CHR(a) && \
      41                 :             :                                                 *(v->now+1) == CHR(b) && \
      42                 :             :                                                 *(v->now+2) == CHR(c))
      43                 :             : #define SET(c)          (v->nexttype = (c))
      44                 :             : #define SETV(c, n)      (v->nexttype = (c), v->nextvalue = (n))
      45                 :             : #define RET(c)          return (SET(c), 1)
      46                 :             : #define RETV(c, n)      return (SETV(c, n), 1)
      47                 :             : #define FAILW(e)        return (ERR(e), 0)      /* ERR does SET(EOS) */
      48                 :             : #define LASTTYPE(t) (v->lasttype == (t))
      49                 :             : 
      50                 :             : /* lexical contexts */
      51                 :             : #define L_ERE   1                               /* mainline ERE/ARE */
      52                 :             : #define L_BRE   2                               /* mainline BRE */
      53                 :             : #define L_Q 3                                   /* REG_QUOTE */
      54                 :             : #define L_EBND  4                               /* ERE/ARE bound */
      55                 :             : #define L_BBND  5                               /* BRE bound */
      56                 :             : #define L_BRACK 6                               /* brackets */
      57                 :             : #define L_CEL   7                               /* collating element */
      58                 :             : #define L_ECL   8                               /* equivalence class */
      59                 :             : #define L_CCL   9                               /* character class */
      60                 :             : #define INTOCON(c)      (v->lexcon = (c))
      61                 :             : #define INCON(con)      (v->lexcon == (con))
      62                 :             : 
      63                 :             : /* construct pointer past end of chr array */
      64                 :             : #define ENDOF(array)    ((array) + sizeof(array)/sizeof(chr))
      65                 :             : 
      66                 :             : /*
      67                 :             :  * lexstart - set up lexical stuff, scan leading options
      68                 :             :  */
      69                 :             : static void
      70                 :         812 : lexstart(struct vars *v)
      71                 :             : {
      72                 :         812 :         prefixes(v);                            /* may turn on new type bits etc. */
      73         [ -  + ]:         812 :         NOERR();
      74                 :             : 
      75         [ +  + ]:         812 :         if (v->cflags & REG_QUOTE)
      76                 :             :         {
      77         [ +  - ]:          13 :                 assert(!(v->cflags & (REG_ADVANCED | REG_EXPANDED | REG_NEWLINE)));
      78                 :          13 :                 INTOCON(L_Q);
      79                 :          13 :         }
      80         [ +  - ]:         799 :         else if (v->cflags & REG_EXTENDED)
      81                 :             :         {
      82         [ +  - ]:         799 :                 assert(!(v->cflags & REG_QUOTE));
      83                 :         799 :                 INTOCON(L_ERE);
      84                 :         799 :         }
      85                 :             :         else
      86                 :             :         {
      87         [ #  # ]:           0 :                 assert(!(v->cflags & (REG_QUOTE | REG_ADVF)));
      88                 :           0 :                 INTOCON(L_BRE);
      89                 :             :         }
      90                 :             : 
      91                 :         812 :         v->nexttype = EMPTY;         /* remember we were at the start */
      92                 :         812 :         next(v);                                        /* set up the first token */
      93                 :         812 : }
      94                 :             : 
      95                 :             : /*
      96                 :             :  * prefixes - implement various special prefixes
      97                 :             :  */
      98                 :             : static void
      99                 :         812 : prefixes(struct vars *v)
     100                 :             : {
     101                 :             :         /* literal string doesn't get any of this stuff */
     102         [ +  + ]:         812 :         if (v->cflags & REG_QUOTE)
     103                 :          13 :                 return;
     104                 :             : 
     105                 :             :         /* initial "***" gets special things */
     106   [ +  +  +  -  :         799 :         if (HAVE(4) && NEXT3('*', '*', '*'))
          -  +  #  #  #  
                      # ]
     107   [ #  #  #  # ]:           0 :                 switch (*(v->now + 3))
     108                 :             :                 {
     109                 :             :                         case CHR('?'):          /* "***?" error, msg shows version */
     110         [ #  # ]:           0 :                                 ERR(REG_BADPAT);
     111                 :           0 :                                 return;                 /* proceed no further */
     112                 :             :                                 break;
     113                 :             :                         case CHR('='):          /* "***=" shifts to literal string */
     114                 :           0 :                                 NOTE(REG_UNONPOSIX);
     115                 :           0 :                                 v->cflags |= REG_QUOTE;
     116                 :           0 :                                 v->cflags &= ~(REG_ADVANCED | REG_EXPANDED | REG_NEWLINE);
     117                 :           0 :                                 v->now += 4;
     118                 :           0 :                                 return;                 /* and there can be no more prefixes */
     119                 :             :                                 break;
     120                 :             :                         case CHR(':'):          /* "***:" shifts to AREs */
     121                 :           0 :                                 NOTE(REG_UNONPOSIX);
     122                 :           0 :                                 v->cflags |= REG_ADVANCED;
     123                 :           0 :                                 v->now += 4;
     124                 :           0 :                                 break;
     125                 :             :                         default:                        /* otherwise *** is just an error */
     126         [ #  # ]:           0 :                                 ERR(REG_BADRPT);
     127                 :           0 :                                 return;
     128                 :             :                                 break;
     129                 :           0 :                 }
     130                 :             : 
     131                 :             :         /* BREs and EREs don't get embedded options */
     132         [ +  - ]:         799 :         if ((v->cflags & REG_ADVANCED) != REG_ADVANCED)
     133                 :           0 :                 return;
     134                 :             : 
     135                 :             :         /* embedded options (AREs only) */
     136   [ +  +  +  -  :         799 :         if (HAVE(3) && NEXT2('(', '?') && iscalpha(*(v->now + 2)))
          +  +  +  +  +  
                      - ]
     137                 :             :         {
     138                 :           0 :                 NOTE(REG_UNONPOSIX);
     139                 :           0 :                 v->now += 2;
     140   [ #  #  #  # ]:           0 :                 for (; !ATEOS() && iscalpha(*v->now); v->now++)
     141   [ #  #  #  #  :           0 :                         switch (*v->now)
          #  #  #  #  #  
                #  #  # ]
     142                 :             :                         {
     143                 :             :                                 case CHR('b'):  /* BREs (but why???) */
     144                 :           0 :                                         v->cflags &= ~(REG_ADVANCED | REG_QUOTE);
     145                 :           0 :                                         break;
     146                 :             :                                 case CHR('c'):  /* case sensitive */
     147                 :           0 :                                         v->cflags &= ~REG_ICASE;
     148                 :           0 :                                         break;
     149                 :             :                                 case CHR('e'):  /* plain EREs */
     150                 :           0 :                                         v->cflags |= REG_EXTENDED;
     151                 :           0 :                                         v->cflags &= ~(REG_ADVF | REG_QUOTE);
     152                 :           0 :                                         break;
     153                 :             :                                 case CHR('i'):  /* case insensitive */
     154                 :           0 :                                         v->cflags |= REG_ICASE;
     155                 :           0 :                                         break;
     156                 :             :                                 case CHR('m'):  /* Perloid synonym for n */
     157                 :             :                                 case CHR('n'):  /* \n affects ^ $ . [^ */
     158                 :           0 :                                         v->cflags |= REG_NEWLINE;
     159                 :           0 :                                         break;
     160                 :             :                                 case CHR('p'):  /* ~Perl, \n affects . [^ */
     161                 :           0 :                                         v->cflags |= REG_NLSTOP;
     162                 :           0 :                                         v->cflags &= ~REG_NLANCH;
     163                 :           0 :                                         break;
     164                 :             :                                 case CHR('q'):  /* literal string */
     165                 :           0 :                                         v->cflags |= REG_QUOTE;
     166                 :           0 :                                         v->cflags &= ~REG_ADVANCED;
     167                 :           0 :                                         break;
     168                 :             :                                 case CHR('s'):  /* single line, \n ordinary */
     169                 :           0 :                                         v->cflags &= ~REG_NEWLINE;
     170                 :           0 :                                         break;
     171                 :             :                                 case CHR('t'):  /* tight syntax */
     172                 :           0 :                                         v->cflags &= ~REG_EXPANDED;
     173                 :           0 :                                         break;
     174                 :             :                                 case CHR('w'):  /* weird, \n affects ^ $ only */
     175                 :           0 :                                         v->cflags &= ~REG_NLSTOP;
     176                 :           0 :                                         v->cflags |= REG_NLANCH;
     177                 :           0 :                                         break;
     178                 :             :                                 case CHR('x'):  /* expanded syntax */
     179                 :           0 :                                         v->cflags |= REG_EXPANDED;
     180                 :           0 :                                         break;
     181                 :             :                                 default:
     182         [ #  # ]:           0 :                                         ERR(REG_BADOPT);
     183                 :           0 :                                         return;
     184                 :           0 :                         }
     185   [ #  #  #  # ]:           0 :                 if (!NEXT1(')'))
     186                 :             :                 {
     187         [ #  # ]:           0 :                         ERR(REG_BADOPT);
     188                 :           0 :                         return;
     189                 :             :                 }
     190                 :           0 :                 v->now++;
     191         [ #  # ]:           0 :                 if (v->cflags & REG_QUOTE)
     192                 :           0 :                         v->cflags &= ~(REG_EXPANDED | REG_NEWLINE);
     193                 :           0 :         }
     194                 :         812 : }
     195                 :             : 
     196                 :             : /*
     197                 :             :  * next - get next token
     198                 :             :  */
     199                 :             : static int                                              /* 1 normal, 0 failure */
     200                 :       18218 : next(struct vars *v)
     201                 :             : {
     202                 :       18218 :         chr                     c;
     203                 :             : 
     204                 :             : next_restart:                                   /* loop here after eating a comment */
     205                 :             : 
     206                 :             :         /* errors yield an infinite sequence of failures */
     207         [ +  + ]:       18218 :         if (ISERR())
     208                 :           3 :                 return 0;                               /* the error has set nexttype to EOS */
     209                 :             : 
     210                 :             :         /* remember flavor of last token */
     211                 :       18215 :         v->lasttype = v->nexttype;
     212                 :             : 
     213                 :             :         /* REG_BOSONLY */
     214   [ +  +  +  - ]:       18215 :         if (v->nexttype == EMPTY && (v->cflags & REG_BOSONLY))
     215                 :             :         {
     216                 :             :                 /* at start of a REG_BOSONLY RE */
     217                 :           0 :                 RETV(SBEGIN, 0);                /* same as \A */
     218                 :             :         }
     219                 :             : 
     220                 :             :         /* skip white space etc. if appropriate (not in literal or []) */
     221         [ +  + ]:       18215 :         if (v->cflags & REG_EXPANDED)
     222         [ +  - ]:           4 :                 switch (v->lexcon)
     223                 :             :                 {
     224                 :             :                         case L_ERE:
     225                 :             :                         case L_BRE:
     226                 :             :                         case L_EBND:
     227                 :             :                         case L_BBND:
     228                 :           4 :                                 skip(v);
     229                 :           4 :                                 break;
     230                 :           4 :                 }
     231                 :             : 
     232                 :             :         /* handle EOS, depending on context */
     233         [ +  + ]:       18215 :         if (ATEOS())
     234                 :             :         {
     235   [ -  -  +  - ]:         808 :                 switch (v->lexcon)
     236                 :             :                 {
     237                 :             :                         case L_ERE:
     238                 :             :                         case L_BRE:
     239                 :             :                         case L_Q:
     240                 :         808 :                                 RET(EOS);
     241                 :             :                                 break;
     242                 :             :                         case L_EBND:
     243                 :             :                         case L_BBND:
     244         [ #  # ]:           0 :                                 FAILW(REG_EBRACE);
     245                 :             :                                 break;
     246                 :             :                         case L_BRACK:
     247                 :             :                         case L_CEL:
     248                 :             :                         case L_ECL:
     249                 :             :                         case L_CCL:
     250         [ #  # ]:           0 :                                 FAILW(REG_EBRACK);
     251                 :             :                                 break;
     252                 :             :                 }
     253                 :           0 :                 assert(NOTREACHED);
     254                 :           0 :         }
     255                 :             : 
     256                 :             :         /* okay, time to actually get a character */
     257                 :       17407 :         c = *v->now++;
     258                 :             : 
     259                 :             :         /* deal with the easy contexts, punt EREs to code below */
     260   [ -  +  -  +  :       17407 :         switch (v->lexcon)
             +  +  -  -  
                      + ]
     261                 :             :         {
     262                 :             :                 case L_BRE:                             /* punt BREs to separate function */
     263                 :           0 :                         return brenext(v, c);
     264                 :             :                         break;
     265                 :             :                 case L_ERE:                             /* see below */
     266                 :             :                         break;
     267                 :             :                 case L_Q:                               /* literal strings are easy */
     268                 :          71 :                         RETV(PLAIN, c);
     269                 :             :                         break;
     270                 :             :                 case L_BBND:                    /* bounds are fairly simple */
     271                 :             :                 case L_EBND:
     272   [ +  +  -  +  :         147 :                         switch (c)
                      - ]
     273                 :             :                         {
     274                 :             :                                 case CHR('0'):
     275                 :             :                                 case CHR('1'):
     276                 :             :                                 case CHR('2'):
     277                 :             :                                 case CHR('3'):
     278                 :             :                                 case CHR('4'):
     279                 :             :                                 case CHR('5'):
     280                 :             :                                 case CHR('6'):
     281                 :             :                                 case CHR('7'):
     282                 :             :                                 case CHR('8'):
     283                 :             :                                 case CHR('9'):
     284                 :          74 :                                         RETV(DIGIT, (chr) DIGITVAL(c));
     285                 :             :                                         break;
     286                 :             :                                 case CHR(','):
     287                 :          25 :                                         RET(',');
     288                 :             :                                         break;
     289                 :             :                                 case CHR('}'):  /* ERE bound ends with } */
     290         [ +  - ]:          48 :                                         if (INCON(L_EBND))
     291                 :             :                                         {
     292                 :          48 :                                                 INTOCON(L_ERE);
     293   [ +  -  +  +  :          48 :                                                 if ((v->cflags & REG_ADVF) && NEXT1('?'))
                   +  + ]
     294                 :             :                                                 {
     295                 :          14 :                                                         v->now++;
     296                 :          14 :                                                         NOTE(REG_UNONPOSIX);
     297                 :          14 :                                                         RETV('}', 0);
     298                 :             :                                                 }
     299                 :          34 :                                                 RETV('}', 1);
     300                 :             :                                         }
     301                 :             :                                         else
     302         [ #  # ]:           0 :                                                 FAILW(REG_BADBR);
     303                 :             :                                         break;
     304                 :             :                                 case CHR('\\'): /* BRE bound ends with \} */
     305   [ #  #  #  #  :           0 :                                         if (INCON(L_BBND) && NEXT1('}'))
                   #  # ]
     306                 :             :                                         {
     307                 :           0 :                                                 v->now++;
     308                 :           0 :                                                 INTOCON(L_BRE);
     309                 :           0 :                                                 RETV('}', 1);
     310                 :             :                                         }
     311                 :             :                                         else
     312         [ #  # ]:           0 :                                                 FAILW(REG_BADBR);
     313                 :             :                                         break;
     314                 :             :                                 default:
     315         [ #  # ]:           0 :                                         FAILW(REG_BADBR);
     316                 :             :                                         break;
     317                 :             :                         }
     318                 :             :                         assert(NOTREACHED);
     319                 :             :                         break;
     320                 :             :                 case L_BRACK:                   /* brackets are not too hard */
     321   [ +  +  +  +  :         242 :                         switch (c)
                      + ]
     322                 :             :                         {
     323                 :             :                                 case CHR(']'):
     324         [ +  + ]:          68 :                                         if (LASTTYPE('['))
     325                 :           2 :                                                 RETV(PLAIN, c);
     326                 :             :                                         else
     327                 :             :                                         {
     328                 :          66 :                                                 INTOCON((v->cflags & REG_EXTENDED) ?
     329                 :             :                                                                 L_ERE : L_BRE);
     330                 :          66 :                                                 RET(']');
     331                 :             :                                         }
     332                 :             :                                         break;
     333                 :             :                                 case CHR('\\'):
     334                 :           3 :                                         NOTE(REG_UBBS);
     335         [ +  - ]:           3 :                                         if (!(v->cflags & REG_ADVF))
     336                 :           0 :                                                 RETV(PLAIN, c);
     337                 :           3 :                                         NOTE(REG_UNONPOSIX);
     338         [ -  + ]:           3 :                                         if (ATEOS())
     339         [ #  # ]:           0 :                                                 FAILW(REG_EESCAPE);
     340         [ +  - ]:           3 :                                         if (!lexescape(v))
     341                 :           0 :                                                 return 0;
     342         [ +  - ]:           3 :                                         switch (v->nexttype)
     343                 :             :                                         {                       /* not all escapes okay here */
     344                 :             :                                                 case PLAIN:
     345                 :             :                                                 case CCLASSS:
     346                 :             :                                                 case CCLASSC:
     347                 :           3 :                                                         return 1;
     348                 :             :                                                         break;
     349                 :             :                                         }
     350                 :             :                                         /* not one of the acceptable escapes */
     351         [ #  # ]:           0 :                                         FAILW(REG_EESCAPE);
     352                 :             :                                         break;
     353                 :             :                                 case CHR('-'):
     354   [ +  -  +  -  :          24 :                                         if (LASTTYPE('[') || NEXT1(']'))
                   -  + ]
     355                 :           0 :                                                 RETV(PLAIN, c);
     356                 :             :                                         else
     357                 :          24 :                                                 RETV(RANGE, c);
     358                 :             :                                         break;
     359                 :             :                                 case CHR('['):
     360         [ -  + ]:          27 :                                         if (ATEOS())
     361         [ #  # ]:           0 :                                                 FAILW(REG_EBRACK);
     362   [ -  +  -  + ]:          27 :                                         switch (*v->now++)
     363                 :             :                                         {
     364                 :             :                                                 case CHR('.'):
     365                 :           0 :                                                         INTOCON(L_CEL);
     366                 :             :                                                         /* might or might not be locale-specific */
     367                 :           0 :                                                         RET(COLLEL);
     368                 :             :                                                         break;
     369                 :             :                                                 case CHR('='):
     370                 :           0 :                                                         INTOCON(L_ECL);
     371                 :           0 :                                                         NOTE(REG_ULOCALE);
     372                 :           0 :                                                         RET(ECLASS);
     373                 :             :                                                         break;
     374                 :             :                                                 case CHR(':'):
     375                 :          24 :                                                         INTOCON(L_CCL);
     376                 :          24 :                                                         NOTE(REG_ULOCALE);
     377                 :          24 :                                                         RET(CCLASS);
     378                 :             :                                                         break;
     379                 :             :                                                 default:        /* oops */
     380                 :           3 :                                                         v->now--;
     381                 :           3 :                                                         RETV(PLAIN, c);
     382                 :             :                                                         break;
     383                 :             :                                         }
     384                 :             :                                         assert(NOTREACHED);
     385                 :             :                                         break;
     386                 :             :                                 default:
     387                 :         120 :                                         RETV(PLAIN, c);
     388                 :             :                                         break;
     389                 :             :                         }
     390                 :             :                         assert(NOTREACHED);
     391                 :             :                         break;
     392                 :             :                 case L_CEL:                             /* collating elements are easy */
     393   [ #  #  #  #  :           0 :                         if (c == CHR('.') && NEXT1(']'))
                   #  # ]
     394                 :             :                         {
     395                 :           0 :                                 v->now++;
     396                 :           0 :                                 INTOCON(L_BRACK);
     397                 :           0 :                                 RETV(END, '.');
     398                 :             :                         }
     399                 :             :                         else
     400                 :           0 :                                 RETV(PLAIN, c);
     401                 :             :                         break;
     402                 :             :                 case L_ECL:                             /* ditto equivalence classes */
     403   [ #  #  #  #  :           0 :                         if (c == CHR('=') && NEXT1(']'))
                   #  # ]
     404                 :             :                         {
     405                 :           0 :                                 v->now++;
     406                 :           0 :                                 INTOCON(L_BRACK);
     407                 :           0 :                                 RETV(END, '=');
     408                 :             :                         }
     409                 :             :                         else
     410                 :           0 :                                 RETV(PLAIN, c);
     411                 :             :                         break;
     412                 :             :                 case L_CCL:                             /* ditto character classes */
     413   [ +  +  +  -  :         144 :                         if (c == CHR(':') && NEXT1(']'))
                   -  + ]
     414                 :             :                         {
     415                 :          24 :                                 v->now++;
     416                 :          24 :                                 INTOCON(L_BRACK);
     417                 :          24 :                                 RETV(END, ':');
     418                 :             :                         }
     419                 :             :                         else
     420                 :         120 :                                 RETV(PLAIN, c);
     421                 :             :                         break;
     422                 :             :                 default:
     423                 :           0 :                         assert(NOTREACHED);
     424                 :           0 :                         break;
     425                 :             :         }
     426                 :             : 
     427                 :             :         /* that got rid of everything except EREs and AREs */
     428         [ -  + ]:       16803 :         assert(INCON(L_ERE));
     429                 :             : 
     430                 :             :         /* deal with EREs and AREs, except for backslashes */
     431   [ +  +  +  +  :       16803 :         switch (c)
          +  +  +  +  +  
             +  +  +  + ]
     432                 :             :         {
     433                 :             :                 case CHR('|'):
     434                 :          53 :                         RET('|');
     435                 :             :                         break;
     436                 :             :                 case CHR('*'):
     437   [ +  -  +  +  :        3143 :                         if ((v->cflags & REG_ADVF) && NEXT1('?'))
                   +  + ]
     438                 :             :                         {
     439                 :           6 :                                 v->now++;
     440                 :           6 :                                 NOTE(REG_UNONPOSIX);
     441                 :           6 :                                 RETV('*', 0);
     442                 :             :                         }
     443                 :        3137 :                         RETV('*', 1);
     444                 :             :                         break;
     445                 :             :                 case CHR('+'):
     446   [ +  -  +  +  :          95 :                         if ((v->cflags & REG_ADVF) && NEXT1('?'))
                   +  + ]
     447                 :             :                         {
     448                 :           3 :                                 v->now++;
     449                 :           3 :                                 NOTE(REG_UNONPOSIX);
     450                 :           3 :                                 RETV('+', 0);
     451                 :             :                         }
     452                 :          92 :                         RETV('+', 1);
     453                 :             :                         break;
     454                 :             :                 case CHR('?'):
     455   [ +  -  +  +  :          11 :                         if ((v->cflags & REG_ADVF) && NEXT1('?'))
                   +  - ]
     456                 :             :                         {
     457                 :           0 :                                 v->now++;
     458                 :           0 :                                 NOTE(REG_UNONPOSIX);
     459                 :           0 :                                 RETV('?', 0);
     460                 :             :                         }
     461                 :          11 :                         RETV('?', 1);
     462                 :             :                         break;
     463                 :             :                 case CHR('{'):                  /* bounds start or plain character */
     464         [ +  - ]:          48 :                         if (v->cflags & REG_EXPANDED)
     465                 :           0 :                                 skip(v);
     466   [ +  -  -  + ]:          48 :                         if (ATEOS() || !iscdigit(*v->now))
     467                 :             :                         {
     468                 :           0 :                                 NOTE(REG_UBRACES);
     469                 :           0 :                                 NOTE(REG_UUNSPEC);
     470                 :           0 :                                 RETV(PLAIN, c);
     471                 :             :                         }
     472                 :             :                         else
     473                 :             :                         {
     474                 :          48 :                                 NOTE(REG_UBOUNDS);
     475                 :          48 :                                 INTOCON(L_EBND);
     476                 :          48 :                                 RET('{');
     477                 :             :                         }
     478                 :             :                         assert(NOTREACHED);
     479                 :             :                         break;
     480                 :             :                 case CHR('('):                  /* parenthesis, or advanced extension */
     481   [ +  -  +  -  :         717 :                         if ((v->cflags & REG_ADVF) && NEXT1('?'))
                   +  + ]
     482                 :             :                         {
     483                 :          68 :                                 NOTE(REG_UNONPOSIX);
     484                 :          68 :                                 v->now++;
     485         [ +  - ]:          68 :                                 if (ATEOS())
     486         [ #  # ]:           0 :                                         FAILW(REG_BADRPT);
     487   [ +  +  -  -  :          68 :                                 switch (*v->now++)
                   +  + ]
     488                 :             :                                 {
     489                 :             :                                         case CHR(':'):  /* non-capturing paren */
     490                 :          41 :                                                 RETV('(', 0);
     491                 :             :                                                 break;
     492                 :             :                                         case CHR('#'):  /* comment */
     493   [ #  #  #  # ]:           0 :                                                 while (!ATEOS() && *v->now != CHR(')'))
     494                 :           0 :                                                         v->now++;
     495         [ #  # ]:           0 :                                                 if (!ATEOS())
     496                 :           0 :                                                         v->now++;
     497         [ #  # ]:           0 :                                                 assert(v->nexttype == v->lasttype);
     498                 :           0 :                                                 goto next_restart;
     499                 :             :                                         case CHR('='):  /* positive lookahead */
     500                 :           8 :                                                 NOTE(REG_ULOOKAROUND);
     501                 :           8 :                                                 RETV(LACON, LATYPE_AHEAD_POS);
     502                 :             :                                                 break;
     503                 :             :                                         case CHR('!'):  /* negative lookahead */
     504                 :           6 :                                                 NOTE(REG_ULOOKAROUND);
     505                 :           6 :                                                 RETV(LACON, LATYPE_AHEAD_NEG);
     506                 :             :                                                 break;
     507                 :             :                                         case CHR('<'):
     508         [ -  + ]:          13 :                                                 if (ATEOS())
     509         [ #  # ]:           0 :                                                         FAILW(REG_BADRPT);
     510      [ -  +  + ]:          13 :                                                 switch (*v->now++)
     511                 :             :                                                 {
     512                 :             :                                                         case CHR('='):  /* positive lookbehind */
     513                 :           9 :                                                                 NOTE(REG_ULOOKAROUND);
     514                 :           9 :                                                                 RETV(LACON, LATYPE_BEHIND_POS);
     515                 :             :                                                                 break;
     516                 :             :                                                         case CHR('!'):  /* negative lookbehind */
     517                 :           4 :                                                                 NOTE(REG_ULOOKAROUND);
     518                 :           4 :                                                                 RETV(LACON, LATYPE_BEHIND_NEG);
     519                 :             :                                                                 break;
     520                 :             :                                                         default:
     521         [ #  # ]:           0 :                                                                 FAILW(REG_BADRPT);
     522                 :             :                                                                 break;
     523                 :             :                                                 }
     524                 :             :                                                 assert(NOTREACHED);
     525                 :             :                                                 break;
     526                 :             :                                         default:
     527         [ #  # ]:           0 :                                                 FAILW(REG_BADRPT);
     528                 :             :                                                 break;
     529                 :             :                                 }
     530                 :             :                                 assert(NOTREACHED);
     531                 :             :                         }
     532                 :         649 :                         RETV('(', 1);
     533                 :             :                         break;
     534                 :             :                 case CHR(')'):
     535         [ +  + ]:         712 :                         if (LASTTYPE('('))
     536                 :           8 :                                 NOTE(REG_UUNSPEC);
     537                 :         712 :                         RETV(')', c);
     538                 :             :                         break;
     539                 :             :                 case CHR('['):                  /* easy except for [[:<:]] and [[:>:]] */
     540   [ +  +  +  + ]:          66 :                         if (HAVE(6) && *(v->now + 0) == CHR('[') &&
     541         [ +  + ]:          20 :                                 *(v->now + 1) == CHR(':') &&
     542         [ +  - ]:          18 :                                 (*(v->now + 2) == CHR('<') ||
     543                 :          18 :                                  *(v->now + 2) == CHR('>')) &&
     544         [ -  + ]:          18 :                                 *(v->now + 3) == CHR(':') &&
     545   [ #  #  #  # ]:           0 :                                 *(v->now + 4) == CHR(']') &&
     546                 :           0 :                                 *(v->now + 5) == CHR(']'))
     547                 :             :                         {
     548                 :           0 :                                 c = *(v->now + 2);
     549                 :           0 :                                 v->now += 6;
     550                 :           0 :                                 NOTE(REG_UNONPOSIX);
     551                 :           0 :                                 RET((c == CHR('<')) ? '<' : '>');
     552                 :             :                         }
     553                 :          66 :                         INTOCON(L_BRACK);
     554   [ +  -  +  + ]:          66 :                         if (NEXT1('^'))
     555                 :             :                         {
     556                 :          17 :                                 v->now++;
     557                 :          17 :                                 RETV('[', 0);
     558                 :             :                         }
     559                 :          49 :                         RETV('[', 1);
     560                 :             :                         break;
     561                 :             :                 case CHR('.'):
     562                 :         387 :                         RET('.');
     563                 :             :                         break;
     564                 :             :                 case CHR('^'):
     565                 :         593 :                         RET('^');
     566                 :             :                         break;
     567                 :             :                 case CHR('$'):
     568                 :         574 :                         RET('$');
     569                 :             :                         break;
     570                 :             :                 case CHR('\\'):                 /* mostly punt backslashes to code below */
     571         [ -  + ]:         233 :                         if (ATEOS())
     572         [ #  # ]:           0 :                                 FAILW(REG_EESCAPE);
     573                 :         233 :                         break;
     574                 :             :                 default:                                /* ordinary character */
     575                 :       10171 :                         RETV(PLAIN, c);
     576                 :             :                         break;
     577                 :             :         }
     578                 :             : 
     579                 :             :         /* ERE/ARE backslash handling; backslash already eaten */
     580         [ +  - ]:         233 :         assert(!ATEOS());
     581         [ +  - ]:         233 :         if (!(v->cflags & REG_ADVF))
     582                 :             :         {                                                       /* only AREs have non-trivial escapes */
     583         [ #  # ]:           0 :                 if (iscalnum(*v->now))
     584                 :             :                 {
     585                 :           0 :                         NOTE(REG_UBSALNUM);
     586                 :           0 :                         NOTE(REG_UUNSPEC);
     587                 :           0 :                 }
     588                 :           0 :                 RETV(PLAIN, *v->now++);
     589                 :             :         }
     590                 :         233 :         return lexescape(v);
     591                 :       18218 : }
     592                 :             : 
     593                 :             : /*
     594                 :             :  * lexescape - parse an ARE backslash escape (backslash already eaten)
     595                 :             :  *
     596                 :             :  * This is used for ARE backslashes both normally and inside bracket
     597                 :             :  * expressions.  In the latter case, not all escape types are allowed,
     598                 :             :  * but the caller must reject unwanted ones after we return.
     599                 :             :  */
     600                 :             : static int
     601                 :         236 : lexescape(struct vars *v)
     602                 :             : {
     603                 :         236 :         chr                     c;
     604                 :             :         static const chr alert[] = {
     605                 :             :                 CHR('a'), CHR('l'), CHR('e'), CHR('r'), CHR('t')
     606                 :             :         };
     607                 :             :         static const chr esc[] = {
     608                 :             :                 CHR('E'), CHR('S'), CHR('C')
     609                 :             :         };
     610                 :         236 :         const chr  *save;
     611                 :             : 
     612         [ +  - ]:         236 :         assert(v->cflags & REG_ADVF);
     613                 :             : 
     614         [ +  - ]:         236 :         assert(!ATEOS());
     615                 :         236 :         c = *v->now++;
     616                 :             : 
     617                 :             :         /* if it's not alphanumeric ASCII, treat it as a plain character */
     618   [ +  +  +  + ]:         236 :         if (!('a' <= c && c <= 'z') &&
     619         [ +  + ]:         229 :                 !('A' <= c && c <= 'Z') &&
     620         [ +  + ]:         179 :                 !('0' <= c && c <= '9'))
     621                 :         148 :                 RETV(PLAIN, c);
     622                 :             : 
     623                 :          88 :         NOTE(REG_UNONPOSIX);
     624   [ +  -  -  +  :          88 :         switch (c)
          -  +  -  -  +  
          -  -  -  +  +  
          -  -  +  +  -  
          -  -  -  +  -  
             +  -  +  - ]
     625                 :             :         {
     626                 :             :                 case CHR('a'):
     627                 :           1 :                         RETV(PLAIN, chrnamed(v, alert, ENDOF(alert), CHR('\007')));
     628                 :             :                         break;
     629                 :             :                 case CHR('A'):
     630                 :           0 :                         RETV(SBEGIN, 0);
     631                 :             :                         break;
     632                 :             :                 case CHR('b'):
     633                 :           4 :                         RETV(PLAIN, CHR('\b'));
     634                 :             :                         break;
     635                 :             :                 case CHR('B'):
     636                 :           0 :                         RETV(PLAIN, CHR('\\'));
     637                 :             :                         break;
     638                 :             :                 case CHR('c'):
     639                 :           0 :                         NOTE(REG_UUNPORT);
     640         [ #  # ]:           0 :                         if (ATEOS())
     641         [ #  # ]:           0 :                                 FAILW(REG_EESCAPE);
     642                 :           0 :                         RETV(PLAIN, (chr) (*v->now++ & 037));
     643                 :             :                         break;
     644                 :             :                 case CHR('d'):
     645                 :          40 :                         NOTE(REG_ULOCALE);
     646                 :          40 :                         RETV(CCLASSS, CC_DIGIT);
     647                 :             :                         break;
     648                 :             :                 case CHR('D'):
     649                 :           0 :                         NOTE(REG_ULOCALE);
     650                 :           0 :                         RETV(CCLASSC, CC_DIGIT);
     651                 :             :                         break;
     652                 :             :                 case CHR('e'):
     653                 :           0 :                         NOTE(REG_UUNPORT);
     654                 :           0 :                         RETV(PLAIN, chrnamed(v, esc, ENDOF(esc), CHR('\033')));
     655                 :             :                         break;
     656                 :             :                 case CHR('f'):
     657                 :           0 :                         RETV(PLAIN, CHR('\f'));
     658                 :             :                         break;
     659                 :             :                 case CHR('m'):
     660                 :           4 :                         RET('<');
     661                 :             :                         break;
     662                 :             :                 case CHR('M'):
     663                 :           3 :                         RET('>');
     664                 :             :                         break;
     665                 :             :                 case CHR('n'):
     666                 :           0 :                         RETV(PLAIN, CHR('\n'));
     667                 :             :                         break;
     668                 :             :                 case CHR('r'):
     669                 :           0 :                         RETV(PLAIN, CHR('\r'));
     670                 :             :                         break;
     671                 :             :                 case CHR('s'):
     672                 :           3 :                         NOTE(REG_ULOCALE);
     673                 :           3 :                         RETV(CCLASSS, CC_SPACE);
     674                 :             :                         break;
     675                 :             :                 case CHR('S'):
     676                 :           3 :                         NOTE(REG_ULOCALE);
     677                 :           3 :                         RETV(CCLASSC, CC_SPACE);
     678                 :             :                         break;
     679                 :             :                 case CHR('t'):
     680                 :           0 :                         RETV(PLAIN, CHR('\t'));
     681                 :             :                         break;
     682                 :             :                 case CHR('u'):
     683                 :           0 :                         c = lexdigits(v, 16, 4, 4);
     684   [ #  #  #  # ]:           0 :                         if (ISERR() || !CHR_IS_IN_RANGE(c))
     685         [ #  # ]:           0 :                                 FAILW(REG_EESCAPE);
     686                 :           0 :                         RETV(PLAIN, c);
     687                 :             :                         break;
     688                 :             :                 case CHR('U'):
     689                 :           0 :                         c = lexdigits(v, 16, 8, 8);
     690   [ #  #  #  # ]:           0 :                         if (ISERR() || !CHR_IS_IN_RANGE(c))
     691         [ #  # ]:           0 :                                 FAILW(REG_EESCAPE);
     692                 :           0 :                         RETV(PLAIN, c);
     693                 :             :                         break;
     694                 :             :                 case CHR('v'):
     695                 :           0 :                         RETV(PLAIN, CHR('\v'));
     696                 :             :                         break;
     697                 :             :                 case CHR('w'):
     698                 :           7 :                         NOTE(REG_ULOCALE);
     699                 :           7 :                         RETV(CCLASSS, CC_WORD);
     700                 :             :                         break;
     701                 :             :                 case CHR('W'):
     702                 :           0 :                         NOTE(REG_ULOCALE);
     703                 :           0 :                         RETV(CCLASSC, CC_WORD);
     704                 :             :                         break;
     705                 :             :                 case CHR('x'):
     706                 :           1 :                         NOTE(REG_UUNPORT);
     707                 :           1 :                         c = lexdigits(v, 16, 1, 255);   /* REs >255 long outside spec */
     708   [ +  -  +  - ]:           1 :                         if (ISERR() || !CHR_IS_IN_RANGE(c))
     709         [ -  + ]:           1 :                                 FAILW(REG_EESCAPE);
     710                 :           0 :                         RETV(PLAIN, c);
     711                 :             :                         break;
     712                 :             :                 case CHR('y'):
     713                 :           0 :                         NOTE(REG_ULOCALE);
     714                 :           0 :                         RETV(WBDRY, 0);
     715                 :             :                         break;
     716                 :             :                 case CHR('Y'):
     717                 :           2 :                         NOTE(REG_ULOCALE);
     718                 :           2 :                         RETV(NWBDRY, 0);
     719                 :             :                         break;
     720                 :             :                 case CHR('Z'):
     721                 :           0 :                         RETV(SEND, 0);
     722                 :             :                         break;
     723                 :             :                 case CHR('1'):
     724                 :             :                 case CHR('2'):
     725                 :             :                 case CHR('3'):
     726                 :             :                 case CHR('4'):
     727                 :             :                 case CHR('5'):
     728                 :             :                 case CHR('6'):
     729                 :             :                 case CHR('7'):
     730                 :             :                 case CHR('8'):
     731                 :             :                 case CHR('9'):
     732                 :          20 :                         save = v->now;
     733                 :          20 :                         v->now--;                    /* put first digit back */
     734                 :          20 :                         c = lexdigits(v, 10, 1, 255);   /* REs >255 long outside spec */
     735         [ -  + ]:          20 :                         if (ISERR())
     736         [ #  # ]:           0 :                                 FAILW(REG_EESCAPE);
     737                 :             :                         /* ugly heuristic (first test is "exactly 1 digit?") */
     738   [ -  +  #  #  :          20 :                         if (v->now == save || ((int) c > 0 && (int) c <= v->nsubexp))
                   #  # ]
     739                 :             :                         {
     740                 :          20 :                                 NOTE(REG_UBACKREF);
     741                 :          20 :                                 RETV(BACKREF, c);
     742                 :             :                         }
     743                 :             :                         /* oops, doesn't look like it's a backref after all... */
     744                 :           0 :                         v->now = save;
     745                 :             :                         /* and fall through into octal number */
     746                 :             :                         /* FALLTHROUGH */
     747                 :             :                 case CHR('0'):
     748                 :           0 :                         NOTE(REG_UUNPORT);
     749                 :           0 :                         v->now--;                    /* put first digit back */
     750                 :           0 :                         c = lexdigits(v, 8, 1, 3);
     751         [ #  # ]:           0 :                         if (ISERR())
     752         [ #  # ]:           0 :                                 FAILW(REG_EESCAPE);
     753         [ #  # ]:           0 :                         if (c > 0xff)
     754                 :             :                         {
     755                 :             :                                 /* out of range, so we handled one digit too much */
     756                 :           0 :                                 v->now--;
     757                 :           0 :                                 c >>= 3;
     758                 :           0 :                         }
     759                 :           0 :                         RETV(PLAIN, c);
     760                 :             :                         break;
     761                 :             :                 default:
     762                 :             : 
     763                 :             :                         /*
     764                 :             :                          * Throw an error for unrecognized ASCII alpha escape sequences,
     765                 :             :                          * which reserves them for future use if needed.
     766                 :             :                          */
     767         [ #  # ]:           0 :                         FAILW(REG_EESCAPE);
     768                 :             :                         break;
     769                 :             :         }
     770                 :             :         assert(NOTREACHED);
     771                 :         236 : }
     772                 :             : 
     773                 :             : /*
     774                 :             :  * lexdigits - slurp up digits and return chr value
     775                 :             :  *
     776                 :             :  * This does not account for overflow; callers should range-check the result
     777                 :             :  * if maxlen is large enough to make that possible.
     778                 :             :  */
     779                 :             : static chr                                              /* chr value; errors signalled via ERR */
     780                 :          21 : lexdigits(struct vars *v,
     781                 :             :                   int base,
     782                 :             :                   int minlen,
     783                 :             :                   int maxlen)
     784                 :             : {
     785                 :          21 :         uchr            n;                              /* unsigned to avoid overflow misbehavior */
     786                 :          21 :         int                     len;
     787                 :          21 :         chr                     c;
     788                 :          21 :         int                     d;
     789                 :          21 :         const uchr      ub = (uchr) base;
     790                 :             : 
     791                 :          21 :         n = 0;
     792   [ -  +  +  + ]:          49 :         for (len = 0; len < maxlen && !ATEOS(); len++)
     793                 :             :         {
     794                 :          40 :                 c = *v->now++;
     795   [ +  +  -  -  :          40 :                 switch (c)
             -  -  -  + ]
     796                 :             :                 {
     797                 :             :                         case CHR('0'):
     798                 :             :                         case CHR('1'):
     799                 :             :                         case CHR('2'):
     800                 :             :                         case CHR('3'):
     801                 :             :                         case CHR('4'):
     802                 :             :                         case CHR('5'):
     803                 :             :                         case CHR('6'):
     804                 :             :                         case CHR('7'):
     805                 :             :                         case CHR('8'):
     806                 :             :                         case CHR('9'):
     807                 :          21 :                                 d = DIGITVAL(c);
     808                 :          21 :                                 break;
     809                 :             :                         case CHR('a'):
     810                 :             :                         case CHR('A'):
     811                 :           0 :                                 d = 10;
     812                 :           0 :                                 break;
     813                 :             :                         case CHR('b'):
     814                 :             :                         case CHR('B'):
     815                 :           0 :                                 d = 11;
     816                 :           0 :                                 break;
     817                 :             :                         case CHR('c'):
     818                 :             :                         case CHR('C'):
     819                 :           0 :                                 d = 12;
     820                 :           0 :                                 break;
     821                 :             :                         case CHR('d'):
     822                 :             :                         case CHR('D'):
     823                 :           0 :                                 d = 13;
     824                 :           0 :                                 break;
     825                 :             :                         case CHR('e'):
     826                 :             :                         case CHR('E'):
     827                 :           0 :                                 d = 14;
     828                 :           0 :                                 break;
     829                 :             :                         case CHR('f'):
     830                 :             :                         case CHR('F'):
     831                 :           7 :                                 d = 15;
     832                 :           7 :                                 break;
     833                 :             :                         default:
     834                 :          12 :                                 v->now--;            /* oops, not a digit at all */
     835                 :          12 :                                 d = -1;
     836                 :          12 :                                 break;
     837                 :             :                 }
     838                 :             : 
     839         [ +  - ]:          40 :                 if (d >= base)
     840                 :             :                 {                                               /* not a plausible digit */
     841                 :           0 :                         v->now--;
     842                 :           0 :                         d = -1;
     843                 :           0 :                 }
     844         [ +  + ]:          40 :                 if (d < 0)
     845                 :          12 :                         break;                          /* NOTE BREAK OUT */
     846                 :          28 :                 n = n * ub + (uchr) d;
     847                 :          28 :         }
     848         [ +  - ]:          21 :         if (len < minlen)
     849         [ #  # ]:           0 :                 ERR(REG_EESCAPE);
     850                 :             : 
     851                 :          42 :         return (chr) n;
     852                 :          21 : }
     853                 :             : 
     854                 :             : /*
     855                 :             :  * brenext - get next BRE token
     856                 :             :  *
     857                 :             :  * This is much like EREs except for all the stupid backslashes and the
     858                 :             :  * context-dependency of some things.
     859                 :             :  */
     860                 :             : static int                                              /* 1 normal, 0 failure */
     861                 :           0 : brenext(struct vars *v,
     862                 :             :                 chr c)
     863                 :             : {
     864   [ #  #  #  #  :           0 :         switch (c)
                #  #  # ]
     865                 :             :         {
     866                 :             :                 case CHR('*'):
     867   [ #  #  #  #  :           0 :                         if (LASTTYPE(EMPTY) || LASTTYPE('(') || LASTTYPE('^'))
                   #  # ]
     868                 :           0 :                                 RETV(PLAIN, c);
     869                 :           0 :                         RETV('*', 1);
     870                 :             :                         break;
     871                 :             :                 case CHR('['):
     872   [ #  #  #  # ]:           0 :                         if (HAVE(6) && *(v->now + 0) == CHR('[') &&
     873         [ #  # ]:           0 :                                 *(v->now + 1) == CHR(':') &&
     874         [ #  # ]:           0 :                                 (*(v->now + 2) == CHR('<') ||
     875                 :           0 :                                  *(v->now + 2) == CHR('>')) &&
     876         [ #  # ]:           0 :                                 *(v->now + 3) == CHR(':') &&
     877   [ #  #  #  # ]:           0 :                                 *(v->now + 4) == CHR(']') &&
     878                 :           0 :                                 *(v->now + 5) == CHR(']'))
     879                 :             :                         {
     880                 :           0 :                                 c = *(v->now + 2);
     881                 :           0 :                                 v->now += 6;
     882                 :           0 :                                 NOTE(REG_UNONPOSIX);
     883                 :           0 :                                 RET((c == CHR('<')) ? '<' : '>');
     884                 :             :                         }
     885                 :           0 :                         INTOCON(L_BRACK);
     886   [ #  #  #  # ]:           0 :                         if (NEXT1('^'))
     887                 :             :                         {
     888                 :           0 :                                 v->now++;
     889                 :           0 :                                 RETV('[', 0);
     890                 :             :                         }
     891                 :           0 :                         RETV('[', 1);
     892                 :             :                         break;
     893                 :             :                 case CHR('.'):
     894                 :           0 :                         RET('.');
     895                 :             :                         break;
     896                 :             :                 case CHR('^'):
     897         [ #  # ]:           0 :                         if (LASTTYPE(EMPTY))
     898                 :           0 :                                 RET('^');
     899         [ #  # ]:           0 :                         if (LASTTYPE('('))
     900                 :             :                         {
     901                 :           0 :                                 NOTE(REG_UUNSPEC);
     902                 :           0 :                                 RET('^');
     903                 :             :                         }
     904                 :           0 :                         RETV(PLAIN, c);
     905                 :             :                         break;
     906                 :             :                 case CHR('$'):
     907         [ #  # ]:           0 :                         if (v->cflags & REG_EXPANDED)
     908                 :           0 :                                 skip(v);
     909         [ #  # ]:           0 :                         if (ATEOS())
     910                 :           0 :                                 RET('$');
     911   [ #  #  #  #  :           0 :                         if (NEXT2('\\', ')'))
                   #  # ]
     912                 :             :                         {
     913                 :           0 :                                 NOTE(REG_UUNSPEC);
     914                 :           0 :                                 RET('$');
     915                 :             :                         }
     916                 :           0 :                         RETV(PLAIN, c);
     917                 :             :                         break;
     918                 :             :                 case CHR('\\'):
     919                 :             :                         break;                          /* see below */
     920                 :             :                 default:
     921                 :           0 :                         RETV(PLAIN, c);
     922                 :             :                         break;
     923                 :             :         }
     924                 :             : 
     925         [ #  # ]:           0 :         assert(c == CHR('\\'));
     926                 :             : 
     927         [ #  # ]:           0 :         if (ATEOS())
     928         [ #  # ]:           0 :                 FAILW(REG_EESCAPE);
     929                 :             : 
     930                 :           0 :         c = *v->now++;
     931   [ #  #  #  #  :           0 :         switch (c)
                #  #  # ]
     932                 :             :         {
     933                 :             :                 case CHR('{'):
     934                 :           0 :                         INTOCON(L_BBND);
     935                 :           0 :                         NOTE(REG_UBOUNDS);
     936                 :           0 :                         RET('{');
     937                 :             :                         break;
     938                 :             :                 case CHR('('):
     939                 :           0 :                         RETV('(', 1);
     940                 :             :                         break;
     941                 :             :                 case CHR(')'):
     942                 :           0 :                         RETV(')', c);
     943                 :             :                         break;
     944                 :             :                 case CHR('<'):
     945                 :           0 :                         NOTE(REG_UNONPOSIX);
     946                 :           0 :                         RET('<');
     947                 :             :                         break;
     948                 :             :                 case CHR('>'):
     949                 :           0 :                         NOTE(REG_UNONPOSIX);
     950                 :           0 :                         RET('>');
     951                 :             :                         break;
     952                 :             :                 case CHR('1'):
     953                 :             :                 case CHR('2'):
     954                 :             :                 case CHR('3'):
     955                 :             :                 case CHR('4'):
     956                 :             :                 case CHR('5'):
     957                 :             :                 case CHR('6'):
     958                 :             :                 case CHR('7'):
     959                 :             :                 case CHR('8'):
     960                 :             :                 case CHR('9'):
     961                 :           0 :                         NOTE(REG_UBACKREF);
     962                 :           0 :                         RETV(BACKREF, (chr) DIGITVAL(c));
     963                 :             :                         break;
     964                 :             :                 default:
     965         [ #  # ]:           0 :                         if (iscalnum(c))
     966                 :             :                         {
     967                 :           0 :                                 NOTE(REG_UBSALNUM);
     968                 :           0 :                                 NOTE(REG_UUNSPEC);
     969                 :           0 :                         }
     970                 :           0 :                         RETV(PLAIN, c);
     971                 :             :                         break;
     972                 :             :         }
     973                 :             : 
     974                 :             :         assert(NOTREACHED);
     975                 :             :         return 0;
     976                 :           0 : }
     977                 :             : 
     978                 :             : /*
     979                 :             :  * skip - skip white space and comments in expanded form
     980                 :             :  */
     981                 :             : static void
     982                 :           4 : skip(struct vars *v)
     983                 :             : {
     984                 :           4 :         const chr  *start = v->now;
     985                 :             : 
     986         [ +  - ]:           4 :         assert(v->cflags & REG_EXPANDED);
     987                 :             : 
     988                 :           4 :         for (;;)
     989                 :             :         {
     990   [ +  +  +  + ]:           8 :                 while (!ATEOS() && iscspace(*v->now))
     991                 :           4 :                         v->now++;
     992   [ +  +  +  - ]:           4 :                 if (ATEOS() || *v->now != CHR('#'))
     993                 :           4 :                         break;                          /* NOTE BREAK OUT */
     994         [ #  # ]:           0 :                 assert(NEXT1('#'));
     995   [ #  #  #  # ]:           0 :                 while (!ATEOS() && *v->now != CHR('\n'))
     996                 :           0 :                         v->now++;
     997                 :             :                 /* leave the newline to be picked up by the iscspace loop */
     998                 :             :         }
     999                 :             : 
    1000         [ -  + ]:           4 :         if (v->now != start)
    1001                 :           4 :                 NOTE(REG_UNONPOSIX);
    1002                 :           4 : }
    1003                 :             : 
    1004                 :             : /*
    1005                 :             :  * newline - return the chr for a newline
    1006                 :             :  *
    1007                 :             :  * This helps confine use of CHR to this source file.
    1008                 :             :  */
    1009                 :             : static chr
    1010                 :          23 : newline(void)
    1011                 :             : {
    1012                 :          23 :         return CHR('\n');
    1013                 :             : }
    1014                 :             : 
    1015                 :             : /*
    1016                 :             :  * chrnamed - return the chr known by a given (chr string) name
    1017                 :             :  *
    1018                 :             :  * The code is a bit clumsy, but this routine gets only such specialized
    1019                 :             :  * use that it hardly matters.
    1020                 :             :  */
    1021                 :             : static chr
    1022                 :           1 : chrnamed(struct vars *v,
    1023                 :             :                  const chr *startp,             /* start of name */
    1024                 :             :                  const chr *endp,               /* just past end of name */
    1025                 :             :                  chr lastresort)                /* what to return if name lookup fails */
    1026                 :             : {
    1027                 :           1 :         chr                     c;
    1028                 :           1 :         int                     errsave;
    1029                 :           1 :         int                     e;
    1030                 :           1 :         struct cvec *cv;
    1031                 :             : 
    1032                 :           1 :         errsave = v->err;
    1033                 :           1 :         v->err = 0;
    1034                 :           1 :         c = element(v, startp, endp);
    1035                 :           1 :         e = v->err;
    1036                 :           1 :         v->err = errsave;
    1037                 :             : 
    1038         [ -  + ]:           1 :         if (e != 0)
    1039                 :           0 :                 return lastresort;
    1040                 :             : 
    1041                 :           1 :         cv = range(v, c, c, 0);
    1042         [ -  + ]:           1 :         if (cv->nchrs == 0)
    1043                 :           1 :                 return lastresort;
    1044                 :           0 :         return cv->chrs[0];
    1045                 :           1 : }
        

Generated by: LCOV version 2.3.2-1