home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume14 / dmake / part15 < prev    next >
Encoding:
Text File  |  1990-07-26  |  39.2 KB  |  1,310 lines

  1. Newsgroups: comp.sources.misc
  2. subject: v14i025: dmake version 3.5 part 15/21
  3. From: dvadura@watdragon.waterloo.edu (Dennis Vadura)
  4. Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  5.  
  6. Posting-number: Volume 14, Issue 25
  7. Submitted-by: dvadura@watdragon.waterloo.edu (Dennis Vadura)
  8. Archive-name: dmake/part15
  9.  
  10. #!/bin/sh
  11. # this is part 15 of a multipart archive
  12. # do not concatenate these parts, unpack them in order with /bin/sh
  13. # file make.c continued
  14. #
  15. CurArch=15
  16. if test ! -r s2_seq_.tmp
  17. then echo "Please unpack part 1 first!"
  18.      exit 1; fi
  19. ( read Scheck
  20.   if test "$Scheck" != $CurArch
  21.   then echo "Please unpack part $Scheck next!"
  22.        exit 1;
  23.   else exit 0; fi
  24. ) < s2_seq_.tmp || exit 1
  25. echo "x - Continuing file make.c"
  26. sed 's/^X//' << 'SHAR_EOF' >> make.c
  27. X    * that fact for all of the prerequisites that we will be making. */
  28. X
  29. X   cp->ce_setdir = setdirroot;
  30. X
  31. X   if( cp->ce_attr & A_SETDIR ) {
  32. X      /* Change directory only if the previous .SETDIR is a different
  33. X      /* directory from the current one.  ie. all cells with the same .SETDIR
  34. X      /* attribute are assumed to come from the same directory. */
  35. X
  36. X      if( (setdirroot == NIL(CELL) || setdirroot->ce_dir != cp->ce_dir) &&
  37. X          (push = Push_dir(cp, (cp->ce_attr | Glob_attr) & A_IGNORE)))
  38. X     setdirroot = cp;
  39. X   }
  40. X
  41. X   DB_PRINT( "mem", ("%s:-A mem %ld", cp->CE_NAME, (long) coreleft()) );
  42. X   if( (how->hw_recipe == NIL(STRING) && !(how->hw_flag & F_INFER)) ) {
  43. X      HOWPTR thp;
  44. X      
  45. X      if( Verbose )
  46. X     printf( "%s:  Infering prerequisite(s) and recipe for [%s]\n", Pname,
  47. X          cp->CE_NAME );
  48. X
  49. X      thp = how->hw_next;
  50. X      (void) Infer_recipe( cp, how, NIL(DFASET), setdirroot );
  51. X
  52. X      /* If we inferred a new set of prerequisites then make
  53. X       * them before the current list represented by the current how pointer */
  54. X      if( thp != how->hw_next )
  55. X     if( (rval = Make(cp, how->hw_next, cp->ce_setdir)) == -1 ||
  56. X         !(how->hw_next->hw_flag & F_MADE) )
  57. X        goto stop_making_it;
  58. X   }
  59. X
  60. X   DB_PRINT( "mem", ("%s:-A mem %ld", cp->CE_NAME, (long) coreleft()) );
  61. X   /* If we have not yet statted the target then do so. */
  62. X   if( !(cp->ce_flag & F_STAT) ) {
  63. X      time_t itime = cp->ce_time;
  64. X      Stat_target( cp, TRUE );
  65. X
  66. X      if( cp->ce_time == (time_t)0L ) {
  67. X         if( cp->ce_flag & F_INFER )
  68. X        cp->ce_time = itime;
  69. X      }
  70. X      else
  71. X         cp->ce_attr |= A_PRECIOUS;  /* File exists so don't remove it later. */
  72. X
  73. X      if( Verbose )
  74. X     printf("%s:  Time stamp of [%s] is %ld\n",Pname,cp->CE_NAME,
  75. X            cp->ce_time);
  76. X   }
  77. X
  78. X   DB_PRINT( "make", ("(%s, %ld, 0x%04x, 0x%04x)", cp->CE_NAME,
  79. X            cp->ce_time, cp->ce_attr, cp->ce_flag) );
  80. X
  81. X   if( !(cp->ce_flag & F_TARGET) && (cp->ce_time == (time_t) 0L) )
  82. X      if( Makemkf )
  83. X     DB_RETURN( -1 );
  84. X      else
  85. X     Fatal( "`%s' not found, and can't be made", cp->CE_NAME );
  86. X
  87. X   DB_PRINT( "mem", ("%s:-A mem %ld", cp->CE_NAME, (long) coreleft()) );
  88. X
  89. X   /* set value of $* if we have not infered a recipe, in this case $* is
  90. X    * the same as $(@:db), this allows us to be compatible with BSD make */
  91. X   if( how->hw_per == NIL(char) ) how->hw_per = "$(@:db)";
  92. X
  93. X   for( dp = how->hw_prq; dp != NIL(LINK); dp = dp->cl_next ) {
  94. X      int seq;
  95. X
  96. X      /* Make the prerequisite, note that if the current target has the
  97. X       * .LIBRARY attribute set we pass on to the prerequisite the .LIBRARYM
  98. X       * attribute and pass on the name of the current target as the library
  99. X       * name, and we take it away when we are done.  */
  100. X
  101. X      tcp = dp->cl_prq;
  102. X      seq = (cp->ce_attr | how->hw_attr | Glob_attr) & A_SEQ;
  103. X
  104. X      if( (tcp->ce_flag & F_VISITED) && !(tcp->ce_flag & F_MADE) )
  105. X         goto stop_making_it;
  106. X      else if( tcp->ce_flag & F_MADE )
  107. X         continue;
  108. X
  109. X      if( strchr(tcp->CE_NAME, '$') ) {
  110. X     /* Make this prerequisite link point at the real prerequisite we
  111. X      * are after, ie figure out what the dynamic one is and point at it. */
  112. X
  113. X     m_at = Def_macro( "@", cp->ce_fname, M_MULTI );
  114. X     name = Expand( tcp->CE_NAME );
  115. X
  116. X     tcp = dp->cl_prq = Def_cell( name, setdirroot );
  117. X     FREE( name );
  118. X      }
  119. X
  120. X      if( cp->ce_attr & A_LIBRARY ) {
  121. X         tcp->ce_attr |= A_LIBRARYM;
  122. X     tcp->ce_lib   = cp->ce_fname;
  123. X      }
  124. X
  125. X      if( (tcp->ce_flag & (F_INFER | F_STAT)) == F_INFER )
  126. X     tcp->ce_time = cp->ce_time;
  127. X
  128. X      /* Propagate parents F_REMOVE and F_INFER attribute to children.
  129. X       * Make certain you do this AFTER propagating the time, since the
  130. X       * time propagation test above uses the F_INFER flag to decide if
  131. X       * it should do so. */
  132. X      tcp->ce_flag |= cp->ce_flag & (F_REMOVE|F_INFER);
  133. X
  134. X      rval |= Make(tcp, tcp->CE_HOW, setdirroot);
  135. X
  136. X      if( cp->ce_attr & A_LIBRARY )
  137. X         tcp->ce_attr ^= A_LIBRARYM;
  138. X
  139. X      if( rval == -1 )
  140. X     goto stop_making_it;
  141. X      else if( seq && (rval == 1) )
  142. X     goto stop_making_it;
  143. X   }
  144. X
  145. X   /* Do the loop again.  We are most definitely going to make the current
  146. X    * how cell now.  NOTE:  doing this loop here also results in a reduction
  147. X    * in peak memory usage by the algorithm. */
  148. X
  149. X   for( dp = how->hw_prq; dp != NIL(LINK); dp = dp->cl_next ) {
  150. X      char *dir;
  151. X      int  tgflg;
  152. X      tcp  = dp->cl_prq;
  153. X      name = tcp->ce_fname;
  154. X
  155. X      /* make certain that all prerequisites are made prior to advancing. */
  156. X      if( !(tcp->ce_flag & F_MADE) ) goto stop_making_it;
  157. X
  158. X      /* If the target is a library, then check to make certain that a member
  159. X       * is newer than an object file sitting on disk.  If the disk version
  160. X       * is newer then set the time stamps so that the archived member is
  161. X       * replaced. */
  162. X      if( cp->ce_attr & A_LIBRARY )
  163. X     if( tcp->ce_time < cp->ce_time ) {
  164. X        time_t mtime = Do_stat( tcp->ce_fname, tcp->ce_lib, NIL(char *) );
  165. X        if( mtime < tcp->ce_time ) tcp->ce_time = cp->ce_time+1L;
  166. X     }
  167. X
  168. X      if( tcp->ce_time > otime ) otime = tcp->ce_time;
  169. X
  170. X      /* Note:  If the prerequisite was made using a SETDIR
  171. X       *        directory then we will include the directory in the name
  172. X       *       of the prerequisite when we build the $?, $&, $^ and $< lists
  173. X       */
  174. X
  175. X      if( (dir = tcp->ce_dir ) != NIL(char) )
  176. X     name = Build_path( dir, name );
  177. X
  178. X      all  = _strapp( all, name );
  179. X      if( tgflg = (dp->cl_flag & F_TARGET) ) inf = _strapp( inf, name );
  180. X
  181. X      if((cp->ce_time<tcp->ce_time) || ((tcp->ce_flag & F_TARGET) && Force)) {
  182. X         outall = _strapp( outall, name );
  183. X         if( tgflg ) imm = _strapp( imm, name );
  184. X      }
  185. X   }
  186. X
  187. X   DB_PRINT( "mem", ("%s:-C mem %ld", cp->CE_NAME, (long) coreleft()) );
  188. X   DB_PRINT( "make", ("I make '%s' if %ld > %ld", cp->CE_NAME, otime,
  189. X          cp->ce_time) );
  190. X
  191. X   /* mark the how cell as visited since we are making it for certain now. */
  192. X   how->hw_flag |= F_VISITED;
  193. X   if( Verbose ) printf( "%s:  >>>> Making [%s]\n", Pname, cp->CE_NAME );
  194. X
  195. X   if( Check && (cp->ce_time < otime) ) {
  196. X      /* Only checking so stop as soon as we determine we will make something */
  197. X      rval = -1;
  198. X      goto stop_making_it;
  199. X   }
  200. X
  201. X   if( (cp->ce_time < otime) || ((cp->ce_flag & F_TARGET) && Force) ) {
  202. X      if( Verbose )
  203. X     printf( "%s:  Updating [%s], (%ld > %ld)\n", Pname,
  204. X         cp->CE_NAME, otime, cp->ce_time );
  205. X
  206. X      cp->ce_attr |= A_UPDATED;
  207. X
  208. X      if( Touch ) {
  209. X     name = cp->ce_fname;
  210. X     lib  = cp->ce_lib;
  211. X
  212. X     if( !(Glob_attr & A_SILENT) || !Trace )
  213. X        if( lib == NIL(char) )
  214. X           printf("touch(%s)", name );
  215. X        else if( cp->ce_attr & A_SYMBOL )
  216. X           printf("touch(%s((%s)))", lib, name );
  217. X        else
  218. X           printf("touch(%s(%s))", lib, name );
  219. X
  220. X     if( !Trace )
  221. X        if( Do_touch( name, lib,
  222. X        (cp->ce_attr & A_SYMBOL) ? &name : NIL(char *) ) != 0 )
  223. X           printf( "  not touched - non-existant" );
  224. X
  225. X     printf( "\n" );
  226. X     Update_time_stamp( cp, how );
  227. X      }
  228. X      else if( how->hw_recipe != NIL(STRING) ) {
  229. X     HASHPTR m_q, m_b, m_g, m_l, m_bb, m_up;
  230. X     TKSTR   tk;
  231. X
  232. X     m_at = Def_macro( "@", cp->ce_fname,M_MULTI );
  233. X     m_g  = Def_macro( ">", cp->ce_lib,  M_MULTI );
  234. X     m_q  = Def_macro( "?", outall,      M_MULTI );
  235. X     m_b  = Def_macro( "<", inf,         M_MULTI );
  236. X     m_l  = Def_macro( "&", all,         M_MULTI );
  237. X     m_bb = Def_macro( "*", how->hw_per, M_MULTI );
  238. X     m_up = Def_macro( "^", imm,         M_MULTI );
  239. X
  240. X     _recipes[ RP_RECIPE ] = how->hw_recipe;
  241. X
  242. X     if( !(how->hw_flag & F_SINGLE) )
  243. X        rval = _exec_commands( cp, how );
  244. X     else {
  245. X        _drop_mac( m_q );
  246. X        SET_TOKEN( &tk, outall );
  247. X
  248. X        Doing_bang = TRUE;
  249. X        name = Get_token( &tk, "", FALSE );
  250. X        do {
  251. X           m_q->ht_value = name;
  252. X
  253. X           Wait_for_completion = TRUE;    /* Reset in _exec_commands */
  254. X           rval = _exec_commands( cp, how );
  255. X           Unlink_temp_files(how);
  256. X        }
  257. X        while( *(name = Get_token( &tk, "", FALSE )) != '\0' );
  258. X        Doing_bang = FALSE;
  259. X        Update_time_stamp( cp, how );
  260. X
  261. X        m_q->ht_value = NIL(char);
  262. X     }
  263. X
  264. X     _drop_mac( m_g  );
  265. X     _drop_mac( m_q  );
  266. X     _drop_mac( m_b  );
  267. X     _drop_mac( m_l  );
  268. X     _drop_mac( m_bb );
  269. X     _drop_mac( m_up );
  270. X      }
  271. X      else if( !(cp->ce_flag & F_RULES) &&
  272. X           ((cp != Root) || !(cp->ce_flag & F_EXPLICIT)) )
  273. X     Fatal( "Don't know how to make `%s'",cp->CE_NAME );
  274. X      else {
  275. X         /* Empty recipe, set the how flag as MADE and update the time stamp */
  276. X     Update_time_stamp( cp, how );
  277. X      }
  278. X   }
  279. X   else {
  280. X      /* Make sure everyone gets remade if Force is set */
  281. X      if( !(cp->ce_flag & F_TARGET) && Force ) cp->ce_time = Do_time();
  282. X
  283. X      /* Set how to MADE since it is done, it was not out of date */
  284. X      how->hw_flag |= F_MADE;
  285. X      if( cp->CE_HOW == how ) {
  286. X     tcp = cp;
  287. X     do {
  288. X        tcp->ce_flag |= F_MADE;
  289. X        tcp = tcp->ce_all;
  290. X     }
  291. X     while( tcp != NIL(CELL) && tcp != cp );
  292. X      }
  293. X   }
  294. X
  295. X   if( cp->CE_HOW == how ) cp->ce_flag |= F_VISITED;
  296. X
  297. Xstop_making_it:
  298. X   if( m_at != NIL(HASH) ) _drop_mac( m_at );
  299. X
  300. X   if( push )  Pop_dir(FALSE);
  301. X
  302. X   if( inf    != NIL(char) ) FREE( inf    );
  303. X   if( all    != NIL(char) ) FREE( all    );
  304. X   if( imm    != NIL(char) ) FREE( imm    );
  305. X   if( outall != NIL(char) ) FREE( outall );
  306. X
  307. X   DB_PRINT( "mem", ("%s:-< mem %ld", cp->CE_NAME, (long) coreleft()) );
  308. X   DB_RETURN( rval );
  309. X}
  310. X
  311. X
  312. X
  313. Xstatic void
  314. X_drop_mac( hp )/*
  315. X================ set a macro value to zero. */
  316. XHASHPTR hp;
  317. X{
  318. X   if( hp->ht_value != NIL(char) ) {
  319. X      FREE( hp->ht_value );
  320. X      hp->ht_value = NIL(char);
  321. X   }
  322. X}
  323. X
  324. X
  325. X
  326. Xstatic int
  327. X_exec_commands( cp, how )/*
  328. X===========================
  329. X  Execute the commands one at a time that are pointed to by the rules pointer
  330. X  of the target cp. If a group is indicated, then the hw_attr determines
  331. X  .IGNORE and .SILENT treatment for the group.
  332. X  
  333. X  The function returns 0, if the command is executed and has successfully
  334. X  returned, and returns 1 if the command is executing but has not yet
  335. X  returned (for parallel makes).
  336. X  
  337. X  The F_MADE bit in the how cell is guaranteed set when the command has
  338. X  successfully completed.  */
  339. XCELLPTR cp;
  340. XHOWPTR  how;
  341. X{
  342. X   register STRINGPTR    rp;
  343. X   char            *cmnd;
  344. X   char            *groupfile;
  345. X   char            *ap;
  346. X   char           *hold = NIL(char);
  347. X   FILE            *tmpfile;
  348. X   FILE            *here_doc = NIL(FILE);
  349. X   int            do_it;
  350. X   int            attr;
  351. X   int            group;
  352. X   int            trace;
  353. X   int            rval  = 0;
  354. X
  355. X   DB_ENTER( "_exec_commands" );
  356. X
  357. X   Current_target = how;
  358. X   attr  = Glob_attr | cp->ce_attr;
  359. X   trace = Trace || !(attr & A_SILENT);
  360. X   group = how->hw_flag & F_GROUP;
  361. X
  362. X   if( group ) {
  363. X      attr  |= how->hw_attr;
  364. X      trace  = Trace || !(attr & A_SILENT);
  365. X
  366. X      if( !Trace ) tmpfile = Start_temp( Grp_suff, cp, how, &groupfile );
  367. X      if( trace )  fputs( "[\n", stdout );
  368. X
  369. X      /* Emit group prolog */
  370. X      if( attr & A_PROLOG )
  371. X         _append_file( _recipes[RP_GPPROLOG], tmpfile, cp->CE_NAME, trace );
  372. X   }
  373. X
  374. X
  375. X   /* Process commands in recipe. If in group, merely append to file.
  376. X    * Otherwise, run them. If a text diversion indicated, expand
  377. X    * that document as required into a temporary file */
  378. X
  379. X   for( rp = _recipes[RP_RECIPE]; rp != NIL(STRING); rp=rp->st_next,FREE(cmnd)){
  380. X      char *savecmnd;
  381. X      int  done = 0;
  382. X
  383. X      do_it = !Trace;
  384. X
  385. X      if( !group && Trace && _strstr(rp->st_string,"$(MAKE)") ) {
  386. X     Wait_for_completion |= Trace;
  387. X     do_it = TRUE;
  388. X      }
  389. X
  390. X      savecmnd = cmnd = Expand( rp->st_string );
  391. X
  392. X/******* TEXT DIVERSION PROCESSING START ********/
  393. X      /* Look for a text diversion surrounded by <+ and +>.  Note that the
  394. X       * diversion may be on a single line or span multiple lines.  Note that
  395. X       * if a diversion is started with <+ and never finished with +> an error
  396. X       * is issued. */
  397. X
  398. X      /* Check for the start of a new diversion */
  399. X      do {
  400. X     if( here_doc == NIL(FILE) && (ap = _strstr(cmnd, "<+")) != NIL(char)) {
  401. X        char *t;
  402. X        char *fname;
  403. X        here_doc = Start_temp( "", cp, how, &fname );
  404. X        *ap = '\0';
  405. X        hold = _strjoin( hold, t = _strjoin(cmnd,fname,-1,FALSE),-1,TRUE);
  406. X        FREE(t);
  407. X        cmnd = ap+2;
  408. X     }
  409. X
  410. X     if( here_doc != NIL(FILE) ) {
  411. X        if( (ap = _strstr(cmnd, "+>")) == NIL(char) ) {
  412. X           _add_here(cmnd, here_doc, TRUE);
  413. X           done = TRUE;
  414. X        }
  415. X        else {
  416. X           *ap = '\0';
  417. X           if( *_strspn(cmnd, " \t") != '\0' )
  418. X          _add_here(cmnd, here_doc, FALSE);
  419. X
  420. X           cmnd = ap+2;
  421. X           Close_temp( how, here_doc );
  422. X           here_doc = NIL(FILE);
  423. X        }
  424. X     }
  425. X     else if( hold != NIL(char) ) {
  426. X        cmnd = _strjoin( hold, cmnd, -1, TRUE );
  427. X        done = TRUE;
  428. X        hold = NIL(char);
  429. X        FREE( savecmnd );
  430. X     }
  431. X     else
  432. X        done = TRUE;
  433. X      }
  434. X      while( *cmnd && !done );
  435. X
  436. X      if( here_doc != NIL(FILE) ) continue;
  437. X      if( hold != NIL(char) ) {
  438. X     FREE(savecmnd);
  439. X     cmnd = hold;
  440. X      }
  441. X/******* TEXT DIVERSION PROCESSING END ********/
  442. X
  443. X
  444. X      if( group )
  445. X         _append_line( cmnd, TRUE, tmpfile, cp->CE_NAME, trace );
  446. X      else {
  447. X     if( *_strspn(cmnd, " \t") != '\0' )
  448. X        _print_cmnd(cmnd, !(do_it && ((rp->st_attr | attr) & A_SILENT)), 0);
  449. X     else
  450. X        do_it = FALSE;
  451. X
  452. X     rval=Do_cmnd(cmnd,FALSE,do_it,cp,how,((attr|rp->st_attr)&A_IGNORE),
  453. X                  rp->st_next == NIL(STRING) );
  454. X      }
  455. X   }
  456. X
  457. X   if( here_doc != NIL(FILE) )
  458. X      Fatal( "Unterminated text diversion while making `%s'", cp->CE_NAME );
  459. X
  460. X   /* If it is a group then output the EPILOG if required and possibly
  461. X    * execute the command */
  462. X   if( group ) {
  463. X      if( attr & A_EPILOG )    /* emit epilog */
  464. X     _append_file( _recipes[RP_GPEPILOG], tmpfile, cp->CE_NAME, trace );
  465. X
  466. X      if( trace ) fputs("]\n", stdout);
  467. X
  468. X      if( do_it = !Trace ) Close_temp( how, tmpfile );
  469. X      rval = Do_cmnd(groupfile, TRUE, do_it, cp, how, attr & A_IGNORE, TRUE);
  470. X   }
  471. X
  472. X   Wait_for_completion = FALSE;
  473. X   DB_RETURN( rval );
  474. X}
  475. X
  476. X
  477. X
  478. Xstatic void
  479. X_print_cmnd( cmnd, echo, map )/*
  480. X================================
  481. X   This routine is called to print out the command to stdout.  If echo is
  482. X   false the printing to stdout is supressed, but the new lines in the command
  483. X   are still deleted. */
  484. Xchar *cmnd;
  485. Xint  echo;
  486. Xint  map;
  487. X{
  488. X   register char *p;
  489. X   register char *n;
  490. X
  491. X   DB_ENTER( "_print_cmnd" );
  492. X
  493. X   if( echo ) printf( "%s\n", cmnd  );
  494. X
  495. X   for( p=cmnd; (n = strchr(p, CONTINUATION_CHAR)) != NIL(char); p=n+1 )
  496. X      if(n[1] == '\n') {
  497. X     DB_PRINT( "make", ("fixing [%s]", p) );
  498. X     strcpy( n, n+2 );
  499. X      }
  500. X      else if( map )
  501. X     Map_esc( n );
  502. X
  503. X   DB_VOID_RETURN;
  504. X}
  505. X
  506. X
  507. X
  508. X/* These routines are used to maintain a stack of directories when making
  509. X * the targets.  If a target cd's to the directory then it is assumed that
  510. X * it will undo it when it is finished making itself. */
  511. X
  512. Xstatic STRINGPTR dir_stack = NIL(STRING);
  513. X
  514. Xint
  515. XPush_dir( cp, ignore )/*
  516. X==========================
  517. X   Change the current working directory to dir and save the current
  518. X   working directory on the stack so that we can come back.
  519. X   
  520. X   If ignore is TRUE then do not complain about _ch_dir if not possible.*/
  521. XCELLPTR cp;
  522. Xint  ignore;
  523. X{
  524. X   STRINGPTR   new_dir;
  525. X   char        *dir;
  526. X
  527. X   DB_ENTER( "Push_dir" );
  528. X
  529. X   if( (dir = cp->ce_dir) == NIL(char) ) dir = Pwd;
  530. X   if( *dir == '\'' && dir[strlen(dir)-1] == '\'' ) {
  531. X      dir = _strdup(dir+1);
  532. X      dir[strlen(dir)-1]='\0';
  533. X   }
  534. X   else
  535. X      dir = Expand(dir);
  536. X
  537. X   if( Set_dir(dir) ) {
  538. X      if( !ignore )
  539. X         Fatal( "Unable to change to directory `%s', target is [%s]",
  540. X            dir, cp->CE_NAME );
  541. X      FREE(dir);
  542. X      DB_RETURN( 0 );
  543. X   }
  544. X
  545. X   DB_PRINT( "dir", ("Push: [%s]", dir) );
  546. X   if( Verbose ) printf( "%s:  Changed to directory [%s]\n", Pname, dir  );
  547. X
  548. X   FREE( dir );
  549. X   TALLOC( new_dir, 1, STRING );
  550. X   new_dir->st_next   = dir_stack;
  551. X   dir_stack          = new_dir;
  552. X   new_dir->st_string = _strdup( Pwd );
  553. X
  554. X   Def_macro( "PWD", Get_current_dir(), M_MULTI | M_EXPANDED );
  555. X   _set_tmd();
  556. X
  557. X   DB_RETURN( 1 );
  558. X}
  559. X
  560. X
  561. X
  562. Xvoid
  563. XPop_dir(ignore)/*
  564. X=================
  565. X   Change the current working directory to the previous saved dir. */
  566. Xint ignore;
  567. X{
  568. X   STRINGPTR old_dir;
  569. X   char      *dir;
  570. X
  571. X   DB_ENTER( "Pop_dir" );
  572. X
  573. X   if( dir_stack == NIL(STRING) )
  574. X      if( ignore ) {
  575. X         DB_VOID_RETURN;
  576. X      }
  577. X      else
  578. X     Error( "Directory stack empty for return from .SETDIR" );
  579. X
  580. X   if( Set_dir(dir = dir_stack->st_string) )
  581. X      Fatal( "Could not change to directory `%s'", dir );
  582. X
  583. X   Def_macro( "PWD", dir, M_MULTI | M_EXPANDED );
  584. X   DB_PRINT( "dir", ("Pop: [%s]", dir) );
  585. X   if( Verbose ) printf( "%s:  Changed back to directory [%s]\n", Pname, dir);
  586. X
  587. X   old_dir   = dir_stack;
  588. X   dir_stack = dir_stack->st_next;
  589. X
  590. X   FREE( old_dir->st_string );
  591. X   FREE( old_dir );
  592. X   _set_tmd();
  593. X
  594. X   DB_VOID_RETURN;
  595. X}
  596. X
  597. X
  598. X
  599. Xstatic void
  600. X_set_tmd()/*
  601. X============
  602. X   Set the TWD Macro */
  603. X{
  604. X   TKSTR md, pd;
  605. X   char  *m, *p;
  606. X   char  *tmd;
  607. X   int   is_sep;
  608. X   int   first = 1;
  609. X
  610. X   SET_TOKEN( &md, Makedir );
  611. X   SET_TOKEN( &pd, Pwd );
  612. X
  613. X   m = Get_token( &md, DirBrkStr, FALSE );
  614. X   (void) Get_token( &pd, DirBrkStr, FALSE );
  615. X   is_sep = (strchr(DirBrkStr, *m) != NIL(char));
  616. X   tmd = _strdup( "" );
  617. X
  618. X   do {
  619. X      m = Get_token( &md, DirBrkStr, FALSE );
  620. X      p = Get_token( &pd, DirBrkStr, FALSE );
  621. X
  622. X      if( !is_sep && strcmp(m, p) ) {    /* they differ */
  623. X     char *tmp;
  624. X     if( first ) {        /* They differ in the first component    */
  625. X        tmd = Makedir;    /* In this case use the full path    */
  626. X        break;
  627. X     }
  628. X
  629. X     if( *p ) tmp = Build_path( "..", tmd );
  630. X     if( *m ) tmp = Build_path( tmd, m );
  631. X     FREE( tmd );
  632. X     tmd = _strdup( tmp );
  633. X      }
  634. X
  635. X      is_sep = 1-is_sep;
  636. X      first  = 0;
  637. X   } while (*m || *p);
  638. X
  639. X   CLEAR_TOKEN( &md );
  640. X   CLEAR_TOKEN( &pd );
  641. X
  642. X   Def_macro( "TMD", tmd, M_MULTI | M_EXPANDED );
  643. X   if( tmd != Makedir ) FREE( tmd );
  644. X}
  645. X
  646. X
  647. Xstatic void
  648. X_set_recipe( target, ind )/*
  649. X============================
  650. X   Set up the _recipes static variable so that the slot passed in points
  651. X   at the rules corresponding to the target supplied. */
  652. Xchar *target;
  653. Xint  ind;
  654. X{
  655. X   CELLPTR cp;
  656. X   HASHPTR hp;
  657. X
  658. X   if( (hp = Get_name( target, Defs, FALSE, NIL(CELL) )) != NIL(HASH) ) {
  659. X      cp = hp->CP_OWNR;
  660. X      if( cp->CE_HOW != NIL(HOW) ) _recipes[ ind ] = cp->CE_RECIPE;
  661. X   }
  662. X   else
  663. X      _recipes[ ind ] = NIL(STRING);
  664. X}
  665. X
  666. X
  667. X
  668. Xstatic void
  669. X_append_line( cmnd, newline, tmpfile, name, printit )
  670. Xchar *cmnd;
  671. Xint  newline;
  672. XFILE *tmpfile;
  673. Xchar *name;
  674. Xint  printit;
  675. X{
  676. X   _print_cmnd( cmnd, printit, 0 );
  677. X
  678. X   if( Trace ) return;
  679. X
  680. X   fputs(cmnd, tmpfile);
  681. X   if( newline ) fputc('\n', tmpfile);
  682. X   fflush(tmpfile);
  683. X
  684. X   if( ferror(tmpfile) )
  685. X      Fatal("Write error on temporary group file, for target `%s'", name);
  686. X}
  687. X
  688. X
  689. X
  690. Xstatic void
  691. X_append_file( rp, tmpfile, name, printit )
  692. Xregister STRINGPTR rp;
  693. XFILE            *tmpfile;
  694. Xchar            *name;
  695. Xint            printit;
  696. X{
  697. X   char *cmnd;
  698. X
  699. X   while( rp != NIL(STRING) ) {
  700. X      _append_line(cmnd = Expand(rp->st_string), TRUE, tmpfile, name, printit);
  701. X      FREE(cmnd);
  702. X      rp = rp->st_next;
  703. X   }
  704. X}
  705. X
  706. X
  707. X
  708. Xstatic void
  709. X_add_here( line, file, newline )
  710. Xchar *line;
  711. XFILE *file;
  712. Xint  newline;
  713. X{
  714. X   while( *line == '\t' )      /* skip initial tabs */
  715. X      line++;
  716. X
  717. X   _print_cmnd( line, FALSE, TRUE );
  718. X   fputs(line, file);
  719. X   if( newline ) fputc('\n', file);
  720. X   fflush(file);
  721. X
  722. X   if( ferror(file) )
  723. X      Fatal("Write error on temporary file for text diversion");
  724. X}
  725. SHAR_EOF
  726. echo "File make.c is complete"
  727. chmod 0440 make.c || echo "restore of make.c fails"
  728. echo "x - extracting make.bat (Text)"
  729. sed 's/^X//' << 'SHAR_EOF' > make.bat &&
  730. Xecho off
  731. Xrem  *** This is the make batchfile that is used under MSDOS to make the
  732. Xrem  *** first version of dmake.  It isn't pretty but it does work, assuming
  733. Xrem  *** the compilers have been correctly setup.  See the warning below
  734. Xrem  *** concerning tlink, if you are making the Turbo C version.
  735. Xrem
  736. Xecho Running make.bat script to make a %1 copy of dmake.
  737. X
  738. Xif %0%1 == %0 goto error
  739. Xif %1 == mscdos goto makemsc
  740. Xif %1 == tccdos goto maketcc
  741. X
  742. Xrem label the possible DOS variations for dmake here.
  743. X:error
  744. Xecho ERROR:  You must specify one of:
  745. Xecho     tccdos  - Turbo C 2.0, compile.
  746. Xecho     mscdos  - Microsoft C 4.0 or higher, compile.
  747. Xgoto end
  748. X
  749. Xrem This is the script that makes dmake using Microsoft C 4.0 or higher.
  750. X:makemsc
  751. Xmsdos\mscdos\make.bat
  752. Xgoto end
  753. X
  754. Xrem This is the script that makes dmake using Turbo C 2.0 or higher.
  755. X:maketcc
  756. Xcls
  757. Xecho WARNING:
  758. Xecho    The default response files msdos\tccdos\tccobj.rsp
  759. Xecho    and msdos\tccdos\tcclib.rsp contain absolute paths to TURBO-C
  760. Xecho    runtime startup objects, and to the standard libraries.  You should
  761. Xecho    check that these files point to the right places before proceeding.
  762. Xecho --
  763. Xecho Continue if ok, or abort and edit the response files.
  764. Xpause
  765. Xmsdos\tccdos\make.bat
  766. X
  767. Xrem All done!
  768. X:end
  769. SHAR_EOF
  770. chmod 0440 make.bat || echo "restore of make.bat fails"
  771. echo "x - extracting macparse.c (Text)"
  772. sed 's/^X//' << 'SHAR_EOF' > macparse.c &&
  773. X/* RCS      -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/macparse.c,v 1.1 90/07/19 13:53:20 dvadura Exp $
  774. X-- SYNOPSIS -- parse a macro definition
  775. X-- 
  776. X-- DESCRIPTION
  777. X--    This file contains the code that parses a macro definition
  778. X--    stored in a buffer.  If the string in buffer is not a valid
  779. X--    macro definition the routie Parse_macro returns 0, otherwise it
  780. X--    returns 1 to indicate success.
  781. X-- 
  782. X-- AUTHOR
  783. X--      Dennis Vadura, dvadura@watdragon.uwaterloo.ca
  784. X--      CS DEPT, University of Waterloo, Waterloo, Ont., Canada
  785. X--
  786. X-- COPYRIGHT
  787. X--      Copyright (c) 1990 by Dennis Vadura.  All rights reserved.
  788. X-- 
  789. X--      This program is free software; you can redistribute it and/or
  790. X--      modify it under the terms of the GNU General Public License
  791. X--      (version 1), as published by the Free Software Foundation, and
  792. X--      found in the file 'LICENSE' included with this distribution.
  793. X-- 
  794. X--      This program is distributed in the hope that it will be useful,
  795. X--      but WITHOUT ANY WARRANTY; without even the implied warrant of
  796. X--      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  797. X--      GNU General Public License for more details.
  798. X-- 
  799. X--      You should have received a copy of the GNU General Public License
  800. X--      along with this program;  if not, write to the Free Software
  801. X--      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  802. X--
  803. X-- LOG
  804. X--     $Log:    macparse.c,v $
  805. X * Revision 1.1  90/07/19  13:53:20  dvadura
  806. X * Initial Revision of Version 3.5
  807. X * 
  808. X*/
  809. X
  810. X#include <ctype.h>
  811. X#include "extern.h"
  812. X#include "alloc.h"
  813. X#include "db.h"
  814. X
  815. Xint
  816. XParse_macro( buffer, flag )/*
  817. X=============================
  818. X   Parse the string in buffer and define it as a macro if it is a valid macro.
  819. X   Note especially the string .SETDIR= since it is an attribute, but looks a
  820. X   lot like a macro definition.  This would not be a problem if make used
  821. X   white space as token separators, since this is not the case we must do
  822. X   something about it. */
  823. Xchar *buffer;
  824. Xint  flag;
  825. X{
  826. X   register char *tok1;        /* temporary place to keep a token */
  827. X   register char *tok2;        /* temporary place to keep a token */
  828. X   char         *result;    /* temporary pointer for strings   */
  829. X   TKSTR          input;        /* place to scan the buffer from   */
  830. X   HASHPTR      hv;        /* pointer to hash table value       */
  831. X   int          operator;    /* what macro operator do we have  */
  832. X
  833. X   DB_ENTER( "Parse_macro" );
  834. X
  835. X   SET_TOKEN( &input, buffer );
  836. X   tok1 = Get_token( &input, "=+:", FALSE );
  837. X
  838. X   if( Macro_op( tok1 ) ) {
  839. X      Error( "No macro name" );
  840. X      CLEAR_TOKEN( &input );
  841. X      DB_RETURN( 1 );
  842. X   }
  843. X
  844. X   tok1 = _strdup( tok1 );
  845. X   tok2 = Get_token( &input, "=+:", FALSE );
  846. X   if( !(operator = Macro_op( tok2 )) || !strcmp( tok1, ".SETDIR") )
  847. X   {
  848. X      CLEAR_TOKEN( &input );
  849. X      FREE( tok1 );
  850. X      DB_RETURN( 0 );
  851. X   }
  852. X
  853. X   tok2 = Expand(tok1); FREE(tok1); tok1 = tok2;
  854. X   tok2 = Get_token( &input, NIL( char ), FALSE );
  855. X
  856. X   switch( operator ) {
  857. X      case M_OP_PLCL:
  858. X      tok2 = Expand( tok2 );
  859. X
  860. X      case M_OP_PL:
  861. X     /* Add to an existing macro, if it is not defined, though, then
  862. X      * fall through and define a new macro */
  863. X
  864. X     if( (hv = GET_MACRO(tok1)) != NIL(HASH) ) {
  865. X        if( hv->ht_value != NIL(char) ) {
  866. X           result = _stradd( hv->ht_value, tok2, FALSE );
  867. X           Def_macro( tok1, result, flag );
  868. X           FREE( result );
  869. X        }
  870. X        else
  871. X           Def_macro( tok1, tok2, flag );
  872. X
  873. X        if( operator == M_OP_PLCL ) FREE(tok2);
  874. X        break;
  875. X     }
  876. X     /*FALLTRHOUGH*/
  877. X
  878. X      case M_OP_EQ:
  879. X     Def_macro( tok1, tok2, flag );
  880. X     if( operator == M_OP_PLCL ) FREE(tok2);
  881. X     break;
  882. X              
  883. X      case M_OP_CL:
  884. X     /* If the macro we are assigning from is a single control
  885. X      * macro with nothing else, then we propagate the M_MULTI
  886. X      * flag to the macro we are assigning the value to so that
  887. X      * the same macro can be used to do this over and over. */
  888. X     If_multi = 0;
  889. X     tok2 = Expand( tok2 );
  890. X     Def_macro( tok1, tok2, M_EXPANDED | flag | If_multi );
  891. X     FREE( tok2 );
  892. X     break;
  893. X   }
  894. X        
  895. X   FREE( tok1 );
  896. X
  897. X   DB_RETURN( 1 );
  898. X}
  899. X
  900. X
  901. X
  902. Xint
  903. XMacro_op( op )/*
  904. X================
  905. X   Check the passed in op string and map it to one of the macro operators */
  906. Xchar *op;
  907. X{
  908. X   int ret = 0;
  909. X
  910. X   DB_ENTER( "macro_op" );
  911. X
  912. X   switch( *op ) {
  913. X      case '=': ret = M_OP_EQ; break;
  914. X      case ':': ret = M_OP_CL; op++; break;
  915. X
  916. X      case '+':
  917. X         if( *op == '+' ) { ret = M_OP_PL;   op++; }
  918. X         if( *op == ':' ) { ret = M_OP_PLCL; op++; }
  919. X         break;
  920. X   }
  921. X
  922. X   if( *op++ != '=' )
  923. X      ret = 0;
  924. X   else if( *op != '\0' )
  925. X      ret = 0;
  926. X
  927. X   DB_RETURN( ret );
  928. X}
  929. X
  930. SHAR_EOF
  931. chmod 0440 macparse.c || echo "restore of macparse.c fails"
  932. echo "x - extracting infer.c (Text)"
  933. sed 's/^X//' << 'SHAR_EOF' > infer.c &&
  934. X/* RCS      -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/infer.c,v 1.1 90/07/21 11:06:32 dvadura Exp $
  935. X-- SYNOPSIS -- infer how to make a target.
  936. X-- 
  937. X-- DESCRIPTION
  938. X--    This file contains the code to infer a recipe, and possibly some new
  939. X--    prerequisites for a target which dmake does not know how to make, or
  940. X--    has no explicit recipe.
  941. X--
  942. X--    The inference fails if no path through the inference graph can be
  943. X--    found by which we can make the target.
  944. X-- 
  945. X-- AUTHOR
  946. X--      Dennis Vadura, dvadura@watdragon.uwaterloo.ca
  947. X--      CS DEPT, University of Waterloo, Waterloo, Ont., Canada
  948. X--
  949. X-- COPYRIGHT
  950. X--      Copyright (c) 1990 by Dennis Vadura.  All rights reserved.
  951. X-- 
  952. X--      This program is free software; you can redistribute it and/or
  953. X--      modify it under the terms of the GNU General Public License
  954. X--      (version 1), as published by the Free Software Foundation, and
  955. X--      found in the file 'LICENSE' included with this distribution.
  956. X-- 
  957. X--      This program is distributed in the hope that it will be useful,
  958. X--      but WITHOUT ANY WARRANTY; without even the implied warrant of
  959. X--      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  960. X--      GNU General Public License for more details.
  961. X-- 
  962. X--      You should have received a copy of the GNU General Public License
  963. X--      along with this program;  if not, write to the Free Software
  964. X--      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  965. X--
  966. X-- LOG
  967. X--     $Log:    infer.c,v $
  968. X * Revision 1.1  90/07/21  11:06:32  dvadura
  969. X * Initial Revision Version 3.5
  970. X * 
  971. X*/
  972. X
  973. X#include "extern.h"
  974. X#include "alloc.h"
  975. X#include "db.h"
  976. X
  977. X/* attributes that get transfered from the % start cell to the inferred
  978. X * cells. */
  979. X
  980. X#define A_TRANSFER  (A_EPILOG  | A_PRECIOUS | A_SILENT |\
  981. X             A_LIBRARY | A_IGNORE   | A_PROLOG)
  982. X
  983. X/* Define local static functions */
  984. Xstatic DFALINKPTR _dfa_subset  ANSI((DFALINKPTR, DFASETPTR));
  985. Xstatic void       _free_dfas   ANSI((DFALINKPTR));
  986. Xstatic int      _count_dots  ANSI((char *));
  987. Xstatic char *      _build_name  ANSI((char *, char *, char *));
  988. X
  989. Xstatic int _prep = -1;    /* Integer value of Prep variable */
  990. Xstatic int _dmax;
  991. X
  992. XCELLPTR
  993. XInfer_recipe( cp, how, dfa_stack, setdirroot )/*
  994. X================================================
  995. X    Infer a set of rules for making a target.  We know we have a HOW
  996. X    cell attached, but it's prerequisite list may be NIL as is its
  997. X    recipe!  A NIL recipe is a prerequisite for calling this routine. */
  998. XCELLPTR    cp;
  999. XHOWPTR     how;
  1000. XDFASETPTR  dfa_stack;
  1001. XCELLPTR    setdirroot;
  1002. X{
  1003. X   DFALINKPTR    pdfa;
  1004. X   DFALINKPTR    dfas;
  1005. X   CELLPTR    infcell;
  1006. X   CELLPTR    meta;
  1007. X   DFASET    top_dfa_stack;
  1008. X   EDGEPTR      pedge;
  1009. X
  1010. X   DB_ENTER( "Infer_recipe" );
  1011. X   DB_PRINT( "inf", (">>> Infer for target [%s]", cp->CE_NAME) );
  1012. X   DB_PRINT( "mem", ("%s:-> mem %ld", cp->CE_NAME, (long)coreleft()));
  1013. X
  1014. X   /* If no further transitive closure on this cell then don't perform
  1015. X    * any more inferences */
  1016. X   if( cp->ce_attr & A_NOINFER ) DB_RETURN(NIL(CELL));
  1017. X   if( _prep == -1 ) _prep = atoi(Prep);  /* _dfa_subset needs _prep */
  1018. X
  1019. X   if( dfa_stack == NIL(DFASET) )
  1020. X      _dmax = _prep + _count_dots(cp->CE_NAME);
  1021. X
  1022. X   /* If none of the inference nodes match then forget about the inference.
  1023. X    * The user did not tell us how to make such a target.  We also stop the
  1024. X    * Inference if the new set of DFA's is a proper subset of a previous
  1025. X    * subset and it's PREP counts exceed the value of Prep.
  1026. X    */
  1027. X   dfas = _dfa_subset( Match_dfa(cp->CE_NAME), dfa_stack );
  1028. X
  1029. X#ifdef DBUG
  1030. X   { char      *tmp;
  1031. X     DFASETPTR ds;
  1032. X
  1033. X      tmp = _strdup("");
  1034. X      for( pdfa = dfas; pdfa != NIL(DFALINK); pdfa = pdfa->dl_next )
  1035. X         tmp = _strapp( tmp, pdfa->dl_meta->CE_NAME );
  1036. X
  1037. X      DB_PRINT( "inf", ("Working DFA subset [%s]", tmp) );
  1038. X      FREE( tmp );
  1039. X
  1040. X      tmp = _strdup( "{" );
  1041. X      for( ds = dfa_stack; ds != NIL(DFASET); ds = ds->df_next ) {
  1042. X     tmp = _strapp( tmp, "[" );
  1043. X     for( pdfa = ds->df_set; pdfa != NIL(DFALINK); pdfa = pdfa->dl_next )
  1044. X        tmp = _strapp( tmp, pdfa->dl_meta->CE_NAME );
  1045. X     tmp = _strapp( tmp, "]" );
  1046. X      }
  1047. X      tmp = _strapp( tmp, "}" );
  1048. X
  1049. X      DB_PRINT( "inf", ("DFA stack:  %s", tmp) );
  1050. X      FREE(tmp);
  1051. X   }
  1052. X#endif
  1053. X
  1054. X   if( dfas == NIL(DFALINK) ) {
  1055. X      DB_PRINT( "mem", ("%s:<- mem %ld",cp->CE_NAME, (long)coreleft()));
  1056. X      DB_PRINT( "inf", ("<<< Exit, no dfas, cp = %04x", NIL(CELL)) );
  1057. X      DB_RETURN( NIL(CELL) );
  1058. X   }
  1059. X
  1060. X
  1061. X   /* We have a set of %-meta's that have not previously been considered, or
  1062. X    * whose counts do not violate the Prep count.  So we should consider
  1063. X    * them, and put them on the top of the stack.
  1064. X    */
  1065. X   top_dfa_stack.df_set  = dfas;
  1066. X   top_dfa_stack.df_next = dfa_stack;
  1067. X
  1068. X
  1069. X   /* Run through the %-meta cells, build the prerequisite cells.  If we are
  1070. X    * performing transitive closure, then call Infer_recipe with the new
  1071. X    * prerequisite.
  1072. X    */
  1073. X   for( pdfa = dfas, infcell = NIL(CELL), pedge = NIL(EDGE);
  1074. X        pdfa != NIL(DFALINK);
  1075. X        pdfa = pdfa->dl_next ) {
  1076. X      int     push   = 0;
  1077. X      int     _trans = 0;
  1078. X      EDGEPTR edge;
  1079. X      EDGEPTR edge_noprq;    /* No prerequisite for this edge */
  1080. X
  1081. X      DB_PRINT( "inf", ("Using dfa:  [%s]", pdfa->dl_meta->CE_NAME) );
  1082. X      meta = pdfa->dl_meta;
  1083. X
  1084. X
  1085. X      /* Change to the required directory prior to checking the prerequisites
  1086. X       * Only if the meta has a directory and we haven't changed dir's
  1087. X       * for the CELL already.
  1088. X       *
  1089. X       * Ignore the %-meta if we had to change to a dir, and the dir
  1090. X       * did not exist.
  1091. X       */
  1092. X      if( !(cp->ce_attr & A_SETDIR) && meta->ce_dir != NIL(char) )
  1093. X     if( (setdirroot == NIL(CELL) || setdirroot->ce_dir != meta->ce_dir) &&
  1094. X         (push = Push_dir(meta, TRUE)) )
  1095. X        setdirroot = cp;
  1096. X     else {
  1097. X        DB_PRINT( "inf", ("Failed PUSH of [%s]", meta->ce_dir) );
  1098. X        continue;
  1099. X     }
  1100. X
  1101. X
  1102. X      /* Now run through the list of prerequisite edge's for the %-meta.
  1103. X       * Build each prerequisite in turn, and then see if it needs to be
  1104. X       * inferred.  We treat the edge that has NO prerequisites last, as
  1105. X       * it gives a recipe for making a %-meta from no prerequisites, and
  1106. X       * we should really check all NON-NULL prerequisites first.
  1107. X       */
  1108. X      edge = meta->CE_EDGES;
  1109. X      edge_noprq = NIL(EDGE);
  1110. X
  1111. X      do {
  1112. X         pedge = edge;
  1113. X
  1114. X     if( edge->ed_prq == NIL(CELL) )
  1115. X        edge_noprq = edge;
  1116. X     else {
  1117. X        HASHPTR  thp;    /* temporary hash table pointer        */
  1118. X        HASH     iprqh;    /* hash cell for new prerequisite    */
  1119. X        CELL     iprq;    /* inferred prerequisite to look for    */
  1120. X        CELLPTR  sdir;    /* local setdir root for inference    */
  1121. X        STRINGPTR sp   = NIL(STRING); /* pointer to rcp of inferred target*/
  1122. X        int      ipush = 0;          /* flag for push on inferred prereq */
  1123. X        char     *name = edge->ed_prq->CE_NAME;
  1124. X        int          _dmax_fix;
  1125. X
  1126. X        DB_PRINT( "inf", ("Trying edge from [%s] to [%s] for [%s]",
  1127. X                  meta->CE_NAME, name, cp->CE_NAME) );
  1128. X
  1129. X        _trans = Transitive &&
  1130. X             !((Glob_attr | edge->ed_prq->ce_attr) & A_NOINFER);
  1131. X
  1132. X        /* Set the temp CELL used for building prerequisite candidates to
  1133. X         * all zero so that we don't have to keep initializing all the
  1134. X         * fields. */
  1135. X        {
  1136. X           register char *s = (char *) &iprq;
  1137. X           register int   n = sizeof(CELL);
  1138. X           while( n ) { *s++ = '\0'; n--; }
  1139. X        }
  1140. X
  1141. X
  1142. X        /* Build the prerequisite name from the %-meta prerequisite given
  1143. X         * for the %-meta rule. */
  1144. X        iprqh.ht_name = _build_name( cp->CE_NAME, name, pdfa->dl_per );
  1145. X        if( strcmp(cp->CE_NAME, iprqh.ht_name) == 0 )
  1146. X           goto try_next_edge;
  1147. X        if((_dmax_fix = (_count_dots(name)-_count_dots(meta->CE_NAME))) < 0)
  1148. X           _dmax_fix = 0;
  1149. X        if( _count_dots(iprqh.ht_name) > _dmax + _dmax_fix )
  1150. X           goto try_next_edge;
  1151. X
  1152. X        DB_PRINT( "inf", ("Checking prerequisite [%s]", iprqh.ht_name) );
  1153. X
  1154. X        if( Verbose )
  1155. X           printf( "%s:  Trying prerequisite [%s] for [%s]\n", Pname,
  1156. X               iprqh.ht_name, cp->CE_NAME );
  1157. X
  1158. X
  1159. X        /* See if the prerequisite CELL has been previously defined.  If
  1160. X         * it has, then make a copy of it into iprq, and use it to try
  1161. X         * the inference.  We make the copy so that we don't modify the
  1162. X         * stat of the inferred cell if the inference fails.
  1163. X         */
  1164. X        thp = Get_name( iprqh.ht_name, Defs, FALSE, setdirroot );
  1165. X        if(thp != NIL(HASH)) {
  1166. X           iprq = *thp->CP_OWNR;
  1167. X           if( iprq.CE_HOW != NIL(HOW) ) sp = iprq.CE_HOW->hw_recipe;
  1168. X        }
  1169. X        else
  1170. X           iprq.ce_name  = &iprqh;
  1171. X
  1172. X
  1173. X        /* If the prerequisite has the .SETDIR attr set, then we
  1174. X         * should try to CD to the directory, if it is really different
  1175. X         * from the one we are currently in.  If the CD fails we ignore
  1176. X         * the edge and go try another edge.
  1177. X         */
  1178. X        sdir = setdirroot;
  1179. X        if( iprq.ce_dir != NIL(char) )
  1180. X           if( sdir==NIL(CELL) || sdir->ce_dir != iprq.ce_dir )
  1181. X              if( ipush = Push_dir(&iprq, TRUE) )
  1182. X             sdir = &iprq;
  1183. X          else
  1184. X             goto try_next_edge;
  1185. X
  1186. X
  1187. X        /* Stat the inferred prerequisite.
  1188. X         */
  1189. X        if( !(iprq.ce_flag & F_STAT) ) Stat_target( &iprq, FALSE );
  1190. X
  1191. X
  1192. X        /* If the STAT succeeded or if the prerequisite has a recipe for
  1193. X         * making it, then infer it.  We may later try to perform a
  1194. X         * second inference on this prerequisite when we actually go to
  1195. X         * make it.
  1196. X         */
  1197. X        if( (iprq.ce_time != (time_t)0L) || (sp != NIL(STRING)) ) {
  1198. X           infcell = Def_cell( iprqh.ht_name, setdirroot );
  1199. X           infcell->ce_flag |= F_REMOVE;
  1200. X        }
  1201. X        else
  1202. X           /* The STAT did not succeed, so call Infer_recipe recursively
  1203. X            * to see if we know how to make the prerequisite.  If it
  1204. X        * returns not NULL, then we have an inferred prerequisite
  1205. X        * and we should Define it and attach it to the CELL pointed at
  1206. X        * by cp.  This recursive inference is performed only if
  1207. X        * Transitive closure is enabled.
  1208. X        */
  1209. X           if( _trans ) {
  1210. X          int _save = _dmax;
  1211. X          if( !_dmax ) _dmax += _dmax_fix;
  1212. X          infcell = Infer_recipe( &iprq, iprq.CE_HOW, &top_dfa_stack,
  1213. X                      sdir);
  1214. X          _dmax = _save;
  1215. X
  1216. X          if( infcell != NIL(CELL) ) {
  1217. X             /* We found we can make the prerequisite, so make it into
  1218. X              * a real node.  This means, mark it for possible
  1219. X              * removal, and when you make it into a node make sure
  1220. X              * you don't clobber the Def_cell name.
  1221. X              */
  1222. X             infcell  = Def_cell( iprqh.ht_name, setdirroot );
  1223. X             thp      = infcell->ce_name;
  1224. X             *infcell = iprq;
  1225. X             infcell->ce_name = thp;
  1226. X             infcell->ce_flag |= F_REMOVE;
  1227. X              }
  1228. X           }
  1229. X
  1230. X        /* If we pushed a directory for the inferred prerequisite then
  1231. X         * pop it.
  1232. X         */
  1233. X        if( ipush ) Pop_dir(FALSE);
  1234. X
  1235. Xtry_next_edge:
  1236. X        FREE( iprqh.ht_name );
  1237. X     }
  1238. X
  1239. X     edge = edge->ed_next;
  1240. X      }
  1241. X      while( infcell == NIL(CELL) && edge != meta->CE_EDGES );
  1242. X
  1243. X
  1244. X      /* If none of the previous edges were any good, and there was an
  1245. X       * edge with no prerequsite, then use it.
  1246. X       */
  1247. X      if( infcell == NIL(CELL) ) 
  1248. X         if( edge_noprq != NIL(EDGE) ) 
  1249. X        pedge = edge_noprq;
  1250. X     else
  1251. X        pedge = NIL(EDGE);
  1252. X      else {
  1253. X     /* We have a match, so make the edge's pointer for the corresponding
  1254. X      * %-meta target point at the matched prerequisite so that the next
  1255. X      * time we perform an inference we will check this edge first.
  1256. X      */
  1257. X         meta->CE_EDGES = pedge;
  1258. X     if( !_trans ) infcell->ce_attr |= A_NOINFER;
  1259. X      }
  1260. X
  1261. X
  1262. X      /* If we pushed a dir when we treated this %-meta, then
  1263. X       * pop it.
  1264. X       */
  1265. X      if( push ) Pop_dir(FALSE);
  1266. X
  1267. X
  1268. X      /* Need this so that pdfa does not get advanced, and remains pointing
  1269. X       * to the dfa, that just resulted in a successful match.
  1270. X       */
  1271. X      if( pedge != NIL(EDGE) ) break;
  1272. X   }
  1273. X
  1274. X
  1275. X   /* If pedge is not NIL then we have found an edge and possibly inferred
  1276. X    * a prerequisite.  In any case we should definitely attach the recipe to
  1277. X    * the HOW node of the cell pointed at by cp.  If the CELL has no HOW node
  1278. X    * the we allocate one.
  1279. X    */
  1280. X   if( pedge != NIL(EDGE) ) {
  1281. X      LINKPTR lp;
  1282. X      HOWPTR  nhow, ihow;
  1283. X
  1284. X      DB_PRINT("inf", ("taking edge [%s] to [%s]", pedge->ed_tg->CE_NAME,
  1285. X           (pedge->ed_prq == NIL(CELL)) ? "(none)":pedge->ed_prq->CE_NAME));
  1286. X
  1287. X      if( Verbose )
  1288. X     printf("%s:  Inferred recipe using edge from [%s] to [%s]\n",
  1289. X        Pname, pedge->ed_tg->CE_NAME,
  1290. X        (pedge->ed_prq == NIL(CELL)) ? "(none)":pedge->ed_prq->CE_NAME);
  1291. X
  1292. X      if( how == NIL(HOW) ) {
  1293. X         /* Get a new HOW node, this should happen only for inferred
  1294. X      * cells, as such they have no prior HOW node */
  1295. X         TALLOC( how, 1, HOW );
  1296. X     cp->CE_HOW = how;
  1297. X      }
  1298. X      
  1299. X
  1300. X      /* Attach the recipe to the HOW node.  Note that if the %-meta recipe
  1301. X       * is a :: recipe then we will attach all of the HOW cells belonging to
  1302. X       * the %-meta :: rule that we matched to the CELL, and we will place
  1303. X       * them so that they preceed subsequent HOW cells in the list.  Under
  1304. SHAR_EOF
  1305. echo "End of part 15"
  1306. echo "File infer.c is continued in part 16"
  1307. echo "16" > s2_seq_.tmp
  1308. exit 0
  1309.  
  1310.