xref: /plan9/sys/src/ape/cmd/make/misc.c (revision 9b7bf7df4595c26f1e9b67beb0c6e44c9876fb05)
1219b2ee8SDavid du Colombier #include "defs.h"
2219b2ee8SDavid du Colombier 
3219b2ee8SDavid du Colombier static int	hasslash(char *);
4219b2ee8SDavid du Colombier static int	haspercent(char *);
5219b2ee8SDavid du Colombier static void	rehash(void);
6219b2ee8SDavid du Colombier 
7219b2ee8SDavid du Colombier /* simple linear hash.  hash function is sum of
8219b2ee8SDavid du Colombier    characters mod hash table size.
9219b2ee8SDavid du Colombier */
10219b2ee8SDavid du Colombier static int
hashloc(char * s)11219b2ee8SDavid du Colombier hashloc(char *s)
12219b2ee8SDavid du Colombier {
13219b2ee8SDavid du Colombier int i;
14219b2ee8SDavid du Colombier int hashval;
15219b2ee8SDavid du Colombier char *t;
16219b2ee8SDavid du Colombier 
17219b2ee8SDavid du Colombier hashval = 0;
18219b2ee8SDavid du Colombier 
19219b2ee8SDavid du Colombier for(t=s; *t!='\0' ; ++t)
20219b2ee8SDavid du Colombier 	hashval += *t;
21219b2ee8SDavid du Colombier 
22219b2ee8SDavid du Colombier hashval %= hashsize;
23219b2ee8SDavid du Colombier 
24219b2ee8SDavid du Colombier for(i=hashval;
25219b2ee8SDavid du Colombier 	hashtab[i]!=0 && !equal(s,hashtab[i]->namep);
26219b2ee8SDavid du Colombier 	i = i >= hashsize-1 ? 0 : i+1) ;
27219b2ee8SDavid du Colombier 
28219b2ee8SDavid du Colombier return i;
29219b2ee8SDavid du Colombier }
30219b2ee8SDavid du Colombier 
31219b2ee8SDavid du Colombier 
32219b2ee8SDavid du Colombier nameblkp
srchname(char * s)33219b2ee8SDavid du Colombier srchname(char *s)
34219b2ee8SDavid du Colombier {
35219b2ee8SDavid du Colombier return  hashtab[hashloc(s)] ;
36219b2ee8SDavid du Colombier }
37219b2ee8SDavid du Colombier 
38219b2ee8SDavid du Colombier 
39219b2ee8SDavid du Colombier 
40219b2ee8SDavid du Colombier nameblkp
makename(char * s)41219b2ee8SDavid du Colombier makename(char *s)
42219b2ee8SDavid du Colombier {
43219b2ee8SDavid du Colombier nameblkp p;
44219b2ee8SDavid du Colombier 
45219b2ee8SDavid du Colombier if(nhashed > hashthresh)
46219b2ee8SDavid du Colombier 	rehash();
47219b2ee8SDavid du Colombier 
48219b2ee8SDavid du Colombier ++nhashed;
49219b2ee8SDavid du Colombier hashtab[hashloc(s)] = p = ALLOC(nameblock);
50219b2ee8SDavid du Colombier p->nxtnameblock = firstname;
51219b2ee8SDavid du Colombier p->namep = copys(s);	/* make a fresh copy of the string s */
52219b2ee8SDavid du Colombier /* p->linep = 0; p->done = 0; p->septype = 0; p->modtime = 0; */
53219b2ee8SDavid du Colombier 
54219b2ee8SDavid du Colombier firstname = p;
55219b2ee8SDavid du Colombier if(mainname==NULL && !haspercent(s) && (*s!='.' || hasslash(s)) )
56219b2ee8SDavid du Colombier 	mainname = p;
57219b2ee8SDavid du Colombier 
58219b2ee8SDavid du Colombier return p;
59219b2ee8SDavid du Colombier }
60219b2ee8SDavid du Colombier 
61219b2ee8SDavid du Colombier 
62219b2ee8SDavid du Colombier static int
hasslash(char * s)63219b2ee8SDavid du Colombier hasslash(char *s)
64219b2ee8SDavid du Colombier {
65219b2ee8SDavid du Colombier for( ; *s ; ++s)
66219b2ee8SDavid du Colombier 	if(*s == '/')
67219b2ee8SDavid du Colombier 		return YES;
68219b2ee8SDavid du Colombier return NO;
69219b2ee8SDavid du Colombier }
70219b2ee8SDavid du Colombier 
71219b2ee8SDavid du Colombier static int
haspercent(char * s)72219b2ee8SDavid du Colombier haspercent(char *s)
73219b2ee8SDavid du Colombier {
74219b2ee8SDavid du Colombier for( ; *s ; ++s)
75219b2ee8SDavid du Colombier 	if(*s == '%')
76219b2ee8SDavid du Colombier 		return YES;
77219b2ee8SDavid du Colombier return NO;
78219b2ee8SDavid du Colombier }
79219b2ee8SDavid du Colombier 
80219b2ee8SDavid du Colombier int
hasparen(char * s)81219b2ee8SDavid du Colombier hasparen(char *s)
82219b2ee8SDavid du Colombier {
83219b2ee8SDavid du Colombier for( ; *s ; ++s)
84219b2ee8SDavid du Colombier 	if(*s == '(')
85219b2ee8SDavid du Colombier 		return YES;
86219b2ee8SDavid du Colombier return NO;
87219b2ee8SDavid du Colombier }
88219b2ee8SDavid du Colombier 
89219b2ee8SDavid du Colombier static void
rehash(void)90219b2ee8SDavid du Colombier rehash(void)
91219b2ee8SDavid du Colombier {
92219b2ee8SDavid du Colombier nameblkp *ohash;
93219b2ee8SDavid du Colombier nameblkp p, *hp, *endohash;
94219b2ee8SDavid du Colombier hp = ohash = hashtab;
95219b2ee8SDavid du Colombier endohash = hashtab + hashsize;
96219b2ee8SDavid du Colombier 
97219b2ee8SDavid du Colombier newhash(2*hashsize);
98219b2ee8SDavid du Colombier 
99219b2ee8SDavid du Colombier while( hp<endohash )
100219b2ee8SDavid du Colombier 	if(p = *hp++)
101219b2ee8SDavid du Colombier 		hashtab[hashloc(p->namep)] = p;
102219b2ee8SDavid du Colombier 
103219b2ee8SDavid du Colombier free( (char *) ohash);
104219b2ee8SDavid du Colombier }
105219b2ee8SDavid du Colombier 
106219b2ee8SDavid du Colombier 
107219b2ee8SDavid du Colombier void
newhash(int newsize)108219b2ee8SDavid du Colombier newhash(int newsize)
109219b2ee8SDavid du Colombier {
110219b2ee8SDavid du Colombier hashsize = newsize;
111219b2ee8SDavid du Colombier hashtab = (nameblkp *) ckalloc(hashsize * sizeof(nameblkp));
112219b2ee8SDavid du Colombier hashthresh = (2*hashsize)/3;
113219b2ee8SDavid du Colombier }
114219b2ee8SDavid du Colombier 
115219b2ee8SDavid du Colombier 
116219b2ee8SDavid du Colombier 
chkname(char * s)117219b2ee8SDavid du Colombier nameblkp chkname(char *s)
118219b2ee8SDavid du Colombier {
119219b2ee8SDavid du Colombier nameblkp p;
120219b2ee8SDavid du Colombier time_t k;
121219b2ee8SDavid du Colombier /*TEMP NEW */
122219b2ee8SDavid du Colombier if(hasparen(s))
123219b2ee8SDavid du Colombier 	{
124219b2ee8SDavid du Colombier 	k = lookarch(s);
125219b2ee8SDavid du Colombier /*TEMP	fprintf(stderr, "chkname(%s): look=%d\n", s, k); */
126219b2ee8SDavid du Colombier 	if(k == 0)
127219b2ee8SDavid du Colombier 		return NULL;
128219b2ee8SDavid du Colombier 	}
129219b2ee8SDavid du Colombier if(p = srchname(s))
130219b2ee8SDavid du Colombier 	return p;
131219b2ee8SDavid du Colombier dirsrch(s);
132219b2ee8SDavid du Colombier return srchname(s);
133219b2ee8SDavid du Colombier }
134219b2ee8SDavid du Colombier 
135219b2ee8SDavid du Colombier 
136219b2ee8SDavid du Colombier 
137219b2ee8SDavid du Colombier char *
copys(char * s)138219b2ee8SDavid du Colombier copys(char *s)
139219b2ee8SDavid du Colombier {
140219b2ee8SDavid du Colombier char *t;
141219b2ee8SDavid du Colombier 
142219b2ee8SDavid du Colombier if( (t = malloc( strlen(s)+1 ) ) == NULL)
143219b2ee8SDavid du Colombier 	fatal("out of memory");
144219b2ee8SDavid du Colombier strcpy(t, s);
145219b2ee8SDavid du Colombier return t;
146219b2ee8SDavid du Colombier }
147219b2ee8SDavid du Colombier 
148219b2ee8SDavid du Colombier 
149219b2ee8SDavid du Colombier 
150219b2ee8SDavid du Colombier char *
concat(char * a,char * b,char * c)151219b2ee8SDavid du Colombier concat(char *a, char *b, char *c)   /* c = concatenation of a and b */
152219b2ee8SDavid du Colombier {
153219b2ee8SDavid du Colombier char *t;
154219b2ee8SDavid du Colombier t = c;
155219b2ee8SDavid du Colombier 
156219b2ee8SDavid du Colombier while(*t = *a++) t++;
157219b2ee8SDavid du Colombier while(*t++ = *b++);
158219b2ee8SDavid du Colombier return c;
159219b2ee8SDavid du Colombier }
160219b2ee8SDavid du Colombier 
161219b2ee8SDavid du Colombier 
162219b2ee8SDavid du Colombier int
suffix(char * a,char * b,char * p)163219b2ee8SDavid du Colombier suffix(char *a, char *b, char *p)  /* is b the suffix of a?  if so, set p = prefix */
164219b2ee8SDavid du Colombier {
165219b2ee8SDavid du Colombier char *a0,*b0;
166219b2ee8SDavid du Colombier a0 = a;
167219b2ee8SDavid du Colombier b0 = b;
168219b2ee8SDavid du Colombier 
169219b2ee8SDavid du Colombier while(*a++);
170219b2ee8SDavid du Colombier while(*b++);
171219b2ee8SDavid du Colombier 
172219b2ee8SDavid du Colombier if( (a-a0) < (b-b0) ) return 0;
173219b2ee8SDavid du Colombier 
174219b2ee8SDavid du Colombier while(b>b0)
175219b2ee8SDavid du Colombier 	if(*--a != *--b) return 0;
176219b2ee8SDavid du Colombier 
177219b2ee8SDavid du Colombier while(a0<a) *p++ = *a0++;
178219b2ee8SDavid du Colombier *p = '\0';
179219b2ee8SDavid du Colombier 
180219b2ee8SDavid du Colombier return 1;
181219b2ee8SDavid du Colombier }
182219b2ee8SDavid du Colombier 
183219b2ee8SDavid du Colombier int *
ckalloc(int n)184219b2ee8SDavid du Colombier ckalloc(int n)
185219b2ee8SDavid du Colombier {
186219b2ee8SDavid du Colombier int *p;
187219b2ee8SDavid du Colombier 
188219b2ee8SDavid du Colombier if( p = (int *) calloc(1,n) )
189219b2ee8SDavid du Colombier 	return p;
190219b2ee8SDavid du Colombier 
191219b2ee8SDavid du Colombier fatal("out of memory");
192219b2ee8SDavid du Colombier /* NOTREACHED */
193027288c8SDavid du Colombier return 0;
194219b2ee8SDavid du Colombier }
195219b2ee8SDavid du Colombier 
196219b2ee8SDavid du Colombier /* copy string a into b, substituting for arguments */
197219b2ee8SDavid du Colombier char *
subst(char * a,char * b,char * e)198*9b7bf7dfSDavid du Colombier subst(char *a, char *b, char *e)
199219b2ee8SDavid du Colombier {
200219b2ee8SDavid du Colombier static depth	= 0;
201219b2ee8SDavid du Colombier char *s;
202219b2ee8SDavid du Colombier char vname[100];
203219b2ee8SDavid du Colombier struct varblock *vbp;
204219b2ee8SDavid du Colombier char closer;
205219b2ee8SDavid du Colombier 
206219b2ee8SDavid du Colombier if(++depth > 100)
207219b2ee8SDavid du Colombier 	fatal("infinitely recursive macro?");
208219b2ee8SDavid du Colombier if(a)  while(*a)
209219b2ee8SDavid du Colombier 	{
210219b2ee8SDavid du Colombier 	if(*a!='$' || a[1]=='\0' || *++a=='$')
211219b2ee8SDavid du Colombier 		/* if a non-macro character copy it.  if $$ or $\0, copy $ */
212219b2ee8SDavid du Colombier 		*b++ = *a++;
213219b2ee8SDavid du Colombier 	else	{
214219b2ee8SDavid du Colombier 		s = vname;
215219b2ee8SDavid du Colombier 		if( *a=='(' || *a=='{' )
216219b2ee8SDavid du Colombier 			{
217219b2ee8SDavid du Colombier 			closer = ( *a=='(' ? ')' : '}');
218219b2ee8SDavid du Colombier 			++a;
219219b2ee8SDavid du Colombier 			while(*a == ' ') ++a;
220219b2ee8SDavid du Colombier 			while(*a!=' ' && *a!=closer && *a!='\0') *s++ = *a++;
221219b2ee8SDavid du Colombier 			while(*a!=closer && *a!='\0') ++a;
222219b2ee8SDavid du Colombier 			if(*a == closer) ++a;
223219b2ee8SDavid du Colombier 			}
224219b2ee8SDavid du Colombier 		else	*s++ = *a++;
225219b2ee8SDavid du Colombier 
226219b2ee8SDavid du Colombier 		*s = '\0';
227219b2ee8SDavid du Colombier 		if( (vbp = varptr(vname)) ->varval != 0)
228219b2ee8SDavid du Colombier 			{
229*9b7bf7dfSDavid du Colombier 			b = subst(vbp->varval, b, e);
230219b2ee8SDavid du Colombier 			vbp->used = YES;
231219b2ee8SDavid du Colombier 			}
232219b2ee8SDavid du Colombier 		}
233*9b7bf7dfSDavid du Colombier 		if(b >= e)
234*9b7bf7dfSDavid du Colombier 			fatal("macro expanded too far");
235219b2ee8SDavid du Colombier 	}
236219b2ee8SDavid du Colombier 
237219b2ee8SDavid du Colombier *b = '\0';
238219b2ee8SDavid du Colombier --depth;
239219b2ee8SDavid du Colombier return b;
240219b2ee8SDavid du Colombier }
241219b2ee8SDavid du Colombier 
242219b2ee8SDavid du Colombier void
setvar(char * v,char * s,int dyn)243219b2ee8SDavid du Colombier setvar(char *v, char *s, int dyn)
244219b2ee8SDavid du Colombier {
245219b2ee8SDavid du Colombier struct varblock *p;
246219b2ee8SDavid du Colombier 
247219b2ee8SDavid du Colombier p = varptr(v);
248219b2ee8SDavid du Colombier if( ! p->noreset )
249219b2ee8SDavid du Colombier 	{
250219b2ee8SDavid du Colombier 	p->varval = s;
251219b2ee8SDavid du Colombier 	p->noreset = inarglist;
252219b2ee8SDavid du Colombier 	if(p->used && !dyn)
253219b2ee8SDavid du Colombier 		fprintf(stderr, "Warning: %s changed after being used\n",v);
254219b2ee8SDavid du Colombier 	if(p->export)
255219b2ee8SDavid du Colombier 		{
256219b2ee8SDavid du Colombier 		/* change string pointed to by environment to new v=s */
257219b2ee8SDavid du Colombier 		char *t;
258219b2ee8SDavid du Colombier 		int lenv;
259219b2ee8SDavid du Colombier 		lenv = strlen(v);
260219b2ee8SDavid du Colombier 		*(p->export) = t = (char *) ckalloc(lenv + strlen(s) + 2);
261219b2ee8SDavid du Colombier 		strcpy(t,v);
262219b2ee8SDavid du Colombier 		t[lenv] = '=';
263219b2ee8SDavid du Colombier 		strcpy(t+lenv+1, s);
264219b2ee8SDavid du Colombier 		}
265219b2ee8SDavid du Colombier 	else
266219b2ee8SDavid du Colombier 		p->export = envpp;
267219b2ee8SDavid du Colombier 	}
268219b2ee8SDavid du Colombier }
269219b2ee8SDavid du Colombier 
270219b2ee8SDavid du Colombier 
271219b2ee8SDavid du Colombier /* for setting Bradford's *D and *F family of macros whens setting * etc */
272219b2ee8SDavid du Colombier void
set3var(char * macro,char * value)273219b2ee8SDavid du Colombier set3var(char *macro, char *value)
274219b2ee8SDavid du Colombier {
275219b2ee8SDavid du Colombier char *s;
276219b2ee8SDavid du Colombier char macjunk[8], *lastslash, *dirpart, *filepart;
277219b2ee8SDavid du Colombier 
278219b2ee8SDavid du Colombier setvar(macro, value, YES);
279219b2ee8SDavid du Colombier if(value == CHNULL)
280219b2ee8SDavid du Colombier 	dirpart = filepart = CHNULL;
281219b2ee8SDavid du Colombier else
282219b2ee8SDavid du Colombier 	{
283219b2ee8SDavid du Colombier 	lastslash = CHNULL;
284219b2ee8SDavid du Colombier 	for(s = value; *s; ++s)
285219b2ee8SDavid du Colombier 		if(*s == '/')
286219b2ee8SDavid du Colombier 			lastslash = s;
287219b2ee8SDavid du Colombier 	if(lastslash)
288219b2ee8SDavid du Colombier 		{
289219b2ee8SDavid du Colombier 		dirpart = copys(value);
290219b2ee8SDavid du Colombier 		filepart = dirpart + (lastslash-value);
291219b2ee8SDavid du Colombier 		filepart[-1] = '\0';
292219b2ee8SDavid du Colombier 		}
293219b2ee8SDavid du Colombier 	else
294219b2ee8SDavid du Colombier 		{
295219b2ee8SDavid du Colombier 		dirpart = "";
296219b2ee8SDavid du Colombier 		filepart = value;
297219b2ee8SDavid du Colombier 		}
298219b2ee8SDavid du Colombier 	}
299219b2ee8SDavid du Colombier setvar(concat(macro, "D", macjunk), dirpart, YES);
300219b2ee8SDavid du Colombier setvar(concat(macro, "F", macjunk), filepart, YES);
301219b2ee8SDavid du Colombier }
302219b2ee8SDavid du Colombier 
303219b2ee8SDavid du Colombier 
304219b2ee8SDavid du Colombier int
eqsign(char * a)305219b2ee8SDavid du Colombier eqsign(char *a)   /*look for arguments with equal signs but not colons */
306219b2ee8SDavid du Colombier {
307219b2ee8SDavid du Colombier char *s, *t;
308219b2ee8SDavid du Colombier char c;
309219b2ee8SDavid du Colombier 
310219b2ee8SDavid du Colombier while(*a == ' ') ++a;
311219b2ee8SDavid du Colombier for(s=a  ;   *s!='\0' && *s!=':'  ; ++s)
312219b2ee8SDavid du Colombier 	if(*s == '=')
313219b2ee8SDavid du Colombier 		{
314219b2ee8SDavid du Colombier 		for(t = a ; *t!='=' && *t!=' ' && *t!='\t' ;  ++t );
315219b2ee8SDavid du Colombier 		c = *t;
316219b2ee8SDavid du Colombier 		*t = '\0';
317219b2ee8SDavid du Colombier 
318219b2ee8SDavid du Colombier 		for(++s; *s==' ' || *s=='\t' ; ++s);
319219b2ee8SDavid du Colombier 		setvar(a, copys(s), NO);
320219b2ee8SDavid du Colombier 		*t = c;
321219b2ee8SDavid du Colombier 		return YES;
322219b2ee8SDavid du Colombier 		}
323219b2ee8SDavid du Colombier 
324219b2ee8SDavid du Colombier return NO;
325219b2ee8SDavid du Colombier }
326219b2ee8SDavid du Colombier 
327219b2ee8SDavid du Colombier struct varblock *
varptr(char * v)328219b2ee8SDavid du Colombier varptr(char *v)
329219b2ee8SDavid du Colombier {
330219b2ee8SDavid du Colombier struct varblock *vp;
331219b2ee8SDavid du Colombier 
332219b2ee8SDavid du Colombier /* for compatibility, $(TGS) = $^ */
333219b2ee8SDavid du Colombier if(equal(v, "TGS") )
334219b2ee8SDavid du Colombier 	v = "^";
335219b2ee8SDavid du Colombier for(vp = firstvar; vp ; vp = vp->nxtvarblock)
336219b2ee8SDavid du Colombier 	if(equal(v , vp->varname))
337219b2ee8SDavid du Colombier 		return vp;
338219b2ee8SDavid du Colombier 
339219b2ee8SDavid du Colombier vp = ALLOC(varblock);
340219b2ee8SDavid du Colombier vp->nxtvarblock = firstvar;
341219b2ee8SDavid du Colombier firstvar = vp;
342219b2ee8SDavid du Colombier vp->varname = copys(v);
343219b2ee8SDavid du Colombier vp->varval = 0;
344219b2ee8SDavid du Colombier return vp;
345219b2ee8SDavid du Colombier }
346219b2ee8SDavid du Colombier 
347219b2ee8SDavid du Colombier int
dynmacro(char * line)348219b2ee8SDavid du Colombier dynmacro(char *line)
349219b2ee8SDavid du Colombier {
350219b2ee8SDavid du Colombier char *s;
351219b2ee8SDavid du Colombier char endc, *endp;
352219b2ee8SDavid du Colombier if(!isalpha(line[0]))
353219b2ee8SDavid du Colombier 	return NO;
354219b2ee8SDavid du Colombier for(s=line+1 ; *s && (isalpha(*s) | isdigit(*s)) ; ++s)
355219b2ee8SDavid du Colombier 	;
356219b2ee8SDavid du Colombier endp = s;
357219b2ee8SDavid du Colombier while( isspace(*s) )
358219b2ee8SDavid du Colombier 	++s;
359219b2ee8SDavid du Colombier if(s[0]!=':' || s[1]!='=')
360219b2ee8SDavid du Colombier 	return NO;
361219b2ee8SDavid du Colombier 
362219b2ee8SDavid du Colombier endc = *endp;
363219b2ee8SDavid du Colombier *endp = '\0';
364219b2ee8SDavid du Colombier setvar(line, copys(s+2), YES);
365219b2ee8SDavid du Colombier *endp = endc;
366219b2ee8SDavid du Colombier 
367219b2ee8SDavid du Colombier return YES;
368219b2ee8SDavid du Colombier }
369219b2ee8SDavid du Colombier 
370219b2ee8SDavid du Colombier 
371219b2ee8SDavid du Colombier void
fatal1(char * s,char * t)372219b2ee8SDavid du Colombier fatal1(char *s, char *t)
373219b2ee8SDavid du Colombier {
374219b2ee8SDavid du Colombier char buf[100];
375219b2ee8SDavid du Colombier sprintf(buf, s, t);
376219b2ee8SDavid du Colombier fatal(buf);
377219b2ee8SDavid du Colombier }
378219b2ee8SDavid du Colombier 
379219b2ee8SDavid du Colombier 
380219b2ee8SDavid du Colombier void
fatal(char * s)381219b2ee8SDavid du Colombier fatal(char *s)
382219b2ee8SDavid du Colombier {
383219b2ee8SDavid du Colombier fflush(stdout);
384219b2ee8SDavid du Colombier if(s)
385219b2ee8SDavid du Colombier 	fprintf(stderr, "Make: %s.  Stop.\n", s);
386219b2ee8SDavid du Colombier else
387219b2ee8SDavid du Colombier 	fprintf(stderr, "\nStop.\n");
388219b2ee8SDavid du Colombier 
389219b2ee8SDavid du Colombier waitstack(0);
390219b2ee8SDavid du Colombier exit(1);
391219b2ee8SDavid du Colombier }
392219b2ee8SDavid du Colombier 
393219b2ee8SDavid du Colombier 
394219b2ee8SDavid du Colombier 
395219b2ee8SDavid du Colombier /* appends to the chain for $? and $^ */
396219b2ee8SDavid du Colombier chainp
appendq(chainp head,char * tail)397219b2ee8SDavid du Colombier appendq(chainp head, char *tail)
398219b2ee8SDavid du Colombier {
399219b2ee8SDavid du Colombier chainp p, q;
400219b2ee8SDavid du Colombier 
401219b2ee8SDavid du Colombier p = ALLOC(chain);
402219b2ee8SDavid du Colombier p->datap = tail;
403219b2ee8SDavid du Colombier 
404219b2ee8SDavid du Colombier if(head)
405219b2ee8SDavid du Colombier 	{
406219b2ee8SDavid du Colombier 	for(q = head ; q->nextp ; q = q->nextp)
407219b2ee8SDavid du Colombier 		;
408219b2ee8SDavid du Colombier 	q->nextp = p;
409219b2ee8SDavid du Colombier 	return head;
410219b2ee8SDavid du Colombier 	}
411219b2ee8SDavid du Colombier else
412219b2ee8SDavid du Colombier 	return p;
413219b2ee8SDavid du Colombier }
414219b2ee8SDavid du Colombier 
415219b2ee8SDavid du Colombier 
416219b2ee8SDavid du Colombier 
417219b2ee8SDavid du Colombier 
418219b2ee8SDavid du Colombier 
419219b2ee8SDavid du Colombier /* builds the value for $? and $^ */
420219b2ee8SDavid du Colombier char *
mkqlist(chainp p,char * qbuf)421219b2ee8SDavid du Colombier mkqlist(chainp p, char *qbuf)
422219b2ee8SDavid du Colombier {
423219b2ee8SDavid du Colombier char *qbufp, *s;
424219b2ee8SDavid du Colombier 
425219b2ee8SDavid du Colombier if(p == NULL)
426219b2ee8SDavid du Colombier 	return "";
427219b2ee8SDavid du Colombier 
428219b2ee8SDavid du Colombier qbufp = qbuf;
429219b2ee8SDavid du Colombier 
430219b2ee8SDavid du Colombier for( ; p ; p = p->nextp)
431219b2ee8SDavid du Colombier 	{
432219b2ee8SDavid du Colombier 	s = p->datap;
433219b2ee8SDavid du Colombier 	if(qbufp+strlen(s) > &qbuf[QBUFMAX-3])
434219b2ee8SDavid du Colombier 		{
435219b2ee8SDavid du Colombier 		fprintf(stderr, "$? list too long\n");
436219b2ee8SDavid du Colombier 		break;
437219b2ee8SDavid du Colombier 		}
438219b2ee8SDavid du Colombier 	while (*s)
439219b2ee8SDavid du Colombier 		*qbufp++ = *s++;
440219b2ee8SDavid du Colombier 	*qbufp++ = ' ';
441219b2ee8SDavid du Colombier 	}
442219b2ee8SDavid du Colombier *--qbufp = '\0';
443219b2ee8SDavid du Colombier return qbuf;
444219b2ee8SDavid du Colombier }
445219b2ee8SDavid du Colombier 
446219b2ee8SDavid du Colombier wildp
iswild(char * name)447219b2ee8SDavid du Colombier iswild(char *name)
448219b2ee8SDavid du Colombier {
449219b2ee8SDavid du Colombier char *s;
450219b2ee8SDavid du Colombier wildp p;
451219b2ee8SDavid du Colombier 
452219b2ee8SDavid du Colombier for(s=name; *s; ++s)
453219b2ee8SDavid du Colombier 	if(*s == '%')
454219b2ee8SDavid du Colombier 		{
455219b2ee8SDavid du Colombier 		p = ALLOC(wild);
456219b2ee8SDavid du Colombier 		*s = '\0';
457219b2ee8SDavid du Colombier 		p->left = copys(name);
458219b2ee8SDavid du Colombier 		*s = '%';
459219b2ee8SDavid du Colombier 		p->right = copys(s+1);
460219b2ee8SDavid du Colombier 		p->llen = strlen(p->left);
461219b2ee8SDavid du Colombier 		p->rlen = strlen(p->right);
462219b2ee8SDavid du Colombier 		p->totlen = p->llen + p->rlen;
463219b2ee8SDavid du Colombier 		return p;
464219b2ee8SDavid du Colombier 		}
465219b2ee8SDavid du Colombier return NULL;
466219b2ee8SDavid du Colombier }
467219b2ee8SDavid du Colombier 
468219b2ee8SDavid du Colombier 
469219b2ee8SDavid du Colombier char *
wildmatch(wildp p,char * name,int len)470219b2ee8SDavid du Colombier wildmatch(wildp p, char *name, int len)
471219b2ee8SDavid du Colombier {
472219b2ee8SDavid du Colombier char *stem;
473219b2ee8SDavid du Colombier char *s;
474219b2ee8SDavid du Colombier char c;
475219b2ee8SDavid du Colombier 
476219b2ee8SDavid du Colombier if(len < p->totlen ||
477219b2ee8SDavid du Colombier    strncmp(name, p->left, p->llen) ||
478219b2ee8SDavid du Colombier    strncmp(s = name+len-p->rlen, p->right, p->rlen) )
479219b2ee8SDavid du Colombier 	return CHNULL;
480219b2ee8SDavid du Colombier 
481219b2ee8SDavid du Colombier /*TEMP fprintf(stderr, "wildmatch(%s)=%s%%%s)\n", name,p->left,p->right); */
482219b2ee8SDavid du Colombier c = *s;
483219b2ee8SDavid du Colombier *s = '\0';
484219b2ee8SDavid du Colombier stem = copys(name + p->llen);
485219b2ee8SDavid du Colombier *s = c;
486219b2ee8SDavid du Colombier return stem;
487219b2ee8SDavid du Colombier }
488219b2ee8SDavid du Colombier 
489219b2ee8SDavid du Colombier 
490219b2ee8SDavid du Colombier 
491219b2ee8SDavid du Colombier /* substitute stem for any % marks */
492219b2ee8SDavid du Colombier char *
wildsub(char * pat,char * stem)493219b2ee8SDavid du Colombier wildsub(char *pat, char *stem)
494219b2ee8SDavid du Colombier {
495219b2ee8SDavid du Colombier static char temp[100];
496219b2ee8SDavid du Colombier char *s, *t;
497219b2ee8SDavid du Colombier 
498219b2ee8SDavid du Colombier s = temp;
499219b2ee8SDavid du Colombier for(; *pat; ++pat)
500219b2ee8SDavid du Colombier 	if(*pat == '%')
501219b2ee8SDavid du Colombier 		for(t = stem ; *t; )
502219b2ee8SDavid du Colombier 			*s++ = *t++;
503219b2ee8SDavid du Colombier 	else
504219b2ee8SDavid du Colombier 		*s++ = *pat;
505219b2ee8SDavid du Colombier *s = '\0';
506219b2ee8SDavid du Colombier return temp;
507219b2ee8SDavid du Colombier }
508