LCOV - differential code coverage report
Current view: top level - src/backend/regex - regc_lex.c (source / functions) Coverage Total Hit UBC CBC
Current: Differential Code Coverage HEAD vs 15 Lines: 94.9 % 553 525 28 525
Current Date: 2023-04-08 17:13:01 Functions: 100.0 % 9 9 9
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (180,240] days: 100.0 % 2 2 2
Legend: Lines: hit not hit (240..) days: 94.9 % 551 523 28 523
Function coverage date bins:
(240..) days: 100.0 % 9 9 9

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

Generated by: LCOV version v1.16-55-g56c0a2a