xref: /csrg-svn/old/make/main.c (revision 32620)
1 static	char *sccsid = "@(#)main.c	4.10 (Berkeley) 87/11/15";
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 #ifdef unix
168 	if( rddescf("makefile") )  rddescf("Makefile");
169 #endif
170 #ifdef gcos
171 	rddescf("makefile");
172 #endif
173 
174 if (doenvlast == YES)
175 	readenv();
176 
177 if(prtrflag) printdesc(NO);
178 
179 if( srchname(".IGNORE") ) ++ignerr;
180 if( srchname(".SILENT") ) silflag = 1;
181 if(p=srchname(".SUFFIXES")) sufflist = p->linep;
182 if( !sufflist ) fprintf(stderr,"No suffix list.\n");
183 
184 #ifdef unix
185 sigivalue = (int) signal(SIGINT, SIG_IGN) & 01;
186 sigqvalue = (int) signal(SIGQUIT, SIG_IGN) & 01;
187 enbint(intrupt);
188 #endif
189 
190 nfargs = 0;
191 
192 for(i=1; i<argc; ++i)
193 	if((s=argv[i]) != 0)
194 		{
195 		if((p=srchname(s)) == 0)
196 			{
197 			p = makename(s);
198 			}
199 		++nfargs;
200 		doname(p, 0, &tjunk);
201 		if(dbgflag) printdesc(YES);
202 		}
203 
204 /*
205 If no file arguments have been encountered, make the first
206 name encountered that doesn't start with a dot
207 */
208 
209 if(nfargs == 0)
210 	if(mainname == 0)
211 		fatal("No arguments or description file");
212 	else	{
213 		doname(mainname, 0, &tjunk);
214 		if(dbgflag) printdesc(YES);
215 		}
216 
217 exit(0);
218 }
219 
220 #include <sys/stat.h>
221 
222 #ifdef unix
223 intrupt()
224 {
225 struct varblock *varptr();
226 char *p;
227 TIMETYPE exists();
228 struct stat sbuf;
229 
230 if(okdel && !noexflag && !touchflag &&
231 	(p = varptr("@")->varval) &&
232 	(stat(p, &sbuf) >= 0 && (sbuf.st_mode&S_IFMT) == S_IFREG) &&
233 	!isprecious(p) )
234 		{
235 		fprintf(stderr, "\n***  %s removed.", p);
236 		unlink(p);
237 		}
238 
239 if(junkname[0])
240 	unlink(junkname);
241 fprintf(stderr, "\n");
242 exit(2);
243 }
244 
245 
246 
247 
248 isprecious(p)
249 char *p;
250 {
251 register struct lineblock *lp;
252 register struct depblock *dp;
253 register struct nameblock *np;
254 
255 if(np = srchname(".PRECIOUS"))
256 	for(lp = np->linep ; lp ; lp = lp->nxtlineblock)
257 		for(dp = lp->depp ; dp ; dp = dp->nxtdepblock)
258 			if(! unequal(p, dp->depname->namep))
259 				return(YES);
260 
261 return(NO);
262 }
263 
264 
265 enbint(k)
266 int (*k)();
267 {
268 if(sigivalue == 0)
269 	signal(SIGINT,k);
270 if(sigqvalue == 0)
271 	signal(SIGQUIT,k);
272 }
273 #endif
274 
275 extern char *builtin[];
276 
277 char **linesptr	= builtin;
278 
279 FILE * fin;
280 int firstrd	= 0;
281 
282 
283 rddescf(descfile)
284 char *descfile;
285 {
286 FILE * k;
287 
288 /* read and parse description */
289 
290 if( !firstrd++ )
291 	{
292 	if( !noruleflag )
293 		rdd1( (FILE *) NULL);
294 
295 	if (doenvlast == NO)
296 		readenv();
297 
298 #ifdef pwb
299 		{
300 		char *nlog, s[BUFSIZ];
301 		nlog = logdir();
302 		if ( (k=fopen( concat(nlog,"/makecomm",s), "r")) != NULL)
303 			rdd1(k);
304 		else if ( (k=fopen( concat(nlog,"/Makecomm",s), "r")) != NULL)
305 			rdd1(k);
306 
307 		if ( (k=fopen("makecomm", "r")) != NULL)
308 			rdd1(k);
309 		else if ( (k=fopen("Makecomm", "r")) != NULL)
310 			rdd1(k);
311 		}
312 #endif
313 
314 	}
315 if(! unequal(descfile, "-"))
316 	return( rdd1(stdin) );
317 
318 if( (k = fopen(descfile,"r")) != NULL)
319 	return( rdd1(k) );
320 
321 return(1);
322 }
323 
324 
325 
326 
327 rdd1(k)
328 FILE * k;
329 {
330 extern int yylineno;
331 extern char *zznextc;
332 
333 fin = k;
334 yylineno = 0;
335 zznextc = 0;
336 
337 if( yyparse() )
338 	fatal("Description file error");
339 
340 if(fin != NULL && fin != stdin)
341 	fclose(fin);
342 
343 return(0);
344 }
345 
346 printdesc(prntflag)
347 int prntflag;
348 {
349 struct nameblock *p;
350 struct depblock *dp;
351 struct varblock *vp;
352 struct dirhdr *od;
353 struct shblock *sp;
354 struct lineblock *lp;
355 
356 #ifdef unix
357 if(prntflag)
358 	{
359 	printf("Open directories:\n");
360 	for (od = firstod; od; od = od->nxtopendir)
361 		printf("\t%d: %s\n", dirfd(od->dirfc), od->dirn);
362 	}
363 #endif
364 
365 if(firstvar != 0) printf("Macros:\n");
366 for(vp = firstvar; vp ; vp = vp->nxtvarblock)
367 	printf("\t%s = %s\n" , vp->varname , vp->varval);
368 
369 for(p = firstname; p; p = p->nxtnameblock)
370 	{
371 	printf("\n\n%s",p->namep);
372 	if(p->linep != 0) printf(":");
373 	if(prntflag) printf("  done=%d",p->done);
374 	if(p==mainname) printf("  (MAIN NAME)");
375 	for(lp = p->linep ; lp ; lp = lp->nxtlineblock)
376 		{
377 		if( dp = lp->depp )
378 			{
379 			printf("\n depends on:");
380 			for(; dp ; dp = dp->nxtdepblock)
381 				if(dp->depname != 0)
382 					printf(" %s ", dp->depname->namep);
383 			}
384 
385 		if(sp = lp->shp)
386 			{
387 			printf("\n commands:\n");
388 			for( ; sp!=0 ; sp = sp->nxtshblock)
389 				printf("\t%s\n", sp->shbp);
390 			}
391 		}
392 	}
393 printf("\n");
394 fflush(stdout);
395 }
396 
397 readenv()
398 {
399 	register char **ep, *p;
400 	extern char **environ;
401 
402 	for(ep = environ ; *ep ; ++ep) {
403 		for (p = *ep; *p; p++) {
404 			if (isalnum(*p))
405 				continue;
406 			if (*p == '=') {
407 				eqsign(*ep);
408 			}
409 			break;
410 		}
411 	}
412 }
413