main.c 7.5 KB

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