Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

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