1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 1992, 1993, 1994 Henry Spencer. 5 * Copyright (c) 1992, 1993, 1994 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Copyright (c) 2011 The FreeBSD Foundation 9 * 10 * Portions of this software were developed by David Chisnall 11 * under sponsorship from the FreeBSD Foundation. 12 * 13 * This code is derived from software contributed to Berkeley by 14 * Henry Spencer. 15 * 16 * Redistribution and use in source and binary forms, with or without 17 * modification, are permitted provided that the following conditions 18 * are met: 19 * 1. Redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer. 21 * 2. Redistributions in binary form must reproduce the above copyright 22 * notice, this list of conditions and the following disclaimer in the 23 * documentation and/or other materials provided with the distribution. 24 * 3. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 * 40 * @(#)regcomp.c 8.5 (Berkeley) 3/20/94 41 */ 42 43 #if defined(LIBC_SCCS) && !defined(lint) 44 static char sccsid[] = "@(#)regcomp.c 8.5 (Berkeley) 3/20/94"; 45 #endif /* LIBC_SCCS and not lint */ 46 #include <sys/types.h> 47 #include <stdio.h> 48 #include <string.h> 49 #include <ctype.h> 50 #include <limits.h> 51 #include <stdlib.h> 52 #include <regex.h> 53 #include <stdbool.h> 54 #include <wchar.h> 55 #include <wctype.h> 56 57 #ifndef LIBREGEX 58 #include "collate.h" 59 #endif 60 61 #include "utils.h" 62 #include "regex2.h" 63 64 #include "cname.h" 65 66 /* 67 * Branching context, used to keep track of branch state for all of the branch- 68 * aware functions. In addition to keeping track of branch positions for the 69 * p_branch_* functions, we use this to simplify some clumsiness in BREs for 70 * detection of whether ^ is acting as an anchor or being used erroneously and 71 * also for whether we're in a sub-expression or not. 72 */ 73 struct branchc { 74 sopno start; 75 sopno back; 76 sopno fwd; 77 78 int nbranch; 79 int nchain; 80 bool outer; 81 bool terminate; 82 }; 83 84 /* 85 * parse structure, passed up and down to avoid global variables and 86 * other clumsinesses 87 */ 88 struct parse { 89 const char *next; /* next character in RE */ 90 const char *end; /* end of string (-> NUL normally) */ 91 int error; /* has an error been seen? */ 92 int gnuext; 93 sop *strip; /* malloced strip */ 94 sopno ssize; /* malloced strip size (allocated) */ 95 sopno slen; /* malloced strip length (used) */ 96 int ncsalloc; /* number of csets allocated */ 97 struct re_guts *g; 98 # define NPAREN 10 /* we need to remember () 1-9 for back refs */ 99 sopno pbegin[NPAREN]; /* -> ( ([0] unused) */ 100 sopno pend[NPAREN]; /* -> ) ([0] unused) */ 101 bool allowbranch; /* can this expression branch? */ 102 bool bre; /* convenience; is this a BRE? */ 103 int pflags; /* other parsing flags -- legacy escapes? */ 104 bool (*parse_expr)(struct parse *, struct branchc *); 105 void (*pre_parse)(struct parse *, struct branchc *); 106 void (*post_parse)(struct parse *, struct branchc *); 107 }; 108 109 #define PFLAG_LEGACY_ESC 0x00000001 110 111 /* ========= begin header generated by ./mkh ========= */ 112 #ifdef __cplusplus 113 extern "C" { 114 #endif 115 116 /* === regcomp.c === */ 117 static bool p_ere_exp(struct parse *p, struct branchc *bc); 118 static void p_str(struct parse *p); 119 static int p_branch_eat_delim(struct parse *p, struct branchc *bc); 120 static void p_branch_ins_offset(struct parse *p, struct branchc *bc); 121 static void p_branch_fix_tail(struct parse *p, struct branchc *bc); 122 static bool p_branch_empty(struct parse *p, struct branchc *bc); 123 static bool p_branch_do(struct parse *p, struct branchc *bc); 124 static void p_bre_pre_parse(struct parse *p, struct branchc *bc); 125 static void p_bre_post_parse(struct parse *p, struct branchc *bc); 126 static void p_re(struct parse *p, int end1, int end2); 127 static bool p_simp_re(struct parse *p, struct branchc *bc); 128 static int p_count(struct parse *p); 129 static void p_bracket(struct parse *p); 130 static int p_range_cmp(wchar_t c1, wchar_t c2); 131 static void p_b_term(struct parse *p, cset *cs); 132 static int p_b_pseudoclass(struct parse *p, char c); 133 static void p_b_cclass(struct parse *p, cset *cs); 134 static void p_b_cclass_named(struct parse *p, cset *cs, const char[]); 135 static void p_b_eclass(struct parse *p, cset *cs); 136 static wint_t p_b_symbol(struct parse *p); 137 static wint_t p_b_coll_elem(struct parse *p, wint_t endc); 138 static bool may_escape(struct parse *p, const wint_t ch); 139 static wint_t othercase(wint_t ch); 140 static void bothcases(struct parse *p, wint_t ch); 141 static void ordinary(struct parse *p, wint_t ch); 142 static void nonnewline(struct parse *p); 143 static void repeat(struct parse *p, sopno start, int from, int to); 144 static int seterr(struct parse *p, int e); 145 static cset *allocset(struct parse *p); 146 static void freeset(struct parse *p, cset *cs); 147 static void CHadd(struct parse *p, cset *cs, wint_t ch); 148 static void CHaddrange(struct parse *p, cset *cs, wint_t min, wint_t max); 149 static void CHaddtype(struct parse *p, cset *cs, wctype_t wct); 150 static wint_t singleton(cset *cs); 151 static sopno dupl(struct parse *p, sopno start, sopno finish); 152 static void doemit(struct parse *p, sop op, size_t opnd); 153 static void doinsert(struct parse *p, sop op, size_t opnd, sopno pos); 154 static void dofwd(struct parse *p, sopno pos, sop value); 155 static int enlarge(struct parse *p, sopno size); 156 static void stripsnug(struct parse *p, struct re_guts *g); 157 static void findmust(struct parse *p, struct re_guts *g); 158 static int altoffset(sop *scan, int offset); 159 static void computejumps(struct parse *p, struct re_guts *g); 160 static void computematchjumps(struct parse *p, struct re_guts *g); 161 static sopno pluscount(struct parse *p, struct re_guts *g); 162 static wint_t wgetnext(struct parse *p); 163 164 #ifdef __cplusplus 165 } 166 #endif 167 /* ========= end header generated by ./mkh ========= */ 168 169 static char nuls[10]; /* place to point scanner in event of error */ 170 171 /* 172 * macros for use with parse structure 173 * BEWARE: these know that the parse structure is named `p' !!! 174 */ 175 #define PEEK() (*p->next) 176 #define PEEK2() (*(p->next+1)) 177 #define MORE() (p->end - p->next > 0) 178 #define MORE2() (p->end - p->next > 1) 179 #define SEE(c) (MORE() && PEEK() == (c)) 180 #define SEETWO(a, b) (MORE2() && PEEK() == (a) && PEEK2() == (b)) 181 #define SEESPEC(a) (p->bre ? SEETWO('\\', a) : SEE(a)) 182 #define EAT(c) ((SEE(c)) ? (NEXT(), 1) : 0) 183 #define EATTWO(a, b) ((SEETWO(a, b)) ? (NEXT2(), 1) : 0) 184 #define EATSPEC(a) (p->bre ? EATTWO('\\', a) : EAT(a)) 185 #define NEXT() (p->next++) 186 #define NEXT2() (p->next += 2) 187 #define NEXTn(n) (p->next += (n)) 188 #define GETNEXT() (*p->next++) 189 #define WGETNEXT() wgetnext(p) 190 #define SETERROR(e) seterr(p, (e)) 191 #define REQUIRE(co, e) ((co) || SETERROR(e)) 192 #define MUSTSEE(c, e) (REQUIRE(MORE() && PEEK() == (c), e)) 193 #define MUSTEAT(c, e) (REQUIRE(MORE() && GETNEXT() == (c), e)) 194 #define MUSTNOTSEE(c, e) (REQUIRE(!MORE() || PEEK() != (c), e)) 195 #define EMIT(op, sopnd) doemit(p, (sop)(op), (size_t)(sopnd)) 196 #define INSERT(op, pos) doinsert(p, (sop)(op), HERE()-(pos)+1, pos) 197 #define AHEAD(pos) dofwd(p, pos, HERE()-(pos)) 198 #define ASTERN(sop, pos) EMIT(sop, HERE()-pos) 199 #define HERE() (p->slen) 200 #define THERE() (p->slen - 1) 201 #define THERETHERE() (p->slen - 2) 202 #define DROP(n) (p->slen -= (n)) 203 204 /* Macro used by computejump()/computematchjump() */ 205 #define MIN(a,b) ((a)<(b)?(a):(b)) 206 207 static int /* 0 success, otherwise REG_something */ 208 regcomp_internal(regex_t * __restrict preg, 209 const char * __restrict pattern, 210 int cflags, int pflags) 211 { 212 struct parse pa; 213 struct re_guts *g; 214 struct parse *p = &pa; 215 int i; 216 size_t len; 217 size_t maxlen; 218 #ifdef REDEBUG 219 # define GOODFLAGS(f) (f) 220 #else 221 # define GOODFLAGS(f) ((f)&~REG_DUMP) 222 #endif 223 224 cflags = GOODFLAGS(cflags); 225 if ((cflags®_EXTENDED) && (cflags®_NOSPEC)) 226 return(REG_INVARG); 227 228 if (cflags®_PEND) { 229 if (preg->re_endp < pattern) 230 return(REG_INVARG); 231 len = preg->re_endp - pattern; 232 } else 233 len = strlen(pattern); 234 235 /* do the mallocs early so failure handling is easy */ 236 g = (struct re_guts *)malloc(sizeof(struct re_guts)); 237 if (g == NULL) 238 return(REG_ESPACE); 239 /* 240 * Limit the pattern space to avoid a 32-bit overflow on buffer 241 * extension. Also avoid any signed overflow in case of conversion 242 * so make the real limit based on a 31-bit overflow. 243 * 244 * Likely not applicable on 64-bit systems but handle the case 245 * generically (who are we to stop people from using ~715MB+ 246 * patterns?). 247 */ 248 maxlen = ((size_t)-1 >> 1) / sizeof(sop) * 2 / 3; 249 if (len >= maxlen) { 250 free((char *)g); 251 return(REG_ESPACE); 252 } 253 p->ssize = len/(size_t)2*(size_t)3 + (size_t)1; /* ugh */ 254 assert(p->ssize >= len); 255 256 p->strip = (sop *)malloc(p->ssize * sizeof(sop)); 257 p->slen = 0; 258 if (p->strip == NULL) { 259 free((char *)g); 260 return(REG_ESPACE); 261 } 262 263 /* set things up */ 264 p->g = g; 265 p->next = pattern; /* convenience; we do not modify it */ 266 p->end = p->next + len; 267 p->error = 0; 268 p->ncsalloc = 0; 269 p->pflags = pflags; 270 for (i = 0; i < NPAREN; i++) { 271 p->pbegin[i] = 0; 272 p->pend[i] = 0; 273 } 274 #ifdef LIBREGEX 275 if (cflags®_POSIX) { 276 p->gnuext = false; 277 p->allowbranch = (cflags & REG_EXTENDED) != 0; 278 } else 279 p->gnuext = p->allowbranch = true; 280 #else 281 p->gnuext = false; 282 p->allowbranch = (cflags & REG_EXTENDED) != 0; 283 #endif 284 if (cflags & REG_EXTENDED) { 285 p->bre = false; 286 p->parse_expr = p_ere_exp; 287 p->pre_parse = NULL; 288 p->post_parse = NULL; 289 } else { 290 p->bre = true; 291 p->parse_expr = p_simp_re; 292 p->pre_parse = p_bre_pre_parse; 293 p->post_parse = p_bre_post_parse; 294 } 295 g->sets = NULL; 296 g->ncsets = 0; 297 g->cflags = cflags; 298 g->iflags = 0; 299 g->nbol = 0; 300 g->neol = 0; 301 g->must = NULL; 302 g->moffset = -1; 303 g->charjump = NULL; 304 g->matchjump = NULL; 305 g->mlen = 0; 306 g->nsub = 0; 307 g->backrefs = 0; 308 309 /* do it */ 310 EMIT(OEND, 0); 311 g->firststate = THERE(); 312 if (cflags & REG_NOSPEC) 313 p_str(p); 314 else 315 p_re(p, OUT, OUT); 316 EMIT(OEND, 0); 317 g->laststate = THERE(); 318 319 /* tidy up loose ends and fill things in */ 320 stripsnug(p, g); 321 findmust(p, g); 322 /* only use Boyer-Moore algorithm if the pattern is bigger 323 * than three characters 324 */ 325 if(g->mlen > 3) { 326 computejumps(p, g); 327 computematchjumps(p, g); 328 if(g->matchjump == NULL && g->charjump != NULL) { 329 free(g->charjump); 330 g->charjump = NULL; 331 } 332 } 333 g->nplus = pluscount(p, g); 334 g->magic = MAGIC2; 335 preg->re_nsub = g->nsub; 336 preg->re_g = g; 337 preg->re_magic = MAGIC1; 338 #ifndef REDEBUG 339 /* not debugging, so can't rely on the assert() in regexec() */ 340 if (g->iflags&BAD) 341 SETERROR(REG_ASSERT); 342 #endif 343 344 /* win or lose, we're done */ 345 if (p->error != 0) /* lose */ 346 regfree(preg); 347 return(p->error); 348 } 349 350 /* 351 - regcomp - interface for parser and compilation 352 = extern int regcomp(regex_t *, const char *, int); 353 = #define REG_BASIC 0000 354 = #define REG_EXTENDED 0001 355 = #define REG_ICASE 0002 356 = #define REG_NOSUB 0004 357 = #define REG_NEWLINE 0010 358 = #define REG_NOSPEC 0020 359 = #define REG_PEND 0040 360 = #define REG_DUMP 0200 361 */ 362 int /* 0 success, otherwise REG_something */ 363 regcomp(regex_t * __restrict preg, 364 const char * __restrict pattern, 365 int cflags) 366 { 367 368 return (regcomp_internal(preg, pattern, cflags, 0)); 369 } 370 371 #ifndef LIBREGEX 372 /* 373 * Legacy interface that requires more lax escaping behavior. 374 */ 375 int 376 freebsd12_regcomp(regex_t * __restrict preg, 377 const char * __restrict pattern, 378 int cflags, int pflags) 379 { 380 381 return (regcomp_internal(preg, pattern, cflags, PFLAG_LEGACY_ESC)); 382 } 383 384 __sym_compat(regcomp, freebsd12_regcomp, FBSD_1.0); 385 #endif /* !LIBREGEX */ 386 387 /* 388 - p_ere_exp - parse one subERE, an atom possibly followed by a repetition op, 389 - return whether we should terminate or not 390 == static bool p_ere_exp(struct parse *p); 391 */ 392 static bool 393 p_ere_exp(struct parse *p, struct branchc *bc) 394 { 395 char c; 396 wint_t wc; 397 sopno pos; 398 int count; 399 int count2; 400 #ifdef LIBREGEX 401 int i; 402 int handled; 403 #endif 404 sopno subno; 405 int wascaret = 0; 406 407 (void)bc; 408 assert(MORE()); /* caller should have ensured this */ 409 c = GETNEXT(); 410 411 #ifdef LIBREGEX 412 handled = 0; 413 #endif 414 pos = HERE(); 415 switch (c) { 416 case '(': 417 (void)REQUIRE(MORE(), REG_EPAREN); 418 p->g->nsub++; 419 subno = p->g->nsub; 420 if (subno < NPAREN) 421 p->pbegin[subno] = HERE(); 422 EMIT(OLPAREN, subno); 423 if (!SEE(')')) 424 p_re(p, ')', IGN); 425 if (subno < NPAREN) { 426 p->pend[subno] = HERE(); 427 assert(p->pend[subno] != 0); 428 } 429 EMIT(ORPAREN, subno); 430 (void)MUSTEAT(')', REG_EPAREN); 431 break; 432 #ifndef POSIX_MISTAKE 433 case ')': /* happens only if no current unmatched ( */ 434 /* 435 * You may ask, why the ifndef? Because I didn't notice 436 * this until slightly too late for 1003.2, and none of the 437 * other 1003.2 regular-expression reviewers noticed it at 438 * all. So an unmatched ) is legal POSIX, at least until 439 * we can get it fixed. 440 */ 441 SETERROR(REG_EPAREN); 442 break; 443 #endif 444 case '^': 445 EMIT(OBOL, 0); 446 p->g->iflags |= USEBOL; 447 p->g->nbol++; 448 wascaret = 1; 449 break; 450 case '$': 451 EMIT(OEOL, 0); 452 p->g->iflags |= USEEOL; 453 p->g->neol++; 454 break; 455 case '|': 456 SETERROR(REG_EMPTY); 457 break; 458 case '*': 459 case '+': 460 case '?': 461 case '{': 462 SETERROR(REG_BADRPT); 463 break; 464 case '.': 465 if (p->g->cflags®_NEWLINE) 466 nonnewline(p); 467 else 468 EMIT(OANY, 0); 469 break; 470 case '[': 471 p_bracket(p); 472 break; 473 case '\\': 474 (void)REQUIRE(MORE(), REG_EESCAPE); 475 wc = WGETNEXT(); 476 #ifdef LIBREGEX 477 if (p->gnuext) { 478 handled = 1; 479 switch (wc) { 480 case '`': 481 EMIT(OBOS, 0); 482 break; 483 case '\'': 484 EMIT(OEOS, 0); 485 break; 486 case 'B': 487 EMIT(ONWBND, 0); 488 break; 489 case 'b': 490 EMIT(OWBND, 0); 491 break; 492 case 'W': 493 case 'w': 494 case 'S': 495 case 's': 496 p_b_pseudoclass(p, wc); 497 break; 498 case '1': 499 case '2': 500 case '3': 501 case '4': 502 case '5': 503 case '6': 504 case '7': 505 case '8': 506 case '9': 507 i = wc - '0'; 508 assert(i < NPAREN); 509 if (p->pend[i] != 0) { 510 assert(i <= p->g->nsub); 511 EMIT(OBACK_, i); 512 assert(p->pbegin[i] != 0); 513 assert(OP(p->strip[p->pbegin[i]]) == OLPAREN); 514 assert(OP(p->strip[p->pend[i]]) == ORPAREN); 515 (void) dupl(p, p->pbegin[i]+1, p->pend[i]); 516 EMIT(O_BACK, i); 517 } else 518 SETERROR(REG_ESUBREG); 519 p->g->backrefs = 1; 520 break; 521 default: 522 handled = 0; 523 } 524 /* Don't proceed to the POSIX bits if we've already handled it */ 525 if (handled) 526 break; 527 } 528 #endif 529 switch (wc) { 530 case '<': 531 EMIT(OBOW, 0); 532 break; 533 case '>': 534 EMIT(OEOW, 0); 535 break; 536 default: 537 if (may_escape(p, wc)) 538 ordinary(p, wc); 539 else 540 SETERROR(REG_EESCAPE); 541 break; 542 } 543 break; 544 default: 545 if (p->error != 0) 546 return (false); 547 p->next--; 548 wc = WGETNEXT(); 549 ordinary(p, wc); 550 break; 551 } 552 553 if (!MORE()) 554 return (false); 555 c = PEEK(); 556 /* we call { a repetition if followed by a digit */ 557 if (!( c == '*' || c == '+' || c == '?' || c == '{')) 558 return (false); /* no repetition, we're done */ 559 else if (c == '{') 560 (void)REQUIRE(MORE2() && \ 561 (isdigit((uch)PEEK2()) || PEEK2() == ','), REG_BADRPT); 562 NEXT(); 563 564 (void)REQUIRE(!wascaret, REG_BADRPT); 565 switch (c) { 566 case '*': /* implemented as +? */ 567 /* this case does not require the (y|) trick, noKLUDGE */ 568 INSERT(OPLUS_, pos); 569 ASTERN(O_PLUS, pos); 570 INSERT(OQUEST_, pos); 571 ASTERN(O_QUEST, pos); 572 break; 573 case '+': 574 INSERT(OPLUS_, pos); 575 ASTERN(O_PLUS, pos); 576 break; 577 case '?': 578 /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */ 579 INSERT(OCH_, pos); /* offset slightly wrong */ 580 ASTERN(OOR1, pos); /* this one's right */ 581 AHEAD(pos); /* fix the OCH_ */ 582 EMIT(OOR2, 0); /* offset very wrong... */ 583 AHEAD(THERE()); /* ...so fix it */ 584 ASTERN(O_CH, THERETHERE()); 585 break; 586 case '{': 587 count = p_count(p); 588 if (EAT(',')) { 589 if (isdigit((uch)PEEK())) { 590 count2 = p_count(p); 591 (void)REQUIRE(count <= count2, REG_BADBR); 592 } else /* single number with comma */ 593 count2 = INFINITY; 594 } else /* just a single number */ 595 count2 = count; 596 repeat(p, pos, count, count2); 597 if (!EAT('}')) { /* error heuristics */ 598 while (MORE() && PEEK() != '}') 599 NEXT(); 600 (void)REQUIRE(MORE(), REG_EBRACE); 601 SETERROR(REG_BADBR); 602 } 603 break; 604 } 605 606 if (!MORE()) 607 return (false); 608 c = PEEK(); 609 if (!( c == '*' || c == '+' || c == '?' || 610 (c == '{' && MORE2() && isdigit((uch)PEEK2())) ) ) 611 return (false); 612 SETERROR(REG_BADRPT); 613 return (false); 614 } 615 616 /* 617 - p_str - string (no metacharacters) "parser" 618 == static void p_str(struct parse *p); 619 */ 620 static void 621 p_str(struct parse *p) 622 { 623 (void)REQUIRE(MORE(), REG_EMPTY); 624 while (MORE()) 625 ordinary(p, WGETNEXT()); 626 } 627 628 /* 629 * Eat consecutive branch delimiters for the kind of expression that we are 630 * parsing, return the number of delimiters that we ate. 631 */ 632 static int 633 p_branch_eat_delim(struct parse *p, struct branchc *bc) 634 { 635 int nskip; 636 637 (void)bc; 638 nskip = 0; 639 while (EATSPEC('|')) 640 ++nskip; 641 return (nskip); 642 } 643 644 /* 645 * Insert necessary branch book-keeping operations. This emits a 646 * bogus 'next' offset, since we still have more to parse 647 */ 648 static void 649 p_branch_ins_offset(struct parse *p, struct branchc *bc) 650 { 651 652 if (bc->nbranch == 0) { 653 INSERT(OCH_, bc->start); /* offset is wrong */ 654 bc->fwd = bc->start; 655 bc->back = bc->start; 656 } 657 658 ASTERN(OOR1, bc->back); 659 bc->back = THERE(); 660 AHEAD(bc->fwd); /* fix previous offset */ 661 bc->fwd = HERE(); 662 EMIT(OOR2, 0); /* offset is very wrong */ 663 ++bc->nbranch; 664 } 665 666 /* 667 * Fix the offset of the tail branch, if we actually had any branches. 668 * This is to correct the bogus placeholder offset that we use. 669 */ 670 static void 671 p_branch_fix_tail(struct parse *p, struct branchc *bc) 672 { 673 674 /* Fix bogus offset at the tail if we actually have branches */ 675 if (bc->nbranch > 0) { 676 AHEAD(bc->fwd); 677 ASTERN(O_CH, bc->back); 678 } 679 } 680 681 /* 682 * Signal to the parser that an empty branch has been encountered; this will, 683 * in the future, be used to allow for more permissive behavior with empty 684 * branches. The return value should indicate whether parsing may continue 685 * or not. 686 */ 687 static bool 688 p_branch_empty(struct parse *p, struct branchc *bc) 689 { 690 691 (void)bc; 692 SETERROR(REG_EMPTY); 693 return (false); 694 } 695 696 /* 697 * Take care of any branching requirements. This includes inserting the 698 * appropriate branching instructions as well as eating all of the branch 699 * delimiters until we either run out of pattern or need to parse more pattern. 700 */ 701 static bool 702 p_branch_do(struct parse *p, struct branchc *bc) 703 { 704 int ate = 0; 705 706 ate = p_branch_eat_delim(p, bc); 707 if (ate == 0) 708 return (false); 709 else if ((ate > 1 || (bc->outer && !MORE())) && !p_branch_empty(p, bc)) 710 /* 711 * Halt parsing only if we have an empty branch and p_branch_empty 712 * indicates that we must not continue. In the future, this will not 713 * necessarily be an error. 714 */ 715 return (false); 716 p_branch_ins_offset(p, bc); 717 718 return (true); 719 } 720 721 static void 722 p_bre_pre_parse(struct parse *p, struct branchc *bc) 723 { 724 725 (void) bc; 726 /* 727 * Does not move cleanly into expression parser because of 728 * ordinary interpration of * at the beginning position of 729 * an expression. 730 */ 731 if (EAT('^')) { 732 EMIT(OBOL, 0); 733 p->g->iflags |= USEBOL; 734 p->g->nbol++; 735 } 736 } 737 738 static void 739 p_bre_post_parse(struct parse *p, struct branchc *bc) 740 { 741 742 /* Expression is terminating due to EOL token */ 743 if (bc->terminate) { 744 DROP(1); 745 EMIT(OEOL, 0); 746 p->g->iflags |= USEEOL; 747 p->g->neol++; 748 } 749 } 750 751 /* 752 - p_re - Top level parser, concatenation and BRE anchoring 753 == static void p_re(struct parse *p, int end1, int end2); 754 * Giving end1 as OUT essentially eliminates the end1/end2 check. 755 * 756 * This implementation is a bit of a kludge, in that a trailing $ is first 757 * taken as an ordinary character and then revised to be an anchor. 758 * The amount of lookahead needed to avoid this kludge is excessive. 759 */ 760 static void 761 p_re(struct parse *p, 762 int end1, /* first terminating character */ 763 int end2) /* second terminating character; ignored for EREs */ 764 { 765 struct branchc bc; 766 767 bc.nbranch = 0; 768 if (end1 == OUT && end2 == OUT) 769 bc.outer = true; 770 else 771 bc.outer = false; 772 #define SEEEND() (!p->bre ? SEE(end1) : SEETWO(end1, end2)) 773 for (;;) { 774 bc.start = HERE(); 775 bc.nchain = 0; 776 bc.terminate = false; 777 if (p->pre_parse != NULL) 778 p->pre_parse(p, &bc); 779 while (MORE() && (!p->allowbranch || !SEESPEC('|')) && !SEEEND()) { 780 bc.terminate = p->parse_expr(p, &bc); 781 ++bc.nchain; 782 } 783 if (p->post_parse != NULL) 784 p->post_parse(p, &bc); 785 (void) REQUIRE(p->gnuext || HERE() != bc.start, REG_EMPTY); 786 #ifdef LIBREGEX 787 if (HERE() == bc.start && !p_branch_empty(p, &bc)) 788 break; 789 #endif 790 if (!p->allowbranch) 791 break; 792 /* 793 * p_branch_do's return value indicates whether we should 794 * continue parsing or not. This is both for correctness and 795 * a slight optimization, because it will check if we've 796 * encountered an empty branch or the end of the string 797 * immediately following a branch delimiter. 798 */ 799 if (!p_branch_do(p, &bc)) 800 break; 801 } 802 #undef SEE_END 803 if (p->allowbranch) 804 p_branch_fix_tail(p, &bc); 805 assert(!MORE() || SEE(end1)); 806 } 807 808 /* 809 - p_simp_re - parse a simple RE, an atom possibly followed by a repetition 810 == static bool p_simp_re(struct parse *p, struct branchc *bc); 811 */ 812 static bool /* was the simple RE an unbackslashed $? */ 813 p_simp_re(struct parse *p, struct branchc *bc) 814 { 815 int c; 816 int cc; /* convenient/control character */ 817 int count; 818 int count2; 819 sopno pos; 820 bool handled; 821 int i; 822 wint_t wc; 823 sopno subno; 824 # define BACKSL (1<<CHAR_BIT) 825 826 pos = HERE(); /* repetition op, if any, covers from here */ 827 handled = false; 828 829 assert(MORE()); /* caller should have ensured this */ 830 c = (uch)GETNEXT(); 831 if (c == '\\') { 832 (void)REQUIRE(MORE(), REG_EESCAPE); 833 cc = (uch)GETNEXT(); 834 c = BACKSL | cc; 835 #ifdef LIBREGEX 836 if (p->gnuext) { 837 handled = true; 838 switch (c) { 839 case BACKSL|'`': 840 EMIT(OBOS, 0); 841 break; 842 case BACKSL|'\'': 843 EMIT(OEOS, 0); 844 break; 845 case BACKSL|'B': 846 EMIT(ONWBND, 0); 847 break; 848 case BACKSL|'b': 849 EMIT(OWBND, 0); 850 break; 851 case BACKSL|'W': 852 case BACKSL|'w': 853 case BACKSL|'S': 854 case BACKSL|'s': 855 p_b_pseudoclass(p, cc); 856 break; 857 default: 858 handled = false; 859 } 860 } 861 #endif 862 } 863 if (!handled) { 864 switch (c) { 865 case '.': 866 if (p->g->cflags®_NEWLINE) 867 nonnewline(p); 868 else 869 EMIT(OANY, 0); 870 break; 871 case '[': 872 p_bracket(p); 873 break; 874 case BACKSL|'<': 875 EMIT(OBOW, 0); 876 break; 877 case BACKSL|'>': 878 EMIT(OEOW, 0); 879 break; 880 case BACKSL|'{': 881 SETERROR(REG_BADRPT); 882 break; 883 case BACKSL|'(': 884 p->g->nsub++; 885 subno = p->g->nsub; 886 if (subno < NPAREN) 887 p->pbegin[subno] = HERE(); 888 EMIT(OLPAREN, subno); 889 /* the MORE here is an error heuristic */ 890 if (MORE() && !SEETWO('\\', ')')) 891 p_re(p, '\\', ')'); 892 if (subno < NPAREN) { 893 p->pend[subno] = HERE(); 894 assert(p->pend[subno] != 0); 895 } 896 EMIT(ORPAREN, subno); 897 (void)REQUIRE(EATTWO('\\', ')'), REG_EPAREN); 898 break; 899 case BACKSL|')': /* should not get here -- must be user */ 900 SETERROR(REG_EPAREN); 901 break; 902 case BACKSL|'1': 903 case BACKSL|'2': 904 case BACKSL|'3': 905 case BACKSL|'4': 906 case BACKSL|'5': 907 case BACKSL|'6': 908 case BACKSL|'7': 909 case BACKSL|'8': 910 case BACKSL|'9': 911 i = (c&~BACKSL) - '0'; 912 assert(i < NPAREN); 913 if (p->pend[i] != 0) { 914 assert(i <= p->g->nsub); 915 EMIT(OBACK_, i); 916 assert(p->pbegin[i] != 0); 917 assert(OP(p->strip[p->pbegin[i]]) == OLPAREN); 918 assert(OP(p->strip[p->pend[i]]) == ORPAREN); 919 (void) dupl(p, p->pbegin[i]+1, p->pend[i]); 920 EMIT(O_BACK, i); 921 } else 922 SETERROR(REG_ESUBREG); 923 p->g->backrefs = 1; 924 break; 925 case '*': 926 /* 927 * Ordinary if used as the first character beyond BOL anchor of 928 * a (sub-)expression, counts as a bad repetition operator if it 929 * appears otherwise. 930 */ 931 (void)REQUIRE(bc->nchain == 0, REG_BADRPT); 932 /* FALLTHROUGH */ 933 default: 934 if (p->error != 0) 935 return (false); /* Definitely not $... */ 936 p->next--; 937 wc = WGETNEXT(); 938 if ((c & BACKSL) == 0 || may_escape(p, wc)) 939 ordinary(p, wc); 940 else 941 SETERROR(REG_EESCAPE); 942 break; 943 } 944 } 945 946 if (EAT('*')) { /* implemented as +? */ 947 /* this case does not require the (y|) trick, noKLUDGE */ 948 INSERT(OPLUS_, pos); 949 ASTERN(O_PLUS, pos); 950 INSERT(OQUEST_, pos); 951 ASTERN(O_QUEST, pos); 952 #ifdef LIBREGEX 953 } else if (p->gnuext && EATTWO('\\', '?')) { 954 INSERT(OQUEST_, pos); 955 ASTERN(O_QUEST, pos); 956 } else if (p->gnuext && EATTWO('\\', '+')) { 957 INSERT(OPLUS_, pos); 958 ASTERN(O_PLUS, pos); 959 #endif 960 } else if (EATTWO('\\', '{')) { 961 count = p_count(p); 962 if (EAT(',')) { 963 if (MORE() && isdigit((uch)PEEK())) { 964 count2 = p_count(p); 965 (void)REQUIRE(count <= count2, REG_BADBR); 966 } else /* single number with comma */ 967 count2 = INFINITY; 968 } else /* just a single number */ 969 count2 = count; 970 repeat(p, pos, count, count2); 971 if (!EATTWO('\\', '}')) { /* error heuristics */ 972 while (MORE() && !SEETWO('\\', '}')) 973 NEXT(); 974 (void)REQUIRE(MORE(), REG_EBRACE); 975 SETERROR(REG_BADBR); 976 } 977 } else if (c == '$') /* $ (but not \$) ends it */ 978 return (true); 979 980 return (false); 981 } 982 983 /* 984 - p_count - parse a repetition count 985 == static int p_count(struct parse *p); 986 */ 987 static int /* the value */ 988 p_count(struct parse *p) 989 { 990 int count = 0; 991 int ndigits = 0; 992 993 while (MORE() && isdigit((uch)PEEK()) && count <= DUPMAX) { 994 count = count*10 + ((uch)GETNEXT() - '0'); 995 ndigits++; 996 } 997 998 (void)REQUIRE(ndigits > 0 && count <= DUPMAX, REG_BADBR); 999 return(count); 1000 } 1001 1002 /* 1003 - p_bracket - parse a bracketed character list 1004 == static void p_bracket(struct parse *p); 1005 */ 1006 static void 1007 p_bracket(struct parse *p) 1008 { 1009 cset *cs; 1010 wint_t ch; 1011 1012 /* Dept of Truly Sickening Special-Case Kludges */ 1013 if (p->end - p->next > 5) { 1014 if (strncmp(p->next, "[:<:]]", 6) == 0) { 1015 EMIT(OBOW, 0); 1016 NEXTn(6); 1017 return; 1018 } 1019 if (strncmp(p->next, "[:>:]]", 6) == 0) { 1020 EMIT(OEOW, 0); 1021 NEXTn(6); 1022 return; 1023 } 1024 } 1025 1026 if ((cs = allocset(p)) == NULL) 1027 return; 1028 1029 if (p->g->cflags®_ICASE) 1030 cs->icase = 1; 1031 if (EAT('^')) 1032 cs->invert = 1; 1033 if (EAT(']')) 1034 CHadd(p, cs, ']'); 1035 else if (EAT('-')) 1036 CHadd(p, cs, '-'); 1037 while (MORE() && PEEK() != ']' && !SEETWO('-', ']')) 1038 p_b_term(p, cs); 1039 if (EAT('-')) 1040 CHadd(p, cs, '-'); 1041 (void)MUSTEAT(']', REG_EBRACK); 1042 1043 if (p->error != 0) /* don't mess things up further */ 1044 return; 1045 1046 if (cs->invert && p->g->cflags®_NEWLINE) 1047 cs->bmp['\n' >> 3] |= 1 << ('\n' & 7); 1048 1049 if ((ch = singleton(cs)) != OUT) { /* optimize singleton sets */ 1050 ordinary(p, ch); 1051 freeset(p, cs); 1052 } else 1053 EMIT(OANYOF, (int)(cs - p->g->sets)); 1054 } 1055 1056 static int 1057 p_range_cmp(wchar_t c1, wchar_t c2) 1058 { 1059 #ifndef LIBREGEX 1060 return __wcollate_range_cmp(c1, c2); 1061 #else 1062 /* Copied from libc/collate __wcollate_range_cmp */ 1063 wchar_t s1[2], s2[2]; 1064 1065 s1[0] = c1; 1066 s1[1] = L'\0'; 1067 s2[0] = c2; 1068 s2[1] = L'\0'; 1069 return (wcscoll(s1, s2)); 1070 #endif 1071 } 1072 1073 /* 1074 - p_b_term - parse one term of a bracketed character list 1075 == static void p_b_term(struct parse *p, cset *cs); 1076 */ 1077 static void 1078 p_b_term(struct parse *p, cset *cs) 1079 { 1080 char c; 1081 wint_t start, finish; 1082 wint_t i; 1083 #ifndef LIBREGEX 1084 struct xlocale_collate *table = 1085 (struct xlocale_collate*)__get_locale()->components[XLC_COLLATE]; 1086 #endif 1087 /* classify what we've got */ 1088 switch ((MORE()) ? PEEK() : '\0') { 1089 case '[': 1090 c = (MORE2()) ? PEEK2() : '\0'; 1091 break; 1092 case '-': 1093 SETERROR(REG_ERANGE); 1094 return; /* NOTE RETURN */ 1095 default: 1096 c = '\0'; 1097 break; 1098 } 1099 1100 switch (c) { 1101 case ':': /* character class */ 1102 NEXT2(); 1103 (void)REQUIRE(MORE(), REG_EBRACK); 1104 c = PEEK(); 1105 (void)REQUIRE(c != '-' && c != ']', REG_ECTYPE); 1106 p_b_cclass(p, cs); 1107 (void)REQUIRE(MORE(), REG_EBRACK); 1108 (void)REQUIRE(EATTWO(':', ']'), REG_ECTYPE); 1109 break; 1110 case '=': /* equivalence class */ 1111 NEXT2(); 1112 (void)REQUIRE(MORE(), REG_EBRACK); 1113 c = PEEK(); 1114 (void)REQUIRE(c != '-' && c != ']', REG_ECOLLATE); 1115 p_b_eclass(p, cs); 1116 (void)REQUIRE(MORE(), REG_EBRACK); 1117 (void)REQUIRE(EATTWO('=', ']'), REG_ECOLLATE); 1118 break; 1119 default: /* symbol, ordinary character, or range */ 1120 start = p_b_symbol(p); 1121 if (SEE('-') && MORE2() && PEEK2() != ']') { 1122 /* range */ 1123 NEXT(); 1124 if (EAT('-')) 1125 finish = '-'; 1126 else 1127 finish = p_b_symbol(p); 1128 } else 1129 finish = start; 1130 if (start == finish) 1131 CHadd(p, cs, start); 1132 else { 1133 #ifndef LIBREGEX 1134 if (table->__collate_load_error || MB_CUR_MAX > 1) { 1135 #else 1136 if (MB_CUR_MAX > 1) { 1137 #endif 1138 (void)REQUIRE(start <= finish, REG_ERANGE); 1139 CHaddrange(p, cs, start, finish); 1140 } else { 1141 (void)REQUIRE(p_range_cmp(start, finish) <= 0, REG_ERANGE); 1142 for (i = 0; i <= UCHAR_MAX; i++) { 1143 if (p_range_cmp(start, i) <= 0 && 1144 p_range_cmp(i, finish) <= 0 ) 1145 CHadd(p, cs, i); 1146 } 1147 } 1148 } 1149 break; 1150 } 1151 } 1152 1153 /* 1154 - p_b_pseudoclass - parse a pseudo-class (\w, \W, \s, \S) 1155 == static int p_b_pseudoclass(struct parse *p, char c) 1156 */ 1157 static int 1158 p_b_pseudoclass(struct parse *p, char c) { 1159 cset *cs; 1160 1161 if ((cs = allocset(p)) == NULL) 1162 return(0); 1163 1164 if (p->g->cflags®_ICASE) 1165 cs->icase = 1; 1166 1167 switch (c) { 1168 case 'W': 1169 cs->invert = 1; 1170 /* PASSTHROUGH */ 1171 case 'w': 1172 p_b_cclass_named(p, cs, "alnum"); 1173 break; 1174 case 'S': 1175 cs->invert = 1; 1176 /* PASSTHROUGH */ 1177 case 's': 1178 p_b_cclass_named(p, cs, "space"); 1179 break; 1180 default: 1181 return(0); 1182 } 1183 1184 EMIT(OANYOF, (int)(cs - p->g->sets)); 1185 return(1); 1186 } 1187 1188 /* 1189 - p_b_cclass - parse a character-class name and deal with it 1190 == static void p_b_cclass(struct parse *p, cset *cs); 1191 */ 1192 static void 1193 p_b_cclass(struct parse *p, cset *cs) 1194 { 1195 const char *sp = p->next; 1196 size_t len; 1197 char clname[16]; 1198 1199 while (MORE() && isalpha((uch)PEEK())) 1200 NEXT(); 1201 len = p->next - sp; 1202 if (len >= sizeof(clname) - 1) { 1203 SETERROR(REG_ECTYPE); 1204 return; 1205 } 1206 memcpy(clname, sp, len); 1207 clname[len] = '\0'; 1208 1209 p_b_cclass_named(p, cs, clname); 1210 } 1211 /* 1212 - p_b_cclass_named - deal with a named character class 1213 == static void p_b_cclass_named(struct parse *p, cset *cs, const char []); 1214 */ 1215 static void 1216 p_b_cclass_named(struct parse *p, cset *cs, const char clname[]) { 1217 wctype_t wct; 1218 1219 if ((wct = wctype(clname)) == 0) { 1220 SETERROR(REG_ECTYPE); 1221 return; 1222 } 1223 CHaddtype(p, cs, wct); 1224 } 1225 1226 /* 1227 - p_b_eclass - parse an equivalence-class name and deal with it 1228 == static void p_b_eclass(struct parse *p, cset *cs); 1229 * 1230 * This implementation is incomplete. xxx 1231 */ 1232 static void 1233 p_b_eclass(struct parse *p, cset *cs) 1234 { 1235 wint_t c; 1236 1237 c = p_b_coll_elem(p, '='); 1238 CHadd(p, cs, c); 1239 } 1240 1241 /* 1242 - p_b_symbol - parse a character or [..]ed multicharacter collating symbol 1243 == static wint_t p_b_symbol(struct parse *p); 1244 */ 1245 static wint_t /* value of symbol */ 1246 p_b_symbol(struct parse *p) 1247 { 1248 wint_t value; 1249 1250 (void)REQUIRE(MORE(), REG_EBRACK); 1251 if (!EATTWO('[', '.')) 1252 return(WGETNEXT()); 1253 1254 /* collating symbol */ 1255 value = p_b_coll_elem(p, '.'); 1256 (void)REQUIRE(EATTWO('.', ']'), REG_ECOLLATE); 1257 return(value); 1258 } 1259 1260 /* 1261 - p_b_coll_elem - parse a collating-element name and look it up 1262 == static wint_t p_b_coll_elem(struct parse *p, wint_t endc); 1263 */ 1264 static wint_t /* value of collating element */ 1265 p_b_coll_elem(struct parse *p, 1266 wint_t endc) /* name ended by endc,']' */ 1267 { 1268 const char *sp = p->next; 1269 struct cname *cp; 1270 mbstate_t mbs; 1271 wchar_t wc; 1272 size_t clen, len; 1273 1274 while (MORE() && !SEETWO(endc, ']')) 1275 NEXT(); 1276 if (!MORE()) { 1277 SETERROR(REG_EBRACK); 1278 return(0); 1279 } 1280 len = p->next - sp; 1281 for (cp = cnames; cp->name != NULL; cp++) 1282 if (strncmp(cp->name, sp, len) == 0 && strlen(cp->name) == len) 1283 return(cp->code); /* known name */ 1284 memset(&mbs, 0, sizeof(mbs)); 1285 if ((clen = mbrtowc(&wc, sp, len, &mbs)) == len) 1286 return (wc); /* single character */ 1287 else if (clen == (size_t)-1 || clen == (size_t)-2) 1288 SETERROR(REG_ILLSEQ); 1289 else 1290 SETERROR(REG_ECOLLATE); /* neither */ 1291 return(0); 1292 } 1293 1294 /* 1295 - may_escape - determine whether 'ch' is escape-able in the current context 1296 == static int may_escape(struct parse *p, const wint_t ch) 1297 */ 1298 static bool 1299 may_escape(struct parse *p, const wint_t ch) 1300 { 1301 1302 if ((p->pflags & PFLAG_LEGACY_ESC) != 0) 1303 return (true); 1304 if (iswalpha(ch) || ch == '\'' || ch == '`') 1305 return (false); 1306 return (true); 1307 #ifdef NOTYET 1308 /* 1309 * Build a whitelist of characters that may be escaped to produce an 1310 * ordinary in the current context. This assumes that these have not 1311 * been otherwise interpreted as a special character. Escaping an 1312 * ordinary character yields undefined results according to 1313 * IEEE 1003.1-2008. Some extensions (notably, some GNU extensions) take 1314 * advantage of this and use escaped ordinary characters to provide 1315 * special meaning, e.g. \b, \B, \w, \W, \s, \S. 1316 */ 1317 switch(ch) { 1318 case '|': 1319 case '+': 1320 case '?': 1321 /* The above characters may not be escaped in BREs */ 1322 if (!(p->g->cflags®_EXTENDED)) 1323 return (false); 1324 /* Fallthrough */ 1325 case '(': 1326 case ')': 1327 case '{': 1328 case '}': 1329 case '.': 1330 case '[': 1331 case ']': 1332 case '\\': 1333 case '*': 1334 case '^': 1335 case '$': 1336 return (true); 1337 default: 1338 return (false); 1339 } 1340 #endif 1341 } 1342 1343 /* 1344 - othercase - return the case counterpart of an alphabetic 1345 == static wint_t othercase(wint_t ch); 1346 */ 1347 static wint_t /* if no counterpart, return ch */ 1348 othercase(wint_t ch) 1349 { 1350 assert(iswalpha(ch)); 1351 if (iswupper(ch)) 1352 return(towlower(ch)); 1353 else if (iswlower(ch)) 1354 return(towupper(ch)); 1355 else /* peculiar, but could happen */ 1356 return(ch); 1357 } 1358 1359 /* 1360 - bothcases - emit a dualcase version of a two-case character 1361 == static void bothcases(struct parse *p, wint_t ch); 1362 * 1363 * Boy, is this implementation ever a kludge... 1364 */ 1365 static void 1366 bothcases(struct parse *p, wint_t ch) 1367 { 1368 const char *oldnext = p->next; 1369 const char *oldend = p->end; 1370 char bracket[3 + MB_LEN_MAX]; 1371 size_t n; 1372 mbstate_t mbs; 1373 1374 assert(othercase(ch) != ch); /* p_bracket() would recurse */ 1375 p->next = bracket; 1376 memset(&mbs, 0, sizeof(mbs)); 1377 n = wcrtomb(bracket, ch, &mbs); 1378 assert(n != (size_t)-1); 1379 bracket[n] = ']'; 1380 bracket[n + 1] = '\0'; 1381 p->end = bracket+n+1; 1382 p_bracket(p); 1383 assert(p->next == p->end); 1384 p->next = oldnext; 1385 p->end = oldend; 1386 } 1387 1388 /* 1389 - ordinary - emit an ordinary character 1390 == static void ordinary(struct parse *p, wint_t ch); 1391 */ 1392 static void 1393 ordinary(struct parse *p, wint_t ch) 1394 { 1395 cset *cs; 1396 1397 if ((p->g->cflags®_ICASE) && iswalpha(ch) && othercase(ch) != ch) 1398 bothcases(p, ch); 1399 else if ((ch & OPDMASK) == ch) 1400 EMIT(OCHAR, ch); 1401 else { 1402 /* 1403 * Kludge: character is too big to fit into an OCHAR operand. 1404 * Emit a singleton set. 1405 */ 1406 if ((cs = allocset(p)) == NULL) 1407 return; 1408 CHadd(p, cs, ch); 1409 EMIT(OANYOF, (int)(cs - p->g->sets)); 1410 } 1411 } 1412 1413 /* 1414 - nonnewline - emit REG_NEWLINE version of OANY 1415 == static void nonnewline(struct parse *p); 1416 * 1417 * Boy, is this implementation ever a kludge... 1418 */ 1419 static void 1420 nonnewline(struct parse *p) 1421 { 1422 const char *oldnext = p->next; 1423 const char *oldend = p->end; 1424 char bracket[4]; 1425 1426 p->next = bracket; 1427 p->end = bracket+3; 1428 bracket[0] = '^'; 1429 bracket[1] = '\n'; 1430 bracket[2] = ']'; 1431 bracket[3] = '\0'; 1432 p_bracket(p); 1433 assert(p->next == bracket+3); 1434 p->next = oldnext; 1435 p->end = oldend; 1436 } 1437 1438 /* 1439 - repeat - generate code for a bounded repetition, recursively if needed 1440 == static void repeat(struct parse *p, sopno start, int from, int to); 1441 */ 1442 static void 1443 repeat(struct parse *p, 1444 sopno start, /* operand from here to end of strip */ 1445 int from, /* repeated from this number */ 1446 int to) /* to this number of times (maybe INFINITY) */ 1447 { 1448 sopno finish = HERE(); 1449 # define N 2 1450 # define INF 3 1451 # define REP(f, t) ((f)*8 + (t)) 1452 # define MAP(n) (((n) <= 1) ? (n) : ((n) == INFINITY) ? INF : N) 1453 sopno copy; 1454 1455 if (p->error != 0) /* head off possible runaway recursion */ 1456 return; 1457 1458 assert(from <= to); 1459 1460 switch (REP(MAP(from), MAP(to))) { 1461 case REP(0, 0): /* must be user doing this */ 1462 DROP(finish-start); /* drop the operand */ 1463 break; 1464 case REP(0, 1): /* as x{1,1}? */ 1465 case REP(0, N): /* as x{1,n}? */ 1466 case REP(0, INF): /* as x{1,}? */ 1467 /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */ 1468 INSERT(OCH_, start); /* offset is wrong... */ 1469 repeat(p, start+1, 1, to); 1470 ASTERN(OOR1, start); 1471 AHEAD(start); /* ... fix it */ 1472 EMIT(OOR2, 0); 1473 AHEAD(THERE()); 1474 ASTERN(O_CH, THERETHERE()); 1475 break; 1476 case REP(1, 1): /* trivial case */ 1477 /* done */ 1478 break; 1479 case REP(1, N): /* as x?x{1,n-1} */ 1480 /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */ 1481 INSERT(OCH_, start); 1482 ASTERN(OOR1, start); 1483 AHEAD(start); 1484 EMIT(OOR2, 0); /* offset very wrong... */ 1485 AHEAD(THERE()); /* ...so fix it */ 1486 ASTERN(O_CH, THERETHERE()); 1487 copy = dupl(p, start+1, finish+1); 1488 assert(copy == finish+4); 1489 repeat(p, copy, 1, to-1); 1490 break; 1491 case REP(1, INF): /* as x+ */ 1492 INSERT(OPLUS_, start); 1493 ASTERN(O_PLUS, start); 1494 break; 1495 case REP(N, N): /* as xx{m-1,n-1} */ 1496 copy = dupl(p, start, finish); 1497 repeat(p, copy, from-1, to-1); 1498 break; 1499 case REP(N, INF): /* as xx{n-1,INF} */ 1500 copy = dupl(p, start, finish); 1501 repeat(p, copy, from-1, to); 1502 break; 1503 default: /* "can't happen" */ 1504 SETERROR(REG_ASSERT); /* just in case */ 1505 break; 1506 } 1507 } 1508 1509 /* 1510 - wgetnext - helper function for WGETNEXT() macro. Gets the next wide 1511 - character from the parse struct, signals a REG_ILLSEQ error if the 1512 - character can't be converted. Returns the number of bytes consumed. 1513 */ 1514 static wint_t 1515 wgetnext(struct parse *p) 1516 { 1517 mbstate_t mbs; 1518 wchar_t wc; 1519 size_t n; 1520 1521 memset(&mbs, 0, sizeof(mbs)); 1522 n = mbrtowc(&wc, p->next, p->end - p->next, &mbs); 1523 if (n == (size_t)-1 || n == (size_t)-2) { 1524 SETERROR(REG_ILLSEQ); 1525 return (0); 1526 } 1527 if (n == 0) 1528 n = 1; 1529 p->next += n; 1530 return (wc); 1531 } 1532 1533 /* 1534 - seterr - set an error condition 1535 == static int seterr(struct parse *p, int e); 1536 */ 1537 static int /* useless but makes type checking happy */ 1538 seterr(struct parse *p, int e) 1539 { 1540 if (p->error == 0) /* keep earliest error condition */ 1541 p->error = e; 1542 p->next = nuls; /* try to bring things to a halt */ 1543 p->end = nuls; 1544 return(0); /* make the return value well-defined */ 1545 } 1546 1547 /* 1548 - allocset - allocate a set of characters for [] 1549 == static cset *allocset(struct parse *p); 1550 */ 1551 static cset * 1552 allocset(struct parse *p) 1553 { 1554 cset *cs, *ncs; 1555 1556 ncs = reallocarray(p->g->sets, p->g->ncsets + 1, sizeof(*ncs)); 1557 if (ncs == NULL) { 1558 SETERROR(REG_ESPACE); 1559 return (NULL); 1560 } 1561 p->g->sets = ncs; 1562 cs = &p->g->sets[p->g->ncsets++]; 1563 memset(cs, 0, sizeof(*cs)); 1564 1565 return(cs); 1566 } 1567 1568 /* 1569 - freeset - free a now-unused set 1570 == static void freeset(struct parse *p, cset *cs); 1571 */ 1572 static void 1573 freeset(struct parse *p, cset *cs) 1574 { 1575 cset *top = &p->g->sets[p->g->ncsets]; 1576 1577 free(cs->wides); 1578 free(cs->ranges); 1579 free(cs->types); 1580 memset(cs, 0, sizeof(*cs)); 1581 if (cs == top-1) /* recover only the easy case */ 1582 p->g->ncsets--; 1583 } 1584 1585 /* 1586 - singleton - Determine whether a set contains only one character, 1587 - returning it if so, otherwise returning OUT. 1588 */ 1589 static wint_t 1590 singleton(cset *cs) 1591 { 1592 wint_t i, s, n; 1593 1594 for (i = n = 0; i < NC; i++) 1595 if (CHIN(cs, i)) { 1596 n++; 1597 s = i; 1598 } 1599 if (n == 1) 1600 return (s); 1601 if (cs->nwides == 1 && cs->nranges == 0 && cs->ntypes == 0 && 1602 cs->icase == 0) 1603 return (cs->wides[0]); 1604 /* Don't bother handling the other cases. */ 1605 return (OUT); 1606 } 1607 1608 /* 1609 - CHadd - add character to character set. 1610 */ 1611 static void 1612 CHadd(struct parse *p, cset *cs, wint_t ch) 1613 { 1614 wint_t nch, *newwides; 1615 assert(ch >= 0); 1616 if (ch < NC) 1617 cs->bmp[ch >> 3] |= 1 << (ch & 7); 1618 else { 1619 newwides = reallocarray(cs->wides, cs->nwides + 1, 1620 sizeof(*cs->wides)); 1621 if (newwides == NULL) { 1622 SETERROR(REG_ESPACE); 1623 return; 1624 } 1625 cs->wides = newwides; 1626 cs->wides[cs->nwides++] = ch; 1627 } 1628 if (cs->icase) { 1629 if ((nch = towlower(ch)) < NC) 1630 cs->bmp[nch >> 3] |= 1 << (nch & 7); 1631 if ((nch = towupper(ch)) < NC) 1632 cs->bmp[nch >> 3] |= 1 << (nch & 7); 1633 } 1634 } 1635 1636 /* 1637 - CHaddrange - add all characters in the range [min,max] to a character set. 1638 */ 1639 static void 1640 CHaddrange(struct parse *p, cset *cs, wint_t min, wint_t max) 1641 { 1642 crange *newranges; 1643 1644 for (; min < NC && min <= max; min++) 1645 CHadd(p, cs, min); 1646 if (min >= max) 1647 return; 1648 newranges = reallocarray(cs->ranges, cs->nranges + 1, 1649 sizeof(*cs->ranges)); 1650 if (newranges == NULL) { 1651 SETERROR(REG_ESPACE); 1652 return; 1653 } 1654 cs->ranges = newranges; 1655 cs->ranges[cs->nranges].min = min; 1656 cs->ranges[cs->nranges].max = max; 1657 cs->nranges++; 1658 } 1659 1660 /* 1661 - CHaddtype - add all characters of a certain type to a character set. 1662 */ 1663 static void 1664 CHaddtype(struct parse *p, cset *cs, wctype_t wct) 1665 { 1666 wint_t i; 1667 wctype_t *newtypes; 1668 1669 for (i = 0; i < NC; i++) 1670 if (iswctype(i, wct)) 1671 CHadd(p, cs, i); 1672 newtypes = reallocarray(cs->types, cs->ntypes + 1, 1673 sizeof(*cs->types)); 1674 if (newtypes == NULL) { 1675 SETERROR(REG_ESPACE); 1676 return; 1677 } 1678 cs->types = newtypes; 1679 cs->types[cs->ntypes++] = wct; 1680 } 1681 1682 /* 1683 - dupl - emit a duplicate of a bunch of sops 1684 == static sopno dupl(struct parse *p, sopno start, sopno finish); 1685 */ 1686 static sopno /* start of duplicate */ 1687 dupl(struct parse *p, 1688 sopno start, /* from here */ 1689 sopno finish) /* to this less one */ 1690 { 1691 sopno ret = HERE(); 1692 sopno len = finish - start; 1693 1694 assert(finish >= start); 1695 if (len == 0) 1696 return(ret); 1697 if (!enlarge(p, p->ssize + len)) /* this many unexpected additions */ 1698 return(ret); 1699 (void) memcpy((char *)(p->strip + p->slen), 1700 (char *)(p->strip + start), (size_t)len*sizeof(sop)); 1701 p->slen += len; 1702 return(ret); 1703 } 1704 1705 /* 1706 - doemit - emit a strip operator 1707 == static void doemit(struct parse *p, sop op, size_t opnd); 1708 * 1709 * It might seem better to implement this as a macro with a function as 1710 * hard-case backup, but it's just too big and messy unless there are 1711 * some changes to the data structures. Maybe later. 1712 */ 1713 static void 1714 doemit(struct parse *p, sop op, size_t opnd) 1715 { 1716 /* avoid making error situations worse */ 1717 if (p->error != 0) 1718 return; 1719 1720 /* deal with oversize operands ("can't happen", more or less) */ 1721 assert(opnd < 1<<OPSHIFT); 1722 1723 /* deal with undersized strip */ 1724 if (p->slen >= p->ssize) 1725 if (!enlarge(p, (p->ssize+1) / 2 * 3)) /* +50% */ 1726 return; 1727 1728 /* finally, it's all reduced to the easy case */ 1729 p->strip[p->slen++] = SOP(op, opnd); 1730 } 1731 1732 /* 1733 - doinsert - insert a sop into the strip 1734 == static void doinsert(struct parse *p, sop op, size_t opnd, sopno pos); 1735 */ 1736 static void 1737 doinsert(struct parse *p, sop op, size_t opnd, sopno pos) 1738 { 1739 sopno sn; 1740 sop s; 1741 int i; 1742 1743 /* avoid making error situations worse */ 1744 if (p->error != 0) 1745 return; 1746 1747 sn = HERE(); 1748 EMIT(op, opnd); /* do checks, ensure space */ 1749 assert(HERE() == sn+1); 1750 s = p->strip[sn]; 1751 1752 /* adjust paren pointers */ 1753 assert(pos > 0); 1754 for (i = 1; i < NPAREN; i++) { 1755 if (p->pbegin[i] >= pos) { 1756 p->pbegin[i]++; 1757 } 1758 if (p->pend[i] >= pos) { 1759 p->pend[i]++; 1760 } 1761 } 1762 1763 memmove((char *)&p->strip[pos+1], (char *)&p->strip[pos], 1764 (HERE()-pos-1)*sizeof(sop)); 1765 p->strip[pos] = s; 1766 } 1767 1768 /* 1769 - dofwd - complete a forward reference 1770 == static void dofwd(struct parse *p, sopno pos, sop value); 1771 */ 1772 static void 1773 dofwd(struct parse *p, sopno pos, sop value) 1774 { 1775 /* avoid making error situations worse */ 1776 if (p->error != 0) 1777 return; 1778 1779 assert(value < 1<<OPSHIFT); 1780 p->strip[pos] = OP(p->strip[pos]) | value; 1781 } 1782 1783 /* 1784 - enlarge - enlarge the strip 1785 == static int enlarge(struct parse *p, sopno size); 1786 */ 1787 static int 1788 enlarge(struct parse *p, sopno size) 1789 { 1790 sop *sp; 1791 1792 if (p->ssize >= size) 1793 return 1; 1794 1795 sp = reallocarray(p->strip, size, sizeof(sop)); 1796 if (sp == NULL) { 1797 SETERROR(REG_ESPACE); 1798 return 0; 1799 } 1800 p->strip = sp; 1801 p->ssize = size; 1802 return 1; 1803 } 1804 1805 /* 1806 - stripsnug - compact the strip 1807 == static void stripsnug(struct parse *p, struct re_guts *g); 1808 */ 1809 static void 1810 stripsnug(struct parse *p, struct re_guts *g) 1811 { 1812 g->nstates = p->slen; 1813 g->strip = reallocarray((char *)p->strip, p->slen, sizeof(sop)); 1814 if (g->strip == NULL) { 1815 SETERROR(REG_ESPACE); 1816 g->strip = p->strip; 1817 } 1818 } 1819 1820 /* 1821 - findmust - fill in must and mlen with longest mandatory literal string 1822 == static void findmust(struct parse *p, struct re_guts *g); 1823 * 1824 * This algorithm could do fancy things like analyzing the operands of | 1825 * for common subsequences. Someday. This code is simple and finds most 1826 * of the interesting cases. 1827 * 1828 * Note that must and mlen got initialized during setup. 1829 */ 1830 static void 1831 findmust(struct parse *p, struct re_guts *g) 1832 { 1833 sop *scan; 1834 sop *start = NULL; 1835 sop *newstart = NULL; 1836 sopno newlen; 1837 sop s; 1838 char *cp; 1839 int offset; 1840 char buf[MB_LEN_MAX]; 1841 size_t clen; 1842 mbstate_t mbs; 1843 1844 /* avoid making error situations worse */ 1845 if (p->error != 0) 1846 return; 1847 1848 /* 1849 * It's not generally safe to do a ``char'' substring search on 1850 * multibyte character strings, but it's safe for at least 1851 * UTF-8 (see RFC 3629). 1852 */ 1853 if (MB_CUR_MAX > 1 && 1854 strcmp(_CurrentRuneLocale->__encoding, "UTF-8") != 0) 1855 return; 1856 1857 /* find the longest OCHAR sequence in strip */ 1858 newlen = 0; 1859 offset = 0; 1860 g->moffset = 0; 1861 scan = g->strip + 1; 1862 do { 1863 s = *scan++; 1864 switch (OP(s)) { 1865 case OCHAR: /* sequence member */ 1866 if (newlen == 0) { /* new sequence */ 1867 memset(&mbs, 0, sizeof(mbs)); 1868 newstart = scan - 1; 1869 } 1870 clen = wcrtomb(buf, OPND(s), &mbs); 1871 if (clen == (size_t)-1) 1872 goto toohard; 1873 newlen += clen; 1874 break; 1875 case OPLUS_: /* things that don't break one */ 1876 case OLPAREN: 1877 case ORPAREN: 1878 break; 1879 case OQUEST_: /* things that must be skipped */ 1880 case OCH_: 1881 offset = altoffset(scan, offset); 1882 scan--; 1883 do { 1884 scan += OPND(s); 1885 s = *scan; 1886 /* assert() interferes w debug printouts */ 1887 if (OP(s) != (sop)O_QUEST && 1888 OP(s) != (sop)O_CH && OP(s) != (sop)OOR2) { 1889 g->iflags |= BAD; 1890 return; 1891 } 1892 } while (OP(s) != (sop)O_QUEST && OP(s) != (sop)O_CH); 1893 /* FALLTHROUGH */ 1894 case OBOW: /* things that break a sequence */ 1895 case OEOW: 1896 case OBOL: 1897 case OEOL: 1898 case OBOS: 1899 case OEOS: 1900 case OWBND: 1901 case ONWBND: 1902 case O_QUEST: 1903 case O_CH: 1904 case OEND: 1905 if (newlen > (sopno)g->mlen) { /* ends one */ 1906 start = newstart; 1907 g->mlen = newlen; 1908 if (offset > -1) { 1909 g->moffset += offset; 1910 offset = newlen; 1911 } else 1912 g->moffset = offset; 1913 } else { 1914 if (offset > -1) 1915 offset += newlen; 1916 } 1917 newlen = 0; 1918 break; 1919 case OANY: 1920 if (newlen > (sopno)g->mlen) { /* ends one */ 1921 start = newstart; 1922 g->mlen = newlen; 1923 if (offset > -1) { 1924 g->moffset += offset; 1925 offset = newlen; 1926 } else 1927 g->moffset = offset; 1928 } else { 1929 if (offset > -1) 1930 offset += newlen; 1931 } 1932 if (offset > -1) 1933 offset++; 1934 newlen = 0; 1935 break; 1936 case OANYOF: /* may or may not invalidate offset */ 1937 /* First, everything as OANY */ 1938 if (newlen > (sopno)g->mlen) { /* ends one */ 1939 start = newstart; 1940 g->mlen = newlen; 1941 if (offset > -1) { 1942 g->moffset += offset; 1943 offset = newlen; 1944 } else 1945 g->moffset = offset; 1946 } else { 1947 if (offset > -1) 1948 offset += newlen; 1949 } 1950 if (offset > -1) 1951 offset++; 1952 newlen = 0; 1953 break; 1954 toohard: 1955 default: 1956 /* Anything here makes it impossible or too hard 1957 * to calculate the offset -- so we give up; 1958 * save the last known good offset, in case the 1959 * must sequence doesn't occur later. 1960 */ 1961 if (newlen > (sopno)g->mlen) { /* ends one */ 1962 start = newstart; 1963 g->mlen = newlen; 1964 if (offset > -1) 1965 g->moffset += offset; 1966 else 1967 g->moffset = offset; 1968 } 1969 offset = -1; 1970 newlen = 0; 1971 break; 1972 } 1973 } while (OP(s) != OEND); 1974 1975 if (g->mlen == 0) { /* there isn't one */ 1976 g->moffset = -1; 1977 return; 1978 } 1979 1980 /* turn it into a character string */ 1981 g->must = malloc((size_t)g->mlen + 1); 1982 if (g->must == NULL) { /* argh; just forget it */ 1983 g->mlen = 0; 1984 g->moffset = -1; 1985 return; 1986 } 1987 cp = g->must; 1988 scan = start; 1989 memset(&mbs, 0, sizeof(mbs)); 1990 while (cp < g->must + g->mlen) { 1991 while (OP(s = *scan++) != OCHAR) 1992 continue; 1993 clen = wcrtomb(cp, OPND(s), &mbs); 1994 assert(clen != (size_t)-1); 1995 cp += clen; 1996 } 1997 assert(cp == g->must + g->mlen); 1998 *cp++ = '\0'; /* just on general principles */ 1999 } 2000 2001 /* 2002 - altoffset - choose biggest offset among multiple choices 2003 == static int altoffset(sop *scan, int offset); 2004 * 2005 * Compute, recursively if necessary, the largest offset among multiple 2006 * re paths. 2007 */ 2008 static int 2009 altoffset(sop *scan, int offset) 2010 { 2011 int largest; 2012 int try; 2013 sop s; 2014 2015 /* If we gave up already on offsets, return */ 2016 if (offset == -1) 2017 return -1; 2018 2019 largest = 0; 2020 try = 0; 2021 s = *scan++; 2022 while (OP(s) != (sop)O_QUEST && OP(s) != (sop)O_CH) { 2023 switch (OP(s)) { 2024 case OOR1: 2025 if (try > largest) 2026 largest = try; 2027 try = 0; 2028 break; 2029 case OQUEST_: 2030 case OCH_: 2031 try = altoffset(scan, try); 2032 if (try == -1) 2033 return -1; 2034 scan--; 2035 do { 2036 scan += OPND(s); 2037 s = *scan; 2038 if (OP(s) != (sop)O_QUEST && 2039 OP(s) != (sop)O_CH && OP(s) != (sop)OOR2) 2040 return -1; 2041 } while (OP(s) != (sop)O_QUEST && OP(s) != (sop)O_CH); 2042 /* We must skip to the next position, or we'll 2043 * leave altoffset() too early. 2044 */ 2045 scan++; 2046 break; 2047 case OANYOF: 2048 case OCHAR: 2049 case OANY: 2050 try++; 2051 case OBOW: 2052 case OEOW: 2053 case OWBND: 2054 case ONWBND: 2055 case OLPAREN: 2056 case ORPAREN: 2057 case OOR2: 2058 break; 2059 default: 2060 try = -1; 2061 break; 2062 } 2063 if (try == -1) 2064 return -1; 2065 s = *scan++; 2066 } 2067 2068 if (try > largest) 2069 largest = try; 2070 2071 return largest+offset; 2072 } 2073 2074 /* 2075 - computejumps - compute char jumps for BM scan 2076 == static void computejumps(struct parse *p, struct re_guts *g); 2077 * 2078 * This algorithm assumes g->must exists and is has size greater than 2079 * zero. It's based on the algorithm found on Computer Algorithms by 2080 * Sara Baase. 2081 * 2082 * A char jump is the number of characters one needs to jump based on 2083 * the value of the character from the text that was mismatched. 2084 */ 2085 static void 2086 computejumps(struct parse *p, struct re_guts *g) 2087 { 2088 int ch; 2089 int mindex; 2090 2091 /* Avoid making errors worse */ 2092 if (p->error != 0) 2093 return; 2094 2095 g->charjump = (int *)malloc((NC_MAX + 1) * sizeof(int)); 2096 if (g->charjump == NULL) /* Not a fatal error */ 2097 return; 2098 /* Adjust for signed chars, if necessary */ 2099 g->charjump = &g->charjump[-(CHAR_MIN)]; 2100 2101 /* If the character does not exist in the pattern, the jump 2102 * is equal to the number of characters in the pattern. 2103 */ 2104 for (ch = CHAR_MIN; ch < (CHAR_MAX + 1); ch++) 2105 g->charjump[ch] = g->mlen; 2106 2107 /* If the character does exist, compute the jump that would 2108 * take us to the last character in the pattern equal to it 2109 * (notice that we match right to left, so that last character 2110 * is the first one that would be matched). 2111 */ 2112 for (mindex = 0; mindex < g->mlen; mindex++) 2113 g->charjump[(int)g->must[mindex]] = g->mlen - mindex - 1; 2114 } 2115 2116 /* 2117 - computematchjumps - compute match jumps for BM scan 2118 == static void computematchjumps(struct parse *p, struct re_guts *g); 2119 * 2120 * This algorithm assumes g->must exists and is has size greater than 2121 * zero. It's based on the algorithm found on Computer Algorithms by 2122 * Sara Baase. 2123 * 2124 * A match jump is the number of characters one needs to advance based 2125 * on the already-matched suffix. 2126 * Notice that all values here are minus (g->mlen-1), because of the way 2127 * the search algorithm works. 2128 */ 2129 static void 2130 computematchjumps(struct parse *p, struct re_guts *g) 2131 { 2132 int mindex; /* General "must" iterator */ 2133 int suffix; /* Keeps track of matching suffix */ 2134 int ssuffix; /* Keeps track of suffixes' suffix */ 2135 int* pmatches; /* pmatches[k] points to the next i 2136 * such that i+1...mlen is a substring 2137 * of k+1...k+mlen-i-1 2138 */ 2139 2140 /* Avoid making errors worse */ 2141 if (p->error != 0) 2142 return; 2143 2144 pmatches = (int*) malloc(g->mlen * sizeof(int)); 2145 if (pmatches == NULL) { 2146 g->matchjump = NULL; 2147 return; 2148 } 2149 2150 g->matchjump = (int*) malloc(g->mlen * sizeof(int)); 2151 if (g->matchjump == NULL) { /* Not a fatal error */ 2152 free(pmatches); 2153 return; 2154 } 2155 2156 /* Set maximum possible jump for each character in the pattern */ 2157 for (mindex = 0; mindex < g->mlen; mindex++) 2158 g->matchjump[mindex] = 2*g->mlen - mindex - 1; 2159 2160 /* Compute pmatches[] */ 2161 for (mindex = g->mlen - 1, suffix = g->mlen; mindex >= 0; 2162 mindex--, suffix--) { 2163 pmatches[mindex] = suffix; 2164 2165 /* If a mismatch is found, interrupting the substring, 2166 * compute the matchjump for that position. If no 2167 * mismatch is found, then a text substring mismatched 2168 * against the suffix will also mismatch against the 2169 * substring. 2170 */ 2171 while (suffix < g->mlen 2172 && g->must[mindex] != g->must[suffix]) { 2173 g->matchjump[suffix] = MIN(g->matchjump[suffix], 2174 g->mlen - mindex - 1); 2175 suffix = pmatches[suffix]; 2176 } 2177 } 2178 2179 /* Compute the matchjump up to the last substring found to jump 2180 * to the beginning of the largest must pattern prefix matching 2181 * it's own suffix. 2182 */ 2183 for (mindex = 0; mindex <= suffix; mindex++) 2184 g->matchjump[mindex] = MIN(g->matchjump[mindex], 2185 g->mlen + suffix - mindex); 2186 2187 ssuffix = pmatches[suffix]; 2188 while (suffix < g->mlen) { 2189 while (suffix <= ssuffix && suffix < g->mlen) { 2190 g->matchjump[suffix] = MIN(g->matchjump[suffix], 2191 g->mlen + ssuffix - suffix); 2192 suffix++; 2193 } 2194 if (suffix < g->mlen) 2195 ssuffix = pmatches[ssuffix]; 2196 } 2197 2198 free(pmatches); 2199 } 2200 2201 /* 2202 - pluscount - count + nesting 2203 == static sopno pluscount(struct parse *p, struct re_guts *g); 2204 */ 2205 static sopno /* nesting depth */ 2206 pluscount(struct parse *p, struct re_guts *g) 2207 { 2208 sop *scan; 2209 sop s; 2210 sopno plusnest = 0; 2211 sopno maxnest = 0; 2212 2213 if (p->error != 0) 2214 return(0); /* there may not be an OEND */ 2215 2216 scan = g->strip + 1; 2217 do { 2218 s = *scan++; 2219 switch (OP(s)) { 2220 case OPLUS_: 2221 plusnest++; 2222 break; 2223 case O_PLUS: 2224 if (plusnest > maxnest) 2225 maxnest = plusnest; 2226 plusnest--; 2227 break; 2228 } 2229 } while (OP(s) != OEND); 2230 if (plusnest != 0) 2231 g->iflags |= BAD; 2232 return(maxnest); 2233 } 2234