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