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