home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume41 / vim / part19 < prev    next >
Text File  |  1993-12-21  |  43KB  |  1,718 lines

  1. Newsgroups: comp.sources.misc
  2. From: mool@oce.nl (Bram Moolenaar)
  3. Subject: v41i069:  vim - Vi IMitation editor, v2.0, Part19/25
  4. Message-ID: <1993Dec21.172738.1928@sparky.sterling.com>
  5. X-Md4-Signature: 66c56722b5170bd257ffccdeb729778c
  6. Keywords: utility, editor, vi, vim
  7. Sender: kent@sparky.sterling.com (Kent Landfield)
  8. Organization: Sterling Software
  9. Date: Tue, 21 Dec 1993 17:27:38 GMT
  10. Approved: kent@sparky.sterling.com
  11.  
  12. Submitted-by: mool@oce.nl (Bram Moolenaar)
  13. Posting-number: Volume 41, Issue 69
  14. Archive-name: vim/part19
  15. Environment: UNIX, AMIGA, MS-DOS
  16. Supersedes: vim: Volume 37, Issue 1-24
  17.  
  18. #! /bin/sh
  19. # This is a shell archive.  Remove anything before this line, then unpack
  20. # it by saving it into a file and typing "sh file".  To overwrite existing
  21. # files, type "sh file -c".  You can also feed this as standard input via
  22. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  23. # will see the following message at the end:
  24. #        "End of archive 19 (of 25)."
  25. # Contents:  vim/src/regexp.c
  26. # Wrapped by mool@oce-rd2 on Wed Dec 15 09:50:08 1993
  27. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  28. if test -f 'vim/src/regexp.c' -a "${1}" != "-c" ; then 
  29.   echo shar: Will not clobber existing file \"'vim/src/regexp.c'\"
  30. else
  31. echo shar: Extracting \"'vim/src/regexp.c'\" \(38964 characters\)
  32. sed "s/^X//" >'vim/src/regexp.c' <<'END_OF_FILE'
  33. X/* vi:ts=4:sw=4
  34. X * NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
  35. X *
  36. X * This is NOT the original regular expression code as written by
  37. X * Henry Spencer. This code has been modified specifically for use
  38. X * with the VIM editor, and should not be used apart from compiling
  39. X * VIM. If you want a good regular expression library, get the
  40. X * original code. The copyright notice that follows is from the
  41. X * original.
  42. X *
  43. X * NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
  44. X *
  45. X *
  46. X * regcomp and regexec -- regsub and regerror are elsewhere
  47. X *
  48. X *        Copyright (c) 1986 by University of Toronto.
  49. X *        Written by Henry Spencer.  Not derived from licensed software.
  50. X *
  51. X *        Permission is granted to anyone to use this software for any
  52. X *        purpose on any computer system, and to redistribute it freely,
  53. X *        subject to the following restrictions:
  54. X *
  55. X *        1. The author is not responsible for the consequences of use of
  56. X *                this software, no matter how awful, even if they arise
  57. X *                from defects in it.
  58. X *
  59. X *        2. The origin of this software must not be misrepresented, either
  60. X *                by explicit claim or by omission.
  61. X *
  62. X *        3. Altered versions must be plainly marked as such, and must not
  63. X *                be misrepresented as being the original software.
  64. X *
  65. X * Beware that some of this code is subtly aware of the way operator
  66. X * precedence is structured in regular expressions.  Serious changes in
  67. X * regular-expression syntax might require a total rethink.
  68. X *
  69. X * $Log:        regexp.c,v $
  70. X * Revision 1.2  88/04/28  08:09:45  tony
  71. X * First modification of the regexp library. Added an external variable
  72. X * 'reg_ic' which can be set to indicate that case should be ignored.
  73. X * Added a new parameter to regexec() to indicate that the given string
  74. X * comes from the beginning of a line and is thus eligible to match
  75. X * 'beginning-of-line'.
  76. X *
  77. X * Revisions by Olaf 'Rhialto' Seibert, rhialto@cs.kun.nl:
  78. X * Changes for vi: (the semantics of several things were rather different)
  79. X * - Added lexical analyzer, because in vi magicness of characters
  80. X *   is rather difficult, and may change over time.
  81. X * - Added support for \< \> \1-\9 and ~
  82. X * - Left some magic stuff in, but only backslashed: \| \+
  83. X * - * and \+ still work after \) even though they shouldn't.
  84. X */
  85. X#include "vim.h"
  86. X#include "globals.h"
  87. X#include "proto.h"
  88. X#undef DEBUG
  89. X
  90. X#include <stdio.h>
  91. X#include "regexp.h"
  92. X#include "regmagic.h"
  93. X
  94. X/*
  95. X * The "internal use only" fields in regexp.h are present to pass info from
  96. X * compile to execute that permits the execute phase to run lots faster on
  97. X * simple cases.  They are:
  98. X *
  99. X * regstart     char that must begin a match; '\0' if none obvious
  100. X * reganch        is the match anchored (at beginning-of-line only)?
  101. X * regmust        string (pointer into program) that match must include, or NULL
  102. X * regmlen        length of regmust string
  103. X *
  104. X * Regstart and reganch permit very fast decisions on suitable starting points
  105. X * for a match, cutting down the work a lot.  Regmust permits fast rejection
  106. X * of lines that cannot possibly match.  The regmust tests are costly enough
  107. X * that regcomp() supplies a regmust only if the r.e. contains something
  108. X * potentially expensive (at present, the only such thing detected is * or +
  109. X * at the start of the r.e., which can involve a lot of backup).  Regmlen is
  110. X * supplied because the test in regexec() needs it and regcomp() is computing
  111. X * it anyway.
  112. X */
  113. X
  114. X/*
  115. X * Structure for regexp "program".    This is essentially a linear encoding
  116. X * of a nondeterministic finite-state machine (aka syntax charts or
  117. X * "railroad normal form" in parsing technology).  Each node is an opcode
  118. X * plus a "next" pointer, possibly plus an operand.  "Next" pointers of
  119. X * all nodes except BRANCH implement concatenation; a "next" pointer with
  120. X * a BRANCH on both ends of it is connecting two alternatives.    (Here we
  121. X * have one of the subtle syntax dependencies:    an individual BRANCH (as
  122. X * opposed to a collection of them) is never concatenated with anything
  123. X * because of operator precedence.)  The operand of some types of node is
  124. X * a literal string; for others, it is a node leading into a sub-FSM.  In
  125. X * particular, the operand of a BRANCH node is the first node of the branch.
  126. X * (NB this is *not* a tree structure:    the tail of the branch connects
  127. X * to the thing following the set of BRANCHes.)  The opcodes are:
  128. X */
  129. X
  130. X/* definition    number               opnd?    meaning */
  131. X#define END     0                /* no    End of program. */
  132. X#define BOL     1                /* no    Match "" at beginning of line. */
  133. X#define EOL     2                /* no    Match "" at end of line. */
  134. X#define ANY     3                /* no    Match any one character. */
  135. X#define ANYOF    4                /* str    Match any character in this string. */
  136. X#define ANYBUT    5                /* str    Match any character not in this
  137. X                                 *        string. */
  138. X#define BRANCH    6                /* node Match this alternative, or the
  139. X                                 *        next... */
  140. X#define BACK    7                /* no    Match "", "next" ptr points backward. */
  141. X#define EXACTLY 8                /* str    Match this string. */
  142. X#define NOTHING 9                /* no    Match empty string. */
  143. X#define STAR    10                /* node Match this (simple) thing 0 or more
  144. X                                 *        times. */
  145. X#define PLUS    11                /* node Match this (simple) thing 1 or more
  146. X                                 *        times. */
  147. X#define BOW        12                /* no    Match "" after [^a-zA-Z0-9_] */
  148. X#define EOW        13                /* no    Match "" at    [^a-zA-Z0-9_] */
  149. X#define MOPEN    20                /* no    Mark this point in input as start of
  150. X                                 *        #n. */
  151. X /* MOPEN+1 is number 1, etc. */
  152. X#define MCLOSE    30                /* no    Analogous to MOPEN. */
  153. X#define BACKREF    40                /* node Match same string again \1-\9 */
  154. X
  155. X#define Magic(x)    ((x)|('\\'<<8))
  156. X
  157. X/*
  158. X * Opcode notes:
  159. X *
  160. X * BRANCH        The set of branches constituting a single choice are hooked
  161. X *                together with their "next" pointers, since precedence prevents
  162. X *                anything being concatenated to any individual branch.  The
  163. X *                "next" pointer of the last BRANCH in a choice points to the
  164. X *                thing following the whole choice.  This is also where the
  165. X *                final "next" pointer of each individual branch points; each
  166. X *                branch starts with the operand node of a BRANCH node.
  167. X *
  168. X * BACK         Normal "next" pointers all implicitly point forward; BACK
  169. X *                exists to make loop structures possible.
  170. X *
  171. X * STAR,PLUS    '?', and complex '*' and '+', are implemented as circular
  172. X *                BRANCH structures using BACK.  Simple cases (one character
  173. X *                per match) are implemented with STAR and PLUS for speed
  174. X *                and to minimize recursive plunges.
  175. X *
  176. X * MOPEN,MCLOSE    ...are numbered at compile time.
  177. X */
  178. X
  179. X/*
  180. X * A node is one char of opcode followed by two chars of "next" pointer.
  181. X * "Next" pointers are stored as two 8-bit pieces, high order first.  The
  182. X * value is a positive offset from the opcode of the node containing it.
  183. X * An operand, if any, simply follows the node.  (Note that much of the
  184. X * code generation knows about this implicit relationship.)
  185. X *
  186. X * Using two bytes for the "next" pointer is vast overkill for most things,
  187. X * but allows patterns to get big without disasters.
  188. X */
  189. X#define OP(p)    (*(p))
  190. X#define NEXT(p) (((*((p)+1)&0377)<<8) + (*((p)+2)&0377))
  191. X#define OPERAND(p)        ((p) + 3)
  192. X
  193. X/*
  194. X * See regmagic.h for one further detail of program structure.
  195. X */
  196. X
  197. X
  198. X/*
  199. X * Utility definitions.
  200. X */
  201. X#ifndef CHARBITS
  202. X#define UCHARAT(p)        ((int)*(unsigned char *)(p))
  203. X#else
  204. X#define UCHARAT(p)        ((int)*(p)&CHARBITS)
  205. X#endif
  206. X
  207. X#define FAIL(m) { emsg(m); return NULL; }
  208. X
  209. Xstatic int ismult __ARGS((int));
  210. X
  211. X    static int
  212. Xismult(c)
  213. X    int c;
  214. X{
  215. X    return (c == Magic('*') || c == Magic('+') || c == Magic('?'));
  216. X}
  217. X
  218. X/*
  219. X * Flags to be passed up and down.
  220. X */
  221. X#define HASWIDTH        01        /* Known never to match null string. */
  222. X#define SIMPLE            02        /* Simple enough to be STAR/PLUS operand. */
  223. X#define SPSTART         04        /* Starts with * or +. */
  224. X#define WORST            0        /* Worst case. */
  225. X
  226. X/*
  227. X * The following supports the ability to ignore case in searches.
  228. X */
  229. X
  230. Xint             reg_ic = 0;     /* set by callers to ignore case */
  231. X
  232. X/*
  233. X * mkup - convert to upper case IF we're doing caseless compares
  234. X */
  235. X#define mkup(c)         (reg_ic ? TO_UPPER(c) : (c))
  236. X
  237. X/*
  238. X * The following allows empty REs, meaning "the same as the previous RE".
  239. X * per the ed(1) manual.
  240. X */
  241. X/* #define EMPTY_RE */            /* this is done outside of regexp */
  242. X#ifdef EMTY_RE
  243. Xchar           *reg_prev_re;
  244. X#endif
  245. X
  246. X#define TILDE
  247. X#ifdef TILDE
  248. Xchar           *reg_prev_sub;
  249. X#endif
  250. X
  251. X/*
  252. X * This if for vi's "magic" mode. If magic is false, only ^$\ are magic.
  253. X */
  254. X
  255. Xint                reg_magic = 1;
  256. X
  257. X/*
  258. X * Global work variables for regcomp().
  259. X */
  260. X
  261. Xstatic unsigned char    *regparse;    /* Input-scan pointer. */
  262. Xstatic int        regnpar;        /* () count. */
  263. Xstatic char     regdummy;
  264. Xstatic char    *regcode;        /* Code-emit pointer; ®dummy = don't. */
  265. Xstatic long     regsize;        /* Code size. */
  266. Xstatic char   **regendp;        /* Ditto for endp. */
  267. X
  268. X/*
  269. X * META contains all characters that may be magic, except '^' and '$'.
  270. X * This depends on the configuration options TILDE, BACKREF.
  271. X * (could be done simpler for compilers that know string concatenation)
  272. X */
  273. X
  274. X#ifdef TILDE
  275. X# ifdef BACKREF
  276. X       static char META[] = ".[()|?+*<>~123456789";
  277. X# else
  278. X       static char META[] = ".[()|?+*<>~";
  279. X# endif
  280. X#else
  281. X# ifdef BACKREF
  282. X       static char META[] = ".[()|?+*<>123456789";
  283. X# else
  284. X       static char META[] = ".[()|?+*<>";
  285. X# endif
  286. X#endif
  287. X
  288. X/*
  289. X * Forward declarations for regcomp()'s friends.
  290. X */
  291. Xstatic void        initchr __ARGS((unsigned char *));
  292. Xstatic int        getchr __ARGS((void));
  293. Xstatic int        peekchr __ARGS((void));
  294. X#define PeekChr() curchr    /* shortcut only when last action was peekchr() */
  295. Xstatic int         curchr;
  296. Xstatic void        skipchr __ARGS((void));
  297. Xstatic void        ungetchr __ARGS((void));
  298. Xstatic char    *reg __ARGS((int, int *));
  299. Xstatic char    *regbranch __ARGS((int *));
  300. Xstatic char    *regpiece __ARGS((int *));
  301. Xstatic char    *regatom __ARGS((int *));
  302. Xstatic char    *regnode __ARGS((int));
  303. Xstatic char    *regnext __ARGS((char *));
  304. Xstatic void     regc __ARGS((int));
  305. Xstatic void     unregc __ARGS((void));
  306. Xstatic void     reginsert __ARGS((int, char *));
  307. Xstatic void     regtail __ARGS((char *, char *));
  308. Xstatic void     regoptail __ARGS((char *, char *));
  309. X
  310. X#undef STRCSPN
  311. X#ifdef STRCSPN
  312. Xstatic int        strcspn __ARGS((const char *, const char *));
  313. X#endif
  314. Xstatic int        cstrncmp __ARGS((char *, char *, int));
  315. X
  316. X/*
  317. X - regcomp - compile a regular expression into internal code
  318. X *
  319. X * We can't allocate space until we know how big the compiled form will be,
  320. X * but we can't compile it (and thus know how big it is) until we've got a
  321. X * place to put the code.  So we cheat:  we compile it twice, once with code
  322. X * generation turned off and size counting turned on, and once "for real".
  323. X * This also means that we don't allocate space until we are sure that the
  324. X * thing really will compile successfully, and we never have to move the
  325. X * code and thus invalidate pointers into it.  (Note that it has to be in
  326. X * one piece because free() must be able to free it all.)
  327. X *
  328. X * Beware that the optimization-preparation code in here knows about some
  329. X * of the structure of the compiled regexp.
  330. X */
  331. X    regexp           *
  332. Xregcomp(exp)
  333. X    char           *exp;
  334. X{
  335. X    register regexp *r;
  336. X    register char  *scan;
  337. X    register char  *longest;
  338. X    register int    len;
  339. X    int             flags;
  340. X/*    extern char    *malloc();*/
  341. X
  342. X    if (exp == NULL) {
  343. X        FAIL(e_null);
  344. X    }
  345. X
  346. X#ifdef EMPTY_RE            /* this is done outside of regexp */
  347. X    if (*exp == '\0') {
  348. X        if (reg_prev_re) {
  349. X            exp = reg_prev_re;
  350. X        } else {
  351. X            FAIL(e_noprevre);
  352. X        }
  353. X    }
  354. X#endif
  355. X
  356. X    /* First pass: determine size, legality. */
  357. X    initchr((unsigned char *)exp);
  358. X    regnpar = 1;
  359. X    regsize = 0L;
  360. X    regcode = ®dummy;
  361. X    regendp = NULL;
  362. X    regc(MAGIC);
  363. X    if (reg(0, &flags) == NULL)
  364. X        return NULL;
  365. X
  366. X    /* Small enough for pointer-storage convention? */
  367. X    if (regsize >= 32767L)        /* Probably could be 65535L. */
  368. X        FAIL(e_toolong);
  369. X
  370. X    /* Allocate space. */
  371. X/*    r = (regexp *) malloc((unsigned) (sizeof(regexp) + regsize));*/
  372. X    r = (regexp *) alloc((unsigned) (sizeof(regexp) + regsize));
  373. X    if (r == NULL)
  374. X        FAIL(e_outofmem);
  375. X
  376. X#ifdef EMPTY_RE            /* this is done outside of regexp */
  377. X    if (exp != reg_prev_re) {
  378. X        free(reg_prev_re);
  379. X        if (reg_prev_re = alloc(strlen(exp) + 1))
  380. X            strcpy(reg_prev_re, exp);
  381. X    }
  382. X#endif
  383. X
  384. X    /* Second pass: emit code. */
  385. X    initchr((unsigned char *)exp);
  386. X    regnpar = 1;
  387. X    regcode = r->program;
  388. X    regendp = r->endp;
  389. X    regc(MAGIC);
  390. X    if (reg(0, &flags) == NULL) {
  391. X        free(r);
  392. X        return NULL;
  393. X    }
  394. X
  395. X    /* Dig out information for optimizations. */
  396. X    r->regstart = '\0';         /* Worst-case defaults. */
  397. X    r->reganch = 0;
  398. X    r->regmust = NULL;
  399. X    r->regmlen = 0;
  400. X    scan = r->program + 1;        /* First BRANCH. */
  401. X    if (OP(regnext(scan)) == END) {     /* Only one top-level choice. */
  402. X        scan = OPERAND(scan);
  403. X
  404. X        /* Starting-point info. */
  405. X        if (OP(scan) == EXACTLY)
  406. X            r->regstart = *OPERAND(scan);
  407. X        else if (OP(scan) == BOL)
  408. X            r->reganch++;
  409. X
  410. X        /*
  411. X         * If there's something expensive in the r.e., find the longest
  412. X         * literal string that must appear and make it the regmust.  Resolve
  413. X         * ties in favor of later strings, since the regstart check works
  414. X         * with the beginning of the r.e. and avoiding duplication
  415. X         * strengthens checking.  Not a strong reason, but sufficient in the
  416. X         * absence of others.
  417. X         */
  418. X        if (flags & SPSTART) {
  419. X            longest = NULL;
  420. X            len = 0;
  421. X            for (; scan != NULL; scan = regnext(scan))
  422. X                if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= (size_t)len) {
  423. X                    longest = OPERAND(scan);
  424. X                    len = strlen(OPERAND(scan));
  425. X                }
  426. X            r->regmust = longest;
  427. X            r->regmlen = len;
  428. X        }
  429. X    }
  430. X#ifdef DEBUG
  431. X    regdump(r);
  432. X#endif
  433. X    return r;
  434. X}
  435. X
  436. X/*
  437. X - reg - regular expression, i.e. main body or parenthesized thing
  438. X *
  439. X * Caller must absorb opening parenthesis.
  440. X *
  441. X * Combining parenthesis handling with the base level of regular expression
  442. X * is a trifle forced, but the need to tie the tails of the branches to what
  443. X * follows makes it hard to avoid.
  444. X */
  445. X    static char *
  446. Xreg(paren, flagp)
  447. X    int             paren;        /* Parenthesized? */
  448. X    int            *flagp;
  449. X{
  450. X    register char  *ret;
  451. X    register char  *br;
  452. X    register char  *ender;
  453. X    register int    parno = 0;
  454. X    int             flags;
  455. X
  456. X    *flagp = HASWIDTH;            /* Tentatively. */
  457. X
  458. X    /* Make an MOPEN node, if parenthesized. */
  459. X    if (paren) {
  460. X        if (regnpar >= NSUBEXP)
  461. X            FAIL(e_toombra);
  462. X        parno = regnpar;
  463. X        regnpar++;
  464. X        ret = regnode((char)(MOPEN + parno));
  465. X        if (regendp)
  466. X            regendp[parno] = NULL;    /* haven't seen the close paren yet */
  467. X    } else
  468. X        ret = NULL;
  469. X
  470. X    /* Pick up the branches, linking them together. */
  471. X    br = regbranch(&flags);
  472. X    if (br == NULL)
  473. X        return NULL;
  474. X    if (ret != NULL)
  475. X        regtail(ret, br);        /* MOPEN -> first. */
  476. X    else
  477. X        ret = br;
  478. X    if (!(flags & HASWIDTH))
  479. X        *flagp &= ~HASWIDTH;
  480. X    *flagp |= flags & SPSTART;
  481. X    while (peekchr() == Magic('|')) {
  482. X        skipchr();
  483. X        br = regbranch(&flags);
  484. X        if (br == NULL)
  485. X            return NULL;
  486. X        regtail(ret, br);        /* BRANCH -> BRANCH. */
  487. X        if (!(flags & HASWIDTH))
  488. X            *flagp &= ~HASWIDTH;
  489. X        *flagp |= flags & SPSTART;
  490. X    }
  491. X
  492. X    /* Make a closing node, and hook it on the end. */
  493. X    ender = regnode((char)((paren) ? MCLOSE + parno : END));
  494. X    regtail(ret, ender);
  495. X
  496. X    /* Hook the tails of the branches to the closing node. */
  497. X    for (br = ret; br != NULL; br = regnext(br))
  498. X        regoptail(br, ender);
  499. X
  500. X    /* Check for proper termination. */
  501. X    if (paren && getchr() != Magic(')')) {
  502. X        FAIL(e_toombra);
  503. X    } else if (!paren && peekchr() != '\0') {
  504. X        if (PeekChr() == Magic(')')) {
  505. X            FAIL(e_toomket);
  506. X        } else
  507. X            FAIL(e_trailing);/* "Can't happen". */
  508. X        /* NOTREACHED */
  509. X    }
  510. X    /*
  511. X     * Here we set the flag allowing back references to this set of
  512. X     * parentheses.
  513. X     */
  514. X    if (paren && regendp)
  515. X        regendp[parno] = ender;    /* have seen the close paren */
  516. X    return ret;
  517. X}
  518. X
  519. X/*
  520. X - regbranch - one alternative of an | operator
  521. X *
  522. X * Implements the concatenation operator.
  523. X */
  524. X    static char    *
  525. Xregbranch(flagp)
  526. X    int            *flagp;
  527. X{
  528. X    register char  *ret;
  529. X    register char  *chain;
  530. X    register char  *latest;
  531. X    int             flags;
  532. X
  533. X    *flagp = WORST;             /* Tentatively. */
  534. X
  535. X    ret = regnode(BRANCH);
  536. X    chain = NULL;
  537. X    while (peekchr() != '\0' && PeekChr() != Magic('|') && PeekChr() != Magic(')')) {
  538. X        latest = regpiece(&flags);
  539. X        if (latest == NULL)
  540. X            return NULL;
  541. X        *flagp |= flags & HASWIDTH;
  542. X        if (chain == NULL)        /* First piece. */
  543. X            *flagp |= flags & SPSTART;
  544. X        else
  545. X            regtail(chain, latest);
  546. X        chain = latest;
  547. X    }
  548. X    if (chain == NULL)            /* Loop ran zero times. */
  549. X        (void) regnode(NOTHING);
  550. X
  551. X    return ret;
  552. X}
  553. X
  554. X/*
  555. X - regpiece - something followed by possible [*+?]
  556. X *
  557. X * Note that the branching code sequences used for ? and the general cases
  558. X * of * and + are somewhat optimized:  they use the same NOTHING node as
  559. X * both the endmarker for their branch list and the body of the last branch.
  560. X * It might seem that this node could be dispensed with entirely, but the
  561. X * endmarker role is not redundant.
  562. X */
  563. Xstatic char    *
  564. Xregpiece(flagp)
  565. X    int            *flagp;
  566. X{
  567. X    register char  *ret;
  568. X    register int    op;
  569. X    register char  *next;
  570. X    int             flags;
  571. X
  572. X    ret = regatom(&flags);
  573. X    if (ret == NULL)
  574. X        return NULL;
  575. X
  576. X    op = peekchr();
  577. X    if (!ismult(op)) {
  578. X        *flagp = flags;
  579. X        return ret;
  580. X    }
  581. X    if (!(flags & HASWIDTH) && op != Magic('?'))
  582. X        FAIL("*+ operand could be empty");
  583. X    *flagp = (op != Magic('+')) ? (WORST | SPSTART) : (WORST | HASWIDTH);
  584. X
  585. X    if (op == Magic('*') && (flags & SIMPLE))
  586. X        reginsert(STAR, ret);
  587. X    else if (op == Magic('*')) {
  588. X        /* Emit x* as (x&|), where & means "self". */
  589. X        reginsert(BRANCH, ret); /* Either x */
  590. X        regoptail(ret, regnode(BACK));    /* and loop */
  591. X        regoptail(ret, ret);    /* back */
  592. X        regtail(ret, regnode(BRANCH));    /* or */
  593. X        regtail(ret, regnode(NOTHING)); /* null. */
  594. X    } else if (op == Magic('+') && (flags & SIMPLE))
  595. X        reginsert(PLUS, ret);
  596. X    else if (op == Magic('+')) {
  597. X        /* Emit x+ as x(&|), where & means "self". */
  598. X        next = regnode(BRANCH); /* Either */
  599. X        regtail(ret, next);
  600. X        regtail(regnode(BACK), ret);    /* loop back */
  601. X        regtail(next, regnode(BRANCH)); /* or */
  602. X        regtail(ret, regnode(NOTHING)); /* null. */
  603. X    } else if (op == Magic('?')) {
  604. X        /* Emit x? as (x|) */
  605. X        reginsert(BRANCH, ret); /* Either x */
  606. X        regtail(ret, regnode(BRANCH));    /* or */
  607. X        next = regnode(NOTHING);/* null. */
  608. X        regtail(ret, next);
  609. X        regoptail(ret, next);
  610. X    }
  611. X    skipchr();
  612. X    if (ismult(peekchr()))
  613. X        FAIL("Nested *?+");
  614. X
  615. X    return ret;
  616. X}
  617. X
  618. X/*
  619. X - regatom - the lowest level
  620. X *
  621. X * Optimization:  gobbles an entire sequence of ordinary characters so that
  622. X * it can turn them into a single node, which is smaller to store and
  623. X * faster to run.
  624. X */
  625. Xstatic char    *
  626. Xregatom(flagp)
  627. X    int            *flagp;
  628. X{
  629. X    register char  *ret;
  630. X    int             flags;
  631. X
  632. X    *flagp = WORST;             /* Tentatively. */
  633. X
  634. X    switch (getchr()) {
  635. X      case Magic('^'):
  636. X        ret = regnode(BOL);
  637. X        break;
  638. X      case Magic('$'):
  639. X        ret = regnode(EOL);
  640. X        break;
  641. X      case Magic('<'):
  642. X        ret = regnode(BOW);
  643. X        break;
  644. X      case Magic('>'):
  645. X        ret = regnode(EOW);
  646. X        break;
  647. X      case Magic('.'):
  648. X        ret = regnode(ANY);
  649. X        *flagp |= HASWIDTH | SIMPLE;
  650. X        break;
  651. X      case Magic('['):{
  652. X            /*
  653. X             * In a character class, different parsing rules apply.
  654. X             * Not even \ is special anymore, nothing is.
  655. X             */
  656. X            if (*regparse == '^') {     /* Complement of range. */
  657. X                ret = regnode(ANYBUT);
  658. X                regparse++;
  659. X            } else
  660. X                ret = regnode(ANYOF);
  661. X            if (*regparse == ']' || *regparse == '-')
  662. X                regc(*regparse++);
  663. X            while (*regparse != '\0' && *regparse != ']') {
  664. X                if (*regparse == '-') {
  665. X                    regparse++;
  666. X                    if (*regparse == ']' || *regparse == '\0')
  667. X                        regc('-');
  668. X                    else {
  669. X                        register int    class;
  670. X                        register int    classend;
  671. X
  672. X                        class = UCHARAT(regparse - 2) + 1;
  673. X                        classend = UCHARAT(regparse);
  674. X                        if (class > classend + 1)
  675. X                            FAIL(e_invrange);
  676. X                        for (; class <= classend; class++)
  677. X                            regc((char)class);
  678. X                        regparse++;
  679. X                    }
  680. X                } else if (*regparse == '\\' && regparse[1]) {
  681. X                    regparse++;
  682. X                    regc(*regparse++);
  683. X                } else
  684. X                    regc(*regparse++);
  685. X            }
  686. X            regc('\0');
  687. X            if (*regparse != ']')
  688. X                FAIL(e_toomsbra);
  689. X            skipchr();            /* let's be friends with the lexer again */
  690. X            *flagp |= HASWIDTH | SIMPLE;
  691. X        }
  692. X        break;
  693. X      case Magic('('):
  694. X        ret = reg(1, &flags);
  695. X        if (ret == NULL)
  696. X            return NULL;
  697. X        *flagp |= flags & (HASWIDTH | SPSTART);
  698. X        break;
  699. X      case '\0':
  700. X      case Magic('|'):
  701. X      case Magic(')'):
  702. X        FAIL(e_internal);    /* Supposed to be caught earlier. */
  703. X        /* break; Not Reached */
  704. X      case Magic('?'):
  705. X      case Magic('+'):
  706. X      case Magic('*'):
  707. X        FAIL("?+* follows nothing");
  708. X        /* break; Not Reached */
  709. X#ifdef TILDE
  710. X      case Magic('~'):            /* previous substitute pattern */
  711. X            if (reg_prev_sub) {
  712. X                register char *p;
  713. X
  714. X                ret = regnode(EXACTLY);
  715. X                p = reg_prev_sub;
  716. X                while (*p) {
  717. X                    regc(*p++);
  718. X                }
  719. X                regc('\0');
  720. X                if (p - reg_prev_sub) {
  721. X                    *flagp |= HASWIDTH;
  722. X                    if ((p - reg_prev_sub) == 1)
  723. X                        *flagp |= SIMPLE;
  724. X                }
  725. X              } else
  726. X                FAIL(e_nopresub);
  727. X            break;
  728. X#endif
  729. X#ifdef BACKREF
  730. X      case Magic('1'):
  731. X      case Magic('2'):
  732. X      case Magic('3'):
  733. X      case Magic('4'):
  734. X      case Magic('5'):
  735. X      case Magic('6'):
  736. X      case Magic('7'):
  737. X      case Magic('8'):
  738. X      case Magic('9'): {
  739. X            int                refnum;
  740. X
  741. X            ungetchr();
  742. X            refnum = getchr() - Magic('0');
  743. X            /*
  744. X             * Check if the back reference is legal. We use the parentheses
  745. X             * pointers to mark encountered close parentheses, but this
  746. X             * is only available in the second pass. Checking opens is
  747. X             * always possible.
  748. X             * Should also check that we don't refer to something that
  749. X             * is repeated (+*?): what instance of the repetition should
  750. X             * we match? TODO.
  751. X             */
  752. X            if (refnum < regnpar &&
  753. X                (regendp == NULL || regendp[refnum] != NULL))
  754. X                ret = regnode(BACKREF + refnum);
  755. X            else
  756. X                FAIL("Illegal back reference");
  757. X        }
  758. X        break;
  759. X#endif
  760. X      default:{
  761. X            register int    len;
  762. X            int                chr;
  763. X
  764. X            ungetchr();
  765. X            len = 0;
  766. X            ret = regnode(EXACTLY);
  767. X            while ((chr = peekchr()) != '\0' && (chr < Magic(0)))
  768. X            {
  769. X                regc(chr);
  770. X                skipchr();
  771. X                len++;
  772. X            }
  773. X#ifdef DEBUG
  774. X            if (len == 0)
  775. X                 FAIL("Unexpected magic character; check META.");
  776. X#endif
  777. X            /*
  778. X             * If there is a following *, \+ or \? we need the character
  779. X             * in front of it as a single character operand
  780. X             */
  781. X            if (len > 1 && ismult(chr))
  782. X            {
  783. X                unregc();            /* Back off of *+? operand */
  784. X                ungetchr();            /* and put it back for next time */
  785. X                --len;
  786. X            }
  787. X            regc('\0');
  788. X            *flagp |= HASWIDTH;
  789. X            if (len == 1)
  790. X                *flagp |= SIMPLE;
  791. X        }
  792. X        break;
  793. X    }
  794. X
  795. X    return ret;
  796. X}
  797. X
  798. X/*
  799. X - regnode - emit a node
  800. X */
  801. Xstatic char    *                /* Location. */
  802. Xregnode(op)
  803. X    int            op;
  804. X{
  805. X    register char  *ret;
  806. X    register char  *ptr;
  807. X
  808. X    ret = regcode;
  809. X    if (ret == ®dummy) {
  810. X        regsize += 3;
  811. X        return ret;
  812. X    }
  813. X    ptr = ret;
  814. X    *ptr++ = op;
  815. X    *ptr++ = '\0';                /* Null "next" pointer. */
  816. X    *ptr++ = '\0';
  817. X    regcode = ptr;
  818. X
  819. X    return ret;
  820. X}
  821. X
  822. X/*
  823. X - regc - emit (if appropriate) a byte of code
  824. X */
  825. Xstatic void
  826. Xregc(b)
  827. X    int            b;
  828. X{
  829. X    if (regcode != ®dummy)
  830. X        *(u_char *)regcode++ = b;
  831. X    else
  832. X        regsize++;
  833. X}
  834. X
  835. X/*
  836. X - unregc - take back (if appropriate) a byte of code
  837. X */
  838. Xstatic void
  839. Xunregc()
  840. X{
  841. X    if (regcode != ®dummy)
  842. X        regcode--;
  843. X    else
  844. X        regsize--;
  845. X}
  846. X
  847. X/*
  848. X - reginsert - insert an operator in front of already-emitted operand
  849. X *
  850. X * Means relocating the operand.
  851. X */
  852. Xstatic void
  853. Xreginsert(op, opnd)
  854. X    int            op;
  855. X    char           *opnd;
  856. X{
  857. X    register char  *src;
  858. X    register char  *dst;
  859. X    register char  *place;
  860. X
  861. X    if (regcode == ®dummy) {
  862. X        regsize += 3;
  863. X        return;
  864. X    }
  865. X    src = regcode;
  866. X    regcode += 3;
  867. X    dst = regcode;
  868. X    while (src > opnd)
  869. X        *--dst = *--src;
  870. X
  871. X    place = opnd;                /* Op node, where operand used to be. */
  872. X    *place++ = op;
  873. X    *place++ = '\0';
  874. X    *place = '\0';
  875. X}
  876. X
  877. X/*
  878. X - regtail - set the next-pointer at the end of a node chain
  879. X */
  880. Xstatic void
  881. Xregtail(p, val)
  882. X    char           *p;
  883. X    char           *val;
  884. X{
  885. X    register char  *scan;
  886. X    register char  *temp;
  887. X    register int    offset;
  888. X
  889. X    if (p == ®dummy)
  890. X        return;
  891. X
  892. X    /* Find last node. */
  893. X    scan = p;
  894. X    for (;;) {
  895. X        temp = regnext(scan);
  896. X        if (temp == NULL)
  897. X            break;
  898. X        scan = temp;
  899. X    }
  900. X
  901. X    if (OP(scan) == BACK)
  902. X        offset = (int)(scan - val);
  903. X    else
  904. X        offset = (int)(val - scan);
  905. X    *(scan + 1) = (char) ((offset >> 8) & 0377);
  906. X    *(scan + 2) = (char) (offset & 0377);
  907. X}
  908. X
  909. X/*
  910. X - regoptail - regtail on operand of first argument; nop if operandless
  911. X */
  912. Xstatic void
  913. Xregoptail(p, val)
  914. X    char           *p;
  915. X    char           *val;
  916. X{
  917. X    /* "Operandless" and "op != BRANCH" are synonymous in practice. */
  918. X    if (p == NULL || p == ®dummy || OP(p) != BRANCH)
  919. X        return;
  920. X    regtail(OPERAND(p), val);
  921. X}
  922. X
  923. X/*
  924. X - getchr() - get the next character from the pattern. We know about
  925. X * magic and such, so therefore we need a lexical analyzer.
  926. X */
  927. X
  928. X/* static int        curchr; */
  929. Xstatic int        prevchr;
  930. Xstatic int        nextchr;    /* used for ungetchr() */
  931. X
  932. Xstatic void
  933. Xinitchr(str)
  934. Xunsigned char *str;
  935. X{
  936. X    regparse = str;
  937. X    curchr = prevchr = nextchr = -1;
  938. X}
  939. X
  940. Xstatic int
  941. Xpeekchr()
  942. X{
  943. X    if (curchr < 0) {
  944. X        switch (curchr = regparse[0]) {
  945. X        case '.':
  946. X        case '*':
  947. X    /*    case '+':*/
  948. X    /*    case '?':*/
  949. X        case '[':
  950. X        case '~':
  951. X            if (reg_magic)
  952. X                curchr = Magic(curchr);
  953. X            break;
  954. X        case '^':
  955. X            /* ^ is only magic as the very first character */
  956. X            if (prevchr < 0)
  957. X                curchr = Magic('^');
  958. X            break;
  959. X        case '$':
  960. X            /* $ is only magic as the very last character */
  961. X            if (!regparse[1])
  962. X                curchr = Magic('$');
  963. X            break;
  964. X        case '\\':
  965. X            regparse++;
  966. X            if (regparse[0] == NUL)
  967. X                curchr = '\\';    /* trailing '\' */
  968. X            else if (strchr(META, regparse[0]))
  969. X            {
  970. X                /*
  971. X                 * META contains everything that may be magic sometimes, except
  972. X                 * ^ and $ ("\^" and "\$" are never magic).
  973. X                 * We now fetch the next character and toggle its magicness.
  974. X                 * Therefore, \ is so meta-magic that it is not in META.
  975. X                 */
  976. X                curchr = -1;
  977. X                peekchr();
  978. X                curchr ^= Magic(0);
  979. X            }
  980. X            else
  981. X            {
  982. X                /*
  983. X                 * Next character can never be (made) magic?
  984. X                 * Then backslashing it won't do anything.
  985. X                 */
  986. X                curchr = regparse[0];
  987. X            }
  988. X            break;
  989. X        }
  990. X    }
  991. X
  992. X    return curchr;
  993. X}
  994. X
  995. Xstatic void
  996. Xskipchr()
  997. X{
  998. X    regparse++;
  999. X    prevchr = curchr;
  1000. X    curchr = nextchr;        /* use previously unget char, or -1 */
  1001. X    nextchr = -1;
  1002. X}
  1003. X
  1004. Xstatic int
  1005. Xgetchr()
  1006. X{
  1007. X    int chr;
  1008. X
  1009. X    chr = peekchr();
  1010. X    skipchr();
  1011. X
  1012. X    return chr;
  1013. X}
  1014. X
  1015. X/*
  1016. X * put character back. Works only once!
  1017. X */
  1018. Xstatic void
  1019. Xungetchr()
  1020. X{
  1021. X    nextchr = curchr;
  1022. X    curchr = prevchr;
  1023. X    /*
  1024. X     * Backup regparse as well; not because we will use what it points at,
  1025. X     * but because skipchr() will bump it again.
  1026. X     */
  1027. X    regparse--;
  1028. X}
  1029. X
  1030. X/*
  1031. X * regexec and friends
  1032. X */
  1033. X
  1034. X/*
  1035. X * Global work variables for regexec().
  1036. X */
  1037. Xstatic char    *reginput;        /* String-input pointer. */
  1038. Xstatic char    *regbol;         /* Beginning of input, for ^ check. */
  1039. Xstatic char   **regstartp;        /* Pointer to startp array. */
  1040. X/* static char   **regendp;    */    /* Ditto for endp. */
  1041. X
  1042. X/*
  1043. X * Forwards.
  1044. X */
  1045. Xstatic int        regtry __ARGS((regexp *, char *));
  1046. Xstatic int        regmatch __ARGS((char *));
  1047. Xstatic int        regrepeat __ARGS((char *));
  1048. X
  1049. X#ifdef DEBUG
  1050. Xint             regnarrate = 1;
  1051. Xvoid            regdump __ARGS((regexp *));
  1052. Xstatic char    *regprop __ARGS((char *));
  1053. X#endif
  1054. X
  1055. X/*
  1056. X - regexec - match a regexp against a string
  1057. X */
  1058. Xint
  1059. Xregexec(prog, string, at_bol)
  1060. X    register regexp *prog;
  1061. X    register char  *string;
  1062. X    int             at_bol;
  1063. X{
  1064. X    register char  *s;
  1065. X
  1066. X    /* Be paranoid... */
  1067. X    if (prog == NULL || string == NULL) {
  1068. X        emsg(e_null);
  1069. X        return 0;
  1070. X    }
  1071. X    /* Check validity of program. */
  1072. X    if (UCHARAT(prog->program) != MAGIC) {
  1073. X        emsg(e_re_corr);
  1074. X        return 0;
  1075. X    }
  1076. X    /* If there is a "must appear" string, look for it. */
  1077. X    if (prog->regmust != NULL) {
  1078. X        s = string;
  1079. X        while ((s = cstrchr(s, prog->regmust[0])) != NULL) {
  1080. X            if (cstrncmp(s, prog->regmust, prog->regmlen) == 0)
  1081. X                break;            /* Found it. */
  1082. X            s++;
  1083. X        }
  1084. X        if (s == NULL)            /* Not present. */
  1085. X            return 0;
  1086. X    }
  1087. X    /* Mark beginning of line for ^ . */
  1088. X    if (at_bol)
  1089. X        regbol = string;        /* is possible to match bol */
  1090. X    else
  1091. X        regbol = NULL;            /* we aren't there, so don't match it */
  1092. X
  1093. X    /* Simplest case:  anchored match need be tried only once. */
  1094. X    if (prog->reganch)
  1095. X        return regtry(prog, string);
  1096. X
  1097. X    /* Messy cases:  unanchored match. */
  1098. X    s = string;
  1099. X    if (prog->regstart != '\0')
  1100. X        /* We know what char it must start with. */
  1101. X        while ((s = cstrchr(s, prog->regstart)) != NULL) {
  1102. X            if (regtry(prog, s))
  1103. X                return 1;
  1104. X            s++;
  1105. X        }
  1106. X    else
  1107. X        /* We don't -- general case. */
  1108. X        do {
  1109. X            if (regtry(prog, s))
  1110. X                return 1;
  1111. X        } while (*s++ != '\0');
  1112. X
  1113. X    /* Failure. */
  1114. X    return 0;
  1115. X}
  1116. X
  1117. X/*
  1118. X - regtry - try match at specific point
  1119. X */
  1120. Xstatic int                        /* 0 failure, 1 success */
  1121. Xregtry(prog, string)
  1122. X    regexp           *prog;
  1123. X    char           *string;
  1124. X{
  1125. X    register int    i;
  1126. X    register char **sp;
  1127. X    register char **ep;
  1128. X
  1129. X    reginput = string;
  1130. X    regstartp = prog->startp;
  1131. X    regendp = prog->endp;
  1132. X
  1133. X    sp = prog->startp;
  1134. X    ep = prog->endp;
  1135. X    for (i = NSUBEXP; i > 0; i--) {
  1136. X        *sp++ = NULL;
  1137. X        *ep++ = NULL;
  1138. X    }
  1139. X    if (regmatch(prog->program + 1)) {
  1140. X        prog->startp[0] = string;
  1141. X        prog->endp[0] = reginput;
  1142. X        return 1;
  1143. X    } else
  1144. X        return 0;
  1145. X}
  1146. X
  1147. X/*
  1148. X - regmatch - main matching routine
  1149. X *
  1150. X * Conceptually the strategy is simple:  check to see whether the current
  1151. X * node matches, call self recursively to see whether the rest matches,
  1152. X * and then act accordingly.  In practice we make some effort to avoid
  1153. X * recursion, in particular by going through "ordinary" nodes (that don't
  1154. X * need to know whether the rest of the match failed) by a loop instead of
  1155. X * by recursion.
  1156. X */
  1157. Xstatic int                        /* 0 failure, 1 success */
  1158. Xregmatch(prog)
  1159. X    char           *prog;
  1160. X{
  1161. X    register char  *scan;        /* Current node. */
  1162. X    char           *next;        /* Next node. */
  1163. X
  1164. X    scan = prog;
  1165. X#ifdef DEBUG
  1166. X    if (scan != NULL && regnarrate)
  1167. X        fprintf(stderr, "%s(\n", regprop(scan));
  1168. X#endif
  1169. X    while (scan != NULL) {
  1170. X#ifdef DEBUG
  1171. X        if (regnarrate) {
  1172. X            fprintf(stderr, "%s...\n", regprop(scan));
  1173. X        }
  1174. X#endif
  1175. X        next = regnext(scan);
  1176. X        switch (OP(scan)) {
  1177. X          case BOL:
  1178. X            if (reginput != regbol)
  1179. X                return 0;
  1180. X            break;
  1181. X          case EOL:
  1182. X            if (*reginput != '\0')
  1183. X                return 0;
  1184. X            break;
  1185. X          case BOW:        /* \<word; reginput points to w */
  1186. X#define isidchar(x)    (isalnum(x) || ((x) == '_'))
  1187. X              if (reginput != regbol && isidchar(reginput[-1]))
  1188. X                return 0;
  1189. X              if (!reginput[0] || !isidchar(reginput[0]))
  1190. X                return 0;
  1191. X            break;
  1192. X          case EOW:        /* word\>; reginput points after d */
  1193. X              if (reginput == regbol || !isidchar(reginput[-1]))
  1194. X                return 0;
  1195. X              if (reginput[0] && isidchar(reginput[0]))
  1196. X                return 0;
  1197. X            break;
  1198. X          case ANY:
  1199. X            if (*reginput == '\0')
  1200. X                return 0;
  1201. X            reginput++;
  1202. X            break;
  1203. X          case EXACTLY:{
  1204. X                register int    len;
  1205. X                register char  *opnd;
  1206. X
  1207. X                opnd = OPERAND(scan);
  1208. X                /* Inline the first character, for speed. */
  1209. X                if (mkup(*opnd) != mkup(*reginput))
  1210. X                    return 0;
  1211. X                len = strlen(opnd);
  1212. X                if (len > 1 && cstrncmp(opnd, reginput, len) != 0)
  1213. X                    return 0;
  1214. X                reginput += len;
  1215. X            }
  1216. X            break;
  1217. X          case ANYOF:
  1218. X            if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) == NULL)
  1219. X                return 0;
  1220. X            reginput++;
  1221. X            break;
  1222. X          case ANYBUT:
  1223. X            if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) != NULL)
  1224. X                return 0;
  1225. X            reginput++;
  1226. X            break;
  1227. X          case NOTHING:
  1228. X            break;
  1229. X          case BACK:
  1230. X            break;
  1231. X          case MOPEN + 1:
  1232. X          case MOPEN + 2:
  1233. X          case MOPEN + 3:
  1234. X          case MOPEN + 4:
  1235. X          case MOPEN + 5:
  1236. X          case MOPEN + 6:
  1237. X          case MOPEN + 7:
  1238. X          case MOPEN + 8:
  1239. X          case MOPEN + 9:{
  1240. X                register int    no;
  1241. X                register char  *save;
  1242. X
  1243. X                no = OP(scan) - MOPEN;
  1244. X                save = regstartp[no];
  1245. X                regstartp[no] = reginput; /* Tentatively */
  1246. X#ifdef DEBUG
  1247. X                printf("MOPEN  %d pre  @'%s' ('%s' )'%s'\n",
  1248. X                    no, save,
  1249. X                    regstartp[no]? regstartp[no] : "NULL",
  1250. X                    regendp[no]? regendp[no] : "NULL");
  1251. X#endif
  1252. X
  1253. X                if (regmatch(next)) {
  1254. X#ifdef DEBUG
  1255. X                printf("MOPEN  %d post @'%s' ('%s' )'%s'\n",
  1256. X                    no, save,
  1257. X                    regstartp[no]? regstartp[no] : "NULL",
  1258. X                    regendp[no]? regendp[no] : "NULL");
  1259. X#endif
  1260. X                    return 1;
  1261. X                }
  1262. X                regstartp[no] = save;        /* We were wrong... */
  1263. X                return 0;
  1264. X            }
  1265. X            /* break; Not Reached */
  1266. X          case MCLOSE + 1:
  1267. X          case MCLOSE + 2:
  1268. X          case MCLOSE + 3:
  1269. X          case MCLOSE + 4:
  1270. X          case MCLOSE + 5:
  1271. X          case MCLOSE + 6:
  1272. X          case MCLOSE + 7:
  1273. X          case MCLOSE + 8:
  1274. X          case MCLOSE + 9:{
  1275. X                register int    no;
  1276. X                register char  *save;
  1277. X
  1278. X                no = OP(scan) - MCLOSE;
  1279. X                save = regendp[no];
  1280. X                regendp[no] = reginput; /* Tentatively */
  1281. X#ifdef DEBUG
  1282. X                printf("MCLOSE %d pre  @'%s' ('%s' )'%s'\n",
  1283. X                    no, save,
  1284. X                    regstartp[no]? regstartp[no] : "NULL",
  1285. X                    regendp[no]? regendp[no] : "NULL");
  1286. X#endif
  1287. X
  1288. X                if (regmatch(next)) {
  1289. X#ifdef DEBUG
  1290. X                printf("MCLOSE %d post @'%s' ('%s' )'%s'\n",
  1291. X                    no, save,
  1292. X                    regstartp[no]? regstartp[no] : "NULL",
  1293. X                    regendp[no]? regendp[no] : "NULL");
  1294. X#endif
  1295. X                    return 1;
  1296. X                }
  1297. X                regendp[no] = save;        /* We were wrong... */
  1298. X                return 0;
  1299. X            }
  1300. X            /* break; Not Reached */
  1301. X#ifdef BACKREF
  1302. X          case BACKREF + 1:
  1303. X          case BACKREF + 2:
  1304. X          case BACKREF + 3:
  1305. X          case BACKREF + 4:
  1306. X          case BACKREF + 5:
  1307. X          case BACKREF + 6:
  1308. X          case BACKREF + 7:
  1309. X          case BACKREF + 8:
  1310. X          case BACKREF + 9:{
  1311. X                register int    no;
  1312. X                int                len;
  1313. X
  1314. X                no = OP(scan) - BACKREF;
  1315. X                if (regendp[no] != NULL) {
  1316. X                    len = (int)(regendp[no] - regstartp[no]);
  1317. X                    if (cstrncmp(regstartp[no], reginput, len) != 0)
  1318. X                        return 0;
  1319. X                    reginput += len;
  1320. X                } else {
  1321. X                    /*emsg("backref to 0-repeat");*/
  1322. X                    /*return 0;*/
  1323. X                }
  1324. X              }
  1325. X            break;
  1326. X#endif
  1327. X          case BRANCH:{
  1328. X                register char  *save;
  1329. X
  1330. X                if (OP(next) != BRANCH) /* No choice. */
  1331. X                    next = OPERAND(scan);        /* Avoid recursion. */
  1332. X                else {
  1333. X                    do {
  1334. X                        save = reginput;
  1335. X                        if (regmatch(OPERAND(scan)))
  1336. X                            return 1;
  1337. X                        reginput = save;
  1338. X                        scan = regnext(scan);
  1339. X                    } while (scan != NULL && OP(scan) == BRANCH);
  1340. X                    return 0;
  1341. X                    /* NOTREACHED */
  1342. X                }
  1343. X            }
  1344. X            break;
  1345. X          case STAR:
  1346. X          case PLUS:{
  1347. X                register char    nextch;
  1348. X                register int    no;
  1349. X                register char  *save;
  1350. X                register int    min;
  1351. X
  1352. X                /*
  1353. X                 * Lookahead to avoid useless match attempts when we know
  1354. X                 * what character comes next.
  1355. X                 */
  1356. X                nextch = '\0';
  1357. X                if (OP(next) == EXACTLY)
  1358. X                    nextch = mkup(*OPERAND(next));
  1359. X                min = (OP(scan) == STAR) ? 0 : 1;
  1360. X                save = reginput;
  1361. X                no = regrepeat(OPERAND(scan));
  1362. X                while (no >= min) {
  1363. X                    /* If it could work, try it. */
  1364. X                    if (nextch == '\0' || mkup(*reginput) == nextch)
  1365. X                        if (regmatch(next))
  1366. X                            return 1;
  1367. X                    /* Couldn't or didn't -- back up. */
  1368. X                    no--;
  1369. X                    reginput = save + no;
  1370. X                }
  1371. X                return 0;
  1372. X            }
  1373. X            /* break; Not Reached */
  1374. X          case END:
  1375. X            return 1;         /* Success! */
  1376. X            /* break; Not Reached */
  1377. X          default:
  1378. X            emsg(e_re_corr);
  1379. X            return 0;
  1380. X            /* break; Not Reached */
  1381. X        }
  1382. X
  1383. X        scan = next;
  1384. X    }
  1385. X
  1386. X    /*
  1387. X     * We get here only if there's trouble -- normally "case END" is the
  1388. X     * terminating point.
  1389. X     */
  1390. X    emsg(e_re_corr);
  1391. X    return 0;
  1392. X}
  1393. X
  1394. X/*
  1395. X - regrepeat - repeatedly match something simple, report how many
  1396. X */
  1397. Xstatic int
  1398. Xregrepeat(p)
  1399. X    char           *p;
  1400. X{
  1401. X    register int    count = 0;
  1402. X    register char  *scan;
  1403. X    register char  *opnd;
  1404. X
  1405. X    scan = reginput;
  1406. X    opnd = OPERAND(p);
  1407. X    switch (OP(p)) {
  1408. X      case ANY:
  1409. X        count = strlen(scan);
  1410. X        scan += count;
  1411. X        break;
  1412. X      case EXACTLY:
  1413. X        while (mkup(*opnd) == mkup(*scan)) {
  1414. X            count++;
  1415. X            scan++;
  1416. X        }
  1417. X        break;
  1418. X      case ANYOF:
  1419. X        while (*scan != '\0' && strchr(opnd, *scan) != NULL) {
  1420. X            count++;
  1421. X            scan++;
  1422. X        }
  1423. X        break;
  1424. X      case ANYBUT:
  1425. X        while (*scan != '\0' && strchr(opnd, *scan) == NULL) {
  1426. X            count++;
  1427. X            scan++;
  1428. X        }
  1429. X        break;
  1430. X      default:                    /* Oh dear.  Called inappropriately. */
  1431. X        emsg(e_re_corr);
  1432. X        count = 0;                /* Best compromise. */
  1433. X        break;
  1434. X    }
  1435. X    reginput = scan;
  1436. X
  1437. X    return count;
  1438. X}
  1439. X
  1440. X/*
  1441. X - regnext - dig the "next" pointer out of a node
  1442. X */
  1443. Xstatic char    *
  1444. Xregnext(p)
  1445. X    register char  *p;
  1446. X{
  1447. X    register int    offset;
  1448. X
  1449. X    if (p == ®dummy)
  1450. X        return NULL;
  1451. X
  1452. X    offset = NEXT(p);
  1453. X    if (offset == 0)
  1454. X        return NULL;
  1455. X
  1456. X    if (OP(p) == BACK)
  1457. X        return p - offset;
  1458. X    else
  1459. X        return p + offset;
  1460. X}
  1461. X
  1462. X#ifdef DEBUG
  1463. X
  1464. X/*
  1465. X - regdump - dump a regexp onto stdout in vaguely comprehensible form
  1466. X */
  1467. Xvoid
  1468. Xregdump(r)
  1469. X    regexp           *r;
  1470. X{
  1471. X    register char  *s;
  1472. X    register char    op = EXACTLY;        /* Arbitrary non-END op. */
  1473. X    register char  *next;
  1474. X    /*extern char    *strchr();*/
  1475. X
  1476. X
  1477. X    s = r->program + 1;
  1478. X    while (op != END) {         /* While that wasn't END last time... */
  1479. X        op = OP(s);
  1480. X        printf("%2d%s", s - r->program, regprop(s));    /* Where, what. */
  1481. X        next = regnext(s);
  1482. X        if (next == NULL)        /* Next ptr. */
  1483. X            printf("(0)");
  1484. X        else
  1485. X            printf("(%d)", (s - r->program) + (next - s));
  1486. X        s += 3;
  1487. X        if (op == ANYOF || op == ANYBUT || op == EXACTLY) {
  1488. X            /* Literal string, where present. */
  1489. X            while (*s != '\0') {
  1490. X                putchar(*s);
  1491. X                s++;
  1492. X            }
  1493. X            s++;
  1494. X        }
  1495. X        putchar('\n');
  1496. X    }
  1497. X
  1498. X    /* Header fields of interest. */
  1499. X    if (r->regstart != '\0')
  1500. X        printf("start `%c' ", r->regstart);
  1501. X    if (r->reganch)
  1502. X        printf("anchored ");
  1503. X    if (r->regmust != NULL)
  1504. X        printf("must have \"%s\"", r->regmust);
  1505. X    printf("\n");
  1506. X}
  1507. X
  1508. X/*
  1509. X - regprop - printable representation of opcode
  1510. X */
  1511. Xstatic char    *
  1512. Xregprop(op)
  1513. X    char           *op;
  1514. X{
  1515. X    register char  *p;
  1516. X    static char     buf[50];
  1517. X
  1518. X    (void) strcpy(buf, ":");
  1519. X
  1520. X    switch (OP(op)) {
  1521. X      case BOL:
  1522. X        p = "BOL";
  1523. X        break;
  1524. X      case EOL:
  1525. X        p = "EOL";
  1526. X        break;
  1527. X      case ANY:
  1528. X        p = "ANY";
  1529. X        break;
  1530. X      case ANYOF:
  1531. X        p = "ANYOF";
  1532. X        break;
  1533. X      case ANYBUT:
  1534. X        p = "ANYBUT";
  1535. X        break;
  1536. X      case BRANCH:
  1537. X        p = "BRANCH";
  1538. X        break;
  1539. X      case EXACTLY:
  1540. X        p = "EXACTLY";
  1541. X        break;
  1542. X      case NOTHING:
  1543. X        p = "NOTHING";
  1544. X        break;
  1545. X      case BACK:
  1546. X        p = "BACK";
  1547. X        break;
  1548. X      case END:
  1549. X        p = "END";
  1550. X        break;
  1551. X      case MOPEN + 1:
  1552. X      case MOPEN + 2:
  1553. X      case MOPEN + 3:
  1554. X      case MOPEN + 4:
  1555. X      case MOPEN + 5:
  1556. X      case MOPEN + 6:
  1557. X      case MOPEN + 7:
  1558. X      case MOPEN + 8:
  1559. X      case MOPEN + 9:
  1560. X        sprintf(buf + strlen(buf), "MOPEN%d", OP(op) - MOPEN);
  1561. X        p = NULL;
  1562. X        break;
  1563. X      case MCLOSE + 1:
  1564. X      case MCLOSE + 2:
  1565. X      case MCLOSE + 3:
  1566. X      case MCLOSE + 4:
  1567. X      case MCLOSE + 5:
  1568. X      case MCLOSE + 6:
  1569. X      case MCLOSE + 7:
  1570. X      case MCLOSE + 8:
  1571. X      case MCLOSE + 9:
  1572. X        sprintf(buf + strlen(buf), "MCLOSE%d", OP(op) - MCLOSE);
  1573. X        p = NULL;
  1574. X        break;
  1575. X      case BACKREF + 1:
  1576. X      case BACKREF + 2:
  1577. X      case BACKREF + 3:
  1578. X      case BACKREF + 4:
  1579. X      case BACKREF + 5:
  1580. X      case BACKREF + 6:
  1581. X      case BACKREF + 7:
  1582. X      case BACKREF + 8:
  1583. X      case BACKREF + 9:
  1584. X        sprintf(buf + strlen(buf), "BACKREF%d", OP(op) - BACKREF);
  1585. X        p = NULL;
  1586. X        break;
  1587. X      case STAR:
  1588. X        p = "STAR";
  1589. X        break;
  1590. X      case PLUS:
  1591. X        p = "PLUS";
  1592. X        break;
  1593. X      default:
  1594. X        sprintf(buf + strlen(buf), "corrupt %d", OP(op));
  1595. X        p = NULL;
  1596. X        break;
  1597. X    }
  1598. X    if (p != NULL)
  1599. X        (void) strcat(buf, p);
  1600. X    return buf;
  1601. X}
  1602. X#endif
  1603. X
  1604. X/*
  1605. X * The following is provided for those people who do not have strcspn() in
  1606. X * their C libraries.  They should get off their butts and do something
  1607. X * about it; at least one public-domain implementation of those (highly
  1608. X * useful) string routines has been published on Usenet.
  1609. X */
  1610. X#ifdef STRCSPN
  1611. X/*
  1612. X * strcspn - find length of initial segment of s1 consisting entirely
  1613. X * of characters not from s2
  1614. X */
  1615. X
  1616. Xstatic int
  1617. Xstrcspn(s1, s2)
  1618. X    const char           *s1;
  1619. X    const char           *s2;
  1620. X{
  1621. X    register char  *scan1;
  1622. X    register char  *scan2;
  1623. X    register int    count;
  1624. X
  1625. X    count = 0;
  1626. X    for (scan1 = s1; *scan1 != '\0'; scan1++) {
  1627. X        for (scan2 = s2; *scan2 != '\0';)        /* ++ moved down. */
  1628. X            if (*scan1 == *scan2++)
  1629. X                return count;
  1630. X        count++;
  1631. X    }
  1632. X    return count;
  1633. X}
  1634. X#endif
  1635. X
  1636. X/*
  1637. X * Compare two strings, ignore case if reg_ic set.
  1638. X * Return 0 if strings match, non-zero otherwise.
  1639. X */
  1640. X    static int
  1641. Xcstrncmp(s1, s2, n)
  1642. X    char           *s1, *s2;
  1643. X    int             n;
  1644. X{
  1645. X    if (!reg_ic)
  1646. X        return strncmp(s1, s2, (size_t)n);
  1647. X
  1648. X#ifndef UNIX
  1649. X    return strnicmp(s1, s2, (size_t)n);
  1650. X#else
  1651. X# ifdef STRNCASECMP
  1652. X    return strncasecmp(s1, s2, (size_t)n);
  1653. X# else
  1654. X    while (n && *s1 && *s2)
  1655. X    {
  1656. X        if (mkup(*s1) != mkup(*s2))
  1657. X            return 1;
  1658. X        s1++;
  1659. X        s2++;
  1660. X        n--;
  1661. X    }
  1662. X    if (n)
  1663. X        return 1;
  1664. X    return 0;
  1665. X# endif    /* STRNCASECMP */
  1666. X#endif    /* UNIX */
  1667. X}
  1668. X
  1669. X    char *
  1670. Xcstrchr(s, c)
  1671. X    char           *s;
  1672. X    int                c;
  1673. X{
  1674. X    char           *p;
  1675. X
  1676. X    c = mkup(c);
  1677. X
  1678. X    for (p = s; *p; p++)
  1679. X    {
  1680. X        if (mkup(*p) == c)
  1681. X            return p;
  1682. X    }
  1683. X    return NULL;
  1684. X}
  1685. END_OF_FILE
  1686. if test 38964 -ne `wc -c <'vim/src/regexp.c'`; then
  1687.     echo shar: \"'vim/src/regexp.c'\" unpacked with wrong size!
  1688. fi
  1689. chmod +x 'vim/src/regexp.c'
  1690. # end of 'vim/src/regexp.c'
  1691. fi
  1692. echo shar: End of archive 19 \(of 25\).
  1693. cp /dev/null ark19isdone
  1694. MISSING=""
  1695. 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 ; do
  1696.     if test ! -f ark${I}isdone ; then
  1697.     MISSING="${MISSING} ${I}"
  1698.     fi
  1699. done
  1700. if test "${MISSING}" = "" ; then
  1701.     echo You have unpacked all 25 archives.
  1702.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1703. else
  1704.     echo You still need to unpack the following archives:
  1705.     echo "        " ${MISSING}
  1706. fi
  1707. ##  End of shell archive.
  1708. exit 0
  1709.  
  1710. ===============================================================================
  1711. Bram Moolenaar                             | DISCLAIMER:  This  note  does  not
  1712. Oce Nederland B.V., Research & Development | necessarily represent the position
  1713. p.o. box 101, 5900 MA  Venlo               | of  Oce-Nederland  B.V.  Therefore
  1714. The Netherlands        phone +31 77 594077 | no liability or responsibility for
  1715. UUCP: mool@oce.nl        fax +31 77 595473 | whatever will be accepted.
  1716.  
  1717. exit 0 # Just in case...
  1718.