#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 10 (of 13)."
# Contents:  stevie/search.c
# Wrapped by thor@surt on Fri Oct 16 09:43:47 1992
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'stevie/search.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'stevie/search.c'\"
else
echo shar: Extracting \"'stevie/search.c'\" \(18329 characters\)
sed "s/^X//" >'stevie/search.c' <<'END_OF_FILE'
X/* $Header: /nw/tony/src/stevie/src/RCS/search.c,v 1.16 89/08/06 09:50:51 tony Exp $
X *
X * This file contains various searching-related routines. These fall into
X * three groups: string searches (for /, ?, n, and N), character searches
X * within a single line (for f, F, t, T, etc), and "other" kinds of searches
X * like the '%' command, and 'word' searches.
X */
X
X#include "stevie.h"
X#include "regexp.h"	/* Henry Spencer's (modified) reg. exp. routines */
X
X/*
X * String searches
X *
X * The actual searches are done using Henry Spencer's regular expression
X * library.
X */
X
X#define	BEGWORD	"([^a-zA-Z0-9_]|^)"	/* replaces "\<" in search strings */
X#define	ENDWORD	"([^a-zA-Z0-9_]|$)"	/* likewise replaces "\>" */
X
X#define	BEGCHAR(c)	(islower(c) || isupper(c) || isdigit(c) || ((c) == '_'))
X
Xbool_t	begword;	/* does the search include a 'begin word' match */
X
X/*
X * mapstring(s) - map special backslash sequences
X */
Xstatic char *
Xmapstring(s)
Xregister char	*s;
X{
X	static	char	ns[80];
X	register char	*p;
X
X	begword = FALSE;
X
X	for (p = ns; *s ;s++) {
X		if (*s != '\\') {	/* not an escape */
X			*p++ = *s;
X			continue;
X		}
X		switch (*++s) {
X		case '/':
X			*p++ = '/';
X			break;
X
X		case '<':
X			strcpy(p, BEGWORD);
X			p += strlen(BEGWORD);
X			begword = TRUE;
X			break;
X
X		case '>':
X			strcpy(p, ENDWORD);
X			p += strlen(ENDWORD);
X			break;
X
X		default:
X			*p++ = '\\';
X			*p++ = *s;
X			break;
X		}
X	}
X	*p++ = NUL;
X
X	return ns;
X}
X
Xstatic char *laststr = NULL;
Xstatic int lastsdir;
X
Xstatic LPTR *
Xssearch(dir,str)
Xint	dir;	/* FORWARD or BACKWARD */
Xchar	*str;
X{
X	LPTR	*bcksearch(), *fwdsearch();
X	LPTR	*pos;
X	char	*old_ls = laststr;
X
X	reg_ic = P(P_IC);	/* tell the regexp routines how to search */
X
X	laststr = strsave(str);
X	lastsdir = dir;
X
X	if (old_ls != NULL)
X		free(old_ls);
X
X	if (dir == BACKWARD) {
X		smsg("?%s", laststr);
X		pos = bcksearch(mapstring(laststr));
X	} else {
X		smsg("/%s", laststr);
X		pos = fwdsearch(mapstring(laststr));
X	}
X
X	/*
X	 * This is kind of a kludge, but its needed to make
X	 * 'beginning of word' searches land on the right place.
X	 */
X	if (pos != NULL && begword) {
X		if (pos->index != 0 || !BEGCHAR(pos->linep->s[0]))
X			pos->index += 1;
X	}
X	return pos;
X}
X
Xbool_t
Xdosearch(dir,str)
Xint	dir;
Xchar	*str;
X{
X	LPTR	*p;
X
X	if (str == NULL)
X		str = laststr;
X
X	got_int = FALSE;
X
X	if ((p = ssearch(dir,str)) == NULL) {
X		if (got_int)
X			msg("Interrupt");
X		else
X			msg("Pattern not found");
X
X		got_int = FALSE;
X		return FALSE;
X	} else {
X		LPTR savep;
X
X		cursupdate();
X		/*
X		 * if we're backing up, we make sure the line we're on
X		 * is on the screen.
X		 */
X		setpcmark();
X		*Curschar = savep = *p;
X		set_want_col = TRUE;
X		cursupdate();
X
X		return TRUE;
X	}
X}
X
X#define	OTHERDIR(x)	(((x) == FORWARD) ? BACKWARD : FORWARD)
X
Xbool_t
Xrepsearch(flag)
Xint	flag;
X{
X	int	dir = lastsdir;
X	bool_t	found;
X
X	if ( laststr == NULL ) {
X		beep();
X		return FALSE;
X	}
X
X	found = dosearch(flag ? OTHERDIR(lastsdir) : lastsdir, laststr);
X
X	/*
X	 * We have to save and restore 'lastsdir' because it gets munged
X	 * by ssearch() and winds up saving the wrong direction from here
X	 * if 'flag' is true.
X	 */
X	lastsdir = dir;
X
X	return found;
X}
X
X/*
X * regerror - called by regexp routines when errors are detected.
X */
Xvoid
Xregerror(s)
Xchar	*s;
X{
X	emsg(s);
X}
X
Xstatic LPTR *
Xfwdsearch(str)
Xregister char	*str;
X{
X	static LPTR	infile;
X	register LPTR	*p;
X	regexp	*prog;
X
X	register char	*s;
X	register int	i;
X
X	if ((prog = regcomp(str)) == NULL) {
X		emsg("Invalid search string");
X		return NULL;
X	}
X
X	p = Curschar;
X	i = Curschar->index + 1;
X	do {
X		s = p->linep->s + i;
X
X		if (regexec(prog, s, i == 0)) {		/* got a match */
X			infile.linep = p->linep;
X			infile.index = (int) (prog->startp[0] - p->linep->s);
X			free((char *)prog);
X			return (&infile);
X		}
X		i = 0;
X
X		if (got_int)
X			goto fwdfail;
X
X	} while ((p = nextline(p)) != NULL);
X
X	/*
X	 * If wrapscan isn't set, then don't scan from the beginning
X	 * of the file. Just return failure here.
X	 */
X	if (!P(P_WS))
X		goto fwdfail;
X
X	/* search from the beginning of the file to Curschar */
X	for (p = Filemem; p != NULL ;p = nextline(p)) {
X		s = p->linep->s;
X
X		if (regexec(prog, s, TRUE)) {		/* got a match */
X			infile.linep = p->linep;
X			infile.index = (int) (prog->startp[0] - s);
X			free((char *)prog);
X			return (&infile);
X		}
X
X		if (p->linep == Curschar->linep)
X			break;
X
X		if (got_int)
X			goto fwdfail;
X	}
X
Xfwdfail:
X	free((char *)prog);
X	return NULL;
X}
X
Xstatic LPTR *
Xbcksearch(str)
Xchar	*str;
X{
X	static LPTR	infile;
X	register LPTR	*p = &infile;
X	register char	*s;
X	register int	i;
X	register char	*match;
X	regexp	*prog;
X
X	/* make sure str isn't empty */
X	if (str == NULL || *str == NUL)
X		return NULL;
X
X	if ((prog = regcomp(str)) == NULL) {
X		emsg("Invalid search string");
X		return NULL;
X	}
X
X	*p = *Curschar;
X	if (dec(p) == -1) {	/* already at start of file? */
X		*p = *Fileend;
X		p->index = strlen(p->linep->s) - 1;
X	}
X
X	if (begword)		/* so we don't get stuck on one match */
X		dec(p);
X
X	i = p->index;
X
X	do {
X		s = p->linep->s;
X
X		if (regexec(prog, s, TRUE)) {	/* match somewhere on line */
X
X			/*
X			 * Now, if there are multiple matches on this line,
X			 * we have to get the last one. Or the last one
X			 * before the cursor, if we're on that line.
X			 */
X			match = prog->startp[0];
X
X			while (regexec(prog, prog->endp[0], FALSE)) {
X				if ((i >= 0) && ((prog->startp[0] - s) > i))
X					break;
X				match = prog->startp[0];
X			}
X
X			if ((i >= 0) && ((match - s) > i)) {
X				i = -1;
X				continue;
X			}
X
X			infile.linep = p->linep;
X			infile.index = (int) (match - s);
X			free((char *)prog);
X			return (&infile);
X		}
X		i = -1;
X
X		if (got_int)
X			goto bckfail;
X
X	} while ((p = prevline(p)) != NULL);
X
X	/*
X	 * If wrapscan isn't set, bag the search now
X	 */
X	if (!P(P_WS))
X		goto bckfail;
X
X	/* search backward from the end of the file */
X	p = prevline(Fileend);
X	do {
X		s = p->linep->s;
X
X		if (regexec(prog, s, TRUE)) {	/* match somewhere on line */
X
X			/*
X			 * Now, if there are multiple matches on this line,
X			 * we have to get the last one.
X			 */
X			match = prog->startp[0];
X
X			while (regexec(prog, prog->endp[0], FALSE))
X				match = prog->startp[0];
X
X			infile.linep = p->linep;
X			infile.index = (int) (match - s);
X			free((char *)prog);
X			return (&infile);
X		}
X
X		if (p->linep == Curschar->linep)
X			break;
X
X		if (got_int)
X			goto bckfail;
X
X	} while ((p = prevline(p)) != NULL);
X
Xbckfail:
X	free((char *)prog);
X	return NULL;
X}
X
X/*
X * dosub(lp, up, cmd)
X *
X * Perform a substitution from line 'lp' to line 'up' using the
X * command pointed to by 'cmd' which should be of the form:
X *
X * /pattern/substitution/g
X *
X * The trailing 'g' is optional and, if present, indicates that multiple
X * substitutions should be performed on each line, if applicable.
X * The usual escapes are supported as described in the regexp docs.
X */
Xvoid
Xdosub(lp, up, cmd)
XLPTR	*lp, *up;
Xchar	*cmd;
X{
X	LINE	*cp;
X	char	*pat, *sub;
X	regexp	*prog;
X	int	nsubs;
X	bool_t	do_all;		/* do multiple substitutions per line */
X
X	/*
X	 * If no range was given, do the current line. If only one line
X	 * was given, just do that one.
X	 */
X	if (lp->linep == NULL)
X		*up = *lp = *Curschar;
X	else {
X		if (up->linep == NULL)
X			*up = *lp;
X	}
X
X	pat = ++cmd;		/* skip the initial '/' */
X
X	while (*cmd) {
X		if (*cmd == '\\')	/* next char is quoted */
X			cmd += 2;
X		else if (*cmd == '/') {	/* delimiter */
X			*cmd++ = NUL;
X			break;
X		} else
X			cmd++;		/* regular character */
X	}
X
X	if (*pat == NUL) {
X		emsg("NULL pattern specified");
X		return;
X	}
X
X	sub = cmd;
X
X	do_all = FALSE;
X
X	while (*cmd) {
X		if (*cmd == '\\')	/* next char is quoted */
X			cmd += 2;
X		else if (*cmd == '/') {	/* delimiter */
X			do_all = (cmd[1] == 'g');
X			*cmd++ = NUL;
X			break;
X		} else
X			cmd++;		/* regular character */
X	}
X
X	reg_ic = P(P_IC);	/* set "ignore case" flag appropriately */
X
X	if ((prog = regcomp(pat)) == NULL) {
X		emsg("Invalid search string");
X		return;
X	}
X
X	nsubs = 0;
X
X	for (cp = lp->linep; cp != NULL ;cp = cp->next) {
X		if (regexec(prog, cp->s, TRUE)) { /* a match on this line */
X			char	*ns, *sns, *p;
X
X			/*
X			 * Get some space for a temporary buffer
X			 * to do the substitution into.
X			 */
X			sns = ns = alloc(2048);
X			if (!sns)  return;
X			*sns = NUL;
X
X			p = cp->s;
X
X			do {
X				for (ns = sns; *ns ;ns++)
X					;
X				/*
X				 * copy up to the part that matched
X				 */
X				while (p < prog->startp[0])
X					*ns++ = *p++;
X
X				regsub(prog, sub, ns);
X
X				/*
X				 * continue searching after the match
X				 */
X				p = prog->endp[0];
X
X			} while (regexec(prog, p, FALSE) && do_all);
X
X			for (ns = sns; *ns ;ns++)
X				;
X
X			/*
X			 * copy the rest of the line, that didn't match
X			 */
X			while (*p)
X				*ns++ = *p++;
X
X			*ns = NUL;
X
X			free(cp->s);		/* free the original line */
X			cp->s = strsave(sns);	/* and save the modified str */
X			cp->size = strlen(cp->s) + 1;
X			free(sns);		/* free the temp buffer */
X			nsubs++;
X			CHANGED;
X		}
X		if (cp == up->linep)
X			break;
X	}
X
X	if (nsubs) {
X		updatescreen();
X		if (nsubs >= P(P_RP))
X			smsg("%d substitution%c", nsubs, (nsubs>1) ? 's' : ' ');
X	} else
X		msg("No match");
X
X	free((char *)prog);
X}
X
X/*
X * doglob(cmd)
X *
X * Execute a global command of the form:
X *
X * g/pattern/X
X *
X * where 'x' is a command character, currently one of the following:
X *
X * d	Delete all matching lines
X * p	Print all matching lines
X *
X * The command character (as well as the trailing slash) is optional, and
X * is assumed to be 'p' if missing.
X */
Xvoid
Xdoglob(lp, up, cmd)
XLPTR	*lp, *up;
Xchar	*cmd;
X{
X	LINE	*cp;
X	char	*pat;
X	regexp	*prog;
X	int	ndone;
X	char	cmdchar = NUL;	/* what to do with matching lines */
X
X	/*
X	 * If no range was given, do every line. If only one line
X	 * was given, just do that one.
X	 */
X	if (lp->linep == NULL) {
X		*lp = *Filemem;
X		*up = *Fileend;
X	} else {
X		if (up->linep == NULL)
X			*up = *lp;
X	}
X
X	pat = ++cmd;		/* skip the initial '/' */
X
X	while (*cmd) {
X		if (*cmd == '\\')	/* next char is quoted */
X			cmd += 2;
X		else if (*cmd == '/') {	/* delimiter */
X			cmdchar = cmd[1];
X			*cmd++ = NUL;
X			break;
X		} else
X			cmd++;		/* regular character */
X	}
X	if (cmdchar == NUL)
X		cmdchar = 'p';
X
X	reg_ic = P(P_IC);	/* set "ignore case" flag appropriately */
X
X	if (cmdchar != 'd' && cmdchar != 'p') {
X		emsg("Invalid command character");
X		return;
X	}
X
X	if ((prog = regcomp(pat)) == NULL) {
X		emsg("Invalid search string");
X		return;
X	}
X
X	msg("");
X	ndone = 0;
X	got_int = FALSE;
X
X	for (cp = lp->linep; cp != NULL && !got_int ;cp = cp->next) {
X		if (regexec(prog, cp->s, TRUE)) { /* a match on this line */
X			switch (cmdchar) {
X
X			case 'd':		/* delete the line */
X				if (Curschar->linep != cp) {
X					LPTR	savep;
X
X					savep = *Curschar;
X					Curschar->linep = cp;
X					Curschar->index = 0;
X					delline(1, FALSE);
X					*Curschar = savep;
X				} else
X					delline(1, FALSE);
X				break;
X
X			case 'p':		/* print the line */
X				prt_line(cp->s);
X				outstr("\r\n");
X				break;
X			}
X			ndone++;
X		}
X		if (cp == up->linep)
X			break;
X	}
X
X	if (ndone) {
X		switch (cmdchar) {
X
X		case 'd':
X			updatescreen();
X			if (ndone >= P(P_RP) || got_int)
X				smsg("%s%d fewer line%c",
X					got_int ? "Interrupt: " : "",
X					ndone,
X					(ndone > 1) ? 's' : ' ');
X			break;
X
X		case 'p':
X			wait_return();
X			break;
X		}
X	} else {
X		if (got_int)
X			msg("Interrupt");
X		else
X			msg("No match");
X	}
X
X	got_int = FALSE;
X	free((char *)prog);
X}
X
X/*
X * Character Searches
X */
X
Xstatic char lastc = NUL;	/* last character searched for */
Xstatic int  lastcdir;		/* last direction of character search */
Xstatic int  lastctype;		/* last type of search ("find" or "to") */
X
X/*
X * searchc(c, dir, type)
X *
X * Search for character 'c', in direction 'dir'. If type is 0, move to
X * the position of the character, otherwise move to just before the char.
X */
Xbool_t
Xsearchc(c, dir, type)
Xchar	c;
Xint	dir;
Xint	type;
X{
X	LPTR	save;
X
X	save = *Curschar;	/* save position in case we fail */
X	lastc = c;
X	lastcdir = dir;
X	lastctype = type;
X
X	/*
X	 * On 'to' searches, skip one to start with so we can repeat
X	 * searches in the same direction and have it work right.
X	 */
X	if (type)
X		(dir == FORWARD) ? oneright() : oneleft();
X
X	while ( (dir == FORWARD) ? oneright() : oneleft() ) {
X		if (gchar(Curschar) == c) {
X			if (type)
X				(dir == FORWARD) ? oneleft() : oneright();
X			return TRUE;
X		}
X	}
X	*Curschar = save;
X	return FALSE;
X}
X
Xbool_t
Xcrepsearch(flag)
Xint	flag;
X{
X	int	dir = lastcdir;
X	int	rval;
X
X	if (lastc == NUL)
X		return FALSE;
X
X	rval = searchc(lastc, flag ? OTHERDIR(lastcdir) : lastcdir, lastctype);
X
X	lastcdir = dir;		/* restore dir., since it may have changed */
X
X	return rval;
X}
X
X/*
X * "Other" Searches
X */
X
X/*
X * showmatch - move the cursor to the matching paren or brace
X */
XLPTR *
Xshowmatch()
X{
X	static	LPTR	pos;
X	int	(*move)(), inc(), dec();
X	char	initc = gchar(Curschar);	/* initial char */
X	char	findc;				/* terminating char */
X	char	c;
X	int	count = 0;
X
X	pos = *Curschar;		/* set starting point */
X
X	switch (initc) {
X
X	case '(':
X		findc = ')';
X		move = inc;
X		break;
X	case ')':
X		findc = '(';
X		move = dec;
X		break;
X	case '{':
X		findc = '}';
X		move = inc;
X		break;
X	case '}':
X		findc = '{';
X		move = dec;
X		break;
X	case '[':
X		findc = ']';
X		move = inc;
X		break;
X	case ']':
X		findc = '[';
X		move = dec;
X		break;
X	default:
X		return (LPTR *) NULL;
X	}
X
X	while ((*move)(&pos) != -1) {		/* until end of file */
X		c = gchar(&pos);
X		if (c == initc)
X			count++;
X		else if (c == findc) {
X			if (count == 0)
X				return &pos;
X			count--;
X		}
X	}
X	return (LPTR *) NULL;			/* never found it */
X}
X
X
X/*
X * The following routines do the word searches performed by the
X * 'w', 'W', 'b', 'B', 'e', and 'E' commands.
X */
X
X/*
X * To perform these searches, characters are placed into one of three
X * classes, and transitions between classes determine word boundaries.
X *
X * The classes are:
X *
X * 0 - white space
X * 1 - letters, digits, and underscore
X * 2 - everything else
X */
X
Xstatic	int	stype;		/* type of the word motion being performed */
X
X#define	C0(c)	(((c) == ' ') || ((c) == '\t') || ((c) == NUL))
X#define	C1(c)	(isalpha(c) || isdigit(c) || ((c) == '_'))
X
X/*
X * cls(c) - returns the class of character 'c'
X *
X * The 'type' of the current search modifies the classes of characters
X * if a 'W', 'B', or 'E' motion is being done. In this case, chars. from
X * class 2 are reported as class 1 since only white space boundaries are
X * of interest.
X */
Xstatic	int
Xcls(c)
Xchar	c;
X{
X	if (C0(c))
X		return 0;
X
X	if (C1(c))
X		return 1;
X
X	/*
X	 * If stype is non-zero, report these as class 1.
X	 */
X	return (stype == 0) ? 2 : 1;
X}
X
X
X/*
X * fwd_word(pos, type) - move forward one word
X *
X * Returns the resulting position, or NULL if EOF was reached.
X */
XLPTR *
Xfwd_word(p, type)
XLPTR	*p;
Xint	type;
X{
X	static	LPTR	pos;
X	int	sclass = cls(gchar(p));		/* starting class */
X
X	pos = *p;
X
X	stype = type;
X
X	/*
X	 * We always move at least one character.
X	 */
X	if (inc(&pos) == -1)
X		return NULL;
X
X	if (sclass != 0) {
X		while (cls(gchar(&pos)) == sclass) {
X			if (inc(&pos) == -1)
X				return NULL;
X		}
X		/*
X		 * If we went from 1 -> 2 or 2 -> 1, return here.
X		 */
X		if (cls(gchar(&pos)) != 0)
X			return &pos;
X	}
X
X	/* We're in white space; go to next non-white */
X
X	while (cls(gchar(&pos)) == 0) {
X		/*
X		 * We'll stop if we land on a blank line
X		 */
X		if (pos.index == 0 && pos.linep->s[0] == NUL)
X			break;
X
X		if (inc(&pos) == -1)
X			return NULL;
X	}
X
X	return &pos;
X}
X
X/*
X * bck_word(pos, type) - move backward one word
X *
X * Returns the resulting position, or NULL if EOF was reached.
X */
XLPTR *
Xbck_word(p, type)
XLPTR	*p;
Xint	type;
X{
X	static	LPTR	pos;
X	int	sclass = cls(gchar(p));		/* starting class */
X
X	pos = *p;
X
X	stype = type;
X
X	if (dec(&pos) == -1)
X		return NULL;
X
X	/*
X	 * If we're in the middle of a word, we just have to
X	 * back up to the start of it.
X	 */
X	if (cls(gchar(&pos)) == sclass && sclass != 0) {
X		/*
X		 * Move backward to start of the current word
X		 */
X		while (cls(gchar(&pos)) == sclass) {
X			if (dec(&pos) == -1)
X				return NULL;
X		}
X		inc(&pos);			/* overshot - forward one */
X		return &pos;
X	}
X
X	/*
X	 * We were at the start of a word. Go back to the start
X	 * of the prior word.
X	 */
X
X	while (cls(gchar(&pos)) == 0) {		/* skip any white space */
X		/*
X		 * We'll stop if we land on a blank line
X		 */
X		if (pos.index == 0 && pos.linep->s[0] == NUL)
X			return &pos;
X
X		if (dec(&pos) == -1)
X			return NULL;
X	}
X
X	sclass = cls(gchar(&pos));
X
X	/*
X	 * Move backward to start of this word.
X	 */
X	while (cls(gchar(&pos)) == sclass) {
X		if (dec(&pos) == -1)
X			return NULL;
X	}
X	inc(&pos);			/* overshot - forward one */
X
X	return &pos;
X}
X
X/*
X * end_word(pos, type, in_change) - move to the end of the word
X *
X * There is an apparent bug in the 'e' motion of the real vi. At least
X * on the System V Release 3 version for the 80386. Unlike 'b' and 'w',
X * the 'e' motion crosses blank lines. When the real vi crosses a blank
X * line in an 'e' motion, the cursor is placed on the FIRST character
X * of the next non-blank line. The 'E' command, however, works correctly.
X * Since this appears to be a bug, I have not duplicated it here.
X *
X * There's a strange special case here that the 'in_change' parameter
X * helps us deal with. Vi effectively turns 'cw' into 'ce'. If we're on
X * a word with only one character, we need to stick at the current
X * position so we don't change two words.
X *
X * Returns the resulting position, or NULL if EOF was reached.
X */
XLPTR *
Xend_word(p, type, in_change)
XLPTR	*p;
Xint	type;
Xbool_t	in_change;
X{
X	static	LPTR	pos;
X	int	sclass = cls(gchar(p));		/* starting class */
X
X	pos = *p;
X
X	stype = type;
X
X	if (inc(&pos) == -1)
X		return NULL;
X
X	/*
X	 * If we're in the middle of a word, we just have to
X	 * move to the end of it.
X	 */
X	if (cls(gchar(&pos)) == sclass && sclass != 0) {
X		/*
X		 * Move forward to end of the current word
X		 */
X		while (cls(gchar(&pos)) == sclass) {
X			if (inc(&pos) == -1)
X				return NULL;
X		}
X		dec(&pos);			/* overshot - forward one */
X		return &pos;
X	}
X
X	/*
X	 * We were at the end of a word. Go to the end of the next
X	 * word, unless we're doing a change. In that case we stick
X	 * at the end of the current word.
X	 */
X	if (in_change)
X		return p;
X
X	while (cls(gchar(&pos)) == 0) {		/* skip any white space */
X		if (inc(&pos) == -1)
X			return NULL;
X	}
X
X	sclass = cls(gchar(&pos));
X
X	/*
X	 * Move forward to end of this word.
X	 */
X	while (cls(gchar(&pos)) == sclass) {
X		if (inc(&pos) == -1)
X			return NULL;
X	}
X	dec(&pos);			/* overshot - forward one */
X
X	return &pos;
X}
END_OF_FILE
if test 18329 -ne `wc -c <'stevie/search.c'`; then
    echo shar: \"'stevie/search.c'\" unpacked with wrong size!
fi
# end of 'stevie/search.c'
fi
echo shar: End of archive 10 \(of 13\).
cp /dev/null ark10isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 13 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
