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, 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 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 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 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 * 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 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 372 fatal1(char *s, char *t) 373 { 374 char buf[100]; 375 sprintf(buf, s, t); 376 fatal(buf); 377 } 378 379 380 void 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 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 * 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 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 * 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 * 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