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