regex.c
上传用户:sddyfurun
上传日期:2007-01-04
资源大小:525k
文件大小:17k
源码类别:

代理服务器

开发平台:

Unix_Linux

  1. #include <pmachine.h>
  2. #ifndef HAVE_RE_COMP
  3. /*
  4.  * These routines are BSD regex(3)/ed(1) compatible regular-expression
  5.  * routines written by Ozan S. Yigit, Computer Science, York University.
  6.  * Parts of the code that are not needed by Prospero have been removed,
  7.  * but most of the accompanying information has been left intact. 
  8.  * This file is to be included on those operating systems that do not
  9.  * support re_comp and re_exec.
  10.  */
  11. /*
  12.  * regex - Regular expression pattern matching
  13.  *         and replacement
  14.  *
  15.  * by:  Ozan S. Yigit (oz@nexus.yorku.ca)
  16.  * Dept. of Computing Services
  17.  *      York University
  18.  *
  19.  * These routines are the PUBLIC DOMAIN equivalents 
  20.  * of regex routines as found in 4.nBSD UN*X, with minor
  21.  * extensions.
  22.  *
  23.  * Modification history:
  24.  *
  25.  * $Log: regex.c,v $
  26.  * Revision 1.4  1996/04/25 20:06:29  blob
  27.  * Added const's so that it will compile on OSs that have const in the prototype in
  28.  * unistd.h
  29.  *
  30.  * Revision 1.3  1996/04/11  06:52:27  blob
  31.  * *** empty log message ***
  32.  *
  33.  * Revision 1.2  1996/04/11  06:51:34  blob
  34.  * Cleaned up warnings...
  35.  *
  36.  * Revision 1.1.1.2  1996/03/14  22:06:31  blob
  37.  * Try 1000000...
  38.  *
  39.  * Revision 1.1.1.1  1996/03/13  20:34:40  blob
  40.  * Initial Socks5 Beta import.
  41.  *
  42.  * Revision 1.1  1991/11/20  02:32:13  brendan
  43.  * entered into RCS
  44.  *
  45.  * Revision 1.1  1991/11/20  02:32:13  brendan
  46.  * entered into RCS
  47.  *
  48.  * Revision 1.3  89/04/01  14:18:09  oz
  49.  * Change all references to a dfa: this is actually an nfa.
  50.  * 
  51.  * Revision 1.2  88/08/28  15:36:04  oz
  52.  * Use a complement bitmap to represent NCL.
  53.  * This removes the need to have seperate 
  54.  * code in the pmatch case block - it is 
  55.  * just CCL code now.
  56.  * 
  57.  * Use the actual CCL code in the CLO
  58.  * section of pmatch. No need for a recursive
  59.  * pmatch call.
  60.  * 
  61.  * Use a bitmap table to set char bits in an
  62.  * 8-bit chunk.
  63.  * 
  64.  * Routines:
  65.  *      re_comp:        compile a regular expression into
  66.  *                      a NFA.
  67.  *
  68.  * char *re_comp(s)
  69.  * char *s;
  70.  *
  71.  *      re_exec:        execute the NFA to match a pattern.
  72.  *
  73.  * int re_exec(s)
  74.  * char *s;
  75.  *
  76.  * Regular Expressions:
  77.  *
  78.  *      [1]     char    matches itself, unless it is a special
  79.  *                      character (metachar): .  [ ] * + ^ $
  80.  *
  81.  *      [2]     .       matches any character.
  82.  *
  83.  *      [3]            matches the character following it, except
  84.  * when followed by a left or right round bracket,
  85.  * a digit 1 to 9 or a left or right angle bracket. 
  86.  * (see [7], [8] and [9])
  87.  * It is used as an escape character for all 
  88.  * other meta-characters, and itself. When used
  89.  * in a set ([4]), it is treated as an ordinary
  90.  * character.
  91.  *
  92.  *      [4]     [set]   matches one of the characters in the set.
  93.  *                      If the first character in the set is "^",
  94.  *                      it matches a character NOT in the set, i.e. 
  95.  * complements the set. A shorthand S-E is 
  96.  * used to specify a set of characters S upto 
  97.  * E, inclusive. The special characters "]" and 
  98.  * "-" have no special meaning if they appear 
  99.  * as the first chars in the set.
  100.  *                      examples:        match:
  101.  *
  102.  *                              [a-z]    any lowercase alpha
  103.  *
  104.  *                              [^]-]    any char except ] and -
  105.  *
  106.  *                              [^A-Z]   any char except uppercase
  107.  *                                       alpha
  108.  *
  109.  *                              [a-zA-Z] any alpha
  110.  *
  111.  *      [5]     *       any regular expression form [1] to [4], followed by
  112.  *                      closure char (*) matches zero or more matches of
  113.  *                      that form.
  114.  *
  115.  *      [6]     +       same as [5], except it matches one or more.
  116.  *
  117.  *      [7]             a regular expression in the form [1] to [10], enclosed
  118.  *                      as (form) matches what form matches. The enclosure
  119.  *                      creates a set of tags, used for [8] and for
  120.  *                      pattern substution. The tagged forms are numbered
  121.  * starting from 1.
  122.  *
  123.  *      [8]             a  followed by a digit 1 to 9 matches whatever a
  124.  *                      previously tagged regular expression ([7]) matched.
  125.  *
  126.  * [9] < a regular expression starting with a < construct
  127.  * > and/or ending with a > construct, restricts the
  128.  * pattern matching to the beginning of a word, and/or
  129.  * the end of a word. A word is defined to be a character
  130.  * string beginning and/or ending with the characters
  131.  * A-Z a-z 0-9 and _. It must also be preceded and/or
  132.  * followed by any character outside those mentioned.
  133.  *
  134.  *      [10]            a composite regular expression xy where x and y
  135.  *                      are in the form [1] to [10] matches the longest
  136.  *                      match of x followed by a match for y.
  137.  *
  138.  *      [11] ^ a regular expression starting with a ^ character
  139.  * $ and/or ending with a $ character, restricts the
  140.  *                      pattern matching to the beginning of the line,
  141.  *                      or the end of line. [anchors] Elsewhere in the
  142.  * pattern, ^ and $ are treated as ordinary characters.
  143.  *
  144.  *
  145.  * Acknowledgements:
  146.  *
  147.  * HCR's Hugh Redelmeier has been most helpful in various
  148.  * stages of development. He convinced me to include BOW
  149.  * and EOW constructs, originally invented by Rob Pike at
  150.  * the University of Toronto.
  151.  *
  152.  * References:
  153.  *              Software tools Kernighan & Plauger
  154.  *              Software tools in Pascal        Kernighan & Plauger
  155.  *              Grep [rsx-11 C dist]            David Conroy
  156.  * ed - text editor Un*x Programmer's Manual
  157.  * Advanced editing on Un*x B. W. Kernighan
  158.  * regexp routines Henry Spencer
  159.  *
  160.  * Notes:
  161.  *
  162.  * This implementation uses a bit-set representation for character
  163.  * classes for speed and compactness. Each character is represented 
  164.  * by one bit in a 128-bit block. Thus, CCL always takes a 
  165.  * constant 16 bytes in the internal nfa, and re_exec does a single
  166.  * bit comparison to locate the character in the set.
  167.  *
  168.  * Examples:
  169.  *
  170.  * pattern: foo*.*
  171.  * compile: CHR f CHR o CLO CHR o END CLO ANY END END
  172.  * matches: fo foo fooo foobar fobar foxx ...
  173.  *
  174.  * pattern: fo[ob]a[rz]
  175.  * compile: CHR f CHR o CCL bitset CHR a CCL bitset END
  176.  * matches: fobar fooar fobaz fooaz
  177.  *
  178.  * pattern: foo\+
  179.  * compile: CHR f CHR o CHR o CHR  CLO CHR  END END
  180.  * matches: foo foo\ foo\  ...
  181.  *
  182.  * pattern: (foo)[1-3]1 (same as foo[1-3]foo)
  183.  * compile: BOT 1 CHR f CHR o CHR o EOT 1 CCL bitset REF 1 END
  184.  * matches: foo1foo foo2foo foo3foo
  185.  *
  186.  * pattern: (fo.*)-1
  187.  * compile: BOT 1 CHR f CHR o CLO ANY END EOT 1 CHR - REF 1 END
  188.  * matches: foo-foo fo-fo fob-fob foobar-foobar ...
  189.  * 
  190.  */
  191. #define MAXNFA  1024
  192. #define MAXTAG  10
  193. #define OKP     1
  194. #define NOP     0
  195. #define CHR     1
  196. #define ANY     2
  197. #define CCL     3
  198. #define BOL     4
  199. #define EOL     5
  200. #define BOT     6
  201. #define EOT     7
  202. #define BOW 8
  203. #define EOW 9
  204. #define REF     10
  205. #define CLO     11
  206. #define END     0
  207. /*
  208.  * The following defines are not meant
  209.  * to be changeable. They are for readability
  210.  * only.
  211.  *
  212.  */
  213. #define MAXCHR 128
  214. #define CHRBIT 8
  215. #define BITBLK MAXCHR/CHRBIT
  216. #define BLKIND 0170
  217. #define BITIND 07
  218. #define ASCIIB 0177
  219. typedef /*unsigned*/ char CHAR;
  220. static int  tagstk[MAXTAG];             /* subpat tag stack..*/
  221. static CHAR nfa[MAXNFA]; /* automaton..       */
  222. static int  sta = NOP;                /* status of lastpat */
  223. static CHAR bittab[BITBLK]; /* bit table for CCL */
  224. /* pre-set bits...   */
  225. static CHAR bitarr[] = {1,2,4,8,16,32,64,128};
  226. static int internal_error;
  227. static void
  228. chset(c)
  229. register CHAR c;
  230. {
  231. bittab[((c) & BLKIND) >> 3] |= bitarr[(c) & BITIND];
  232. }
  233. #define badpat(x) return (*nfa = END, x)
  234. #define store(x) *mp++ = x
  235.  
  236. char *   
  237. re_comp(pat)
  238. const char *pat;
  239. {
  240. register const char *p;               /* pattern pointer   */
  241. register CHAR *mp = nfa;        /* nfa pointer       */
  242. register CHAR *lp;              /* saved pointer..   */
  243. register CHAR *sp = nfa;        /* another one..     */
  244. register int tagi = 0;          /* tag stack index   */
  245. register int tagc = 1;          /* actual tag count  */
  246. register int n;
  247. register CHAR mask; /* xor mask -CCL/NCL */
  248. int c1, c2;
  249. if (!pat || !*pat)
  250. if (sta)
  251. return 0;
  252. else
  253. badpat("No previous regular expression");
  254. sta = NOP;
  255. for (p = pat; *p; p++) {
  256. lp = mp;
  257. switch(*p) {
  258. case '.':               /* match any char..  */
  259. store(ANY);
  260. break;
  261. case '^':               /* match beginning.. */
  262. if (p == pat)
  263. store(BOL);
  264. else {
  265. store(CHR);
  266. store(*p);
  267. }
  268. break;
  269. case '$':               /* match endofline.. */
  270. if (!*(p+1))
  271. store(EOL);
  272. else {
  273. store(CHR);
  274. store(*p);
  275. }
  276. break;
  277. case '[':               /* match char class..*/
  278. store(CCL);
  279. if (*++p == '^') {
  280. mask = 0377;
  281. p++;
  282. }
  283. else
  284. mask = 0;
  285. if (*p == '-') /* real dash */
  286. chset(*p++);
  287. if (*p == ']') /* real brac */
  288. chset(*p++);
  289. while (*p && *p != ']') {
  290. if (*p == '-' && *(p+1) && *(p+1) != ']') {
  291. p++;
  292. c1 = *(p-2) + 1;
  293. c2 = *p++;
  294. while (c1 <= c2)
  295. chset(c1++);
  296. }
  297. #ifdef EXTEND
  298. else if (*p == '\' && *(p+1)) {
  299. p++;
  300. chset(*p++);
  301. }
  302. #endif
  303. else
  304. chset(*p++);
  305. }
  306. if (!*p)
  307. badpat("Missing ]");
  308. for (n = 0; n < BITBLK; bittab[n++] = (char) 0)
  309. store(mask ^ bittab[n]);
  310. break;
  311. case '*':               /* match 0 or more.. */
  312. case '+':               /* match 1 or more.. */
  313. if (p == pat)
  314. badpat("Empty closure");
  315. lp = sp; /* previous opcode */
  316. if (*lp == CLO) /* equivalence..   */
  317. break;
  318. switch(*lp) {
  319. case BOL:
  320. case BOT:
  321. case EOT:
  322. case BOW:
  323. case EOW:
  324. case REF:
  325. badpat("Illegal closure");
  326. default:
  327. break;
  328. }
  329. if (*p == '+')
  330. for (sp = mp; lp < sp; lp++)
  331. store(*lp);
  332. store(END);
  333. store(END);
  334. sp = mp;
  335. while (--mp > lp)
  336. *mp = mp[-1];
  337. store(CLO);
  338. mp = sp;
  339. break;
  340. case '\':              /* tags, backrefs .. */
  341. switch(*++p) {
  342. case '(':
  343. if (tagc < MAXTAG) {
  344. tagstk[++tagi] = tagc;
  345. store(BOT);
  346. store(tagc++);
  347. }
  348. else
  349. badpat("Too many \(\) pairs");
  350. break;
  351. case ')':
  352. if (*sp == BOT)
  353. badpat("Null pattern inside \(\)");
  354. if (tagi > 0) {
  355. store(EOT);
  356. store(tagstk[tagi--]);
  357. }
  358. else
  359. badpat("Unmatched \)");
  360. break;
  361. case '<':
  362. store(BOW);
  363. break;
  364. case '>':
  365. if (*sp == BOW)
  366. badpat("Null pattern inside \<\>");
  367. store(EOW);
  368. break;
  369. case '1':
  370. case '2':
  371. case '3':
  372. case '4':
  373. case '5':
  374. case '6':
  375. case '7':
  376. case '8':
  377. case '9':
  378. n = *p-'0';
  379. if (tagi > 0 && tagstk[tagi] == n)
  380. badpat("Cyclical reference");
  381. if (tagc > n) {
  382. store(REF);
  383. store(n);
  384. }
  385. else
  386. badpat("Undetermined reference");
  387. break;
  388. #ifdef EXTEND
  389. case 'b':
  390. store(CHR);
  391. store('b');
  392. break;
  393. case 'n':
  394. store(CHR);
  395. store('n');
  396. break;
  397. case 'f':
  398. store(CHR);
  399. store('f');
  400. break;
  401. case 'r':
  402. store(CHR);
  403. store('r');
  404. break;
  405. case 't':
  406. store(CHR);
  407. store('t');
  408. break;
  409. #endif
  410. default:
  411. store(CHR);
  412. store(*p);
  413. }
  414. break;
  415. default :               /* an ordinary char  */
  416. store(CHR);
  417. store(*p);
  418. break;
  419. }
  420. sp = lp;
  421. }
  422. if (tagi > 0)
  423. badpat("Unmatched \(");
  424. store(END);
  425. sta = OKP;
  426. return 0;
  427. }
  428. static const char *bol;
  429. static const char *bopat[MAXTAG];
  430. static const char *eopat[MAXTAG];
  431. static const char *pmatch P((const char *, CHAR *));
  432. /*
  433.  * re_exec:
  434.  *  execute nfa to find a match.
  435.  *
  436.  * special cases: (nfa[0])
  437.  * BOL
  438.  * Match only once, starting from the
  439.  * beginning.
  440.  * CHR
  441.  * First locate the character without
  442.  * calling pmatch, and if found, call
  443.  * pmatch for the remaining string.
  444.  * END
  445.  * re_comp failed, poor luser did not
  446.  * check for it. Fail fast.
  447.  *
  448.  * If a match is found, bopat[0] and eopat[0] are set
  449.  * to the beginning and the end of the matched fragment,
  450.  * respectively.
  451.  *
  452.  */
  453. int
  454. re_exec(lp)
  455. register const char *lp;
  456. {
  457. register char c;
  458. register const char *ep = 0;
  459. register CHAR *ap = nfa;
  460. bol = lp;
  461. bopat[0] = 0;
  462. bopat[1] = 0;
  463. bopat[2] = 0;
  464. bopat[3] = 0;
  465. bopat[4] = 0;
  466. bopat[5] = 0;
  467. bopat[6] = 0;
  468. bopat[7] = 0;
  469. bopat[8] = 0;
  470. bopat[9] = 0;
  471. switch(*ap) {
  472. case BOL: /* anchored: match from BOL only */
  473. ep = pmatch(lp,ap);
  474. break;
  475. case CHR: /* ordinary char: locate it fast */
  476. c = *(ap+1);
  477. while (*lp && *lp != c)
  478. lp++;
  479. if (!*lp) /* if EOS, fail, else fall thru. */
  480. return 0;
  481. default: /* regular matching all the way. */
  482. while (*lp) {
  483. if ((ep = pmatch(lp,ap)))
  484. break;
  485. lp++;
  486. }
  487. break;
  488. case END: /* munged automaton. fail always */
  489. return 0;
  490. }
  491. if (!ep)
  492. return 0;
  493. if (internal_error)
  494. return -1;
  495. bopat[0] = lp;
  496. eopat[0] = ep;
  497. return 1;
  498. }
  499. /* 
  500.  * pmatch: 
  501.  * internal routine for the hard part
  502.  *
  503.  *  This code is mostly snarfed from an early
  504.  *  grep written by David Conroy. The backref and
  505.  *  tag stuff, and various other mods are by oZ.
  506.  *
  507.  * special cases: (nfa[n], nfa[n+1])
  508.  * CLO ANY
  509.  * We KNOW ".*" will match ANYTHING
  510.  * upto the end of line. Thus, go to
  511.  * the end of line straight, without
  512.  * calling pmatch recursively. As in
  513.  * the other closure cases, the remaining
  514.  * pattern must be matched by moving
  515.  * backwards on the string recursively,
  516.  * to find a match for xy (x is ".*" and 
  517.  * y is the remaining pattern) where
  518.  * the match satisfies the LONGEST match
  519.  * for x followed by a match for y.
  520.  * CLO CHR
  521.  * We can again scan the string forward
  522.  * for the single char without recursion, 
  523.  * and at the point of failure, we execute 
  524.  * the remaining nfa recursively, as
  525.  * described above.
  526.  *
  527.  * At the end of a successful match, bopat[n] and eopat[n]
  528.  * are set to the beginning and end of subpatterns matched
  529.  * by tagged expressions (n = 1 to 9).
  530.  *
  531.  */
  532. /*
  533.  * character classification table for word boundary
  534.  * operators BOW and EOW. the reason for not using 
  535.  * ctype macros is that we can let the user add into 
  536.  * our own table. see re_modw. This table is not in
  537.  * the bitset form, since we may wish to extend it
  538.  * in the future for other character classifications. 
  539.  *
  540.  * TRUE for 0-9 A-Z a-z _
  541.  */
  542. static char chrtyp[MAXCHR] = {
  543. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
  544. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
  545. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
  546. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
  547. 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 
  548. 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 
  549. 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 
  550. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
  551. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
  552. 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 
  553. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
  554. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
  555. 1, 1, 1, 0, 0, 0, 0, 0
  556. };
  557. #define inascii(x) (0177&(x))
  558. #define iswordc(x)  chrtyp[inascii(x)]
  559. #define isinset(x,y)  ((x)[((y)&BLKIND)>>3] & bitarr[(y)&BITIND])
  560. /*
  561.  * skip values for CLO XXX to skip past the closure
  562.  *
  563.  */
  564. #define ANYSKIP 2  /* [CLO] ANY END ...      */
  565. #define CHRSKIP 3 /* [CLO] CHR chr END ...     */
  566. #define CCLSKIP 18 /* [CLO] CCL 16bytes END ... */
  567. static const char *
  568. pmatch(lp, ap)
  569. register const char *lp;
  570. register CHAR *ap;
  571. {
  572. register int op, c, n;
  573. register const char *e; /* extra pointer for CLO */
  574. register const char *bp; /* beginning of subpat.. */
  575. register const char *ep; /* ending of subpat..  */
  576. const char *are; /* to save the line ptr. */
  577. while ((op = *ap++) != END)
  578. switch(op) {
  579. case CHR:
  580. if (*lp++ != *ap++)
  581. return 0;
  582. break;
  583. case ANY:
  584. if (!*lp++)
  585. return 0;
  586. break;
  587. case CCL:
  588. c = *lp++;
  589. if (!isinset(ap,c))
  590. return 0;
  591. ap += BITBLK;
  592. break;
  593. case BOL:
  594. if (lp != bol)
  595. return 0;
  596. break;
  597. case EOL:
  598. if (*lp)
  599. return 0;
  600. break;
  601. case BOT:
  602. bopat[(int)(*ap++)] = lp;
  603. break;
  604. case EOT:
  605. eopat[(int)(*ap++)] = lp;
  606. break;
  607.   case BOW:
  608. if ((lp!=bol && iswordc(lp[-1])) || !iswordc(*lp))
  609. return 0;
  610. break;
  611. case EOW:
  612. if (lp==bol || !iswordc(lp[-1]) || iswordc(*lp))
  613. return 0;
  614. break;
  615. case REF:
  616. n = *ap++;
  617. bp = bopat[n];
  618. ep = eopat[n];
  619. while (bp < ep)
  620. if (*bp++ != *lp++)
  621. return 0;
  622. break;
  623. case CLO:
  624. are = lp;
  625. switch(*ap) {
  626. case ANY:
  627. while (*lp)
  628. lp++;
  629. n = ANYSKIP;
  630. break;
  631. case CHR:
  632. c = *(ap+1);
  633. while (*lp && c == *lp)
  634. lp++;
  635. n = CHRSKIP;
  636. break;
  637. case CCL:
  638. while ((c = *lp) && isinset(ap+1,c))
  639. lp++;
  640. n = CCLSKIP;
  641. break;
  642. default:
  643. internal_error++;
  644. return 0;
  645. }
  646. ap += n;
  647. while (lp >= are) {
  648.     if ((e = pmatch(lp, ap)))
  649. return e;
  650. --lp;
  651. }
  652. return 0;
  653. default:
  654. internal_error++;
  655. return 0;
  656. }
  657. return lp;
  658. }
  659. #endif /* Need regex libraries? Compile to nothing if not.  */