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