home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume25 / tcl / part18 < prev    next >
Encoding:
Text File  |  1991-11-15  |  30.7 KB  |  1,288 lines

  1. Newsgroups: comp.sources.misc
  2. From: karl@sugar.neosoft.com (Karl Lehenbauer)
  3. Subject:  v25i086:  tcl - tool command language, version 6.1, Part18/33
  4. Message-ID: <1991Nov15.224847.20860@sparky.imd.sterling.com>
  5. X-Md4-Signature: 20b946d85ebcce76f62a10f231defea4
  6. Date: Fri, 15 Nov 1991 22:48:47 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: karl@sugar.neosoft.com (Karl Lehenbauer)
  10. Posting-number: Volume 25, Issue 86
  11. Archive-name: tcl/part18
  12. Environment: UNIX
  13.  
  14. #! /bin/sh
  15. # This is a shell archive.  Remove anything before this line, then unpack
  16. # it by saving it into a file and typing "sh file".  To overwrite existing
  17. # files, type "sh file -c".  You can also feed this as standard input via
  18. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  19. # will see the following message at the end:
  20. #        "End of archive 18 (of 33)."
  21. # Contents:  tcl6.1/regexp.c
  22. # Wrapped by karl@one on Tue Nov 12 19:44:26 1991
  23. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  24. if test -f 'tcl6.1/regexp.c' -a "${1}" != "-c" ; then 
  25.   echo shar: Will not clobber existing file \"'tcl6.1/regexp.c'\"
  26. else
  27. echo shar: Extracting \"'tcl6.1/regexp.c'\" \(28040 characters\)
  28. sed "s/^X//" >'tcl6.1/regexp.c' <<'END_OF_FILE'
  29. X/*
  30. X * regcomp and regexec -- regsub and regerror are elsewhere
  31. X *
  32. X *    Copyright (c) 1986 by University of Toronto.
  33. X *    Written by Henry Spencer.  Not derived from licensed software.
  34. X *
  35. X *    Permission is granted to anyone to use this software for any
  36. X *    purpose on any computer system, and to redistribute it freely,
  37. X *    subject to the following restrictions:
  38. X *
  39. X *    1. The author is not responsible for the consequences of use of
  40. X *        this software, no matter how awful, even if they arise
  41. X *        from defects in it.
  42. X *
  43. X *    2. The origin of this software must not be misrepresented, either
  44. X *        by explicit claim or by omission.
  45. X *
  46. X *    3. Altered versions must be plainly marked as such, and must not
  47. X *        be misrepresented as being the original software.
  48. X *
  49. X * Beware that some of this code is subtly aware of the way operator
  50. X * precedence is structured in regular expressions.  Serious changes in
  51. X * regular-expression syntax might require a total rethink.
  52. X *
  53. X * *** NOTE: this code has been altered slightly for use in Tcl. ***
  54. X * *** The only change is to use ckalloc and ckfree instead of   ***
  55. X * *** malloc and free.                         ***
  56. X */
  57. X#include "tclInt.h"
  58. X
  59. X/*
  60. X * The "internal use only" fields in regexp.h are present to pass info from
  61. X * compile to execute that permits the execute phase to run lots faster on
  62. X * simple cases.  They are:
  63. X *
  64. X * regstart    char that must begin a match; '\0' if none obvious
  65. X * reganch    is the match anchored (at beginning-of-line only)?
  66. X * regmust    string (pointer into program) that match must include, or NULL
  67. X * regmlen    length of regmust string
  68. X *
  69. X * Regstart and reganch permit very fast decisions on suitable starting points
  70. X * for a match, cutting down the work a lot.  Regmust permits fast rejection
  71. X * of lines that cannot possibly match.  The regmust tests are costly enough
  72. X * that regcomp() supplies a regmust only if the r.e. contains something
  73. X * potentially expensive (at present, the only such thing detected is * or +
  74. X * at the start of the r.e., which can involve a lot of backup).  Regmlen is
  75. X * supplied because the test in regexec() needs it and regcomp() is computing
  76. X * it anyway.
  77. X */
  78. X
  79. X/*
  80. X * Structure for regexp "program".  This is essentially a linear encoding
  81. X * of a nondeterministic finite-state machine (aka syntax charts or
  82. X * "railroad normal form" in parsing technology).  Each node is an opcode
  83. X * plus a "next" pointer, possibly plus an operand.  "Next" pointers of
  84. X * all nodes except BRANCH implement concatenation; a "next" pointer with
  85. X * a BRANCH on both ends of it is connecting two alternatives.  (Here we
  86. X * have one of the subtle syntax dependencies:  an individual BRANCH (as
  87. X * opposed to a collection of them) is never concatenated with anything
  88. X * because of operator precedence.)  The operand of some types of node is
  89. X * a literal string; for others, it is a node leading into a sub-FSM.  In
  90. X * particular, the operand of a BRANCH node is the first node of the branch.
  91. X * (NB this is *not* a tree structure:  the tail of the branch connects
  92. X * to the thing following the set of BRANCHes.)  The opcodes are:
  93. X */
  94. X
  95. X/* definition    number    opnd?    meaning */
  96. X#define    END    0    /* no    End of program. */
  97. X#define    BOL    1    /* no    Match "" at beginning of line. */
  98. X#define    EOL    2    /* no    Match "" at end of line. */
  99. X#define    ANY    3    /* no    Match any one character. */
  100. X#define    ANYOF    4    /* str    Match any character in this string. */
  101. X#define    ANYBUT    5    /* str    Match any character not in this string. */
  102. X#define    BRANCH    6    /* node    Match this alternative, or the next... */
  103. X#define    BACK    7    /* no    Match "", "next" ptr points backward. */
  104. X#define    EXACTLY    8    /* str    Match this string. */
  105. X#define    NOTHING    9    /* no    Match empty string. */
  106. X#define    STAR    10    /* node    Match this (simple) thing 0 or more times. */
  107. X#define    PLUS    11    /* node    Match this (simple) thing 1 or more times. */
  108. X#define    OPEN    20    /* no    Mark this point in input as start of #n. */
  109. X            /*    OPEN+1 is number 1, etc. */
  110. X#define    CLOSE    30    /* no    Analogous to OPEN. */
  111. X
  112. X/*
  113. X * Opcode notes:
  114. X *
  115. X * BRANCH    The set of branches constituting a single choice are hooked
  116. X *        together with their "next" pointers, since precedence prevents
  117. X *        anything being concatenated to any individual branch.  The
  118. X *        "next" pointer of the last BRANCH in a choice points to the
  119. X *        thing following the whole choice.  This is also where the
  120. X *        final "next" pointer of each individual branch points; each
  121. X *        branch starts with the operand node of a BRANCH node.
  122. X *
  123. X * BACK        Normal "next" pointers all implicitly point forward; BACK
  124. X *        exists to make loop structures possible.
  125. X *
  126. X * STAR,PLUS    '?', and complex '*' and '+', are implemented as circular
  127. X *        BRANCH structures using BACK.  Simple cases (one character
  128. X *        per match) are implemented with STAR and PLUS for speed
  129. X *        and to minimize recursive plunges.
  130. X *
  131. X * OPEN,CLOSE    ...are numbered at compile time.
  132. X */
  133. X
  134. X/*
  135. X * A node is one char of opcode followed by two chars of "next" pointer.
  136. X * "Next" pointers are stored as two 8-bit pieces, high order first.  The
  137. X * value is a positive offset from the opcode of the node containing it.
  138. X * An operand, if any, simply follows the node.  (Note that much of the
  139. X * code generation knows about this implicit relationship.)
  140. X *
  141. X * Using two bytes for the "next" pointer is vast overkill for most things,
  142. X * but allows patterns to get big without disasters.
  143. X */
  144. X#define    OP(p)    (*(p))
  145. X#define    NEXT(p)    (((*((p)+1)&0377)<<8) + (*((p)+2)&0377))
  146. X#define    OPERAND(p)    ((p) + 3)
  147. X
  148. X/*
  149. X * See regmagic.h for one further detail of program structure.
  150. X */
  151. X
  152. X
  153. X/*
  154. X * Utility definitions.
  155. X */
  156. X#ifndef CHARBITS
  157. X#define    UCHARAT(p)    ((int)*(unsigned char *)(p))
  158. X#else
  159. X#define    UCHARAT(p)    ((int)*(p)&CHARBITS)
  160. X#endif
  161. X
  162. X#define    FAIL(m)    { regerror(m); return(NULL); }
  163. X#define    ISMULT(c)    ((c) == '*' || (c) == '+' || (c) == '?')
  164. X#define    META    "^$.[()|?+*\\"
  165. X
  166. X/*
  167. X * Flags to be passed up and down.
  168. X */
  169. X#define    HASWIDTH    01    /* Known never to match null string. */
  170. X#define    SIMPLE        02    /* Simple enough to be STAR/PLUS operand. */
  171. X#define    SPSTART        04    /* Starts with * or +. */
  172. X#define    WORST        0    /* Worst case. */
  173. X
  174. X/*
  175. X * Global work variables for regcomp().
  176. X */
  177. Xstatic char *regparse;        /* Input-scan pointer. */
  178. Xstatic int regnpar;        /* () count. */
  179. Xstatic char regdummy;
  180. Xstatic char *regcode;        /* Code-emit pointer; ®dummy = don't. */
  181. Xstatic long regsize;        /* Code size. */
  182. X
  183. X/*
  184. X * The first byte of the regexp internal "program" is actually this magic
  185. X * number; the start node begins in the second byte.
  186. X */
  187. X#define    MAGIC    0234
  188. X
  189. X
  190. X/*
  191. X * Forward declarations for regcomp()'s friends.
  192. X */
  193. X#ifndef STATIC
  194. X#define    STATIC    static
  195. X#endif
  196. XSTATIC char *reg();
  197. XSTATIC char *regbranch();
  198. XSTATIC char *regpiece();
  199. XSTATIC char *regatom();
  200. XSTATIC char *regnode();
  201. XSTATIC char *regnext();
  202. XSTATIC void regc();
  203. XSTATIC void reginsert();
  204. XSTATIC void regtail();
  205. XSTATIC void regoptail();
  206. X#ifdef STRCSPN
  207. XSTATIC int strcspn();
  208. X#endif
  209. X
  210. X/*
  211. X - regcomp - compile a regular expression into internal code
  212. X *
  213. X * We can't allocate space until we know how big the compiled form will be,
  214. X * but we can't compile it (and thus know how big it is) until we've got a
  215. X * place to put the code.  So we cheat:  we compile it twice, once with code
  216. X * generation turned off and size counting turned on, and once "for real".
  217. X * This also means that we don't allocate space until we are sure that the
  218. X * thing really will compile successfully, and we never have to move the
  219. X * code and thus invalidate pointers into it.  (Note that it has to be in
  220. X * one piece because free() must be able to free it all.)
  221. X *
  222. X * Beware that the optimization-preparation code in here knows about some
  223. X * of the structure of the compiled regexp.
  224. X */
  225. Xregexp *
  226. Xregcomp(exp)
  227. Xchar *exp;
  228. X{
  229. X    register regexp *r;
  230. X    register char *scan;
  231. X    register char *longest;
  232. X    register int len;
  233. X    int flags;
  234. X
  235. X    if (exp == NULL)
  236. X        FAIL("NULL argument");
  237. X
  238. X    /* First pass: determine size, legality. */
  239. X    regparse = exp;
  240. X    regnpar = 1;
  241. X    regsize = 0L;
  242. X    regcode = ®dummy;
  243. X    regc(MAGIC);
  244. X    if (reg(0, &flags) == NULL)
  245. X        return(NULL);
  246. X
  247. X    /* Small enough for pointer-storage convention? */
  248. X    if (regsize >= 32767L)        /* Probably could be 65535L. */
  249. X        FAIL("regexp too big");
  250. X
  251. X    /* Allocate space. */
  252. X    r = (regexp *)ckalloc(sizeof(regexp) + (unsigned)regsize);
  253. X    if (r == NULL)
  254. X        FAIL("out of space");
  255. X
  256. X    /* Second pass: emit code. */
  257. X    regparse = exp;
  258. X    regnpar = 1;
  259. X    regcode = r->program;
  260. X    regc(MAGIC);
  261. X    if (reg(0, &flags) == NULL)
  262. X        return(NULL);
  263. X
  264. X    /* Dig out information for optimizations. */
  265. X    r->regstart = '\0';    /* Worst-case defaults. */
  266. X    r->reganch = 0;
  267. X    r->regmust = NULL;
  268. X    r->regmlen = 0;
  269. X    scan = r->program+1;            /* First BRANCH. */
  270. X    if (OP(regnext(scan)) == END) {        /* Only one top-level choice. */
  271. X        scan = OPERAND(scan);
  272. X
  273. X        /* Starting-point info. */
  274. X        if (OP(scan) == EXACTLY)
  275. X            r->regstart = *OPERAND(scan);
  276. X        else if (OP(scan) == BOL)
  277. X            r->reganch++;
  278. X
  279. X        /*
  280. X         * If there's something expensive in the r.e., find the
  281. X         * longest literal string that must appear and make it the
  282. X         * regmust.  Resolve ties in favor of later strings, since
  283. X         * the regstart check works with the beginning of the r.e.
  284. X         * and avoiding duplication strengthens checking.  Not a
  285. X         * strong reason, but sufficient in the absence of others.
  286. X         */
  287. X        if (flags&SPSTART) {
  288. X            longest = NULL;
  289. X            len = 0;
  290. X            for (; scan != NULL; scan = regnext(scan))
  291. X                if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= len) {
  292. X                    longest = OPERAND(scan);
  293. X                    len = strlen(OPERAND(scan));
  294. X                }
  295. X            r->regmust = longest;
  296. X            r->regmlen = len;
  297. X        }
  298. X    }
  299. X
  300. X    return(r);
  301. X}
  302. X
  303. X/*
  304. X - reg - regular expression, i.e. main body or parenthesized thing
  305. X *
  306. X * Caller must absorb opening parenthesis.
  307. X *
  308. X * Combining parenthesis handling with the base level of regular expression
  309. X * is a trifle forced, but the need to tie the tails of the branches to what
  310. X * follows makes it hard to avoid.
  311. X */
  312. Xstatic char *
  313. Xreg(paren, flagp)
  314. Xint paren;            /* Parenthesized? */
  315. Xint *flagp;
  316. X{
  317. X    register char *ret;
  318. X    register char *br;
  319. X    register char *ender;
  320. X    register int parno = 0;
  321. X    int flags;
  322. X
  323. X    *flagp = HASWIDTH;    /* Tentatively. */
  324. X
  325. X    /* Make an OPEN node, if parenthesized. */
  326. X    if (paren) {
  327. X        if (regnpar >= NSUBEXP)
  328. X            FAIL("too many ()");
  329. X        parno = regnpar;
  330. X        regnpar++;
  331. X        ret = regnode(OPEN+parno);
  332. X    } else
  333. X        ret = NULL;
  334. X
  335. X    /* Pick up the branches, linking them together. */
  336. X    br = regbranch(&flags);
  337. X    if (br == NULL)
  338. X        return(NULL);
  339. X    if (ret != NULL)
  340. X        regtail(ret, br);    /* OPEN -> first. */
  341. X    else
  342. X        ret = br;
  343. X    if (!(flags&HASWIDTH))
  344. X        *flagp &= ~HASWIDTH;
  345. X    *flagp |= flags&SPSTART;
  346. X    while (*regparse == '|') {
  347. X        regparse++;
  348. X        br = regbranch(&flags);
  349. X        if (br == NULL)
  350. X            return(NULL);
  351. X        regtail(ret, br);    /* BRANCH -> BRANCH. */
  352. X        if (!(flags&HASWIDTH))
  353. X            *flagp &= ~HASWIDTH;
  354. X        *flagp |= flags&SPSTART;
  355. X    }
  356. X
  357. X    /* Make a closing node, and hook it on the end. */
  358. X    ender = regnode((paren) ? CLOSE+parno : END);    
  359. X    regtail(ret, ender);
  360. X
  361. X    /* Hook the tails of the branches to the closing node. */
  362. X    for (br = ret; br != NULL; br = regnext(br))
  363. X        regoptail(br, ender);
  364. X
  365. X    /* Check for proper termination. */
  366. X    if (paren && *regparse++ != ')') {
  367. X        FAIL("unmatched ()");
  368. X    } else if (!paren && *regparse != '\0') {
  369. X        if (*regparse == ')') {
  370. X            FAIL("unmatched ()");
  371. X        } else
  372. X            FAIL("junk on end");    /* "Can't happen". */
  373. X        /* NOTREACHED */
  374. X    }
  375. X
  376. X    return(ret);
  377. X}
  378. X
  379. X/*
  380. X - regbranch - one alternative of an | operator
  381. X *
  382. X * Implements the concatenation operator.
  383. X */
  384. Xstatic char *
  385. Xregbranch(flagp)
  386. Xint *flagp;
  387. X{
  388. X    register char *ret;
  389. X    register char *chain;
  390. X    register char *latest;
  391. X    int flags;
  392. X
  393. X    *flagp = WORST;        /* Tentatively. */
  394. X
  395. X    ret = regnode(BRANCH);
  396. X    chain = NULL;
  397. X    while (*regparse != '\0' && *regparse != '|' && *regparse != ')') {
  398. X        latest = regpiece(&flags);
  399. X        if (latest == NULL)
  400. X            return(NULL);
  401. X        *flagp |= flags&HASWIDTH;
  402. X        if (chain == NULL)    /* First piece. */
  403. X            *flagp |= flags&SPSTART;
  404. X        else
  405. X            regtail(chain, latest);
  406. X        chain = latest;
  407. X    }
  408. X    if (chain == NULL)    /* Loop ran zero times. */
  409. X        (void) regnode(NOTHING);
  410. X
  411. X    return(ret);
  412. X}
  413. X
  414. X/*
  415. X - regpiece - something followed by possible [*+?]
  416. X *
  417. X * Note that the branching code sequences used for ? and the general cases
  418. X * of * and + are somewhat optimized:  they use the same NOTHING node as
  419. X * both the endmarker for their branch list and the body of the last branch.
  420. X * It might seem that this node could be dispensed with entirely, but the
  421. X * endmarker role is not redundant.
  422. X */
  423. Xstatic char *
  424. Xregpiece(flagp)
  425. Xint *flagp;
  426. X{
  427. X    register char *ret;
  428. X    register char op;
  429. X    register char *next;
  430. X    int flags;
  431. X
  432. X    ret = regatom(&flags);
  433. X    if (ret == NULL)
  434. X        return(NULL);
  435. X
  436. X    op = *regparse;
  437. X    if (!ISMULT(op)) {
  438. X        *flagp = flags;
  439. X        return(ret);
  440. X    }
  441. X
  442. X    if (!(flags&HASWIDTH) && op != '?')
  443. X        FAIL("*+ operand could be empty");
  444. X    *flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH);
  445. X
  446. X    if (op == '*' && (flags&SIMPLE))
  447. X        reginsert(STAR, ret);
  448. X    else if (op == '*') {
  449. X        /* Emit x* as (x&|), where & means "self". */
  450. X        reginsert(BRANCH, ret);            /* Either x */
  451. X        regoptail(ret, regnode(BACK));        /* and loop */
  452. X        regoptail(ret, ret);            /* back */
  453. X        regtail(ret, regnode(BRANCH));        /* or */
  454. X        regtail(ret, regnode(NOTHING));        /* null. */
  455. X    } else if (op == '+' && (flags&SIMPLE))
  456. X        reginsert(PLUS, ret);
  457. X    else if (op == '+') {
  458. X        /* Emit x+ as x(&|), where & means "self". */
  459. X        next = regnode(BRANCH);            /* Either */
  460. X        regtail(ret, next);
  461. X        regtail(regnode(BACK), ret);        /* loop back */
  462. X        regtail(next, regnode(BRANCH));        /* or */
  463. X        regtail(ret, regnode(NOTHING));        /* null. */
  464. X    } else if (op == '?') {
  465. X        /* Emit x? as (x|) */
  466. X        reginsert(BRANCH, ret);            /* Either x */
  467. X        regtail(ret, regnode(BRANCH));        /* or */
  468. X        next = regnode(NOTHING);        /* null. */
  469. X        regtail(ret, next);
  470. X        regoptail(ret, next);
  471. X    }
  472. X    regparse++;
  473. X    if (ISMULT(*regparse))
  474. X        FAIL("nested *?+");
  475. X
  476. X    return(ret);
  477. X}
  478. X
  479. X/*
  480. X - regatom - the lowest level
  481. X *
  482. X * Optimization:  gobbles an entire sequence of ordinary characters so that
  483. X * it can turn them into a single node, which is smaller to store and
  484. X * faster to run.  Backslashed characters are exceptions, each becoming a
  485. X * separate node; the code is simpler that way and it's not worth fixing.
  486. X */
  487. Xstatic char *
  488. Xregatom(flagp)
  489. Xint *flagp;
  490. X{
  491. X    register char *ret;
  492. X    int flags;
  493. X
  494. X    *flagp = WORST;        /* Tentatively. */
  495. X
  496. X    switch (*regparse++) {
  497. X    case '^':
  498. X        ret = regnode(BOL);
  499. X        break;
  500. X    case '$':
  501. X        ret = regnode(EOL);
  502. X        break;
  503. X    case '.':
  504. X        ret = regnode(ANY);
  505. X        *flagp |= HASWIDTH|SIMPLE;
  506. X        break;
  507. X    case '[': {
  508. X            register int clss;
  509. X            register int classend;
  510. X
  511. X            if (*regparse == '^') {    /* Complement of range. */
  512. X                ret = regnode(ANYBUT);
  513. X                regparse++;
  514. X            } else
  515. X                ret = regnode(ANYOF);
  516. X            if (*regparse == ']' || *regparse == '-')
  517. X                regc(*regparse++);
  518. X            while (*regparse != '\0' && *regparse != ']') {
  519. X                if (*regparse == '-') {
  520. X                    regparse++;
  521. X                    if (*regparse == ']' || *regparse == '\0')
  522. X                        regc('-');
  523. X                    else {
  524. X                        clss = UCHARAT(regparse-2)+1;
  525. X                        classend = UCHARAT(regparse);
  526. X                        if (clss > classend+1)
  527. X                            FAIL("invalid [] range");
  528. X                        for (; clss <= classend; clss++)
  529. X                            regc(clss);
  530. X                        regparse++;
  531. X                    }
  532. X                } else
  533. X                    regc(*regparse++);
  534. X            }
  535. X            regc('\0');
  536. X            if (*regparse != ']')
  537. X                FAIL("unmatched []");
  538. X            regparse++;
  539. X            *flagp |= HASWIDTH|SIMPLE;
  540. X        }
  541. X        break;
  542. X    case '(':
  543. X        ret = reg(1, &flags);
  544. X        if (ret == NULL)
  545. X            return(NULL);
  546. X        *flagp |= flags&(HASWIDTH|SPSTART);
  547. X        break;
  548. X    case '\0':
  549. X    case '|':
  550. X    case ')':
  551. X        FAIL("internal urp");    /* Supposed to be caught earlier. */
  552. X        /* NOTREACHED */
  553. X        break;
  554. X    case '?':
  555. X    case '+':
  556. X    case '*':
  557. X        FAIL("?+* follows nothing");
  558. X        /* NOTREACHED */
  559. X        break;
  560. X    case '\\':
  561. X        if (*regparse == '\0')
  562. X            FAIL("trailing \\");
  563. X        ret = regnode(EXACTLY);
  564. X        regc(*regparse++);
  565. X        regc('\0');
  566. X        *flagp |= HASWIDTH|SIMPLE;
  567. X        break;
  568. X    default: {
  569. X            register int len;
  570. X            register char ender;
  571. X
  572. X            regparse--;
  573. X            len = strcspn(regparse, META);
  574. X            if (len <= 0)
  575. X                FAIL("internal disaster");
  576. X            ender = *(regparse+len);
  577. X            if (len > 1 && ISMULT(ender))
  578. X                len--;        /* Back off clear of ?+* operand. */
  579. X            *flagp |= HASWIDTH;
  580. X            if (len == 1)
  581. X                *flagp |= SIMPLE;
  582. X            ret = regnode(EXACTLY);
  583. X            while (len > 0) {
  584. X                regc(*regparse++);
  585. X                len--;
  586. X            }
  587. X            regc('\0');
  588. X        }
  589. X        break;
  590. X    }
  591. X
  592. X    return(ret);
  593. X}
  594. X
  595. X/*
  596. X - regnode - emit a node
  597. X */
  598. Xstatic char *            /* Location. */
  599. Xregnode(op)
  600. Xchar op;
  601. X{
  602. X    register char *ret;
  603. X    register char *ptr;
  604. X
  605. X    ret = regcode;
  606. X    if (ret == ®dummy) {
  607. X        regsize += 3;
  608. X        return(ret);
  609. X    }
  610. X
  611. X    ptr = ret;
  612. X    *ptr++ = op;
  613. X    *ptr++ = '\0';        /* Null "next" pointer. */
  614. X    *ptr++ = '\0';
  615. X    regcode = ptr;
  616. X
  617. X    return(ret);
  618. X}
  619. X
  620. X/*
  621. X - regc - emit (if appropriate) a byte of code
  622. X */
  623. Xstatic void
  624. Xregc(b)
  625. Xchar b;
  626. X{
  627. X    if (regcode != ®dummy)
  628. X        *regcode++ = b;
  629. X    else
  630. X        regsize++;
  631. X}
  632. X
  633. X/*
  634. X - reginsert - insert an operator in front of already-emitted operand
  635. X *
  636. X * Means relocating the operand.
  637. X */
  638. Xstatic void
  639. Xreginsert(op, opnd)
  640. Xchar op;
  641. Xchar *opnd;
  642. X{
  643. X    register char *src;
  644. X    register char *dst;
  645. X    register char *place;
  646. X
  647. X    if (regcode == ®dummy) {
  648. X        regsize += 3;
  649. X        return;
  650. X    }
  651. X
  652. X    src = regcode;
  653. X    regcode += 3;
  654. X    dst = regcode;
  655. X    while (src > opnd)
  656. X        *--dst = *--src;
  657. X
  658. X    place = opnd;        /* Op node, where operand used to be. */
  659. X    *place++ = op;
  660. X    *place++ = '\0';
  661. X    *place++ = '\0';
  662. X}
  663. X
  664. X/*
  665. X - regtail - set the next-pointer at the end of a node chain
  666. X */
  667. Xstatic void
  668. Xregtail(p, val)
  669. Xchar *p;
  670. Xchar *val;
  671. X{
  672. X    register char *scan;
  673. X    register char *temp;
  674. X    register int offset;
  675. X
  676. X    if (p == ®dummy)
  677. X        return;
  678. X
  679. X    /* Find last node. */
  680. X    scan = p;
  681. X    for (;;) {
  682. X        temp = regnext(scan);
  683. X        if (temp == NULL)
  684. X            break;
  685. X        scan = temp;
  686. X    }
  687. X
  688. X    if (OP(scan) == BACK)
  689. X        offset = scan - val;
  690. X    else
  691. X        offset = val - scan;
  692. X    *(scan+1) = (offset>>8)&0377;
  693. X    *(scan+2) = offset&0377;
  694. X}
  695. X
  696. X/*
  697. X - regoptail - regtail on operand of first argument; nop if operandless
  698. X */
  699. Xstatic void
  700. Xregoptail(p, val)
  701. Xchar *p;
  702. Xchar *val;
  703. X{
  704. X    /* "Operandless" and "op != BRANCH" are synonymous in practice. */
  705. X    if (p == NULL || p == ®dummy || OP(p) != BRANCH)
  706. X        return;
  707. X    regtail(OPERAND(p), val);
  708. X}
  709. X
  710. X/*
  711. X * regexec and friends
  712. X */
  713. X
  714. X/*
  715. X * Global work variables for regexec().
  716. X */
  717. Xstatic char *reginput;        /* String-input pointer. */
  718. Xstatic char *regbol;        /* Beginning of input, for ^ check. */
  719. Xstatic char **regstartp;    /* Pointer to startp array. */
  720. Xstatic char **regendp;        /* Ditto for endp. */
  721. X
  722. X/*
  723. X * Forwards.
  724. X */
  725. XSTATIC int regtry();
  726. XSTATIC int regmatch();
  727. XSTATIC int regrepeat();
  728. X
  729. X#ifdef DEBUG
  730. Xint regnarrate = 0;
  731. Xvoid regdump();
  732. XSTATIC char *regprop();
  733. X#endif
  734. X
  735. X/*
  736. X - regexec - match a regexp against a string
  737. X */
  738. Xint
  739. Xregexec(prog, string)
  740. Xregister regexp *prog;
  741. Xregister char *string;
  742. X{
  743. X    register char *s;
  744. X    extern char *strchr();
  745. X
  746. X    /* Be paranoid... */
  747. X    if (prog == NULL || string == NULL) {
  748. X        regerror("NULL parameter");
  749. X        return(0);
  750. X    }
  751. X
  752. X    /* Check validity of program. */
  753. X    if (UCHARAT(prog->program) != MAGIC) {
  754. X        regerror("corrupted program");
  755. X        return(0);
  756. X    }
  757. X
  758. X    /* If there is a "must appear" string, look for it. */
  759. X    if (prog->regmust != NULL) {
  760. X        s = string;
  761. X        while ((s = strchr(s, prog->regmust[0])) != NULL) {
  762. X            if (strncmp(s, prog->regmust, prog->regmlen) == 0)
  763. X                break;    /* Found it. */
  764. X            s++;
  765. X        }
  766. X        if (s == NULL)    /* Not present. */
  767. X            return(0);
  768. X    }
  769. X
  770. X    /* Mark beginning of line for ^ . */
  771. X    regbol = string;
  772. X
  773. X    /* Simplest case:  anchored match need be tried only once. */
  774. X    if (prog->reganch)
  775. X        return(regtry(prog, string));
  776. X
  777. X    /* Messy cases:  unanchored match. */
  778. X    s = string;
  779. X    if (prog->regstart != '\0')
  780. X        /* We know what char it must start with. */
  781. X        while ((s = strchr(s, prog->regstart)) != NULL) {
  782. X            if (regtry(prog, s))
  783. X                return(1);
  784. X            s++;
  785. X        }
  786. X    else
  787. X        /* We don't -- general case. */
  788. X        do {
  789. X            if (regtry(prog, s))
  790. X                return(1);
  791. X        } while (*s++ != '\0');
  792. X
  793. X    /* Failure. */
  794. X    return(0);
  795. X}
  796. X
  797. X/*
  798. X - regtry - try match at specific point
  799. X */
  800. Xstatic int            /* 0 failure, 1 success */
  801. Xregtry(prog, string)
  802. Xregexp *prog;
  803. Xchar *string;
  804. X{
  805. X    register int i;
  806. X    register char **sp;
  807. X    register char **ep;
  808. X
  809. X    reginput = string;
  810. X    regstartp = prog->startp;
  811. X    regendp = prog->endp;
  812. X
  813. X    sp = prog->startp;
  814. X    ep = prog->endp;
  815. X    for (i = NSUBEXP; i > 0; i--) {
  816. X        *sp++ = NULL;
  817. X        *ep++ = NULL;
  818. X    }
  819. X    if (regmatch(prog->program + 1)) {
  820. X        prog->startp[0] = string;
  821. X        prog->endp[0] = reginput;
  822. X        return(1);
  823. X    } else
  824. X        return(0);
  825. X}
  826. X
  827. X/*
  828. X - regmatch - main matching routine
  829. X *
  830. X * Conceptually the strategy is simple:  check to see whether the current
  831. X * node matches, call self recursively to see whether the rest matches,
  832. X * and then act accordingly.  In practice we make some effort to avoid
  833. X * recursion, in particular by going through "ordinary" nodes (that don't
  834. X * need to know whether the rest of the match failed) by a loop instead of
  835. X * by recursion.
  836. X */
  837. Xstatic int            /* 0 failure, 1 success */
  838. Xregmatch(prog)
  839. Xchar *prog;
  840. X{
  841. X    register char *scan;    /* Current node. */
  842. X    char *next;        /* Next node. */
  843. X    extern char *strchr();
  844. X
  845. X    scan = prog;
  846. X#ifdef DEBUG
  847. X    if (scan != NULL && regnarrate)
  848. X        fprintf(stderr, "%s(\n", regprop(scan));
  849. X#endif
  850. X    while (scan != NULL) {
  851. X#ifdef DEBUG
  852. X        if (regnarrate)
  853. X            fprintf(stderr, "%s...\n", regprop(scan));
  854. X#endif
  855. X        next = regnext(scan);
  856. X
  857. X        switch (OP(scan)) {
  858. X        case BOL:
  859. X            if (reginput != regbol)
  860. X                return(0);
  861. X            break;
  862. X        case EOL:
  863. X            if (*reginput != '\0')
  864. X                return(0);
  865. X            break;
  866. X        case ANY:
  867. X            if (*reginput == '\0')
  868. X                return(0);
  869. X            reginput++;
  870. X            break;
  871. X        case EXACTLY: {
  872. X                register int len;
  873. X                register char *opnd;
  874. X
  875. X                opnd = OPERAND(scan);
  876. X                /* Inline the first character, for speed. */
  877. X                if (*opnd != *reginput)
  878. X                    return(0);
  879. X                len = strlen(opnd);
  880. X                if (len > 1 && strncmp(opnd, reginput, len) != 0)
  881. X                    return(0);
  882. X                reginput += len;
  883. X            }
  884. X            break;
  885. X        case ANYOF:
  886. X             if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) == NULL)
  887. X                return(0);
  888. X            reginput++;
  889. X            break;
  890. X        case ANYBUT:
  891. X             if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) != NULL)
  892. X                return(0);
  893. X            reginput++;
  894. X            break;
  895. X        case NOTHING:
  896. X            break;
  897. X        case BACK:
  898. X            break;
  899. X        case OPEN+1:
  900. X        case OPEN+2:
  901. X        case OPEN+3:
  902. X        case OPEN+4:
  903. X        case OPEN+5:
  904. X        case OPEN+6:
  905. X        case OPEN+7:
  906. X        case OPEN+8:
  907. X        case OPEN+9: {
  908. X                register int no;
  909. X                register char *save;
  910. X
  911. X                no = OP(scan) - OPEN;
  912. X                save = reginput;
  913. X
  914. X                if (regmatch(next)) {
  915. X                    /*
  916. X                     * Don't set startp if some later
  917. X                     * invocation of the same parentheses
  918. X                     * already has.
  919. X                     */
  920. X                    if (regstartp[no] == NULL)
  921. X                        regstartp[no] = save;
  922. X                    return(1);
  923. X                } else
  924. X                    return(0);
  925. X            }
  926. X            /* NOTREACHED */
  927. X            break;
  928. X        case CLOSE+1:
  929. X        case CLOSE+2:
  930. X        case CLOSE+3:
  931. X        case CLOSE+4:
  932. X        case CLOSE+5:
  933. X        case CLOSE+6:
  934. X        case CLOSE+7:
  935. X        case CLOSE+8:
  936. X        case CLOSE+9: {
  937. X                register int no;
  938. X                register char *save;
  939. X
  940. X                no = OP(scan) - CLOSE;
  941. X                save = reginput;
  942. X
  943. X                if (regmatch(next)) {
  944. X                    /*
  945. X                     * Don't set endp if some later
  946. X                     * invocation of the same parentheses
  947. X                     * already has.
  948. X                     */
  949. X                    if (regendp[no] == NULL)
  950. X                        regendp[no] = save;
  951. X                    return(1);
  952. X                } else
  953. X                    return(0);
  954. X            }
  955. X            /* NOTREACHED */
  956. X            break;
  957. X        case BRANCH: {
  958. X                register char *save;
  959. X
  960. X                if (OP(next) != BRANCH)        /* No choice. */
  961. X                    next = OPERAND(scan);    /* Avoid recursion. */
  962. X                else {
  963. X                    do {
  964. X                        save = reginput;
  965. X                        if (regmatch(OPERAND(scan)))
  966. X                            return(1);
  967. X                        reginput = save;
  968. X                        scan = regnext(scan);
  969. X                    } while (scan != NULL && OP(scan) == BRANCH);
  970. X                    return(0);
  971. X                    /* NOTREACHED */
  972. X                }
  973. X            }
  974. X            /* NOTREACHED */
  975. X            break;
  976. X        case STAR:
  977. X        case PLUS: {
  978. X                register char nextch;
  979. X                register int no;
  980. X                register char *save;
  981. X                register int min;
  982. X
  983. X                /*
  984. X                 * Lookahead to avoid useless match attempts
  985. X                 * when we know what character comes next.
  986. X                 */
  987. X                nextch = '\0';
  988. X                if (OP(next) == EXACTLY)
  989. X                    nextch = *OPERAND(next);
  990. X                min = (OP(scan) == STAR) ? 0 : 1;
  991. X                save = reginput;
  992. X                no = regrepeat(OPERAND(scan));
  993. X                while (no >= min) {
  994. X                    /* If it could work, try it. */
  995. X                    if (nextch == '\0' || *reginput == nextch)
  996. X                        if (regmatch(next))
  997. X                            return(1);
  998. X                    /* Couldn't or didn't -- back up. */
  999. X                    no--;
  1000. X                    reginput = save + no;
  1001. X                }
  1002. X                return(0);
  1003. X            }
  1004. X            /* NOTREACHED */
  1005. X            break;
  1006. X        case END:
  1007. X            return(1);    /* Success! */
  1008. X            /* NOTREACHED */
  1009. X            break;
  1010. X        default:
  1011. X            regerror("memory corruption");
  1012. X            return(0);
  1013. X            /* NOTREACHED */
  1014. X            break;
  1015. X        }
  1016. X
  1017. X        scan = next;
  1018. X    }
  1019. X
  1020. X    /*
  1021. X     * We get here only if there's trouble -- normally "case END" is
  1022. X     * the terminating point.
  1023. X     */
  1024. X    regerror("corrupted pointers");
  1025. X    return(0);
  1026. X}
  1027. X
  1028. X/*
  1029. X - regrepeat - repeatedly match something simple, report how many
  1030. X */
  1031. Xstatic int
  1032. Xregrepeat(p)
  1033. Xchar *p;
  1034. X{
  1035. X    register int count = 0;
  1036. X    register char *scan;
  1037. X    register char *opnd;
  1038. X
  1039. X    scan = reginput;
  1040. X    opnd = OPERAND(p);
  1041. X    switch (OP(p)) {
  1042. X    case ANY:
  1043. X        count = strlen(scan);
  1044. X        scan += count;
  1045. X        break;
  1046. X    case EXACTLY:
  1047. X        while (*opnd == *scan) {
  1048. X            count++;
  1049. X            scan++;
  1050. X        }
  1051. X        break;
  1052. X    case ANYOF:
  1053. X        while (*scan != '\0' && strchr(opnd, *scan) != NULL) {
  1054. X            count++;
  1055. X            scan++;
  1056. X        }
  1057. X        break;
  1058. X    case ANYBUT:
  1059. X        while (*scan != '\0' && strchr(opnd, *scan) == NULL) {
  1060. X            count++;
  1061. X            scan++;
  1062. X        }
  1063. X        break;
  1064. X    default:        /* Oh dear.  Called inappropriately. */
  1065. X        regerror("internal foulup");
  1066. X        count = 0;    /* Best compromise. */
  1067. X        break;
  1068. X    }
  1069. X    reginput = scan;
  1070. X
  1071. X    return(count);
  1072. X}
  1073. X
  1074. X/*
  1075. X - regnext - dig the "next" pointer out of a node
  1076. X */
  1077. Xstatic char *
  1078. Xregnext(p)
  1079. Xregister char *p;
  1080. X{
  1081. X    register int offset;
  1082. X
  1083. X    if (p == ®dummy)
  1084. X        return(NULL);
  1085. X
  1086. X    offset = NEXT(p);
  1087. X    if (offset == 0)
  1088. X        return(NULL);
  1089. X
  1090. X    if (OP(p) == BACK)
  1091. X        return(p-offset);
  1092. X    else
  1093. X        return(p+offset);
  1094. X}
  1095. X
  1096. X#ifdef DEBUG
  1097. X
  1098. XSTATIC char *regprop();
  1099. X
  1100. X/*
  1101. X - regdump - dump a regexp onto stdout in vaguely comprehensible form
  1102. X */
  1103. Xvoid
  1104. Xregdump(r)
  1105. Xregexp *r;
  1106. X{
  1107. X    register char *s;
  1108. X    register char op = EXACTLY;    /* Arbitrary non-END op. */
  1109. X    register char *next;
  1110. X    extern char *strchr();
  1111. X
  1112. X
  1113. X    s = r->program + 1;
  1114. X    while (op != END) {    /* While that wasn't END last time... */
  1115. X        op = OP(s);
  1116. X        printf("%2d%s", s-r->program, regprop(s));    /* Where, what. */
  1117. X        next = regnext(s);
  1118. X        if (next == NULL)        /* Next ptr. */
  1119. X            printf("(0)");
  1120. X        else 
  1121. X            printf("(%d)", (s-r->program)+(next-s));
  1122. X        s += 3;
  1123. X        if (op == ANYOF || op == ANYBUT || op == EXACTLY) {
  1124. X            /* Literal string, where present. */
  1125. X            while (*s != '\0') {
  1126. X                putchar(*s);
  1127. X                s++;
  1128. X            }
  1129. X            s++;
  1130. X        }
  1131. X        putchar('\n');
  1132. X    }
  1133. X
  1134. X    /* Header fields of interest. */
  1135. X    if (r->regstart != '\0')
  1136. X        printf("start `%c' ", r->regstart);
  1137. X    if (r->reganch)
  1138. X        printf("anchored ");
  1139. X    if (r->regmust != NULL)
  1140. X        printf("must have \"%s\"", r->regmust);
  1141. X    printf("\n");
  1142. X}
  1143. X
  1144. X/*
  1145. X - regprop - printable representation of opcode
  1146. X */
  1147. Xstatic char *
  1148. Xregprop(op)
  1149. Xchar *op;
  1150. X{
  1151. X    register char *p;
  1152. X    static char buf[50];
  1153. X
  1154. X    (void) strcpy(buf, ":");
  1155. X
  1156. X    switch (OP(op)) {
  1157. X    case BOL:
  1158. X        p = "BOL";
  1159. X        break;
  1160. X    case EOL:
  1161. X        p = "EOL";
  1162. X        break;
  1163. X    case ANY:
  1164. X        p = "ANY";
  1165. X        break;
  1166. X    case ANYOF:
  1167. X        p = "ANYOF";
  1168. X        break;
  1169. X    case ANYBUT:
  1170. X        p = "ANYBUT";
  1171. X        break;
  1172. X    case BRANCH:
  1173. X        p = "BRANCH";
  1174. X        break;
  1175. X    case EXACTLY:
  1176. X        p = "EXACTLY";
  1177. X        break;
  1178. X    case NOTHING:
  1179. X        p = "NOTHING";
  1180. X        break;
  1181. X    case BACK:
  1182. X        p = "BACK";
  1183. X        break;
  1184. X    case END:
  1185. X        p = "END";
  1186. X        break;
  1187. X    case OPEN+1:
  1188. X    case OPEN+2:
  1189. X    case OPEN+3:
  1190. X    case OPEN+4:
  1191. X    case OPEN+5:
  1192. X    case OPEN+6:
  1193. X    case OPEN+7:
  1194. X    case OPEN+8:
  1195. X    case OPEN+9:
  1196. X        sprintf(buf+strlen(buf), "OPEN%d", OP(op)-OPEN);
  1197. X        p = NULL;
  1198. X        break;
  1199. X    case CLOSE+1:
  1200. X    case CLOSE+2:
  1201. X    case CLOSE+3:
  1202. X    case CLOSE+4:
  1203. X    case CLOSE+5:
  1204. X    case CLOSE+6:
  1205. X    case CLOSE+7:
  1206. X    case CLOSE+8:
  1207. X    case CLOSE+9:
  1208. X        sprintf(buf+strlen(buf), "CLOSE%d", OP(op)-CLOSE);
  1209. X        p = NULL;
  1210. X        break;
  1211. X    case STAR:
  1212. X        p = "STAR";
  1213. X        break;
  1214. X    case PLUS:
  1215. X        p = "PLUS";
  1216. X        break;
  1217. X    default:
  1218. X        regerror("corrupted opcode");
  1219. X        break;
  1220. X    }
  1221. X    if (p != NULL)
  1222. X        (void) strcat(buf, p);
  1223. X    return(buf);
  1224. X}
  1225. X#endif
  1226. X
  1227. X/*
  1228. X * The following is provided for those people who do not have strcspn() in
  1229. X * their C libraries.  They should get off their butts and do something
  1230. X * about it; at least one public-domain implementation of those (highly
  1231. X * useful) string routines has been published on Usenet.
  1232. X */
  1233. X#ifdef STRCSPN
  1234. X/*
  1235. X * strcspn - find length of initial segment of s1 consisting entirely
  1236. X * of characters not from s2
  1237. X */
  1238. X
  1239. Xstatic int
  1240. Xstrcspn(s1, s2)
  1241. Xchar *s1;
  1242. Xchar *s2;
  1243. X{
  1244. X    register char *scan1;
  1245. X    register char *scan2;
  1246. X    register int count;
  1247. X
  1248. X    count = 0;
  1249. X    for (scan1 = s1; *scan1 != '\0'; scan1++) {
  1250. X        for (scan2 = s2; *scan2 != '\0';)    /* ++ moved down. */
  1251. X            if (*scan1 == *scan2++)
  1252. X                return(count);
  1253. X        count++;
  1254. X    }
  1255. X    return(count);
  1256. X}
  1257. X#endif
  1258. END_OF_FILE
  1259. if test 28040 -ne `wc -c <'tcl6.1/regexp.c'`; then
  1260.     echo shar: \"'tcl6.1/regexp.c'\" unpacked with wrong size!
  1261. fi
  1262. # end of 'tcl6.1/regexp.c'
  1263. fi
  1264. echo shar: End of archive 18 \(of 33\).
  1265. cp /dev/null ark18isdone
  1266. MISSING=""
  1267. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 ; do
  1268.     if test ! -f ark${I}isdone ; then
  1269.     MISSING="${MISSING} ${I}"
  1270.     fi
  1271. done
  1272. if test "${MISSING}" = "" ; then
  1273.     echo You have unpacked all 33 archives.
  1274.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1275. else
  1276.     echo You still need to unpack the following archives:
  1277.     echo "        " ${MISSING}
  1278. fi
  1279. ##  End of shell archive.
  1280. exit 0
  1281.  
  1282. exit 0 # Just in case...
  1283. -- 
  1284. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  1285. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  1286. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  1287. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  1288.