xref: /original-bsd/old/make/main.c (revision 2301fdfb)
1 static	char *sccsid = "@(#)main.c	4.11 (Berkeley) 88/09/13";
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 
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 int 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 intrupt()
222 {
223 struct varblock *varptr();
224 char *p;
225 TIMETYPE exists();
226 struct stat sbuf;
227 
228 if(okdel && !noexflag && !touchflag &&
229 	(p = varptr("@")->varval) &&
230 	(stat(p, &sbuf) >= 0 && (sbuf.st_mode&S_IFMT) == S_IFREG) &&
231 	!isprecious(p) )
232 		{
233 		fprintf(stderr, "\n***  %s removed.", p);
234 		unlink(p);
235 		}
236 
237 if(junkname[0])
238 	unlink(junkname);
239 fprintf(stderr, "\n");
240 exit(2);
241 }
242 
243 
244 
245 
246 isprecious(p)
247 char *p;
248 {
249 register struct lineblock *lp;
250 register struct depblock *dp;
251 register struct nameblock *np;
252 
253 if(np = srchname(".PRECIOUS"))
254 	for(lp = np->linep ; lp ; lp = lp->nxtlineblock)
255 		for(dp = lp->depp ; dp ; dp = dp->nxtdepblock)
256 			if(! unequal(p, dp->depname->namep))
257 				return(YES);
258 
259 return(NO);
260 }
261 
262 
263 enbint(k)
264 int (*k)();
265 {
266 if(sigivalue == 0)
267 	signal(SIGINT,k);
268 if(sigqvalue == 0)
269 	signal(SIGQUIT,k);
270 }
271 #endif
272 
273 extern char *builtin[];
274 
275 char **linesptr	= builtin;
276 
277 FILE * fin;
278 int firstrd	= 0;
279 
280 
281 rddescf(descfile)
282 char *descfile;
283 {
284 FILE * k;
285 
286 /* read and parse description */
287 
288 if( !firstrd++ )
289 	{
290 	if( !noruleflag )
291 		rdd1( (FILE *) NULL);
292 
293 	if (doenvlast == NO)
294 		readenv();
295 
296 #ifdef pwb
297 		{
298 		char *nlog, s[BUFSIZ];
299 		nlog = logdir();
300 		if ( (k=fopen( concat(nlog,"/makecomm",s), "r")) != NULL)
301 			rdd1(k);
302 		else if ( (k=fopen( concat(nlog,"/Makecomm",s), "r")) != NULL)
303 			rdd1(k);
304 
305 		if ( (k=fopen("makecomm", "r")) != NULL)
306 			rdd1(k);
307 		else if ( (k=fopen("Makecomm", "r")) != NULL)
308 			rdd1(k);
309 		}
310 #endif
311 
312 	}
313 if(! unequal(descfile, "-"))
314 	return( rdd1(stdin) );
315 
316 if( (k = fopen(descfile,"r")) != NULL)
317 	return( rdd1(k) );
318 
319 return(1);
320 }
321 
322 
323 
324 
325 rdd1(k)
326 FILE * k;
327 {
328 extern int yylineno;
329 extern char *zznextc;
330 
331 fin = k;
332 yylineno = 0;
333 zznextc = 0;
334 
335 if( yyparse() )
336 	fatal("Description file error");
337 
338 if(fin != NULL && fin != stdin)
339 	fclose(fin);
340 
341 return(0);
342 }
343 
344 printdesc(prntflag)
345 int prntflag;
346 {
347 struct nameblock *p;
348 struct depblock *dp;
349 struct varblock *vp;
350 struct dirhdr *od;
351 struct shblock *sp;
352 struct lineblock *lp;
353 
354 #ifdef unix
355 if(prntflag)
356 	{
357 	printf("Open directories:\n");
358 	for (od = firstod; od; od = od->nxtopendir)
359 		printf("\t%d: %s\n", dirfd(od->dirfc), od->dirn);
360 	}
361 #endif
362 
363 if(firstvar != 0) printf("Macros:\n");
364 for(vp = firstvar; vp ; vp = vp->nxtvarblock)
365 	printf("\t%s = %s\n" , vp->varname , vp->varval);
366 
367 for(p = firstname; p; p = p->nxtnameblock)
368 	{
369 	printf("\n\n%s",p->namep);
370 	if(p->linep != 0) printf(":");
371 	if(prntflag) printf("  done=%d",p->done);
372 	if(p==mainname) printf("  (MAIN NAME)");
373 	for(lp = p->linep ; lp ; lp = lp->nxtlineblock)
374 		{
375 		if( dp = lp->depp )
376 			{
377 			printf("\n depends on:");
378 			for(; dp ; dp = dp->nxtdepblock)
379 				if(dp->depname != 0)
380 					printf(" %s ", dp->depname->namep);
381 			}
382 
383 		if(sp = lp->shp)
384 			{
385 			printf("\n commands:\n");
386 			for( ; sp!=0 ; sp = sp->nxtshblock)
387 				printf("\t%s\n", sp->shbp);
388 			}
389 		}
390 	}
391 printf("\n");
392 fflush(stdout);
393 }
394 
395 readenv()
396 {
397 	register char **ep, *p;
398 	extern char **environ;
399 
400 	for(ep = environ ; *ep ; ++ep) {
401 		for (p = *ep; *p; p++) {
402 			if (isalnum(*p))
403 				continue;
404 			if (*p == '=') {
405 				eqsign(*ep);
406 			}
407 			break;
408 		}
409 	}
410 }
411