]> git.lizzy.rs Git - plan9front.git/blob - sys/src/ape/cmd/make/main.c
libc: use Runemax instead of hardcoded 0x65536 for fmtchar check (thanks qrstuv)
[plan9front.git] / sys / src / ape / cmd / make / main.c
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
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
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
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
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
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
362 rdarray(char **s)
363 {
364 linesptr = s;
365 parse(CHNULL);
366 }
367
368 static void
369 loadenv(void)
370 {
371 for(envpp = environ ; *envpp ; ++envpp)
372         eqsign(*envpp);
373 envpp = NULL;
374 }
375 \f
376 static void
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 }