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