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