]> git.lizzy.rs Git - plan9front.git/blob - sys/src/ape/cmd/make/misc.c
libc: use Runemax instead of hardcoded 0x65536 for fmtchar check (thanks qrstuv)
[plan9front.git] / sys / src / ape / cmd / make / misc.c
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 \f
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 return 0;/* NOTREACHED */
193 }
194
195 /* copy string a into b, substituting for arguments */
196 char *
197 subst(char *a, char *b)
198 {
199 static depth    = 0;
200 char *s;
201 char vname[100];
202 struct varblock *vbp;
203 char closer;
204
205 if(++depth > 100)
206         fatal("infinitely recursive macro?");
207 if(a)  while(*a)
208         {
209         if(*a!='$' || a[1]=='\0' || *++a=='$')
210                 /* if a non-macro character copy it.  if $$ or $\0, copy $ */
211                 *b++ = *a++;
212         else    {
213                 s = vname;
214                 if( *a=='(' || *a=='{' )
215                         {
216                         closer = ( *a=='(' ? ')' : '}');
217                         ++a;
218                         while(*a == ' ') ++a;
219                         while(*a!=' ' && *a!=closer && *a!='\0') *s++ = *a++;
220                         while(*a!=closer && *a!='\0') ++a;
221                         if(*a == closer) ++a;
222                         }
223                 else    *s++ = *a++;
224
225                 *s = '\0';
226                 if( (vbp = varptr(vname)) ->varval != 0)
227                         {
228                         b = subst(vbp->varval, b);
229                         vbp->used = YES;
230                         }
231                 }
232         }
233
234 *b = '\0';
235 --depth;
236 return b;
237 }
238
239 void
240 setvar(char *v, char *s, int dyn)
241 {
242 struct varblock *p;
243
244 p = varptr(v);
245 if( ! p->noreset )
246         {
247         p->varval = s;
248         p->noreset = inarglist;
249         if(p->used && !dyn)
250                 fprintf(stderr, "Warning: %s changed after being used\n",v);
251         if(p->export)
252                 {
253                 /* change string pointed to by environment to new v=s */
254                 char *t;
255                 int lenv;
256                 lenv = strlen(v);
257                 *(p->export) = t = (char *) ckalloc(lenv + strlen(s) + 2);
258                 strcpy(t,v);
259                 t[lenv] = '=';
260                 strcpy(t+lenv+1, s);
261                 }
262         else
263                 p->export = envpp;
264         }
265 }
266
267
268 /* for setting Bradford's *D and *F family of macros whens setting * etc */
269 void
270 set3var(char *macro, char *value)
271 {
272 char *s;
273 char macjunk[8], *lastslash, *dirpart, *filepart;
274
275 setvar(macro, value, YES);
276 if(value == CHNULL)
277         dirpart = filepart = CHNULL;
278 else
279         {
280         lastslash = CHNULL;
281         for(s = value; *s; ++s)
282                 if(*s == '/')
283                         lastslash = s;
284         if(lastslash)
285                 {
286                 dirpart = copys(value);
287                 filepart = dirpart + (lastslash-value);
288                 filepart[-1] = '\0';
289                 }
290         else
291                 {
292                 dirpart = "";
293                 filepart = value;
294                 }
295         }
296 setvar(concat(macro, "D", macjunk), dirpart, YES);
297 setvar(concat(macro, "F", macjunk), filepart, YES);
298 }
299
300
301 int
302 eqsign(char *a)   /*look for arguments with equal signs but not colons */
303 {
304 char *s, *t;
305 char c;
306
307 while(*a == ' ') ++a;
308 for(s=a  ;   *s!='\0' && *s!=':'  ; ++s)
309         if(*s == '=')
310                 {
311                 for(t = a ; *t!='=' && *t!=' ' && *t!='\t' ;  ++t );
312                 c = *t;
313                 *t = '\0';
314
315                 for(++s; *s==' ' || *s=='\t' ; ++s);
316                 setvar(a, copys(s), NO);
317                 *t = c;
318                 return YES;
319                 }
320
321 return NO;
322 }
323
324 struct varblock *
325 varptr(char *v)
326 {
327 struct varblock *vp;
328
329 /* for compatibility, $(TGS) = $^ */
330 if(equal(v, "TGS") )
331         v = "^";
332 for(vp = firstvar; vp ; vp = vp->nxtvarblock)
333         if(equal(v , vp->varname))
334                 return vp;
335
336 vp = ALLOC(varblock);
337 vp->nxtvarblock = firstvar;
338 firstvar = vp;
339 vp->varname = copys(v);
340 vp->varval = 0;
341 return vp;
342 }
343
344 int
345 dynmacro(char *line)
346 {
347 char *s;
348 char endc, *endp;
349 if(!isalpha(line[0]))
350         return NO;
351 for(s=line+1 ; *s && (isalpha(*s) | isdigit(*s)) ; ++s)
352         ;
353 endp = s;
354 while( isspace(*s) )
355         ++s;
356 if(s[0]!=':' || s[1]!='=')
357         return NO;
358
359 endc = *endp;
360 *endp = '\0';
361 setvar(line, copys(s+2), YES);
362 *endp = endc;
363
364 return YES;
365 }
366
367
368 void
369 fatal1(char *s, char *t)
370 {
371 char buf[100];
372 sprintf(buf, s, t);
373 fatal(buf);
374 }
375
376
377 void
378 fatal(char *s)
379 {
380 fflush(stdout);
381 if(s)
382         fprintf(stderr, "Make: %s.  Stop.\n", s);
383 else
384         fprintf(stderr, "\nStop.\n");
385
386 waitstack(0);
387 exit(1);
388 }
389
390
391
392 /* appends to the chain for $? and $^ */
393 chainp
394 appendq(chainp head, char *tail)
395 {
396 chainp p, q;
397
398 p = ALLOC(chain);
399 p->datap = tail;
400
401 if(head)
402         {
403         for(q = head ; q->nextp ; q = q->nextp)
404                 ;
405         q->nextp = p;
406         return head;
407         }
408 else
409         return p;
410 }
411
412
413
414
415
416 /* builds the value for $? and $^ */
417 char *
418 mkqlist(chainp p, char *qbuf)
419 {
420 char *qbufp, *s;
421
422 if(p == NULL)
423         return "";
424
425 qbufp = qbuf;
426
427 for( ; p ; p = p->nextp)
428         {
429         s = p->datap;
430         if(qbufp+strlen(s) > &qbuf[QBUFMAX-3])
431                 {
432                 fprintf(stderr, "$? list too long\n");
433                 break;
434                 }
435         while (*s)
436                 *qbufp++ = *s++;
437         *qbufp++ = ' ';
438         }
439 *--qbufp = '\0';
440 return qbuf;
441 }
442
443 wildp
444 iswild(char *name)
445 {
446 char *s;
447 wildp p;
448
449 for(s=name; *s; ++s)
450         if(*s == '%')
451                 {
452                 p = ALLOC(wild);
453                 *s = '\0';
454                 p->left = copys(name);
455                 *s = '%';
456                 p->right = copys(s+1);
457                 p->llen = strlen(p->left);
458                 p->rlen = strlen(p->right);
459                 p->totlen = p->llen + p->rlen;
460                 return p;
461                 }
462 return NULL;
463 }
464
465
466 char *
467 wildmatch(wildp p, char *name, int len)
468 {
469 char *stem;
470 char *s;
471 char c;
472
473 if(len < p->totlen ||
474    strncmp(name, p->left, p->llen) ||
475    strncmp(s = name+len-p->rlen, p->right, p->rlen) )
476         return CHNULL;
477
478 /*TEMP fprintf(stderr, "wildmatch(%s)=%s%%%s)\n", name,p->left,p->right); */
479 c = *s;
480 *s = '\0';
481 stem = copys(name + p->llen);
482 *s = c;
483 return stem;
484 }
485
486
487
488 /* substitute stem for any % marks */
489 char *
490 wildsub(char *pat, char *stem)
491 {
492 static char temp[100];
493 char *s, *t;
494
495 s = temp;
496 for(; *pat; ++pat)
497         if(*pat == '%')
498                 for(t = stem ; *t; )
499                         *s++ = *t++;
500         else
501                 *s++ = *pat;
502 *s = '\0';
503 return temp;
504 }