doname.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. #include "defs.h"
  2. static int docom1(char *, int, int, int, int);
  3. static void expand(depblkp);
  4. /* BASIC PROCEDURE. RECURSIVE. */
  5. /*
  6. p->done = 0 don't know what to do yet
  7. p->done = 1 file in process of being updated
  8. p->done = 2 file already exists in current state
  9. p->done = 3 file make failed
  10. */
  11. int
  12. doname(nameblkp p, int reclevel, time_t *tval, int nowait)
  13. {
  14. int errstat;
  15. int okdel1;
  16. int didwork;
  17. int len;
  18. time_t td, td1, tdep, ptime, ptime1;
  19. depblkp q;
  20. depblkp qtemp, suffp, suffp1;
  21. nameblkp p1, p2;
  22. struct shblock *implcom, *explcom;
  23. lineblkp lp;
  24. lineblkp lp1, lp2;
  25. char sourcename[100], prefix[100], temp[100], concsuff[20];
  26. char *stem;
  27. char *pnamep, *p1namep;
  28. chainp allchain, qchain;
  29. char qbuf[QBUFMAX], tgsbuf[QBUFMAX];
  30. wildp wp;
  31. int nproc1;
  32. char *lastslash, *s;
  33. if(p == 0)
  34. {
  35. *tval = 0;
  36. return 0;
  37. }
  38. if(dbgflag)
  39. {
  40. printf("doname(%s,%d)\n",p->namep,reclevel);
  41. fflush(stdout);
  42. }
  43. if(p->done > 0)
  44. {
  45. *tval = p->modtime;
  46. return (p->done == 3);
  47. }
  48. errstat = 0;
  49. tdep = 0;
  50. implcom = 0;
  51. explcom = 0;
  52. ptime = exists(p->namep);
  53. ptime1 = 0;
  54. didwork = NO;
  55. p->done = 1; /* avoid infinite loops */
  56. nproc1 = nproc; /* current depth of process stack */
  57. qchain = NULL;
  58. allchain = NULL;
  59. /* define values of Bradford's $$@ and $$/ macros */
  60. for(s = lastslash = p->namep; *s; ++s)
  61. if(*s == '/')
  62. lastslash = s;
  63. setvar("$@", p->namep, YES);
  64. setvar("$/", lastslash, YES);
  65. /* expand any names that have embedded metacharacters */
  66. for(lp = p->linep ; lp ; lp = lp->nxtlineblock)
  67. for(q = lp->depp ; q ; q=qtemp )
  68. {
  69. qtemp = q->nxtdepblock;
  70. expand(q);
  71. }
  72. /* make sure all dependents are up to date */
  73. for(lp = p->linep ; lp ; lp = lp->nxtlineblock)
  74. {
  75. td = 0;
  76. for(q = lp->depp ; q ; q = q->nxtdepblock)
  77. if(q->depname)
  78. {
  79. errstat += doname(q->depname, reclevel+1, &td1, q->nowait);
  80. if(dbgflag)
  81. printf("TIME(%s)=%ld\n",q->depname->namep, td1);
  82. if(td1 > td)
  83. td = td1;
  84. if(ptime < td1)
  85. qchain = appendq(qchain, q->depname->namep);
  86. allchain = appendq(allchain, q->depname->namep);
  87. }
  88. if(p->septype == SOMEDEPS)
  89. {
  90. if(lp->shp)
  91. if( ptime<td || (ptime==0 && td==0) || lp->depp==0)
  92. {
  93. okdel1 = okdel;
  94. okdel = NO;
  95. set3var("@", p->namep);
  96. setvar("?", mkqlist(qchain,qbuf), YES);
  97. setvar("^", mkqlist(allchain,tgsbuf), YES);
  98. qchain = NULL;
  99. if( !questflag )
  100. errstat += docom(lp->shp, nowait, nproc1);
  101. set3var("@", CHNULL);
  102. okdel = okdel1;
  103. ptime1 = prestime();
  104. didwork = YES;
  105. }
  106. }
  107. else {
  108. if(lp->shp != 0)
  109. {
  110. if(explcom)
  111. fprintf(stderr, "Too many command lines for `%s'\n",
  112. p->namep);
  113. else explcom = lp->shp;
  114. }
  115. if(td > tdep) tdep = td;
  116. }
  117. }
  118. /* Look for implicit dependents, using suffix rules */
  119. for(lp = sufflist ; lp ; lp = lp->nxtlineblock)
  120. for(suffp = lp->depp ; suffp ; suffp = suffp->nxtdepblock)
  121. {
  122. pnamep = suffp->depname->namep;
  123. if(suffix(p->namep , pnamep , prefix))
  124. {
  125. (void)srchdir(concat(prefix,"*",temp), NO, (depblkp) NULL);
  126. for(lp1 = sufflist ; lp1 ; lp1 = lp1->nxtlineblock)
  127. for(suffp1=lp1->depp; suffp1 ; suffp1 = suffp1->nxtdepblock)
  128. {
  129. p1namep = suffp1->depname->namep;
  130. if( (p1=srchname(concat(p1namep, pnamep ,concsuff))) &&
  131. (p2=srchname(concat(prefix, p1namep ,sourcename))) )
  132. {
  133. errstat += doname(p2, reclevel+1, &td, NO);
  134. if(ptime < td)
  135. qchain = appendq(qchain, p2->namep);
  136. if(dbgflag) printf("TIME(%s)=%ld\n", p2->namep, td);
  137. if(td > tdep) tdep = td;
  138. set3var("*", prefix);
  139. set3var("<", copys(sourcename));
  140. for(lp2=p1->linep ; lp2 ; lp2 = lp2->nxtlineblock)
  141. if(implcom = lp2->shp) break;
  142. goto endloop;
  143. }
  144. }
  145. }
  146. }
  147. /* Look for implicit dependents, using pattern matching rules */
  148. len = strlen(p->namep);
  149. for(wp = firstwild ; wp ; wp = wp->next)
  150. if(stem = wildmatch(wp, p->namep, len) )
  151. {
  152. lp = wp->linep;
  153. for(q = lp->depp; q; q = q->nxtdepblock)
  154. {
  155. if(dbgflag>1 && q->depname)
  156. fprintf(stderr,"check dep of %s on %s\n", p->namep,
  157. wildsub(q->depname->namep,stem));
  158. if(q->depname &&
  159. ! chkname(wildsub(q->depname->namep,stem)))
  160. break;
  161. }
  162. if(q) /* some name not found, go to next line */
  163. continue;
  164. for(q = lp->depp; q; q = q->nxtdepblock)
  165. {
  166. nameblkp tamep;
  167. if(q->depname == NULL)
  168. continue;
  169. tamep = srchname( wildsub(q->depname->namep,stem));
  170. /*TEMP fprintf(stderr,"check dep %s on %s =>%s\n",p->namep,q->depname->namep,tamep->namep);*/
  171. /*TEMP*/if(dbgflag) printf("%s depends on %s. stem=%s\n", p->namep,tamep->namep, stem);
  172. errstat += doname(tamep, reclevel+1, &td, q->nowait);
  173. if(ptime < td)
  174. qchain = appendq(qchain, tamep->namep);
  175. allchain = appendq(allchain, tamep->namep);
  176. if(dbgflag) printf("TIME(%s)=%ld\n", tamep->namep, td);
  177. if(td > tdep)
  178. tdep = td;
  179. set3var("<", copys(tamep->namep) );
  180. }
  181. set3var("*", stem);
  182. setvar("%", stem, YES);
  183. implcom = lp->shp;
  184. goto endloop;
  185. }
  186. endloop:
  187. if(errstat==0 && (ptime<tdep || (ptime==0 && tdep==0) ) )
  188. {
  189. ptime = (tdep>0 ? tdep : prestime() );
  190. set3var("@", p->namep);
  191. setvar("?", mkqlist(qchain,qbuf), YES);
  192. setvar("^", mkqlist(allchain,tgsbuf), YES);
  193. if(explcom)
  194. errstat += docom(explcom, nowait, nproc1);
  195. else if(implcom)
  196. errstat += docom(implcom, nowait, nproc1);
  197. else if(p->septype == 0)
  198. if(p1=srchname(".DEFAULT"))
  199. {
  200. set3var("<", p->namep);
  201. for(lp2 = p1->linep ; lp2 ; lp2 = lp2->nxtlineblock)
  202. if(implcom = lp2->shp)
  203. {
  204. errstat += docom(implcom, nowait,nproc1);
  205. break;
  206. }
  207. }
  208. else if(keepgoing)
  209. {
  210. printf("Don't know how to make %s\n", p->namep);
  211. ++errstat;
  212. }
  213. else
  214. fatal1(" Don't know how to make %s", p->namep);
  215. set3var("@", CHNULL);
  216. if(noexflag || nowait || (ptime = exists(p->namep)) == 0 )
  217. ptime = prestime();
  218. }
  219. else if(errstat!=0 && reclevel==0)
  220. printf("`%s' not remade because of errors\n", p->namep);
  221. else if(!questflag && reclevel==0 && didwork==NO)
  222. printf("`%s' is up to date.\n", p->namep);
  223. if(questflag && reclevel==0)
  224. exit(ndocoms>0 ? -1 : 0);
  225. p->done = (errstat ? 3 : 2);
  226. if(ptime1 > ptime)
  227. ptime = ptime1;
  228. p->modtime = ptime;
  229. *tval = ptime;
  230. return errstat;
  231. }
  232. docom(struct shblock *q, int nowait, int nproc1)
  233. {
  234. char *s;
  235. int ign, nopr, doit;
  236. char string[OUTMAX];
  237. ++ndocoms;
  238. if(questflag)
  239. return NO;
  240. if(touchflag)
  241. {
  242. s = varptr("@")->varval;
  243. if(!silflag)
  244. printf("touch(%s)\n", s);
  245. if(!noexflag)
  246. touch(YES, s);
  247. return NO;
  248. }
  249. if(nproc1 < nproc)
  250. waitstack(nproc1);
  251. for( ; q ; q = q->nxtshblock )
  252. {
  253. subst(q->shbp, string, &string[sizeof string - 1]);
  254. ign = ignerr;
  255. nopr = NO;
  256. doit = NO;
  257. for(s = string ; ; ++s)
  258. {
  259. switch(*s)
  260. {
  261. case '-':
  262. ign = YES;
  263. continue;
  264. case '@':
  265. nopr = YES;
  266. continue;
  267. case '+':
  268. doit = YES;
  269. continue;
  270. default:
  271. break;
  272. }
  273. break;
  274. }
  275. if( docom1(s, ign, nopr, doit||!noexflag, nowait&&!q->nxtshblock) && !ign)
  276. return YES;
  277. }
  278. return NO;
  279. }
  280. static int
  281. docom1(char *comstring, int nohalt, int noprint, int doit, int nowait)
  282. {
  283. int status;
  284. char *prefix;
  285. if(comstring[0] == '\0')
  286. return 0;
  287. if(!silflag && (!noprint || !doit) )
  288. prefix = doit ? prompt : "" ;
  289. else
  290. prefix = CHNULL;
  291. if(dynmacro(comstring) || !doit)
  292. {
  293. if(prefix)
  294. {
  295. fputs(prefix, stdout);
  296. puts(comstring); /* with a newline */
  297. fflush(stdout);
  298. }
  299. return 0;
  300. }
  301. status = dosys(comstring, nohalt, nowait, prefix);
  302. baddirs(); /* directories may have changed */
  303. return status;
  304. }
  305. /*
  306. If there are any Shell meta characters in the name,
  307. expand into a list, after searching directory
  308. */
  309. static void
  310. expand(depblkp q)
  311. {
  312. char *s;
  313. char *s1;
  314. depblkp p;
  315. s1 = q->depname->namep;
  316. for(s=s1 ; ;) switch(*s++)
  317. {
  318. case '\0':
  319. return;
  320. case '*':
  321. case '?':
  322. case '[':
  323. if( p = srchdir(s1 , YES, q->nxtdepblock) )
  324. {
  325. q->nxtdepblock = p;
  326. q->depname = 0;
  327. }
  328. return;
  329. }
  330. }