xref: /original-bsd/old/make/files.c (revision cd18b70b)
1 static	char *sccsid = "@(#)files.c	4.16 (Berkeley) 87/11/15";
2 #include <fcntl.h>
3 
4 /* UNIX DEPENDENT PROCEDURES */
5 
6 
7 /* DEFAULT RULES FOR UNIX */
8 
9 char *builtin[] =
10 	{
11 #ifdef pwb
12 	".SUFFIXES : .L .out .o .c .f .e .r .y .yr .ye .l .s .z .x .t .h .cl",
13 #else
14 	".SUFFIXES : .out .o .c .F .f .e .r .y .yr .ye .l .s .cl .p",
15 #endif
16 	"YACC=yacc",
17 	"YACCR=yacc -r",
18 	"YACCE=yacc -e",
19 	"YFLAGS=",
20 	"LEX=lex",
21 	"LFLAGS=",
22 	"CC=cc",
23 #if defined(vax) || defined(sun) || defined(tahoe)
24 	"AS=as",
25 #else
26 	"AS=as -",
27 #endif
28 	"PC=pc",
29 	"PFLAGS=",
30 	"CFLAGS=",
31 	"RC=f77",
32 	"RFLAGS=",
33 	"FC=f77",
34 	"EFLAGS=",
35 	"FFLAGS=",
36 	"LOADLIBES=",
37 #ifdef pwb
38 	"SCOMP=scomp",
39 	"SCFLAGS=",
40 	"CMDICT=cmdict",
41 	"CMFLAGS=",
42 #endif
43 
44 	".c.o :",
45 	"\t$(CC) $(CFLAGS) -c $<",
46 
47 	".p.o :",
48 	"\t$(PC) $(PFLAGS) -c $<",
49 
50 	".cl.o :",
51 	"\tclass -c $<",
52 
53 	".e.o .r.o .F.o .f.o :",
54 	"\t$(FC) $(RFLAGS) $(EFLAGS) $(FFLAGS) -c $<",
55 
56 	".s.o :",
57 	"\t$(AS) -o $@ $<",
58 
59 	".y.o :",
60 	"\t$(YACC) $(YFLAGS) $<",
61 	"\t$(CC) $(CFLAGS) -c y.tab.c",
62 	"\trm y.tab.c",
63 	"\tmv y.tab.o $@",
64 
65 	".yr.o:",
66 	"\t$(YACCR) $(YFLAGS) $<",
67 	"\t$(RC) $(RFLAGS) -c y.tab.r",
68 	"\trm y.tab.r",
69 	"\tmv y.tab.o $@",
70 
71 	".ye.o :",
72 	"\t$(YACCE) $(YFLAGS) $<",
73 	"\t$(EC) $(RFLAGS) -c y.tab.e",
74 	"\trm y.tab.e",
75 	"\tmv y.tab.o $@",
76 
77 	".l.o :",
78 	"\t$(LEX) $(LFLAGS) $<",
79 	"\t$(CC) $(CFLAGS) -c lex.yy.c",
80 	"\trm lex.yy.c",
81 	"\tmv lex.yy.o $@",
82 
83 	".y.c :",
84 	"\t$(YACC) $(YFLAGS) $<",
85 	"\tmv y.tab.c $@",
86 
87 	".l.c :",
88 	"\t$(LEX) $(LFLAGS) $<",
89 	"\tmv lex.yy.c $@",
90 
91 	".yr.r:",
92 	"\t$(YACCR) $(YFLAGS) $<",
93 	"\tmv y.tab.r $@",
94 
95 	".ye.e :",
96 	"\t$(YACCE) $(YFLAGS) $<",
97 	"\tmv y.tab.e $@",
98 
99 #ifdef pwb
100 	".o.L .c.L .t.L:",
101 	"\t$(SCOMP) $(SCFLAGS) $<",
102 
103 	".t.o:",
104 	"\t$(SCOMP) $(SCFLAGS) -c $<",
105 
106 	".t.c:",
107 	"\t$(SCOMP) $(SCFLAGS) -t $<",
108 
109 	".h.z .t.z:",
110 	"\t$(CMDICT) $(CMFLAGS) $<",
111 
112 	".h.x .t.x:",
113 	"\t$(CMDICT) $(CMFLAGS) -c $<",
114 #endif
115 
116 	".s.out .c.out .o.out :",
117 	"\t$(CC) $(CFLAGS) $< $(LOADLIBES) -o $@",
118 
119 	".f.out .F.out .r.out .e.out :",
120 	"\t$(FC) $(EFLAGS) $(RFLAGS) $(FFLAGS) $< $(LOADLIBES) -o $@",
121 	"\t-rm $*.o",
122 
123 	".y.out :",
124 	"\t$(YACC) $(YFLAGS) $<",
125 	"\t$(CC) $(CFLAGS) y.tab.c $(LOADLIBES) -ly -o $@",
126 	"\trm y.tab.c",
127 
128 	".l.out :",
129 	"\t$(LEX) $(LFLAGS) $<",
130 	"\t$(CC) $(CFLAGS) lex.yy.c $(LOADLIBES) -ll -o $@",
131 	"\trm lex.yy.c",
132 
133 	0 };
134 
135 #include "defs"
136 #include <sys/stat.h>
137 
138 
139 
140 TIMETYPE
141 exists(pname)
142 struct nameblock *pname;
143 {
144 struct stat buf;
145 register char *s, *filename;
146 TIMETYPE lookarch();
147 extern char *findfl();
148 
149 filename = pname->namep;
150 
151 for(s = filename ; *s!='\0' && *s!='(' ; ++s)
152 	;
153 
154 if(*s == '(')
155 	return(lookarch(filename));
156 
157 if (stat(filename, &buf) < 0)
158 {
159 	s = findfl(filename);
160 	if(s != (char *)-1)
161 	{
162 		pname->alias = copys(s);
163 		if(stat(pname->alias, &buf) == 0)
164 			return(buf.st_mtime);
165 	}
166 	return(0);
167 }
168 else	return(buf.st_mtime);
169 }
170 
171 
172 TIMETYPE prestime()
173 {
174 TIMETYPE t;
175 time(&t);
176 return(t);
177 }
178 
179 
180 
181 FSTATIC char nbuf[MAXNAMLEN + 1];
182 FSTATIC char *nbufend	= &nbuf[MAXNAMLEN];
183 
184 
185 
186 struct depblock *srchdir(pat, mkchain, nextdbl)
187 register char *pat; /* pattern to be matched in directory */
188 int mkchain;  /* nonzero if results to be remembered */
189 struct depblock *nextdbl;  /* final value for chain */
190 {
191 DIR *dirf;
192 register int i;
193 int nread, cldir;
194 char *dirname, *dirpref, *endir, *filepat, *p, temp[BUFSIZ];
195 char fullname[BUFSIZ], *p1, *p2;
196 struct nameblock *q;
197 struct depblock *thisdbl;
198 struct dirhdr *od;
199 struct pattern *patp;
200 struct varblock *cp, *varptr();
201 char *path, pth[BUFSIZ], *strcpy();
202 struct direct *dptr;
203 
204 
205 thisdbl = 0;
206 
207 if(mkchain == NO)
208 	for(patp=firstpat ; patp ; patp = patp->nxtpattern)
209 		if(! unequal(pat, patp->patval)) return(0);
210 
211 patp = ALLOC(pattern);
212 patp->nxtpattern = firstpat;
213 firstpat = patp;
214 patp->patval = copys(pat);
215 
216 endir = 0;
217 
218 for(p=pat; *p!='\0'; ++p)
219 	if(*p=='/') endir = p;
220 
221 if(endir==0)
222 	{
223 	dirpref = "";
224 	filepat = pat;
225 	cp = varptr("VPATH");
226 	if (cp->varval == NULL) path = ".";
227 	else {
228 	       path = pth;
229 	       *path = '\0';
230 	       if (strncmp(cp->varval, ".:", 2) != 0) strcpy(pth,".:");
231 	       strcat(pth, cp->varval);
232 	       }
233 	}
234 else	{
235 	*endir = '\0';
236 	path = strcpy(pth, pat);
237 	dirpref = concat(pat, "/", temp);
238 	filepat = endir+1;
239 	}
240 
241 while (*path) {			/* Loop thru each VPATH directory */
242   dirname = path;
243   for (; *path; path++)
244     if (*path == ':') {
245       *path++ = '\0';
246       break;
247       }
248 
249 dirf = NULL;
250 cldir = NO;
251 
252 for(od = firstod; od; od = od->nxtopendir)
253 	if(! unequal(dirname, od->dirn) )
254 		{
255 		dirf = od->dirfc;
256 		if (dirf != NULL)
257 			rewinddir(dirf); /* start over at the beginning  */
258 		break;
259 		}
260 
261 if(dirf == NULL)
262 	{
263 	dirf = opendir(dirname);
264 	if(nopdir >= MAXDIR)
265 		cldir = YES;
266 	else	{
267 		++nopdir;
268 		od = ALLOC(dirhdr);
269 		od->nxtopendir = firstod;
270 		firstod = od;
271 		od->dirfc = dirf;
272 		od->dirn = copys(dirname);
273 		fcntl(dirfd(dirf), F_SETFD, 1);
274 		}
275 	}
276 
277 if(dirf == NULL)
278 	{
279 	fprintf(stderr, "Directory %s: ", dirname);
280 	fatal("Cannot open");
281 	}
282 
283 else for (dptr = readdir(dirf); dptr != NULL; dptr = readdir(dirf))
284 	{
285 	p1 = dptr->d_name;
286 	p2 = nbuf;
287 	while( (p2<nbufend) && (*p2++ = *p1++)!='\0' )
288 		/* void */;
289 	if( amatch(nbuf,filepat) )
290 		{
291 		concat(dirpref,nbuf,fullname);
292 		if( (q=srchname(fullname)) ==0)
293 			q = makename(copys(fullname));
294 		if(mkchain)
295 			{
296 			thisdbl = ALLOC(depblock);
297 			thisdbl->nxtdepblock = nextdbl;
298 			thisdbl->depname = q;
299 			nextdbl = thisdbl;
300 			}
301 		}
302 	}
303 
304 if(endir != 0)  *endir = '/';
305 
306 if(cldir) {
307 	closedir(dirf);
308 	dirf = NULL;
309 }
310 } /* End of VPATH loop */
311 return(thisdbl);
312 }
313 
314 /* stolen from glob through find */
315 
316 static amatch(s, p)
317 char *s, *p;
318 {
319 	register int cc, scc, k;
320 	int c, lc;
321 
322 	scc = *s;
323 	lc = 077777;
324 	switch (c = *p) {
325 
326 	case '[':
327 		k = 0;
328 		while (cc = *++p) {
329 			switch (cc) {
330 
331 			case ']':
332 				if (k)
333 					return(amatch(++s, ++p));
334 				else
335 					return(0);
336 
337 			case '-':
338 				k |= (lc <= scc)  & (scc <= (cc=p[1]) ) ;
339 			}
340 			if (scc==(lc=cc)) k++;
341 		}
342 		return(0);
343 
344 	case '?':
345 	caseq:
346 		if(scc) return(amatch(++s, ++p));
347 		return(0);
348 	case '*':
349 		return(umatch(s, ++p));
350 	case 0:
351 		return(!scc);
352 	}
353 	if (c==scc) goto caseq;
354 	return(0);
355 }
356 
357 static umatch(s, p)
358 char *s, *p;
359 {
360 	if(*p==0) return(1);
361 	while(*s)
362 		if (amatch(s++,p)) return(1);
363 	return(0);
364 }
365 
366 #ifdef METERFILE
367 #include <pwd.h>
368 int meteron	= 0;	/* default: metering off */
369 
370 meter(file)
371 char *file;
372 {
373 TIMETYPE tvec;
374 char *p, *ctime();
375 FILE * mout;
376 struct passwd *pwd, *getpwuid();
377 
378 if(file==0 || meteron==0) return;
379 
380 pwd = getpwuid(getuid());
381 
382 time(&tvec);
383 
384 if( (mout=fopen(file,"a")) != NULL )
385 	{
386 	p = ctime(&tvec);
387 	p[16] = '\0';
388 	fprintf(mout,"User %s, %s\n",pwd->pw_name,p+4);
389 	fclose(mout);
390 	}
391 }
392 #endif
393 
394 
395 /* look inside archives for notations a(b) and a((b))
396 	a(b)	is file member   b   in archive a
397 	a((b))	is entry point  _b  in object archive a
398 */
399 
400 #ifdef ASCARCH
401 #	include <ar.h>
402 #else
403 #	include <ar.h>
404 #endif
405 #include <a.out.h>
406 
407 static long arflen;
408 static long arfdate;
409 static char arfname[16];
410 FILE *arfd;
411 long int arpos, arlen;
412 
413 static struct exec objhead;
414 
415 static struct nlist objentry;
416 
417 
418 TIMETYPE lookarch(filename)
419 char *filename;
420 {
421 char *p, *q, *send, s[MAXNAMLEN + 1];
422 int i, nc, nsym, objarch;
423 
424 for(p = filename; *p!= '(' ; ++p)
425 	;
426 *p = '\0';
427 openarch(filename);
428 *p++ = '(';
429 
430 if(*p == '(')
431 	{
432 	objarch = YES;
433 	nc = 8;
434 	++p;
435 	}
436 else
437 	{
438 	objarch = NO;
439 	nc = MAXNAMLEN;
440 	}
441 send = s + nc;
442 
443 for( q = s ; q<send && *p!='\0' && *p!=')' ; *q++ = *p++ )
444 	;
445 while(q < send)
446 	*q++ = '\0';
447 while(getarch())
448 	{
449 	if(objarch)
450 		{
451 		getobj();
452 		nsym = objhead.a_syms / sizeof(objentry);
453 		for(i = 0; i<nsym ; ++i)
454 			{
455 			fread( (char *) &objentry, sizeof(objentry),1,arfd);
456 			if( (objentry.n_type & N_EXT)
457 			   && ((objentry.n_type & ~N_EXT) || objentry.n_value)
458 			   && eqstr(objentry.n_un.n_name,s,nc))
459 				{
460 				clarch();
461 				return(arfdate);
462 				}
463 			}
464 		}
465 
466 	else if( eqstr(arfname, s, nc))
467 		{
468 		clarch();
469 		return(arfdate);
470 		}
471 	}
472 
473 clarch();
474 return( 0L);
475 }
476 
477 
478 clarch()
479 {
480 fclose( arfd );
481 }
482 
483 
484 openarch(f)
485 register char *f;
486 {
487 #ifdef ASCARCH
488 char magic[SARMAG];
489 #endif
490 int word;
491 #include <sys/stat.h>
492 struct stat buf;
493 
494 stat(f, &buf);
495 arlen = buf.st_size;
496 
497 arfd = fopen(f, "r");
498 if(arfd == NULL)
499 	fatal1("cannot open %s", f);
500 
501 	fread( (char *) &word, sizeof(word), 1, arfd);
502 #ifdef ASCARCH
503 	fseek(arfd, 0L, 0);
504 	fread(magic, SARMAG, 1, arfd);
505 	arpos = SARMAG;
506 	if( ! eqstr(magic, ARMAG, SARMAG) )
507 #else
508 	arpos = sizeof(word);
509 	if(word != ARMAG)
510 #endif
511 		fatal1("%s is not an archive", f);
512 
513 arflen = 0;
514 }
515 
516 
517 
518 getarch()
519 {
520 	struct ar_hdr arhead;
521 	long atol();
522 
523 arpos += (arflen + 1) & ~1L;	/* round archived file length up to even */
524 if(arpos >= arlen)
525 	return(0);
526 fseek(arfd, arpos, 0);
527 
528 	fread( (char *) &arhead, sizeof(arhead), 1, arfd);
529 	arpos += sizeof(arhead);
530 #ifdef ASCARCH
531 	arflen = atol(arhead.ar_size);
532 	arfdate = atol(arhead.ar_date);
533 #else
534 	arflen = arhead.ar_size;
535 	arfdate = arhead.ar_date;
536 #endif
537 	strncpy(arfname, arhead.ar_name, sizeof(arhead.ar_name));
538 return(1);
539 }
540 
541 
542 getobj()
543 {
544 long int skip;
545 
546 fread( (char *) &objhead, sizeof(objhead), 1, arfd);
547 if (N_BADMAG(objhead))
548 	fatal1("%s is not an object module", arfname);
549 skip = objhead.a_text + objhead.a_data;
550 #ifndef pdp11
551 skip += objhead.a_trsize + objhead.a_drsize;
552 #else
553 if(! objhead.a_flag )
554 	skip *= 2;
555 #endif
556 fseek(arfd, skip, 1);
557 }
558 
559 
560 eqstr(a,b,n)
561 register char *a, *b;
562 int n;
563 {
564 register int i;
565 for(i = 0 ; i < n ; ++i)
566 	if(*a++ != *b++)
567 		return(NO);
568 return(YES);
569 }
570 
571 
572 /*
573  *	findfl(name)	(like execvp, but does path search and finds files)
574  */
575 static char fname[128];
576 
577 char *execat();
578 
579 char *findfl(name)
580 register char *name;
581 {
582 	register char *p;
583 	register struct varblock *cp;
584 	struct stat buf;
585 
586 	for (p = name; *p; p++)
587 		if(*p == '/') return(name);
588 
589 	cp = varptr("VPATH");
590 	if(cp->varval == NULL || *cp->varval == 0)
591 		p = ":";
592 	else
593 		p = cp->varval;
594 
595 	do
596 	{
597 		p = execat(p, name, fname);
598 		if(stat(fname,&buf) >= 0)
599 			return(fname);
600 	} while (p);
601 	return((char *)-1);
602 }
603 
604 char *execat(s1, s2, si)
605 register char *s1, *s2;
606 char *si;
607 {
608 	register char *s;
609 
610 	s = si;
611 	while (*s1 && *s1 != ':' && *s1 != '-')
612 		*s++ = *s1++;
613 	if (si != s)
614 		*s++ = '/';
615 	while (*s2)
616 		*s++ = *s2++;
617 	*s = '\0';
618 	return(*s1? ++s1: 0);
619 }
620 
621 
622 /* copy s to d, changing file names to file aliases */
623 fixname(s, d)
624 char *s, *d;
625 {
626 	register char *r, *q;
627 	struct nameblock *pn;
628 	char name[BUFSIZ];
629 
630 	while (*s) {
631 		if (isspace(*s)) *d++ = *s++;
632 		else {
633 			r = name;
634 			while (*s) {
635 				if (isspace(*s)) break;
636 				*r++ = *s++;
637 				}
638 			*r = '\0';
639 
640 			if (((pn = srchname(name)) != 0) && (pn->alias))
641 				q = pn->alias;
642 			else q = name;
643 
644 			while (*q) *d++ = *q++;
645 			}
646 		}
647 	*d = '\0';
648 }
649