172339Sabial#define Extern extern
272339Sabial#include <sys/types.h>
372339Sabial#include <sys/stat.h>
472339Sabial#include <dirent.h>
572339Sabial#include <limits.h>
672339Sabial#include <signal.h>
772339Sabial#define _NSIG NSIG
872339Sabial#include <errno.h>
972339Sabial#include <setjmp.h>
1072339Sabial#include "sh.h"
1172339Sabial
1272339Sabial/* -------- eval.c -------- */
1372339Sabial/* #include "sh.h" */
1472339Sabial/* #include "word.h" */
1572339Sabial
1672339Sabial/*
1772339Sabial * ${}
1872339Sabial * `command`
1972339Sabial * blank interpretation
2072339Sabial * quoting
2172339Sabial * glob
2272339Sabial */
2372339Sabial
2472339Sabial_PROTOTYPE(static int expand, (char *cp, struct wdblock **wbp, int f ));
2572339Sabial_PROTOTYPE(static char *blank, (int f ));
2672339Sabial_PROTOTYPE(static int dollar, (int quoted ));
2772339Sabial_PROTOTYPE(static int grave, (int quoted ));
2872339Sabial_PROTOTYPE(void globname, (char *we, char *pp ));
2972339Sabial_PROTOTYPE(static char *generate, (char *start1, char *end1, char *middle, char *end ));
3072339Sabial_PROTOTYPE(static int anyspcl, (struct wdblock *wb ));
3172339Sabial_PROTOTYPE(static int xstrcmp, (char *p1, char *p2 ));
3272339Sabial_PROTOTYPE(void glob0, (char *a0, unsigned int a1, int a2, int (*a3)(char *, char *)));
3372339Sabial_PROTOTYPE(void glob1, (char *base, char *lim ));
3472339Sabial_PROTOTYPE(void glob2, (char *i, char *j ));
3572339Sabial_PROTOTYPE(void glob3, (char *i, char *j, char *k ));
3672339Sabial_PROTOTYPE(char *memcopy, (char *ato, char *from, int nb ));
3772339Sabial
3872339Sabialchar **
3972339Sabialeval(ap, f)
4072339Sabialregister char **ap;
4172339Sabialint f;
4272339Sabial{
4372339Sabial	struct wdblock *wb;
4472339Sabial	char **wp;
4572339Sabial	char **wf;
4672339Sabial	jmp_buf ev;
4772339Sabial
4872339Sabial	wp = NULL;
4972339Sabial	wb = NULL;
5072339Sabial	wf = NULL;
5172339Sabial	if (newenv(setjmp(errpt = ev)) == 0) {
5272339Sabial		while (*ap && isassign(*ap))
5372339Sabial			expand(*ap++, &wb, f & ~DOGLOB);
5472339Sabial		if (flag['k']) {
5572339Sabial			for (wf = ap; *wf; wf++) {
5672339Sabial				if (isassign(*wf))
5772339Sabial					expand(*wf, &wb, f & ~DOGLOB);
5872339Sabial			}
5972339Sabial		}
6072339Sabial		for (wb = addword((char *)0, wb); *ap; ap++) {
6172339Sabial			if (!flag['k'] || !isassign(*ap))
6272339Sabial				expand(*ap, &wb, f & ~DOKEY);
6372339Sabial		}
6472339Sabial		wb = addword((char *)0, wb);
6572339Sabial		wp = getwords(wb);
6672339Sabial		quitenv();
6772339Sabial	} else
6872339Sabial		gflg = 1;
6972339Sabial	return(gflg? (char **)NULL: wp);
7072339Sabial}
7172339Sabial
7272339Sabial/*
7372339Sabial * Make the exported environment from the exported
7472339Sabial * names in the dictionary. Keyword assignments
7572339Sabial * will already have been done.
7672339Sabial */
7772339Sabialchar **
7872339Sabialmakenv()
7972339Sabial
8072339Sabial{
8172339Sabial	register struct wdblock *wb;
8272339Sabial	register struct var *vp;
8372339Sabial
8472339Sabial	wb = NULL;
8572339Sabial	for (vp = vlist; vp; vp = vp->next)
8672339Sabial		if (vp->status & EXPORT)
8772339Sabial			wb = addword(vp->name, wb);
8872339Sabial	wb = addword((char *)0, wb);
8972339Sabial	return(getwords(wb));
9072339Sabial}
9172339Sabial
9272339Sabialchar *
9372339Sabialevalstr(cp, f)
9472339Sabialregister char *cp;
9572339Sabialint f;
9672339Sabial{
9772339Sabial	struct wdblock *wb;
9872339Sabial
9972339Sabial	wb = NULL;
10072339Sabial	if (expand(cp, &wb, f)) {
10172339Sabial		if (wb == NULL || wb->w_nword == 0 || (cp = wb->w_words[0]) == NULL)
10272339Sabial			cp = "";
10372339Sabial		DELETE(wb);
10472339Sabial	} else
10572339Sabial		cp = NULL;
10672339Sabial	return(cp);
10772339Sabial}
10872339Sabial
10972339Sabialstatic int
11072339Sabialexpand(cp, wbp, f)
11172339Sabialregister char *cp;
11272339Sabialregister struct wdblock **wbp;
11372339Sabialint f;
11472339Sabial{
11572339Sabial	jmp_buf ev;
11672339Sabial
11772339Sabial	gflg = 0;
11872339Sabial	if (cp == NULL)
11972339Sabial		return(0);
12072339Sabial	if (!anys("$`'\"", cp) &&
12172339Sabial	    !anys(ifs->value, cp) &&
12272339Sabial	    ((f&DOGLOB)==0 || !anys("[*?", cp))) {
12372339Sabial		cp = strsave(cp, areanum);
12472339Sabial		if (f & DOTRIM)
12572339Sabial			unquote(cp);
12672339Sabial		*wbp = addword(cp, *wbp);
12772339Sabial		return(1);
12872339Sabial	}
12972339Sabial	if (newenv(setjmp(errpt = ev)) == 0) {
13072339Sabial		PUSHIO(aword, cp, strchar);
13172339Sabial		e.iobase = e.iop;
13272339Sabial		while ((cp = blank(f)) && gflg == 0) {
13372339Sabial			e.linep = cp;
13472339Sabial			cp = strsave(cp, areanum);
13572339Sabial			if ((f&DOGLOB) == 0) {
13672339Sabial				if (f & DOTRIM)
13772339Sabial					unquote(cp);
13872339Sabial				*wbp = addword(cp, *wbp);
13972339Sabial			} else
14072339Sabial				*wbp = glob(cp, *wbp);
14172339Sabial		}
14272339Sabial		quitenv();
14372339Sabial	} else
14472339Sabial		gflg = 1;
14572339Sabial	return(gflg == 0);
14672339Sabial}
14772339Sabial
14872339Sabial/*
14972339Sabial * Blank interpretation and quoting
15072339Sabial */
15172339Sabialstatic char *
15272339Sabialblank(f)
15372339Sabialint f;
15472339Sabial{
15572339Sabial	register c, c1;
15672339Sabial	register char *sp;
15772339Sabial	int scanequals, foundequals;
15872339Sabial
15972339Sabial	sp = e.linep;
16072339Sabial	scanequals = f & DOKEY;
16172339Sabial	foundequals = 0;
16272339Sabial
16372339Sabialloop:
16472339Sabial	switch (c = subgetc('"', foundequals)) {
16572339Sabial	case 0:
16672339Sabial		if (sp == e.linep)
16772339Sabial			return(0);
16872339Sabial		*e.linep++ = 0;
16972339Sabial		return(sp);
17072339Sabial
17172339Sabial	default:
17272339Sabial		if (f & DOBLANK && any(c, ifs->value))
17372339Sabial			goto loop;
17472339Sabial		break;
17572339Sabial
17672339Sabial	case '"':
17772339Sabial	case '\'':
17872339Sabial		scanequals = 0;
17972339Sabial		if (INSUB())
18072339Sabial			break;
18172339Sabial		for (c1 = c; (c = subgetc(c1, 1)) != c1;) {
18272339Sabial			if (c == 0)
18372339Sabial				break;
18472339Sabial			if (c == '\'' || !any(c, "$`\""))
18572339Sabial				c |= QUOTE;
18672339Sabial			*e.linep++ = c;
18772339Sabial		}
18872339Sabial		c = 0;
18972339Sabial	}
19072339Sabial	unget(c);
19172339Sabial	if (!letter(c))
19272339Sabial		scanequals = 0;
19372339Sabial	for (;;) {
19472339Sabial		c = subgetc('"', foundequals);
19572339Sabial		if (c == 0 ||
19672339Sabial		    f & (DOBLANK && any(c, ifs->value)) ||
19772339Sabial		    (!INSUB() && any(c, "\"'"))) {
19872339Sabial		        scanequals = 0;
19972339Sabial			unget(c);
20072339Sabial			if (any(c, "\"'"))
20172339Sabial				goto loop;
20272339Sabial			break;
20372339Sabial		}
20472339Sabial		if (scanequals)
20572339Sabial			if (c == '=') {
20672339Sabial				foundequals = 1;
20772339Sabial				scanequals  = 0;
20872339Sabial			}
20972339Sabial			else if (!letnum(c))
21072339Sabial				scanequals = 0;
21172339Sabial		*e.linep++ = c;
21272339Sabial	}
21372339Sabial	*e.linep++ = 0;
21472339Sabial	return(sp);
21572339Sabial}
21672339Sabial
21772339Sabial/*
21872339Sabial * Get characters, substituting for ` and $
21972339Sabial */
22072339Sabialint
22172339Sabialsubgetc(ec, quoted)
22272339Sabialregister char ec;
22372339Sabialint quoted;
22472339Sabial{
22572339Sabial	register char c;
22672339Sabial
22772339Sabialagain:
22872339Sabial	c = getc(ec);
22972339Sabial	if (!INSUB() && ec != '\'') {
23072339Sabial		if (c == '`') {
23172339Sabial			if (grave(quoted) == 0)
23272339Sabial				return(0);
23372339Sabial			e.iop->task = XGRAVE;
23472339Sabial			goto again;
23572339Sabial		}
23672339Sabial		if (c == '$' && (c = dollar(quoted)) == 0) {
23772339Sabial			e.iop->task = XDOLL;
23872339Sabial			goto again;
23972339Sabial		}
24072339Sabial	}
24172339Sabial	return(c);
24272339Sabial}
24372339Sabial
24472339Sabial/*
24572339Sabial * Prepare to generate the string returned by ${} substitution.
24672339Sabial */
24772339Sabialstatic int
24872339Sabialdollar(quoted)
24972339Sabialint quoted;
25072339Sabial{
25172339Sabial	int otask;
25272339Sabial	struct io *oiop;
25372339Sabial	char *dolp;
25472339Sabial	register char *s, c, *cp;
25572339Sabial	struct var *vp;
25672339Sabial
25772339Sabial	c = readc();
25872339Sabial	s = e.linep;
25972339Sabial	if (c != '{') {
26072339Sabial		*e.linep++ = c;
26172339Sabial		if (letter(c)) {
26272339Sabial			while ((c = readc())!=0 && letnum(c))
26372339Sabial				if (e.linep < elinep)
26472339Sabial					*e.linep++ = c;
26572339Sabial			unget(c);
26672339Sabial		}
26772339Sabial		c = 0;
26872339Sabial	} else {
26972339Sabial		oiop = e.iop;
27072339Sabial		otask = e.iop->task;
27172339Sabial		e.iop->task = XOTHER;
27272339Sabial		while ((c = subgetc('"', 0))!=0 && c!='}' && c!='\n')
27372339Sabial			if (e.linep < elinep)
27472339Sabial				*e.linep++ = c;
27572339Sabial		if (oiop == e.iop)
27672339Sabial			e.iop->task = otask;
27772339Sabial		if (c != '}') {
27872339Sabial			err("unclosed ${");
27972339Sabial			gflg++;
28072339Sabial			return(c);
28172339Sabial		}
28272339Sabial	}
28372339Sabial	if (e.linep >= elinep) {
28472339Sabial		err("string in ${} too long");
28572339Sabial		gflg++;
28672339Sabial		e.linep -= 10;
28772339Sabial	}
28872339Sabial	*e.linep = 0;
28972339Sabial	if (*s)
29072339Sabial		for (cp = s+1; *cp; cp++)
29172339Sabial			if (any(*cp, "=-+?")) {
29272339Sabial				c = *cp;
29372339Sabial				*cp++ = 0;
29472339Sabial				break;
29572339Sabial			}
29672339Sabial	if (s[1] == 0 && (*s == '*' || *s == '@')) {
29772339Sabial		if (dolc > 1) {
29872339Sabial			/* currently this does not distinguish $* and $@ */
29972339Sabial			/* should check dollar */
30072339Sabial			e.linep = s;
30172339Sabial			PUSHIO(awordlist, dolv+1, dolchar);
30272339Sabial			return(0);
30372339Sabial		} else {	/* trap the nasty ${=} */
30472339Sabial			s[0] = '1';
30572339Sabial			s[1] = 0;
30672339Sabial		}
30772339Sabial	}
30872339Sabial	vp = lookup(s);
30972339Sabial	if ((dolp = vp->value) == null) {
31072339Sabial		switch (c) {
31172339Sabial		case '=':
31272339Sabial			if (digit(*s)) {
31372339Sabial				err("cannot use ${...=...} with $n");
31472339Sabial				gflg++;
31572339Sabial				break;
31672339Sabial			}
31772339Sabial			setval(vp, cp);
31872339Sabial			dolp = vp->value;
31972339Sabial			break;
32072339Sabial
32172339Sabial		case '-':
32272339Sabial			dolp = strsave(cp, areanum);
32372339Sabial			break;
32472339Sabial
32572339Sabial		case '?':
32672339Sabial			if (*cp == 0) {
32772339Sabial				prs("missing value for ");
32872339Sabial				err(s);
32972339Sabial			} else
33072339Sabial				err(cp);
33172339Sabial			gflg++;
33272339Sabial			break;
33372339Sabial		}
33472339Sabial	} else if (c == '+')
33572339Sabial		dolp = strsave(cp, areanum);
33672339Sabial	if (flag['u'] && dolp == null) {
33772339Sabial		prs("unset variable: ");
33872339Sabial		err(s);
33972339Sabial		gflg++;
34072339Sabial	}
34172339Sabial	e.linep = s;
34272339Sabial	PUSHIO(aword, dolp, quoted ? qstrchar : strchar);
34372339Sabial	return(0);
34472339Sabial}
34572339Sabial
34672339Sabial/*
34772339Sabial * Run the command in `...` and read its output.
34872339Sabial */
34972339Sabialstatic int
35072339Sabialgrave(quoted)
35172339Sabialint quoted;
35272339Sabial{
35372339Sabial	register char *cp;
35472339Sabial	register int i;
35572339Sabial	int pf[2];
35672339Sabial
35772339Sabial	for (cp = e.iop->argp->aword; *cp != '`'; cp++)
35872339Sabial		if (*cp == 0) {
35972339Sabial			err("no closing `");
36072339Sabial			return(0);
36172339Sabial		}
36272339Sabial	if (openpipe(pf) < 0)
36372339Sabial		return(0);
36472339Sabial	if ((i = fork()) == -1) {
36572339Sabial		closepipe(pf);
36672339Sabial		err("try again");
36772339Sabial		return(0);
36872339Sabial	}
36972339Sabial	if (i != 0) {
37072339Sabial		e.iop->argp->aword = ++cp;
37172339Sabial		close(pf[1]);
37272339Sabial		PUSHIO(afile, remap(pf[0]), quoted? qgravechar: gravechar);
37372339Sabial		return(1);
37472339Sabial	}
37572339Sabial	*cp = 0;
37672339Sabial	/* allow trapped signals */
37772339Sabial	for (i=0; i<=_NSIG; i++)
37872339Sabial		if (ourtrap[i] && signal(i, SIG_IGN) != SIG_IGN)
37972339Sabial			signal(i, SIG_DFL);
38072339Sabial	dup2(pf[1], 1);
38172339Sabial	closepipe(pf);
38272339Sabial	flag['e'] = 0;
38372339Sabial	flag['v'] = 0;
38472339Sabial	flag['n'] = 0;
38572339Sabial	cp = strsave(e.iop->argp->aword, 0);
38672339Sabial	areanum = 1;
38772339Sabial	freehere(areanum);
38872339Sabial	freearea(areanum);	/* free old space */
38972339Sabial	e.oenv = NULL;
39072339Sabial	e.iop = (e.iobase = iostack) - 1;
39172339Sabial	unquote(cp);
39272339Sabial	talking = 0;
39372339Sabial	PUSHIO(aword, cp, nlchar);
39472339Sabial	onecommand();
39572339Sabial	exit(1);
39672339Sabial}
39772339Sabial
39872339Sabialchar *
39972339Sabialunquote(as)
40072339Sabialregister char *as;
40172339Sabial{
40272339Sabial	register char *s;
40372339Sabial
40472339Sabial	if ((s = as) != NULL)
40572339Sabial		while (*s)
40672339Sabial			*s++ &= ~QUOTE;
40772339Sabial	return(as);
40872339Sabial}
40972339Sabial
41072339Sabial/* -------- glob.c -------- */
41172339Sabial/* #include "sh.h" */
41272339Sabial
41372339Sabial/*
41472339Sabial * glob
41572339Sabial */
41672339Sabial
41772339Sabial#define	scopy(x) strsave((x), areanum)
41872339Sabial#define	BLKSIZ	512
41972339Sabial#define	NDENT	((BLKSIZ+sizeof(struct dirent)-1)/sizeof(struct dirent))
42072339Sabial
42172339Sabialstatic	struct wdblock	*cl, *nl;
42272339Sabialstatic	char	spcl[] = "[?*";
42372339Sabial
42472339Sabialstruct wdblock *
42572339Sabialglob(cp, wb)
42672339Sabialchar *cp;
42772339Sabialstruct wdblock *wb;
42872339Sabial{
42972339Sabial	register i;
43072339Sabial	register char *pp;
43172339Sabial
43272339Sabial	if (cp == 0)
43372339Sabial		return(wb);
43472339Sabial	i = 0;
43572339Sabial	for (pp = cp; *pp; pp++)
43672339Sabial		if (any(*pp, spcl))
43772339Sabial			i++;
43872339Sabial		else if (!any(*pp & ~QUOTE, spcl))
43972339Sabial			*pp &= ~QUOTE;
44072339Sabial	if (i != 0) {
44172339Sabial		for (cl = addword(scopy(cp), (struct wdblock *)0); anyspcl(cl); cl = nl) {
44272339Sabial			nl = newword(cl->w_nword*2);
44372339Sabial			for(i=0; i<cl->w_nword; i++) { /* for each argument */
44472339Sabial				for (pp = cl->w_words[i]; *pp; pp++)
44572339Sabial					if (any(*pp, spcl)) {
44672339Sabial						globname(cl->w_words[i], pp);
44772339Sabial						break;
44872339Sabial					}
44972339Sabial				if (*pp == '\0')
45072339Sabial					nl = addword(scopy(cl->w_words[i]), nl);
45172339Sabial			}
45272339Sabial			for(i=0; i<cl->w_nword; i++)
45372339Sabial				DELETE(cl->w_words[i]);
45472339Sabial			DELETE(cl);
45572339Sabial		}
45672339Sabial		for(i=0; i<cl->w_nword; i++)
45772339Sabial			unquote(cl->w_words[i]);
45872339Sabial		glob0((char *)cl->w_words, cl->w_nword, sizeof(char *), xstrcmp);
45972339Sabial		if (cl->w_nword) {
46072339Sabial			for (i=0; i<cl->w_nword; i++)
46172339Sabial				wb = addword(cl->w_words[i], wb);
46272339Sabial			DELETE(cl);
46372339Sabial			return(wb);
46472339Sabial		}
46572339Sabial	}
46672339Sabial	wb = addword(unquote(cp), wb);
46772339Sabial	return(wb);
46872339Sabial}
46972339Sabial
47072339Sabialvoid
47172339Sabialglobname(we, pp)
47272339Sabialchar *we;
47372339Sabialregister char *pp;
47472339Sabial{
47572339Sabial	register char *np, *cp;
47672339Sabial	char *name, *gp, *dp;
47772339Sabial	int dn, j, n, k;
47872339Sabial	DIR *dirp;
47972339Sabial	struct dirent *de;
48072339Sabial	char dname[NAME_MAX+1];
48172339Sabial	struct stat dbuf;
48272339Sabial
48372339Sabial	for (np = we; np != pp; pp--)
48472339Sabial		if (pp[-1] == '/')
48572339Sabial			break;
48672339Sabial	for (dp = cp = space((int)(pp-np)+3); np < pp;)
48772339Sabial		*cp++ = *np++;
48872339Sabial	*cp++ = '.';
48972339Sabial	*cp = '\0';
49072339Sabial	for (gp = cp = space(strlen(pp)+1); *np && *np != '/';)
49172339Sabial		*cp++ = *np++;
49272339Sabial	*cp = '\0';
49372339Sabial	dirp = opendir(dp);
49472339Sabial	if (dirp == 0) {
49572339Sabial		DELETE(dp);
49672339Sabial		DELETE(gp);
49772339Sabial		return;
49872339Sabial	}
49972339Sabial	dname[NAME_MAX] = '\0';
50072339Sabial	while ((de=readdir(dirp))!=NULL) {
50172339Sabial		/* XXX Hmmm... What this could be? (abial) */
50272339Sabial		/*
50372339Sabial		if (ent[j].d_ino == 0)
50472339Sabial			continue;
50572339Sabial		*/
50672339Sabial		strncpy(dname, de->d_name, NAME_MAX);
50772339Sabial			if (dname[0] == '.')
50872339Sabial				if (*gp != '.')
50972339Sabial					continue;
51072339Sabial			for(k=0; k<NAME_MAX; k++)
51172339Sabial				if (any(dname[k], spcl))
51272339Sabial					dname[k] |= QUOTE;
51372339Sabial			if (gmatch(dname, gp)) {
51472339Sabial				name = generate(we, pp, dname, np);
51572339Sabial				if (*np && !anys(np, spcl)) {
51672339Sabial					if (stat(name,&dbuf)) {
51772339Sabial						DELETE(name);
51872339Sabial						continue;
51972339Sabial					}
52072339Sabial				}
52172339Sabial				nl = addword(name, nl);
52272339Sabial			}
52372339Sabial	}
52472339Sabial	closedir(dirp);
52572339Sabial	DELETE(dp);
52672339Sabial	DELETE(gp);
52772339Sabial}
52872339Sabial
52972339Sabial/*
53072339Sabial * generate a pathname as below.
53172339Sabial * start..end1 / middle end
53272339Sabial * the slashes come for free
53372339Sabial */
53472339Sabialstatic char *
53572339Sabialgenerate(start1, end1, middle, end)
53672339Sabialchar *start1;
53772339Sabialregister char *end1;
53872339Sabialchar *middle, *end;
53972339Sabial{
54072339Sabial	char *p;
54172339Sabial	register char *op, *xp;
54272339Sabial
54372339Sabial	p = op = space((int)(end1-start1)+strlen(middle)+strlen(end)+2);
54472339Sabial	for (xp = start1; xp != end1;)
54572339Sabial		*op++ = *xp++;
54672339Sabial	for (xp = middle; (*op++ = *xp++) != '\0';)
54772339Sabial		;
54872339Sabial	op--;
54972339Sabial	for (xp = end; (*op++ = *xp++) != '\0';)
55072339Sabial		;
55172339Sabial	return(p);
55272339Sabial}
55372339Sabial
55472339Sabialstatic int
55572339Sabialanyspcl(wb)
55672339Sabialregister struct wdblock *wb;
55772339Sabial{
55872339Sabial	register i;
55972339Sabial	register char **wd;
56072339Sabial
56172339Sabial	wd = wb->w_words;
56272339Sabial	for (i=0; i<wb->w_nword; i++)
56372339Sabial		if (anys(spcl, *wd++))
56472339Sabial			return(1);
56572339Sabial	return(0);
56672339Sabial}
56772339Sabial
56872339Sabialstatic int
56972339Sabialxstrcmp(p1, p2)
57072339Sabialchar *p1, *p2;
57172339Sabial{
57272339Sabial	return(strcmp(*(char **)p1, *(char **)p2));
57372339Sabial}
57472339Sabial
57572339Sabial/* -------- word.c -------- */
57672339Sabial/* #include "sh.h" */
57772339Sabial/* #include "word.h" */
57872339Sabial
57972339Sabial#define	NSTART	16	/* default number of words to allow for initially */
58072339Sabial
58172339Sabialstruct wdblock *
58272339Sabialnewword(nw)
58372339Sabialregister int nw;
58472339Sabial{
58572339Sabial	register struct wdblock *wb;
58672339Sabial
58772339Sabial	wb = (struct wdblock *) space(sizeof(*wb) + nw*sizeof(char *));
58872339Sabial	wb->w_bsize = nw;
58972339Sabial	wb->w_nword = 0;
59072339Sabial	return(wb);
59172339Sabial}
59272339Sabial
59372339Sabialstruct wdblock *
59472339Sabialaddword(wd, wb)
59572339Sabialchar *wd;
59672339Sabialregister struct wdblock *wb;
59772339Sabial{
59872339Sabial	register struct wdblock *wb2;
59972339Sabial	register nw;
60072339Sabial
60172339Sabial	if (wb == NULL)
60272339Sabial		wb = newword(NSTART);
60372339Sabial	if ((nw = wb->w_nword) >= wb->w_bsize) {
60472339Sabial		wb2 = newword(nw * 2);
60572339Sabial		memcopy((char *)wb2->w_words, (char *)wb->w_words, nw*sizeof(char *));
60672339Sabial		wb2->w_nword = nw;
60772339Sabial		DELETE(wb);
60872339Sabial		wb = wb2;
60972339Sabial	}
61072339Sabial	wb->w_words[wb->w_nword++] = wd;
61172339Sabial	return(wb);
61272339Sabial}
61372339Sabial
61472339Sabialchar **
61572339Sabialgetwords(wb)
61672339Sabialregister struct wdblock *wb;
61772339Sabial{
61872339Sabial	register char **wd;
61972339Sabial	register nb;
62072339Sabial
62172339Sabial	if (wb == NULL)
62272339Sabial		return((char **)NULL);
62372339Sabial	if (wb->w_nword == 0) {
62472339Sabial		DELETE(wb);
62572339Sabial		return((char **)NULL);
62672339Sabial	}
62772339Sabial	wd = (char **) space(nb = sizeof(*wd) * wb->w_nword);
62872339Sabial	memcopy((char *)wd, (char *)wb->w_words, nb);
62972339Sabial	DELETE(wb);	/* perhaps should done by caller */
63072339Sabial	return(wd);
63172339Sabial}
63272339Sabial
63372339Sabial_PROTOTYPE(int (*func), (char *, char *));
63472339Sabialint	globv;
63572339Sabial
63672339Sabialvoid
63772339Sabialglob0(a0, a1, a2, a3)
63872339Sabialchar *a0;
63972339Sabialunsigned a1;
64072339Sabialint a2;
64172339Sabial_PROTOTYPE(int (*a3), (char *, char *));
64272339Sabial{
64372339Sabial	func = a3;
64472339Sabial	globv = a2;
64572339Sabial	glob1(a0, a0 + a1 * a2);
64672339Sabial}
64772339Sabial
64872339Sabialvoid
64972339Sabialglob1(base, lim)
65072339Sabialchar *base, *lim;
65172339Sabial{
65272339Sabial	register char *i, *j;
65372339Sabial	int v2;
65472339Sabial	char *lptr, *hptr;
65572339Sabial	int c;
65672339Sabial	unsigned n;
65772339Sabial
65872339Sabial
65972339Sabial	v2 = globv;
66072339Sabial
66172339Sabialtop:
66272339Sabial	if ((n=(int)(lim-base)) <= v2)
66372339Sabial		return;
66472339Sabial	n = v2 * (n / (2*v2));
66572339Sabial	hptr = lptr = base+n;
66672339Sabial	i = base;
66772339Sabial	j = lim-v2;
66872339Sabial	for(;;) {
66972339Sabial		if (i < lptr) {
67072339Sabial			if ((c = (*func)(i, lptr)) == 0) {
67172339Sabial				glob2(i, lptr -= v2);
67272339Sabial				continue;
67372339Sabial			}
67472339Sabial			if (c < 0) {
67572339Sabial				i += v2;
67672339Sabial				continue;
67772339Sabial			}
67872339Sabial		}
67972339Sabial
68072339Sabialbegin:
68172339Sabial		if (j > hptr) {
68272339Sabial			if ((c = (*func)(hptr, j)) == 0) {
68372339Sabial				glob2(hptr += v2, j);
68472339Sabial				goto begin;
68572339Sabial			}
68672339Sabial			if (c > 0) {
68772339Sabial				if (i == lptr) {
68872339Sabial					glob3(i, hptr += v2, j);
68972339Sabial					i = lptr += v2;
69072339Sabial					goto begin;
69172339Sabial				}
69272339Sabial				glob2(i, j);
69372339Sabial				j -= v2;
69472339Sabial				i += v2;
69572339Sabial				continue;
69672339Sabial			}
69772339Sabial			j -= v2;
69872339Sabial			goto begin;
69972339Sabial		}
70072339Sabial
70172339Sabial
70272339Sabial		if (i == lptr) {
70372339Sabial			if (lptr-base >= lim-hptr) {
70472339Sabial				glob1(hptr+v2, lim);
70572339Sabial				lim = lptr;
70672339Sabial			} else {
70772339Sabial				glob1(base, lptr);
70872339Sabial				base = hptr+v2;
70972339Sabial			}
71072339Sabial			goto top;
71172339Sabial		}
71272339Sabial
71372339Sabial
71472339Sabial		glob3(j, lptr -= v2, i);
71572339Sabial		j = hptr -= v2;
71672339Sabial	}
71772339Sabial}
71872339Sabial
71972339Sabialvoid
72072339Sabialglob2(i, j)
72172339Sabialchar *i, *j;
72272339Sabial{
72372339Sabial	register char *index1, *index2, c;
72472339Sabial	int m;
72572339Sabial
72672339Sabial	m = globv;
72772339Sabial	index1 = i;
72872339Sabial	index2 = j;
72972339Sabial	do {
73072339Sabial		c = *index1;
73172339Sabial		*index1++ = *index2;
73272339Sabial		*index2++ = c;
73372339Sabial	} while(--m);
73472339Sabial}
73572339Sabial
73672339Sabialvoid
73772339Sabialglob3(i, j, k)
73872339Sabialchar *i, *j, *k;
73972339Sabial{
74072339Sabial	register char *index1, *index2, *index3;
74172339Sabial	int c;
74272339Sabial	int m;
74372339Sabial
74472339Sabial	m = globv;
74572339Sabial	index1 = i;
74672339Sabial	index2 = j;
74772339Sabial	index3 = k;
74872339Sabial	do {
74972339Sabial		c = *index1;
75072339Sabial		*index1++ = *index3;
75172339Sabial		*index3++ = *index2;
75272339Sabial		*index2++ = c;
75372339Sabial	} while(--m);
75472339Sabial}
75572339Sabial
75672339Sabialchar *
75772339Sabialmemcopy(ato, from, nb)
75872339Sabialregister char *ato, *from;
75972339Sabialregister int nb;
76072339Sabial{
76172339Sabial	register char *to;
76272339Sabial
76372339Sabial	to = ato;
76472339Sabial	while (--nb >= 0)
76572339Sabial		*to++ = *from++;
76672339Sabial	return(ato);
76772339Sabial}
768