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