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 } 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 } 505