160786Sps/*
260786Sps * regcomp and regexec -- regsub and regerror are elsewhere
360786Sps *
460786Sps *	Copyright (c) 1986 by University of Toronto.
560786Sps *	Written by Henry Spencer.  Not derived from licensed software.
660786Sps *
760786Sps *	Permission is granted to anyone to use this software for any
860786Sps *	purpose on any computer system, and to redistribute it freely,
960786Sps *	subject to the following restrictions:
1060786Sps *
1160786Sps *	1. The author is not responsible for the consequences of use of
1260786Sps *		this software, no matter how awful, even if they arise
1360786Sps *		from defects in it.
1460786Sps *
1560786Sps *	2. The origin of this software must not be misrepresented, either
1660786Sps *		by explicit claim or by omission.
1760786Sps *
1860786Sps *	3. Altered versions must be plainly marked as such, and must not
1960786Sps *		be misrepresented as being the original software.
2060786Sps *
2160786Sps * Beware that some of this code is subtly aware of the way operator
2260786Sps * precedence is structured in regular expressions.  Serious changes in
2360786Sps * regular-expression syntax might require a total rethink.
2460786Sps *
2560786Sps * *** NOTE: this code has been altered slightly for use in Tcl. ***
2660786Sps * Slightly modified by David MacKenzie to undo most of the changes for TCL.
2760786Sps * Added regexec2 with notbol parameter. -- 4/19/99 Mark Nudelman
2860786Sps */
2960786Sps
3060786Sps#include "less.h"
3160786Sps#if HAVE_STDIO_H
3260786Sps#include <stdio.h>
3360786Sps#endif
3460786Sps#if HAVE_STDLIB_H
3560786Sps#include <stdlib.h>
3660786Sps#endif
3760786Sps#if HAVE_STRING_H
3860786Sps#include <string.h>
3960786Sps#endif
4060786Sps#include "regexp.h"
4160786Sps
4260786Sps/*
4360786Sps * The "internal use only" fields in regexp.h are present to pass info from
4460786Sps * compile to execute that permits the execute phase to run lots faster on
4560786Sps * simple cases.  They are:
4660786Sps *
4760786Sps * regstart	char that must begin a match; '\0' if none obvious
4860786Sps * reganch	is the match anchored (at beginning-of-line only)?
4960786Sps * regmust	string (pointer into program) that match must include, or NULL
5060786Sps * regmlen	length of regmust string
5160786Sps *
5260786Sps * Regstart and reganch permit very fast decisions on suitable starting points
5360786Sps * for a match, cutting down the work a lot.  Regmust permits fast rejection
5460786Sps * of lines that cannot possibly match.  The regmust tests are costly enough
5560786Sps * that regcomp() supplies a regmust only if the r.e. contains something
5660786Sps * potentially expensive (at present, the only such thing detected is * or +
5760786Sps * at the start of the r.e., which can involve a lot of backup).  Regmlen is
5860786Sps * supplied because the test in regexec() needs it and regcomp() is
5960786Sps * computing it anyway.
6060786Sps */
6160786Sps
6260786Sps/*
6360786Sps * Structure for regexp "program".  This is essentially a linear encoding
6460786Sps * of a nondeterministic finite-state machine (aka syntax charts or
6560786Sps * "railroad normal form" in parsing technology).  Each node is an opcode
6660786Sps * plus a "next" pointer, possibly plus an operand.  "Next" pointers of
6760786Sps * all nodes except BRANCH implement concatenation; a "next" pointer with
6860786Sps * a BRANCH on both ends of it is connecting two alternatives.  (Here we
6960786Sps * have one of the subtle syntax dependencies:  an individual BRANCH (as
7060786Sps * opposed to a collection of them) is never concatenated with anything
7160786Sps * because of operator precedence.)  The operand of some types of node is
7260786Sps * a literal string; for others, it is a node leading into a sub-FSM.  In
7360786Sps * particular, the operand of a BRANCH node is the first node of the branch.
7460786Sps * (NB this is *not* a tree structure:  the tail of the branch connects
7560786Sps * to the thing following the set of BRANCHes.)  The opcodes are:
7660786Sps */
7760786Sps
7860786Sps/* definition	number	opnd?	meaning */
7960786Sps#undef EOL
8060786Sps#define	END	0	/* no	End of program. */
8160786Sps#define	BOL	1	/* no	Match "" at beginning of line. */
8260786Sps#define	EOL	2	/* no	Match "" at end of line. */
8360786Sps#define	ANY	3	/* no	Match any one character. */
8460786Sps#define	ANYOF	4	/* str	Match any character in this string. */
8560786Sps#define	ANYBUT	5	/* str	Match any character not in this string. */
8660786Sps#define	BRANCH	6	/* node	Match this alternative, or the next... */
8760786Sps#define	BACK	7	/* no	Match "", "next" ptr points backward. */
8860786Sps#define	EXACTLY	8	/* str	Match this string. */
8960786Sps#define	NOTHING	9	/* no	Match empty string. */
9060786Sps#define	STAR	10	/* node	Match this (simple) thing 0 or more times. */
9160786Sps#define	PLUS	11	/* node	Match this (simple) thing 1 or more times. */
9260786Sps#define	OPEN	20	/* no	Mark this point in input as start of #n. */
9360786Sps			/*	OPEN+1 is number 1, etc. */
9460786Sps#define	CLOSE	30	/* no	Analogous to OPEN. */
9560786Sps
9660786Sps/*
9760786Sps * Opcode notes:
9860786Sps *
9960786Sps * BRANCH	The set of branches constituting a single choice are hooked
10060786Sps *		together with their "next" pointers, since precedence prevents
10160786Sps *		anything being concatenated to any individual branch.  The
10260786Sps *		"next" pointer of the last BRANCH in a choice points to the
10360786Sps *		thing following the whole choice.  This is also where the
10460786Sps *		final "next" pointer of each individual branch points; each
10560786Sps *		branch starts with the operand node of a BRANCH node.
10660786Sps *
10760786Sps * BACK		Normal "next" pointers all implicitly point forward; BACK
10860786Sps *		exists to make loop structures possible.
10960786Sps *
11060786Sps * STAR,PLUS	'?', and complex '*' and '+', are implemented as circular
11160786Sps *		BRANCH structures using BACK.  Simple cases (one character
11260786Sps *		per match) are implemented with STAR and PLUS for speed
11360786Sps *		and to minimize recursive plunges.
11460786Sps *
11560786Sps * OPEN,CLOSE	...are numbered at compile time.
11660786Sps */
11760786Sps
11860786Sps/*
11960786Sps * A node is one char of opcode followed by two chars of "next" pointer.
12060786Sps * "Next" pointers are stored as two 8-bit pieces, high order first.  The
12160786Sps * value is a positive offset from the opcode of the node containing it.
12260786Sps * An operand, if any, simply follows the node.  (Note that much of the
12360786Sps * code generation knows about this implicit relationship.)
12460786Sps *
12560786Sps * Using two bytes for the "next" pointer is vast overkill for most things,
12660786Sps * but allows patterns to get big without disasters.
12760786Sps */
12860786Sps#define	OP(p)	(*(p))
12960786Sps#define	NEXT(p)	(((*((p)+1)&0377)<<8) + (*((p)+2)&0377))
13060786Sps#define	OPERAND(p)	((p) + 3)
13160786Sps
13260786Sps/*
13360786Sps * See regmagic.h for one further detail of program structure.
13460786Sps */
13560786Sps
13660786Sps
13760786Sps/*
13860786Sps * Utility definitions.
13960786Sps */
14060786Sps#ifndef CHARBITS
14160786Sps#define	UCHARAT(p)	((int)*(unsigned char *)(p))
14260786Sps#else
14360786Sps#define	UCHARAT(p)	((int)*(p)&CHARBITS)
14460786Sps#endif
14560786Sps
14660786Sps#define	FAIL(m)	{ regerror(m); return(NULL); }
14760786Sps#define	ISMULT(c)	((c) == '*' || (c) == '+' || (c) == '?')
14860786Sps#define	META	"^$.[()|?+*\\"
14960786Sps
15060786Sps/*
15160786Sps * Flags to be passed up and down.
15260786Sps */
15360786Sps#define	HASWIDTH	01	/* Known never to match null string. */
15460786Sps#define	SIMPLE		02	/* Simple enough to be STAR/PLUS operand. */
15560786Sps#define	SPSTART		04	/* Starts with * or +. */
15660786Sps#define	WORST		0	/* Worst case. */
15760786Sps
15860786Sps/*
15960786Sps * Global work variables for regcomp().
16060786Sps */
16160786Spsstatic char *regparse;		/* Input-scan pointer. */
16260786Spsstatic int regnpar;		/* () count. */
16360786Spsstatic char regdummy;
16460786Spsstatic char *regcode;		/* Code-emit pointer; &regdummy = don't. */
16560786Spsstatic long regsize;		/* Code size. */
16660786Sps
16760786Sps/*
16860786Sps * The first byte of the regexp internal "program" is actually this magic
16960786Sps * number; the start node begins in the second byte.
17060786Sps */
17160786Sps#define	MAGIC	0234
17260786Sps
17360786Sps
17460786Sps/*
17560786Sps * Forward declarations for regcomp()'s friends.
17660786Sps */
17760786Sps#ifndef STATIC
17860786Sps#define	STATIC	static
17960786Sps#endif
18060786SpsSTATIC char *reg();
18160786SpsSTATIC char *regbranch();
18260786SpsSTATIC char *regpiece();
18360786SpsSTATIC char *regatom();
18460786SpsSTATIC char *regnode();
18560786SpsSTATIC char *regnext();
18660786SpsSTATIC void regc();
18760786SpsSTATIC void reginsert();
18860786SpsSTATIC void regtail();
18960786SpsSTATIC void regoptail();
19060786Sps#ifdef STRCSPN
19160786SpsSTATIC int strcspn();
19260786Sps#endif
19360786Sps
19460786Sps/*
19560786Sps - regcomp - compile a regular expression into internal code
19660786Sps *
19760786Sps * We can't allocate space until we know how big the compiled form will be,
19860786Sps * but we can't compile it (and thus know how big it is) until we've got a
19960786Sps * place to put the code.  So we cheat:  we compile it twice, once with code
20060786Sps * generation turned off and size counting turned on, and once "for real".
20160786Sps * This also means that we don't allocate space until we are sure that the
20260786Sps * thing really will compile successfully, and we never have to move the
20360786Sps * code and thus invalidate pointers into it.  (Note that it has to be in
20460786Sps * one piece because free() must be able to free it all.)
20560786Sps *
20660786Sps * Beware that the optimization-preparation code in here knows about some
20760786Sps * of the structure of the compiled regexp.
20860786Sps */
20960786Spsregexp *
21060786Spsregcomp(exp)
21160786Spschar *exp;
21260786Sps{
21360786Sps	register regexp *r;
21460786Sps	register char *scan;
21560786Sps	register char *longest;
21660786Sps	register int len;
21760786Sps	int flags;
21860786Sps
21960786Sps	if (exp == NULL)
22060786Sps		FAIL("NULL argument");
22160786Sps
22260786Sps	/* First pass: determine size, legality. */
22360786Sps	regparse = exp;
22460786Sps	regnpar = 1;
22560786Sps	regsize = 0L;
22660786Sps	regcode = &regdummy;
22760786Sps	regc(MAGIC);
22860786Sps	if (reg(0, &flags) == NULL)
22960786Sps		return(NULL);
23060786Sps
23160786Sps	/* Small enough for pointer-storage convention? */
23260786Sps	if (regsize >= 32767L)		/* Probably could be 65535L. */
23360786Sps		FAIL("regexp too big");
23460786Sps
23560786Sps	/* Allocate space. */
23660786Sps	r = (regexp *)malloc(sizeof(regexp) + (unsigned)regsize);
23760786Sps	if (r == NULL)
23860786Sps		FAIL("out of space");
23960786Sps
24060786Sps	/* Second pass: emit code. */
24160786Sps	regparse = exp;
24260786Sps	regnpar = 1;
24360786Sps	regcode = r->program;
24460786Sps	regc(MAGIC);
24560786Sps	if (reg(0, &flags) == NULL)
24660786Sps		return(NULL);
24760786Sps
24860786Sps	/* Dig out information for optimizations. */
24960786Sps	r->regstart = '\0';	/* Worst-case defaults. */
25060786Sps	r->reganch = 0;
25160786Sps	r->regmust = NULL;
25260786Sps	r->regmlen = 0;
25360786Sps	scan = r->program+1;			/* First BRANCH. */
25460786Sps	if (OP(regnext(scan)) == END) {		/* Only one top-level choice. */
25560786Sps		scan = OPERAND(scan);
25660786Sps
25760786Sps		/* Starting-point info. */
25860786Sps		if (OP(scan) == EXACTLY)
25960786Sps			r->regstart = *OPERAND(scan);
26060786Sps		else if (OP(scan) == BOL)
26160786Sps			r->reganch++;
26260786Sps
26360786Sps		/*
26460786Sps		 * If there's something expensive in the r.e., find the
26560786Sps		 * longest literal string that must appear and make it the
26660786Sps		 * regmust.  Resolve ties in favor of later strings, since
26760786Sps		 * the regstart check works with the beginning of the r.e.
26860786Sps		 * and avoiding duplication strengthens checking.  Not a
26960786Sps		 * strong reason, but sufficient in the absence of others.
27060786Sps		 */
27160786Sps		if (flags&SPSTART) {
27260786Sps			longest = NULL;
27360786Sps			len = 0;
27460786Sps			for (; scan != NULL; scan = regnext(scan))
27560786Sps				if (OP(scan) == EXACTLY && ((int) strlen(OPERAND(scan))) >= len) {
27660786Sps					longest = OPERAND(scan);
27760786Sps					len = strlen(OPERAND(scan));
27860786Sps				}
27960786Sps			r->regmust = longest;
28060786Sps			r->regmlen = len;
28160786Sps		}
28260786Sps	}
28360786Sps
28460786Sps	return(r);
28560786Sps}
28660786Sps
28760786Sps/*
28860786Sps - reg - regular expression, i.e. main body or parenthesized thing
28960786Sps *
29060786Sps * Caller must absorb opening parenthesis.
29160786Sps *
29260786Sps * Combining parenthesis handling with the base level of regular expression
29360786Sps * is a trifle forced, but the need to tie the tails of the branches to what
29460786Sps * follows makes it hard to avoid.
29560786Sps */
29660786Spsstatic char *
29760786Spsreg(paren, flagp)
29860786Spsint paren;			/* Parenthesized? */
29960786Spsint *flagp;
30060786Sps{
30160786Sps	register char *ret;
30260786Sps	register char *br;
30360786Sps	register char *ender;
30460786Sps	register int parno = 0;
30560786Sps	int flags;
30660786Sps
30760786Sps	*flagp = HASWIDTH;	/* Tentatively. */
30860786Sps
30960786Sps	/* Make an OPEN node, if parenthesized. */
31060786Sps	if (paren) {
31160786Sps		if (regnpar >= NSUBEXP)
31260786Sps			FAIL("too many ()");
31360786Sps		parno = regnpar;
31460786Sps		regnpar++;
31560786Sps		ret = regnode(OPEN+parno);
31660786Sps	} else
31760786Sps		ret = NULL;
31860786Sps
31960786Sps	/* Pick up the branches, linking them together. */
32060786Sps	br = regbranch(&flags);
32160786Sps	if (br == NULL)
32260786Sps		return(NULL);
32360786Sps	if (ret != NULL)
32460786Sps		regtail(ret, br);	/* OPEN -> first. */
32560786Sps	else
32660786Sps		ret = br;
32760786Sps	if (!(flags&HASWIDTH))
32860786Sps		*flagp &= ~HASWIDTH;
32960786Sps	*flagp |= flags&SPSTART;
33060786Sps	while (*regparse == '|') {
33160786Sps		regparse++;
33260786Sps		br = regbranch(&flags);
33360786Sps		if (br == NULL)
33460786Sps			return(NULL);
33560786Sps		regtail(ret, br);	/* BRANCH -> BRANCH. */
33660786Sps		if (!(flags&HASWIDTH))
33760786Sps			*flagp &= ~HASWIDTH;
33860786Sps		*flagp |= flags&SPSTART;
33960786Sps	}
34060786Sps
34160786Sps	/* Make a closing node, and hook it on the end. */
34260786Sps	ender = regnode((paren) ? CLOSE+parno : END);
34360786Sps	regtail(ret, ender);
34460786Sps
34560786Sps	/* Hook the tails of the branches to the closing node. */
34660786Sps	for (br = ret; br != NULL; br = regnext(br))
34760786Sps		regoptail(br, ender);
34860786Sps
34960786Sps	/* Check for proper termination. */
35060786Sps	if (paren && *regparse++ != ')') {
35160786Sps		FAIL("unmatched ()");
35260786Sps	} else if (!paren && *regparse != '\0') {
35360786Sps		if (*regparse == ')') {
35460786Sps			FAIL("unmatched ()");
35560786Sps		} else
35660786Sps			FAIL("junk on end");	/* "Can't happen". */
35760786Sps		/* NOTREACHED */
35860786Sps	}
35960786Sps
36060786Sps	return(ret);
36160786Sps}
36260786Sps
36360786Sps/*
36460786Sps - regbranch - one alternative of an | operator
36560786Sps *
36660786Sps * Implements the concatenation operator.
36760786Sps */
36860786Spsstatic char *
36960786Spsregbranch(flagp)
37060786Spsint *flagp;
37160786Sps{
37260786Sps	register char *ret;
37360786Sps	register char *chain;
37460786Sps	register char *latest;
37560786Sps	int flags;
37660786Sps
37760786Sps	*flagp = WORST;		/* Tentatively. */
37860786Sps
37960786Sps	ret = regnode(BRANCH);
38060786Sps	chain = NULL;
38160786Sps	while (*regparse != '\0' && *regparse != '|' && *regparse != ')') {
38260786Sps		latest = regpiece(&flags);
38360786Sps		if (latest == NULL)
38460786Sps			return(NULL);
38560786Sps		*flagp |= flags&HASWIDTH;
38660786Sps		if (chain == NULL)	/* First piece. */
38760786Sps			*flagp |= flags&SPSTART;
38860786Sps		else
38960786Sps			regtail(chain, latest);
39060786Sps		chain = latest;
39160786Sps	}
39260786Sps	if (chain == NULL)	/* Loop ran zero times. */
39360786Sps		(void) regnode(NOTHING);
39460786Sps
39560786Sps	return(ret);
39660786Sps}
39760786Sps
39860786Sps/*
39960786Sps - regpiece - something followed by possible [*+?]
40060786Sps *
40160786Sps * Note that the branching code sequences used for ? and the general cases
40260786Sps * of * and + are somewhat optimized:  they use the same NOTHING node as
40360786Sps * both the endmarker for their branch list and the body of the last branch.
40460786Sps * It might seem that this node could be dispensed with entirely, but the
40560786Sps * endmarker role is not redundant.
40660786Sps */
40760786Spsstatic char *
40860786Spsregpiece(flagp)
40960786Spsint *flagp;
41060786Sps{
41160786Sps	register char *ret;
41260786Sps	register char op;
41360786Sps	register char *next;
41460786Sps	int flags;
41560786Sps
41660786Sps	ret = regatom(&flags);
41760786Sps	if (ret == NULL)
41860786Sps		return(NULL);
41960786Sps
42060786Sps	op = *regparse;
42160786Sps	if (!ISMULT(op)) {
42260786Sps		*flagp = flags;
42360786Sps		return(ret);
42460786Sps	}
42560786Sps
42660786Sps	if (!(flags&HASWIDTH) && op != '?')
42760786Sps		FAIL("*+ operand could be empty");
42860786Sps	*flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH);
42960786Sps
43060786Sps	if (op == '*' && (flags&SIMPLE))
43160786Sps		reginsert(STAR, ret);
43260786Sps	else if (op == '*') {
43360786Sps		/* Emit x* as (x&|), where & means "self". */
43460786Sps		reginsert(BRANCH, ret);			/* Either x */
43560786Sps		regoptail(ret, regnode(BACK));		/* and loop */
43660786Sps		regoptail(ret, ret);			/* back */
43760786Sps		regtail(ret, regnode(BRANCH));		/* or */
43860786Sps		regtail(ret, regnode(NOTHING));		/* null. */
43960786Sps	} else if (op == '+' && (flags&SIMPLE))
44060786Sps		reginsert(PLUS, ret);
44160786Sps	else if (op == '+') {
44260786Sps		/* Emit x+ as x(&|), where & means "self". */
44360786Sps		next = regnode(BRANCH);			/* Either */
44460786Sps		regtail(ret, next);
44560786Sps		regtail(regnode(BACK), ret);		/* loop back */
44660786Sps		regtail(next, regnode(BRANCH));		/* or */
44760786Sps		regtail(ret, regnode(NOTHING));		/* null. */
44860786Sps	} else if (op == '?') {
44960786Sps		/* Emit x? as (x|) */
45060786Sps		reginsert(BRANCH, ret);			/* Either x */
45160786Sps		regtail(ret, regnode(BRANCH));		/* or */
45260786Sps		next = regnode(NOTHING);		/* null. */
45360786Sps		regtail(ret, next);
45460786Sps		regoptail(ret, next);
45560786Sps	}
45660786Sps	regparse++;
45760786Sps	if (ISMULT(*regparse))
45860786Sps		FAIL("nested *?+");
45960786Sps
46060786Sps	return(ret);
46160786Sps}
46260786Sps
46360786Sps/*
46460786Sps - regatom - the lowest level
46560786Sps *
46660786Sps * Optimization:  gobbles an entire sequence of ordinary characters so that
46760786Sps * it can turn them into a single node, which is smaller to store and
46860786Sps * faster to run.  Backslashed characters are exceptions, each becoming a
46960786Sps * separate node; the code is simpler that way and it's not worth fixing.
47060786Sps */
47160786Spsstatic char *
47260786Spsregatom(flagp)
47360786Spsint *flagp;
47460786Sps{
47560786Sps	register char *ret;
47660786Sps	int flags;
47760786Sps
47860786Sps	*flagp = WORST;		/* Tentatively. */
47960786Sps
48060786Sps	switch (*regparse++) {
48160786Sps	case '^':
48260786Sps		ret = regnode(BOL);
48360786Sps		break;
48460786Sps	case '$':
48560786Sps		ret = regnode(EOL);
48660786Sps		break;
48760786Sps	case '.':
48860786Sps		ret = regnode(ANY);
48960786Sps		*flagp |= HASWIDTH|SIMPLE;
49060786Sps		break;
49160786Sps	case '[': {
49260786Sps			register int clss;
49360786Sps			register int classend;
49460786Sps
49560786Sps			if (*regparse == '^') {	/* Complement of range. */
49660786Sps				ret = regnode(ANYBUT);
49760786Sps				regparse++;
49860786Sps			} else
49960786Sps				ret = regnode(ANYOF);
50060786Sps			if (*regparse == ']' || *regparse == '-')
50160786Sps				regc(*regparse++);
50260786Sps			while (*regparse != '\0' && *regparse != ']') {
50360786Sps				if (*regparse == '-') {
50460786Sps					regparse++;
50560786Sps					if (*regparse == ']' || *regparse == '\0')
50660786Sps						regc('-');
50760786Sps					else {
50860786Sps						clss = UCHARAT(regparse-2)+1;
50960786Sps						classend = UCHARAT(regparse);
51060786Sps						if (clss > classend+1)
51160786Sps							FAIL("invalid [] range");
51260786Sps						for (; clss <= classend; clss++)
51360786Sps							regc(clss);
51460786Sps						regparse++;
51560786Sps					}
51660786Sps				} else
51760786Sps					regc(*regparse++);
51860786Sps			}
51960786Sps			regc('\0');
52060786Sps			if (*regparse != ']')
52160786Sps				FAIL("unmatched []");
52260786Sps			regparse++;
52360786Sps			*flagp |= HASWIDTH|SIMPLE;
52460786Sps		}
52560786Sps		break;
52660786Sps	case '(':
52760786Sps		ret = reg(1, &flags);
52860786Sps		if (ret == NULL)
52960786Sps			return(NULL);
53060786Sps		*flagp |= flags&(HASWIDTH|SPSTART);
53160786Sps		break;
53260786Sps	case '\0':
53360786Sps	case '|':
53460786Sps	case ')':
53560786Sps		FAIL("internal urp");	/* Supposed to be caught earlier. */
53660786Sps		/* NOTREACHED */
53760786Sps		break;
53860786Sps	case '?':
53960786Sps	case '+':
54060786Sps	case '*':
54160786Sps		FAIL("?+* follows nothing");
54260786Sps		/* NOTREACHED */
54360786Sps		break;
54460786Sps	case '\\':
54560786Sps		if (*regparse == '\0')
54660786Sps			FAIL("trailing \\");
54760786Sps		ret = regnode(EXACTLY);
54860786Sps		regc(*regparse++);
54960786Sps		regc('\0');
55060786Sps		*flagp |= HASWIDTH|SIMPLE;
55160786Sps		break;
55260786Sps	default: {
55360786Sps			register int len;
55460786Sps			register char ender;
55560786Sps
55660786Sps			regparse--;
55760786Sps			len = strcspn(regparse, META);
55860786Sps			if (len <= 0)
55960786Sps				FAIL("internal disaster");
56060786Sps			ender = *(regparse+len);
56160786Sps			if (len > 1 && ISMULT(ender))
56260786Sps				len--;		/* Back off clear of ?+* operand. */
56360786Sps			*flagp |= HASWIDTH;
56460786Sps			if (len == 1)
56560786Sps				*flagp |= SIMPLE;
56660786Sps			ret = regnode(EXACTLY);
56760786Sps			while (len > 0) {
56860786Sps				regc(*regparse++);
56960786Sps				len--;
57060786Sps			}
57160786Sps			regc('\0');
57260786Sps		}
57360786Sps		break;
57460786Sps	}
57560786Sps
57660786Sps	return(ret);
57760786Sps}
57860786Sps
57960786Sps/*
58060786Sps - regnode - emit a node
58160786Sps */
58260786Spsstatic char *			/* Location. */
58360786Spsregnode(op)
58460786Spschar op;
58560786Sps{
58660786Sps	register char *ret;
58760786Sps	register char *ptr;
58860786Sps
58960786Sps	ret = regcode;
59060786Sps	if (ret == &regdummy) {
59160786Sps		regsize += 3;
59260786Sps		return(ret);
59360786Sps	}
59460786Sps
59560786Sps	ptr = ret;
59660786Sps	*ptr++ = op;
59760786Sps	*ptr++ = '\0';		/* Null "next" pointer. */
59860786Sps	*ptr++ = '\0';
59960786Sps	regcode = ptr;
60060786Sps
60160786Sps	return(ret);
60260786Sps}
60360786Sps
60460786Sps/*
60560786Sps - regc - emit (if appropriate) a byte of code
60660786Sps */
60760786Spsstatic void
60860786Spsregc(b)
60960786Spschar b;
61060786Sps{
61160786Sps	if (regcode != &regdummy)
61260786Sps		*regcode++ = b;
61360786Sps	else
61460786Sps		regsize++;
61560786Sps}
61660786Sps
61760786Sps/*
61860786Sps - reginsert - insert an operator in front of already-emitted operand
61960786Sps *
62060786Sps * Means relocating the operand.
62160786Sps */
62260786Spsstatic void
62360786Spsreginsert(op, opnd)
62460786Spschar op;
62560786Spschar *opnd;
62660786Sps{
62760786Sps	register char *src;
62860786Sps	register char *dst;
62960786Sps	register char *place;
63060786Sps
63160786Sps	if (regcode == &regdummy) {
63260786Sps		regsize += 3;
63360786Sps		return;
63460786Sps	}
63560786Sps
63660786Sps	src = regcode;
63760786Sps	regcode += 3;
63860786Sps	dst = regcode;
63960786Sps	while (src > opnd)
64060786Sps		*--dst = *--src;
64160786Sps
64260786Sps	place = opnd;		/* Op node, where operand used to be. */
64360786Sps	*place++ = op;
64460786Sps	*place++ = '\0';
64560786Sps	*place++ = '\0';
64660786Sps}
64760786Sps
64860786Sps/*
64960786Sps - regtail - set the next-pointer at the end of a node chain
65060786Sps */
65160786Spsstatic void
65260786Spsregtail(p, val)
65360786Spschar *p;
65460786Spschar *val;
65560786Sps{
65660786Sps	register char *scan;
65760786Sps	register char *temp;
65860786Sps	register int offset;
65960786Sps
66060786Sps	if (p == &regdummy)
66160786Sps		return;
66260786Sps
66360786Sps	/* Find last node. */
66460786Sps	scan = p;
66560786Sps	for (;;) {
66660786Sps		temp = regnext(scan);
66760786Sps		if (temp == NULL)
66860786Sps			break;
66960786Sps		scan = temp;
67060786Sps	}
67160786Sps
67260786Sps	if (OP(scan) == BACK)
67360786Sps		offset = scan - val;
67460786Sps	else
67560786Sps		offset = val - scan;
67660786Sps	*(scan+1) = (offset>>8)&0377;
67760786Sps	*(scan+2) = offset&0377;
67860786Sps}
67960786Sps
68060786Sps/*
68160786Sps - regoptail - regtail on operand of first argument; nop if operandless
68260786Sps */
68360786Spsstatic void
68460786Spsregoptail(p, val)
68560786Spschar *p;
68660786Spschar *val;
68760786Sps{
68860786Sps	/* "Operandless" and "op != BRANCH" are synonymous in practice. */
68960786Sps	if (p == NULL || p == &regdummy || OP(p) != BRANCH)
69060786Sps		return;
69160786Sps	regtail(OPERAND(p), val);
69260786Sps}
69360786Sps
69460786Sps/*
69560786Sps * regexec and friends
69660786Sps */
69760786Sps
69860786Sps/*
69960786Sps * Global work variables for regexec().
70060786Sps */
70160786Spsstatic char *reginput;		/* String-input pointer. */
70260786Spsstatic char *regbol;		/* Beginning of input, for ^ check. */
70360786Spsstatic char **regstartp;	/* Pointer to startp array. */
70460786Spsstatic char **regendp;		/* Ditto for endp. */
70560786Sps
70660786Sps/*
70760786Sps * Forwards.
70860786Sps */
70960786SpsSTATIC int regtry();
71060786SpsSTATIC int regmatch();
71160786SpsSTATIC int regrepeat();
71260786Sps
71360786Sps#ifdef DEBUG
71460786Spsint regnarrate = 0;
71560786Spsvoid regdump();
71660786SpsSTATIC char *regprop();
71760786Sps#endif
71860786Sps
71960786Sps/*
72060786Sps - regexec - match a regexp against a string
72160786Sps */
72260786Spsint
72360786Spsregexec2(prog, string, notbol)
72460786Spsregister regexp *prog;
72560786Spsregister char *string;
72660786Spsint notbol;
72760786Sps{
72860786Sps	register char *s;
72960786Sps
73060786Sps	/* Be paranoid... */
73160786Sps	if (prog == NULL || string == NULL) {
73260786Sps		regerror("NULL parameter");
73360786Sps		return(0);
73460786Sps	}
73560786Sps
73660786Sps	/* Check validity of program. */
73760786Sps	if (UCHARAT(prog->program) != MAGIC) {
73860786Sps		regerror("corrupted program");
73960786Sps		return(0);
74060786Sps	}
74160786Sps
74260786Sps	/* If there is a "must appear" string, look for it. */
74360786Sps	if (prog->regmust != NULL) {
74460786Sps		s = string;
74560786Sps		while ((s = strchr(s, prog->regmust[0])) != NULL) {
74660786Sps			if (strncmp(s, prog->regmust, prog->regmlen) == 0)
74760786Sps				break;	/* Found it. */
74860786Sps			s++;
74960786Sps		}
75060786Sps		if (s == NULL)	/* Not present. */
75160786Sps			return(0);
75260786Sps	}
75360786Sps
75460786Sps	/* Mark beginning of line for ^ . */
75560786Sps	if (notbol)
75660786Sps		regbol = NULL;
75760786Sps	else
75860786Sps		regbol = string;
75960786Sps
76060786Sps	/* Simplest case:  anchored match need be tried only once. */
76160786Sps	if (prog->reganch)
76260786Sps		return(regtry(prog, string));
76360786Sps
76460786Sps	/* Messy cases:  unanchored match. */
76560786Sps	s = string;
76660786Sps	if (prog->regstart != '\0')
76760786Sps		/* We know what char it must start with. */
76860786Sps		while ((s = strchr(s, prog->regstart)) != NULL) {
76960786Sps			if (regtry(prog, s))
77060786Sps				return(1);
77160786Sps			s++;
77260786Sps		}
77360786Sps	else
77460786Sps		/* We don't -- general case. */
77560786Sps		do {
77660786Sps			if (regtry(prog, s))
77760786Sps				return(1);
77860786Sps		} while (*s++ != '\0');
77960786Sps
78060786Sps	/* Failure. */
78160786Sps	return(0);
78260786Sps}
78360786Sps
78460786Spsint
78560786Spsregexec(prog, string)
78660786Spsregister regexp *prog;
78760786Spsregister char *string;
78860786Sps{
78960786Sps	return regexec2(prog, string, 0);
79060786Sps}
79160786Sps
79260786Sps/*
79360786Sps - regtry - try match at specific point
79460786Sps */
79560786Spsstatic int			/* 0 failure, 1 success */
79660786Spsregtry(prog, string)
79760786Spsregexp *prog;
79860786Spschar *string;
79960786Sps{
80060786Sps	register int i;
80160786Sps	register char **sp;
80260786Sps	register char **ep;
80360786Sps
80460786Sps	reginput = string;
80560786Sps	regstartp = prog->startp;
80660786Sps	regendp = prog->endp;
80760786Sps
80860786Sps	sp = prog->startp;
80960786Sps	ep = prog->endp;
81060786Sps	for (i = NSUBEXP; i > 0; i--) {
81160786Sps		*sp++ = NULL;
81260786Sps		*ep++ = NULL;
81360786Sps	}
81460786Sps	if (regmatch(prog->program + 1)) {
81560786Sps		prog->startp[0] = string;
81660786Sps		prog->endp[0] = reginput;
81760786Sps		return(1);
81860786Sps	} else
81960786Sps		return(0);
82060786Sps}
82160786Sps
82260786Sps/*
82360786Sps - regmatch - main matching routine
82460786Sps *
82560786Sps * Conceptually the strategy is simple:  check to see whether the current
82660786Sps * node matches, call self recursively to see whether the rest matches,
82760786Sps * and then act accordingly.  In practice we make some effort to avoid
82860786Sps * recursion, in particular by going through "ordinary" nodes (that don't
82960786Sps * need to know whether the rest of the match failed) by a loop instead of
83060786Sps * by recursion.
83160786Sps */
83260786Spsstatic int			/* 0 failure, 1 success */
83360786Spsregmatch(prog)
83460786Spschar *prog;
83560786Sps{
83660786Sps	register char *scan;	/* Current node. */
83760786Sps	char *next;		/* Next node. */
83860786Sps
83960786Sps	scan = prog;
84060786Sps#ifdef DEBUG
84160786Sps	if (scan != NULL && regnarrate)
84260786Sps		fprintf(stderr, "%s(\n", regprop(scan));
84360786Sps#endif
84460786Sps	while (scan != NULL) {
84560786Sps#ifdef DEBUG
84660786Sps		if (regnarrate)
84760786Sps			fprintf(stderr, "%s...\n", regprop(scan));
84860786Sps#endif
84960786Sps		next = regnext(scan);
85060786Sps
85160786Sps		switch (OP(scan)) {
85260786Sps		case BOL:
85360786Sps			if (reginput != regbol)
85460786Sps				return(0);
85560786Sps			break;
85660786Sps		case EOL:
85760786Sps			if (*reginput != '\0')
85860786Sps				return(0);
85960786Sps			break;
86060786Sps		case ANY:
86160786Sps			if (*reginput == '\0')
86260786Sps				return(0);
86360786Sps			reginput++;
86460786Sps			break;
86560786Sps		case EXACTLY: {
86660786Sps				register int len;
86760786Sps				register char *opnd;
86860786Sps
86960786Sps				opnd = OPERAND(scan);
87060786Sps				/* Inline the first character, for speed. */
87160786Sps				if (*opnd != *reginput)
87260786Sps					return(0);
87360786Sps				len = strlen(opnd);
87460786Sps				if (len > 1 && strncmp(opnd, reginput, len) != 0)
87560786Sps					return(0);
87660786Sps				reginput += len;
87760786Sps			}
87860786Sps			break;
87960786Sps		case ANYOF:
88060786Sps 			if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) == NULL)
88160786Sps				return(0);
88260786Sps			reginput++;
88360786Sps			break;
88460786Sps		case ANYBUT:
88560786Sps 			if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) != NULL)
88660786Sps				return(0);
88760786Sps			reginput++;
88860786Sps			break;
88960786Sps		case NOTHING:
89060786Sps			break;
89160786Sps		case BACK:
89260786Sps			break;
89360786Sps		case OPEN+1:
89460786Sps		case OPEN+2:
89560786Sps		case OPEN+3:
89660786Sps		case OPEN+4:
89760786Sps		case OPEN+5:
89860786Sps		case OPEN+6:
89960786Sps		case OPEN+7:
90060786Sps		case OPEN+8:
90160786Sps		case OPEN+9: {
90260786Sps				register int no;
90360786Sps				register char *save;
90460786Sps
90560786Sps				no = OP(scan) - OPEN;
90660786Sps				save = reginput;
90760786Sps
90860786Sps				if (regmatch(next)) {
90960786Sps					/*
91060786Sps					 * Don't set startp if some later
91160786Sps					 * invocation of the same parentheses
91260786Sps					 * already has.
91360786Sps					 */
91460786Sps					if (regstartp[no] == NULL)
91560786Sps						regstartp[no] = save;
91660786Sps					return(1);
91760786Sps				} else
91860786Sps					return(0);
91960786Sps			}
92060786Sps			/* NOTREACHED */
92160786Sps			break;
92260786Sps		case CLOSE+1:
92360786Sps		case CLOSE+2:
92460786Sps		case CLOSE+3:
92560786Sps		case CLOSE+4:
92660786Sps		case CLOSE+5:
92760786Sps		case CLOSE+6:
92860786Sps		case CLOSE+7:
92960786Sps		case CLOSE+8:
93060786Sps		case CLOSE+9: {
93160786Sps				register int no;
93260786Sps				register char *save;
93360786Sps
93460786Sps				no = OP(scan) - CLOSE;
93560786Sps				save = reginput;
93660786Sps
93760786Sps				if (regmatch(next)) {
93860786Sps					/*
93960786Sps					 * Don't set endp if some later
94060786Sps					 * invocation of the same parentheses
94160786Sps					 * already has.
94260786Sps					 */
94360786Sps					if (regendp[no] == NULL)
94460786Sps						regendp[no] = save;
94560786Sps					return(1);
94660786Sps				} else
94760786Sps					return(0);
94860786Sps			}
94960786Sps			/* NOTREACHED */
95060786Sps			break;
95160786Sps		case BRANCH: {
95260786Sps				register char *save;
95360786Sps
95460786Sps				if (OP(next) != BRANCH)		/* No choice. */
95560786Sps					next = OPERAND(scan);	/* Avoid recursion. */
95660786Sps				else {
95760786Sps					do {
95860786Sps						save = reginput;
95960786Sps						if (regmatch(OPERAND(scan)))
96060786Sps							return(1);
96160786Sps						reginput = save;
96260786Sps						scan = regnext(scan);
96360786Sps					} while (scan != NULL && OP(scan) == BRANCH);
96460786Sps					return(0);
96560786Sps					/* NOTREACHED */
96660786Sps				}
96760786Sps			}
96860786Sps			/* NOTREACHED */
96960786Sps			break;
97060786Sps		case STAR:
97160786Sps		case PLUS: {
97260786Sps				register char nextch;
97360786Sps				register int no;
97460786Sps				register char *save;
97560786Sps				register int min;
97660786Sps
97760786Sps				/*
97860786Sps				 * Lookahead to avoid useless match attempts
97960786Sps				 * when we know what character comes next.
98060786Sps				 */
98160786Sps				nextch = '\0';
98260786Sps				if (OP(next) == EXACTLY)
98360786Sps					nextch = *OPERAND(next);
98460786Sps				min = (OP(scan) == STAR) ? 0 : 1;
98560786Sps				save = reginput;
98660786Sps				no = regrepeat(OPERAND(scan));
98760786Sps				while (no >= min) {
98860786Sps					/* If it could work, try it. */
98960786Sps					if (nextch == '\0' || *reginput == nextch)
99060786Sps						if (regmatch(next))
99160786Sps							return(1);
99260786Sps					/* Couldn't or didn't -- back up. */
99360786Sps					no--;
99460786Sps					reginput = save + no;
99560786Sps				}
99660786Sps				return(0);
99760786Sps			}
99860786Sps			/* NOTREACHED */
99960786Sps			break;
100060786Sps		case END:
100160786Sps			return(1);	/* Success! */
100260786Sps			/* NOTREACHED */
100360786Sps			break;
100460786Sps		default:
100560786Sps			regerror("memory corruption");
100660786Sps			return(0);
100760786Sps			/* NOTREACHED */
100860786Sps			break;
100960786Sps		}
101060786Sps
101160786Sps		scan = next;
101260786Sps	}
101360786Sps
101460786Sps	/*
101560786Sps	 * We get here only if there's trouble -- normally "case END" is
101660786Sps	 * the terminating point.
101760786Sps	 */
101860786Sps	regerror("corrupted pointers");
101960786Sps	return(0);
102060786Sps}
102160786Sps
102260786Sps/*
102360786Sps - regrepeat - repeatedly match something simple, report how many
102460786Sps */
102560786Spsstatic int
102660786Spsregrepeat(p)
102760786Spschar *p;
102860786Sps{
102960786Sps	register int count = 0;
103060786Sps	register char *scan;
103160786Sps	register char *opnd;
103260786Sps
103360786Sps	scan = reginput;
103460786Sps	opnd = OPERAND(p);
103560786Sps	switch (OP(p)) {
103660786Sps	case ANY:
103760786Sps		count = strlen(scan);
103860786Sps		scan += count;
103960786Sps		break;
104060786Sps	case EXACTLY:
104160786Sps		while (*opnd == *scan) {
104260786Sps			count++;
104360786Sps			scan++;
104460786Sps		}
104560786Sps		break;
104660786Sps	case ANYOF:
104760786Sps		while (*scan != '\0' && strchr(opnd, *scan) != NULL) {
104860786Sps			count++;
104960786Sps			scan++;
105060786Sps		}
105160786Sps		break;
105260786Sps	case ANYBUT:
105360786Sps		while (*scan != '\0' && strchr(opnd, *scan) == NULL) {
105460786Sps			count++;
105560786Sps			scan++;
105660786Sps		}
105760786Sps		break;
105860786Sps	default:		/* Oh dear.  Called inappropriately. */
105960786Sps		regerror("internal foulup");
106060786Sps		count = 0;	/* Best compromise. */
106160786Sps		break;
106260786Sps	}
106360786Sps	reginput = scan;
106460786Sps
106560786Sps	return(count);
106660786Sps}
106760786Sps
106860786Sps/*
106960786Sps - regnext - dig the "next" pointer out of a node
107060786Sps */
107160786Spsstatic char *
107260786Spsregnext(p)
107360786Spsregister char *p;
107460786Sps{
107560786Sps	register int offset;
107660786Sps
107760786Sps	if (p == &regdummy)
107860786Sps		return(NULL);
107960786Sps
108060786Sps	offset = NEXT(p);
108160786Sps	if (offset == 0)
108260786Sps		return(NULL);
108360786Sps
108460786Sps	if (OP(p) == BACK)
108560786Sps		return(p-offset);
108660786Sps	else
108760786Sps		return(p+offset);
108860786Sps}
108960786Sps
109060786Sps#ifdef DEBUG
109160786Sps
109260786SpsSTATIC char *regprop();
109360786Sps
109460786Sps/*
109560786Sps - regdump - dump a regexp onto stdout in vaguely comprehensible form
109660786Sps */
109760786Spsvoid
109860786Spsregdump(r)
109960786Spsregexp *r;
110060786Sps{
110160786Sps	register char *s;
110260786Sps	register char op = EXACTLY;	/* Arbitrary non-END op. */
110360786Sps	register char *next;
110460786Sps
110560786Sps
110660786Sps	s = r->program + 1;
110760786Sps	while (op != END) {	/* While that wasn't END last time... */
110860786Sps		op = OP(s);
110960786Sps		printf("%2d%s", s-r->program, regprop(s));	/* Where, what. */
111060786Sps		next = regnext(s);
111160786Sps		if (next == NULL)		/* Next ptr. */
111260786Sps			printf("(0)");
111360786Sps		else
111460786Sps			printf("(%d)", (s-r->program)+(next-s));
111560786Sps		s += 3;
111660786Sps		if (op == ANYOF || op == ANYBUT || op == EXACTLY) {
111760786Sps			/* Literal string, where present. */
111860786Sps			while (*s != '\0') {
111960786Sps				putchar(*s);
112060786Sps				s++;
112160786Sps			}
112260786Sps			s++;
112360786Sps		}
112460786Sps		putchar('\n');
112560786Sps	}
112660786Sps
112760786Sps	/* Header fields of interest. */
112860786Sps	if (r->regstart != '\0')
112960786Sps		printf("start `%c' ", r->regstart);
113060786Sps	if (r->reganch)
113160786Sps		printf("anchored ");
113260786Sps	if (r->regmust != NULL)
113360786Sps		printf("must have \"%s\"", r->regmust);
113460786Sps	printf("\n");
113560786Sps}
113660786Sps
113760786Sps/*
113860786Sps - regprop - printable representation of opcode
113960786Sps */
114060786Spsstatic char *
114160786Spsregprop(op)
114260786Spschar *op;
114360786Sps{
114460786Sps	register char *p;
114560786Sps	static char buf[50];
114660786Sps
114760786Sps	(void) strcpy(buf, ":");
114860786Sps
114960786Sps	switch (OP(op)) {
115060786Sps	case BOL:
115160786Sps		p = "BOL";
115260786Sps		break;
115360786Sps	case EOL:
115460786Sps		p = "EOL";
115560786Sps		break;
115660786Sps	case ANY:
115760786Sps		p = "ANY";
115860786Sps		break;
115960786Sps	case ANYOF:
116060786Sps		p = "ANYOF";
116160786Sps		break;
116260786Sps	case ANYBUT:
116360786Sps		p = "ANYBUT";
116460786Sps		break;
116560786Sps	case BRANCH:
116660786Sps		p = "BRANCH";
116760786Sps		break;
116860786Sps	case EXACTLY:
116960786Sps		p = "EXACTLY";
117060786Sps		break;
117160786Sps	case NOTHING:
117260786Sps		p = "NOTHING";
117360786Sps		break;
117460786Sps	case BACK:
117560786Sps		p = "BACK";
117660786Sps		break;
117760786Sps	case END:
117860786Sps		p = "END";
117960786Sps		break;
118060786Sps	case OPEN+1:
118160786Sps	case OPEN+2:
118260786Sps	case OPEN+3:
118360786Sps	case OPEN+4:
118460786Sps	case OPEN+5:
118560786Sps	case OPEN+6:
118660786Sps	case OPEN+7:
118760786Sps	case OPEN+8:
118860786Sps	case OPEN+9:
118960786Sps		sprintf(buf+strlen(buf), "OPEN%d", OP(op)-OPEN);
119060786Sps		p = NULL;
119160786Sps		break;
119260786Sps	case CLOSE+1:
119360786Sps	case CLOSE+2:
119460786Sps	case CLOSE+3:
119560786Sps	case CLOSE+4:
119660786Sps	case CLOSE+5:
119760786Sps	case CLOSE+6:
119860786Sps	case CLOSE+7:
119960786Sps	case CLOSE+8:
120060786Sps	case CLOSE+9:
120160786Sps		sprintf(buf+strlen(buf), "CLOSE%d", OP(op)-CLOSE);
120260786Sps		p = NULL;
120360786Sps		break;
120460786Sps	case STAR:
120560786Sps		p = "STAR";
120660786Sps		break;
120760786Sps	case PLUS:
120860786Sps		p = "PLUS";
120960786Sps		break;
121060786Sps	default:
121160786Sps		regerror("corrupted opcode");
121260786Sps		break;
121360786Sps	}
121460786Sps	if (p != NULL)
121560786Sps		(void) strcat(buf, p);
121660786Sps	return(buf);
121760786Sps}
121860786Sps#endif
121960786Sps
122060786Sps/*
122160786Sps * The following is provided for those people who do not have strcspn() in
122260786Sps * their C libraries.  They should get off their butts and do something
122360786Sps * about it; at least one public-domain implementation of those (highly
122460786Sps * useful) string routines has been published on Usenet.
122560786Sps */
122660786Sps#ifdef STRCSPN
122760786Sps/*
122860786Sps * strcspn - find length of initial segment of s1 consisting entirely
122960786Sps * of characters not from s2
123060786Sps */
123160786Sps
123260786Spsstatic int
123360786Spsstrcspn(s1, s2)
123460786Spschar *s1;
123560786Spschar *s2;
123660786Sps{
123760786Sps	register char *scan1;
123860786Sps	register char *scan2;
123960786Sps	register int count;
124060786Sps
124160786Sps	count = 0;
124260786Sps	for (scan1 = s1; *scan1 != '\0'; scan1++) {
124360786Sps		for (scan2 = s2; *scan2 != '\0';)	/* ++ moved down. */
124460786Sps			if (*scan1 == *scan2++)
124560786Sps				return(count);
124660786Sps		count++;
124760786Sps	}
124860786Sps	return(count);
124960786Sps}
125060786Sps#endif
1251