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