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
hashloc(char * s)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
srchname(char * s)33 srchname(char *s)
34 {
35 return hashtab[hashloc(s)] ;
36 }
37
38
39
40 nameblkp
makename(char * s)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
hasslash(char * s)63 hasslash(char *s)
64 {
65 for( ; *s ; ++s)
66 if(*s == '/')
67 return YES;
68 return NO;
69 }
70
71 static int
haspercent(char * s)72 haspercent(char *s)
73 {
74 for( ; *s ; ++s)
75 if(*s == '%')
76 return YES;
77 return NO;
78 }
79
80 int
hasparen(char * s)81 hasparen(char *s)
82 {
83 for( ; *s ; ++s)
84 if(*s == '(')
85 return YES;
86 return NO;
87 }
88
89 static void
rehash(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
newhash(int newsize)108 newhash(int newsize)
109 {
110 hashsize = newsize;
111 hashtab = (nameblkp *) ckalloc(hashsize * sizeof(nameblkp));
112 hashthresh = (2*hashsize)/3;
113 }
114
115
116
chkname(char * s)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 *
copys(char * s)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 *
concat(char * a,char * b,char * c)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
suffix(char * a,char * b,char * p)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 *
ckalloc(int n)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 *
subst(char * a,char * b,char * e)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
setvar(char * v,char * s,int dyn)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
set3var(char * macro,char * value)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
eqsign(char * a)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 *
varptr(char * v)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
dynmacro(char * line)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
fatal1(char * s,char * t)372 fatal1(char *s, char *t)
373 {
374 char buf[100];
375 sprintf(buf, s, t);
376 fatal(buf);
377 }
378
379
380 void
fatal(char * s)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
appendq(chainp head,char * tail)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 *
mkqlist(chainp p,char * qbuf)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
iswild(char * name)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 *
wildmatch(wildp p,char * name,int len)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 *
wildsub(char * pat,char * stem)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 }
508