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