regcomp.c
上传用户:baixin
上传日期:2008-03-13
资源大小:4795k
文件大小:45k
开发平台:

MultiPlatform

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