home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / compsrcs / unix / volume03 / regexp < prev    next >
Encoding:
Text File  |  1988-09-11  |  56.3 KB  |  2,242 lines

  1. Subject: regexp(3)
  2. Newsgroups: mod.sources
  3. Approved: jpn@panda.UUCP
  4.  
  5. Mod.sources:  Volume 3, Issue 89
  6. Submitted by: decvax!utzoo!henry
  7.  
  8. Below is an almost-public-domain re-implementation of the V8 regexp(3)
  9. routines.
  10.  
  11.                 Henry Spencer @ U of Toronto Zoology
  12.                 {allegra,ihnp4,linus,decvax}!utzoo!henry
  13. --------------
  14. echo README:
  15. sed 's/^X//' >README <<'!'
  16. XThis is a nearly-public-domain reimplementation of the V8 regexp(3) package.
  17. XIt gives C programs the ability to use egrep-style regular expressions, and
  18. Xdoes it in a much cleaner fashion than the analogous routines in SysV.
  19. X
  20. X    Copyright (c) 1986 by University of Toronto.
  21. X    Written by Henry Spencer.  Not derived from licensed software.
  22. X
  23. X    Permission is granted to anyone to use this software for any
  24. X    purpose on any computer system, and to redistribute it freely,
  25. X    subject to the following restrictions:
  26. X
  27. X    1. The author is not responsible for the consequences of use of
  28. X        this software, no matter how awful, even if they arise
  29. X        from defects in it.
  30. X
  31. X    2. The origin of this software must not be misrepresented, either
  32. X        by explicit claim or by omission.
  33. X
  34. X    3. Altered versions must be plainly marked as such, and must not
  35. X        be misrepresented as being the original software.
  36. X
  37. XBarring a couple of small items in the BUGS list, this implementation is
  38. Xbelieved 100% compatible with V8.  It should even be binary-compatible,
  39. Xsort of, since the only fields in a "struct regexp" that other people have
  40. Xany business touching are declared in exactly the same way at the same
  41. Xlocation in the struct (the beginning).
  42. X
  43. XThis implementation is *NOT* AT&T/Bell code, and is not derived from licensed
  44. Xsoftware.  Even though U of T is a V8 licensee.  This software is based on
  45. Xa V8 manual page sent to me by Dennis Ritchie (the manual page enclosed
  46. Xhere is a complete rewrite and hence is not covered by AT&T copyright).
  47. XThe software was nearly complete at the time of arrival of our V8 tape.
  48. XI haven't even looked at V8 yet, although a friend elsewhere at U of T has
  49. Xbeen kind enough to run a few test programs using the V8 regexp(3) to resolve
  50. Xa few fine points.  I admit to some familiarity with regular-expression
  51. Ximplementations of the past, but the only one that this code traces any
  52. Xancestry to is the one published in Kernighan & Plauger (from which this
  53. Xone draws ideas but not code).
  54. X
  55. XSimplistically:  put this stuff into a source directory, copy regexp.h into
  56. X/usr/include, inspect Makefile for compilation options that need changing
  57. Xto suit your local environment, and then do "make r".  This compiles the
  58. Xregexp(3) functions, compiles a test program, and runs a large set of
  59. Xregression tests.  If there are no complaints, then put regexp.o, regsub.o,
  60. Xand regerror.o into your C library, and regexp.3 into your manual-pages
  61. Xdirectory.
  62. X
  63. XNote that if you don't put regexp.h into /usr/include *before* compiling,
  64. Xyou'll have to add "-I." to CFLAGS before compiling.
  65. X
  66. XThe files are:
  67. X
  68. XMakefile    instructions to make everything
  69. Xregexp.3    manual page
  70. Xregexp.h    header file, for /usr/include
  71. Xregexp.c    source for regcomp() and regexec()
  72. Xregsub.c    source for regsub()
  73. Xregerror.c    source for default regerror()
  74. Xregmagic.h    internal header file
  75. Xtry.c        source for test program
  76. Xtimer.c        source for timing program
  77. Xtests        test list for try and timer
  78. X
  79. XThis implementation uses nondeterministic automata rather than the
  80. Xdeterministic ones found in some other implementations, which makes it
  81. Xsimpler, smaller, and faster at compiling regular expressions, but slower
  82. Xat executing them.  In theory, anyway.  This implementation does employ
  83. Xsome special-case optimizations to make the simpler cases (which do make
  84. Xup the bulk of regular expressions actually used) run quickly.  In general,
  85. Xif you want blazing speed you're in the wrong place.  Replacing the insides
  86. Xof egrep with this stuff is probably a mistake; if you want your own egrep
  87. Xyou're going to have to do a lot more work.  But if you want to use regular
  88. Xexpressions a little bit in something else, you're in luck.  Note that many
  89. Xexisting text editors use nondeterministic regular-expression implementations,
  90. Xso you're in good company.
  91. X
  92. XThis stuff should be pretty portable, given appropriate option settings.
  93. XIf your chars have less than 8 bits, you're going to have to change the
  94. Xinternal representation of the automaton, although knowledge of the details
  95. Xof this is fairly localized.  There are no "reserved" char values except for
  96. XNUL, and no special significance is attached to the top bit of chars.
  97. XThe string(3) functions are used a fair bit, on the grounds that they are
  98. Xprobably faster than coding the operations in line.  Some attempts at code
  99. Xtuning have been made, but this is invariably a bit machine-specific.
  100. !
  101. echo Makefile:
  102. sed 's/^X//' >Makefile <<'!'
  103. X# Things you might want to put in ENV and LENV:
  104. X# -Dvoid=int        compilers that don't do void
  105. X# -DCHARBITS=0377    compilers that don't do unsigned char
  106. X# -DSTATIC=extern    compilers that don't like "static foo();" as forward decl
  107. X# -DSTRCSPN        library does not have strcspn()
  108. X# -Dstrchr=index    library does not have strchr()
  109. X# -DERRAVAIL        have utzoo-compatible error() function and friends
  110. XENV=-Dvoid=int -DCHARBITS=0377 -DSTATIC=extern
  111. XLENV=-Dvoid=int -DCHARBITS=0377
  112. X
  113. X# Things you might want to put in TEST:
  114. X# -DDEBUG        debugging hooks
  115. X# -I.            regexp.h from current directory, not /usr/include
  116. XTEST=
  117. X
  118. X# Things you might want to put in PROF:
  119. X# -Dstatic='/* */'    make everything global so profiler can see it.
  120. X# -p            profiler
  121. XPROF=
  122. X
  123. XCFLAGS=-O $(ENV) $(TEST) $(PROF)
  124. XLINTFLAGS=$(LENV) $(TEST) -ha
  125. XLDFLAGS=-i
  126. X
  127. XOBJ=regexp.o regsub.o
  128. XLSRC=regexp.c regsub.c regerror.c
  129. XDTR=README dMakefile regexp.3 regexp.h regexp.c regsub.c regerror.c \
  130. X    regmagic.h try.c timer.c tests
  131. X
  132. Xtry:    try.o $(OBJ)
  133. X    cc $(LDFLAGS) try.o $(OBJ) -o try
  134. X
  135. X# Making timer will probably require putting stuff in $(PROF) and then
  136. X# recompiling everything; the following is just the final stage.
  137. Xtimer:    timer.o $(OBJ)
  138. X    cc $(LDFLAGS) $(PROF) timer.o $(OBJ) -o timer
  139. X
  140. Xtimer.o:    timer.c timer.t.h
  141. X
  142. Xtimer.t.h:    tests
  143. X    sed 's/    /","/g;s/\\/&&/g;s/.*/{"&"},/' tests >timer.t.h
  144. X
  145. X# Regression test.
  146. Xr:    try tests
  147. X    @echo 'No news is good news...'
  148. X    try <tests
  149. X
  150. Xlint:    timer.t.h
  151. X    @echo 'Complaints about multiply-declared regerror() are legit.'
  152. X    lint $(LINTFLAGS) $(LSRC) try.c
  153. X    lint $(LINTFLAGS) $(LSRC) timer.c
  154. X
  155. Xregexp.o:    regexp.c regexp.h regmagic.h
  156. Xregsub.o:    regsub.c regexp.h regmagic.h
  157. X
  158. Xclean:
  159. X    rm -f *.o core mon.out timer.t.h dMakefile dtr try timer
  160. X
  161. Xdtr:    r makedtr $(DTR)
  162. X    makedtr $(DTR) >dtr
  163. X
  164. XdMakefile:    Makefile
  165. X    sed '/^L*ENV=/s/ *-DERRAVAIL//' Makefile >dMakefile
  166. !
  167. echo regexp.3:
  168. sed 's/^X//' >regexp.3 <<'!'
  169. X.TH REGEXP 3 local
  170. X.DA 30 Nov 1985
  171. X.SH NAME
  172. Xregcomp, regexec, regsub, regerror \- regular expression handler
  173. X.SH SYNOPSIS
  174. X.ft B
  175. X.nf
  176. X#include <regexp.h>
  177. X
  178. Xregexp *regcomp(exp)
  179. Xchar *exp;
  180. X
  181. Xint regexec(prog, string)
  182. Xregexp *prog;
  183. Xchar *string;
  184. X
  185. Xregsub(prog, source, dest)
  186. Xregexp *prog;
  187. Xchar *source;
  188. Xchar *dest;
  189. X
  190. Xregerror(msg)
  191. Xchar *msg;
  192. X.SH DESCRIPTION
  193. XThese functions implement
  194. X.IR egrep (1)-style
  195. Xregular expressions and supporting facilities.
  196. X.PP
  197. X.I Regcomp
  198. Xcompiles a regular expression into a structure of type
  199. X.IR regexp ,
  200. Xand returns a pointer to it.
  201. XThe space has been allocated using
  202. X.IR malloc (3)
  203. Xand may be released by
  204. X.IR free .
  205. X.PP
  206. X.I Regexec
  207. Xmatches a NUL-terminated \fIstring\fR against the compiled regular expression
  208. Xin \fIprog\fR.
  209. XIt returns 1 for success and 0 for failure, and adjusts the contents of
  210. X\fIprog\fR's \fIstartp\fR and \fIendp\fR (see below) accordingly.
  211. X.PP
  212. XThe members of a
  213. X.I regexp
  214. Xstructure include at least the following (not necessarily in order):
  215. X.PP
  216. X.RS
  217. Xchar *startp[NSUBEXP];
  218. X.br
  219. Xchar *endp[NSUBEXP];
  220. X.RE
  221. X.PP
  222. Xwhere
  223. X.I NSUBEXP
  224. Xis defined (as 10) in the header file.
  225. XOnce a successful \fIregexec\fR has been done using the \fIregexp\fR,
  226. Xeach \fIstartp\fR-\fIendp\fR pair describes one substring
  227. Xwithin the \fIstring\fR,
  228. Xwith the \fIstartp\fR pointing to the first character of the substring and
  229. Xthe \fIendp\fR pointing to the first character following the substring.
  230. XThe 0th substring is the substring of \fIstring\fR that matched the whole
  231. Xregular expression.
  232. XThe others are those substrings that matched parenthesized expressions
  233. Xwithin the regular expression, with parenthesized expressions numbered
  234. Xin left-to-right order of their opening parentheses.
  235. X.PP
  236. X.I Regsub
  237. Xcopies \fIsource\fR to \fIdest\fR, making substitutions according to the
  238. Xmost recent \fIregexec\fR performed using \fIprog\fR.
  239. XEach instance of `&' in \fIsource\fR is replaced by the substring
  240. Xindicated by \fIstartp\fR[\fI0\fR] and
  241. X\fIendp\fR[\fI0\fR].
  242. XEach instance of `\e\fIn\fR', where \fIn\fR is a digit, is replaced by
  243. Xthe substring indicated by
  244. X\fIstartp\fR[\fIn\fR] and
  245. X\fIendp\fR[\fIn\fR].
  246. X.PP
  247. X.I Regerror
  248. Xis called whenever an error is detected in \fIregcomp\fR, \fIregexec\fR,
  249. Xor \fIregsub\fR.
  250. XThe default \fIregerror\fR writes the string \fImsg\fR,
  251. Xwith a suitable indicator of origin,
  252. Xon the standard
  253. Xerror output
  254. Xand invokes \fIexit\fR(2).
  255. X.I Regerror
  256. Xcan be replaced by the user if other actions are desirable.
  257. X.SH "REGULAR EXPRESSION SYNTAX"
  258. XA regular expression is zero or more \fIbranches\fR, separated by `|'.
  259. XIt matches anything that matches one of the branches.
  260. X.PP
  261. XA branch is zero or more \fIpieces\fR, concatenated.
  262. XIt matches a match for the first, followed by a match for the second, etc.
  263. X.PP
  264. XA piece is an \fIatom\fR possibly followed by `*', `+', or `?'.
  265. XAn atom followed by `*' matches a sequence of 0 or more matches of the atom.
  266. XAn atom followed by `+' matches a sequence of 1 or more matches of the atom.
  267. XAn atom followed by `?' matches a match of the atom, or the null string.
  268. X.PP
  269. XAn atom is a regular expression in parentheses (matching a match for the
  270. Xregular expression), a \fIrange\fR (see below), `.'
  271. X(matching any single character), `^' (matching the null string at the
  272. Xbeginning of the input string), `$' (matching the null string at the
  273. Xend of the input string), a `\e' followed by a single character (matching
  274. Xthat character), or a single character with no other significance
  275. X(matching that character).
  276. X.PP
  277. XA \fIrange\fR is a sequence of characters enclosed in `[]'.
  278. XIt normally matches any single character from the sequence.
  279. XIf the sequence begins with `^',
  280. Xit matches any single character \fInot\fR from the rest of the sequence.
  281. XIf two characters in the sequence are separated by `\-', this is shorthand
  282. Xfor the full list of ASCII characters between them
  283. X(e.g. `[0-9]' matches any decimal digit).
  284. XTo include a literal `]' in the sequence, make it the first character
  285. X(following a possible `^').
  286. XTo include a literal `\-', make it the first or last character.
  287. X.SH AMBIGUITY
  288. XIf a regular expression could match two different parts of the input string,
  289. Xit will match the one which begins earliest.
  290. XIf both begin in the same place    but match different lengths, or match
  291. Xthe same length in different ways, life gets messier, as follows.
  292. X.PP
  293. XIn general, the possibilities in a list of branches are considered in
  294. Xleft-to-right order, the possibilities for `*', `+', and `?' are
  295. Xconsidered longest-first, nested constructs are considered from the
  296. Xoutermost in, and concatenated constructs are considered leftmost-first.
  297. XThe match that will be chosen is the one that uses the earliest
  298. Xpossibility in the first choice that has to be made.
  299. XIf there is more than one choice, the next will be made in the same manner
  300. X(earliest possibility) subject to the decision on the first choice.
  301. XAnd so forth.
  302. X.PP
  303. XFor example, `(ab|a)b*c' could match `abc' in one of two ways.
  304. XThe first choice is between `ab' and `a'; since `ab' is earlier, and does
  305. Xlead to a successful overall match, it is chosen.
  306. XSince the `b' is already spoken for,
  307. Xthe `b*' must match its last possibility\(emthe empty string\(emsince
  308. Xit must respect the earlier choice.
  309. X.PP
  310. XIn the particular case where no `|'s are present and there is only one
  311. X`*', `+', or `?', the net effect is that the longest possible
  312. Xmatch will be chosen.
  313. XSo `ab*', presented with `xabbbby', will match `abbbb'.
  314. XNote that if `ab*' is tried against `xabyabbbz', it
  315. Xwill match `ab' just after `x', due to the begins-earliest rule.
  316. X(In effect, the decision on where to start the match is the first choice
  317. Xto be made, hence subsequent choices must respect it even if this leads them
  318. Xto less-preferred alternatives.)
  319. X.SH SEE ALSO
  320. Xegrep(1), expr(1)
  321. X.SH DIAGNOSTICS
  322. X\fIRegcomp\fR returns NULL for a failure
  323. X(\fIregerror\fR permitting),
  324. Xwhere failures are syntax errors, exceeding implementation limits,
  325. Xor applying `+' or `*' to a possibly-null operand.
  326. X.SH HISTORY
  327. XBoth code and manual page were
  328. Xwritten at U of T.
  329. XThey are intended to be compatible with the Bell V8 \fIregexp\fR(3),
  330. Xbut are not derived from Bell code.
  331. X.SH BUGS
  332. XEmpty branches and empty regular expressions are not portable to V8.
  333. X.PP
  334. XThe restriction against
  335. Xapplying `*' or `+' to a possibly-null operand is an artifact of the
  336. Xsimplistic implementation.
  337. X.PP
  338. XDoes not support \fIegrep\fR's newline-separated branches;
  339. Xneither does the V8 \fIregexp\fR(3), though.
  340. X.PP
  341. XDue to emphasis on
  342. Xcompactness and simplicity,
  343. Xit's not strikingly fast.
  344. XIt does give special attention to handling simple cases quickly.
  345. !
  346. echo regexp.h:
  347. sed 's/^X//' >regexp.h <<'!'
  348. X/*
  349. X * Definitions etc. for regexp(3) routines.
  350. X *
  351. X * Caveat:  this is V8 regexp(3) [actually, a reimplementation thereof],
  352. X * not the System V one.
  353. X */
  354. X#define NSUBEXP  10
  355. Xtypedef struct regexp {
  356. X    char *startp[NSUBEXP];
  357. X    char *endp[NSUBEXP];
  358. X    char regstart;        /* Internal use only. */
  359. X    char reganch;        /* Internal use only. */
  360. X    char *regmust;        /* Internal use only. */
  361. X    int regmlen;        /* Internal use only. */
  362. X    char program[1];    /* Unwarranted chumminess with compiler. */
  363. X} regexp;
  364. X
  365. Xextern regexp *regcomp();
  366. Xextern int regexec();
  367. Xextern void regsub();
  368. Xextern void regerror();
  369. !
  370. echo regexp.c:
  371. sed 's/^X//' >regexp.c <<'!'
  372. X/*
  373. X * regcomp and regexec -- regsub and regerror are elsewhere
  374. X *
  375. X *    Copyright (c) 1986 by University of Toronto.
  376. X *    Written by Henry Spencer.  Not derived from licensed software.
  377. X *
  378. X *    Permission is granted to anyone to use this software for any
  379. X *    purpose on any computer system, and to redistribute it freely,
  380. X *    subject to the following restrictions:
  381. X *
  382. X *    1. The author is not responsible for the consequences of use of
  383. X *        this software, no matter how awful, even if they arise
  384. X *        from defects in it.
  385. X *
  386. X *    2. The origin of this software must not be misrepresented, either
  387. X *        by explicit claim or by omission.
  388. X *
  389. X *    3. Altered versions must be plainly marked as such, and must not
  390. X *        be misrepresented as being the original software.
  391. X *
  392. X * Beware that some of this code is subtly aware of the way operator
  393. X * precedence is structured in regular expressions.  Serious changes in
  394. X * regular-expression syntax might require a total rethink.
  395. X */
  396. X#include <stdio.h>
  397. X#include <regexp.h>
  398. X#include "regmagic.h"
  399. X
  400. X/*
  401. X * The "internal use only" fields in regexp.h are present to pass info from
  402. X * compile to execute that permits the execute phase to run lots faster on
  403. X * simple cases.  They are:
  404. X *
  405. X * regstart    char that must begin a match; '\0' if none obvious
  406. X * reganch    is the match anchored (at beginning-of-line only)?
  407. X * regmust    string (pointer into program) that match must include, or NULL
  408. X * regmlen    length of regmust string
  409. X *
  410. X * Regstart and reganch permit very fast decisions on suitable starting points
  411. X * for a match, cutting down the work a lot.  Regmust permits fast rejection
  412. X * of lines that cannot possibly match.  The regmust tests are costly enough
  413. X * that regcomp() supplies a regmust only if the r.e. contains something
  414. X * potentially expensive (at present, the only such thing detected is * or +
  415. X * at the start of the r.e., which can involve a lot of backup).  Regmlen is
  416. X * supplied because the test in regexec() needs it and regcomp() is computing
  417. X * it anyway.
  418. X */
  419. X
  420. X/*
  421. X * Structure for regexp "program".  This is essentially a linear encoding
  422. X * of a nondeterministic finite-state machine (aka syntax charts or
  423. X * "railroad normal form" in parsing technology).  Each node is an opcode
  424. X * plus a "next" pointer, possibly plus an operand.  "Next" pointers of
  425. X * all nodes except BRANCH implement concatenation; a "next" pointer with
  426. X * a BRANCH on both ends of it is connecting two alternatives.  (Here we
  427. X * have one of the subtle syntax dependencies:  an individual BRANCH (as
  428. X * opposed to a collection of them) is never concatenated with anything
  429. X * because of operator precedence.)  The operand of some types of node is
  430. X * a literal string; for others, it is a node leading into a sub-FSM.  In
  431. X * particular, the operand of a BRANCH node is the first node of the branch.
  432. X * (NB this is *not* a tree structure:  the tail of the branch connects
  433. X * to the thing following the set of BRANCHes.)  The opcodes are:
  434. X */
  435. X
  436. X/* definition    number    opnd?    meaning */
  437. X#define    END    0    /* no    End of program. */
  438. X#define    BOL    1    /* no    Match "" at beginning of line. */
  439. X#define    EOL    2    /* no    Match "" at end of line. */
  440. X#define    ANY    3    /* no    Match any one character. */
  441. X#define    ANYOF    4    /* str    Match any character in this string. */
  442. X#define    ANYBUT    5    /* str    Match any character not in this string. */
  443. X#define    BRANCH    6    /* node    Match this alternative, or the next... */
  444. X#define    BACK    7    /* no    Match "", "next" ptr points backward. */
  445. X#define    EXACTLY    8    /* str    Match this string. */
  446. X#define    NOTHING    9    /* no    Match empty string. */
  447. X#define    STAR    10    /* node    Match this (simple) thing 0 or more times. */
  448. X#define    PLUS    11    /* node    Match this (simple) thing 1 or more times. */
  449. X#define    OPEN    20    /* no    Mark this point in input as start of #n. */
  450. X            /*    OPEN+1 is number 1, etc. */
  451. X#define    CLOSE    30    /* no    Analogous to OPEN. */
  452. X
  453. X/*
  454. X * Opcode notes:
  455. X *
  456. X * BRANCH    The set of branches constituting a single choice are hooked
  457. X *        together with their "next" pointers, since precedence prevents
  458. X *        anything being concatenated to any individual branch.  The
  459. X *        "next" pointer of the last BRANCH in a choice points to the
  460. X *        thing following the whole choice.  This is also where the
  461. X *        final "next" pointer of each individual branch points; each
  462. X *        branch starts with the operand node of a BRANCH node.
  463. X *
  464. X * BACK        Normal "next" pointers all implicitly point forward; BACK
  465. X *        exists to make loop structures possible.
  466. X *
  467. X * STAR,PLUS    '?', and complex '*' and '+', are implemented as circular
  468. X *        BRANCH structures using BACK.  Simple cases (one character
  469. X *        per match) are implemented with STAR and PLUS for speed
  470. X *        and to minimize recursive plunges.
  471. X *
  472. X * OPEN,CLOSE    ...are numbered at compile time.
  473. X */
  474. X
  475. X/*
  476. X * A node is one char of opcode followed by two chars of "next" pointer.
  477. X * "Next" pointers are stored as two 8-bit pieces, high order first.  The
  478. X * value is a positive offset from the opcode of the node containing it.
  479. X * An operand, if any, simply follows the node.  (Note that much of the
  480. X * code generation knows about this implicit relationship.)
  481. X *
  482. X * Using two bytes for the "next" pointer is vast overkill for most things,
  483. X * but allows patterns to get big without disasters.
  484. X */
  485. X#define    OP(p)    (*(p))
  486. X#define    NEXT(p)    (((*((p)+1)&0377)<<8) + *((p)+2)&0377)
  487. X#define    OPERAND(p)    ((p) + 3)
  488. X
  489. X/*
  490. X * See regmagic.h for one further detail of program structure.
  491. X */
  492. X
  493. X
  494. X/*
  495. X * Utility definitions.
  496. X */
  497. X#ifndef CHARBITS
  498. X#define    UCHARAT(p)    ((int)*(unsigned char *)(p))
  499. X#else
  500. X#define    UCHARAT(p)    ((int)*(p)&CHARBITS)
  501. X#endif
  502. X
  503. X#define    FAIL(m)    { regerror(m); return(NULL); }
  504. X#define    ISMULT(c)    ((c) == '*' || (c) == '+' || (c) == '?')
  505. X#define    META    "^$.[()|?+*\\"
  506. X
  507. X/*
  508. X * Flags to be passed up and down.
  509. X */
  510. X#define    HASWIDTH    01    /* Known never to match null string. */
  511. X#define    SIMPLE        02    /* Simple enough to be STAR/PLUS operand. */
  512. X#define    SPSTART        04    /* Starts with * or +. */
  513. X#define    WORST        0    /* Worst case. */
  514. X
  515. X/*
  516. X * Global work variables for regcomp().
  517. X */
  518. Xstatic char *regparse;        /* Input-scan pointer. */
  519. Xstatic int regnpar;        /* () count. */
  520. Xstatic char regdummy;
  521. Xstatic char *regcode;        /* Code-emit pointer; ®dummy = don't. */
  522. Xstatic long regsize;        /* Code size. */
  523. X
  524. X/*
  525. X * Forward declarations for regcomp()'s friends.
  526. X */
  527. X#ifndef STATIC
  528. X#define    STATIC    static
  529. X#endif
  530. XSTATIC char *reg();
  531. XSTATIC char *regbranch();
  532. XSTATIC char *regpiece();
  533. XSTATIC char *regatom();
  534. XSTATIC char *regnode();
  535. XSTATIC char *regnext();
  536. XSTATIC void regc();
  537. XSTATIC void reginsert();
  538. XSTATIC void regtail();
  539. XSTATIC void regoptail();
  540. X#ifdef STRCSPN
  541. XSTATIC int strcspn();
  542. X#endif
  543. X
  544. X/*
  545. X - regcomp - compile a regular expression into internal code
  546. X *
  547. X * We can't allocate space until we know how big the compiled form will be,
  548. X * but we can't compile it (and thus know how big it is) until we've got a
  549. X * place to put the code.  So we cheat:  we compile it twice, once with code
  550. X * generation turned off and size counting turned on, and once "for real".
  551. X * This also means that we don't allocate space until we are sure that the
  552. X * thing really will compile successfully, and we never have to move the
  553. X * code and thus invalidate pointers into it.  (Note that it has to be in
  554. X * one piece because free() must be able to free it all.)
  555. X *
  556. X * Beware that the optimization-preparation code in here knows about some
  557. X * of the structure of the compiled regexp.
  558. X */
  559. Xregexp *
  560. Xregcomp(exp)
  561. Xchar *exp;
  562. X{
  563. X    register regexp *r;
  564. X    register char *scan;
  565. X    register char *longest;
  566. X    register int len;
  567. X    int flags;
  568. X    extern char *malloc();
  569. X
  570. X    if (exp == NULL)
  571. X        FAIL("NULL argument");
  572. X
  573. X    /* First pass: determine size, legality. */
  574. X    regparse = exp;
  575. X    regnpar = 1;
  576. X    regsize = 0L;
  577. X    regcode = ®dummy;
  578. X    regc(MAGIC);
  579. X    if (reg(0, &flags) == NULL)
  580. X        return(NULL);
  581. X
  582. X    /* Small enough for pointer-storage convention? */
  583. X    if (regsize >= 32767L)        /* Probably could be 65535L. */
  584. X        FAIL("regexp too big");
  585. X
  586. X    /* Allocate space. */
  587. X    r = (regexp *)malloc(sizeof(regexp) + (unsigned)regsize);
  588. X    if (r == NULL)
  589. X        FAIL("out of space");
  590. X
  591. X    /* Second pass: emit code. */
  592. X    regparse = exp;
  593. X    regnpar = 1;
  594. X    regcode = r->program;
  595. X    regc(MAGIC);
  596. X    if (reg(0, &flags) == NULL)
  597. X        return(NULL);
  598. X
  599. X    /* Dig out information for optimizations. */
  600. X    r->regstart = '\0';    /* Worst-case defaults. */
  601. X    r->reganch = 0;
  602. X    r->regmust = NULL;
  603. X    r->regmlen = 0;
  604. X    scan = r->program+1;            /* First BRANCH. */
  605. X    if (OP(regnext(scan)) == END) {        /* Only one top-level choice. */
  606. X        scan = OPERAND(scan);
  607. X
  608. X        /* Starting-point info. */
  609. X        if (OP(scan) == EXACTLY)
  610. X            r->regstart = *OPERAND(scan);
  611. X        else if (OP(scan) == BOL)
  612. X            r->reganch++;
  613. X
  614. X        /*
  615. X         * If there's something expensive in the r.e., find the
  616. X         * longest literal string that must appear and make it the
  617. X         * regmust.  Resolve ties in favor of later strings, since
  618. X         * the regstart check works with the beginning of the r.e.
  619. X         * and avoiding duplication strengthens checking.  Not a
  620. X         * strong reason, but sufficient in the absence of others.
  621. X         */
  622. X        if (flags&SPSTART) {
  623. X            longest = NULL;
  624. X            len = 0;
  625. X            for (; scan != NULL; scan = regnext(scan))
  626. X                if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= len) {
  627. X                    longest = OPERAND(scan);
  628. X                    len = strlen(OPERAND(scan));
  629. X                }
  630. X            r->regmust = longest;
  631. X            r->regmlen = len;
  632. X        }
  633. X    }
  634. X
  635. X    return(r);
  636. X}
  637. X
  638. X/*
  639. X - reg - regular expression, i.e. main body or parenthesized thing
  640. X *
  641. X * Caller must absorb opening parenthesis.
  642. X *
  643. X * Combining parenthesis handling with the base level of regular expression
  644. X * is a trifle forced, but the need to tie the tails of the branches to what
  645. X * follows makes it hard to avoid.
  646. X */
  647. Xstatic char *
  648. Xreg(paren, flagp)
  649. Xint paren;            /* Parenthesized? */
  650. Xint *flagp;
  651. X{
  652. X    register char *ret;
  653. X    register char *br;
  654. X    register char *ender;
  655. X    register int parno;
  656. X    int flags;
  657. X
  658. X    *flagp = HASWIDTH;    /* Tentatively. */
  659. X
  660. X    /* Make an OPEN node, if parenthesized. */
  661. X    if (paren) {
  662. X        if (regnpar >= NSUBEXP)
  663. X            FAIL("too many ()");
  664. X        parno = regnpar;
  665. X        regnpar++;
  666. X        ret = regnode(OPEN+parno);
  667. X    } else
  668. X        ret = NULL;
  669. X
  670. X    /* Pick up the branches, linking them together. */
  671. X    br = regbranch(&flags);
  672. X    if (br == NULL)
  673. X        return(NULL);
  674. X    if (ret != NULL)
  675. X        regtail(ret, br);    /* OPEN -> first. */
  676. X    else
  677. X        ret = br;
  678. X    if (!(flags&HASWIDTH))
  679. X        *flagp &= ~HASWIDTH;
  680. X    *flagp |= flags&SPSTART;
  681. X    while (*regparse == '|') {
  682. X        regparse++;
  683. X        br = regbranch(&flags);
  684. X        if (br == NULL)
  685. X            return(NULL);
  686. X        regtail(ret, br);    /* BRANCH -> BRANCH. */
  687. X        if (!(flags&HASWIDTH))
  688. X            *flagp &= ~HASWIDTH;
  689. X        *flagp |= flags&SPSTART;
  690. X    }
  691. X
  692. X    /* Make a closing node, and hook it on the end. */
  693. X    ender = regnode((paren) ? CLOSE+parno : END);    
  694. X    regtail(ret, ender);
  695. X
  696. X    /* Hook the tails of the branches to the closing node. */
  697. X    for (br = ret; br != NULL; br = regnext(br))
  698. X        regoptail(br, ender);
  699. X
  700. X    /* Check for proper termination. */
  701. X    if (paren && *regparse++ != ')') {
  702. X        FAIL("unmatched ()");
  703. X    } else if (!paren && *regparse != '\0') {
  704. X        if (*regparse == ')') {
  705. X            FAIL("unmatched ()");
  706. X        } else
  707. X            FAIL("junk on end");    /* "Can't happen". */
  708. X        /* NOTREACHED */
  709. X    }
  710. X
  711. X    return(ret);
  712. X}
  713. X
  714. X/*
  715. X - regbranch - one alternative of an | operator
  716. X *
  717. X * Implements the concatenation operator.
  718. X */
  719. Xstatic char *
  720. Xregbranch(flagp)
  721. Xint *flagp;
  722. X{
  723. X    register char *ret;
  724. X    register char *chain;
  725. X    register char *latest;
  726. X    int flags;
  727. X
  728. X    *flagp = WORST;        /* Tentatively. */
  729. X
  730. X    ret = regnode(BRANCH);
  731. X    chain = NULL;
  732. X    while (*regparse != '\0' && *regparse != '|' && *regparse != ')') {
  733. X        latest = regpiece(&flags);
  734. X        if (latest == NULL)
  735. X            return(NULL);
  736. X        *flagp |= flags&HASWIDTH;
  737. X        if (chain == NULL)    /* First piece. */
  738. X            *flagp |= flags&SPSTART;
  739. X        else
  740. X            regtail(chain, latest);
  741. X        chain = latest;
  742. X    }
  743. X    if (chain == NULL)    /* Loop ran zero times. */
  744. X        (void) regnode(NOTHING);
  745. X
  746. X    return(ret);
  747. X}
  748. X
  749. X/*
  750. X - regpiece - something followed by possible [*+?]
  751. X *
  752. X * Note that the branching code sequences used for ? and the general cases
  753. X * of * and + are somewhat optimized:  they use the same NOTHING node as
  754. X * both the endmarker for their branch list and the body of the last branch.
  755. X * It might seem that this node could be dispensed with entirely, but the
  756. X * endmarker role is not redundant.
  757. X */
  758. Xstatic char *
  759. Xregpiece(flagp)
  760. Xint *flagp;
  761. X{
  762. X    register char *ret;
  763. X    register char op;
  764. X    register char *next;
  765. X    int flags;
  766. X
  767. X    ret = regatom(&flags);
  768. X    if (ret == NULL)
  769. X        return(NULL);
  770. X
  771. X    op = *regparse;
  772. X    if (!ISMULT(op)) {
  773. X        *flagp = flags;
  774. X        return(ret);
  775. X    }
  776. X
  777. X    if (!(flags&HASWIDTH) && op != '?')
  778. X        FAIL("*+ operand could be empty");
  779. X    *flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH);
  780. X
  781. X    if (op == '*' && (flags&SIMPLE))
  782. X        reginsert(STAR, ret);
  783. X    else if (op == '*') {
  784. X        /* Emit x* as (x&|), where & means "self". */
  785. X        reginsert(BRANCH, ret);            /* Either x */
  786. X        regoptail(ret, regnode(BACK));        /* and loop */
  787. X        regoptail(ret, ret);            /* back */
  788. X        regtail(ret, regnode(BRANCH));        /* or */
  789. X        regtail(ret, regnode(NOTHING));        /* null. */
  790. X    } else if (op == '+' && (flags&SIMPLE))
  791. X        reginsert(PLUS, ret);
  792. X    else if (op == '+') {
  793. X        /* Emit x+ as x(&|), where & means "self". */
  794. X        next = regnode(BRANCH);            /* Either */
  795. X        regtail(ret, next);
  796. X        regtail(regnode(BACK), ret);        /* loop back */
  797. X        regtail(next, regnode(BRANCH));        /* or */
  798. X        regtail(ret, regnode(NOTHING));        /* null. */
  799. X    } else if (op == '?') {
  800. X        /* Emit x? as (x|) */
  801. X        reginsert(BRANCH, ret);            /* Either x */
  802. X        regtail(ret, regnode(BRANCH));        /* or */
  803. X        next = regnode(NOTHING);        /* null. */
  804. X        regtail(ret, next);
  805. X        regoptail(ret, next);
  806. X    }
  807. X    regparse++;
  808. X    if (ISMULT(*regparse))
  809. X        FAIL("nested *?+");
  810. X
  811. X    return(ret);
  812. X}
  813. X
  814. X/*
  815. X - regatom - the lowest level
  816. X *
  817. X * Optimization:  gobbles an entire sequence of ordinary characters so that
  818. X * it can turn them into a single node, which is smaller to store and
  819. X * faster to run.  Backslashed characters are exceptions, each becoming a
  820. X * separate node; the code is simpler that way and it's not worth fixing.
  821. X */
  822. Xstatic char *
  823. Xregatom(flagp)
  824. Xint *flagp;
  825. X{
  826. X    register char *ret;
  827. X    int flags;
  828. X
  829. X    *flagp = WORST;        /* Tentatively. */
  830. X
  831. X    switch (*regparse++) {
  832. X    case '^':
  833. X        ret = regnode(BOL);
  834. X        break;
  835. X    case '$':
  836. X        ret = regnode(EOL);
  837. X        break;
  838. X    case '.':
  839. X        ret = regnode(ANY);
  840. X        *flagp |= HASWIDTH|SIMPLE;
  841. X        break;
  842. X    case '[': {
  843. X            register int class;
  844. X            register int classend;
  845. X
  846. X            if (*regparse == '^') {    /* Complement of range. */
  847. X                ret = regnode(ANYBUT);
  848. X                regparse++;
  849. X            } else
  850. X                ret = regnode(ANYOF);
  851. X            if (*regparse == ']' || *regparse == '-')
  852. X                regc(*regparse++);
  853. X            while (*regparse != '\0' && *regparse != ']') {
  854. X                if (*regparse == '-') {
  855. X                    regparse++;
  856. X                    if (*regparse == ']' || *regparse == '\0')
  857. X                        regc('-');
  858. X                    else {
  859. X                        class = UCHARAT(regparse-2)+1;
  860. X                        classend = UCHARAT(regparse);
  861. X                        if (class > classend+1)
  862. X                            FAIL("invalid [] range");
  863. X                        for (; class <= classend; class++)
  864. X                            regc(class);
  865. X                        regparse++;
  866. X                    }
  867. X                } else
  868. X                    regc(*regparse++);
  869. X            }
  870. X            regc('\0');
  871. X            if (*regparse != ']')
  872. X                FAIL("unmatched []");
  873. X            regparse++;
  874. X            *flagp |= HASWIDTH|SIMPLE;
  875. X        }
  876. X        break;
  877. X    case '(':
  878. X        ret = reg(1, &flags);
  879. X        if (ret == NULL)
  880. X            return(NULL);
  881. X        *flagp |= flags&(HASWIDTH|SPSTART);
  882. X        break;
  883. X    case '\0':
  884. X    case '|':
  885. X    case ')':
  886. X        FAIL("internal urp");    /* Supposed to be caught earlier. */
  887. X        break;
  888. X    case '?':
  889. X    case '+':
  890. X    case '*':
  891. X        FAIL("?+* follows nothing");
  892. X        break;
  893. X    case '\\':
  894. X        if (*regparse == '\0')
  895. X            FAIL("trailing \\");
  896. X        ret = regnode(EXACTLY);
  897. X        regc(*regparse++);
  898. X        regc('\0');
  899. X        *flagp |= HASWIDTH|SIMPLE;
  900. X        break;
  901. X    default: {
  902. X            register int len;
  903. X            register char ender;
  904. X
  905. X            regparse--;
  906. X            len = strcspn(regparse, META);
  907. X            if (len <= 0)
  908. X                FAIL("internal disaster");
  909. X            ender = *(regparse+len);
  910. X            if (len > 1 && ISMULT(ender))
  911. X                len--;        /* Back off clear of ?+* operand. */
  912. X            *flagp |= HASWIDTH;
  913. X            if (len == 1)
  914. X                *flagp |= SIMPLE;
  915. X            ret = regnode(EXACTLY);
  916. X            while (len > 0) {
  917. X                regc(*regparse++);
  918. X                len--;
  919. X            }
  920. X            regc('\0');
  921. X        }
  922. X        break;
  923. X    }
  924. X
  925. X    return(ret);
  926. X}
  927. X
  928. X/*
  929. X - regnode - emit a node
  930. X */
  931. Xstatic char *            /* Location. */
  932. Xregnode(op)
  933. Xchar op;
  934. X{
  935. X    register char *ret;
  936. X    register char *ptr;
  937. X
  938. X    ret = regcode;
  939. X    if (ret == ®dummy) {
  940. X        regsize += 3;
  941. X        return(ret);
  942. X    }
  943. X
  944. X    ptr = ret;
  945. X    *ptr++ = op;
  946. X    *ptr++ = '\0';        /* Null "next" pointer. */
  947. X    *ptr++ = '\0';
  948. X    regcode = ptr;
  949. X
  950. X    return(ret);
  951. X}
  952. X
  953. X/*
  954. X - regc - emit (if appropriate) a byte of code
  955. X */
  956. Xstatic void
  957. Xregc(b)
  958. Xchar b;
  959. X{
  960. X    if (regcode != ®dummy)
  961. X        *regcode++ = b;
  962. X    else
  963. X        regsize++;
  964. X}
  965. X
  966. X/*
  967. X - reginsert - insert an operator in front of already-emitted operand
  968. X *
  969. X * Means relocating the operand.
  970. X */
  971. Xstatic void
  972. Xreginsert(op, opnd)
  973. Xchar op;
  974. Xchar *opnd;
  975. X{
  976. X    register char *src;
  977. X    register char *dst;
  978. X    register char *place;
  979. X
  980. X    if (regcode == ®dummy) {
  981. X        regsize += 3;
  982. X        return;
  983. X    }
  984. X
  985. X    src = regcode;
  986. X    regcode += 3;
  987. X    dst = regcode;
  988. X    while (src > opnd)
  989. X        *--dst = *--src;
  990. X
  991. X    place = opnd;        /* Op node, where operand used to be. */
  992. X    *place++ = op;
  993. X    *place++ = '\0';
  994. X    *place++ = '\0';
  995. X}
  996. X
  997. X/*
  998. X - regtail - set the next-pointer at the end of a node chain
  999. X */
  1000. Xstatic void
  1001. Xregtail(p, val)
  1002. Xchar *p;
  1003. Xchar *val;
  1004. X{
  1005. X    register char *scan;
  1006. X    register char *temp;
  1007. X    register int offset;
  1008. X
  1009. X    if (p == ®dummy)
  1010. X        return;
  1011. X
  1012. X    /* Find last node. */
  1013. X    scan = p;
  1014. X    for (;;) {
  1015. X        temp = regnext(scan);
  1016. X        if (temp == NULL)
  1017. X            break;
  1018. X        scan = temp;
  1019. X    }
  1020. X
  1021. X    if (OP(scan) == BACK)
  1022. X        offset = scan - val;
  1023. X    else
  1024. X        offset = val - scan;
  1025. X    *(scan+1) = (offset>>8)&0377;
  1026. X    *(scan+2) = offset&0377;
  1027. X}
  1028. X
  1029. X/*
  1030. X - regoptail - regtail on operand of first argument; nop if operandless
  1031. X */
  1032. Xstatic void
  1033. Xregoptail(p, val)
  1034. Xchar *p;
  1035. Xchar *val;
  1036. X{
  1037. X    /* "Operandless" and "op != BRANCH" are synonymous in practice. */
  1038. X    if (p == NULL || p == ®dummy || OP(p) != BRANCH)
  1039. X        return;
  1040. X    regtail(OPERAND(p), val);
  1041. X}
  1042. X
  1043. X/*
  1044. X * regexec and friends
  1045. X */
  1046. X
  1047. X/*
  1048. X * Global work variables for regexec().
  1049. X */
  1050. Xstatic char *reginput;        /* String-input pointer. */
  1051. Xstatic char *regbol;        /* Beginning of input, for ^ check. */
  1052. Xstatic char **regstartp;    /* Pointer to startp array. */
  1053. Xstatic char **regendp;        /* Ditto for endp. */
  1054. X
  1055. X/*
  1056. X * Forwards.
  1057. X */
  1058. XSTATIC int regtry();
  1059. XSTATIC int regmatch();
  1060. XSTATIC int regrepeat();
  1061. X
  1062. X#ifdef DEBUG
  1063. Xint regnarrate = 0;
  1064. Xvoid regdump();
  1065. XSTATIC char *regprop();
  1066. X#endif
  1067. X
  1068. X/*
  1069. X - regexec - match a regexp against a string
  1070. X */
  1071. Xint
  1072. Xregexec(prog, string)
  1073. Xregister regexp *prog;
  1074. Xregister char *string;
  1075. X{
  1076. X    register char *s;
  1077. X    extern char *strchr();
  1078. X
  1079. X    /* Be paranoid... */
  1080. X    if (prog == NULL || string == NULL) {
  1081. X        regerror("NULL parameter");
  1082. X        return(0);
  1083. X    }
  1084. X
  1085. X    /* Check validity of program. */
  1086. X    if (UCHARAT(prog->program) != MAGIC) {
  1087. X        regerror("corrupted program");
  1088. X        return(0);
  1089. X    }
  1090. X
  1091. X    /* If there is a "must appear" string, look for it. */
  1092. X    if (prog->regmust != NULL) {
  1093. X        s = string;
  1094. X        while ((s = strchr(s, prog->regmust[0])) != NULL) {
  1095. X            if (strncmp(s, prog->regmust, prog->regmlen) == 0)
  1096. X                break;    /* Found it. */
  1097. X            s++;
  1098. X        }
  1099. X        if (s == NULL)    /* Not present. */
  1100. X            return(0);
  1101. X    }
  1102. X
  1103. X    /* Mark beginning of line for ^ . */
  1104. X    regbol = string;
  1105. X
  1106. X    /* Simplest case:  anchored match need be tried only once. */
  1107. X    if (prog->reganch)
  1108. X        return(regtry(prog, string));
  1109. X
  1110. X    /* Messy cases:  unanchored match. */
  1111. X    s = string;
  1112. X    if (prog->regstart != '\0')
  1113. X        /* We know what char it must start with. */
  1114. X        while ((s = strchr(s, prog->regstart)) != NULL) {
  1115. X            if (regtry(prog, s))
  1116. X                return(1);
  1117. X            s++;
  1118. X        }
  1119. X    else
  1120. X        /* We don't -- general case. */
  1121. X        do {
  1122. X            if (regtry(prog, s))
  1123. X                return(1);
  1124. X        } while (*s++ != '\0');
  1125. X
  1126. X    /* Failure. */
  1127. X    return(0);
  1128. X}
  1129. X
  1130. X/*
  1131. X - regtry - try match at specific point
  1132. X */
  1133. Xstatic int            /* 0 failure, 1 success */
  1134. Xregtry(prog, string)
  1135. Xregexp *prog;
  1136. Xchar *string;
  1137. X{
  1138. X    register int i;
  1139. X    register char **sp;
  1140. X    register char **ep;
  1141. X
  1142. X    reginput = string;
  1143. X    regstartp = prog->startp;
  1144. X    regendp = prog->endp;
  1145. X
  1146. X    sp = prog->startp;
  1147. X    ep = prog->endp;
  1148. X    for (i = NSUBEXP; i > 0; i--) {
  1149. X        *sp++ = NULL;
  1150. X        *ep++ = NULL;
  1151. X    }
  1152. X    if (regmatch(prog->program + 1)) {
  1153. X        prog->startp[0] = string;
  1154. X        prog->endp[0] = reginput;
  1155. X        return(1);
  1156. X    } else
  1157. X        return(0);
  1158. X}
  1159. X
  1160. X/*
  1161. X - regmatch - main matching routine
  1162. X *
  1163. X * Conceptually the strategy is simple:  check to see whether the current
  1164. X * node matches, call self recursively to see whether the rest matches,
  1165. X * and then act accordingly.  In practice we make some effort to avoid
  1166. X * recursion, in particular by going through "ordinary" nodes (that don't
  1167. X * need to know whether the rest of the match failed) by a loop instead of
  1168. X * by recursion.
  1169. X */
  1170. Xstatic int            /* 0 failure, 1 success */
  1171. Xregmatch(prog)
  1172. Xchar *prog;
  1173. X{
  1174. X    register char *scan;    /* Current node. */
  1175. X    char *next;        /* Next node. */
  1176. X    extern char *strchr();
  1177. X
  1178. X    scan = prog;
  1179. X#ifdef DEBUG
  1180. X    if (scan != NULL && regnarrate)
  1181. X        fprintf(stderr, "%s(\n", regprop(scan));
  1182. X#endif
  1183. X    while (scan != NULL) {
  1184. X#ifdef DEBUG
  1185. X        if (regnarrate)
  1186. X            fprintf(stderr, "%s...\n", regprop(scan));
  1187. X#endif
  1188. X        next = regnext(scan);
  1189. X
  1190. X        switch (OP(scan)) {
  1191. X        case BOL:
  1192. X            if (reginput != regbol)
  1193. X                return(0);
  1194. X            break;
  1195. X        case EOL:
  1196. X            if (*reginput != '\0')
  1197. X                return(0);
  1198. X            break;
  1199. X        case ANY:
  1200. X            if (*reginput == '\0')
  1201. X                return(0);
  1202. X            reginput++;
  1203. X            break;
  1204. X        case EXACTLY: {
  1205. X                register int len;
  1206. X                register char *opnd;
  1207. X
  1208. X                opnd = OPERAND(scan);
  1209. X                /* Inline the first character, for speed. */
  1210. X                if (*opnd != *reginput)
  1211. X                    return(0);
  1212. X                len = strlen(opnd);
  1213. X                if (len > 1 && strncmp(opnd, reginput, len) != 0)
  1214. X                    return(0);
  1215. X                reginput += len;
  1216. X            }
  1217. X            break;
  1218. X        case ANYOF:
  1219. X            if (strchr(OPERAND(scan), *reginput) == NULL)
  1220. X                return(0);
  1221. X            reginput++;
  1222. X            break;
  1223. X        case ANYBUT:
  1224. X            if (strchr(OPERAND(scan), *reginput) != NULL)
  1225. X                return(0);
  1226. X            reginput++;
  1227. X            break;
  1228. X        case NOTHING:
  1229. X            break;
  1230. X        case BACK:
  1231. X            break;
  1232. X        case OPEN+1:
  1233. X        case OPEN+2:
  1234. X        case OPEN+3:
  1235. X        case OPEN+4:
  1236. X        case OPEN+5:
  1237. X        case OPEN+6:
  1238. X        case OPEN+7:
  1239. X        case OPEN+8:
  1240. X        case OPEN+9: {
  1241. X                register int no;
  1242. X                register char *save;
  1243. X
  1244. X                no = OP(scan) - OPEN;
  1245. X                save = reginput;
  1246. X
  1247. X                if (regmatch(next)) {
  1248. X                    /*
  1249. X                     * Don't set startp if some later
  1250. X                     * invocation of the same parentheses
  1251. X                     * already has.
  1252. X                     */
  1253. X                    if (regstartp[no] == NULL)
  1254. X                        regstartp[no] = save;
  1255. X                    return(1);
  1256. X                } else
  1257. X                    return(0);
  1258. X            }
  1259. X            break;
  1260. X        case CLOSE+1:
  1261. X        case CLOSE+2:
  1262. X        case CLOSE+3:
  1263. X        case CLOSE+4:
  1264. X        case CLOSE+5:
  1265. X        case CLOSE+6:
  1266. X        case CLOSE+7:
  1267. X        case CLOSE+8:
  1268. X        case CLOSE+9: {
  1269. X                register int no;
  1270. X                register char *save;
  1271. X
  1272. X                no = OP(scan) - CLOSE;
  1273. X                save = reginput;
  1274. X
  1275. X                if (regmatch(next)) {
  1276. X                    /*
  1277. X                     * Don't set endp if some later
  1278. X                     * invocation of the same parentheses
  1279. X                     * already has.
  1280. X                     */
  1281. X                    if (regendp[no] == NULL)
  1282. X                        regendp[no] = save;
  1283. X                    return(1);
  1284. X                } else
  1285. X                    return(0);
  1286. X            }
  1287. X            break;
  1288. X        case BRANCH: {
  1289. X                register char *save;
  1290. X
  1291. X                if (OP(next) != BRANCH)        /* No choice. */
  1292. X                    next = OPERAND(scan);    /* Avoid recursion. */
  1293. X                else {
  1294. X                    do {
  1295. X                        save = reginput;
  1296. X                        if (regmatch(OPERAND(scan)))
  1297. X                            return(1);
  1298. X                        reginput = save;
  1299. X                        scan = regnext(scan);
  1300. X                    } while (scan != NULL && OP(scan) == BRANCH);
  1301. X                    return(0);
  1302. X                    /* NOTREACHED */
  1303. X                }
  1304. X            }
  1305. X            break;
  1306. X        case STAR:
  1307. X        case PLUS: {
  1308. X                register char nextch;
  1309. X                register int no;
  1310. X                register char *save;
  1311. X                register int min;
  1312. X
  1313. X                /*
  1314. X                 * Lookahead to avoid useless match attempts
  1315. X                 * when we know what character comes next.
  1316. X                 */
  1317. X                nextch = '\0';
  1318. X                if (OP(next) == EXACTLY)
  1319. X                    nextch = *OPERAND(next);
  1320. X                min = (OP(scan) == STAR) ? 0 : 1;
  1321. X                save = reginput;
  1322. X                no = regrepeat(OPERAND(scan));
  1323. X                while (no >= min) {
  1324. X                    /* If it could work, try it. */
  1325. X                    if (nextch == '\0' || *reginput == nextch)
  1326. X                        if (regmatch(next))
  1327. X                            return(1);
  1328. X                    /* Couldn't or didn't -- back up. */
  1329. X                    no--;
  1330. X                    reginput = save + no;
  1331. X                }
  1332. X                return(0);
  1333. X            }
  1334. X            break;
  1335. X        case END:
  1336. X            return(1);    /* Success! */
  1337. X            break;
  1338. X        default:
  1339. X            regerror("memory corruption");
  1340. X            return(0);
  1341. X            break;
  1342. X        }
  1343. X
  1344. X        scan = next;
  1345. X    }
  1346. X
  1347. X    /*
  1348. X     * We get here only if there's trouble -- normally "case END" is
  1349. X     * the terminating point.
  1350. X     */
  1351. X    regerror("corrupted pointers");
  1352. X    return(0);
  1353. X}
  1354. X
  1355. X/*
  1356. X - regrepeat - repeatedly match something simple, report how many
  1357. X */
  1358. Xstatic int
  1359. Xregrepeat(p)
  1360. Xchar *p;
  1361. X{
  1362. X    register int count = 0;
  1363. X    register char *scan;
  1364. X    register char *opnd;
  1365. X
  1366. X    scan = reginput;
  1367. X    opnd = OPERAND(p);
  1368. X    switch (OP(p)) {
  1369. X    case ANY:
  1370. X        count = strlen(scan);
  1371. X        scan += count;
  1372. X        break;
  1373. X    case EXACTLY:
  1374. X        while (*opnd == *scan) {
  1375. X            count++;
  1376. X            scan++;
  1377. X        }
  1378. X        break;
  1379. X    case ANYOF:
  1380. X        while (*scan != '\0' && strchr(opnd, *scan) != NULL) {
  1381. X            count++;
  1382. X            scan++;
  1383. X        }
  1384. X        break;
  1385. X    case ANYBUT:
  1386. X        while (*scan != '\0' && strchr(opnd, *scan) == NULL) {
  1387. X            count++;
  1388. X            scan++;
  1389. X        }
  1390. X        break;
  1391. X    default:        /* Oh dear.  Called inappropriately. */
  1392. X        regerror("internal foulup");
  1393. X        count = 0;    /* Best compromise. */
  1394. X        break;
  1395. X    }
  1396. X    reginput = scan;
  1397. X
  1398. X    return(count);
  1399. X}
  1400. X
  1401. X/*
  1402. X - regnext - dig the "next" pointer out of a node
  1403. X */
  1404. Xstatic char *
  1405. Xregnext(p)
  1406. Xregister char *p;
  1407. X{
  1408. X    register int offset;
  1409. X
  1410. X    if (p == ®dummy)
  1411. X        return(NULL);
  1412. X
  1413. X    offset = NEXT(p);
  1414. X    if (offset == 0)
  1415. X        return(NULL);
  1416. X
  1417. X    if (OP(p) == BACK)
  1418. X        return(p-offset);
  1419. X    else
  1420. X        return(p+offset);
  1421. X}
  1422. X
  1423. X#ifdef DEBUG
  1424. X
  1425. XSTATIC char *regprop();
  1426. X
  1427. X/*
  1428. X - regdump - dump a regexp onto stdout in vaguely comprehensible form
  1429. X */
  1430. Xvoid
  1431. Xregdump(r)
  1432. Xregexp *r;
  1433. X{
  1434. X    register char *s;
  1435. X    register char op = EXACTLY;    /* Arbitrary non-END op. */
  1436. X    register char *next;
  1437. X    extern char *strchr();
  1438. X
  1439. X
  1440. X    s = r->program + 1;
  1441. X    while (op != END) {    /* While that wasn't END last time... */
  1442. X        op = OP(s);
  1443. X        printf("%2d%s", s-r->program, regprop(s));    /* Where, what. */
  1444. X        next = regnext(s);
  1445. X        if (next == NULL)        /* Next ptr. */
  1446. X            printf("(0)");
  1447. X        else 
  1448. X            printf("(%d)", (s-r->program)+(next-s));
  1449. X        s += 3;
  1450. X        if (op == ANYOF || op == ANYBUT || op == EXACTLY) {
  1451. X            /* Literal string, where present. */
  1452. X            while (*s != '\0') {
  1453. X                putchar(*s);
  1454. X                s++;
  1455. X            }
  1456. X            s++;
  1457. X        }
  1458. X        putchar('\n');
  1459. X    }
  1460. X
  1461. X    /* Header fields of interest. */
  1462. X    if (r->regstart != '\0')
  1463. X        printf("start `%c' ", r->regstart);
  1464. X    if (r->reganch)
  1465. X        printf("anchored ");
  1466. X    if (r->regmust != NULL)
  1467. X        printf("must have \"%s\"", r->regmust);
  1468. X    printf("\n");
  1469. X}
  1470. X
  1471. X/*
  1472. X - regprop - printable representation of opcode
  1473. X */
  1474. Xstatic char *
  1475. Xregprop(op)
  1476. Xchar *op;
  1477. X{
  1478. X    register char *p;
  1479. X    static char buf[50];
  1480. X
  1481. X    (void) strcpy(buf, ":");
  1482. X
  1483. X    switch (OP(op)) {
  1484. X    case BOL:
  1485. X        p = "BOL";
  1486. X        break;
  1487. X    case EOL:
  1488. X        p = "EOL";
  1489. X        break;
  1490. X    case ANY:
  1491. X        p = "ANY";
  1492. X        break;
  1493. X    case ANYOF:
  1494. X        p = "ANYOF";
  1495. X        break;
  1496. X    case ANYBUT:
  1497. X        p = "ANYBUT";
  1498. X        break;
  1499. X    case BRANCH:
  1500. X        p = "BRANCH";
  1501. X        break;
  1502. X    case EXACTLY:
  1503. X        p = "EXACTLY";
  1504. X        break;
  1505. X    case NOTHING:
  1506. X        p = "NOTHING";
  1507. X        break;
  1508. X    case BACK:
  1509. X        p = "BACK";
  1510. X        break;
  1511. X    case END:
  1512. X        p = "END";
  1513. X        break;
  1514. X    case OPEN+1:
  1515. X    case OPEN+2:
  1516. X    case OPEN+3:
  1517. X    case OPEN+4:
  1518. X    case OPEN+5:
  1519. X    case OPEN+6:
  1520. X    case OPEN+7:
  1521. X    case OPEN+8:
  1522. X    case OPEN+9:
  1523. X        sprintf(buf+strlen(buf), "OPEN%d", OP(op)-OPEN);
  1524. X        p = NULL;
  1525. X        break;
  1526. X    case CLOSE+1:
  1527. X    case CLOSE+2:
  1528. X    case CLOSE+3:
  1529. X    case CLOSE+4:
  1530. X    case CLOSE+5:
  1531. X    case CLOSE+6:
  1532. X    case CLOSE+7:
  1533. X    case CLOSE+8:
  1534. X    case CLOSE+9:
  1535. X        sprintf(buf+strlen(buf), "CLOSE%d", OP(op)-CLOSE);
  1536. X        p = NULL;
  1537. X        break;
  1538. X    case STAR:
  1539. X        p = "STAR";
  1540. X        break;
  1541. X    case PLUS:
  1542. X        p = "PLUS";
  1543. X        break;
  1544. X    default:
  1545. X        regerror("corrupted opcode");
  1546. X        break;
  1547. X    }
  1548. X    if (p != NULL)
  1549. X        (void) strcat(buf, p);
  1550. X    return(buf);
  1551. X}
  1552. X#endif
  1553. X
  1554. X/*
  1555. X * The following is provided for those people who do not have strcspn() in
  1556. X * their C libraries.  They should get off their butts and do something
  1557. X * about it; at least one public-domain implementation of those (highly
  1558. X * useful) string routines has been published on Usenet.
  1559. X */
  1560. X#ifdef STRCSPN
  1561. X/*
  1562. X * strcspn - find length of initial segment of s1 consisting entirely
  1563. X * of characters not from s2
  1564. X */
  1565. X
  1566. Xstatic int
  1567. Xstrcspn(s1, s2)
  1568. Xchar *s1;
  1569. Xchar *s2;
  1570. X{
  1571. X    register char *scan1;
  1572. X    register char *scan2;
  1573. X    register int count;
  1574. X
  1575. X    count = 0;
  1576. X    for (scan1 = s1; *scan1 != '\0'; scan1++) {
  1577. X        for (scan2 = s2; *scan2 != '\0';)    /* ++ moved down. */
  1578. X            if (*scan1 == *scan2++)
  1579. X                return(count);
  1580. X        count++;
  1581. X    }
  1582. X    return(count);
  1583. X}
  1584. X#endif
  1585. !
  1586. echo regsub.c:
  1587. sed 's/^X//' >regsub.c <<'!'
  1588. X/*
  1589. X * regsub
  1590. X *
  1591. X *    Copyright (c) 1986 by University of Toronto.
  1592. X *    Written by Henry Spencer.  Not derived from licensed software.
  1593. X *
  1594. X *    Permission is granted to anyone to use this software for any
  1595. X *    purpose on any computer system, and to redistribute it freely,
  1596. X *    subject to the following restrictions:
  1597. X *
  1598. X *    1. The author is not responsible for the consequences of use of
  1599. X *        this software, no matter how awful, even if they arise
  1600. X *        from defects in it.
  1601. X *
  1602. X *    2. The origin of this software must not be misrepresented, either
  1603. X *        by explicit claim or by omission.
  1604. X *
  1605. X *    3. Altered versions must be plainly marked as such, and must not
  1606. X *        be misrepresented as being the original software.
  1607. X */
  1608. X#include <stdio.h>
  1609. X#include <regexp.h>
  1610. X#include "regmagic.h"
  1611. X
  1612. X#ifndef CHARBITS
  1613. X#define    UCHARAT(p)    ((int)*(unsigned char *)(p))
  1614. X#else
  1615. X#define    UCHARAT(p)    ((int)*(p)&CHARBITS)
  1616. X#endif
  1617. X
  1618. X/*
  1619. X - regsub - perform substitutions after a regexp match
  1620. X */
  1621. Xvoid
  1622. Xregsub(prog, source, dest)
  1623. Xregexp *prog;
  1624. Xchar *source;
  1625. Xchar *dest;
  1626. X{
  1627. X    register char *src;
  1628. X    register char *dst;
  1629. X    register char c;
  1630. X    register int no;
  1631. X    register int len;
  1632. X    extern char *strncpy();
  1633. X
  1634. X    if (prog == NULL || source == NULL || dest == NULL) {
  1635. X        regerror("NULL parm to regsub");
  1636. X        return;
  1637. X    }
  1638. X    if (UCHARAT(prog->program) != MAGIC) {
  1639. X        regerror("damaged regexp fed to regsub");
  1640. X        return;
  1641. X    }
  1642. X
  1643. X    src = source;
  1644. X    dst = dest;
  1645. X    while ((c = *src++) != '\0') {
  1646. X        if (c == '&')
  1647. X            no = 0;
  1648. X        else if (c == '\\' && '0' <= *src && *src <= '9')
  1649. X            no = *src++ - '0';
  1650. X        else
  1651. X            no = -1;
  1652. X
  1653. X        if (no < 0)    /* Ordinary character. */
  1654. X            *dst++ = c;
  1655. X        else if (prog->startp[no] != NULL && prog->endp[no] != NULL) {
  1656. X            len = prog->endp[no] - prog->startp[no];
  1657. X            (void) strncpy(dst, prog->startp[no], len);
  1658. X            dst += len;
  1659. X            if (*(dst-1) == '\0') {        /* strncpy hit NUL. */
  1660. X                regerror("damaged match string");
  1661. X                return;
  1662. X            }
  1663. X        }
  1664. X    }
  1665. X    *dst++ = '\0';
  1666. X}
  1667. !
  1668. echo regerror.c:
  1669. sed 's/^X//' >regerror.c <<'!'
  1670. X#include <stdio.h>
  1671. X
  1672. Xvoid
  1673. Xregerror(s)
  1674. Xchar *s;
  1675. X{
  1676. X#ifdef ERRAVAIL
  1677. X    error("regexp: %s", s);
  1678. X#else
  1679. X    fprintf(stderr, "regexp(3): %s", s);
  1680. X    exit(1);
  1681. X#endif
  1682. X    /* NOTREACHED */
  1683. X}
  1684. !
  1685. echo regmagic.h:
  1686. sed 's/^X//' >regmagic.h <<'!'
  1687. X/*
  1688. X * The first byte of the regexp internal "program" is actually this magic
  1689. X * number; the start node begins in the second byte.
  1690. X */
  1691. X#define    MAGIC    0234
  1692. !
  1693. echo try.c:
  1694. sed 's/^X//' >try.c <<'!'
  1695. X/*
  1696. X * Simple test program for regexp(3) stuff.  Knows about debugging hooks.
  1697. X *
  1698. X *    Copyright (c) 1986 by University of Toronto.
  1699. X *    Written by Henry Spencer.  Not derived from licensed software.
  1700. X *
  1701. X *    Permission is granted to anyone to use this software for any
  1702. X *    purpose on any computer system, and to redistribute it freely,
  1703. X *    subject to the following restrictions:
  1704. X *
  1705. X *    1. The author is not responsible for the consequences of use of
  1706. X *        this software, no matter how awful, even if they arise
  1707. X *        from defects in it.
  1708. X *
  1709. X *    2. The origin of this software must not be misrepresented, either
  1710. X *        by explicit claim or by omission.
  1711. X *
  1712. X *    3. Altered versions must be plainly marked as such, and must not
  1713. X *        be misrepresented as being the original software.
  1714. X *
  1715. X * Usage: try re [string [output [-]]]
  1716. X * The re is compiled and dumped, regexeced against the string, the result
  1717. X * is applied to output using regsub().  The - triggers a running narrative
  1718. X * from regexec().  Dumping and narrative don't happen unless DEBUG.
  1719. X *
  1720. X * If there are no arguments, stdin is assumed to be a stream of lines with
  1721. X * five fields:  a r.e., a string to match it against, a result code, a
  1722. X * source string for regsub, and the proper result.  Result codes are 'c'
  1723. X * for compile failure, 'y' for match success, 'n' for match failure.
  1724. X * Field separator is tab.
  1725. X */
  1726. X#include <stdio.h>
  1727. X#include <regexp.h>
  1728. X
  1729. X#ifdef ERRAVAIL
  1730. Xchar *progname;
  1731. Xextern char *mkprogname();
  1732. X#endif
  1733. X
  1734. X#ifdef DEBUG
  1735. Xextern int regnarrate;
  1736. X#endif
  1737. X
  1738. Xchar buf[BUFSIZ];
  1739. X
  1740. Xint errreport = 0;        /* Report errors via errseen? */
  1741. Xchar *errseen = NULL;        /* Error message. */
  1742. Xint status = 0;            /* Exit status. */
  1743. X
  1744. X/* ARGSUSED */
  1745. Xmain(argc, argv)
  1746. Xint argc;
  1747. Xchar *argv[];
  1748. X{
  1749. X    regexp *r;
  1750. X    int i;
  1751. X
  1752. X#ifdef ERRAVAIL
  1753. X    progname = mkprogname(argv[0]);
  1754. X#endif
  1755. X
  1756. X    if (argc == 1) {
  1757. X        multiple();
  1758. X        exit(status);
  1759. X    }
  1760. X
  1761. X    r = regcomp(argv[1]);
  1762. X    if (r == NULL)
  1763. X        error("regcomp failure", "");
  1764. X#ifdef DEBUG
  1765. X    regdump(r);
  1766. X    if (argc > 4)
  1767. X        regnarrate++;
  1768. X#endif
  1769. X    if (argc > 2) {
  1770. X        i = regexec(r, argv[2]);
  1771. X        printf("%d", i);
  1772. X        for (i = 1; i < NSUBEXP; i++)
  1773. X            if (r->startp[i] != NULL && r->endp[i] != NULL)
  1774. X                printf(" \\%d", i);
  1775. X        printf("\n");
  1776. X    }
  1777. X    if (argc > 3) {
  1778. X        regsub(r, argv[3], buf);
  1779. X        printf("%s\n", buf);
  1780. X    }
  1781. X    exit(status);
  1782. X}
  1783. X
  1784. Xvoid
  1785. Xregerror(s)
  1786. Xchar *s;
  1787. X{
  1788. X    if (errreport)
  1789. X        errseen = s;
  1790. X    else
  1791. X        error(s, "");
  1792. X}
  1793. X
  1794. X#ifndef ERRAVAIL
  1795. Xerror(s1, s2)
  1796. Xchar *s1;
  1797. Xchar *s2;
  1798. X{
  1799. X    fprintf(stderr, "regexp: ");
  1800. X    fprintf(stderr, s1, s2);
  1801. X    fprintf(stderr, "\n");
  1802. X    exit(1);
  1803. X}
  1804. X#endif
  1805. X
  1806. Xint lineno;
  1807. X
  1808. Xregexp badregexp;        /* Implicit init to 0. */
  1809. X
  1810. Xmultiple()
  1811. X{
  1812. X    char rbuf[BUFSIZ];
  1813. X    char *field[5];
  1814. X    char *scan;
  1815. X    int i;
  1816. X    regexp *r;
  1817. X    extern char *strchr();
  1818. X
  1819. X    errreport = 1;
  1820. X    lineno = 0;
  1821. X    while (fgets(rbuf, sizeof(rbuf), stdin) != NULL) {
  1822. X        rbuf[strlen(rbuf)-1] = '\0';    /* Dispense with \n. */
  1823. X        lineno++;
  1824. X        scan = rbuf;
  1825. X        for (i = 0; i < 5; i++) {
  1826. X            field[i] = scan;
  1827. X            if (field[i] == NULL) {
  1828. X                complain("bad testfile format", "");
  1829. X                exit(1);
  1830. X            }
  1831. X            scan = strchr(scan, '\t');
  1832. X            if (scan != NULL)
  1833. X                *scan++ = '\0';
  1834. X        }
  1835. X        try(field);
  1836. X    }
  1837. X
  1838. X    /* And finish up with some internal testing... */
  1839. X    lineno = 9990;
  1840. X    errseen = NULL;
  1841. X    if (regcomp((char *)NULL) != NULL || errseen == NULL)
  1842. X        complain("regcomp(NULL) doesn't complain", "");
  1843. X    lineno = 9991;
  1844. X    errseen = NULL;
  1845. X    if (regexec((regexp *)NULL, "foo") || errseen == NULL)
  1846. X        complain("regexec(NULL, ...) doesn't complain", "");
  1847. X    lineno = 9992;
  1848. X    r = regcomp("foo");
  1849. X    if (r == NULL) {
  1850. X        complain("regcomp(\"foo\") fails", "");
  1851. X        return;
  1852. X    }
  1853. X    lineno = 9993;
  1854. X    errseen = NULL;
  1855. X    if (regexec(r, (char *)NULL) || errseen == NULL)
  1856. X        complain("regexec(..., NULL) doesn't complain", "");
  1857. X    lineno = 9994;
  1858. X    errseen = NULL;
  1859. X    regsub((regexp *)NULL, "foo", rbuf);
  1860. X    if (errseen == NULL)
  1861. X        complain("regsub(NULL, ..., ...) doesn't complain", "");
  1862. X    lineno = 9995;
  1863. X    errseen = NULL;
  1864. X    regsub(r, (char *)NULL, rbuf);
  1865. X    if (errseen == NULL)
  1866. X        complain("regsub(..., NULL, ...) doesn't complain", "");
  1867. X    lineno = 9996;
  1868. X    errseen = NULL;
  1869. X    regsub(r, "foo", (char *)NULL);
  1870. X    if (errseen == NULL)
  1871. X        complain("regsub(..., ..., NULL) doesn't complain", "");
  1872. X    lineno = 9997;
  1873. X    errseen = NULL;
  1874. X    if (regexec(&badregexp, "foo") || errseen == NULL)
  1875. X        complain("regexec(nonsense, ...) doesn't complain", "");
  1876. X    lineno = 9998;
  1877. X    errseen = NULL;
  1878. X    regsub(&badregexp, "foo", rbuf);
  1879. X    if (errseen == NULL)
  1880. X        complain("regsub(nonsense, ..., ...) doesn't complain", "");
  1881. X}
  1882. X
  1883. Xtry(fields)
  1884. Xchar **fields;
  1885. X{
  1886. X    regexp *r;
  1887. X    char dbuf[BUFSIZ];
  1888. X
  1889. X    errseen = NULL;
  1890. X    r = regcomp(fields[0]);
  1891. X    if (r == NULL) {
  1892. X        if (*fields[2] != 'c')
  1893. X            complain("regcomp failure in `%s'", fields[0]);
  1894. X        return;
  1895. X    }
  1896. X    if (*fields[2] == 'c') {
  1897. X        complain("unexpected regcomp success in `%s'", fields[0]);
  1898. X        free((char *)r);
  1899. X        return;
  1900. X    }
  1901. X    if (!regexec(r, fields[1])) {
  1902. X        if (*fields[2] != 'n')
  1903. X            complain("regexec failure in `%s'", "");
  1904. X        free((char *)r);
  1905. X        return;
  1906. X    }
  1907. X    if (*fields[2] == 'n') {
  1908. X        complain("unexpected regexec success", "");
  1909. X        free((char *)r);
  1910. X        return;
  1911. X    }
  1912. X    errseen = NULL;
  1913. X    regsub(r, fields[3], dbuf);
  1914. X    if (errseen != NULL) {
  1915. X        complain("regsub complaint", "");
  1916. X        free((char *)r);
  1917. X        return;
  1918. X    }
  1919. X    if (strcmp(dbuf, fields[4]) != 0)
  1920. X        complain("regsub result `%s' wrong", dbuf);
  1921. X    free((char *)r);
  1922. X}
  1923. X
  1924. Xcomplain(s1, s2)
  1925. Xchar *s1;
  1926. Xchar *s2;
  1927. X{
  1928. X    fprintf(stderr, "try: %d: ", lineno);
  1929. X    fprintf(stderr, s1, s2);
  1930. X    fprintf(stderr, " (%s)\n", (errseen != NULL) ? errseen : "");
  1931. X    status = 1;
  1932. X}
  1933. !
  1934. echo timer.c:
  1935. sed 's/^X//' >timer.c <<'!'
  1936. X/*
  1937. X * Simple timing program for regcomp().
  1938. X *
  1939. X *    Copyright (c) 1986 by University of Toronto.
  1940. X *    Written by Henry Spencer.  Not derived from licensed software.
  1941. X *
  1942. X *    Permission is granted to anyone to use this software for any
  1943. X *    purpose on any computer system, and to redistribute it freely,
  1944. X *    subject to the following restrictions:
  1945. X *
  1946. X *    1. The author is not responsible for the consequences of use of
  1947. X *        this software, no matter how awful, even if they arise
  1948. X *        from defects in it.
  1949. X *
  1950. X *    2. The origin of this software must not be misrepresented, either
  1951. X *        by explicit claim or by omission.
  1952. X *
  1953. X *    3. Altered versions must be plainly marked as such, and must not
  1954. X *        be misrepresented as being the original software.
  1955. X *
  1956. X * Usage: timer ncomp nexec nsub
  1957. X *    or
  1958. X *    timer ncomp nexec nsub regexp string [ answer [ sub ] ]
  1959. X *
  1960. X * The second form is for timing repetitions of a single test case.
  1961. X * The first form's test data is a compiled-in copy of the "tests" file.
  1962. X * Ncomp, nexec, nsub are how many times to do each regcomp, regexec,
  1963. X * and regsub.  The way to time an operation individually is to do something
  1964. X * like "timer 1 50 1".
  1965. X */
  1966. X#include <stdio.h>
  1967. X
  1968. Xstruct try {
  1969. X    char *re, *str, *ans, *src, *dst;
  1970. X} tests[] = {
  1971. X#include "timer.t.h"
  1972. X{ NULL, NULL, NULL, NULL, NULL }
  1973. X};
  1974. X
  1975. X#include <regexp.h>
  1976. X
  1977. Xint errreport = 0;        /* Report errors via errseen? */
  1978. Xchar *errseen = NULL;        /* Error message. */
  1979. X
  1980. Xchar *progname;
  1981. X
  1982. X/* ARGSUSED */
  1983. Xmain(argc, argv)
  1984. Xint argc;
  1985. Xchar *argv[];
  1986. X{
  1987. X    int ncomp, nexec, nsub;
  1988. X    struct try one;
  1989. X    char dummy[512];
  1990. X
  1991. X    if (argc < 4) {
  1992. X        ncomp = 1;
  1993. X        nexec = 1;
  1994. X        nsub = 1;
  1995. X    } else {
  1996. X        ncomp = atoi(argv[1]);
  1997. X        nexec = atoi(argv[2]);
  1998. X        nsub = atoi(argv[3]);
  1999. X    }
  2000. X    
  2001. X    progname = argv[0];
  2002. X    if (argc > 5) {
  2003. X        one.re = argv[4];
  2004. X        one.str = argv[5];
  2005. X        if (argc > 6)
  2006. X            one.ans = argv[6];
  2007. X        else
  2008. X            one.ans = "y";
  2009. X        if (argc > 7) {    
  2010. X            one.src = argv[7];
  2011. X            one.dst = "xxx";
  2012. X        } else {
  2013. X            one.src = "x";
  2014. X            one.dst = "x";
  2015. X        }
  2016. X        errreport = 1;
  2017. X        try(one, ncomp, nexec, nsub);
  2018. X    } else
  2019. X        multiple(ncomp, nexec, nsub);
  2020. X    exit(0);
  2021. X}
  2022. X
  2023. Xvoid
  2024. Xregerror(s)
  2025. Xchar *s;
  2026. X{
  2027. X    if (errreport)
  2028. X        errseen = s;
  2029. X    else
  2030. X        error(s, "");
  2031. X}
  2032. X
  2033. X#ifndef ERRAVAIL
  2034. Xerror(s1, s2)
  2035. Xchar *s1;
  2036. Xchar *s2;
  2037. X{
  2038. X    fprintf(stderr, "regexp: ");
  2039. X    fprintf(stderr, s1, s2);
  2040. X    fprintf(stderr, "\n");
  2041. X    exit(1);
  2042. X}
  2043. X#endif
  2044. X
  2045. Xint lineno = 0;
  2046. X
  2047. Xmultiple(ncomp, nexec, nsub)
  2048. Xint ncomp, nexec, nsub;
  2049. X{
  2050. X    register int i;
  2051. X    extern char *strchr();
  2052. X
  2053. X    errreport = 1;
  2054. X    for (i = 0; tests[i].re != NULL; i++) {
  2055. X        lineno++;
  2056. X        try(tests[i], ncomp, nexec, nsub);
  2057. X    }
  2058. X}
  2059. X
  2060. Xtry(fields, ncomp, nexec, nsub)
  2061. Xstruct try fields;
  2062. Xint ncomp, nexec, nsub;
  2063. X{
  2064. X    regexp *r;
  2065. X    char dbuf[BUFSIZ];
  2066. X    register int i;
  2067. X
  2068. X    errseen = NULL;
  2069. X    r = regcomp(fields.re);
  2070. X    if (r == NULL) {
  2071. X        if (*fields.ans != 'c')
  2072. X            complain("regcomp failure in `%s'", fields.re);
  2073. X        return;
  2074. X    }
  2075. X    if (*fields.ans == 'c') {
  2076. X        complain("unexpected regcomp success in `%s'", fields.re);
  2077. X        free((char *)r);
  2078. X        return;
  2079. X    }
  2080. X    for (i = ncomp-1; i > 0; i--) {
  2081. X        free((char *)r);
  2082. X        r = regcomp(fields.re);
  2083. X    }
  2084. X    if (!regexec(r, fields.str)) {
  2085. X        if (*fields.ans != 'n')
  2086. X            complain("regexec failure in `%s'", "");
  2087. X        free((char *)r);
  2088. X        return;
  2089. X    }
  2090. X    if (*fields.ans == 'n') {
  2091. X        complain("unexpected regexec success", "");
  2092. X        free((char *)r);
  2093. X        return;
  2094. X    }
  2095. X    for (i = nexec-1; i > 0; i--)
  2096. X        (void) regexec(r, fields.str);
  2097. X    errseen = NULL;
  2098. X    for (i = nsub; i > 0; i--)
  2099. X        regsub(r, fields.src, dbuf);
  2100. X    if (errseen != NULL) {    
  2101. X        complain("regsub complaint", "");
  2102. X        free((char *)r);
  2103. X        return;
  2104. X    }
  2105. X    if (strcmp(dbuf, fields.dst) != 0)
  2106. X        complain("regsub result `%s' wrong", dbuf);
  2107. X    free((char *)r);
  2108. X}
  2109. X
  2110. Xcomplain(s1, s2)
  2111. Xchar *s1;
  2112. Xchar *s2;
  2113. X{
  2114. X    fprintf(stderr, "try: %d: ", lineno);
  2115. X    fprintf(stderr, s1, s2);
  2116. X    fprintf(stderr, " (%s)\n", (errseen != NULL) ? errseen : "");
  2117. X}
  2118. !
  2119. echo tests:
  2120. sed 's/^X//' >tests <<'!'
  2121. Xabc    abc    y    &    abc
  2122. Xabc    xbc    n    -    -
  2123. Xabc    axc    n    -    -
  2124. Xabc    abx    n    -    -
  2125. Xabc    xabcy    y    &    abc
  2126. Xabc    ababc    y    &    abc
  2127. Xab*c    abc    y    &    abc
  2128. Xab*bc    abc    y    &    abc
  2129. Xab*bc    abbc    y    &    abbc
  2130. Xab*bc    abbbbc    y    &    abbbbc
  2131. Xab+bc    abbc    y    &    abbc
  2132. Xab+bc    abc    n    -    -
  2133. Xab+bc    abq    n    -    -
  2134. Xab+bc    abbbbc    y    &    abbbbc
  2135. Xab?bc    abbc    y    &    abbc
  2136. Xab?bc    abc    y    &    abc
  2137. Xab?bc    abbbbc    n    -    -
  2138. Xab?c    abc    y    &    abc
  2139. X^abc$    abc    y    &    abc
  2140. X^abc$    abcc    n    -    -
  2141. X^abc    abcc    y    &    abc
  2142. X^abc$    aabc    n    -    -
  2143. Xabc$    aabc    y    &    abc
  2144. X^    abc    y    &    
  2145. X$    abc    y    &    
  2146. Xa.c    abc    y    &    abc
  2147. Xa.c    axc    y    &    axc
  2148. Xa.*c    axyzc    y    &    axyzc
  2149. Xa.*c    axyzd    n    -    -
  2150. Xa[bc]d    abc    n    -    -
  2151. Xa[bc]d    abd    y    &    abd
  2152. Xa[b-d]e    abd    n    -    -
  2153. Xa[b-d]e    ace    y    &    ace
  2154. Xa[b-d]    aac    y    &    ac
  2155. Xa[-b]    a-    y    &    a-
  2156. Xa[b-]    a-    y    &    a-
  2157. Xa[b-a]    -    c    -    -
  2158. Xa[]b    -    c    -    -
  2159. Xa[    -    c    -    -
  2160. Xa]    a]    y    &    a]
  2161. Xa[]]b    a]b    y    &    a]b
  2162. Xa[^bc]d    aed    y    &    aed
  2163. Xa[^bc]d    abd    n    -    -
  2164. Xa[^-b]c    adc    y    &    adc
  2165. Xa[^-b]c    a-c    n    -    -
  2166. Xa[^]b]c    a]c    n    -    -
  2167. Xa[^]b]c    adc    y    &    adc
  2168. Xab|cd    abc    y    &    ab
  2169. Xab|cd    abcd    y    &    ab
  2170. X()ef    def    y    &-\1    ef-
  2171. X()*    -    c    -    -
  2172. X*a    -    c    -    -
  2173. X^*    -    c    -    -
  2174. X$*    -    c    -    -
  2175. X(*)b    -    c    -    -
  2176. X$b    b    n    -    -
  2177. Xa\    -    c    -    -
  2178. Xa\(b    a(b    y    &-\1    a(b-
  2179. Xa\(*b    ab    y    &    ab
  2180. Xa\(*b    a((b    y    &    a((b
  2181. Xa\\b    a\b    y    &    a\b
  2182. Xabc)    -    c    -    -
  2183. X(abc    -    c    -    -
  2184. X((a))    abc    y    &-\1-\2    a-a-a
  2185. X(a)b(c)    abc    y    &-\1-\2    abc-a-c
  2186. Xa+b+c    aabbabc    y    &    abc
  2187. Xa**    -    c    -    -
  2188. Xa*?    -    c    -    -
  2189. X(a*)*    -    c    -    -
  2190. X(a*)+    -    c    -    -
  2191. X(a|)*    -    c    -    -
  2192. X(a*|b)*    -    c    -    -
  2193. X(a+|b)*    ab    y    &-\1    ab-b
  2194. X(a+|b)+    ab    y    &-\1    ab-b
  2195. X(a+|b)?    ab    y    &-\1    a-a
  2196. X[^ab]*    cde    y    &    cde
  2197. X(^)*    -    c    -    -
  2198. X(ab|)*    -    c    -    -
  2199. X)(    -    c    -    -
  2200. X    abc    y    &    
  2201. Xabc        n    -    -
  2202. Xa*        y    &    
  2203. X([abc])*d    abbbcd    y    &-\1    abbbcd-c
  2204. X([abc])*bcd    abcd    y    &-\1    abcd-a
  2205. Xa|b|c|d|e    e    y    &    e
  2206. X(a|b|c|d|e)f    ef    y    &-\1    ef-e
  2207. X((a*|b))*    -    c    -    -
  2208. Xabcd*efg    abcdefg    y    &    abcdefg
  2209. Xab*    xabyabbbz    y    &    ab
  2210. Xab*    xayabbbz    y    &    a
  2211. X(ab|cd)e    abcde    y    &-\1    cde-cd
  2212. X[abhgefdc]ij    hij    y    &    hij
  2213. X^(ab|cd)e    abcde    n    x\1y    xy
  2214. X(abc|)ef    abcdef    y    &-\1    ef-
  2215. X(a|b)c*d    abcd    y    &-\1    bcd-b
  2216. X(ab|ab*)bc    abc    y    &-\1    abc-a
  2217. Xa([bc]*)c*    abc    y    &-\1    abc-bc
  2218. Xa([bc]*)(c*d)    abcd    y    &-\1-\2    abcd-bc-d
  2219. Xa([bc]+)(c*d)    abcd    y    &-\1-\2    abcd-bc-d
  2220. Xa([bc]*)(c+d)    abcd    y    &-\1-\2    abcd-b-cd
  2221. Xa[bcd]*dcdcde    adcdcde    y    &    adcdcde
  2222. Xa[bcd]+dcdcde    adcdcde    n    -    -
  2223. X(ab|a)b*c    abc    y    &-\1    abc-ab
  2224. X((a)(b)c)(d)    abcd    y    \1-\2-\3-\4    abc-a-b-d
  2225. X[a-zA-Z_][a-zA-Z0-9_]*    alpha    y    &    alpha
  2226. X^a(bc+|b[eh])g|.h$    abh    y    &-\1    bh-
  2227. X(bc+d$|ef*g.|h?i(j|k))    effgz    y    &-\1-\2    effgz-effgz-
  2228. X(bc+d$|ef*g.|h?i(j|k))    ij    y    &-\1-\2    ij-ij-j
  2229. X(bc+d$|ef*g.|h?i(j|k))    effg    n    -    -
  2230. X(bc+d$|ef*g.|h?i(j|k))    bcdd    n    -    -
  2231. X(bc+d$|ef*g.|h?i(j|k))    reffgz    y    &-\1-\2    effgz-effgz-
  2232. X((((((((((a))))))))))    -    c    -    -
  2233. X(((((((((a)))))))))    a    y    &    a
  2234. Xmultiple words of text    uh-uh    n    -    -
  2235. Xmultiple words    multiple words, yeah    y    &    multiple words
  2236. X(.*)c(.*)    abcde    y    &-\1-\2    abcde-ab-de
  2237. X\((.*), (.*)\)    (a, b)    y    (\2, \1)    (b, a)
  2238. !
  2239. echo done
  2240. exit 0
  2241.  
  2242.