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