1 /*- 2 * Copyright (c) 1992, 1993, 1994 Henry Spencer. 3 * Copyright (c) 1992, 1993, 1994 4 * The Regents of the University of California. All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * Henry Spencer. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by the University of 20 * California, Berkeley and its contributors. 21 * 4. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 * @(#)regcomp.c 8.5 (Berkeley) 3/20/94 38 */ 39 40 #if defined(LIBC_SCCS) && !defined(lint) 41 #if 0 42 static char sccsid[] = "@(#)regcomp.c 8.5 (Berkeley) 3/20/94"; 43 #else 44 static char rcsid[] = "$OpenBSD: regcomp.c,v 1.8 2002/02/16 21:27:24 millert Exp $"; 45 #endif 46 #endif /* LIBC_SCCS and not lint */ 47 48 #include <sys/types.h> 49 #include <stdio.h> 50 #include <string.h> 51 #include <ctype.h> 52 #include <limits.h> 53 #include <stdlib.h> 54 #include <regex.h> 55 56 #include "utils.h" 57 #include "regex2.h" 58 59 #include "cclass.h" 60 #include "cname.h" 61 62 /* 63 * parse structure, passed up and down to avoid global variables and 64 * other clumsinesses 65 */ 66 struct parse { 67 char *next; /* next character in RE */ 68 char *end; /* end of string (-> NUL normally) */ 69 int error; /* has an error been seen? */ 70 sop *strip; /* malloced strip */ 71 sopno ssize; /* malloced strip size (allocated) */ 72 sopno slen; /* malloced strip length (used) */ 73 int ncsalloc; /* number of csets allocated */ 74 struct re_guts *g; 75 # define NPAREN 10 /* we need to remember () 1-9 for back refs */ 76 sopno pbegin[NPAREN]; /* -> ( ([0] unused) */ 77 sopno pend[NPAREN]; /* -> ) ([0] unused) */ 78 }; 79 80 /* ========= begin header generated by ./mkh ========= */ 81 #ifdef __cplusplus 82 extern "C" { 83 #endif 84 85 /* === regcomp.c === */ 86 static void p_ere(struct parse *p, int stop); 87 static void p_ere_exp(struct parse *p); 88 static void p_str(struct parse *p); 89 static void p_bre(struct parse *p, int end1, int end2); 90 static int p_simp_re(struct parse *p, int starordinary); 91 static int p_count(struct parse *p); 92 static void p_bracket(struct parse *p); 93 static void p_b_term(struct parse *p, cset *cs); 94 static void p_b_cclass(struct parse *p, cset *cs); 95 static void p_b_eclass(struct parse *p, cset *cs); 96 static char p_b_symbol(struct parse *p); 97 static char p_b_coll_elem(struct parse *p, int endc); 98 static char othercase(int ch); 99 static void bothcases(struct parse *p, int ch); 100 static void ordinary(struct parse *p, int ch); 101 static void nonnewline(struct parse *p); 102 static void repeat(struct parse *p, sopno start, int from, int to); 103 static int seterr(struct parse *p, int e); 104 static cset *allocset(struct parse *p); 105 static void freeset(struct parse *p, cset *cs); 106 static int freezeset(struct parse *p, cset *cs); 107 static int firstch(struct parse *p, cset *cs); 108 static int nch(struct parse *p, cset *cs); 109 static void mcadd(struct parse *p, cset *cs, char *cp); 110 static void mcinvert(struct parse *p, cset *cs); 111 static void mccase(struct parse *p, cset *cs); 112 static int isinsets(struct re_guts *g, int c); 113 static int samesets(struct re_guts *g, int c1, int c2); 114 static void categorize(struct parse *p, struct re_guts *g); 115 static sopno dupl(struct parse *p, sopno start, sopno finish); 116 static void doemit(struct parse *p, sop op, size_t opnd); 117 static void doinsert(struct parse *p, sop op, size_t opnd, sopno pos); 118 static void dofwd(struct parse *p, sopno pos, sop value); 119 static void enlarge(struct parse *p, sopno size); 120 static void stripsnug(struct parse *p, struct re_guts *g); 121 static void findmust(struct parse *p, struct re_guts *g); 122 static sopno pluscount(struct parse *p, struct re_guts *g); 123 124 #ifdef __cplusplus 125 } 126 #endif 127 /* ========= end header generated by ./mkh ========= */ 128 129 static char nuls[10]; /* place to point scanner in event of error */ 130 131 /* 132 * macros for use with parse structure 133 * BEWARE: these know that the parse structure is named `p' !!! 134 */ 135 #define PEEK() (*p->next) 136 #define PEEK2() (*(p->next+1)) 137 #define MORE() (p->next < p->end) 138 #define MORE2() (p->next+1 < p->end) 139 #define SEE(c) (MORE() && PEEK() == (c)) 140 #define SEETWO(a, b) (MORE() && MORE2() && PEEK() == (a) && PEEK2() == (b)) 141 #define EAT(c) ((SEE(c)) ? (NEXT(), 1) : 0) 142 #define EATTWO(a, b) ((SEETWO(a, b)) ? (NEXT2(), 1) : 0) 143 #define NEXT() (p->next++) 144 #define NEXT2() (p->next += 2) 145 #define NEXTn(n) (p->next += (n)) 146 #define GETNEXT() (*p->next++) 147 #define SETERROR(e) seterr(p, (e)) 148 #define REQUIRE(co, e) ((co) || SETERROR(e)) 149 #define MUSTSEE(c, e) (REQUIRE(MORE() && PEEK() == (c), e)) 150 #define MUSTEAT(c, e) (REQUIRE(MORE() && GETNEXT() == (c), e)) 151 #define MUSTNOTSEE(c, e) (REQUIRE(!MORE() || PEEK() != (c), e)) 152 #define EMIT(op, sopnd) doemit(p, (sop)(op), (size_t)(sopnd)) 153 #define INSERT(op, pos) doinsert(p, (sop)(op), HERE()-(pos)+1, pos) 154 #define AHEAD(pos) dofwd(p, pos, HERE()-(pos)) 155 #define ASTERN(sop, pos) EMIT(sop, HERE()-pos) 156 #define HERE() (p->slen) 157 #define THERE() (p->slen - 1) 158 #define THERETHERE() (p->slen - 2) 159 #define DROP(n) (p->slen -= (n)) 160 161 #ifndef NDEBUG 162 static int never = 0; /* for use in asserts; shuts lint up */ 163 #else 164 #define never 0 /* some <assert.h>s have bugs too */ 165 #endif 166 167 /* 168 - regcomp - interface for parser and compilation 169 = extern int regcomp(regex_t *, const char *, int); 170 = #define REG_BASIC 0000 171 = #define REG_EXTENDED 0001 172 = #define REG_ICASE 0002 173 = #define REG_NOSUB 0004 174 = #define REG_NEWLINE 0010 175 = #define REG_NOSPEC 0020 176 = #define REG_PEND 0040 177 = #define REG_DUMP 0200 178 */ 179 int /* 0 success, otherwise REG_something */ 180 regcomp(preg, pattern, cflags) 181 regex_t *preg; 182 const char *pattern; 183 int cflags; 184 { 185 struct parse pa; 186 register struct re_guts *g; 187 register struct parse *p = &pa; 188 register int i; 189 register size_t len; 190 #ifdef REDEBUG 191 # define GOODFLAGS(f) (f) 192 #else 193 # define GOODFLAGS(f) ((f)&~REG_DUMP) 194 #endif 195 196 cflags = GOODFLAGS(cflags); 197 if ((cflags®_EXTENDED) && (cflags®_NOSPEC)) 198 return(REG_INVARG); 199 200 if (cflags®_PEND) { 201 if (preg->re_endp < pattern) 202 return(REG_INVARG); 203 len = preg->re_endp - pattern; 204 } else 205 len = strlen((char *)pattern); 206 207 /* do the mallocs early so failure handling is easy */ 208 g = (struct re_guts *)malloc(sizeof(struct re_guts) + 209 (NC-1)*sizeof(cat_t)); 210 if (g == NULL) 211 return(REG_ESPACE); 212 p->ssize = len/(size_t)2*(size_t)3 + (size_t)1; /* ugh */ 213 p->strip = (sop *)malloc(p->ssize * sizeof(sop)); 214 p->slen = 0; 215 if (p->strip == NULL) { 216 free((char *)g); 217 return(REG_ESPACE); 218 } 219 220 /* set things up */ 221 p->g = g; 222 p->next = (char *)pattern; /* convenience; we do not modify it */ 223 p->end = p->next + len; 224 p->error = 0; 225 p->ncsalloc = 0; 226 for (i = 0; i < NPAREN; i++) { 227 p->pbegin[i] = 0; 228 p->pend[i] = 0; 229 } 230 g->csetsize = NC; 231 g->sets = NULL; 232 g->setbits = NULL; 233 g->ncsets = 0; 234 g->cflags = cflags; 235 g->iflags = 0; 236 g->nbol = 0; 237 g->neol = 0; 238 g->must = NULL; 239 g->mlen = 0; 240 g->nsub = 0; 241 g->ncategories = 1; /* category 0 is "everything else" */ 242 g->categories = &g->catspace[-(CHAR_MIN)]; 243 (void) memset((char *)g->catspace, 0, NC*sizeof(cat_t)); 244 g->backrefs = 0; 245 246 /* do it */ 247 EMIT(OEND, 0); 248 g->firststate = THERE(); 249 if (cflags®_EXTENDED) 250 p_ere(p, OUT); 251 else if (cflags®_NOSPEC) 252 p_str(p); 253 else 254 p_bre(p, OUT, OUT); 255 EMIT(OEND, 0); 256 g->laststate = THERE(); 257 258 /* tidy up loose ends and fill things in */ 259 categorize(p, g); 260 stripsnug(p, g); 261 findmust(p, g); 262 g->nplus = pluscount(p, g); 263 g->magic = MAGIC2; 264 preg->re_nsub = g->nsub; 265 preg->re_g = g; 266 preg->re_magic = MAGIC1; 267 #ifndef REDEBUG 268 /* not debugging, so can't rely on the assert() in regexec() */ 269 if (g->iflags&BAD) 270 SETERROR(REG_ASSERT); 271 #endif 272 273 /* win or lose, we're done */ 274 if (p->error != 0) /* lose */ 275 regfree(preg); 276 return(p->error); 277 } 278 279 /* 280 - p_ere - ERE parser top level, concatenation and alternation 281 == static void p_ere(register struct parse *p, int stop); 282 */ 283 static void 284 p_ere(p, stop) 285 register struct parse *p; 286 int stop; /* character this ERE should end at */ 287 { 288 register char c; 289 register sopno prevback; 290 register sopno prevfwd; 291 register sopno conc; 292 register int first = 1; /* is this the first alternative? */ 293 294 for (;;) { 295 /* do a bunch of concatenated expressions */ 296 conc = HERE(); 297 while (MORE() && (c = PEEK()) != '|' && c != stop) 298 p_ere_exp(p); 299 REQUIRE(HERE() != conc, REG_EMPTY); /* require nonempty */ 300 301 if (!EAT('|')) 302 break; /* NOTE BREAK OUT */ 303 304 if (first) { 305 INSERT(OCH_, conc); /* offset is wrong */ 306 prevfwd = conc; 307 prevback = conc; 308 first = 0; 309 } 310 ASTERN(OOR1, prevback); 311 prevback = THERE(); 312 AHEAD(prevfwd); /* fix previous offset */ 313 prevfwd = HERE(); 314 EMIT(OOR2, 0); /* offset is very wrong */ 315 } 316 317 if (!first) { /* tail-end fixups */ 318 AHEAD(prevfwd); 319 ASTERN(O_CH, prevback); 320 } 321 322 assert(!MORE() || SEE(stop)); 323 } 324 325 /* 326 - p_ere_exp - parse one subERE, an atom possibly followed by a repetition op 327 == static void p_ere_exp(register struct parse *p); 328 */ 329 static void 330 p_ere_exp(p) 331 register struct parse *p; 332 { 333 register char c; 334 register sopno pos; 335 register int count; 336 register int count2; 337 register sopno subno; 338 int wascaret = 0; 339 340 assert(MORE()); /* caller should have ensured this */ 341 c = GETNEXT(); 342 343 pos = HERE(); 344 switch (c) { 345 case '(': 346 REQUIRE(MORE(), REG_EPAREN); 347 p->g->nsub++; 348 subno = p->g->nsub; 349 if (subno < NPAREN) 350 p->pbegin[subno] = HERE(); 351 EMIT(OLPAREN, subno); 352 if (!SEE(')')) 353 p_ere(p, ')'); 354 if (subno < NPAREN) { 355 p->pend[subno] = HERE(); 356 assert(p->pend[subno] != 0); 357 } 358 EMIT(ORPAREN, subno); 359 MUSTEAT(')', REG_EPAREN); 360 break; 361 #ifndef POSIX_MISTAKE 362 case ')': /* happens only if no current unmatched ( */ 363 /* 364 * You may ask, why the ifndef? Because I didn't notice 365 * this until slightly too late for 1003.2, and none of the 366 * other 1003.2 regular-expression reviewers noticed it at 367 * all. So an unmatched ) is legal POSIX, at least until 368 * we can get it fixed. 369 */ 370 SETERROR(REG_EPAREN); 371 break; 372 #endif 373 case '^': 374 EMIT(OBOL, 0); 375 p->g->iflags |= USEBOL; 376 p->g->nbol++; 377 wascaret = 1; 378 break; 379 case '$': 380 EMIT(OEOL, 0); 381 p->g->iflags |= USEEOL; 382 p->g->neol++; 383 break; 384 case '|': 385 SETERROR(REG_EMPTY); 386 break; 387 case '*': 388 case '+': 389 case '?': 390 SETERROR(REG_BADRPT); 391 break; 392 case '.': 393 if (p->g->cflags®_NEWLINE) 394 nonnewline(p); 395 else 396 EMIT(OANY, 0); 397 break; 398 case '[': 399 p_bracket(p); 400 break; 401 case '\\': 402 REQUIRE(MORE(), REG_EESCAPE); 403 c = GETNEXT(); 404 ordinary(p, c); 405 break; 406 case '{': /* okay as ordinary except if digit follows */ 407 REQUIRE(!MORE() || !isdigit(PEEK()), REG_BADRPT); 408 /* FALLTHROUGH */ 409 default: 410 ordinary(p, c); 411 break; 412 } 413 414 if (!MORE()) 415 return; 416 c = PEEK(); 417 /* we call { a repetition if followed by a digit */ 418 if (!( c == '*' || c == '+' || c == '?' || 419 (c == '{' && MORE2() && isdigit(PEEK2())) )) 420 return; /* no repetition, we're done */ 421 NEXT(); 422 423 REQUIRE(!wascaret, REG_BADRPT); 424 switch (c) { 425 case '*': /* implemented as +? */ 426 /* this case does not require the (y|) trick, noKLUDGE */ 427 INSERT(OPLUS_, pos); 428 ASTERN(O_PLUS, pos); 429 INSERT(OQUEST_, pos); 430 ASTERN(O_QUEST, pos); 431 break; 432 case '+': 433 INSERT(OPLUS_, pos); 434 ASTERN(O_PLUS, pos); 435 break; 436 case '?': 437 /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */ 438 INSERT(OCH_, pos); /* offset slightly wrong */ 439 ASTERN(OOR1, pos); /* this one's right */ 440 AHEAD(pos); /* fix the OCH_ */ 441 EMIT(OOR2, 0); /* offset very wrong... */ 442 AHEAD(THERE()); /* ...so fix it */ 443 ASTERN(O_CH, THERETHERE()); 444 break; 445 case '{': 446 count = p_count(p); 447 if (EAT(',')) { 448 if (isdigit(PEEK())) { 449 count2 = p_count(p); 450 REQUIRE(count <= count2, REG_BADBR); 451 } else /* single number with comma */ 452 count2 = INFINITY; 453 } else /* just a single number */ 454 count2 = count; 455 repeat(p, pos, count, count2); 456 if (!EAT('}')) { /* error heuristics */ 457 while (MORE() && PEEK() != '}') 458 NEXT(); 459 REQUIRE(MORE(), REG_EBRACE); 460 SETERROR(REG_BADBR); 461 } 462 break; 463 } 464 465 if (!MORE()) 466 return; 467 c = PEEK(); 468 if (!( c == '*' || c == '+' || c == '?' || 469 (c == '{' && MORE2() && isdigit(PEEK2())) ) ) 470 return; 471 SETERROR(REG_BADRPT); 472 } 473 474 /* 475 - p_str - string (no metacharacters) "parser" 476 == static void p_str(register struct parse *p); 477 */ 478 static void 479 p_str(p) 480 register struct parse *p; 481 { 482 REQUIRE(MORE(), REG_EMPTY); 483 while (MORE()) 484 ordinary(p, GETNEXT()); 485 } 486 487 /* 488 - p_bre - BRE parser top level, anchoring and concatenation 489 == static void p_bre(register struct parse *p, register int end1, \ 490 == register int end2); 491 * Giving end1 as OUT essentially eliminates the end1/end2 check. 492 * 493 * This implementation is a bit of a kludge, in that a trailing $ is first 494 * taken as an ordinary character and then revised to be an anchor. The 495 * only undesirable side effect is that '$' gets included as a character 496 * category in such cases. This is fairly harmless; not worth fixing. 497 * The amount of lookahead needed to avoid this kludge is excessive. 498 */ 499 static void 500 p_bre(p, end1, end2) 501 register struct parse *p; 502 register int end1; /* first terminating character */ 503 register int end2; /* second terminating character */ 504 { 505 register sopno start = HERE(); 506 register int first = 1; /* first subexpression? */ 507 register int wasdollar = 0; 508 509 if (EAT('^')) { 510 EMIT(OBOL, 0); 511 p->g->iflags |= USEBOL; 512 p->g->nbol++; 513 } 514 while (MORE() && !SEETWO(end1, end2)) { 515 wasdollar = p_simp_re(p, first); 516 first = 0; 517 } 518 if (wasdollar) { /* oops, that was a trailing anchor */ 519 DROP(1); 520 EMIT(OEOL, 0); 521 p->g->iflags |= USEEOL; 522 p->g->neol++; 523 } 524 525 REQUIRE(HERE() != start, REG_EMPTY); /* require nonempty */ 526 } 527 528 /* 529 - p_simp_re - parse a simple RE, an atom possibly followed by a repetition 530 == static int p_simp_re(register struct parse *p, int starordinary); 531 */ 532 static int /* was the simple RE an unbackslashed $? */ 533 p_simp_re(p, starordinary) 534 register struct parse *p; 535 int starordinary; /* is a leading * an ordinary character? */ 536 { 537 register int c; 538 register int count; 539 register int count2; 540 register sopno pos; 541 register int i; 542 register sopno subno; 543 # define BACKSL (1<<CHAR_BIT) 544 545 pos = HERE(); /* repetion op, if any, covers from here */ 546 547 assert(MORE()); /* caller should have ensured this */ 548 c = GETNEXT(); 549 if (c == '\\') { 550 REQUIRE(MORE(), REG_EESCAPE); 551 c = BACKSL | (unsigned char)GETNEXT(); 552 } 553 switch (c) { 554 case '.': 555 if (p->g->cflags®_NEWLINE) 556 nonnewline(p); 557 else 558 EMIT(OANY, 0); 559 break; 560 case '[': 561 p_bracket(p); 562 break; 563 case BACKSL|'{': 564 SETERROR(REG_BADRPT); 565 break; 566 case BACKSL|'(': 567 p->g->nsub++; 568 subno = p->g->nsub; 569 if (subno < NPAREN) 570 p->pbegin[subno] = HERE(); 571 EMIT(OLPAREN, subno); 572 /* the MORE here is an error heuristic */ 573 if (MORE() && !SEETWO('\\', ')')) 574 p_bre(p, '\\', ')'); 575 if (subno < NPAREN) { 576 p->pend[subno] = HERE(); 577 assert(p->pend[subno] != 0); 578 } 579 EMIT(ORPAREN, subno); 580 REQUIRE(EATTWO('\\', ')'), REG_EPAREN); 581 break; 582 case BACKSL|')': /* should not get here -- must be user */ 583 case BACKSL|'}': 584 SETERROR(REG_EPAREN); 585 break; 586 case BACKSL|'1': 587 case BACKSL|'2': 588 case BACKSL|'3': 589 case BACKSL|'4': 590 case BACKSL|'5': 591 case BACKSL|'6': 592 case BACKSL|'7': 593 case BACKSL|'8': 594 case BACKSL|'9': 595 i = (c&~BACKSL) - '0'; 596 assert(i < NPAREN); 597 if (p->pend[i] != 0) { 598 assert(i <= p->g->nsub); 599 EMIT(OBACK_, i); 600 assert(p->pbegin[i] != 0); 601 assert(OP(p->strip[p->pbegin[i]]) == OLPAREN); 602 assert(OP(p->strip[p->pend[i]]) == ORPAREN); 603 (void) dupl(p, p->pbegin[i]+1, p->pend[i]); 604 EMIT(O_BACK, i); 605 } else 606 SETERROR(REG_ESUBREG); 607 p->g->backrefs = 1; 608 break; 609 case '*': 610 REQUIRE(starordinary, REG_BADRPT); 611 /* FALLTHROUGH */ 612 default: 613 ordinary(p, c &~ BACKSL); 614 break; 615 } 616 617 if (EAT('*')) { /* implemented as +? */ 618 /* this case does not require the (y|) trick, noKLUDGE */ 619 INSERT(OPLUS_, pos); 620 ASTERN(O_PLUS, pos); 621 INSERT(OQUEST_, pos); 622 ASTERN(O_QUEST, pos); 623 } else if (EATTWO('\\', '{')) { 624 count = p_count(p); 625 if (EAT(',')) { 626 if (MORE() && isdigit(PEEK())) { 627 count2 = p_count(p); 628 REQUIRE(count <= count2, REG_BADBR); 629 } else /* single number with comma */ 630 count2 = INFINITY; 631 } else /* just a single number */ 632 count2 = count; 633 repeat(p, pos, count, count2); 634 if (!EATTWO('\\', '}')) { /* error heuristics */ 635 while (MORE() && !SEETWO('\\', '}')) 636 NEXT(); 637 REQUIRE(MORE(), REG_EBRACE); 638 SETERROR(REG_BADBR); 639 } 640 } else if (c == (unsigned char)'$') /* $ (but not \$) ends it */ 641 return(1); 642 643 return(0); 644 } 645 646 /* 647 - p_count - parse a repetition count 648 == static int p_count(register struct parse *p); 649 */ 650 static int /* the value */ 651 p_count(p) 652 register struct parse *p; 653 { 654 register int count = 0; 655 register int ndigits = 0; 656 657 while (MORE() && isdigit(PEEK()) && count <= DUPMAX) { 658 count = count*10 + (GETNEXT() - '0'); 659 ndigits++; 660 } 661 662 REQUIRE(ndigits > 0 && count <= DUPMAX, REG_BADBR); 663 return(count); 664 } 665 666 /* 667 - p_bracket - parse a bracketed character list 668 == static void p_bracket(register struct parse *p); 669 * 670 * Note a significant property of this code: if the allocset() did SETERROR, 671 * no set operations are done. 672 */ 673 static void 674 p_bracket(p) 675 register struct parse *p; 676 { 677 register cset *cs = allocset(p); 678 register int invert = 0; 679 680 /* Dept of Truly Sickening Special-Case Kludges */ 681 if (p->next + 5 < p->end && strncmp(p->next, "[:<:]]", 6) == 0) { 682 EMIT(OBOW, 0); 683 NEXTn(6); 684 return; 685 } 686 if (p->next + 5 < p->end && strncmp(p->next, "[:>:]]", 6) == 0) { 687 EMIT(OEOW, 0); 688 NEXTn(6); 689 return; 690 } 691 692 if (EAT('^')) 693 invert++; /* make note to invert set at end */ 694 if (EAT(']')) 695 CHadd(cs, ']'); 696 else if (EAT('-')) 697 CHadd(cs, '-'); 698 while (MORE() && PEEK() != ']' && !SEETWO('-', ']')) 699 p_b_term(p, cs); 700 if (EAT('-')) 701 CHadd(cs, '-'); 702 MUSTEAT(']', REG_EBRACK); 703 704 if (p->error != 0) /* don't mess things up further */ 705 return; 706 707 if (p->g->cflags®_ICASE) { 708 register int i; 709 register int ci; 710 711 for (i = p->g->csetsize - 1; i >= 0; i--) 712 if (CHIN(cs, i) && isalpha(i)) { 713 ci = othercase(i); 714 if (ci != i) 715 CHadd(cs, ci); 716 } 717 if (cs->multis != NULL) 718 mccase(p, cs); 719 } 720 if (invert) { 721 register int i; 722 723 for (i = p->g->csetsize - 1; i >= 0; i--) 724 if (CHIN(cs, i)) 725 CHsub(cs, i); 726 else 727 CHadd(cs, i); 728 if (p->g->cflags®_NEWLINE) 729 CHsub(cs, '\n'); 730 if (cs->multis != NULL) 731 mcinvert(p, cs); 732 } 733 734 assert(cs->multis == NULL); /* xxx */ 735 736 if (nch(p, cs) == 1) { /* optimize singleton sets */ 737 ordinary(p, firstch(p, cs)); 738 freeset(p, cs); 739 } else 740 EMIT(OANYOF, freezeset(p, cs)); 741 } 742 743 /* 744 - p_b_term - parse one term of a bracketed character list 745 == static void p_b_term(register struct parse *p, register cset *cs); 746 */ 747 static void 748 p_b_term(p, cs) 749 register struct parse *p; 750 register cset *cs; 751 { 752 register char c; 753 register char start, finish; 754 register int i; 755 756 /* classify what we've got */ 757 switch ((MORE()) ? PEEK() : '\0') { 758 case '[': 759 c = (MORE2()) ? PEEK2() : '\0'; 760 break; 761 case '-': 762 SETERROR(REG_ERANGE); 763 return; /* NOTE RETURN */ 764 break; 765 default: 766 c = '\0'; 767 break; 768 } 769 770 switch (c) { 771 case ':': /* character class */ 772 NEXT2(); 773 REQUIRE(MORE(), REG_EBRACK); 774 c = PEEK(); 775 REQUIRE(c != '-' && c != ']', REG_ECTYPE); 776 p_b_cclass(p, cs); 777 REQUIRE(MORE(), REG_EBRACK); 778 REQUIRE(EATTWO(':', ']'), REG_ECTYPE); 779 break; 780 case '=': /* equivalence class */ 781 NEXT2(); 782 REQUIRE(MORE(), REG_EBRACK); 783 c = PEEK(); 784 REQUIRE(c != '-' && c != ']', REG_ECOLLATE); 785 p_b_eclass(p, cs); 786 REQUIRE(MORE(), REG_EBRACK); 787 REQUIRE(EATTWO('=', ']'), REG_ECOLLATE); 788 break; 789 default: /* symbol, ordinary character, or range */ 790 /* xxx revision needed for multichar stuff */ 791 start = p_b_symbol(p); 792 if (SEE('-') && MORE2() && PEEK2() != ']') { 793 /* range */ 794 NEXT(); 795 if (EAT('-')) 796 finish = '-'; 797 else 798 finish = p_b_symbol(p); 799 } else 800 finish = start; 801 /* xxx what about signed chars here... */ 802 REQUIRE(start <= finish, REG_ERANGE); 803 for (i = start; i <= finish; i++) 804 CHadd(cs, i); 805 break; 806 } 807 } 808 809 /* 810 - p_b_cclass - parse a character-class name and deal with it 811 == static void p_b_cclass(register struct parse *p, register cset *cs); 812 */ 813 static void 814 p_b_cclass(p, cs) 815 register struct parse *p; 816 register cset *cs; 817 { 818 register char *sp = p->next; 819 register struct cclass *cp; 820 register size_t len; 821 register char *u; 822 register char c; 823 824 while (MORE() && isalpha(PEEK())) 825 NEXT(); 826 len = p->next - sp; 827 for (cp = cclasses; cp->name != NULL; cp++) 828 if (strncmp(cp->name, sp, len) == 0 && cp->name[len] == '\0') 829 break; 830 if (cp->name == NULL) { 831 /* oops, didn't find it */ 832 SETERROR(REG_ECTYPE); 833 return; 834 } 835 836 u = cp->chars; 837 while ((c = *u++) != '\0') 838 CHadd(cs, c); 839 for (u = cp->multis; *u != '\0'; u += strlen(u) + 1) 840 MCadd(p, cs, u); 841 } 842 843 /* 844 - p_b_eclass - parse an equivalence-class name and deal with it 845 == static void p_b_eclass(register struct parse *p, register cset *cs); 846 * 847 * This implementation is incomplete. xxx 848 */ 849 static void 850 p_b_eclass(p, cs) 851 register struct parse *p; 852 register cset *cs; 853 { 854 register char c; 855 856 c = p_b_coll_elem(p, '='); 857 CHadd(cs, c); 858 } 859 860 /* 861 - p_b_symbol - parse a character or [..]ed multicharacter collating symbol 862 == static char p_b_symbol(register struct parse *p); 863 */ 864 static char /* value of symbol */ 865 p_b_symbol(p) 866 register struct parse *p; 867 { 868 register char value; 869 870 REQUIRE(MORE(), REG_EBRACK); 871 if (!EATTWO('[', '.')) 872 return(GETNEXT()); 873 874 /* collating symbol */ 875 value = p_b_coll_elem(p, '.'); 876 REQUIRE(EATTWO('.', ']'), REG_ECOLLATE); 877 return(value); 878 } 879 880 /* 881 - p_b_coll_elem - parse a collating-element name and look it up 882 == static char p_b_coll_elem(register struct parse *p, int endc); 883 */ 884 static char /* value of collating element */ 885 p_b_coll_elem(p, endc) 886 register struct parse *p; 887 int endc; /* name ended by endc,']' */ 888 { 889 register char *sp = p->next; 890 register struct cname *cp; 891 register int len; 892 893 while (MORE() && !SEETWO(endc, ']')) 894 NEXT(); 895 if (!MORE()) { 896 SETERROR(REG_EBRACK); 897 return(0); 898 } 899 len = p->next - sp; 900 for (cp = cnames; cp->name != NULL; cp++) 901 if (strncmp(cp->name, sp, len) == 0 && cp->name[len] == '\0') 902 return(cp->code); /* known name */ 903 if (len == 1) 904 return(*sp); /* single character */ 905 SETERROR(REG_ECOLLATE); /* neither */ 906 return(0); 907 } 908 909 /* 910 - othercase - return the case counterpart of an alphabetic 911 == static char othercase(int ch); 912 */ 913 static char /* if no counterpart, return ch */ 914 othercase(ch) 915 int ch; 916 { 917 assert(isalpha(ch)); 918 if (isupper(ch)) 919 return(tolower(ch)); 920 else if (islower(ch)) 921 return(toupper(ch)); 922 else /* peculiar, but could happen */ 923 return(ch); 924 } 925 926 /* 927 - bothcases - emit a dualcase version of a two-case character 928 == static void bothcases(register struct parse *p, int ch); 929 * 930 * Boy, is this implementation ever a kludge... 931 */ 932 static void 933 bothcases(p, ch) 934 register struct parse *p; 935 int ch; 936 { 937 register char *oldnext = p->next; 938 register char *oldend = p->end; 939 char bracket[3]; 940 941 assert(othercase(ch) != ch); /* p_bracket() would recurse */ 942 p->next = bracket; 943 p->end = bracket+2; 944 bracket[0] = ch; 945 bracket[1] = ']'; 946 bracket[2] = '\0'; 947 p_bracket(p); 948 assert(p->next == bracket+2); 949 p->next = oldnext; 950 p->end = oldend; 951 } 952 953 /* 954 - ordinary - emit an ordinary character 955 == static void ordinary(register struct parse *p, register int ch); 956 */ 957 static void 958 ordinary(p, ch) 959 register struct parse *p; 960 register int ch; 961 { 962 register cat_t *cap = p->g->categories; 963 964 if ((p->g->cflags®_ICASE) && isalpha(ch) && othercase(ch) != ch) 965 bothcases(p, ch); 966 else { 967 EMIT(OCHAR, (unsigned char)ch); 968 if (cap[ch] == 0) 969 cap[ch] = p->g->ncategories++; 970 } 971 } 972 973 /* 974 - nonnewline - emit REG_NEWLINE version of OANY 975 == static void nonnewline(register struct parse *p); 976 * 977 * Boy, is this implementation ever a kludge... 978 */ 979 static void 980 nonnewline(p) 981 register struct parse *p; 982 { 983 register char *oldnext = p->next; 984 register char *oldend = p->end; 985 char bracket[4]; 986 987 p->next = bracket; 988 p->end = bracket+3; 989 bracket[0] = '^'; 990 bracket[1] = '\n'; 991 bracket[2] = ']'; 992 bracket[3] = '\0'; 993 p_bracket(p); 994 assert(p->next == bracket+3); 995 p->next = oldnext; 996 p->end = oldend; 997 } 998 999 /* 1000 - repeat - generate code for a bounded repetition, recursively if needed 1001 == static void repeat(register struct parse *p, sopno start, int from, int to); 1002 */ 1003 static void 1004 repeat(p, start, from, to) 1005 register struct parse *p; 1006 sopno start; /* operand from here to end of strip */ 1007 int from; /* repeated from this number */ 1008 int to; /* to this number of times (maybe INFINITY) */ 1009 { 1010 register sopno finish = HERE(); 1011 # define N 2 1012 # define INF 3 1013 # define REP(f, t) ((f)*8 + (t)) 1014 # define MAP(n) (((n) <= 1) ? (n) : ((n) == INFINITY) ? INF : N) 1015 register sopno copy; 1016 1017 if (p->error != 0) /* head off possible runaway recursion */ 1018 return; 1019 1020 assert(from <= to); 1021 1022 switch (REP(MAP(from), MAP(to))) { 1023 case REP(0, 0): /* must be user doing this */ 1024 DROP(finish-start); /* drop the operand */ 1025 break; 1026 case REP(0, 1): /* as x{1,1}? */ 1027 case REP(0, N): /* as x{1,n}? */ 1028 case REP(0, INF): /* as x{1,}? */ 1029 /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */ 1030 INSERT(OCH_, start); /* offset is wrong... */ 1031 repeat(p, start+1, 1, to); 1032 ASTERN(OOR1, start); 1033 AHEAD(start); /* ... fix it */ 1034 EMIT(OOR2, 0); 1035 AHEAD(THERE()); 1036 ASTERN(O_CH, THERETHERE()); 1037 break; 1038 case REP(1, 1): /* trivial case */ 1039 /* done */ 1040 break; 1041 case REP(1, N): /* as x?x{1,n-1} */ 1042 /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */ 1043 INSERT(OCH_, start); 1044 ASTERN(OOR1, start); 1045 AHEAD(start); 1046 EMIT(OOR2, 0); /* offset very wrong... */ 1047 AHEAD(THERE()); /* ...so fix it */ 1048 ASTERN(O_CH, THERETHERE()); 1049 copy = dupl(p, start+1, finish+1); 1050 assert(copy == finish+4); 1051 repeat(p, copy, 1, to-1); 1052 break; 1053 case REP(1, INF): /* as x+ */ 1054 INSERT(OPLUS_, start); 1055 ASTERN(O_PLUS, start); 1056 break; 1057 case REP(N, N): /* as xx{m-1,n-1} */ 1058 copy = dupl(p, start, finish); 1059 repeat(p, copy, from-1, to-1); 1060 break; 1061 case REP(N, INF): /* as xx{n-1,INF} */ 1062 copy = dupl(p, start, finish); 1063 repeat(p, copy, from-1, to); 1064 break; 1065 default: /* "can't happen" */ 1066 SETERROR(REG_ASSERT); /* just in case */ 1067 break; 1068 } 1069 } 1070 1071 /* 1072 - seterr - set an error condition 1073 == static int seterr(register struct parse *p, int e); 1074 */ 1075 static int /* useless but makes type checking happy */ 1076 seterr(p, e) 1077 register struct parse *p; 1078 int e; 1079 { 1080 if (p->error == 0) /* keep earliest error condition */ 1081 p->error = e; 1082 p->next = nuls; /* try to bring things to a halt */ 1083 p->end = nuls; 1084 return(0); /* make the return value well-defined */ 1085 } 1086 1087 /* 1088 - allocset - allocate a set of characters for [] 1089 == static cset *allocset(register struct parse *p); 1090 */ 1091 static cset * 1092 allocset(p) 1093 register struct parse *p; 1094 { 1095 register int no = p->g->ncsets++; 1096 register size_t nc; 1097 register size_t nbytes; 1098 register cset *cs; 1099 register size_t css = (size_t)p->g->csetsize; 1100 register int i; 1101 1102 if (no >= p->ncsalloc) { /* need another column of space */ 1103 p->ncsalloc += CHAR_BIT; 1104 nc = p->ncsalloc; 1105 assert(nc % CHAR_BIT == 0); 1106 nbytes = nc / CHAR_BIT * css; 1107 if (p->g->sets == NULL) 1108 p->g->sets = (cset *)malloc(nc * sizeof(cset)); 1109 else { 1110 cset *ptr; 1111 ptr = (cset *)realloc((char *)p->g->sets, 1112 nc * sizeof(cset)); 1113 if (ptr == NULL) { 1114 free(p->g->sets); 1115 p->g->sets = NULL; 1116 } else 1117 p->g->sets = ptr; 1118 } 1119 if (p->g->sets == NULL) 1120 goto nomem; 1121 1122 if (p->g->setbits == NULL) 1123 p->g->setbits = (uch *)malloc(nbytes); 1124 else { 1125 uch *ptr; 1126 1127 ptr = (uch *)realloc((char *)p->g->setbits, nbytes); 1128 if (ptr == NULL) { 1129 free(p->g->setbits); 1130 p->g->setbits = NULL; 1131 } else { 1132 p->g->setbits = ptr; 1133 1134 for (i = 0; i < no; i++) 1135 p->g->sets[i].ptr = p->g->setbits + 1136 css*(i/CHAR_BIT); 1137 } 1138 } 1139 1140 if (p->g->sets == NULL || p->g->setbits == NULL) { 1141 nomem: 1142 no = 0; 1143 SETERROR(REG_ESPACE); 1144 /* caller's responsibility not to do set ops */ 1145 } else 1146 (void) memset((char *)p->g->setbits + (nbytes - css), 1147 0, css); 1148 } 1149 1150 assert(p->g->sets != NULL); /* xxx */ 1151 if (p->g->sets != NULL && p->g->setbits != NULL) { 1152 cs = &p->g->sets[no]; 1153 cs->ptr = p->g->setbits + css*((no)/CHAR_BIT); 1154 } 1155 cs->mask = 1 << ((no) % CHAR_BIT); 1156 cs->hash = 0; 1157 cs->smultis = 0; 1158 cs->multis = NULL; 1159 1160 return(cs); 1161 } 1162 1163 /* 1164 - freeset - free a now-unused set 1165 == static void freeset(register struct parse *p, register cset *cs); 1166 */ 1167 static void 1168 freeset(p, cs) 1169 register struct parse *p; 1170 register cset *cs; 1171 { 1172 register int i; 1173 register cset *top = &p->g->sets[p->g->ncsets]; 1174 register size_t css = (size_t)p->g->csetsize; 1175 1176 for (i = 0; i < css; i++) 1177 CHsub(cs, i); 1178 if (cs == top-1) /* recover only the easy case */ 1179 p->g->ncsets--; 1180 } 1181 1182 /* 1183 - freezeset - final processing on a set of characters 1184 == static int freezeset(register struct parse *p, register cset *cs); 1185 * 1186 * The main task here is merging identical sets. This is usually a waste 1187 * of time (although the hash code minimizes the overhead), but can win 1188 * big if REG_ICASE is being used. REG_ICASE, by the way, is why the hash 1189 * is done using addition rather than xor -- all ASCII [aA] sets xor to 1190 * the same value! 1191 */ 1192 static int /* set number */ 1193 freezeset(p, cs) 1194 register struct parse *p; 1195 register cset *cs; 1196 { 1197 register uch h = cs->hash; 1198 register int i; 1199 register cset *top = &p->g->sets[p->g->ncsets]; 1200 register cset *cs2; 1201 register size_t css = (size_t)p->g->csetsize; 1202 1203 /* look for an earlier one which is the same */ 1204 for (cs2 = &p->g->sets[0]; cs2 < top; cs2++) 1205 if (cs2->hash == h && cs2 != cs) { 1206 /* maybe */ 1207 for (i = 0; i < css; i++) 1208 if (!!CHIN(cs2, i) != !!CHIN(cs, i)) 1209 break; /* no */ 1210 if (i == css) 1211 break; /* yes */ 1212 } 1213 1214 if (cs2 < top) { /* found one */ 1215 freeset(p, cs); 1216 cs = cs2; 1217 } 1218 1219 return((int)(cs - p->g->sets)); 1220 } 1221 1222 /* 1223 - firstch - return first character in a set (which must have at least one) 1224 == static int firstch(register struct parse *p, register cset *cs); 1225 */ 1226 static int /* character; there is no "none" value */ 1227 firstch(p, cs) 1228 register struct parse *p; 1229 register cset *cs; 1230 { 1231 register int i; 1232 register size_t css = (size_t)p->g->csetsize; 1233 1234 for (i = 0; i < css; i++) 1235 if (CHIN(cs, i)) 1236 return((char)i); 1237 assert(never); 1238 return(0); /* arbitrary */ 1239 } 1240 1241 /* 1242 - nch - number of characters in a set 1243 == static int nch(register struct parse *p, register cset *cs); 1244 */ 1245 static int 1246 nch(p, cs) 1247 register struct parse *p; 1248 register cset *cs; 1249 { 1250 register int i; 1251 register size_t css = (size_t)p->g->csetsize; 1252 register int n = 0; 1253 1254 for (i = 0; i < css; i++) 1255 if (CHIN(cs, i)) 1256 n++; 1257 return(n); 1258 } 1259 1260 /* 1261 - mcadd - add a collating element to a cset 1262 == static void mcadd(register struct parse *p, register cset *cs, \ 1263 == register char *cp); 1264 */ 1265 static void 1266 mcadd(p, cs, cp) 1267 register struct parse *p; 1268 register cset *cs; 1269 register char *cp; 1270 { 1271 register size_t oldend = cs->smultis; 1272 void *np; 1273 1274 cs->smultis += strlen(cp) + 1; 1275 if (cs->multis == NULL) 1276 np = malloc(cs->smultis); 1277 else 1278 np = realloc(cs->multis, cs->smultis); 1279 if (np == NULL) { 1280 if (cs->multis) 1281 free(cs->multis); 1282 cs->multis = NULL; 1283 SETERROR(REG_ESPACE); 1284 return; 1285 } 1286 cs->multis = np; 1287 1288 (void) strcpy(cs->multis + oldend - 1, cp); 1289 cs->multis[cs->smultis - 1] = '\0'; 1290 } 1291 1292 /* 1293 - mcinvert - invert the list of collating elements in a cset 1294 == static void mcinvert(register struct parse *p, register cset *cs); 1295 * 1296 * This would have to know the set of possibilities. Implementation 1297 * is deferred. 1298 */ 1299 /* ARGSUSED */ 1300 static void 1301 mcinvert(p, cs) 1302 register struct parse *p; 1303 register cset *cs; 1304 { 1305 assert(cs->multis == NULL); /* xxx */ 1306 } 1307 1308 /* 1309 - mccase - add case counterparts of the list of collating elements in a cset 1310 == static void mccase(register struct parse *p, register cset *cs); 1311 * 1312 * This would have to know the set of possibilities. Implementation 1313 * is deferred. 1314 */ 1315 /* ARGSUSED */ 1316 static void 1317 mccase(p, cs) 1318 register struct parse *p; 1319 register cset *cs; 1320 { 1321 assert(cs->multis == NULL); /* xxx */ 1322 } 1323 1324 /* 1325 - isinsets - is this character in any sets? 1326 == static int isinsets(register struct re_guts *g, int c); 1327 */ 1328 static int /* predicate */ 1329 isinsets(g, c) 1330 register struct re_guts *g; 1331 int c; 1332 { 1333 register uch *col; 1334 register int i; 1335 register int ncols = (g->ncsets+(CHAR_BIT-1)) / CHAR_BIT; 1336 register unsigned uc = (unsigned char)c; 1337 1338 for (i = 0, col = g->setbits; i < ncols; i++, col += g->csetsize) 1339 if (col[uc] != 0) 1340 return(1); 1341 return(0); 1342 } 1343 1344 /* 1345 - samesets - are these two characters in exactly the same sets? 1346 == static int samesets(register struct re_guts *g, int c1, int c2); 1347 */ 1348 static int /* predicate */ 1349 samesets(g, c1, c2) 1350 register struct re_guts *g; 1351 int c1; 1352 int c2; 1353 { 1354 register uch *col; 1355 register int i; 1356 register int ncols = (g->ncsets+(CHAR_BIT-1)) / CHAR_BIT; 1357 register unsigned uc1 = (unsigned char)c1; 1358 register unsigned uc2 = (unsigned char)c2; 1359 1360 for (i = 0, col = g->setbits; i < ncols; i++, col += g->csetsize) 1361 if (col[uc1] != col[uc2]) 1362 return(0); 1363 return(1); 1364 } 1365 1366 /* 1367 - categorize - sort out character categories 1368 == static void categorize(struct parse *p, register struct re_guts *g); 1369 */ 1370 static void 1371 categorize(p, g) 1372 struct parse *p; 1373 register struct re_guts *g; 1374 { 1375 register cat_t *cats = g->categories; 1376 register int c; 1377 register int c2; 1378 register cat_t cat; 1379 1380 /* avoid making error situations worse */ 1381 if (p->error != 0) 1382 return; 1383 1384 for (c = CHAR_MIN; c <= CHAR_MAX; c++) 1385 if (cats[c] == 0 && isinsets(g, c)) { 1386 cat = g->ncategories++; 1387 cats[c] = cat; 1388 for (c2 = c+1; c2 <= CHAR_MAX; c2++) 1389 if (cats[c2] == 0 && samesets(g, c, c2)) 1390 cats[c2] = cat; 1391 } 1392 } 1393 1394 /* 1395 - dupl - emit a duplicate of a bunch of sops 1396 == static sopno dupl(register struct parse *p, sopno start, sopno finish); 1397 */ 1398 static sopno /* start of duplicate */ 1399 dupl(p, start, finish) 1400 register struct parse *p; 1401 sopno start; /* from here */ 1402 sopno finish; /* to this less one */ 1403 { 1404 register sopno ret = HERE(); 1405 register sopno len = finish - start; 1406 1407 assert(finish >= start); 1408 if (len == 0) 1409 return(ret); 1410 enlarge(p, p->ssize + len); /* this many unexpected additions */ 1411 assert(p->ssize >= p->slen + len); 1412 (void) memcpy((char *)(p->strip + p->slen), 1413 (char *)(p->strip + start), (size_t)len*sizeof(sop)); 1414 p->slen += len; 1415 return(ret); 1416 } 1417 1418 /* 1419 - doemit - emit a strip operator 1420 == static void doemit(register struct parse *p, sop op, size_t opnd); 1421 * 1422 * It might seem better to implement this as a macro with a function as 1423 * hard-case backup, but it's just too big and messy unless there are 1424 * some changes to the data structures. Maybe later. 1425 */ 1426 static void 1427 doemit(p, op, opnd) 1428 register struct parse *p; 1429 sop op; 1430 size_t opnd; 1431 { 1432 /* avoid making error situations worse */ 1433 if (p->error != 0) 1434 return; 1435 1436 /* deal with oversize operands ("can't happen", more or less) */ 1437 assert(opnd < 1<<OPSHIFT); 1438 1439 /* deal with undersized strip */ 1440 if (p->slen >= p->ssize) 1441 enlarge(p, (p->ssize+1) / 2 * 3); /* +50% */ 1442 assert(p->slen < p->ssize); 1443 1444 /* finally, it's all reduced to the easy case */ 1445 p->strip[p->slen++] = SOP(op, opnd); 1446 } 1447 1448 /* 1449 - doinsert - insert a sop into the strip 1450 == static void doinsert(register struct parse *p, sop op, size_t opnd, sopno pos); 1451 */ 1452 static void 1453 doinsert(p, op, opnd, pos) 1454 register struct parse *p; 1455 sop op; 1456 size_t opnd; 1457 sopno pos; 1458 { 1459 register sopno sn; 1460 register sop s; 1461 register int i; 1462 1463 /* avoid making error situations worse */ 1464 if (p->error != 0) 1465 return; 1466 1467 sn = HERE(); 1468 EMIT(op, opnd); /* do checks, ensure space */ 1469 assert(HERE() == sn+1); 1470 s = p->strip[sn]; 1471 1472 /* adjust paren pointers */ 1473 assert(pos > 0); 1474 for (i = 1; i < NPAREN; i++) { 1475 if (p->pbegin[i] >= pos) { 1476 p->pbegin[i]++; 1477 } 1478 if (p->pend[i] >= pos) { 1479 p->pend[i]++; 1480 } 1481 } 1482 1483 memmove((char *)&p->strip[pos+1], (char *)&p->strip[pos], 1484 (HERE()-pos-1)*sizeof(sop)); 1485 p->strip[pos] = s; 1486 } 1487 1488 /* 1489 - dofwd - complete a forward reference 1490 == static void dofwd(register struct parse *p, sopno pos, sop value); 1491 */ 1492 static void 1493 dofwd(p, pos, value) 1494 register struct parse *p; 1495 register sopno pos; 1496 sop value; 1497 { 1498 /* avoid making error situations worse */ 1499 if (p->error != 0) 1500 return; 1501 1502 assert(value < 1<<OPSHIFT); 1503 p->strip[pos] = OP(p->strip[pos]) | value; 1504 } 1505 1506 /* 1507 - enlarge - enlarge the strip 1508 == static void enlarge(register struct parse *p, sopno size); 1509 */ 1510 static void 1511 enlarge(p, size) 1512 register struct parse *p; 1513 register sopno size; 1514 { 1515 register sop *sp; 1516 1517 if (p->ssize >= size) 1518 return; 1519 1520 sp = (sop *)realloc(p->strip, size*sizeof(sop)); 1521 if (sp == NULL) { 1522 SETERROR(REG_ESPACE); 1523 return; 1524 } 1525 p->strip = sp; 1526 p->ssize = size; 1527 } 1528 1529 /* 1530 - stripsnug - compact the strip 1531 == static void stripsnug(register struct parse *p, register struct re_guts *g); 1532 */ 1533 static void 1534 stripsnug(p, g) 1535 register struct parse *p; 1536 register struct re_guts *g; 1537 { 1538 g->nstates = p->slen; 1539 g->strip = (sop *)realloc((char *)p->strip, p->slen * sizeof(sop)); 1540 if (g->strip == NULL) { 1541 SETERROR(REG_ESPACE); 1542 g->strip = p->strip; 1543 } 1544 } 1545 1546 /* 1547 - findmust - fill in must and mlen with longest mandatory literal string 1548 == static void findmust(register struct parse *p, register struct re_guts *g); 1549 * 1550 * This algorithm could do fancy things like analyzing the operands of | 1551 * for common subsequences. Someday. This code is simple and finds most 1552 * of the interesting cases. 1553 * 1554 * Note that must and mlen got initialized during setup. 1555 */ 1556 static void 1557 findmust(p, g) 1558 struct parse *p; 1559 register struct re_guts *g; 1560 { 1561 register sop *scan; 1562 sop *start; 1563 register sop *newstart; 1564 register sopno newlen; 1565 register sop s; 1566 register char *cp; 1567 register sopno i; 1568 1569 /* avoid making error situations worse */ 1570 if (p->error != 0) 1571 return; 1572 1573 /* find the longest OCHAR sequence in strip */ 1574 newlen = 0; 1575 scan = g->strip + 1; 1576 do { 1577 s = *scan++; 1578 switch (OP(s)) { 1579 case OCHAR: /* sequence member */ 1580 if (newlen == 0) /* new sequence */ 1581 newstart = scan - 1; 1582 newlen++; 1583 break; 1584 case OPLUS_: /* things that don't break one */ 1585 case OLPAREN: 1586 case ORPAREN: 1587 break; 1588 case OQUEST_: /* things that must be skipped */ 1589 case OCH_: 1590 scan--; 1591 do { 1592 scan += OPND(s); 1593 s = *scan; 1594 /* assert() interferes w debug printouts */ 1595 if (OP(s) != O_QUEST && OP(s) != O_CH && 1596 OP(s) != OOR2) { 1597 g->iflags |= BAD; 1598 return; 1599 } 1600 } while (OP(s) != O_QUEST && OP(s) != O_CH); 1601 /* fallthrough */ 1602 default: /* things that break a sequence */ 1603 if (newlen > g->mlen) { /* ends one */ 1604 start = newstart; 1605 g->mlen = newlen; 1606 } 1607 newlen = 0; 1608 break; 1609 } 1610 } while (OP(s) != OEND); 1611 1612 if (g->mlen == 0) /* there isn't one */ 1613 return; 1614 1615 /* turn it into a character string */ 1616 g->must = malloc((size_t)g->mlen + 1); 1617 if (g->must == NULL) { /* argh; just forget it */ 1618 g->mlen = 0; 1619 return; 1620 } 1621 cp = g->must; 1622 scan = start; 1623 for (i = g->mlen; i > 0; i--) { 1624 while (OP(s = *scan++) != OCHAR) 1625 continue; 1626 assert(cp < g->must + g->mlen); 1627 *cp++ = (char)OPND(s); 1628 } 1629 assert(cp == g->must + g->mlen); 1630 *cp++ = '\0'; /* just on general principles */ 1631 } 1632 1633 /* 1634 - pluscount - count + nesting 1635 == static sopno pluscount(register struct parse *p, register struct re_guts *g); 1636 */ 1637 static sopno /* nesting depth */ 1638 pluscount(p, g) 1639 struct parse *p; 1640 register struct re_guts *g; 1641 { 1642 register sop *scan; 1643 register sop s; 1644 register sopno plusnest = 0; 1645 register sopno maxnest = 0; 1646 1647 if (p->error != 0) 1648 return(0); /* there may not be an OEND */ 1649 1650 scan = g->strip + 1; 1651 do { 1652 s = *scan++; 1653 switch (OP(s)) { 1654 case OPLUS_: 1655 plusnest++; 1656 break; 1657 case O_PLUS: 1658 if (plusnest > maxnest) 1659 maxnest = plusnest; 1660 plusnest--; 1661 break; 1662 } 1663 } while (OP(s) != OEND); 1664 if (plusnest != 0) 1665 g->iflags |= BAD; 1666 return(maxnest); 1667 } 1668