regcomp.c
上传用户:weiyuanprp
上传日期:2020-05-20
资源大小:1169k
文件大小:41k
源码类别:

传真(Fax)编程

开发平台:

C/C++

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