home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume15 / perl2 / part02 < prev    next >
Encoding:
Internet Message Format  |  1989-01-05  |  49.7 KB

  1. Subject:  v15i091:  Perl, release 2, Part02/15
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Larry Wall <lwall@jpl-devvax.jpl.nasa.gov>
  7. Posting-number: Volume 15, Issue 91
  8. Archive-name: perl2/part02
  9.  
  10. #! /bin/sh
  11.  
  12. # Make a new directory for the perl sources, cd to it, and run kits 1
  13. # thru 15 through sh.  When all 15 kits have been run, read README.
  14.  
  15. echo "This is perl 2.0 kit 2 (of 15).  If kit 2 is complete, the line"
  16. echo '"'"End of kit 2 (of 15)"'" will echo at the end.'
  17. echo ""
  18. export PATH || (echo "You didn't use sh, you clunch." ; kill $$)
  19. mkdir eg eg/g t 2>/dev/null
  20. echo Extracting regexp.c
  21. sed >regexp.c <<'!STUFFY!FUNK!' -e 's/X//'
  22. X/* NOTE: this is derived from Henry Spencer's regexp code, and should not
  23. X * confused with the original package (see point 3 below).  Thanks, Henry!
  24. X */
  25. X
  26. X/* Additional note: this code is very heavily munged from Henry's version
  27. X * in places.  In some spots I've traded clarity for efficiency, so don't
  28. X * blame Henry for some of the lack of readability.
  29. X */
  30. X
  31. X/* $Header: regexp.c,v 2.0 88/06/05 00:10:45 root Exp $
  32. X *
  33. X * $Log:    regexp.c,v $
  34. X * Revision 2.0  88/06/05  00:10:45  root
  35. X * Baseline version 2.0.
  36. X * 
  37. X */
  38. X
  39. X/*
  40. X * regcomp and regexec -- regsub and regerror are not used in perl
  41. X *
  42. X *    Copyright (c) 1986 by University of Toronto.
  43. X *    Written by Henry Spencer.  Not derived from licensed software.
  44. X *
  45. X *    Permission is granted to anyone to use this software for any
  46. X *    purpose on any computer system, and to redistribute it freely,
  47. X *    subject to the following restrictions:
  48. X *
  49. X *    1. The author is not responsible for the consequences of use of
  50. X *        this software, no matter how awful, even if they arise
  51. X *        from defects in it.
  52. X *
  53. X *    2. The origin of this software must not be misrepresented, either
  54. X *        by explicit claim or by omission.
  55. X *
  56. X *    3. Altered versions must be plainly marked as such, and must not
  57. X *        be misrepresented as being the original software.
  58. X *
  59. X * Beware that some of this code is subtly aware of the way operator
  60. X * precedence is structured in regular expressions.  Serious changes in
  61. X * regular-expression syntax might require a total rethink.
  62. X */
  63. X#include "EXTERN.h"
  64. X#include "perl.h"
  65. X
  66. X/*
  67. X * The "internal use only" fields in regexp.h are present to pass info from
  68. X * compile to execute that permits the execute phase to run lots faster on
  69. X * simple cases.  They are:
  70. X *
  71. X * regstart    str that must begin a match; Nullch if none obvious
  72. X * reganch    is the match anchored (at beginning-of-line only)?
  73. X * regmust    string (pointer into program) that match must include, or NULL
  74. X *  [regmust changed to STR* for bminstr()--law]
  75. X * regmlen    length of regmust string
  76. X *  [regmlen not used currently]
  77. X *
  78. X * Regstart and reganch permit very fast decisions on suitable starting points
  79. X * for a match, cutting down the work a lot.  Regmust permits fast rejection
  80. X * of lines that cannot possibly match.  The regmust tests are costly enough
  81. X * that regcomp() supplies a regmust only if the r.e. contains something
  82. X * potentially expensive (at present, the only such thing detected is * or +
  83. X * at the start of the r.e., which can involve a lot of backup).  Regmlen is
  84. X * supplied because the test in regexec() needs it and regcomp() is computing
  85. X * it anyway.
  86. X * [regmust is now supplied always.  The tests that use regmust have a
  87. X * heuristic that disables the test if it usually matches.]
  88. X *
  89. X * [In fact, we now use regmust in many cases to locate where the search
  90. X * starts in the string, so if regback is >= 0, the regmust search is never
  91. X * wasted effort.  The regback variable says how many characters back from
  92. X * where regmust matched is the earliest possible start of the match.
  93. X * For instance, /[a-z].foo/ has a regmust of 'foo' and a regback of 2.]
  94. X */
  95. X
  96. X/*
  97. X * Structure for regexp "program".  This is essentially a linear encoding
  98. X * of a nondeterministic finite-state machine (aka syntax charts or
  99. X * "railroad normal form" in parsing technology).  Each node is an opcode
  100. X * plus a "next" pointer, possibly plus an operand.  "Next" pointers of
  101. X * all nodes except BRANCH implement concatenation; a "next" pointer with
  102. X * a BRANCH on both ends of it is connecting two alternatives.  (Here we
  103. X * have one of the subtle syntax dependencies:  an individual BRANCH (as
  104. X * opposed to a collection of them) is never concatenated with anything
  105. X * because of operator precedence.)  The operand of some types of node is
  106. X * a literal string; for others, it is a node leading into a sub-FSM.  In
  107. X * particular, the operand of a BRANCH node is the first node of the branch.
  108. X * (NB this is *not* a tree structure:  the tail of the branch connects
  109. X * to the thing following the set of BRANCHes.)  The opcodes are:
  110. X */
  111. X
  112. X/* definition    number    opnd?    meaning */
  113. X#define    END    0    /* no    End of program. */
  114. X#define    BOL    1    /* no    Match "" at beginning of line. */
  115. X#define    EOL    2    /* no    Match "" at end of line. */
  116. X#define    ANY    3    /* no    Match any one character. */
  117. X#define    ANYOF    4    /* str    Match any character in this string. */
  118. X#define    ANYBUT    5    /* str    Match any character not in this string. */
  119. X#define    BRANCH    6    /* node    Match this alternative, or the next... */
  120. X#define    BACK    7    /* no    Match "", "next" ptr points backward. */
  121. X#define    EXACTLY    8    /* str    Match this string (preceded by length). */
  122. X#define    NOTHING    9    /* no    Match empty string. */
  123. X#define    STAR    10    /* node    Match this (simple) thing 0 or more times. */
  124. X#define    PLUS    11    /* node    Match this (simple) thing 1 or more times. */
  125. X#define ALNUM    12    /* no    Match any alphanumeric character */
  126. X#define NALNUM    13    /* no    Match any non-alphanumeric character */
  127. X#define BOUND    14    /* no    Match "" at any word boundary */
  128. X#define NBOUND    15    /* no    Match "" at any word non-boundary */
  129. X#define SPACE    16    /* no    Match any whitespace character */
  130. X#define NSPACE    17    /* no    Match any non-whitespace character */
  131. X#define DIGIT    18    /* no    Match any numeric character */
  132. X#define NDIGIT    19    /* no    Match any non-numeric character */
  133. X#define REF    20    /* no    Match some already matched string */
  134. X#define    OPEN    30    /* no    Mark this point in input as start of #n. */
  135. X            /*    OPEN+1 is number 1, etc. */
  136. X#define    CLOSE    40    /* no    Analogous to OPEN. */
  137. X
  138. X/*
  139. X * Opcode notes:
  140. X *
  141. X * BRANCH    The set of branches constituting a single choice are hooked
  142. X *        together with their "next" pointers, since precedence prevents
  143. X *        anything being concatenated to any individual branch.  The
  144. X *        "next" pointer of the last BRANCH in a choice points to the
  145. X *        thing following the whole choice.  This is also where the
  146. X *        final "next" pointer of each individual branch points; each
  147. X *        branch starts with the operand node of a BRANCH node.
  148. X *
  149. X * BACK        Normal "next" pointers all implicitly point forward; BACK
  150. X *        exists to make loop structures possible.
  151. X *
  152. X * STAR,PLUS    '?', and complex '*' and '+', are implemented as circular
  153. X *        BRANCH structures using BACK.  Simple cases (one character
  154. X *        per match) are implemented with STAR and PLUS for speed
  155. X *        and to minimize recursive plunges.
  156. X *
  157. X * OPEN,CLOSE    ...are numbered at compile time.
  158. X */
  159. X
  160. X/* The following have no fixed length. */
  161. Xchar varies[] = {BRANCH,BACK,STAR,PLUS,REF,0};
  162. X
  163. X/* The following always have a length of 1. */
  164. Xchar simple[] = {ANY,ANYOF,ANYBUT,ALNUM,NALNUM,SPACE,NSPACE,DIGIT,NDIGIT,0};
  165. X
  166. X/*
  167. X * A node is one char of opcode followed by two chars of "next" pointer.
  168. X * "Next" pointers are stored as two 8-bit pieces, high order first.  The
  169. X * value is a positive offset from the opcode of the node containing it.
  170. X * An operand, if any, simply follows the node.  (Note that much of the
  171. X * code generation knows about this implicit relationship.)
  172. X *
  173. X * Using two bytes for the "next" pointer is vast overkill for most things,
  174. X * but allows patterns to get big without disasters.
  175. X *
  176. X * [If ALIGN is defined, the "next" pointer is always aligned on an even
  177. X * boundary, and reads the offset directly as a short.  Also, there is no
  178. X * special test to reverse the sign of BACK pointers since the offset is
  179. X * stored negative.]
  180. X */
  181. X
  182. X#ifndef STATIC
  183. X#define    STATIC    static
  184. X#endif
  185. X
  186. X#define ALIGN
  187. X#define FASTANY
  188. X#ifdef DEBUG
  189. X#undef DEBUG
  190. X#endif
  191. X#ifdef DEBUGGING
  192. X#define DEBUG
  193. X#endif
  194. X
  195. X#ifdef DEBUG
  196. Xint regnarrate = 0;
  197. Xvoid regdump();
  198. XSTATIC char *regprop();
  199. X#endif
  200. X
  201. X
  202. X#define    OP(p)    (*(p))
  203. X
  204. X#ifdef ALIGN
  205. X#define NEXT(p) (*(short*)(p+1))
  206. X#else
  207. X#define    NEXT(p)    (((*((p)+1)&0377)<<8) + (*((p)+2)&0377))
  208. X#endif
  209. X
  210. X#define    OPERAND(p)    ((p) + 3)
  211. X
  212. X#ifdef ALIGN
  213. X#define    NEXTOPER(p)    ((p) + 4)
  214. X#else
  215. X#define    NEXTOPER(p)    ((p) + 3)
  216. X#endif
  217. X
  218. X#define MAGIC 0234
  219. X
  220. X/*
  221. X * Utility definitions.
  222. X */
  223. X#ifndef CHARBITS
  224. X#define    UCHARAT(p)    ((int)*(unsigned char *)(p))
  225. X#else
  226. X#define    UCHARAT(p)    ((int)*(p)&CHARBITS)
  227. X#endif
  228. X
  229. X#define    FAIL(m)    fatal("/%s/: %s",regprecomp,m)
  230. X#define    ISMULT(c)    ((c) == '*' || (c) == '+' || (c) == '?')
  231. X#define    META    "^$.[()|?+*\\"
  232. X
  233. X/*
  234. X * Flags to be passed up and down.
  235. X */
  236. X#define    HASWIDTH    01    /* Known never to match null string. */
  237. X#define    SIMPLE        02    /* Simple enough to be STAR/PLUS operand. */
  238. X#define    SPSTART        04    /* Starts with * or +. */
  239. X#define    WORST        0    /* Worst case. */
  240. X
  241. X/*
  242. X * Global work variables for regcomp().
  243. X */
  244. Xstatic char *regprecomp;        /* uncompiled string. */
  245. Xstatic char *regparse;        /* Input-scan pointer. */
  246. Xstatic int regnpar;        /* () count. */
  247. Xstatic char regdummy;
  248. Xstatic char *regcode;        /* Code-emit pointer; ®dummy = don't. */
  249. Xstatic long regsize;        /* Code size. */
  250. Xstatic int regfold;
  251. X
  252. X/*
  253. X * Forward declarations for regcomp()'s friends.
  254. X */
  255. XSTATIC char *reg();
  256. XSTATIC char *regbranch();
  257. XSTATIC char *regpiece();
  258. XSTATIC char *regatom();
  259. XSTATIC char *regclass();
  260. XSTATIC char *regchar();
  261. XSTATIC char *regnode();
  262. XSTATIC char *regnext();
  263. XSTATIC void regc();
  264. XSTATIC void reginsert();
  265. XSTATIC void regtail();
  266. XSTATIC void regoptail();
  267. X#ifndef STRCSPN
  268. XSTATIC int strcspn();
  269. X#endif
  270. X
  271. X/*
  272. X - regcomp - compile a regular expression into internal code
  273. X *
  274. X * We can't allocate space until we know how big the compiled form will be,
  275. X * but we can't compile it (and thus know how big it is) until we've got a
  276. X * place to put the code.  So we cheat:  we compile it twice, once with code
  277. X * generation turned off and size counting turned on, and once "for real".
  278. X * This also means that we don't allocate space until we are sure that the
  279. X * thing really will compile successfully, and we never have to move the
  280. X * code and thus invalidate pointers into it.  (Note that it has to be in
  281. X * one piece because free() must be able to free it all.) [NB: not true in perl]
  282. X *
  283. X * Beware that the optimization-preparation code in here knows about some
  284. X * of the structure of the compiled regexp.  [I'll say.]
  285. X */
  286. Xregexp *
  287. Xregcomp(exp,fold,rare)
  288. Xchar *exp;
  289. Xint fold;
  290. Xint rare;
  291. X{
  292. X    register regexp *r;
  293. X    register char *scan;
  294. X    register STR *longest;
  295. X    register int len;
  296. X    register char *first;
  297. X    int flags;
  298. X    int back;
  299. X    int curback;
  300. X    extern char *safemalloc();
  301. X    extern char *savestr();
  302. X
  303. X    if (exp == NULL)
  304. X        fatal("NULL regexp argument");
  305. X
  306. X    /* First pass: determine size, legality. */
  307. X    regfold = fold;
  308. X    regparse = exp;
  309. X    regprecomp = savestr(exp);
  310. X    regnpar = 1;
  311. X    regsize = 0L;
  312. X    regcode = ®dummy;
  313. X    regc(MAGIC);
  314. X    if (reg(0, &flags) == NULL) {
  315. X        safefree(regprecomp);
  316. X        return(NULL);
  317. X    }
  318. X
  319. X    /* Small enough for pointer-storage convention? */
  320. X    if (regsize >= 32767L)        /* Probably could be 65535L. */
  321. X        FAIL("regexp too big");
  322. X
  323. X    /* Allocate space. */
  324. X    r = (regexp *)safemalloc(sizeof(regexp) + (unsigned)regsize);
  325. X    if (r == NULL)
  326. X        FAIL("regexp out of space");
  327. X
  328. X    /* Second pass: emit code. */
  329. X    r->precomp = regprecomp;
  330. X    r->subbase = NULL;
  331. X    regparse = exp;
  332. X    regnpar = 1;
  333. X    regcode = r->program;
  334. X    regc(MAGIC);
  335. X    if (reg(0, &flags) == NULL)
  336. X        return(NULL);
  337. X
  338. X    /* Dig out information for optimizations. */
  339. X    r->regstart = Nullstr;    /* Worst-case defaults. */
  340. X    r->reganch = 0;
  341. X    r->regmust = Nullstr;
  342. X    r->regback = -1;
  343. X    r->regstclass = Nullch;
  344. X    scan = r->program+1;            /* First BRANCH. */
  345. X    if (!fold && OP(regnext(scan)) == END) {/* Only one top-level choice. */
  346. X        scan = NEXTOPER(scan);
  347. X
  348. X        first = scan;
  349. X        while ((OP(first) > OPEN && OP(first) < CLOSE) ||
  350. X            (OP(first) == BRANCH && OP(regnext(first)) != BRANCH) ||
  351. X            (OP(first) == PLUS) )
  352. X            first = NEXTOPER(first);
  353. X
  354. X        /* Starting-point info. */
  355. X        if (OP(first) == EXACTLY)
  356. X            r->regstart = str_make(OPERAND(first)+1);
  357. X        else if ((exp = index(simple,OP(first))) && exp > simple)
  358. X            r->regstclass = first;
  359. X        else if (OP(first) == BOUND || OP(first) == NBOUND)
  360. X            r->regstclass = first;
  361. X        else if (OP(first) == BOL)
  362. X            r->reganch++;
  363. X
  364. X#ifdef DEBUGGING
  365. X        if (debug & 512)
  366. X            fprintf(stderr,"first %d next %d offset %d\n",
  367. X              OP(first), OP(NEXTOPER(first)), first - scan);
  368. X#endif
  369. X        /*
  370. X         * If there's something expensive in the r.e., find the
  371. X         * longest literal string that must appear and make it the
  372. X         * regmust.  Resolve ties in favor of later strings, since
  373. X         * the regstart check works with the beginning of the r.e.
  374. X         * and avoiding duplication strengthens checking.  Not a
  375. X         * strong reason, but sufficient in the absence of others.
  376. X         * [Now we resolve ties in favor of the earlier string if
  377. X         * it happens that curback has been invalidated, since the
  378. X         * earlier string may buy us something the later one won't.]
  379. X         */
  380. X        longest = str_new(10);
  381. X        len = 0;
  382. X        curback = 0;
  383. X        while (scan != NULL) {
  384. X            if (OP(scan) == BRANCH) {
  385. X                if (OP(regnext(scan)) == BRANCH) {
  386. X                curback = -30000;
  387. X                while (OP(scan) == BRANCH)
  388. X                    scan = regnext(scan);
  389. X                }
  390. X                else    /* single branch is ok */
  391. X                scan = NEXTOPER(scan);
  392. X            }
  393. X            if (OP(scan) == EXACTLY) {
  394. X                if (curback - back == len) {
  395. X                str_cat(longest, OPERAND(scan)+1);
  396. X                len += *OPERAND(scan);
  397. X                curback += *OPERAND(scan);
  398. X                }
  399. X                else if (*OPERAND(scan) >= len + (curback >= 0)) {
  400. X                str_set(longest, OPERAND(scan)+1);
  401. X                len = *OPERAND(scan);
  402. X                back = curback;
  403. X                curback += len;
  404. X                }
  405. X                else
  406. X                curback += *OPERAND(scan);
  407. X            }
  408. X            else if (index(varies,OP(scan)))
  409. X                curback = -30000;
  410. X            else if (index(simple,OP(scan)))
  411. X                curback++;
  412. X            scan = regnext(scan);
  413. X        }
  414. X        if (len) {
  415. X            r->regmust = longest;
  416. X            if (back < 0)
  417. X                back = -1;
  418. X            r->regback = back;
  419. X            if (len > !(sawstudy))
  420. X                fbmcompile(r->regmust);
  421. X            *(long*)&r->regmust->str_nval = 100;
  422. X#ifdef DEBUGGING
  423. X            if (debug & 512)
  424. X                fprintf(stderr,"must = '%s' back=%d\n",
  425. X                longest,back);
  426. X#endif
  427. X        }
  428. X        else
  429. X            str_free(longest);
  430. X    }
  431. X
  432. X    r->do_folding = fold;
  433. X    r->nparens = regnpar - 1;
  434. X#ifdef DEBUG
  435. X    if (debug & 512)
  436. X        regdump(r);
  437. X#endif
  438. X    return(r);
  439. X}
  440. X
  441. X/*
  442. X - reg - regular expression, i.e. main body or parenthesized thing
  443. X *
  444. X * Caller must absorb opening parenthesis.
  445. X *
  446. X * Combining parenthesis handling with the base level of regular expression
  447. X * is a trifle forced, but the need to tie the tails of the branches to what
  448. X * follows makes it hard to avoid.
  449. X */
  450. Xstatic char *
  451. Xreg(paren, flagp)
  452. Xint paren;            /* Parenthesized? */
  453. Xint *flagp;
  454. X{
  455. X    register char *ret;
  456. X    register char *br;
  457. X    register char *ender;
  458. X    register int parno;
  459. X    int flags;
  460. X
  461. X    *flagp = HASWIDTH;    /* Tentatively. */
  462. X
  463. X    /* Make an OPEN node, if parenthesized. */
  464. X    if (paren) {
  465. X        if (regnpar >= NSUBEXP)
  466. X            FAIL("too many () in regexp");
  467. X        parno = regnpar;
  468. X        regnpar++;
  469. X        ret = regnode(OPEN+parno);
  470. X    } else
  471. X        ret = NULL;
  472. X
  473. X    /* Pick up the branches, linking them together. */
  474. X    br = regbranch(&flags);
  475. X    if (br == NULL)
  476. X        return(NULL);
  477. X    if (ret != NULL)
  478. X        regtail(ret, br);    /* OPEN -> first. */
  479. X    else
  480. X        ret = br;
  481. X    if (!(flags&HASWIDTH))
  482. X        *flagp &= ~HASWIDTH;
  483. X    *flagp |= flags&SPSTART;
  484. X    while (*regparse == '|') {
  485. X        regparse++;
  486. X        br = regbranch(&flags);
  487. X        if (br == NULL)
  488. X            return(NULL);
  489. X        regtail(ret, br);    /* BRANCH -> BRANCH. */
  490. X        if (!(flags&HASWIDTH))
  491. X            *flagp &= ~HASWIDTH;
  492. X        *flagp |= flags&SPSTART;
  493. X    }
  494. X
  495. X    /* Make a closing node, and hook it on the end. */
  496. X    ender = regnode((paren) ? CLOSE+parno : END);    
  497. X    regtail(ret, ender);
  498. X
  499. X    /* Hook the tails of the branches to the closing node. */
  500. X    for (br = ret; br != NULL; br = regnext(br))
  501. X        regoptail(br, ender);
  502. X
  503. X    /* Check for proper termination. */
  504. X    if (paren && *regparse++ != ')') {
  505. X        FAIL("unmatched () in regexp");
  506. X    } else if (!paren && *regparse != '\0') {
  507. X        if (*regparse == ')') {
  508. X            FAIL("unmatched () in regexp");
  509. X        } else
  510. X            FAIL("junk on end of regexp");    /* "Can't happen". */
  511. X        /* NOTREACHED */
  512. X    }
  513. X
  514. X    return(ret);
  515. X}
  516. X
  517. X/*
  518. X - regbranch - one alternative of an | operator
  519. X *
  520. X * Implements the concatenation operator.
  521. X */
  522. Xstatic char *
  523. Xregbranch(flagp)
  524. Xint *flagp;
  525. X{
  526. X    register char *ret;
  527. X    register char *chain;
  528. X    register char *latest;
  529. X    int flags;
  530. X
  531. X    *flagp = WORST;        /* Tentatively. */
  532. X
  533. X    ret = regnode(BRANCH);
  534. X    chain = NULL;
  535. X    while (*regparse != '\0' && *regparse != '|' && *regparse != ')') {
  536. X        latest = regpiece(&flags);
  537. X        if (latest == NULL)
  538. X            return(NULL);
  539. X        *flagp |= flags&HASWIDTH;
  540. X        if (chain == NULL)    /* First piece. */
  541. X            *flagp |= flags&SPSTART;
  542. X        else
  543. X            regtail(chain, latest);
  544. X        chain = latest;
  545. X    }
  546. X    if (chain == NULL)    /* Loop ran zero times. */
  547. X        (void) regnode(NOTHING);
  548. X
  549. X    return(ret);
  550. X}
  551. X
  552. X/*
  553. X - regpiece - something followed by possible [*+?]
  554. X *
  555. X * Note that the branching code sequences used for ? and the general cases
  556. X * of * and + are somewhat optimized:  they use the same NOTHING node as
  557. X * both the endmarker for their branch list and the body of the last branch.
  558. X * It might seem that this node could be dispensed with entirely, but the
  559. X * endmarker role is not redundant.
  560. X */
  561. Xstatic char *
  562. Xregpiece(flagp)
  563. Xint *flagp;
  564. X{
  565. X    register char *ret;
  566. X    register char op;
  567. X    register char *next;
  568. X    int flags;
  569. X
  570. X    ret = regatom(&flags);
  571. X    if (ret == NULL)
  572. X        return(NULL);
  573. X
  574. X    op = *regparse;
  575. X    if (!ISMULT(op)) {
  576. X        *flagp = flags;
  577. X        return(ret);
  578. X    }
  579. X
  580. X    if (!(flags&HASWIDTH) && op != '?')
  581. X        FAIL("regexp *+ operand could be empty");
  582. X    *flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH);
  583. X
  584. X    if (op == '*' && (flags&SIMPLE))
  585. X        reginsert(STAR, ret);
  586. X    else if (op == '*') {
  587. X        /* Emit x* as (x&|), where & means "self". */
  588. X        reginsert(BRANCH, ret);            /* Either x */
  589. X        regoptail(ret, regnode(BACK));        /* and loop */
  590. X        regoptail(ret, ret);            /* back */
  591. X        regtail(ret, regnode(BRANCH));        /* or */
  592. X        regtail(ret, regnode(NOTHING));        /* null. */
  593. X    } else if (op == '+' && (flags&SIMPLE))
  594. X        reginsert(PLUS, ret);
  595. X    else if (op == '+') {
  596. X        /* Emit x+ as x(&|), where & means "self". */
  597. X        next = regnode(BRANCH);            /* Either */
  598. X        regtail(ret, next);
  599. X        regtail(regnode(BACK), ret);        /* loop back */
  600. X        regtail(next, regnode(BRANCH));        /* or */
  601. X        regtail(ret, regnode(NOTHING));        /* null. */
  602. X    } else if (op == '?') {
  603. X        /* Emit x? as (x|) */
  604. X        reginsert(BRANCH, ret);            /* Either x */
  605. X        regtail(ret, regnode(BRANCH));        /* or */
  606. X        next = regnode(NOTHING);        /* null. */
  607. X        regtail(ret, next);
  608. X        regoptail(ret, next);
  609. X    }
  610. X    regparse++;
  611. X    if (ISMULT(*regparse))
  612. X        FAIL("nested *?+ in regexp");
  613. X
  614. X    return(ret);
  615. X}
  616. X
  617. Xstatic int foo;
  618. X
  619. X/*
  620. X - regatom - the lowest level
  621. X *
  622. X * Optimization:  gobbles an entire sequence of ordinary characters so that
  623. X * it can turn them into a single node, which is smaller to store and
  624. X * faster to run.  Backslashed characters are exceptions, each becoming a
  625. X * separate node; the code is simpler that way and it's not worth fixing.
  626. X *
  627. X * [Yes, it is worth fixing, some scripts can run twice the speed.]
  628. X */
  629. Xstatic char *
  630. Xregatom(flagp)
  631. Xint *flagp;
  632. X{
  633. X    register char *ret;
  634. X    int flags;
  635. X
  636. X    *flagp = WORST;        /* Tentatively. */
  637. X
  638. X    switch (*regparse++) {
  639. X    case '^':
  640. X        ret = regnode(BOL);
  641. X        break;
  642. X    case '$':
  643. X        ret = regnode(EOL);
  644. X        break;
  645. X    case '.':
  646. X        ret = regnode(ANY);
  647. X        *flagp |= HASWIDTH|SIMPLE;
  648. X        break;
  649. X    case '[':
  650. X        ret = regclass();
  651. X        *flagp |= HASWIDTH|SIMPLE;
  652. X        break;
  653. X    case '(':
  654. X        ret = reg(1, &flags);
  655. X        if (ret == NULL)
  656. X            return(NULL);
  657. X        *flagp |= flags&(HASWIDTH|SPSTART);
  658. X        break;
  659. X    case '\0':
  660. X    case '|':
  661. X    case ')':
  662. X        FAIL("internal urp in regexp");    /* Supposed to be caught earlier. */
  663. X        break;
  664. X    case '?':
  665. X    case '+':
  666. X    case '*':
  667. X        FAIL("?+* follows nothing in regexp");
  668. X        break;
  669. X    case '\\':
  670. X        switch (*regparse) {
  671. X        case '\0':
  672. X            FAIL("trailing \\ in regexp");
  673. X        case 'w':
  674. X            ret = regnode(ALNUM);
  675. X            *flagp |= HASWIDTH|SIMPLE;
  676. X            regparse++;
  677. X            break;
  678. X        case 'W':
  679. X            ret = regnode(NALNUM);
  680. X            *flagp |= HASWIDTH|SIMPLE;
  681. X            regparse++;
  682. X            break;
  683. X        case 'b':
  684. X            ret = regnode(BOUND);
  685. X            *flagp |= SIMPLE;
  686. X            regparse++;
  687. X            break;
  688. X        case 'B':
  689. X            ret = regnode(NBOUND);
  690. X            *flagp |= SIMPLE;
  691. X            regparse++;
  692. X            break;
  693. X        case 's':
  694. X            ret = regnode(SPACE);
  695. X            *flagp |= HASWIDTH|SIMPLE;
  696. X            regparse++;
  697. X            break;
  698. X        case 'S':
  699. X            ret = regnode(NSPACE);
  700. X            *flagp |= HASWIDTH|SIMPLE;
  701. X            regparse++;
  702. X            break;
  703. X        case 'd':
  704. X            ret = regnode(DIGIT);
  705. X            *flagp |= HASWIDTH|SIMPLE;
  706. X            regparse++;
  707. X            break;
  708. X        case 'D':
  709. X            ret = regnode(NDIGIT);
  710. X            *flagp |= HASWIDTH|SIMPLE;
  711. X            regparse++;
  712. X            break;
  713. X        case 'n':
  714. X        case 'r':
  715. X        case 't':
  716. X        case 'f':
  717. X            goto defchar;
  718. X        case '0': case '1': case '2': case '3': case '4':
  719. X        case '5': case '6': case '7': case '8': case '9':
  720. X            if (isdigit(regparse[1]))
  721. X                goto defchar;
  722. X            else {
  723. X                ret = regnode(REF + *regparse++ - '0');
  724. X                *flagp |= SIMPLE;
  725. X            }
  726. X            break;
  727. X        default:
  728. X            goto defchar;
  729. X        }
  730. X        break;
  731. X    default: {
  732. X            register int len;
  733. X            register char ender;
  734. X            register char *p;
  735. X            char *oldp;
  736. X            int foo;
  737. X
  738. X            defchar:
  739. X            ret = regnode(EXACTLY);
  740. X            regc(0);        /* save spot for len */
  741. X            for (len=0, p=regparse-1; len < 127 && *p; len++) {
  742. X                oldp = p;
  743. X                switch (*p) {
  744. X                case '^':
  745. X                case '$':
  746. X                case '.':
  747. X                case '[':
  748. X                case '(':
  749. X                case ')':
  750. X                case '|':
  751. X                goto loopdone;
  752. X                case '\\':
  753. X                switch (*++p) {
  754. X                case '\0':
  755. X                    FAIL("trailing \\ in regexp");
  756. X                case 'w':
  757. X                case 'W':
  758. X                case 'b':
  759. X                case 'B':
  760. X                case 's':
  761. X                case 'S':
  762. X                case 'd':
  763. X                case 'D':
  764. X                    --p;
  765. X                    goto loopdone;
  766. X                case 'n':
  767. X                    ender = '\n';
  768. X                    p++;
  769. X                    break;
  770. X                case 'r':
  771. X                    ender = '\r';
  772. X                    p++;
  773. X                    break;
  774. X                case 't':
  775. X                    ender = '\t';
  776. X                    p++;
  777. X                    break;
  778. X                case 'f':
  779. X                    ender = '\f';
  780. X                    p++;
  781. X                    break;
  782. X                case '0': case '1': case '2': case '3':case '4':
  783. X                case '5': case '6': case '7': case '8':case '9':
  784. X                    if (isdigit(p[1])) {
  785. X                    foo = *p++ - '0';
  786. X                    foo <<= 3;
  787. X                    foo += *p - '0';
  788. X                    if (isdigit(p[1]))
  789. X                        foo = (foo<<3) + *++p - '0';
  790. X                    ender = foo;
  791. X                    p++;
  792. X                    }
  793. X                    else {
  794. X                    --p;
  795. X                    goto loopdone;
  796. X                    }
  797. X                    break;
  798. X                default:
  799. X                    ender = *p++;
  800. X                    break;
  801. X                }
  802. X                break;
  803. X                default:
  804. X                ender = *p++;
  805. X                break;
  806. X                }
  807. X                if (regfold && isupper(ender))
  808. X                    ender = tolower(ender);
  809. X                if (ISMULT(*p)) { /* Back off on ?+*. */
  810. X                if (len)
  811. X                    p = oldp;
  812. X                else {
  813. X                    len++;
  814. X                    regc(ender);
  815. X                }
  816. X                break;
  817. X                }
  818. X                regc(ender);
  819. X            }
  820. X            loopdone:
  821. X            regparse = p;
  822. X            if (len <= 0)
  823. X                FAIL("internal disaster in regexp");
  824. X            *flagp |= HASWIDTH;
  825. X            if (len == 1)
  826. X                *flagp |= SIMPLE;
  827. X            *OPERAND(ret) = len;
  828. X            regc('\0');
  829. X        }
  830. X        break;
  831. X    }
  832. X
  833. X    return(ret);
  834. X}
  835. X
  836. X#ifdef FASTANY
  837. Xstatic void
  838. Xregset(bits,def,c)
  839. Xchar *bits;
  840. Xint def;
  841. Xregister int c;
  842. X{
  843. X    if (regcode == ®dummy)
  844. X        return;
  845. X    if (def)
  846. X        bits[c >> 3] &= ~(1 << (c & 7));
  847. X    else
  848. X        bits[c >> 3] |=  (1 << (c & 7));
  849. X}
  850. X
  851. Xstatic char *
  852. Xregclass()
  853. X{
  854. X    register char *bits;
  855. X    register int class;
  856. X    register int lastclass;
  857. X    register int range = 0;
  858. X    register char *ret;
  859. X    register int def;
  860. X
  861. X    if (*regparse == '^') {    /* Complement of range. */
  862. X        ret = regnode(ANYBUT);
  863. X        regparse++;
  864. X        def = 0;
  865. X    } else {
  866. X        ret = regnode(ANYOF);
  867. X        def = 255;
  868. X    }
  869. X    bits = regcode;
  870. X    for (class = 0; class < 32; class++)
  871. X        regc(def);
  872. X    if (*regparse == ']' || *regparse == '-')
  873. X        regset(bits,def,lastclass = *regparse++);
  874. X    while (*regparse != '\0' && *regparse != ']') {
  875. X        class = UCHARAT(regparse++);
  876. X        if (class == '\\') {
  877. X            class = UCHARAT(regparse++);
  878. X            switch (class) {
  879. X            case 'w':
  880. X                for (class = 'a'; class <= 'z'; class++)
  881. X                    regset(bits,def,class);
  882. X                for (class = 'A'; class <= 'Z'; class++)
  883. X                    regset(bits,def,class);
  884. X                for (class = '0'; class <= '9'; class++)
  885. X                    regset(bits,def,class);
  886. X                regset(bits,def,'_');
  887. X                lastclass = 1234;
  888. X                continue;
  889. X            case 's':
  890. X                regset(bits,def,' ');
  891. X                regset(bits,def,'\t');
  892. X                regset(bits,def,'\r');
  893. X                regset(bits,def,'\f');
  894. X                regset(bits,def,'\n');
  895. X                lastclass = 1234;
  896. X                continue;
  897. X            case 'd':
  898. X                for (class = '0'; class <= '9'; class++)
  899. X                    regset(bits,def,class);
  900. X                lastclass = 1234;
  901. X                continue;
  902. X            case 'n':
  903. X                class = '\n';
  904. X                break;
  905. X            case 'r':
  906. X                class = '\r';
  907. X                break;
  908. X            case 't':
  909. X                class = '\t';
  910. X                break;
  911. X            case 'f':
  912. X                class = '\f';
  913. X                break;
  914. X            case 'b':
  915. X                class = '\b';
  916. X                break;
  917. X            case '0': case '1': case '2': case '3': case '4':
  918. X            case '5': case '6': case '7': case '8': case '9':
  919. X                class -= '0';
  920. X                if (isdigit(*regparse)) {
  921. X                    class <<= 3;
  922. X                    class += *regparse++ - '0';
  923. X                }
  924. X                if (isdigit(*regparse)) {
  925. X                    class <<= 3;
  926. X                    class += *regparse++ - '0';
  927. X                }
  928. X                break;
  929. X            }
  930. X        }
  931. X        if (!range && class == '-' && *regparse && *regparse != ']') {
  932. X            range = 1;
  933. X            continue;
  934. X        }
  935. X        if (range) {
  936. X            if (lastclass > class)
  937. X                FAIL("invalid [] range in regexp");
  938. X        }
  939. X        else
  940. X            lastclass = class - 1;
  941. X        range = 0;
  942. X        for (lastclass++; lastclass <= class; lastclass++) {
  943. X            regset(bits,def,lastclass);
  944. X            if (regfold && isupper(lastclass))
  945. X                regset(bits,def,tolower(lastclass));
  946. X        }
  947. X        lastclass = class;
  948. X    }
  949. X    if (*regparse != ']')
  950. X        FAIL("unmatched [] in regexp");
  951. X    regset(bits,0,0);        /* always bomb out on null */
  952. X    regparse++;
  953. X    return ret;
  954. X}
  955. X
  956. X#else /* !FASTANY */
  957. Xstatic char *
  958. Xregclass()
  959. X{
  960. X    register int class;
  961. X    register int lastclass;
  962. X    register int range = 0;
  963. X    register char *ret;
  964. X
  965. X    if (*regparse == '^') {    /* Complement of range. */
  966. X        ret = regnode(ANYBUT);
  967. X        regparse++;
  968. X    } else
  969. X        ret = regnode(ANYOF);
  970. X    if (*regparse == ']' || *regparse == '-')
  971. X        regc(lastclass = *regparse++);
  972. X    while (*regparse != '\0' && *regparse != ']') {
  973. X        class = UCHARAT(regparse++);
  974. X        if (class == '\\') {
  975. X            class = UCHARAT(regparse++);
  976. X            switch (class) {
  977. X            case 'w':
  978. X                for (class = 'a'; class <= 'z'; class++)
  979. X                    regc(class);
  980. X                for (class = 'A'; class <= 'Z'; class++)
  981. X                    regc(class);
  982. X                for (class = '0'; class <= '9'; class++)
  983. X                    regc(class);
  984. X                regc('_');
  985. X                lastclass = 1234;
  986. X                continue;
  987. X            case 's':
  988. X                regc(' ');
  989. X                regc('\t');
  990. X                regc('\r');
  991. X                regc('\f');
  992. X                regc('\n');
  993. X                lastclass = 1234;
  994. X                continue;
  995. X            case 'd':
  996. X                for (class = '0'; class <= '9'; class++)
  997. X                    regc(class);
  998. X                lastclass = 1234;
  999. X                continue;
  1000. X            case 'n':
  1001. X                class = '\n';
  1002. X                break;
  1003. X            case 'r':
  1004. X                class = '\r';
  1005. X                break;
  1006. X            case 't':
  1007. X                class = '\t';
  1008. X                break;
  1009. X            case 'f':
  1010. X                class = '\f';
  1011. X                break;
  1012. X            case 'b':
  1013. X                class = '\b';
  1014. X                break;
  1015. X            case '0': case '1': case '2': case '3': case '4':
  1016. X            case '5': case '6': case '7': case '8': case '9':
  1017. X                class -= '0';
  1018. X                if (isdigit(*regparse)) {
  1019. X                    class <<= 3;
  1020. X                    class += *regparse++ - '0';
  1021. X                }
  1022. X                if (isdigit(*regparse)) {
  1023. X                    class <<= 3;
  1024. X                    class += *regparse++ - '0';
  1025. X                }
  1026. X                break;
  1027. X            }
  1028. X        }
  1029. X        if (!range && class == '-' && *regparse && *regparse != ']') {
  1030. X            range = 1;
  1031. X            continue;
  1032. X        }
  1033. X        if (range) {
  1034. X            if (lastclass > class)
  1035. X                FAIL("invalid [] range in regexp");
  1036. X        }
  1037. X        else
  1038. X            lastclass = class - 1;
  1039. X        range = 0;
  1040. X        for (lastclass++; lastclass <= class; lastclass++) {
  1041. X            regc(lastclass);
  1042. X            if (regfold && isupper(lastclass))
  1043. X                regc(tolower(lastclass));
  1044. X        }
  1045. X        lastclass = class;
  1046. X    }
  1047. X    regc('\0');
  1048. X    if (*regparse != ']')
  1049. X        FAIL("unmatched [] in regexp");
  1050. X    regparse++;
  1051. X    return ret;
  1052. X}
  1053. X#endif /* NOTDEF */
  1054. X
  1055. Xstatic char *
  1056. Xregchar(ch,flagp)
  1057. Xint ch;
  1058. Xint *flagp;
  1059. X{
  1060. X    char *ret;
  1061. X
  1062. X    ret = regnode(EXACTLY);
  1063. X    regc(1);
  1064. X    regc(ch);
  1065. X    regc('\0');
  1066. X    regparse++;
  1067. X    *flagp |= HASWIDTH|SIMPLE;
  1068. X    return ret;
  1069. X}
  1070. X
  1071. X/*
  1072. X - regnode - emit a node
  1073. X */
  1074. Xstatic char *            /* Location. */
  1075. Xregnode(op)
  1076. Xchar op;
  1077. X{
  1078. X    register char *ret;
  1079. X    register char *ptr;
  1080. X
  1081. X    ret = regcode;
  1082. X    if (ret == ®dummy) {
  1083. X#ifdef ALIGN
  1084. X        if (!(regsize & 1))
  1085. X            regsize++;
  1086. X#endif
  1087. X        regsize += 3;
  1088. X        return(ret);
  1089. X    }
  1090. X
  1091. X#ifdef ALIGN
  1092. X    if (!((long)ret & 1))
  1093. X        *ret++ = 127;
  1094. X#endif
  1095. X    ptr = ret;
  1096. X    *ptr++ = op;
  1097. X    *ptr++ = '\0';        /* Null "next" pointer. */
  1098. X    *ptr++ = '\0';
  1099. X    regcode = ptr;
  1100. X
  1101. X    return(ret);
  1102. X}
  1103. X
  1104. X/*
  1105. X - regc - emit (if appropriate) a byte of code
  1106. X */
  1107. Xstatic void
  1108. Xregc(b)
  1109. Xchar b;
  1110. X{
  1111. X    if (regcode != ®dummy)
  1112. X        *regcode++ = b;
  1113. X    else
  1114. X        regsize++;
  1115. X}
  1116. X
  1117. X/*
  1118. X - reginsert - insert an operator in front of already-emitted operand
  1119. X *
  1120. X * Means relocating the operand.
  1121. X */
  1122. Xstatic void
  1123. Xreginsert(op, opnd)
  1124. Xchar op;
  1125. Xchar *opnd;
  1126. X{
  1127. X    register char *src;
  1128. X    register char *dst;
  1129. X    register char *place;
  1130. X
  1131. X    if (regcode == ®dummy) {
  1132. X#ifdef ALIGN
  1133. X        regsize += 4;
  1134. X#else
  1135. X        regsize += 3;
  1136. X#endif
  1137. X        return;
  1138. X    }
  1139. X
  1140. X    src = regcode;
  1141. X#ifdef ALIGN
  1142. X    regcode += 4;
  1143. X#else
  1144. X    regcode += 3;
  1145. X#endif
  1146. X    dst = regcode;
  1147. X    while (src > opnd)
  1148. X        *--dst = *--src;
  1149. X
  1150. X    place = opnd;        /* Op node, where operand used to be. */
  1151. X    *place++ = op;
  1152. X    *place++ = '\0';
  1153. X    *place++ = '\0';
  1154. X}
  1155. X
  1156. X/*
  1157. X - regtail - set the next-pointer at the end of a node chain
  1158. X */
  1159. Xstatic void
  1160. Xregtail(p, val)
  1161. Xchar *p;
  1162. Xchar *val;
  1163. X{
  1164. X    register char *scan;
  1165. X    register char *temp;
  1166. X    register int offset;
  1167. X
  1168. X    if (p == ®dummy)
  1169. X        return;
  1170. X
  1171. X    /* Find last node. */
  1172. X    scan = p;
  1173. X    for (;;) {
  1174. X        temp = regnext(scan);
  1175. X        if (temp == NULL)
  1176. X            break;
  1177. X        scan = temp;
  1178. X    }
  1179. X
  1180. X#ifdef ALIGN
  1181. X    offset = val - scan;
  1182. X    *(short*)(scan+1) = offset;
  1183. X#else
  1184. X    if (OP(scan) == BACK)
  1185. X        offset = scan - val;
  1186. X    else
  1187. X        offset = val - scan;
  1188. X    *(scan+1) = (offset>>8)&0377;
  1189. X    *(scan+2) = offset&0377;
  1190. X#endif
  1191. X}
  1192. X
  1193. X/*
  1194. X - regoptail - regtail on operand of first argument; nop if operandless
  1195. X */
  1196. Xstatic void
  1197. Xregoptail(p, val)
  1198. Xchar *p;
  1199. Xchar *val;
  1200. X{
  1201. X    /* "Operandless" and "op != BRANCH" are synonymous in practice. */
  1202. X    if (p == NULL || p == ®dummy || OP(p) != BRANCH)
  1203. X        return;
  1204. X    regtail(NEXTOPER(p), val);
  1205. X}
  1206. X
  1207. X/*
  1208. X * regexec and friends
  1209. X */
  1210. X
  1211. X/*
  1212. X * Global work variables for regexec().
  1213. X */
  1214. Xstatic char *reginput;        /* String-input pointer. */
  1215. Xstatic char *regbol;        /* Beginning of input, for ^ check. */
  1216. Xstatic char **regstartp;    /* Pointer to startp array. */
  1217. Xstatic char **regendp;        /* Ditto for endp. */
  1218. Xstatic char *reglastparen;    /* Similarly for lastparen. */
  1219. Xstatic char *regtill;
  1220. X
  1221. Xstatic char *regmystartp[10];    /* For remembering backreferences. */
  1222. Xstatic char *regmyendp[10];
  1223. X
  1224. X/*
  1225. X * Forwards.
  1226. X */
  1227. XSTATIC int regtry();
  1228. XSTATIC int regmatch();
  1229. XSTATIC int regrepeat();
  1230. X
  1231. Xextern char sawampersand;
  1232. Xextern int multiline;
  1233. X
  1234. X/*
  1235. X - regexec - match a regexp against a string
  1236. X */
  1237. Xint
  1238. Xregexec(prog, stringarg, strend, beginning, minend, screamer)
  1239. Xregister regexp *prog;
  1240. Xchar *stringarg;
  1241. Xchar *strend;    /* pointer to null at end of string */
  1242. Xint beginning;    /* is ^ valid at the beginning of stringarg? */
  1243. Xint minend;    /* end of match must be at least minend after stringarg */
  1244. XSTR *screamer;
  1245. X{
  1246. X    register char *s;
  1247. X    extern char *index();
  1248. X    register int tmp, i;
  1249. X    register char *string = stringarg;
  1250. X    register char *c;
  1251. X    extern char *savestr();
  1252. X
  1253. X    /* Be paranoid... */
  1254. X    if (prog == NULL || string == NULL) {
  1255. X        fatal("NULL regexp parameter");
  1256. X        return(0);
  1257. X    }
  1258. X
  1259. X    regprecomp = prog->precomp;
  1260. X    /* Check validity of program. */
  1261. X    if (UCHARAT(prog->program) != MAGIC) {
  1262. X        FAIL("corrupted regexp program");
  1263. X    }
  1264. X
  1265. X    if (prog->do_folding) {
  1266. X        i = strend - string;
  1267. X        string = savestr(string);
  1268. X        strend = string + i;
  1269. X        for (s = string; *s; s++)
  1270. X            if (isupper(*s))
  1271. X                *s = tolower(*s);
  1272. X    }
  1273. X
  1274. X    /* If there is a "must appear" string, look for it. */
  1275. X    s = string;
  1276. X    if (prog->regmust != Nullstr) {
  1277. X        if (beginning && screamer) {
  1278. X            if (screamfirst[prog->regmust->str_rare] >= 0)
  1279. X                s = screaminstr(screamer,prog->regmust);
  1280. X            else
  1281. X                s = Nullch;
  1282. X        }
  1283. X        else
  1284. X            s = fbminstr(s,strend,prog->regmust);
  1285. X        if (!s) {
  1286. X            ++*(long*)&prog->regmust->str_nval;    /* hooray */
  1287. X            goto phooey;    /* not present */
  1288. X        }
  1289. X        else if (prog->regback >= 0) {
  1290. X            s -= prog->regback;
  1291. X            if (s < string)
  1292. X                s = string;
  1293. X        }
  1294. X        else if (--*(long*)&prog->regmust->str_nval < 0) { /* boo */
  1295. X            str_free(prog->regmust);
  1296. X            prog->regmust = Nullstr;    /* disable regmust */
  1297. X            s = string;
  1298. X        }
  1299. X        else
  1300. X            s = string;
  1301. X    }
  1302. X
  1303. X    /* Mark beginning of line for ^ . */
  1304. X    if (beginning)
  1305. X        regbol = string;
  1306. X    else
  1307. X        regbol = NULL;
  1308. X
  1309. X    /* see how far we have to get to not match where we matched before */
  1310. X    regtill = string+minend;
  1311. X
  1312. X    /* Simplest case:  anchored match need be tried only once. */
  1313. X    /*  [unless multiline is set] */
  1314. X    if (prog->reganch) {
  1315. X        if (regtry(prog, string))
  1316. X            goto got_it;
  1317. X        else if (multiline) {
  1318. X            /* for multiline we only have to try after newlines */
  1319. X            if (s > string)
  1320. X                s--;
  1321. X            while ((s = index(s, '\n')) != NULL) {
  1322. X                if (*++s && regtry(prog, s))
  1323. X                    goto got_it;
  1324. X            }
  1325. X        }
  1326. X        goto phooey;
  1327. X    }
  1328. X
  1329. X    /* Messy cases:  unanchored match. */
  1330. X    if (prog->regstart) {
  1331. X        /* We know what string it must start with. */
  1332. X        if (prog->regstart->str_pok == 3) {
  1333. X            while ((s = fbminstr(s, strend, prog->regstart)) != NULL) {
  1334. X                if (regtry(prog, s))
  1335. X                    goto got_it;
  1336. X                s++;
  1337. X            }
  1338. X        }
  1339. X        else {
  1340. X            c = prog->regstart->str_ptr;
  1341. X            while ((s = instr(s, c)) != NULL) {
  1342. X                if (regtry(prog, s))
  1343. X                    goto got_it;
  1344. X                s++;
  1345. X            }
  1346. X        }
  1347. X    }
  1348. X    else if (c = prog->regstclass) {
  1349. X        /* We know what class it must start with. */
  1350. X        switch (OP(c)) {
  1351. X        case ANYOF: case ANYBUT:
  1352. X            c = OPERAND(c);
  1353. X            while (i = *s) {
  1354. X                if (!(c[i >> 3] & (1 << (i&7))))
  1355. X                    if (regtry(prog, s))
  1356. X                        goto got_it;
  1357. X                s++;
  1358. X            }
  1359. X            break;
  1360. X        case BOUND:
  1361. X            tmp = 0;
  1362. X            while (i = *s) {
  1363. X                if (tmp != (isalpha(i) || isdigit(i) || i == '_')) {
  1364. X                    tmp = !tmp;
  1365. X                    if (regtry(prog, s))
  1366. X                        goto got_it;
  1367. X                }
  1368. X                s++;
  1369. X            }
  1370. X            if (tmp && regtry(prog,s))
  1371. X                goto got_it;
  1372. X            break;
  1373. X        case NBOUND:
  1374. X            tmp = 0;
  1375. X            while (i = *s) {
  1376. X                if (tmp != (isalpha(i) || isdigit(i) || i == '_'))
  1377. X                    tmp = !tmp;
  1378. X                else if (regtry(prog, s))
  1379. X                    goto got_it;
  1380. X                s++;
  1381. X            }
  1382. X            if (!tmp && regtry(prog,s))
  1383. X                goto got_it;
  1384. X            break;
  1385. X        case ALNUM:
  1386. X            while (i = *s) {
  1387. X                if (isalpha(i) || isdigit(i) || i == '_')
  1388. X                    if (regtry(prog, s))
  1389. X                        goto got_it;
  1390. X                s++;
  1391. X            }
  1392. X            break;
  1393. X        case NALNUM:
  1394. X            while (i = *s) {
  1395. X                if (!isalpha(i) && !isdigit(i) && i != '_')
  1396. X                    if (regtry(prog, s))
  1397. X                        goto got_it;
  1398. X                s++;
  1399. X            }
  1400. X            break;
  1401. X        case SPACE:
  1402. X            while (i = *s) {
  1403. X                if (isspace(i))
  1404. X                    if (regtry(prog, s))
  1405. X                        goto got_it;
  1406. X                s++;
  1407. X            }
  1408. X            break;
  1409. X        case NSPACE:
  1410. X            while (i = *s) {
  1411. X                if (!isspace(i))
  1412. X                    if (regtry(prog, s))
  1413. X                        goto got_it;
  1414. X                s++;
  1415. X            }
  1416. X            break;
  1417. X        case DIGIT:
  1418. X            while (i = *s) {
  1419. X                if (isdigit(i))
  1420. X                    if (regtry(prog, s))
  1421. X                        goto got_it;
  1422. X                s++;
  1423. X            }
  1424. X            break;
  1425. X        case NDIGIT:
  1426. X            while (i = *s) {
  1427. X                if (!isdigit(i))
  1428. X                    if (regtry(prog, s))
  1429. X                        goto got_it;
  1430. X                s++;
  1431. X            }
  1432. X            break;
  1433. X        }
  1434. X    }
  1435. X    else
  1436. X        /* We don't know much -- general case. */
  1437. X        do {
  1438. X            if (regtry(prog, s))
  1439. X                goto got_it;
  1440. X        } while (*s++ != '\0');
  1441. X
  1442. X    /* Failure. */
  1443. X    goto phooey;
  1444. X
  1445. X    got_it:
  1446. X    if (prog->nparens || sawampersand || prog->do_folding) {
  1447. X        s = savestr(stringarg);    /* so $digit will always work */
  1448. X        if (prog->subbase)
  1449. X            safefree(prog->subbase);
  1450. X        prog->subbase = s;
  1451. X        tmp = prog->subbase - string;
  1452. X        for (i = 0; i <= prog->nparens; i++) {
  1453. X            if (prog->endp[i]) {
  1454. X                prog->startp[i] += tmp;
  1455. X                prog->endp[i] += tmp;
  1456. X            }
  1457. X        }
  1458. X        if (prog->do_folding) {
  1459. X            safefree(string);
  1460. X        }
  1461. X    }
  1462. X    return(1);
  1463. X
  1464. X    phooey:
  1465. X    if (prog->do_folding) {
  1466. X        safefree(string);
  1467. X    }
  1468. X    return(0);
  1469. X}
  1470. X
  1471. X/*
  1472. X - regtry - try match at specific point
  1473. X */
  1474. Xstatic int            /* 0 failure, 1 success */
  1475. Xregtry(prog, string)
  1476. Xregexp *prog;
  1477. Xchar *string;
  1478. X{
  1479. X    register int i;
  1480. X    register char **sp;
  1481. X    register char **ep;
  1482. X
  1483. X    reginput = string;
  1484. X    regstartp = prog->startp;
  1485. X    regendp = prog->endp;
  1486. X    reglastparen = &prog->lastparen;
  1487. X
  1488. X    sp = prog->startp;
  1489. X    ep = prog->endp;
  1490. X    if (prog->nparens) {
  1491. X        for (i = NSUBEXP; i > 0; i--) {
  1492. X            *sp++ = NULL;
  1493. X            *ep++ = NULL;
  1494. X        }
  1495. X    }
  1496. X    if (regmatch(prog->program + 1) && reginput >= regtill) {
  1497. X        prog->startp[0] = string;
  1498. X        prog->endp[0] = reginput;
  1499. X        return(1);
  1500. X    } else
  1501. X        return(0);
  1502. X}
  1503. X
  1504. X/*
  1505. X - regmatch - main matching routine
  1506. X *
  1507. X * Conceptually the strategy is simple:  check to see whether the current
  1508. X * node matches, call self recursively to see whether the rest matches,
  1509. X * and then act accordingly.  In practice we make some effort to avoid
  1510. X * recursion, in particular by going through "ordinary" nodes (that don't
  1511. X * need to know whether the rest of the match failed) by a loop instead of
  1512. X * by recursion.
  1513. X */
  1514. X/* [lwall] I've hoisted the register declarations to the outer block in order to
  1515. X * maybe save a little bit of pushing and popping on the stack.  It also takes
  1516. X * advantage of machines that use a register save mask on subroutine entry.
  1517. X */
  1518. Xstatic int            /* 0 failure, 1 success */
  1519. Xregmatch(prog)
  1520. Xchar *prog;
  1521. X{
  1522. X    register char *scan;    /* Current node. */
  1523. X    char *next;        /* Next node. */
  1524. X    extern char *index();
  1525. X    register int nextchar;
  1526. X    register int n;        /* no or next */
  1527. X    register int ln;        /* len or last */
  1528. X    register char *s;    /* operand or save */
  1529. X    register char *locinput = reginput;
  1530. X
  1531. X    nextchar = *reginput;
  1532. X    scan = prog;
  1533. X#ifdef DEBUG
  1534. X    if (scan != NULL && regnarrate)
  1535. X        fprintf(stderr, "%s(\n", regprop(scan));
  1536. X#endif
  1537. X    while (scan != NULL) {
  1538. X#ifdef DEBUG
  1539. X        if (regnarrate)
  1540. X            fprintf(stderr, "%s...\n", regprop(scan));
  1541. X#endif
  1542. X
  1543. X#ifdef ALIGN
  1544. X        next = scan + NEXT(scan);
  1545. X        if (next == scan)
  1546. X            next = NULL;
  1547. X#else
  1548. X        next = regnext(scan);
  1549. X#endif
  1550. X
  1551. X        switch (OP(scan)) {
  1552. X        case BOL:
  1553. X            if (locinput == regbol ||
  1554. X                (nextchar && locinput[-1] == '\n') ) {
  1555. X                regtill--;
  1556. X                break;
  1557. X            }
  1558. X            return(0);
  1559. X        case EOL:
  1560. X            if (nextchar != '\0' && nextchar != '\n')
  1561. X                return(0);
  1562. X            regtill--;
  1563. X            break;
  1564. X        case ANY:
  1565. X            if (nextchar == '\0' || nextchar == '\n')
  1566. X                return(0);
  1567. X            nextchar = *++locinput;
  1568. X            break;
  1569. X        case EXACTLY:
  1570. X            s = OPERAND(scan);
  1571. X            ln = *s++;
  1572. X            /* Inline the first character, for speed. */
  1573. X            if (*s != nextchar)
  1574. X                return(0);
  1575. X            if (ln > 1 && strncmp(s, locinput, ln) != 0)
  1576. X                return(0);
  1577. X            locinput += ln;
  1578. X            nextchar = *locinput;
  1579. X            break;
  1580. X        case ANYOF:
  1581. X        case ANYBUT:
  1582. X            s = OPERAND(scan);
  1583. X            if (nextchar < 0)
  1584. X                nextchar = UCHARAT(locinput);
  1585. X            if (s[nextchar >> 3] & (1 << (nextchar&7)))
  1586. X                return(0);
  1587. X            nextchar = *++locinput;
  1588. X            break;
  1589. X#ifdef NOTDEF
  1590. X        case ANYOF:
  1591. X             if (nextchar == '\0' || index(OPERAND(scan), nextchar) == NULL)
  1592. X                return(0);
  1593. X            nextchar = *++locinput;
  1594. X            break;
  1595. X        case ANYBUT:
  1596. X             if (nextchar == '\0' || index(OPERAND(scan), nextchar) != NULL)
  1597. X                return(0);
  1598. X            nextchar = *++locinput;
  1599. X            break;
  1600. X#endif
  1601. X        case ALNUM:
  1602. X            if (!nextchar)
  1603. X                return(0);
  1604. X            if (!isalpha(nextchar) && !isdigit(nextchar) &&
  1605. X              nextchar != '_')
  1606. X                return(0);
  1607. X            nextchar = *++locinput;
  1608. X            break;
  1609. X        case NALNUM:
  1610. X            if (!nextchar)
  1611. X                return(0);
  1612. X            if (isalpha(nextchar) || isdigit(nextchar) ||
  1613. X              nextchar == '_')
  1614. X                return(0);
  1615. X            nextchar = *++locinput;
  1616. X            break;
  1617. X        case NBOUND:
  1618. X        case BOUND:
  1619. X            if (locinput == regbol)    /* was last char in word? */
  1620. X                ln = 0;
  1621. X            else 
  1622. X                ln = (isalpha(locinput[-1]) ||
  1623. X                     isdigit(locinput[-1]) ||
  1624. X                     locinput[-1] == '_' );
  1625. X            n = (isalpha(nextchar) || isdigit(nextchar) ||
  1626. X                nextchar == '_' );    /* is next char in word? */
  1627. X            if ((ln == n) == (OP(scan) == BOUND))
  1628. X                return(0);
  1629. X            break;
  1630. X        case SPACE:
  1631. X            if (!nextchar)
  1632. X                return(0);
  1633. X            if (!isspace(nextchar))
  1634. X                return(0);
  1635. X            nextchar = *++locinput;
  1636. X            break;
  1637. X        case NSPACE:
  1638. X            if (!nextchar)
  1639. X                return(0);
  1640. X            if (isspace(nextchar))
  1641. X                return(0);
  1642. X            nextchar = *++locinput;
  1643. X            break;
  1644. X        case DIGIT:
  1645. X            if (!isdigit(nextchar))
  1646. X                return(0);
  1647. X            nextchar = *++locinput;
  1648. X            break;
  1649. X        case NDIGIT:
  1650. X            if (!nextchar)
  1651. X                return(0);
  1652. X            if (isdigit(nextchar))
  1653. X                return(0);
  1654. X            nextchar = *++locinput;
  1655. X            break;
  1656. X        case REF:
  1657. X        case REF+1:
  1658. X        case REF+2:
  1659. X        case REF+3:
  1660. X        case REF+4:
  1661. X        case REF+5:
  1662. X        case REF+6:
  1663. X        case REF+7:
  1664. X        case REF+8:
  1665. X        case REF+9:
  1666. X            n = OP(scan) - REF;
  1667. X            s = regmystartp[n];
  1668. X            if (!s)
  1669. X                return(0);
  1670. X            if (!regmyendp[n])
  1671. X                return(0);
  1672. X            if (s == regmyendp[n])
  1673. X                break;
  1674. X            /* Inline the first character, for speed. */
  1675. X            if (*s != nextchar)
  1676. X                return(0);
  1677. X            ln = regmyendp[n] - s;
  1678. X            if (ln > 1 && strncmp(s, locinput, ln) != 0)
  1679. X                return(0);
  1680. X            locinput += ln;
  1681. X            nextchar = *locinput;
  1682. X            break;
  1683. X
  1684. X        case NOTHING:
  1685. X            break;
  1686. X        case BACK:
  1687. X            break;
  1688. X        case OPEN+1:
  1689. X        case OPEN+2:
  1690. X        case OPEN+3:
  1691. X        case OPEN+4:
  1692. X        case OPEN+5:
  1693. X        case OPEN+6:
  1694. X        case OPEN+7:
  1695. X        case OPEN+8:
  1696. X        case OPEN+9:
  1697. X            n = OP(scan) - OPEN;
  1698. X            reginput = locinput;
  1699. X
  1700. X            regmystartp[n] = locinput;    /* for REF */
  1701. X            if (regmatch(next)) {
  1702. X                /*
  1703. X                 * Don't set startp if some later
  1704. X                 * invocation of the same parentheses
  1705. X                 * already has.
  1706. X                 */
  1707. X                if (regstartp[n] == NULL)
  1708. X                    regstartp[n] = locinput;
  1709. X                return(1);
  1710. X            } else
  1711. X                return(0);
  1712. X            /* NOTREACHED */
  1713. X        case CLOSE+1:
  1714. X        case CLOSE+2:
  1715. X        case CLOSE+3:
  1716. X        case CLOSE+4:
  1717. X        case CLOSE+5:
  1718. X        case CLOSE+6:
  1719. X        case CLOSE+7:
  1720. X        case CLOSE+8:
  1721. X        case CLOSE+9: {
  1722. X                n = OP(scan) - CLOSE;
  1723. X                reginput = locinput;
  1724. X
  1725. X                regmyendp[n] = locinput;    /* for REF */
  1726. X                if (regmatch(next)) {
  1727. X                    /*
  1728. X                     * Don't set endp if some later
  1729. X                     * invocation of the same parentheses
  1730. X                     * already has.
  1731. X                     */
  1732. X                    if (regendp[n] == NULL) {
  1733. X                        regendp[n] = locinput;
  1734. X                        *reglastparen = n;
  1735. X                    }
  1736. X                    return(1);
  1737. X                } else
  1738. X                    return(0);
  1739. X            }
  1740. X            break;
  1741. X        case BRANCH: {
  1742. X                if (OP(next) != BRANCH)        /* No choice. */
  1743. X                    next = NEXTOPER(scan);    /* Avoid recursion. */
  1744. X                else {
  1745. X                    do {
  1746. X                        reginput = locinput;
  1747. X                        if (regmatch(NEXTOPER(scan)))
  1748. X                            return(1);
  1749. X#ifdef ALIGN
  1750. X                        if (n = NEXT(scan))
  1751. X                            scan += n;
  1752. X                        else
  1753. X                            scan = NULL;
  1754. X#else
  1755. X                        scan = regnext(scan);
  1756. X#endif
  1757. X                    } while (scan != NULL && OP(scan) == BRANCH);
  1758. X                    return(0);
  1759. X                    /* NOTREACHED */
  1760. X                }
  1761. X            }
  1762. X            break;
  1763. X        case STAR:
  1764. X        case PLUS:
  1765. X            /*
  1766. X             * Lookahead to avoid useless match attempts
  1767. X             * when we know what character comes next.
  1768. X             */
  1769. X            if (OP(next) == EXACTLY)
  1770. X                nextchar = *(OPERAND(next)+1);
  1771. X            else
  1772. X                nextchar = '\0';
  1773. X            ln = (OP(scan) == STAR) ? 0 : 1;
  1774. X            reginput = locinput;
  1775. X            n = regrepeat(NEXTOPER(scan));
  1776. X            while (n >= ln) {
  1777. X                /* If it could work, try it. */
  1778. X                if (nextchar == '\0' || *reginput == nextchar)
  1779. X                    if (regmatch(next))
  1780. X                        return(1);
  1781. X                /* Couldn't or didn't -- back up. */
  1782. X                n--;
  1783. X                reginput = locinput + n;
  1784. X            }
  1785. X            return(0);
  1786. X        case END:
  1787. X            reginput = locinput; /* put where regtry can find it */
  1788. X            return(1);    /* Success! */
  1789. X        default:
  1790. X            printf("%x %d\n",scan,scan[1]);
  1791. X            FAIL("regexp memory corruption");
  1792. X        }
  1793. X
  1794. X        scan = next;
  1795. X    }
  1796. X
  1797. X    /*
  1798. X     * We get here only if there's trouble -- normally "case END" is
  1799. X     * the terminating point.
  1800. X     */
  1801. X    FAIL("corrupted regexp pointers");
  1802. X    /*NOTREACHED*/
  1803. X}
  1804. X
  1805. X/*
  1806. X - regrepeat - repeatedly match something simple, report how many
  1807. X */
  1808. X/*
  1809. X * [This routine now assumes that it will only match on things of length 1.
  1810. X * That was true before, but now we assume scan - reginput is the count,
  1811. X * rather than incrementing count on every character.]
  1812. X */
  1813. Xstatic int
  1814. Xregrepeat(p)
  1815. Xchar *p;
  1816. X{
  1817. X    register char *scan;
  1818. X    register char *opnd;
  1819. X    register int c;
  1820. X
  1821. X    scan = reginput;
  1822. X    opnd = OPERAND(p);
  1823. X    switch (OP(p)) {
  1824. X    case ANY:
  1825. X        while (*scan && *scan != '\n')
  1826. X            scan++;
  1827. X        break;
  1828. X    case EXACTLY:        /* length of string is 1 */
  1829. X        opnd++;
  1830. X        while (*opnd == *scan)
  1831. X            scan++;
  1832. X        break;
  1833. X#ifdef FASTANY
  1834. X    case ANYOF:
  1835. X    case ANYBUT:
  1836. X        c = UCHARAT(scan);
  1837. X        while (!(opnd[c >> 3] & (1 << (c & 7)))) {
  1838. X            scan++;
  1839. X            c = UCHARAT(scan);
  1840. X        }
  1841. X        break;
  1842. X#else
  1843. X    case ANYOF:
  1844. X        while (*scan != '\0' && index(opnd, *scan) != NULL)
  1845. X            scan++;
  1846. X        break;
  1847. X    case ANYBUT:
  1848. X        while (*scan != '\0' && index(opnd, *scan) == NULL)
  1849. X            scan++;
  1850. X        break;
  1851. X#endif /* FASTANY */
  1852. X    case ALNUM:
  1853. X        while (*scan && (isalpha(*scan) || isdigit(*scan) ||
  1854. X          *scan == '_'))
  1855. X            scan++;
  1856. X        break;
  1857. X    case NALNUM:
  1858. X        while (*scan && (!isalpha(*scan) && !isdigit(*scan) &&
  1859. X          *scan != '_'))
  1860. X            scan++;
  1861. X        break;
  1862. X    case SPACE:
  1863. X        while (*scan && isspace(*scan))
  1864. X            scan++;
  1865. X        break;
  1866. X    case NSPACE:
  1867. X        while (*scan && !isspace(*scan))
  1868. X            scan++;
  1869. X        break;
  1870. X    case DIGIT:
  1871. X        while (*scan && isdigit(*scan))
  1872. X            scan++;
  1873. X        break;
  1874. X    case NDIGIT:
  1875. X        while (*scan && !isdigit(*scan))
  1876. X            scan++;
  1877. X        break;
  1878. X    default:        /* Oh dear.  Called inappropriately. */
  1879. X        FAIL("internal regexp foulup");
  1880. X        /* NOTREACHED */
  1881. X    }
  1882. X
  1883. X    c = scan - reginput;
  1884. X    reginput = scan;
  1885. X
  1886. X    return(c);
  1887. X}
  1888. X
  1889. X/*
  1890. X - regnext - dig the "next" pointer out of a node
  1891. X *
  1892. X * [Note, when ALIGN is defined there are two places in regmatch() that bypass
  1893. X * this code for speed.]
  1894. X */
  1895. Xstatic char *
  1896. Xregnext(p)
  1897. Xregister char *p;
  1898. X{
  1899. X    register int offset;
  1900. X
  1901. X    if (p == ®dummy)
  1902. X        return(NULL);
  1903. X
  1904. X    offset = NEXT(p);
  1905. X    if (offset == 0)
  1906. X        return(NULL);
  1907. X
  1908. X#ifdef ALIGN
  1909. X    return(p+offset);
  1910. X#else
  1911. X    if (OP(p) == BACK)
  1912. X        return(p-offset);
  1913. X    else
  1914. X        return(p+offset);
  1915. X#endif
  1916. X}
  1917. X
  1918. X#ifdef DEBUG
  1919. X
  1920. XSTATIC char *regprop();
  1921. X
  1922. X/*
  1923. X - regdump - dump a regexp onto stdout in vaguely comprehensible form
  1924. X */
  1925. Xvoid
  1926. Xregdump(r)
  1927. Xregexp *r;
  1928. X{
  1929. X    register char *s;
  1930. X    register char op = EXACTLY;    /* Arbitrary non-END op. */
  1931. X    register char *next;
  1932. X    extern char *index();
  1933. X
  1934. X
  1935. X    s = r->program + 1;
  1936. X    while (op != END) {    /* While that wasn't END last time... */
  1937. X#ifdef ALIGN
  1938. X        if (!((long)s & 1))
  1939. X            s++;
  1940. X#endif
  1941. X        op = OP(s);
  1942. X        printf("%2d%s", s-r->program, regprop(s));    /* Where, what. */
  1943. X        next = regnext(s);
  1944. X        if (next == NULL)        /* Next ptr. */
  1945. X            printf("(0)");
  1946. X        else 
  1947. X            printf("(%d)", (s-r->program)+(next-s));
  1948. X        s += 3;
  1949. X        if (op == ANYOF || op == ANYBUT) {
  1950. X            s += 32;
  1951. X        }
  1952. X        if (op == EXACTLY) {
  1953. X            /* Literal string, where present. */
  1954. X            s++;
  1955. X            while (*s != '\0') {
  1956. X                putchar(*s);
  1957. X                s++;
  1958. X            }
  1959. X            s++;
  1960. X        }
  1961. X        putchar('\n');
  1962. X    }
  1963. X
  1964. X    /* Header fields of interest. */
  1965. X    if (r->regstart)
  1966. X        printf("start `%s' ", r->regstart->str_ptr);
  1967. X    if (r->regstclass)
  1968. X        printf("stclass `%s' ", regprop(OP(r->regstclass)));
  1969. X    if (r->reganch)
  1970. X        printf("anchored ");
  1971. X    if (r->regmust != NULL)
  1972. X        printf("must have \"%s\" back %d ", r->regmust->str_ptr,
  1973. X          r->regback);
  1974. X    printf("\n");
  1975. X}
  1976. X
  1977. X/*
  1978. X - regprop - printable representation of opcode
  1979. X */
  1980. Xstatic char *
  1981. Xregprop(op)
  1982. Xchar *op;
  1983. X{
  1984. X    register char *p;
  1985. X    static char buf[50];
  1986. X
  1987. X    (void) strcpy(buf, ":");
  1988. X
  1989. X    switch (OP(op)) {
  1990. X    case BOL:
  1991. X        p = "BOL";
  1992. X        break;
  1993. X    case EOL:
  1994. X        p = "EOL";
  1995. X        break;
  1996. X    case ANY:
  1997. X        p = "ANY";
  1998. X        break;
  1999. X    case ANYOF:
  2000. X        p = "ANYOF";
  2001. X        break;
  2002. X    case ANYBUT:
  2003. X        p = "ANYBUT";
  2004. X        break;
  2005. X    case BRANCH:
  2006. X        p = "BRANCH";
  2007. X        break;
  2008. X    case EXACTLY:
  2009. X        p = "EXACTLY";
  2010. X        break;
  2011. X    case NOTHING:
  2012. X        p = "NOTHING";
  2013. X        break;
  2014. X    case BACK:
  2015. X        p = "BACK";
  2016. X        break;
  2017. X    case END:
  2018. X        p = "END";
  2019. X        break;
  2020. X    case ALNUM:
  2021. X        p = "ALNUM";
  2022. X        break;
  2023. X    case NALNUM:
  2024. X        p = "NALNUM";
  2025. X        break;
  2026. X    case BOUND:
  2027. X        p = "BOUND";
  2028. X        break;
  2029. X    case NBOUND:
  2030. X        p = "NBOUND";
  2031. X        break;
  2032. X    case SPACE:
  2033. X        p = "SPACE";
  2034. X        break;
  2035. X    case NSPACE:
  2036. X        p = "NSPACE";
  2037. X        break;
  2038. X    case DIGIT:
  2039. X        p = "DIGIT";
  2040. X        break;
  2041. X    case NDIGIT:
  2042. X        p = "NDIGIT";
  2043. X        break;
  2044. X    case REF:
  2045. X    case REF+1:
  2046. X    case REF+2:
  2047. X    case REF+3:
  2048. X    case REF+4:
  2049. X    case REF+5:
  2050. X    case REF+6:
  2051. X    case REF+7:
  2052. X    case REF+8:
  2053. X    case REF+9:
  2054. X        sprintf(buf+strlen(buf), "REF%d", OP(op)-REF);
  2055. X        p = NULL;
  2056. X        break;
  2057. X    case OPEN+1:
  2058. X    case OPEN+2:
  2059. X    case OPEN+3:
  2060. X    case OPEN+4:
  2061. X    case OPEN+5:
  2062. X    case OPEN+6:
  2063. X    case OPEN+7:
  2064. X    case OPEN+8:
  2065. X    case OPEN+9:
  2066. X        sprintf(buf+strlen(buf), "OPEN%d", OP(op)-OPEN);
  2067. X        p = NULL;
  2068. X        break;
  2069. X    case CLOSE+1:
  2070. X    case CLOSE+2:
  2071. X    case CLOSE+3:
  2072. X    case CLOSE+4:
  2073. X    case CLOSE+5:
  2074. X    case CLOSE+6:
  2075. X    case CLOSE+7:
  2076. X    case CLOSE+8:
  2077. X    case CLOSE+9:
  2078. X        sprintf(buf+strlen(buf), "CLOSE%d", OP(op)-CLOSE);
  2079. X        p = NULL;
  2080. X        break;
  2081. X    case STAR:
  2082. X        p = "STAR";
  2083. X        break;
  2084. X    case PLUS:
  2085. X        p = "PLUS";
  2086. X        break;
  2087. X    default:
  2088. X        FAIL("corrupted regexp opcode");
  2089. X    }
  2090. X    if (p != NULL)
  2091. X        (void) strcat(buf, p);
  2092. X    return(buf);
  2093. X}
  2094. X#endif
  2095. X
  2096. X#ifdef NOTDEF
  2097. X/*
  2098. X * The following is provided for those people who do not have strcspn() in
  2099. X * their C libraries.  They should get off their butts and do something
  2100. X * about it; at least one public-domain implementation of those (highly
  2101. X * useful) string routines has been published on Usenet.
  2102. X */
  2103. X#ifndef STRCSPN
  2104. X/*
  2105. X * strcspn - find length of initial segment of s1 consisting entirely
  2106. X * of characters not from s2
  2107. X */
  2108. X
  2109. Xstatic int
  2110. Xstrcspn(s1, s2)
  2111. Xchar *s1;
  2112. Xchar *s2;
  2113. X{
  2114. X    register char *scan1;
  2115. X    register char *scan2;
  2116. X    register int count;
  2117. X
  2118. X    count = 0;
  2119. X    for (scan1 = s1; *scan1 != '\0'; scan1++) {
  2120. X        for (scan2 = s2; *scan2 != '\0';)    /* ++ moved down. */
  2121. X            if (*scan1 == *scan2++)
  2122. X                return(count);
  2123. X        count++;
  2124. X    }
  2125. X    return(count);
  2126. X}
  2127. X#endif
  2128. X#endif /* NOTDEF */
  2129. X
  2130. Xregfree(r)
  2131. Xstruct regexp *r;
  2132. X{
  2133. X    if (r->precomp)
  2134. X        safefree(r->precomp);
  2135. X    if (r->subbase)
  2136. X        safefree(r->subbase);
  2137. X    if (r->regmust)
  2138. X        str_free(r->regmust);
  2139. X    if (r->regstart)
  2140. X        str_free(r->regstart);
  2141. X    safefree((char*)r);
  2142. X}
  2143. !STUFFY!FUNK!
  2144. echo ""
  2145. echo "End of kit 2 (of 15)"
  2146. cat /dev/null >kit2isdone
  2147. run=''
  2148. config=''
  2149. for iskit in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15; do
  2150.     if test -f kit${iskit}isdone; then
  2151.     run="$run $iskit"
  2152.     else
  2153.     todo="$todo $iskit"
  2154.     fi
  2155. done
  2156. case $todo in
  2157.     '')
  2158.     echo "You have run all your kits.  Please read README and then type Configure."
  2159.     chmod 755 Configure
  2160.     ;;
  2161.     *)  echo "You have run$run."
  2162.     echo "You still need to run$todo."
  2163.     ;;
  2164. esac
  2165. : Someone might mail this, so...
  2166. exit
  2167.  
  2168.