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