xref: /plan9/sys/src/ape/cmd/make/misc.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1*219b2ee8SDavid du Colombier #include "defs.h"
2*219b2ee8SDavid du Colombier 
3*219b2ee8SDavid du Colombier static int	hasslash(char *);
4*219b2ee8SDavid du Colombier static int	haspercent(char *);
5*219b2ee8SDavid du Colombier static void	rehash(void);
6*219b2ee8SDavid du Colombier 
7*219b2ee8SDavid du Colombier /* simple linear hash.  hash function is sum of
8*219b2ee8SDavid du Colombier    characters mod hash table size.
9*219b2ee8SDavid du Colombier */
10*219b2ee8SDavid du Colombier static int
11*219b2ee8SDavid du Colombier hashloc(char *s)
12*219b2ee8SDavid du Colombier {
13*219b2ee8SDavid du Colombier int i;
14*219b2ee8SDavid du Colombier int hashval;
15*219b2ee8SDavid du Colombier char *t;
16*219b2ee8SDavid du Colombier 
17*219b2ee8SDavid du Colombier hashval = 0;
18*219b2ee8SDavid du Colombier 
19*219b2ee8SDavid du Colombier for(t=s; *t!='\0' ; ++t)
20*219b2ee8SDavid du Colombier 	hashval += *t;
21*219b2ee8SDavid du Colombier 
22*219b2ee8SDavid du Colombier hashval %= hashsize;
23*219b2ee8SDavid du Colombier 
24*219b2ee8SDavid du Colombier for(i=hashval;
25*219b2ee8SDavid du Colombier 	hashtab[i]!=0 && !equal(s,hashtab[i]->namep);
26*219b2ee8SDavid du Colombier 	i = i >= hashsize-1 ? 0 : i+1) ;
27*219b2ee8SDavid du Colombier 
28*219b2ee8SDavid du Colombier return i;
29*219b2ee8SDavid du Colombier }
30*219b2ee8SDavid du Colombier 
31*219b2ee8SDavid du Colombier 
32*219b2ee8SDavid du Colombier nameblkp
33*219b2ee8SDavid du Colombier srchname(char *s)
34*219b2ee8SDavid du Colombier {
35*219b2ee8SDavid du Colombier return  hashtab[hashloc(s)] ;
36*219b2ee8SDavid du Colombier }
37*219b2ee8SDavid du Colombier 
38*219b2ee8SDavid du Colombier 
39*219b2ee8SDavid du Colombier 
40*219b2ee8SDavid du Colombier nameblkp
41*219b2ee8SDavid du Colombier makename(char *s)
42*219b2ee8SDavid du Colombier {
43*219b2ee8SDavid du Colombier nameblkp p;
44*219b2ee8SDavid du Colombier 
45*219b2ee8SDavid du Colombier if(nhashed > hashthresh)
46*219b2ee8SDavid du Colombier 	rehash();
47*219b2ee8SDavid du Colombier 
48*219b2ee8SDavid du Colombier ++nhashed;
49*219b2ee8SDavid du Colombier hashtab[hashloc(s)] = p = ALLOC(nameblock);
50*219b2ee8SDavid du Colombier p->nxtnameblock = firstname;
51*219b2ee8SDavid du Colombier p->namep = copys(s);	/* make a fresh copy of the string s */
52*219b2ee8SDavid du Colombier /* p->linep = 0; p->done = 0; p->septype = 0; p->modtime = 0; */
53*219b2ee8SDavid du Colombier 
54*219b2ee8SDavid du Colombier firstname = p;
55*219b2ee8SDavid du Colombier if(mainname==NULL && !haspercent(s) && (*s!='.' || hasslash(s)) )
56*219b2ee8SDavid du Colombier 	mainname = p;
57*219b2ee8SDavid du Colombier 
58*219b2ee8SDavid du Colombier return p;
59*219b2ee8SDavid du Colombier }
60*219b2ee8SDavid du Colombier 
61*219b2ee8SDavid du Colombier 
62*219b2ee8SDavid du Colombier static int
63*219b2ee8SDavid du Colombier hasslash(char *s)
64*219b2ee8SDavid du Colombier {
65*219b2ee8SDavid du Colombier for( ; *s ; ++s)
66*219b2ee8SDavid du Colombier 	if(*s == '/')
67*219b2ee8SDavid du Colombier 		return YES;
68*219b2ee8SDavid du Colombier return NO;
69*219b2ee8SDavid du Colombier }
70*219b2ee8SDavid du Colombier 
71*219b2ee8SDavid du Colombier static int
72*219b2ee8SDavid du Colombier haspercent(char *s)
73*219b2ee8SDavid du Colombier {
74*219b2ee8SDavid du Colombier for( ; *s ; ++s)
75*219b2ee8SDavid du Colombier 	if(*s == '%')
76*219b2ee8SDavid du Colombier 		return YES;
77*219b2ee8SDavid du Colombier return NO;
78*219b2ee8SDavid du Colombier }
79*219b2ee8SDavid du Colombier 
80*219b2ee8SDavid du Colombier int
81*219b2ee8SDavid du Colombier hasparen(char *s)
82*219b2ee8SDavid du Colombier {
83*219b2ee8SDavid du Colombier for( ; *s ; ++s)
84*219b2ee8SDavid du Colombier 	if(*s == '(')
85*219b2ee8SDavid du Colombier 		return YES;
86*219b2ee8SDavid du Colombier return NO;
87*219b2ee8SDavid du Colombier }
88*219b2ee8SDavid du Colombier 
89*219b2ee8SDavid du Colombier static void
90*219b2ee8SDavid du Colombier rehash(void)
91*219b2ee8SDavid du Colombier {
92*219b2ee8SDavid du Colombier nameblkp *ohash;
93*219b2ee8SDavid du Colombier nameblkp p, *hp, *endohash;
94*219b2ee8SDavid du Colombier hp = ohash = hashtab;
95*219b2ee8SDavid du Colombier endohash = hashtab + hashsize;
96*219b2ee8SDavid du Colombier 
97*219b2ee8SDavid du Colombier newhash(2*hashsize);
98*219b2ee8SDavid du Colombier 
99*219b2ee8SDavid du Colombier while( hp<endohash )
100*219b2ee8SDavid du Colombier 	if(p = *hp++)
101*219b2ee8SDavid du Colombier 		hashtab[hashloc(p->namep)] = p;
102*219b2ee8SDavid du Colombier 
103*219b2ee8SDavid du Colombier free( (char *) ohash);
104*219b2ee8SDavid du Colombier }
105*219b2ee8SDavid du Colombier 
106*219b2ee8SDavid du Colombier 
107*219b2ee8SDavid du Colombier void
108*219b2ee8SDavid du Colombier newhash(int newsize)
109*219b2ee8SDavid du Colombier {
110*219b2ee8SDavid du Colombier hashsize = newsize;
111*219b2ee8SDavid du Colombier hashtab = (nameblkp *) ckalloc(hashsize * sizeof(nameblkp));
112*219b2ee8SDavid du Colombier hashthresh = (2*hashsize)/3;
113*219b2ee8SDavid du Colombier }
114*219b2ee8SDavid du Colombier 
115*219b2ee8SDavid du Colombier 
116*219b2ee8SDavid du Colombier 
117*219b2ee8SDavid du Colombier nameblkp chkname(char *s)
118*219b2ee8SDavid du Colombier {
119*219b2ee8SDavid du Colombier nameblkp p;
120*219b2ee8SDavid du Colombier time_t k;
121*219b2ee8SDavid du Colombier /*TEMP NEW */
122*219b2ee8SDavid du Colombier if(hasparen(s))
123*219b2ee8SDavid du Colombier 	{
124*219b2ee8SDavid du Colombier 	k = lookarch(s);
125*219b2ee8SDavid du Colombier /*TEMP	fprintf(stderr, "chkname(%s): look=%d\n", s, k); */
126*219b2ee8SDavid du Colombier 	if(k == 0)
127*219b2ee8SDavid du Colombier 		return NULL;
128*219b2ee8SDavid du Colombier 	}
129*219b2ee8SDavid du Colombier if(p = srchname(s))
130*219b2ee8SDavid du Colombier 	return p;
131*219b2ee8SDavid du Colombier dirsrch(s);
132*219b2ee8SDavid du Colombier return srchname(s);
133*219b2ee8SDavid du Colombier }
134*219b2ee8SDavid du Colombier 
135*219b2ee8SDavid du Colombier 
136*219b2ee8SDavid du Colombier 
137*219b2ee8SDavid du Colombier char *
138*219b2ee8SDavid du Colombier copys(char *s)
139*219b2ee8SDavid du Colombier {
140*219b2ee8SDavid du Colombier char *t;
141*219b2ee8SDavid du Colombier 
142*219b2ee8SDavid du Colombier if( (t = malloc( strlen(s)+1 ) ) == NULL)
143*219b2ee8SDavid du Colombier 	fatal("out of memory");
144*219b2ee8SDavid du Colombier strcpy(t, s);
145*219b2ee8SDavid du Colombier return t;
146*219b2ee8SDavid du Colombier }
147*219b2ee8SDavid du Colombier 
148*219b2ee8SDavid du Colombier 
149*219b2ee8SDavid du Colombier 
150*219b2ee8SDavid du Colombier char *
151*219b2ee8SDavid du Colombier concat(char *a, char *b, char *c)   /* c = concatenation of a and b */
152*219b2ee8SDavid du Colombier {
153*219b2ee8SDavid du Colombier char *t;
154*219b2ee8SDavid du Colombier t = c;
155*219b2ee8SDavid du Colombier 
156*219b2ee8SDavid du Colombier while(*t = *a++) t++;
157*219b2ee8SDavid du Colombier while(*t++ = *b++);
158*219b2ee8SDavid du Colombier return c;
159*219b2ee8SDavid du Colombier }
160*219b2ee8SDavid du Colombier 
161*219b2ee8SDavid du Colombier 
162*219b2ee8SDavid du Colombier int
163*219b2ee8SDavid du Colombier suffix(char *a, char *b, char *p)  /* is b the suffix of a?  if so, set p = prefix */
164*219b2ee8SDavid du Colombier {
165*219b2ee8SDavid du Colombier char *a0,*b0;
166*219b2ee8SDavid du Colombier a0 = a;
167*219b2ee8SDavid du Colombier b0 = b;
168*219b2ee8SDavid du Colombier 
169*219b2ee8SDavid du Colombier while(*a++);
170*219b2ee8SDavid du Colombier while(*b++);
171*219b2ee8SDavid du Colombier 
172*219b2ee8SDavid du Colombier if( (a-a0) < (b-b0) ) return 0;
173*219b2ee8SDavid du Colombier 
174*219b2ee8SDavid du Colombier while(b>b0)
175*219b2ee8SDavid du Colombier 	if(*--a != *--b) return 0;
176*219b2ee8SDavid du Colombier 
177*219b2ee8SDavid du Colombier while(a0<a) *p++ = *a0++;
178*219b2ee8SDavid du Colombier *p = '\0';
179*219b2ee8SDavid du Colombier 
180*219b2ee8SDavid du Colombier return 1;
181*219b2ee8SDavid du Colombier }
182*219b2ee8SDavid du Colombier 
183*219b2ee8SDavid du Colombier int *
184*219b2ee8SDavid du Colombier ckalloc(int n)
185*219b2ee8SDavid du Colombier {
186*219b2ee8SDavid du Colombier int *p;
187*219b2ee8SDavid du Colombier 
188*219b2ee8SDavid du Colombier if( p = (int *) calloc(1,n) )
189*219b2ee8SDavid du Colombier 	return p;
190*219b2ee8SDavid du Colombier 
191*219b2ee8SDavid du Colombier fatal("out of memory");
192*219b2ee8SDavid du Colombier /* NOTREACHED */
193*219b2ee8SDavid du Colombier }
194*219b2ee8SDavid du Colombier 
195*219b2ee8SDavid du Colombier /* copy string a into b, substituting for arguments */
196*219b2ee8SDavid du Colombier char *
197*219b2ee8SDavid du Colombier subst(char *a, char *b)
198*219b2ee8SDavid du Colombier {
199*219b2ee8SDavid du Colombier static depth	= 0;
200*219b2ee8SDavid du Colombier char *s;
201*219b2ee8SDavid du Colombier char vname[100];
202*219b2ee8SDavid du Colombier struct varblock *vbp;
203*219b2ee8SDavid du Colombier char closer;
204*219b2ee8SDavid du Colombier 
205*219b2ee8SDavid du Colombier if(++depth > 100)
206*219b2ee8SDavid du Colombier 	fatal("infinitely recursive macro?");
207*219b2ee8SDavid du Colombier if(a)  while(*a)
208*219b2ee8SDavid du Colombier 	{
209*219b2ee8SDavid du Colombier 	if(*a!='$' || a[1]=='\0' || *++a=='$')
210*219b2ee8SDavid du Colombier 		/* if a non-macro character copy it.  if $$ or $\0, copy $ */
211*219b2ee8SDavid du Colombier 		*b++ = *a++;
212*219b2ee8SDavid du Colombier 	else	{
213*219b2ee8SDavid du Colombier 		s = vname;
214*219b2ee8SDavid du Colombier 		if( *a=='(' || *a=='{' )
215*219b2ee8SDavid du Colombier 			{
216*219b2ee8SDavid du Colombier 			closer = ( *a=='(' ? ')' : '}');
217*219b2ee8SDavid du Colombier 			++a;
218*219b2ee8SDavid du Colombier 			while(*a == ' ') ++a;
219*219b2ee8SDavid du Colombier 			while(*a!=' ' && *a!=closer && *a!='\0') *s++ = *a++;
220*219b2ee8SDavid du Colombier 			while(*a!=closer && *a!='\0') ++a;
221*219b2ee8SDavid du Colombier 			if(*a == closer) ++a;
222*219b2ee8SDavid du Colombier 			}
223*219b2ee8SDavid du Colombier 		else	*s++ = *a++;
224*219b2ee8SDavid du Colombier 
225*219b2ee8SDavid du Colombier 		*s = '\0';
226*219b2ee8SDavid du Colombier 		if( (vbp = varptr(vname)) ->varval != 0)
227*219b2ee8SDavid du Colombier 			{
228*219b2ee8SDavid du Colombier 			b = subst(vbp->varval, b);
229*219b2ee8SDavid du Colombier 			vbp->used = YES;
230*219b2ee8SDavid du Colombier 			}
231*219b2ee8SDavid du Colombier 		}
232*219b2ee8SDavid du Colombier 	}
233*219b2ee8SDavid du Colombier 
234*219b2ee8SDavid du Colombier *b = '\0';
235*219b2ee8SDavid du Colombier --depth;
236*219b2ee8SDavid du Colombier return b;
237*219b2ee8SDavid du Colombier }
238*219b2ee8SDavid du Colombier 
239*219b2ee8SDavid du Colombier void
240*219b2ee8SDavid du Colombier setvar(char *v, char *s, int dyn)
241*219b2ee8SDavid du Colombier {
242*219b2ee8SDavid du Colombier struct varblock *p;
243*219b2ee8SDavid du Colombier 
244*219b2ee8SDavid du Colombier p = varptr(v);
245*219b2ee8SDavid du Colombier if( ! p->noreset )
246*219b2ee8SDavid du Colombier 	{
247*219b2ee8SDavid du Colombier 	p->varval = s;
248*219b2ee8SDavid du Colombier 	p->noreset = inarglist;
249*219b2ee8SDavid du Colombier 	if(p->used && !dyn)
250*219b2ee8SDavid du Colombier 		fprintf(stderr, "Warning: %s changed after being used\n",v);
251*219b2ee8SDavid du Colombier 	if(p->export)
252*219b2ee8SDavid du Colombier 		{
253*219b2ee8SDavid du Colombier 		/* change string pointed to by environment to new v=s */
254*219b2ee8SDavid du Colombier 		char *t;
255*219b2ee8SDavid du Colombier 		int lenv;
256*219b2ee8SDavid du Colombier 		lenv = strlen(v);
257*219b2ee8SDavid du Colombier 		*(p->export) = t = (char *) ckalloc(lenv + strlen(s) + 2);
258*219b2ee8SDavid du Colombier 		strcpy(t,v);
259*219b2ee8SDavid du Colombier 		t[lenv] = '=';
260*219b2ee8SDavid du Colombier 		strcpy(t+lenv+1, s);
261*219b2ee8SDavid du Colombier 		}
262*219b2ee8SDavid du Colombier 	else
263*219b2ee8SDavid du Colombier 		p->export = envpp;
264*219b2ee8SDavid du Colombier 	}
265*219b2ee8SDavid du Colombier }
266*219b2ee8SDavid du Colombier 
267*219b2ee8SDavid du Colombier 
268*219b2ee8SDavid du Colombier /* for setting Bradford's *D and *F family of macros whens setting * etc */
269*219b2ee8SDavid du Colombier void
270*219b2ee8SDavid du Colombier set3var(char *macro, char *value)
271*219b2ee8SDavid du Colombier {
272*219b2ee8SDavid du Colombier char *s;
273*219b2ee8SDavid du Colombier char macjunk[8], *lastslash, *dirpart, *filepart;
274*219b2ee8SDavid du Colombier 
275*219b2ee8SDavid du Colombier setvar(macro, value, YES);
276*219b2ee8SDavid du Colombier if(value == CHNULL)
277*219b2ee8SDavid du Colombier 	dirpart = filepart = CHNULL;
278*219b2ee8SDavid du Colombier else
279*219b2ee8SDavid du Colombier 	{
280*219b2ee8SDavid du Colombier 	lastslash = CHNULL;
281*219b2ee8SDavid du Colombier 	for(s = value; *s; ++s)
282*219b2ee8SDavid du Colombier 		if(*s == '/')
283*219b2ee8SDavid du Colombier 			lastslash = s;
284*219b2ee8SDavid du Colombier 	if(lastslash)
285*219b2ee8SDavid du Colombier 		{
286*219b2ee8SDavid du Colombier 		dirpart = copys(value);
287*219b2ee8SDavid du Colombier 		filepart = dirpart + (lastslash-value);
288*219b2ee8SDavid du Colombier 		filepart[-1] = '\0';
289*219b2ee8SDavid du Colombier 		}
290*219b2ee8SDavid du Colombier 	else
291*219b2ee8SDavid du Colombier 		{
292*219b2ee8SDavid du Colombier 		dirpart = "";
293*219b2ee8SDavid du Colombier 		filepart = value;
294*219b2ee8SDavid du Colombier 		}
295*219b2ee8SDavid du Colombier 	}
296*219b2ee8SDavid du Colombier setvar(concat(macro, "D", macjunk), dirpart, YES);
297*219b2ee8SDavid du Colombier setvar(concat(macro, "F", macjunk), filepart, YES);
298*219b2ee8SDavid du Colombier }
299*219b2ee8SDavid du Colombier 
300*219b2ee8SDavid du Colombier 
301*219b2ee8SDavid du Colombier int
302*219b2ee8SDavid du Colombier eqsign(char *a)   /*look for arguments with equal signs but not colons */
303*219b2ee8SDavid du Colombier {
304*219b2ee8SDavid du Colombier char *s, *t;
305*219b2ee8SDavid du Colombier char c;
306*219b2ee8SDavid du Colombier 
307*219b2ee8SDavid du Colombier while(*a == ' ') ++a;
308*219b2ee8SDavid du Colombier for(s=a  ;   *s!='\0' && *s!=':'  ; ++s)
309*219b2ee8SDavid du Colombier 	if(*s == '=')
310*219b2ee8SDavid du Colombier 		{
311*219b2ee8SDavid du Colombier 		for(t = a ; *t!='=' && *t!=' ' && *t!='\t' ;  ++t );
312*219b2ee8SDavid du Colombier 		c = *t;
313*219b2ee8SDavid du Colombier 		*t = '\0';
314*219b2ee8SDavid du Colombier 
315*219b2ee8SDavid du Colombier 		for(++s; *s==' ' || *s=='\t' ; ++s);
316*219b2ee8SDavid du Colombier 		setvar(a, copys(s), NO);
317*219b2ee8SDavid du Colombier 		*t = c;
318*219b2ee8SDavid du Colombier 		return YES;
319*219b2ee8SDavid du Colombier 		}
320*219b2ee8SDavid du Colombier 
321*219b2ee8SDavid du Colombier return NO;
322*219b2ee8SDavid du Colombier }
323*219b2ee8SDavid du Colombier 
324*219b2ee8SDavid du Colombier struct varblock *
325*219b2ee8SDavid du Colombier varptr(char *v)
326*219b2ee8SDavid du Colombier {
327*219b2ee8SDavid du Colombier struct varblock *vp;
328*219b2ee8SDavid du Colombier 
329*219b2ee8SDavid du Colombier /* for compatibility, $(TGS) = $^ */
330*219b2ee8SDavid du Colombier if(equal(v, "TGS") )
331*219b2ee8SDavid du Colombier 	v = "^";
332*219b2ee8SDavid du Colombier for(vp = firstvar; vp ; vp = vp->nxtvarblock)
333*219b2ee8SDavid du Colombier 	if(equal(v , vp->varname))
334*219b2ee8SDavid du Colombier 		return vp;
335*219b2ee8SDavid du Colombier 
336*219b2ee8SDavid du Colombier vp = ALLOC(varblock);
337*219b2ee8SDavid du Colombier vp->nxtvarblock = firstvar;
338*219b2ee8SDavid du Colombier firstvar = vp;
339*219b2ee8SDavid du Colombier vp->varname = copys(v);
340*219b2ee8SDavid du Colombier vp->varval = 0;
341*219b2ee8SDavid du Colombier return vp;
342*219b2ee8SDavid du Colombier }
343*219b2ee8SDavid du Colombier 
344*219b2ee8SDavid du Colombier int
345*219b2ee8SDavid du Colombier dynmacro(char *line)
346*219b2ee8SDavid du Colombier {
347*219b2ee8SDavid du Colombier char *s;
348*219b2ee8SDavid du Colombier char endc, *endp;
349*219b2ee8SDavid du Colombier if(!isalpha(line[0]))
350*219b2ee8SDavid du Colombier 	return NO;
351*219b2ee8SDavid du Colombier for(s=line+1 ; *s && (isalpha(*s) | isdigit(*s)) ; ++s)
352*219b2ee8SDavid du Colombier 	;
353*219b2ee8SDavid du Colombier endp = s;
354*219b2ee8SDavid du Colombier while( isspace(*s) )
355*219b2ee8SDavid du Colombier 	++s;
356*219b2ee8SDavid du Colombier if(s[0]!=':' || s[1]!='=')
357*219b2ee8SDavid du Colombier 	return NO;
358*219b2ee8SDavid du Colombier 
359*219b2ee8SDavid du Colombier endc = *endp;
360*219b2ee8SDavid du Colombier *endp = '\0';
361*219b2ee8SDavid du Colombier setvar(line, copys(s+2), YES);
362*219b2ee8SDavid du Colombier *endp = endc;
363*219b2ee8SDavid du Colombier 
364*219b2ee8SDavid du Colombier return YES;
365*219b2ee8SDavid du Colombier }
366*219b2ee8SDavid du Colombier 
367*219b2ee8SDavid du Colombier 
368*219b2ee8SDavid du Colombier void
369*219b2ee8SDavid du Colombier fatal1(char *s, char *t)
370*219b2ee8SDavid du Colombier {
371*219b2ee8SDavid du Colombier char buf[100];
372*219b2ee8SDavid du Colombier sprintf(buf, s, t);
373*219b2ee8SDavid du Colombier fatal(buf);
374*219b2ee8SDavid du Colombier }
375*219b2ee8SDavid du Colombier 
376*219b2ee8SDavid du Colombier 
377*219b2ee8SDavid du Colombier void
378*219b2ee8SDavid du Colombier fatal(char *s)
379*219b2ee8SDavid du Colombier {
380*219b2ee8SDavid du Colombier fflush(stdout);
381*219b2ee8SDavid du Colombier if(s)
382*219b2ee8SDavid du Colombier 	fprintf(stderr, "Make: %s.  Stop.\n", s);
383*219b2ee8SDavid du Colombier else
384*219b2ee8SDavid du Colombier 	fprintf(stderr, "\nStop.\n");
385*219b2ee8SDavid du Colombier 
386*219b2ee8SDavid du Colombier waitstack(0);
387*219b2ee8SDavid du Colombier exit(1);
388*219b2ee8SDavid du Colombier }
389*219b2ee8SDavid du Colombier 
390*219b2ee8SDavid du Colombier 
391*219b2ee8SDavid du Colombier 
392*219b2ee8SDavid du Colombier /* appends to the chain for $? and $^ */
393*219b2ee8SDavid du Colombier chainp
394*219b2ee8SDavid du Colombier appendq(chainp head, char *tail)
395*219b2ee8SDavid du Colombier {
396*219b2ee8SDavid du Colombier chainp p, q;
397*219b2ee8SDavid du Colombier 
398*219b2ee8SDavid du Colombier p = ALLOC(chain);
399*219b2ee8SDavid du Colombier p->datap = tail;
400*219b2ee8SDavid du Colombier 
401*219b2ee8SDavid du Colombier if(head)
402*219b2ee8SDavid du Colombier 	{
403*219b2ee8SDavid du Colombier 	for(q = head ; q->nextp ; q = q->nextp)
404*219b2ee8SDavid du Colombier 		;
405*219b2ee8SDavid du Colombier 	q->nextp = p;
406*219b2ee8SDavid du Colombier 	return head;
407*219b2ee8SDavid du Colombier 	}
408*219b2ee8SDavid du Colombier else
409*219b2ee8SDavid du Colombier 	return p;
410*219b2ee8SDavid du Colombier }
411*219b2ee8SDavid du Colombier 
412*219b2ee8SDavid du Colombier 
413*219b2ee8SDavid du Colombier 
414*219b2ee8SDavid du Colombier 
415*219b2ee8SDavid du Colombier 
416*219b2ee8SDavid du Colombier /* builds the value for $? and $^ */
417*219b2ee8SDavid du Colombier char *
418*219b2ee8SDavid du Colombier mkqlist(chainp p, char *qbuf)
419*219b2ee8SDavid du Colombier {
420*219b2ee8SDavid du Colombier char *qbufp, *s;
421*219b2ee8SDavid du Colombier 
422*219b2ee8SDavid du Colombier if(p == NULL)
423*219b2ee8SDavid du Colombier 	return "";
424*219b2ee8SDavid du Colombier 
425*219b2ee8SDavid du Colombier qbufp = qbuf;
426*219b2ee8SDavid du Colombier 
427*219b2ee8SDavid du Colombier for( ; p ; p = p->nextp)
428*219b2ee8SDavid du Colombier 	{
429*219b2ee8SDavid du Colombier 	s = p->datap;
430*219b2ee8SDavid du Colombier 	if(qbufp+strlen(s) > &qbuf[QBUFMAX-3])
431*219b2ee8SDavid du Colombier 		{
432*219b2ee8SDavid du Colombier 		fprintf(stderr, "$? list too long\n");
433*219b2ee8SDavid du Colombier 		break;
434*219b2ee8SDavid du Colombier 		}
435*219b2ee8SDavid du Colombier 	while (*s)
436*219b2ee8SDavid du Colombier 		*qbufp++ = *s++;
437*219b2ee8SDavid du Colombier 	*qbufp++ = ' ';
438*219b2ee8SDavid du Colombier 	}
439*219b2ee8SDavid du Colombier *--qbufp = '\0';
440*219b2ee8SDavid du Colombier return qbuf;
441*219b2ee8SDavid du Colombier }
442*219b2ee8SDavid du Colombier 
443*219b2ee8SDavid du Colombier wildp
444*219b2ee8SDavid du Colombier iswild(char *name)
445*219b2ee8SDavid du Colombier {
446*219b2ee8SDavid du Colombier char *s;
447*219b2ee8SDavid du Colombier wildp p;
448*219b2ee8SDavid du Colombier 
449*219b2ee8SDavid du Colombier for(s=name; *s; ++s)
450*219b2ee8SDavid du Colombier 	if(*s == '%')
451*219b2ee8SDavid du Colombier 		{
452*219b2ee8SDavid du Colombier 		p = ALLOC(wild);
453*219b2ee8SDavid du Colombier 		*s = '\0';
454*219b2ee8SDavid du Colombier 		p->left = copys(name);
455*219b2ee8SDavid du Colombier 		*s = '%';
456*219b2ee8SDavid du Colombier 		p->right = copys(s+1);
457*219b2ee8SDavid du Colombier 		p->llen = strlen(p->left);
458*219b2ee8SDavid du Colombier 		p->rlen = strlen(p->right);
459*219b2ee8SDavid du Colombier 		p->totlen = p->llen + p->rlen;
460*219b2ee8SDavid du Colombier 		return p;
461*219b2ee8SDavid du Colombier 		}
462*219b2ee8SDavid du Colombier return NULL;
463*219b2ee8SDavid du Colombier }
464*219b2ee8SDavid du Colombier 
465*219b2ee8SDavid du Colombier 
466*219b2ee8SDavid du Colombier char *
467*219b2ee8SDavid du Colombier wildmatch(wildp p, char *name, int len)
468*219b2ee8SDavid du Colombier {
469*219b2ee8SDavid du Colombier char *stem;
470*219b2ee8SDavid du Colombier char *s;
471*219b2ee8SDavid du Colombier char c;
472*219b2ee8SDavid du Colombier 
473*219b2ee8SDavid du Colombier if(len < p->totlen ||
474*219b2ee8SDavid du Colombier    strncmp(name, p->left, p->llen) ||
475*219b2ee8SDavid du Colombier    strncmp(s = name+len-p->rlen, p->right, p->rlen) )
476*219b2ee8SDavid du Colombier 	return CHNULL;
477*219b2ee8SDavid du Colombier 
478*219b2ee8SDavid du Colombier /*TEMP fprintf(stderr, "wildmatch(%s)=%s%%%s)\n", name,p->left,p->right); */
479*219b2ee8SDavid du Colombier c = *s;
480*219b2ee8SDavid du Colombier *s = '\0';
481*219b2ee8SDavid du Colombier stem = copys(name + p->llen);
482*219b2ee8SDavid du Colombier *s = c;
483*219b2ee8SDavid du Colombier return stem;
484*219b2ee8SDavid du Colombier }
485*219b2ee8SDavid du Colombier 
486*219b2ee8SDavid du Colombier 
487*219b2ee8SDavid du Colombier 
488*219b2ee8SDavid du Colombier /* substitute stem for any % marks */
489*219b2ee8SDavid du Colombier char *
490*219b2ee8SDavid du Colombier wildsub(char *pat, char *stem)
491*219b2ee8SDavid du Colombier {
492*219b2ee8SDavid du Colombier static char temp[100];
493*219b2ee8SDavid du Colombier char *s, *t;
494*219b2ee8SDavid du Colombier 
495*219b2ee8SDavid du Colombier s = temp;
496*219b2ee8SDavid du Colombier for(; *pat; ++pat)
497*219b2ee8SDavid du Colombier 	if(*pat == '%')
498*219b2ee8SDavid du Colombier 		for(t = stem ; *t; )
499*219b2ee8SDavid du Colombier 			*s++ = *t++;
500*219b2ee8SDavid du Colombier 	else
501*219b2ee8SDavid du Colombier 		*s++ = *pat;
502*219b2ee8SDavid du Colombier *s = '\0';
503*219b2ee8SDavid du Colombier return temp;
504*219b2ee8SDavid du Colombier }
505