make.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  1. /*
  2. * Do the actual making for make
  3. *
  4. * $Header$
  5. */
  6. #include <stdio.h>
  7. #ifdef unix
  8. #include <sys/types.h>
  9. #include <sys/stat.h>
  10. #include <errno.h>
  11. #endif
  12. #ifdef eon
  13. #include <sys/stat.h>
  14. #include <sys/err.h>
  15. #endif
  16. #ifdef os9
  17. #include <time.h>
  18. #include <os9.h>
  19. #include <modes.h>
  20. #include <direct.h>
  21. #include <errno.h>
  22. #endif
  23. #include "h.h"
  24. /*
  25. * Exec a shell that returns exit status correctly (/bin/esh).
  26. * The standard EON shell returns the process number of the last
  27. * async command, used by the debugger (ugg).
  28. * [exec on eon is like a fork+exec on unix]
  29. */
  30. int
  31. dosh(string, shell)
  32. char * string;
  33. char * shell;
  34. {
  35. int number;
  36. #ifdef unix
  37. return system(string);
  38. #endif
  39. #ifdef eon
  40. return ((number = execl(shell, shell,"-c", string, 0)) == -1) ?
  41. -1: /* couldn't start the shell */
  42. wait(number); /* return its exit status */
  43. #endif
  44. #ifdef os9
  45. int status, pid;
  46. strcat(string, "\n");
  47. if ((number = os9fork(shell, strlen(string), string, 0, 0, 0)) == -1)
  48. return -1; /* Couldn't start a shell */
  49. do
  50. {
  51. if ((pid = wait(&status)) == -1)
  52. return -1; /* child already died!?!? */
  53. } while (pid != number);
  54. return status;
  55. #endif
  56. }
  57. /*
  58. * Do commands to make a target
  59. */
  60. void
  61. docmds1(np, lp)
  62. struct name * np;
  63. struct line * lp;
  64. {
  65. bool ssilent;
  66. bool signore;
  67. int estat;
  68. register char * q;
  69. register char * p;
  70. char * shell;
  71. register struct cmd * cp;
  72. if (*(shell = getmacro("SHELL")) == '\0')
  73. #ifdef eon
  74. shell = ":bin/esh";
  75. #endif
  76. #ifdef unix
  77. shell = "/bin/sh";
  78. #endif
  79. #ifdef os9
  80. shell = "shell";
  81. #endif
  82. for (cp = lp->l_cmd; cp; cp = cp->c_next)
  83. {
  84. strcpy(str1, cp->c_cmd);
  85. expand(str1);
  86. q = str1;
  87. ssilent = silent;
  88. signore = ignore;
  89. while ((*q == '@') || (*q == '-'))
  90. {
  91. if (*q == '@') /* Specific silent */
  92. ssilent = TRUE;
  93. else /* Specific ignore */
  94. signore = TRUE;
  95. q++; /* Not part of the command */
  96. }
  97. if (!domake)
  98. ssilent = 0;
  99. if (!ssilent)
  100. fputs(" ", stdout);
  101. for (p=q; *p; p++)
  102. {
  103. if (*p == '\n' && p[1] != '\0')
  104. {
  105. *p = ' ';
  106. if (!ssilent)
  107. fputs("\\\n", stdout);
  108. }
  109. else if (!ssilent)
  110. putchar(*p);
  111. }
  112. if (!ssilent) {
  113. putchar('\n');
  114. fflush(stdout);
  115. }
  116. if (domake)
  117. { /* Get the shell to execute it */
  118. if ((estat = dosh(q, shell)) != 0)
  119. {
  120. if (estat == -1)
  121. fatal("Couldn't execute %s", shell);
  122. else
  123. {
  124. printf("%s: Error code %d", myname, estat);
  125. if (signore)
  126. fputs(" (Ignored)\n", stdout);
  127. else
  128. {
  129. putchar('\n');
  130. if (!(np->n_flag & N_PREC))
  131. if (unlink(np->n_name) == 0)
  132. printf("%s: '%s' removed.\n", myname, np->n_name);
  133. exit(1);
  134. }
  135. }
  136. fflush(stdout);
  137. }
  138. }
  139. }
  140. }
  141. docmds(np)
  142. struct name * np;
  143. {
  144. register struct line * lp;
  145. for (lp = np->n_line; lp; lp = lp->l_next)
  146. docmds1(np, lp);
  147. }
  148. #ifdef os9
  149. /*
  150. * Some stuffing around to get the modified time of a file
  151. * in an os9 file system
  152. */
  153. getmdate(fd, tbp)
  154. struct sgtbuf * tbp;
  155. {
  156. struct registers regs;
  157. static struct fildes fdbuf;
  158. regs.rg_a = fd;
  159. regs.rg_b = SS_FD;
  160. regs.rg_x = &fdbuf;
  161. regs.rg_y = sizeof (fdbuf);
  162. if (_os9(I_GETSTT, &regs) == -1)
  163. {
  164. errno = regs.rg_b & 0xff;
  165. return -1;
  166. }
  167. if (tbp)
  168. {
  169. _strass(tbp, fdbuf.fd_date, sizeof (fdbuf.fd_date));
  170. tbp->t_second = 0; /* Files are only acurate to mins */
  171. }
  172. return 0;
  173. }
  174. /*
  175. * Kludge routine to return an aproximation of how many
  176. * seconds since 1980. Dates will be in order, but will not
  177. * be lineer
  178. */
  179. time_t
  180. cnvtime(tbp)
  181. struct sgtbuf *tbp;
  182. {
  183. long acc;
  184. acc = tbp->t_year - 80; /* Baseyear is 1980 */
  185. acc = acc * 12 + tbp->t_month;
  186. acc = acc * 31 + tbp->t_day;
  187. acc = acc * 24 + tbp->t_hour;
  188. acc = acc * 60 + tbp->t_minute;
  189. acc = acc * 60 + tbp->t_second;
  190. return acc;
  191. }
  192. /*
  193. * Get the current time in the internal format
  194. */
  195. time(tp)
  196. time_t * tp;
  197. {
  198. struct sgtbuf tbuf;
  199. if (getime(&tbuf) < 0)
  200. return -1;
  201. if (tp)
  202. *tp = cnvtime(&tbuf);
  203. return 0;
  204. }
  205. #endif
  206. /*
  207. * Get the modification time of a file. If the first
  208. * doesn't exist, it's modtime is set to 0.
  209. */
  210. void
  211. modtime(np)
  212. struct name * np;
  213. {
  214. #ifdef unix
  215. struct stat info;
  216. if (stat(np->n_name, &info) < 0)
  217. {
  218. if (errno != ENOENT)
  219. fatal("Can't open %s; error %d", np->n_name, errno);
  220. np->n_time = 0L;
  221. }
  222. else
  223. np->n_time = info.st_mtime;
  224. #endif
  225. #ifdef eon
  226. struct stat info;
  227. int fd;
  228. if ((fd = open(np->n_name, 0)) < 0)
  229. {
  230. if (errno != ER_NOTF)
  231. fatal("Can't open %s; error %02x", np->n_name, errno);
  232. np->n_time = 0L;
  233. }
  234. else if (getstat(fd, &info) < 0)
  235. fatal("Can't getstat %s; error %02x", np->n_name, errno);
  236. else
  237. np->n_time = info.st_mod;
  238. close(fd);
  239. #endif
  240. #ifdef os9
  241. struct sgtbuf info;
  242. int fd;
  243. if ((fd = open(np->n_name, 0)) < 0)
  244. {
  245. if (errno != E_PNNF)
  246. fatal("Can't open %s; error %02x", np->n_name, errno);
  247. np->n_time = 0L;
  248. }
  249. else if (getmdate(fd, &info) < 0)
  250. fatal("Can't getstat %s; error %02x", np->n_name, errno);
  251. else
  252. np->n_time = cnvtime(&info);
  253. close(fd);
  254. #endif
  255. }
  256. /*
  257. * Update the mod time of a file to now.
  258. */
  259. void
  260. touch(np)
  261. struct name * np;
  262. {
  263. char c;
  264. int fd;
  265. if (!domake || !silent)
  266. printf(" touch(%s)\n", np->n_name);
  267. if (domake)
  268. {
  269. #ifdef unix
  270. long a[2];
  271. long time();
  272. a[0] = a[1] = time((long *)0);
  273. if (utime(np->n_name, &a[0]) < 0)
  274. printf("%s: '%s' not touched - non-existant\n",
  275. myname, np->n_name);
  276. #endif
  277. #ifdef eon
  278. if ((fd = open(np->n_name, 0)) < 0)
  279. printf("%s: '%s' not touched - non-existant\n",
  280. myname, np->n_name);
  281. else
  282. {
  283. uread(fd, &c, 1, 0);
  284. uwrite(fd, &c, 1);
  285. }
  286. close(fd);
  287. #endif
  288. #ifdef os9
  289. /*
  290. * Strange that something almost as totally useless
  291. * as this is easy to do in os9!
  292. */
  293. if ((fd = open(np->n_name, S_IWRITE)) < 0)
  294. printf("%s: '%s' not touched - non-existant\n",
  295. myname, np->n_name);
  296. close(fd);
  297. #endif
  298. }
  299. }
  300. /*
  301. * Recursive routine to make a target.
  302. */
  303. int
  304. make(np, level)
  305. struct name * np;
  306. int level;
  307. {
  308. register struct depend * dp;
  309. register struct line * lp;
  310. register struct depend * qdp;
  311. time_t dtime = 1;
  312. bool didsomething = 0;
  313. int dynamic = 0;
  314. if (np->n_flag & N_DONE)
  315. return 0;
  316. if (!np->n_time)
  317. modtime(np); /* Gets modtime of this file */
  318. if (rules)
  319. {
  320. for (lp = np->n_line; lp; lp = lp->l_next)
  321. if (lp->l_cmd)
  322. break;
  323. if (!lp) {
  324. dyndep(np);
  325. dynamic = 1;
  326. }
  327. }
  328. if (!(np->n_flag & N_TARG) && np->n_time == 0L)
  329. fatal("Don't know how to make %s", np->n_name);
  330. for (qdp = (struct depend *)0, lp = np->n_line; lp; lp = lp->l_next)
  331. {
  332. for (dp = lp->l_dep; dp; dp = dp->d_next)
  333. {
  334. char *sv = 0;
  335. if (dynamic) {
  336. char *s = getmacro("<");
  337. if (s) {
  338. sv = malloc((unsigned)(strlen(s)+1));
  339. if (!sv) {
  340. fatal("no space for saved $<");
  341. }
  342. strcpy(sv, s);
  343. }
  344. }
  345. make(dp->d_name, level+1);
  346. if (dynamic && sv) {
  347. setmacro("<", sv, 4);
  348. free(sv);
  349. }
  350. if (np->n_time < dp->d_name->n_time)
  351. qdp = newdep(dp->d_name, qdp);
  352. dtime = max(dtime, dp->d_name->n_time);
  353. }
  354. if (!quest && (np->n_flag & N_DOUBLE) && (np->n_time < dtime))
  355. {
  356. make1(np, lp, qdp); /* free()'s qdp */
  357. dtime = 1;
  358. qdp = (struct depend *)0;
  359. didsomething++;
  360. }
  361. }
  362. np->n_flag |= N_DONE;
  363. if (quest)
  364. {
  365. long t;
  366. t = np->n_time;
  367. time(&np->n_time);
  368. return t < dtime;
  369. }
  370. else if (np->n_time < dtime && !(np->n_flag & N_DOUBLE))
  371. {
  372. make1(np, (struct line *)0, qdp); /* free()'s qdp */
  373. time(&np->n_time);
  374. }
  375. else if (level == 0 && !didsomething)
  376. printf("%s: '%s' is up to date\n", myname, np->n_name);
  377. return 0;
  378. }
  379. make1(np, lp, qdp)
  380. register struct depend * qdp;
  381. struct line * lp;
  382. struct name * np;
  383. {
  384. register struct depend * dp;
  385. register char *p;
  386. char *rindex();
  387. if (dotouch)
  388. touch(np);
  389. else
  390. {
  391. strcpy(str1, "");
  392. for (dp = qdp; dp; dp = qdp)
  393. {
  394. if (strlen(str1))
  395. strcat(str1, " ");
  396. strcat(str1, dp->d_name->n_name);
  397. qdp = dp->d_next;
  398. free((char *)dp);
  399. }
  400. setmacro("?", str1, 4);
  401. setmacro("@", np->n_name, 4);
  402. p = rindex(np->n_name, '.');
  403. if (p) *p = 0;
  404. setmacro("*", np->n_name, 4);
  405. if (p) *p = '.';
  406. if (lp) /* lp set if doing a :: rule */
  407. docmds1(np, lp);
  408. else
  409. docmds(np);
  410. }
  411. }