xref: /original-bsd/old/make/main.c (revision dbb87b25)
1 static	char *sccsid = "@(#)main.c	4.12 (Berkeley) 91/02/28";
2 # include "defs"
3 /*
4 command make to update programs.
5 Flags:	'd'  print out debugging comments
6 	'p'  print out a version of the input graph
7 	's'  silent mode--don't print out commands
8 	'f'  the next argument is the name of the description file;
9 	     "makefile" is the default
10 	'i'  ignore error codes from the shell
11 	'S'  stop after any command fails (normally do parallel work)
12 	'n'   don't issue, just print, commands
13 	't'   touch (update time of) files but don't issue command
14 	'q'   don't do anything, but check if object is up to date;
15 	      returns exit code 0 if up to date, -1 if not
16 	'e'  environment variables have precedence over makefiles
17 */
18 
19 struct nameblock *mainname	= NULL;
20 struct nameblock *firstname	= NULL;
21 struct lineblock *sufflist	= NULL;
22 struct varblock *firstvar	= NULL;
23 struct pattern *firstpat	= NULL;
24 struct dirhdr *firstod		= NULL;
25 
26 #include <signal.h>
27 int sigivalue	= 0;
28 int sigqvalue	= 0;
29 int waitpid	= 0;
30 
31 int dbgflag	= NO;
32 int prtrflag	= NO;
33 int silflag	= NO;
34 int noexflag	= NO;
35 int keepgoing	= NO;
36 int noruleflag	= NO;
37 int touchflag	= NO;
38 int questflag	= NO;
39 int ndocoms	= NO;
40 int ignerr	= NO;    /* default is to stop on error */
41 int okdel	= YES;
42 int doenvlast	= NO;
43 int inarglist;
44 #ifdef pwb
45 char *prompt	= ">";	/* other systems -- pick what you want */
46 #else
47 char *prompt	= "";	/* other systems -- pick what you want */
48 #endif
49 int nopdir	= 0;
50 char junkname[20];
51 char funny[128];
52 char	options[26 + 1] = { '-' };
53 
main(argc,argv)54 main(argc,argv)
55 int argc;
56 char *argv[];
57 {
58 register struct nameblock *p;
59 int i, j;
60 int descset, nfargs;
61 TIMETYPE tjunk;
62 char c, *s;
63 static char onechar[2] = "X";
64 #ifdef unix
65 void intrupt();
66 #endif
67 char *op = options + 1;
68 
69 
70 #ifdef METERFILE
71 meter(METERFILE);
72 #endif
73 
74 descset = 0;
75 
76 funny['\0'] = (META | TERMINAL);
77 for(s = "=|^();&<>*?[]:$`'\"\\\n" ; *s ; ++s)
78 	funny[*s] |= META;
79 for(s = "\n\t :;&>|" ; *s ; ++s)
80 	funny[*s] |= TERMINAL;
81 
82 
83 inarglist = 1;
84 for(i=1; i<argc; ++i)
85 	if(argv[i]!=0 && argv[i][0]!='-' && eqsign(argv[i]))
86 		argv[i] = 0;
87 
88 setvar("$","$");
89 inarglist = 0;
90 
91 for (i=1; i<argc; ++i)
92 	if (argv[i]!=0 && argv[i][0]=='-') {
93 		for (j=1 ; (c=argv[i][j])!='\0' ; ++j) {
94 			*op++ = c;
95 			switch (c) {
96 
97 			case 'd':
98 				dbgflag = YES;
99 				break;
100 
101 			case 'p':
102 				prtrflag = YES;
103 				break;
104 
105 			case 's':
106 				silflag = YES;
107 				break;
108 
109 			case 'i':
110 				ignerr = YES;
111 				break;
112 
113 			case 'S':
114 				keepgoing = NO;
115 				break;
116 
117 			case 'k':
118 				keepgoing = YES;
119 				break;
120 
121 			case 'n':
122 				noexflag = YES;
123 				break;
124 
125 			case 'r':
126 				noruleflag = YES;
127 				break;
128 
129 			case 't':
130 				touchflag = YES;
131 				break;
132 
133 			case 'q':
134 				questflag = YES;
135 				break;
136 
137 			case 'f':
138 				op--;		/* don't pass this one */
139 				if(i >= argc-1)
140 				  fatal("No description argument after -f flag");
141 				if( rddescf(argv[i+1]) )
142 				fatal1("Cannot open %s", argv[i+1]);
143 				argv[i+1] = 0;
144 				++descset;
145 				break;
146 
147 			case 'e':
148 				doenvlast = YES;
149 				break;
150 
151 			default:
152 				onechar[0] = c;	/* to make lint happy */
153 				fatal1("Unknown flag argument %s", onechar);
154 			}
155 		}
156 		argv[i] = 0;
157 	}
158 
159 *op++ = '\0';
160 if (strcmp(options, "-") == 0)
161 	*options = '\0';
162 setvar("MFLAGS", options);		/* MFLAGS=options to make */
163 
164 setvar("MACHINE", MACHINE);
165 
166 if (!descset) {
167 	if (rddescf("makefile"))
168 		rddescf("Makefile");
169 	rddescf(".depend");
170 }
171 
172 if (doenvlast == YES)
173 	readenv();
174 
175 if(prtrflag) printdesc(NO);
176 
177 if( srchname(".IGNORE") ) ++ignerr;
178 if( srchname(".SILENT") ) silflag = 1;
179 if(p=srchname(".SUFFIXES")) sufflist = p->linep;
180 if( !sufflist ) fprintf(stderr,"No suffix list.\n");
181 
182 #ifdef unix
183 sigivalue = (int) signal(SIGINT, SIG_IGN) & 01;
184 sigqvalue = (int) signal(SIGQUIT, SIG_IGN) & 01;
185 enbint(intrupt);
186 #endif
187 
188 nfargs = 0;
189 
190 for(i=1; i<argc; ++i)
191 	if((s=argv[i]) != 0)
192 		{
193 		if((p=srchname(s)) == 0)
194 			{
195 			p = makename(s);
196 			}
197 		++nfargs;
198 		doname(p, 0, &tjunk);
199 		if(dbgflag) printdesc(YES);
200 		}
201 
202 /*
203 If no file arguments have been encountered, make the first
204 name encountered that doesn't start with a dot
205 */
206 
207 if(nfargs == 0)
208 	if(mainname == 0)
209 		fatal("No arguments or description file");
210 	else	{
211 		doname(mainname, 0, &tjunk);
212 		if(dbgflag) printdesc(YES);
213 		}
214 
215 exit(0);
216 }
217 
218 #include <sys/stat.h>
219 
220 #ifdef unix
221 void
intrupt()222 intrupt()
223 {
224 struct varblock *varptr();
225 char *p;
226 TIMETYPE exists();
227 struct stat sbuf;
228 
229 if(okdel && !noexflag && !touchflag &&
230 	(p = varptr("@")->varval) &&
231 	(stat(p, &sbuf) >= 0 && (sbuf.st_mode&S_IFMT) == S_IFREG) &&
232 	!isprecious(p) )
233 		{
234 		fprintf(stderr, "\n***  %s removed.", p);
235 		unlink(p);
236 		}
237 
238 if(junkname[0])
239 	unlink(junkname);
240 fprintf(stderr, "\n");
241 exit(2);
242 }
243 
244 
245 
246 
isprecious(p)247 isprecious(p)
248 char *p;
249 {
250 register struct lineblock *lp;
251 register struct depblock *dp;
252 register struct nameblock *np;
253 
254 if(np = srchname(".PRECIOUS"))
255 	for(lp = np->linep ; lp ; lp = lp->nxtlineblock)
256 		for(dp = lp->depp ; dp ; dp = dp->nxtdepblock)
257 			if(! unequal(p, dp->depname->namep))
258 				return(YES);
259 
260 return(NO);
261 }
262 
263 
264 enbint(k)
265 void (*k)();
266 {
267 if(sigivalue == 0)
268 	signal(SIGINT,k);
269 if(sigqvalue == 0)
270 	signal(SIGQUIT,k);
271 }
272 #endif
273 
274 extern char *builtin[];
275 
276 char **linesptr	= builtin;
277 
278 FILE * fin;
279 int firstrd	= 0;
280 
281 
rddescf(descfile)282 rddescf(descfile)
283 char *descfile;
284 {
285 FILE * k;
286 
287 /* read and parse description */
288 
289 if( !firstrd++ )
290 	{
291 	if( !noruleflag )
292 		rdd1( (FILE *) NULL);
293 
294 	if (doenvlast == NO)
295 		readenv();
296 
297 #ifdef pwb
298 		{
299 		char *nlog, s[BUFSIZ];
300 		nlog = logdir();
301 		if ( (k=fopen( concat(nlog,"/makecomm",s), "r")) != NULL)
302 			rdd1(k);
303 		else if ( (k=fopen( concat(nlog,"/Makecomm",s), "r")) != NULL)
304 			rdd1(k);
305 
306 		if ( (k=fopen("makecomm", "r")) != NULL)
307 			rdd1(k);
308 		else if ( (k=fopen("Makecomm", "r")) != NULL)
309 			rdd1(k);
310 		}
311 #endif
312 
313 	}
314 if(! unequal(descfile, "-"))
315 	return( rdd1(stdin) );
316 
317 if( (k = fopen(descfile,"r")) != NULL)
318 	return( rdd1(k) );
319 
320 return(1);
321 }
322 
323 
324 
325 
rdd1(k)326 rdd1(k)
327 FILE * k;
328 {
329 extern int yylineno;
330 extern char *zznextc;
331 
332 fin = k;
333 yylineno = 0;
334 zznextc = 0;
335 
336 if( yyparse() )
337 	fatal("Description file error");
338 
339 if(fin != NULL && fin != stdin)
340 	fclose(fin);
341 
342 return(0);
343 }
344 
printdesc(prntflag)345 printdesc(prntflag)
346 int prntflag;
347 {
348 struct nameblock *p;
349 struct depblock *dp;
350 struct varblock *vp;
351 struct dirhdr *od;
352 struct shblock *sp;
353 struct lineblock *lp;
354 
355 #ifdef unix
356 if(prntflag)
357 	{
358 	printf("Open directories:\n");
359 	for (od = firstod; od; od = od->nxtopendir)
360 		printf("\t%d: %s\n", dirfd(od->dirfc), od->dirn);
361 	}
362 #endif
363 
364 if(firstvar != 0) printf("Macros:\n");
365 for(vp = firstvar; vp ; vp = vp->nxtvarblock)
366 	printf("\t%s = %s\n" , vp->varname , vp->varval);
367 
368 for(p = firstname; p; p = p->nxtnameblock)
369 	{
370 	printf("\n\n%s",p->namep);
371 	if(p->linep != 0) printf(":");
372 	if(prntflag) printf("  done=%d",p->done);
373 	if(p==mainname) printf("  (MAIN NAME)");
374 	for(lp = p->linep ; lp ; lp = lp->nxtlineblock)
375 		{
376 		if( dp = lp->depp )
377 			{
378 			printf("\n depends on:");
379 			for(; dp ; dp = dp->nxtdepblock)
380 				if(dp->depname != 0)
381 					printf(" %s ", dp->depname->namep);
382 			}
383 
384 		if(sp = lp->shp)
385 			{
386 			printf("\n commands:\n");
387 			for( ; sp!=0 ; sp = sp->nxtshblock)
388 				printf("\t%s\n", sp->shbp);
389 			}
390 		}
391 	}
392 printf("\n");
393 fflush(stdout);
394 }
395 
readenv()396 readenv()
397 {
398 	register char **ep, *p;
399 	extern char **environ;
400 
401 	for(ep = environ ; *ep ; ++ep) {
402 		for (p = *ep; *p; p++) {
403 			if (isalnum(*p))
404 				continue;
405 			if (*p == '=') {
406 				eqsign(*ep);
407 			}
408 			break;
409 		}
410 	}
411 }
412