home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume27 / dmake / part31 < prev    next >
Encoding:
Text File  |  1992-01-29  |  39.9 KB  |  1,399 lines

  1. Newsgroups: comp.sources.misc
  2. From: dvadura@plg.waterloo.edu (Dennis Vadura)
  3. Subject:  v27i132:  dmake - dmake Version 3.8, Part31/41
  4. Message-ID: <1992Jan29.164636.1032@sparky.imd.sterling.com>
  5. X-Md4-Signature: 9073b9c38091d1bd459c7b08279c1d8c
  6. Date: Wed, 29 Jan 1992 16:46:36 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: dvadura@plg.waterloo.edu (Dennis Vadura)
  10. Posting-number: Volume 27, Issue 132
  11. Archive-name: dmake/part31
  12. Environment: Atari-ST, Coherent, Mac, MSDOS, OS/2, UNIX
  13. Supersedes: dmake: Volume 19, Issue 22-58
  14.  
  15. ---- Cut Here and feed the following to sh ----
  16. # this is dmake.shar.31 (part 31 of a multipart archive)
  17. # do not concatenate these parts, unpack them in order with /bin/sh
  18. # file dmake/rulparse.c continued
  19. #
  20. if test ! -r _shar_seq_.tmp; then
  21.     echo 'Please unpack part 1 first!'
  22.     exit 1
  23. fi
  24. (read Scheck
  25.  if test "$Scheck" != 31; then
  26.     echo Please unpack part "$Scheck" next!
  27.     exit 1
  28.  else
  29.     exit 0
  30.  fi
  31. ) < _shar_seq_.tmp || exit 1
  32. if test -f _shar_wnt_.tmp; then
  33. sed 's/^X//' << 'SHAR_EOF' >> 'dmake/rulparse.c' &&
  34. {
  35. X   int res = (*_strspn(list,"@-%+ \t") == '[');
  36. X   if( res ) _sv_attr |= Rcp_attribute(list);
  37. X   return(res);
  38. }
  39. X
  40. X
  41. static void
  42. _do_special( special, op, attr, set_dir, target, prereq, state )/*
  43. ==================================================================
  44. X   Process a special target.  So far the only special targets we have
  45. X   are those recognized by the _is_special function.
  46. X
  47. X   target is always only a single special target.
  48. X   
  49. X   NOTE:  For the cases of .IMPORT, and .INCLUDE, the cells created by the
  50. X         parser are never freed.  This is due to the fact that it is too much
  51. X      trouble to get them out of the hash table once they are defined, and
  52. X      if they are per chance used again it will be ok, anyway, since the
  53. X      cell is not really used by the code below.  */
  54. X
  55. int    special;
  56. int    op;
  57. t_attr    attr;
  58. char    *set_dir;
  59. CELLPTR target;
  60. CELLPTR prereq;
  61. int     *state;
  62. {
  63. X   HASHPTR    hp;        /* pointer to macro def cell        */
  64. X   CELLPTR    cp;        /* temporary pointer into cells list    */
  65. X   CELLPTR     dp;        /* pointer to directory dir cell    */
  66. X   LINKPTR     lp;        /* pointer at prerequisite list     */
  67. X   char        *dir;        /* current dir to prepend        */
  68. X   char        *path;        /* resulting path to try to read    */
  69. X   char     *name;        /* File name for processing a .INCLUDE    */
  70. X   char        *tmp;        /* temporary string pointer        */
  71. X   FILE     *fil;        /* File descriptor returned by Openfile    */
  72. X
  73. X   DB_ENTER( "_do_special" );
  74. X
  75. X   target->ce_flag = F_SPECIAL;    /* mark the target as special */
  76. X
  77. X   switch( special ) {
  78. X      case ST_EXPORT:
  79. X     for( ; prereq != NIL(CELL); prereq = prereq->ce_link ) {
  80. X        DB_PRINT( "par", ("Exporting [%s]", prereq->CE_NAME) );
  81. X        hp = GET_MACRO( prereq->CE_NAME );
  82. X
  83. X        if( hp != NIL(HASH) ) {
  84. X           char *tmpstr = hp->ht_value;
  85. X
  86. X           if( tmpstr == NIL(char) ) tmpstr = "";
  87. X
  88. X           if( Write_env_string( prereq->CE_NAME, tmpstr ) != 0 )
  89. X          Warning( "Could not export %s", prereq->CE_NAME );
  90. X        }
  91. X     }
  92. X     break;
  93. X
  94. X      case ST_IMPORT:
  95. X     for( ; prereq != NIL(CELL); prereq = prereq->ce_link ) {
  96. X        char *tmpstr;
  97. X
  98. X        DB_PRINT( "par", ("Importing [%s]", prereq->CE_NAME) );
  99. X
  100. X        if( strcmp(prereq->CE_NAME, ".EVERYTHING") == 0 ) {
  101. X           t_attr sattr = Glob_attr;
  102. X           Glob_attr |= A_SILENT;
  103. X
  104. X           ReadEnvironment();
  105. X
  106. X           Glob_attr = sattr;
  107. X        }
  108. X        else {
  109. X           tmpstr = Read_env_string( prereq->CE_NAME );
  110. X
  111. X           if( tmpstr != NIL(char) )
  112. X          Def_macro( prereq->CE_NAME,tmpstr,M_EXPANDED | M_LITERAL);
  113. X           else
  114. X          if( !((Glob_attr | attr) & A_IGNORE) )
  115. X             Fatal("Imported macro `%s' not found",prereq->CE_NAME);
  116. X        }
  117. X     }
  118. X
  119. X     attr &= ~A_IGNORE;
  120. X     break;
  121. X
  122. X      case ST_INCLUDE:
  123. X      {
  124. X     int ignore     = (((Glob_attr | attr) & A_IGNORE) != 0);
  125. X     int pushed     = FALSE;
  126. X     LINKPTR prqlnk = NIL(LINK);
  127. X     LINKPTR prqlst = NIL(LINK);
  128. X
  129. X     if( prereq == NIL(CELL) )  Fatal( "No .INCLUDE file(s) specified" );
  130. X
  131. X     dp = Def_cell( ".INCLUDEDIRS" );
  132. X
  133. X     if( (attr & A_SETDIR) && *(dir = strchr(set_dir, '=')+1) )
  134. X        pushed = Push_dir( dir, ".INCLUDE", ignore );
  135. X
  136. X     for( cp=prereq; cp != NIL(CELL); cp = cp->ce_link ) {
  137. X        LINKPTR ltmp;
  138. X        TALLOC(ltmp, 1, LINK);
  139. X        ltmp->cl_prq = cp;
  140. X
  141. X        if( prqlnk == NIL(LINK) )
  142. X           prqlst = ltmp;
  143. X        else
  144. X           prqlnk->cl_next = ltmp;
  145. X
  146. X        prqlnk = ltmp;
  147. X     }
  148. X
  149. X     for( ; prqlst != NIL(LINK); FREE(prqlst), prqlst=prqlnk ) {
  150. X        prqlnk = prqlst->cl_next;
  151. X        cp     = prqlst->cl_prq;
  152. X        name   = cp->CE_NAME;
  153. X        
  154. X        if( *name == '<' ) {
  155. X           /* We have a file name enclosed in <....>
  156. X            * so get rid of the <> arround the file name */
  157. X
  158. X           name++;
  159. X           if( (tmp = strrchr( name, '>' )) != NIL( char ) )
  160. X          *tmp = 0;
  161. X
  162. X           if( If_root_path( name ) )
  163. X              fil = Openfile( name, FALSE, FALSE );
  164. X           else
  165. X          fil = NIL(FILE);
  166. X        }
  167. X        else
  168. X           fil = Openfile( name, FALSE, FALSE );
  169. X           
  170. X        if( fil == NIL(FILE) ) {    /*if true ==> not found in current dir*/
  171. X           /* Now we must scan the list of prerequisites for .INCLUDEDIRS
  172. X            * looking for the file in each of the specified directories.
  173. X        * if we don't find it then we issue an error.  The error
  174. X        * message is suppressed if the .IGNORE attribute of attr is
  175. X        * set.  If a file is found we call Parse on the file to
  176. X        * perform the parse and then continue on from where we left
  177. X        * off.  */
  178. X
  179. X           for(lp=dp->CE_PRQ; lp && fil == NIL(FILE); lp=lp->cl_next) {
  180. X          dir  = lp->cl_prq->CE_NAME;
  181. X          if( strchr(dir, '$') ) dir = Expand(dir);
  182. X          path = Build_path( dir, name );
  183. X
  184. X          DB_PRINT( "par", ("Trying to include [%s]", path) );
  185. X
  186. X          fil = Openfile( path, FALSE, FALSE );
  187. X          if( dir != lp->cl_prq->CE_NAME ) FREE(dir);
  188. X           }
  189. X        }
  190. X
  191. X        if( fil != NIL(FILE) )
  192. X           Parse( fil );
  193. X        else if( !((Glob_attr | attr) & A_IGNORE) )
  194. X           Fatal( "Include file %s, not found", name );
  195. X     }
  196. X
  197. X     if( pushed ) Pop_dir(FALSE);
  198. X     attr &= ~(A_IGNORE|A_SETDIR);
  199. X      }
  200. X      break;
  201. X     
  202. X      case ST_SOURCE:
  203. X      /* case ST_SUFFIXES: */
  204. X           if( prereq != NIL(CELL) )
  205. X        _do_targets( op & (R_OP_CL | R_OP_MI | R_OP_UP), attr, set_dir,
  206. X             target, prereq );
  207. X     else {
  208. X        /* The old semantics of .SOURCE were that an empty list of
  209. X         * prerequisites clears the .SOURCE list.  So we must implement
  210. X         * that here as a clearout prerequisite operation.  Since this is
  211. X         * a standard operation with the :- opcode we can simply call the
  212. X         * proper routine with the target cell and it should do the trick
  213. X         */
  214. X
  215. X        if( op == R_OP_CL || (op & R_OP_MI) )
  216. X           Clear_prerequisites( target );
  217. X     }
  218. X
  219. X     op &= ~(R_OP_MI | R_OP_UP);
  220. X     break;
  221. X
  222. X      case ST_KEEP:
  223. X     if( Keep_state != NIL(char) ) break;
  224. X     Def_macro( ".KEEP_STATE", "_state.mk", M_EXPANDED );
  225. X     break;
  226. X
  227. X      case ST_REST:
  228. X         /* The rest of the special targets can all take rules, as such they
  229. X      * must be able to affect the state of the parser. */
  230. X
  231. X     {
  232. X        int s_targ = Target;
  233. X
  234. X        Target     = TRUE;
  235. X        _sp_target = TRUE;
  236. X        *state     = _do_targets( op, attr, set_dir, target, prereq );
  237. X        Target     = s_targ;
  238. X
  239. X        target->ce_flag |= F_TARGET;
  240. X
  241. X        attr    = A_DEFAULT;
  242. X        op      = R_OP_CL;
  243. X     }
  244. X     break;
  245. X
  246. X      default:break;
  247. X   }
  248. X      
  249. X   if( op   != R_OP_CL   ) Warning( "Modifier(s) for operator ignored" );
  250. X   if( attr != A_DEFAULT ) Warning( "Extra attributes ignored" );
  251. X
  252. X   DB_VOID_RETURN;
  253. }
  254. X
  255. X
  256. X
  257. static int
  258. _do_targets( op, attr, set_dir, targets, prereq )/*
  259. ================================================= */
  260. int    op;
  261. t_attr    attr;
  262. char    *set_dir;
  263. CELLPTR targets;
  264. CELLPTR prereq;
  265. {
  266. X   CELLPTR    tg1;        /* temporary target pointer        */
  267. X   CELLPTR    tp1;        /* temporary prerequisite pointer    */
  268. X   char        *p;        /* temporary char pointer        */
  269. X   CELLPTR      prev_cell;    /* pointer for .UPDATEALL processing    */
  270. X   CELLPTR      first_cell;    /* pointer for .UPDATEALL processing    */
  271. X   int        update;        /* A_UPDATEALL attribute flag        */
  272. X   int        smagic = 0;    /* collective amount of magic :-)    */
  273. X   int          tflag = FALSE;    /* set to TRUE if we add target to root */
  274. X
  275. X   DB_ENTER( "_do_targets" );
  276. X
  277. X   if( update = ((attr & A_UPDATEALL) != 0) )
  278. X      if( targets == NIL(CELL) )
  279. X     Fatal( ".UPDATEALL attribute requires non-empty list of targets" );
  280. X
  281. X   first_cell = prev_cell = NIL(CELL);
  282. X   for( tg1 = targets; tg1 != NIL(CELL); tg1 = tg1->ce_link ) {
  283. X      /* Check each target.  Check for inconsistencies between :: and : rule
  284. X       * sets.  :: may follow either : or :: but not the reverse.
  285. X       *
  286. X       * Any targets that contain :: rules are represented by a prerequisite
  287. X       * list hanging off the main target cell where each of the prerequisites
  288. X       * is a copy of the target cell but is not entered into the hash table.
  289. X       */
  290. X      int magic  = (tg1->ce_flag & F_PERCENT) && !(tg1->ce_flag & F_MAGIC);
  291. X      smagic |= magic;
  292. X
  293. X      if( !(op & R_OP_DCL ) && (tg1->ce_flag & F_MULTI) && !magic )
  294. X     Fatal( "Inconsistency in inference rules for %s", tg1->CE_NAME );
  295. X
  296. X      if( magic )
  297. X         do {
  298. X        _build_graph( op, tg1, prereq );
  299. X        if( prereq != NIL(CELL) ) prereq = prereq->ce_link;
  300. X     } while( prereq != NIL(CELL) );
  301. X      else if( !(tg1->ce_flag & F_SPECIAL) && 
  302. X        (prereq == NIL(CELL)) &&
  303. X        (p = _is_magic( tg1->CE_NAME )) != NIL(char))
  304. X         smagic |= _do_magic( op, p, tg1, prereq, attr, set_dir );
  305. X      else if( op & R_OP_DCL ) {
  306. X     CELLPTR tmp_cell = _make_multi(tg1);
  307. X     tflag |= _add_root(tg1);
  308. X     targets = _replace_cell( targets, tg1, tmp_cell );
  309. X     tg1 = tmp_cell;
  310. X      }
  311. X
  312. X      if( !magic ) _set_attributes( attr, set_dir, tg1 );
  313. X
  314. X      if( update ) {
  315. X     if( smagic ) Fatal( ".UPDATEALL attribute not legal in meta rule" );
  316. X
  317. X     /* Check this as it would break another circular .UPATEALL list if
  318. X      * we blindly assign it and it is part of another list already. */
  319. X     if( tg1->ce_all != NIL(CELL) )
  320. X        Fatal( "Target [%s] appears on multiple .UPDATEALL lists" );
  321. X
  322. X     tg1->ce_all = prev_cell;
  323. X     if( prev_cell == NIL(CELL) ) first_cell = tg1;
  324. X     prev_cell = tg1;
  325. X      }
  326. X
  327. X      /* Build the proper prerequisite list of the target.  If the `-',
  328. X       * modifier was used clear the prerequisite list before adding any
  329. X       * new prerequisites.  Else add them to the head/tail as appropriate.
  330. X       *
  331. X       * If the target has F_PERCENT set then no prerequisites are used. */
  332. X
  333. X      if( !(tg1->ce_flag & F_PERCENT) ) {
  334. X     if( op & R_OP_MI ) Clear_prerequisites( tg1 );
  335. X
  336. X     if( (op & R_OP_UP) && (tg1->ce_prq != NIL(LINK)) )
  337. X        _stick_at_head( tg1, prereq );
  338. X     else for( tp1=prereq; tp1 != NIL(CELL); tp1 = tp1->ce_link )
  339. X        Add_prerequisite( tg1, tp1, FALSE, FALSE );
  340. X      }
  341. X      else if( op & (R_OP_MI | R_OP_UP) )
  342. X     Warning( "Modifier(s) `^!' for %-meta target ignored" );
  343. X   }
  344. X
  345. X   if( tflag ) Target = TRUE;
  346. X   if( first_cell != NIL(CELL) ) first_cell->ce_all = prev_cell;
  347. X
  348. X
  349. X   /* Check to see if we have NO targets but some attributes.  IF so then
  350. X    * apply all of the attributes to the complete list of prerequisites.
  351. X    * Cannot happen for F_PERCENT targets. (ie. in that case targets is always
  352. X    * not NIL) */
  353. X
  354. X   if( (targets == NIL(CELL)) && attr )
  355. X      if( prereq != NIL(CELL) )
  356. X     for( tp1=prereq; tp1 != NIL(CELL); tp1 = tp1->ce_link )
  357. X        _set_attributes( attr, set_dir, tp1 );
  358. X      else
  359. X     _set_global_attr( attr );
  360. X
  361. X   /* Fix up the ce_link pointers so that when we go to attach a recipe in
  362. X    * Bind_targets to rules we get the right thing if it's an .UPDATEALL ::
  363. X    * recipe */
  364. X   if( update ) {
  365. X      for( tp1=NIL(CELL),tg1=prev_cell; tg1!=first_cell; tg1=tg1->ce_all ) {
  366. X     tg1->ce_link = tp1;
  367. X     tp1 = tg1;
  368. X      }
  369. X      tg1->ce_link = tp1;
  370. X      targets = first_cell;
  371. X   }
  372. X
  373. X   /* Now that we have built the lists of targets, the parser must parse the
  374. X    * rules if there are any.  However we must start the rule list with the
  375. X    * rule specified as via the ; kludge, if there is one */
  376. X   _sv_targets = targets;
  377. X   _sv_attr    = attr;
  378. X   _sv_flag    = ((op & R_OP_BG) ? F_SINGLE : F_DEFAULT);
  379. X      
  380. X   DB_RETURN( RULE_SCAN );
  381. }
  382. X
  383. X
  384. static int
  385. _do_magic( op, dot, target, prereq, attr, set_dir )/*
  386. =====================================================
  387. X   This function takes a magic target of the form .<chars>.<chars> or
  388. X   .<chars> and builds the appropriate % rules for that target.
  389. X   
  390. X   The function builds the % rule, `%.o : %.c'  from .c.o, and
  391. X   `%.a :' from .a */
  392. X
  393. int    op;
  394. char    *dot;
  395. CELLPTR target;
  396. CELLPTR prereq;
  397. t_attr  attr;
  398. char    *set_dir;
  399. {
  400. X   CELLPTR tg;
  401. X   CELLPTR prq;
  402. X   char    *tmp, *tmp2;
  403. X
  404. X   DB_ENTER( "_do_magic" );
  405. X
  406. X   if( prereq != NIL(CELL) )
  407. X      Warning( "Ignoring prerequisites of old style meta-target" );
  408. X
  409. X   if( dot == target->CE_NAME )    {        /* its of the form .a    */
  410. X      tg  = Def_cell( "%" );            /* ==> no prerequisite  */
  411. X      tmp = _build_meta( target->CE_NAME );
  412. X      prq = Def_cell( tmp );
  413. X      FREE( tmp );
  414. X
  415. X      _build_graph( op, tg, prq );
  416. X   }
  417. X   else {
  418. X      tmp = _build_meta( dot );
  419. X      tg  = Def_cell( tmp );
  420. X      FREE( tmp );
  421. X
  422. X      tmp = _build_meta( tmp2 = _substr( target->CE_NAME, dot ) );
  423. X      prq = Def_cell( tmp );
  424. X      FREE( tmp  );
  425. X      FREE( tmp2 );
  426. X
  427. X      _build_graph( op, tg, prq );
  428. X   }
  429. X
  430. X   tg->ce_flag      |= F_PERCENT;
  431. X   target->ce_flag  |= (F_MAGIC|F_PERCENT);
  432. X
  433. X   _set_attributes( attr, set_dir, tg );
  434. X
  435. X   DB_RETURN(1);
  436. }
  437. X
  438. X
  439. static CELLPTR
  440. _replace_cell( lst, cell, rep )
  441. CELLPTR lst;
  442. CELLPTR cell;
  443. CELLPTR rep;
  444. {
  445. X   register CELLPTR tp;
  446. X   
  447. X   if( lst == cell ) {
  448. X      rep->ce_link = lst->ce_link;
  449. X      lst = rep;
  450. X   }
  451. X   else {
  452. X      for( tp=lst; tp->ce_link != cell; tp=tp->ce_link );
  453. X      rep->ce_link = tp->ce_link->ce_link;
  454. X      tp->ce_link = rep;
  455. X   }
  456. X
  457. X   return(lst);
  458. }
  459. X
  460. X
  461. static char *
  462. _build_meta( name )/*
  463. =====================
  464. X   Check to see if the name is of the form .c~ if so and if Augmake
  465. X   translation is enabled then return s.%.c, else return %.suff, where if the
  466. X   suffix ends in '~' then leave it be.*/
  467. char *name;
  468. {
  469. X   char *tmp;
  470. X   int  test = Augmake ? name[strlen(name)-1] == '~' : 0;
  471. X
  472. X   tmp = _strjoin( test ? "s.%" : "%", name, -1, FALSE);
  473. X   if( test ) tmp[ strlen(tmp)-1 ] = '\0';
  474. X
  475. X   return(tmp);
  476. }
  477. X
  478. X
  479. X
  480. static void
  481. _build_graph( op, target, prereq )/*
  482. ====================================
  483. X   This function is called to build the graph for the % rule given by
  484. X   target : prereq cell combination.  This function assumes that target
  485. X   is a % target and that prereq is a single % prerequisite.  R_OP_CL
  486. X   rules replace existing rules if any, only R_OP_CL works for meta-rules.
  487. X   %.o :: %.c is meaningless. 
  488. X   
  489. X   It also assumes that target cell has F_PERCENT set already. */
  490. int op;
  491. CELLPTR target;
  492. CELLPTR prereq;
  493. {
  494. X   LINKPTR edl;
  495. X   CELLPTR edge;
  496. X   int match;
  497. X
  498. X   DB_ENTER( "_build_graph" );
  499. X   DB_PRINT( "%", ("Building graph for [%s : %s]", target->CE_NAME,
  500. X            (prereq == NIL(CELL)) ? "" : prereq->CE_NAME) );
  501. X
  502. X   if( prereq != NIL(CELL) ) {
  503. X      char *name = prereq->CE_NAME;
  504. X      int   len  = strlen(name);
  505. X
  506. X      if( *name == '\'' && name[len-1]=='\'' ){
  507. X     _add_global_prereq( prereq );
  508. X     name[len-1] = '\0';
  509. X     strcpy(name, name+1);
  510. X     DB_VOID_RETURN;
  511. X      }
  512. X   }
  513. X
  514. X   /* Search the list of prerequisites for the current target and see if
  515. X    * any of them match the current %-meta : prereq pair.  NOTE that %-metas
  516. X    * are built as if they were F_MULTI targets. */
  517. X
  518. X   match = FALSE;
  519. X   for( edl=target->ce_prq; edl != NIL(LINK); edl=edl->cl_next ) {
  520. X      edge = edl->cl_prq;
  521. X
  522. X      DB_PRINT( "%", ("Trying to match [%s]", edge?edge->CE_NAME:"(nil)") );
  523. X
  524. X      if(    (!edge->ce_prq && !prereq)
  525. X      || (   edge->ce_prq
  526. X          && edge->ce_prq->cl_prq == prereq
  527. X          && (   edge->ce_dir == _sv_setdir
  528. X          || (   edge->ce_dir
  529. X              && _sv_setdir
  530. X              && !strcmp(edge->ce_dir,strchr(_sv_setdir,'=')+1)
  531. X             )
  532. X         )
  533. X         )
  534. X    ) {
  535. X     match = TRUE;
  536. X     break;
  537. X      }
  538. X   }
  539. X
  540. X   if( match ) {
  541. X      /* match is TRUE hence, we found an edge joining the target and the
  542. X       * prerequisite so reset the new edge's how values to reflect the new
  543. X       * recipe etc. */
  544. X      DB_PRINT( "%", ("It's an old edge") );
  545. X
  546. X      edge->ce_dir    = NIL(char);
  547. X      edge->ce_flag  &= (F_PERCENT|F_MAGIC|F_DFA);
  548. X      edge->ce_attr  &= A_NOINFER;
  549. X   }
  550. X   else {
  551. X      DB_PRINT( "%", ("Adding a new edge") );
  552. X
  553. X      if( !(target->ce_flag & F_DFA) ) {
  554. X     Add_nfa( target->CE_NAME );
  555. X     target->ce_flag |= F_DFA;
  556. X      }
  557. X      edge = _make_multi(target);
  558. X      if( prereq ) Add_prerequisite(edge, prereq, FALSE, TRUE);
  559. X   }
  560. X
  561. X   if( op & R_OP_DCL )
  562. X   Warning( "'::' operator for meta-target '%s' ignored, ':' operator assumed.",
  563. X           target->CE_NAME );
  564. X
  565. X   edge->ce_link = _sv_edgel;
  566. X   _sv_edgel = edge;
  567. X   _sv_globprq_only = 0;
  568. X
  569. X   DB_VOID_RETURN;
  570. }
  571. X
  572. X
  573. static CELLPTR
  574. _make_multi( tg )
  575. CELLPTR tg;
  576. {
  577. X   CELLPTR cp;
  578. X
  579. X   /* This first handle the case when a : foo ; exists prior to seeing
  580. X    * a :: fee; */
  581. X   if( !(tg->ce_flag & F_MULTI) && (tg->ce_prq || tg->ce_recipe) ) {
  582. X      TALLOC(cp, 1, CELL);
  583. X      *cp = *tg;
  584. X
  585. X      tg->ce_prq    = NIL(LINK);
  586. X      tg->ce_flag  |= F_RULES|F_MULTI|F_TARGET;
  587. X      tg->ce_attr  |= A_SEQ;
  588. X      tg->ce_recipe = NIL(STRING);
  589. X      tg->ce_dir    = NIL(char);
  590. X      cp->ce_count  = ++tg->ce_index;
  591. X
  592. X      Add_prerequisite(tg, cp, FALSE, TRUE);
  593. X   }
  594. X
  595. X   TALLOC(cp, 1, CELL);
  596. X   *cp = *tg;
  597. X
  598. X   if( !(tg->ce_flag & F_MULTI) ) {
  599. X      tg->ce_prq    = NIL(LINK);
  600. X      tg->ce_flag  |= F_RULES|F_MULTI|F_TARGET;
  601. X      tg->ce_attr  |= A_SEQ;
  602. X      tg->ce_recipe = NIL(STRING);
  603. X      tg->ce_dir    = NIL(char);
  604. X   }
  605. X   else {
  606. X      cp->ce_flag  &= ~(F_RULES|F_MULTI);
  607. X      cp->ce_attr  &= ~A_SEQ;
  608. X      cp->ce_prq    = NIL(LINK);
  609. X      cp->ce_index  = 0;
  610. X   }
  611. X   cp->ce_count = ++tg->ce_index;
  612. X   cp->ce_flag |= F_TARGET;
  613. X
  614. X   Add_prerequisite(tg, cp, FALSE, TRUE);
  615. X   return(cp);
  616. }
  617. X
  618. X
  619. static void
  620. _add_global_prereq( pq )/*
  621. ==========================
  622. X    Prerequisite is a non-% prerequisite for a %-rule target, add it to
  623. X    the target's list of global prerequsites to add on match */
  624. CELLPTR pq;
  625. {
  626. X   register LINKPTR ln;
  627. X
  628. X   TALLOC( ln, 1, LINK );
  629. X   ln->cl_next = _sv_glb_prq;
  630. X   ln->cl_prq  = pq;
  631. X   _sv_glb_prq = ln;
  632. }
  633. X
  634. X
  635. X
  636. static void
  637. _set_attributes( attr, set_dir, cp )/*
  638. ======================================
  639. X    Set the appropriate attributes for a cell */
  640. t_attr    attr;
  641. char    *set_dir;
  642. CELLPTR cp;
  643. {
  644. X   char   *dir;
  645. X
  646. X   DB_ENTER( "_set_attributes" );
  647. X
  648. X   /* If .SETDIR attribute is set then we have at least .SETDIR= in the
  649. X    * set_dir string.  So go and fishout what is at the end of the =.
  650. X    * If not set and not NULL then propagate it to the target cell. */
  651. X
  652. X   if( attr & A_SETDIR ) {
  653. X      dir = strchr( set_dir, '=' ) + 1;
  654. X
  655. X      if( cp->ce_dir )
  656. X     Warning( "Multiple .SETDIR for %s ignored", cp->CE_NAME );
  657. X      else
  658. X     if( *dir ) cp->ce_dir = _strdup(dir);
  659. X   }
  660. X   cp->ce_attr |= attr;        /* set rest of attributes for target */
  661. X
  662. X   DB_VOID_RETURN;
  663. }
  664. X
  665. X
  666. X
  667. static void
  668. _set_global_attr( attr )/*
  669. ==========================
  670. X    Handle the setting of the global attribute functions based on
  671. X    The attribute flags set in attr. */
  672. t_attr attr;
  673. {
  674. X   t_attr flag;
  675. X
  676. X   /* Some compilers can't handle a switch on a long, and t_attr is now a long
  677. X    * integer on some systems.  foey! */
  678. X   for( flag = MAX_ATTR; flag; flag >>= 1 )
  679. X      if( flag & attr )
  680. X     if( flag == A_PRECIOUS)      Def_macro(".PRECIOUS",  "y", M_EXPANDED);
  681. X     else if( flag == A_SILENT)   Def_macro(".SILENT",    "y", M_EXPANDED);
  682. X     else if( flag == A_IGNORE )  Def_macro(".IGNORE",    "y", M_EXPANDED);
  683. X     else if( flag == A_EPILOG )  Def_macro(".EPILOG",    "y", M_EXPANDED);
  684. X     else if( flag == A_PROLOG )  Def_macro(".PROLOG",    "y", M_EXPANDED);
  685. X     else if( flag == A_NOINFER ) Def_macro(".NOINFER",   "y", M_EXPANDED);
  686. X     else if( flag == A_SEQ )     Def_macro(".SEQUENTIAL","y", M_EXPANDED);
  687. X     else if( flag == A_SHELL )   Def_macro(".USESHELL",  "y", M_EXPANDED);
  688. X     else if( flag == A_MKSARGS ) Def_macro(".MKSARGS",   "y", M_EXPANDED);
  689. X     else if( flag == A_SWAP )    Def_macro(".SWAP",      "y", M_EXPANDED);
  690. X
  691. X   attr &= ~A_GLOB;
  692. X   if( attr ) Warning( "Non global attribute(s) ignored" );
  693. }
  694. X
  695. X
  696. X
  697. static void
  698. _stick_at_head( cp, pq )/*
  699. ==========================
  700. X    Add the prerequisite list to the head of the existing prerequisite
  701. X    list */
  702. X
  703. CELLPTR cp;          /* cell for target node    */
  704. CELLPTR pq;        /* list of prerequisites to add */
  705. {
  706. X   DB_ENTER( "_stick_at_head" );
  707. X
  708. X   if( pq->ce_link != NIL(CELL) ) _stick_at_head( cp, pq->ce_link );
  709. X   Add_prerequisite( cp, pq, TRUE, FALSE );
  710. X
  711. X   DB_VOID_RETURN;
  712. }
  713. X
  714. X
  715. X
  716. static t_attr
  717. _is_attribute( name )/*
  718. =======================
  719. X   Check the passed name against the list of valid attributes and return the
  720. X   attribute index if it is, else return 0, indicating the name is not a valid
  721. X   attribute.  The present attributes are defined in dmake.h as A_xxx #defines,
  722. X   with the corresponding makefile specification:  (note they must be named
  723. X   exactly as defined below)
  724. X   
  725. X   Valid attributes are:  .IGNORE, .SETDIR=, .SILENT, .PRECIOUS, .LIBRARY,
  726. X                          .EPILOG, .PROLOG,  .LIBRARYM, .SYMBOL, .UPDATEALL,
  727. X              .USESHELL, .NOINFER, .PHONY, .SWAP, .SEQUENTIAL
  728. X              .NOSTATE,  .MKSARGS
  729. X
  730. X   NOTE:  The strcmp's are OK since at most three are ever executed for any
  731. X          one attribute check, and that happens only when we can be fairly
  732. X          certain we have an attribute.  */
  733. char *name;
  734. {
  735. X   t_attr attr = 0;
  736. X   
  737. X   DB_ENTER( "_is_attribute" );
  738. X   
  739. X   if( *name++ == '.' )
  740. X      switch( *name )
  741. X      {
  742. X         case 'E': attr = (strcmp(name, "EPILOG"))   ? 0 : A_EPILOG;  break;
  743. X         case 'I': attr = (strcmp(name, "IGNORE"))   ? 0 : A_IGNORE;  break;
  744. X         case 'L': attr = (strcmp(name, "LIBRARY"))  ? 0 : A_LIBRARY; break;
  745. X         case 'M': attr = (strcmp(name, "MKSARGS"))  ? 0 : A_MKSARGS; break;
  746. X
  747. X         case 'N':
  748. X        if( !strcmp(name, "NOINFER") )      attr = A_NOINFER;
  749. X        else if( !strcmp(name, "NOSTATE"))  attr = A_NOSTATE;
  750. X        else attr = 0;
  751. X        break;
  752. X
  753. X         case 'U':
  754. X        if( !strcmp(name, "UPDATEALL") )    attr = A_UPDATEALL;
  755. X        else if( !strcmp(name, "USESHELL")) attr = A_SHELL;
  756. X        else attr = 0;
  757. X        break;
  758. X
  759. X         case 'P':
  760. X            if( !strcmp(name, "PRECIOUS") )     attr = A_PRECIOUS;
  761. X            else if( !strcmp(name, "PROLOG") )  attr = A_PROLOG;
  762. X            else if( !strcmp(name, "PHONY") )   attr = A_PHONY;
  763. X            else attr = 0;
  764. X            break;
  765. X
  766. X         case 'S':
  767. X            if( !strncmp(name, "SETDIR=", 7) )    attr = A_SETDIR;
  768. X            else if( !strcmp(name, "SILENT") )    attr = A_SILENT;
  769. X            else if( !strcmp(name, "SYMBOL") )    attr = A_SYMBOL;
  770. X            else if( !strcmp(name, "SEQUENTIAL")) attr = A_SEQ;
  771. X            else if( !strcmp(name, "SWAP"))       attr = A_SWAP;
  772. X            else attr = 0;
  773. X            break;
  774. X      }
  775. X
  776. X   DB_RETURN( attr );
  777. }
  778. X
  779. X
  780. X
  781. static int
  782. _is_special( tg )/*
  783. ===================
  784. X   This function returns TRUE if the name passed in represents a special
  785. X   target, otherwise it returns false.  A special target is one that has
  786. X   a special meaning to dmake, and may require processing at the time that
  787. X   it is parsed.
  788. X   
  789. X   Current Special targets are:
  790. X    .GROUPPROLOG    .GROUPEPILOG    .INCLUDE    .IMPORT
  791. X    .EXPORT        .SOURCE     .SUFFIXES    .ERROR
  792. X    .INCLUDEDIRS    .MAKEFILES    .REMOVE        .KEEP_STATE
  793. */
  794. char *tg;
  795. {
  796. X   DB_ENTER( "_is_special" );
  797. X   
  798. X   if( *tg++ != '.' ) DB_RETURN( 0 );
  799. X   
  800. X   switch( *tg )
  801. X   {
  802. X      case 'I':
  803. X         if( !strcmp( tg, "IMPORT" ) )        DB_RETURN( ST_IMPORT   );
  804. X         else if( !strcmp( tg, "INCLUDE" ) )    DB_RETURN( ST_INCLUDE  );
  805. X     else if( !strcmp( tg, "INCLUDEDIRS" )) DB_RETURN( ST_REST     );
  806. X     break;
  807. X      
  808. X      case 'M':
  809. X         if( !strcmp( tg, "MAKEFILES" ) )    DB_RETURN( ST_REST     );
  810. X     break;
  811. X
  812. X      case 'E':
  813. X         if( !strcmp( tg, "ERROR" ) )        DB_RETURN( ST_REST     );
  814. X         else if( !strcmp( tg, "EXPORT" ) )    DB_RETURN( ST_EXPORT   );
  815. X     break;
  816. X
  817. X      case 'G':
  818. X     if( !strcmp( tg, "GROUPPROLOG" ))      DB_RETURN( ST_REST     );
  819. X     else if( !strcmp( tg, "GROUPEPILOG" )) DB_RETURN( ST_REST     );
  820. X     break;
  821. X
  822. X      case 'K':
  823. X         if( !strcmp( tg, "KEEP_STATE" ) )    DB_RETURN( ST_KEEP     );
  824. X     break;
  825. X
  826. X      case 'R':
  827. X         if( !strcmp( tg, "REMOVE" ) )        DB_RETURN( ST_REST     );
  828. X     break;
  829. X
  830. X      case 'S':
  831. X         if( !strncmp( tg, "SOURCE", 6 ) )    DB_RETURN( ST_SOURCE   );
  832. X         else if( !strncmp(tg, "SUFFIXES", 8 )) DB_RETURN( ST_SOURCE   );
  833. X     break;
  834. X   }
  835. X   
  836. X   DB_RETURN( 0 );
  837. }
  838. X
  839. X
  840. X
  841. static int
  842. _is_percent( np )/*
  843. ===================
  844. X    return TRUE if np points at a string containing a % sign */
  845. char *np;
  846. {
  847. X   return( (strchr(np,'%') && (*np != '\'' && np[strlen(np)-1] != '\'')) ?
  848. X       TRUE : FALSE );
  849. }
  850. X
  851. X
  852. static char *
  853. _is_magic( np )/*
  854. =================
  855. X    return TRUE if np points at a string of the form
  856. X          .<chars>.<chars>  or  .<chars>
  857. X    where chars are only alpha characters.
  858. X
  859. X        NOTE:  reject target if it begins with ./ or ../ */
  860. char *np;
  861. {
  862. X   register char *n;
  863. X
  864. X   n = np;
  865. X   if( *n != '.' ) return( NIL(char) );
  866. X   if (strchr(DirBrkStr, *(n+1))!=NULL || *(n+1) == '.' )
  867. X      return (NIL(char));
  868. X
  869. X   for( n++; isgraph(*n) && (*n != '.'); n++ );
  870. X
  871. X   if( *n != '\0' ) {
  872. X      if( *n != '.' )  return( NIL(char) );
  873. X      for( np = n++; isgraph( *n ) && (*n != '.'); n++ );
  874. X      if( *n != '\0' ) return( NIL(char) );
  875. X   }
  876. X   else if( !Augmake )
  877. X      return( NIL(char) );
  878. X
  879. X   /* np points at the second . of .<chars>.<chars> string.
  880. X    * if the special target is of the form .<chars> then np points at the
  881. X    * first . in the token. */
  882. X
  883. X   return( np );
  884. }
  885. X
  886. X
  887. static int
  888. _add_root(tg)
  889. CELLPTR tg;
  890. {
  891. X   int res = FALSE;
  892. X
  893. X   if( !Target && !(tg->ce_flag & (F_SPECIAL|F_PERCENT)) ) {
  894. X      Add_prerequisite( Root, tg, FALSE, TRUE );
  895. X
  896. X      tg->ce_flag |= F_TARGET;
  897. X      tg->ce_attr |= A_FRINGE;
  898. X      res          = TRUE;
  899. X   }
  900. X
  901. X   return(res);
  902. }
  903. SHAR_EOF
  904. chmod 0640 dmake/rulparse.c ||
  905. echo 'restore of dmake/rulparse.c failed'
  906. Wc_c="`wc -c < 'dmake/rulparse.c'`"
  907. test 39571 -eq "$Wc_c" ||
  908.     echo 'dmake/rulparse.c: original size 39571, current size' "$Wc_c"
  909. rm -f _shar_wnt_.tmp
  910. fi
  911. # ============= dmake/stat.c ==============
  912. if test -f 'dmake/stat.c' -a X"$1" != X"-c"; then
  913.     echo 'x - skipping dmake/stat.c (File already exists)'
  914.     rm -f _shar_wnt_.tmp
  915. else
  916. > _shar_wnt_.tmp
  917. sed 's/^X//' << 'SHAR_EOF' > 'dmake/stat.c' &&
  918. /* RCS      -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/stat.c,v 1.1 1992/01/24 03:27:58 dvadura Exp $
  919. -- SYNOPSIS -- bind a target name to a file.
  920. -- 
  921. -- DESCRIPTION
  922. --    This file contains the code to go and stat a target.  The stat rules
  923. --    follow a predefined order defined in the comment for Stat_target.
  924. -- 
  925. -- AUTHOR
  926. --      Dennis Vadura, dvadura@watdragon.uwaterloo.ca
  927. --      CS DEPT, University of Waterloo, Waterloo, Ont., Canada
  928. --
  929. -- COPYRIGHT
  930. --      Copyright (c) 1990 by Dennis Vadura.  All rights reserved.
  931. -- 
  932. --      This program is free software; you can redistribute it and/or
  933. --      modify it under the terms of the GNU General Public License
  934. --      (version 1), as published by the Free Software Foundation, and
  935. --      found in the file 'LICENSE' included with this distribution.
  936. -- 
  937. --      This program is distributed in the hope that it will be useful,
  938. --      but WITHOUT ANY WARRANTY; without even the implied warrant of
  939. --      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  940. --      GNU General Public License for more details.
  941. -- 
  942. --      You should have received a copy of the GNU General Public License
  943. --      along with this program;  if not, write to the Free Software
  944. --      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  945. --
  946. -- LOG
  947. --     $Log: stat.c,v $
  948. X * Revision 1.1  1992/01/24  03:27:58  dvadura
  949. X * dmake Version 3.8, Initial revision
  950. X *
  951. */
  952. X
  953. #include "extern.h"
  954. X
  955. X
  956. static    int    _check_dir_list ANSI((CELLPTR, CELLPTR, int));
  957. X
  958. #ifdef DBUG
  959. X   /* Just a little ditty for debugging this thing */
  960. X   static time_t
  961. X   _do_stat( name, lib, sym )
  962. X   char *name;
  963. X   char *lib;
  964. X   char **sym;
  965. X   {
  966. X      time_t res;
  967. X      DB_ENTER( "_do_stat" );
  968. X
  969. X      res = Do_stat(name, lib, sym);
  970. X      DB_PRINT( "stat", ("Statted [%s,%s,%d,%ld]", name, lib, sym, res) );
  971. X
  972. X      DB_RETURN( res );
  973. X   }   
  974. #define DO_STAT(A,B,C)  _do_stat(A,B,C)
  975. #else
  976. #define DO_STAT(A,B,C)  Do_stat(A,B,C)
  977. #endif
  978. X
  979. static char *_first;    /* local storage of first attempted path */
  980. X
  981. PUBLIC void
  982. Stat_target( cp, setfname )/*
  983. =============================
  984. X    Stat a target.  When doing so follow the following rules, suppose
  985. X    that cp->CE_NAME points at a target called fred.o:
  986. X
  987. X        0.      If A_SYMBOL attribute set look into the library
  988. X            then do the steps 1 thru 4 on the resulting name.
  989. X        1.    Try path's obtained by prepending any dirs found as
  990. X            prerequisites for .SOURCE.o.
  991. X        2.    If not found, do same as 2 but use .SOURCE
  992. X        3.    If not found and .LIBRARYM attribute for the target is
  993. X            set then look for it in the corresponding library.
  994. X            4.    If found in step 0 thru 3, then ce_fname points at
  995. X            file name associate with target, else ce_fname points
  996. X            at a file name built by the first .SOURCE* dir that
  997. X            applied. */
  998. X
  999. CELLPTR cp;
  1000. int     setfname;
  1001. {
  1002. X   register HASHPTR hp;
  1003. X   static   HASHPTR srchp = NIL(HASH);
  1004. X   char            *name;
  1005. X   char            *tmp;
  1006. X   int            res = 0;
  1007. X
  1008. X   DB_ENTER( "Stat_target" );
  1009. X
  1010. X   name = cp->CE_NAME;
  1011. X   if( srchp == NIL(HASH) ) srchp = Get_name(".SOURCE",Defs,FALSE);
  1012. X
  1013. X   /* Look for a symbol of the form lib((symbol)) the name of the symbol
  1014. X    * as entered in the hash table is (symbol) so pull out symbol and try
  1015. X    * to find it's module.  If successful DO_STAT will return the module
  1016. X    * as well as the archive member name (pointed at by tmp).  We then
  1017. X    * replace the symbol name with the archive member name so that we
  1018. X    * have the proper name for any future refrences. */
  1019. X
  1020. X   if( cp->ce_attr & A_SYMBOL ) {
  1021. X      DB_PRINT( "stat", ("Binding lib symbol [%s]", name) );
  1022. X
  1023. X      cp->ce_time = DO_STAT( name, cp->ce_lib, &tmp );
  1024. X
  1025. X      if( cp->ce_time != (time_t) 0L ) {
  1026. X     /* stat the new member name below  note tmp must point at a string
  1027. X      * returned by MALLOC... ie. the Do_stat code should use _strdup */
  1028. X
  1029. X     if( Verbose & V_MAKE )
  1030. X        printf( "%s:  Mapped ((%s)) to %s(%s)\n", Pname,
  1031. X             name, cp->ce_lib, tmp );
  1032. X
  1033. X         FREE( name );        
  1034. X     name = cp->CE_NAME = tmp;        
  1035. X     cp->ce_attr &= ~(A_FFNAME | A_SYMBOL);
  1036. X      }
  1037. X      else
  1038. X         { DB_VOID_RETURN; }
  1039. X   }
  1040. X
  1041. X   _first = NIL(char);
  1042. X   tmp = _strjoin( ".SOURCE", Get_suffix( name ), -1, FALSE);
  1043. X
  1044. X   /* Check .SOURCE.xxx target */
  1045. X   if( (hp = Get_name(tmp, Defs, FALSE)) != NIL(HASH) )
  1046. X      res = _check_dir_list( cp, hp->CP_OWNR, setfname );
  1047. X
  1048. X   /* Check just .SOURCE */
  1049. X   if( !res && (srchp != NIL(HASH)) )
  1050. X      res = _check_dir_list( cp, srchp->CP_OWNR, setfname );
  1051. X
  1052. X   /* If libmember and we haven't found it check the library */
  1053. X   if( !res && (cp->ce_attr & A_LIBRARYM) ) {
  1054. X      cp->ce_time = DO_STAT(name, cp->ce_lib, NIL(char *));
  1055. X
  1056. X      if( !cp->ce_time && Tmd && *Tmd && cp->ce_lib ) {
  1057. X     cp->ce_lib=Build_path(Tmd,cp->ce_lib);
  1058. X     cp->ce_time = DO_STAT(name, cp->ce_lib, NIL(char *));
  1059. X      }
  1060. X
  1061. X      if( Verbose & V_MAKE )
  1062. X     printf( "%s:  Checking library '%s' for member [%s], time %ld\n",
  1063. X         Pname, cp->ce_lib, name, cp->ce_time );
  1064. X   }
  1065. X
  1066. X   FREE( tmp );
  1067. X
  1068. X   if( setfname == 1 || (setfname == -1 && cp->ce_time != (time_t)0L) ) {
  1069. X      if( (cp->ce_attr & A_FFNAME) && (cp->ce_fname != NIL(char)) )
  1070. X     FREE( cp->ce_fname );
  1071. X
  1072. X      if( _first != NIL(char) ) {
  1073. X     cp->ce_fname = _first;
  1074. X     cp->ce_attr |= A_FFNAME;
  1075. X      }
  1076. X      else {
  1077. X     cp->ce_fname = cp->CE_NAME;
  1078. X     cp->ce_attr &= ~A_FFNAME;
  1079. X      }
  1080. X   }
  1081. X   else if( _first )
  1082. X      FREE( _first );
  1083. X
  1084. X   /* set it as stated only if successful, this way, we shall try again
  1085. X    * later. */
  1086. X   if( cp->ce_time != (time_t)0L ) cp->ce_flag |= F_STAT;
  1087. X
  1088. X   DB_VOID_RETURN;
  1089. }
  1090. X
  1091. X
  1092. X
  1093. static int
  1094. _check_dir_list( cp, sp, setfname )/*
  1095. =====================================
  1096. X    Check the list of dir's given by the prerequisite list of sp, for a
  1097. X    file pointed at by cp.  Returns 0 if path not bound, else returns
  1098. X    1 and replaces old name for cell with new cell name. */
  1099. X
  1100. CELLPTR cp;
  1101. CELLPTR sp;
  1102. int     setfname;
  1103. {
  1104. X   register LINKPTR lp;
  1105. X   char *dir;
  1106. X   char *path;
  1107. X   char *name;
  1108. X   int  res  = 0;
  1109. X   int  fset = 0;
  1110. X
  1111. X   DB_ENTER( "_check_dir_list" );
  1112. X   DB_PRINT( "mem", ("%s:-> mem %ld", cp->CE_NAME, (long) coreleft()) );
  1113. X
  1114. X   if( sp->ce_prq != NIL(LINK) )    /* check prerequisites if any */
  1115. X   {
  1116. X      /* Use the real name instead of basename, this prevents silly
  1117. X       * loops in inference code, and is consistent with man page */
  1118. X      name = cp->CE_NAME;
  1119. X
  1120. X      /* Here we loop through each directory on the list, and try to stat
  1121. X       * the target.  We always save the first pathname we try and stat in
  1122. X       * _first.  If we subsequently get a match we then replace the value of
  1123. X       * _first by the matched path name.  */
  1124. X
  1125. X      for( lp=sp->CE_PRQ; lp != NIL(LINK) && !res; lp=lp->cl_next ) {
  1126. X     int  nodup = 0;
  1127. X     dir  = lp->cl_prq->CE_NAME;
  1128. X
  1129. X     if( strchr( dir, '$' ) ) dir = Expand(dir);
  1130. X     if( strcmp( dir, ".NULL" ) == 0 ) {
  1131. X        nodup = 1;
  1132. X        path = cp->CE_NAME;
  1133. X     }
  1134. X     else
  1135. X        path = Build_path( dir, name );
  1136. X
  1137. X     res = ((cp->ce_time = DO_STAT(path,NIL(char),NIL(char *))) != (time_t)0L);
  1138. #if 0
  1139. I think this will break a lot of things!
  1140. X     /* It didn't work and TMD macro has a value so try to stat it
  1141. X      * relative to the original MAKEDIR directory. */
  1142. X     if( Tmd && !*Tmd && !res ) {
  1143. X        char *p = _strdup(path);
  1144. X        path = Build_path(Tmd,p); FREE(p);
  1145. X        res = ((cp->ce_time = DO_STAT(path,NIL(char),NIL(char *))) != (time_t)0L);
  1146. X     }
  1147. #endif
  1148. X
  1149. X     /* Have to use _strdup to set _first since Build_path, builds it's
  1150. X      * path names inside a static buffer. */
  1151. X     if( setfname )
  1152. X        if( (_first == NIL(char) && !fset) || res ) {
  1153. X           if( _first != NIL(char) ) FREE( _first );
  1154. X           _first = nodup ? NIL(char) : _strdup(path);
  1155. X           fset = 1;
  1156. X        }
  1157. X
  1158. X     DB_PRINT( "stat", ("_first [%s], path [%s]", _first, path) );
  1159. X     if( dir != lp->cl_prq->CE_NAME )  FREE(dir);
  1160. X      }
  1161. X   }
  1162. X
  1163. X   DB_PRINT( "mem", ("%s:-< mem %ld", cp->CE_NAME, (long) coreleft()) );
  1164. X   DB_RETURN( res );
  1165. }
  1166. SHAR_EOF
  1167. chmod 0640 dmake/stat.c ||
  1168. echo 'restore of dmake/stat.c failed'
  1169. Wc_c="`wc -c < 'dmake/stat.c'`"
  1170. test 7774 -eq "$Wc_c" ||
  1171.     echo 'dmake/stat.c: original size 7774, current size' "$Wc_c"
  1172. rm -f _shar_wnt_.tmp
  1173. fi
  1174. # ============= dmake/state.c ==============
  1175. if test -f 'dmake/state.c' -a X"$1" != X"-c"; then
  1176.     echo 'x - skipping dmake/state.c (File already exists)'
  1177.     rm -f _shar_wnt_.tmp
  1178. else
  1179. > _shar_wnt_.tmp
  1180. sed 's/^X//' << 'SHAR_EOF' > 'dmake/state.c' &&
  1181. /* RCS      -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/state.c,v 1.1 1992/01/24 03:27:05 dvadura Exp $
  1182. -- SYNOPSIS -- .KEEP_STATE state file management
  1183. -- 
  1184. -- DESCRIPTION
  1185. --     Three routines to interface to the .KEEP_STATE state file.
  1186. --
  1187. --        Read_state()    - reads the state file if any.
  1188. --        Write_state()    - writes the state file.
  1189. --
  1190. --        Check_state(cp,how) - checks an entry returns 0 or 1
  1191. --                      and updates the entry.
  1192. --
  1193. -- AUTHOR
  1194. --      Dennis Vadura, dvadura@watdragon.uwaterloo.ca
  1195. --      CS DEPT, University of Waterloo, Waterloo, Ont., Canada
  1196. --
  1197. -- COPYRIGHT
  1198. --      Copyright (c) 1990 by Dennis Vadura.  All rights reserved.
  1199. -- 
  1200. --      This program is free software; you can redistribute it and/or
  1201. --      modify it under the terms of the GNU General Public License
  1202. --      (version 1), as published by the Free Software Foundation, and
  1203. --      found in the file 'LICENSE' included with this distribution.
  1204. -- 
  1205. --      This program is distributed in the hope that it will be useful,
  1206. --      but WITHOUT ANY WARRANTY; without even the implied warrant of
  1207. --      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  1208. --      GNU General Public License for more details.
  1209. -- 
  1210. --      You should have received a copy of the GNU General Public License
  1211. --      along with this program;  if not, write to the Free Software
  1212. --      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  1213. --
  1214. -- LOG
  1215. --     $Log: state.c,v $
  1216. X * Revision 1.1  1992/01/24  03:27:05  dvadura
  1217. X * dmake Version 3.8, Initial revision
  1218. X *
  1219. */
  1220. X
  1221. #include "extern.h"
  1222. X
  1223. typedef struct se {
  1224. X   char        *st_name;        /* name of cell        */
  1225. X   uint32    st_nkey;        /* name hash key    */
  1226. X   int        st_count;        /* how count for how    */
  1227. X   uint32    st_dkey;        /* directory hash key    */
  1228. X   uint32    st_key;            /* hash key        */
  1229. X   struct se    *st_next;
  1230. } KSTATE, *KSTATEPTR;
  1231. X
  1232. static KSTATEPTR _st_head  = NIL(KSTATE);
  1233. static KSTATEPTR _st_tail  = NIL(KSTATE);
  1234. static int       _st_upd   = FALSE;
  1235. static char     *_st_file  = NIL(char);
  1236. X
  1237. static int  _my_fgets ANSI((char *, int, FILE *));
  1238. X
  1239. PUBLIC void
  1240. Read_state()
  1241. {
  1242. X   char *buf;
  1243. X   char sizeb[20];
  1244. X   int  size;
  1245. X   FILE *fp;
  1246. X   KSTATEPTR sp;
  1247. X
  1248. X   if( (fp = Search_file(".KEEP_STATE", &_st_file)) != NIL(FILE) ) {
  1249. X      if( _my_fgets( sizeb, 20, fp ) ) {
  1250. X     size = atol(sizeb);
  1251. X     buf = MALLOC(size+2, char);
  1252. X
  1253. X     while( _my_fgets(buf, size, fp) ) {
  1254. X        TALLOC(sp, 1, KSTATE);
  1255. X        sp->st_name = _strdup(buf);
  1256. X        (void) Hash(buf, &sp->st_nkey);
  1257. X
  1258. X        if( _my_fgets(buf, size, fp) ) sp->st_count = atoi(buf);
  1259. X        if( _my_fgets(buf, size, fp) ) sp->st_dkey   = (uint32) atol(buf);
  1260. X
  1261. X        if( _my_fgets(buf, size, fp) )
  1262. X           sp->st_key = (uint32) atol(buf);
  1263. X        else {
  1264. X           FREE(sp);
  1265. X           break;
  1266. X        }
  1267. X
  1268. X        if( _st_head == NIL(KSTATE) )
  1269. X           _st_head = sp;
  1270. X        else
  1271. X           _st_tail->st_next = sp;
  1272. X
  1273. X        _st_tail = sp;
  1274. X     }
  1275. X
  1276. X     FREE(buf);
  1277. X      }
  1278. X
  1279. X      Closefile(fp);
  1280. X   }
  1281. }
  1282. X
  1283. X
  1284. PUBLIC void
  1285. Write_state()
  1286. {
  1287. X   static int in_write = 0;
  1288. X   register KSTATEPTR sp;
  1289. X   FILE *fp;
  1290. X
  1291. X   if( !_st_upd || !_st_file || (_st_file && !*_st_file) ||
  1292. X       Trace || in_write ) return;
  1293. X
  1294. X   in_write++;
  1295. X   if( (fp = Openfile(_st_file, TRUE, TRUE)) != NIL(FILE) ) {
  1296. X      int maxlen = 0;
  1297. X      int tmplen;
  1298. X
  1299. X      for( sp = _st_head; sp; sp=sp->st_next )
  1300. X     if( (tmplen = strlen(sp->st_name)+2) > maxlen )
  1301. X        maxlen = tmplen;
  1302. X
  1303. X      /* A nice arbitrary minimum size */
  1304. X      if( maxlen < 20 ) maxlen = 20;
  1305. X      fprintf( fp, "%d\n", maxlen );
  1306. X
  1307. X      for( sp = _st_head; sp; sp=sp->st_next ) {
  1308. X     uint16 hv;
  1309. X     uint32 hk;
  1310. X
  1311. X     if( Search_table(Defs, sp->st_name, &hv, &hk) ) {
  1312. X        fprintf( fp, "%s\n",  sp->st_name   );
  1313. X        fprintf( fp, "%d\n",  sp->st_count );
  1314. X        fprintf( fp, "%lu\n", sp->st_dkey   );
  1315. X        fprintf( fp, "%lu\n", sp->st_key    );
  1316. X     }
  1317. X      }
  1318. X
  1319. X      Closefile();
  1320. X   }
  1321. X   else
  1322. X      Fatal("Cannot open STATE file %s", _st_file);
  1323. X
  1324. X   in_write = 0;
  1325. }
  1326. X
  1327. X
  1328. PUBLIC int
  1329. Check_state( cp, recipes, maxrcp )
  1330. CELLPTR cp;
  1331. STRINGPTR *recipes;
  1332. int  maxrcp;
  1333. {
  1334. X   KSTATEPTR  st;
  1335. X   STRINGPTR sp;
  1336. X   int    i;
  1337. X   uint32 thkey;
  1338. X   uint32 hkey;
  1339. X   uint32 nkey;
  1340. X   uint32 dkey;
  1341. X   int    update = FALSE;
  1342. X
  1343. X   if(    strcmp(cp->CE_NAME,".REMOVE") == 0
  1344. X       || (cp->ce_attr & (A_PHONY|A_NOSTATE)) )
  1345. X      return(FALSE);
  1346. X
  1347. X   (void) Hash( cp->CE_NAME, &nkey ); thkey = nkey + (uint32) cp->ce_count;
  1348. X   (void) Hash( Pwd,  &dkey ); thkey += dkey;
  1349. X
  1350. X   Suppress_temp_file = TRUE;
  1351. X   for( i=0 ; i<maxrcp; i++ )
  1352. X      for(sp=recipes[i]; sp != NIL(STRING); sp=sp->st_next ) {
  1353. X     char *cmnd = Expand(sp->st_string);
  1354. X
  1355. X     (void) Hash(cmnd, &hkey); thkey += hkey;
  1356. X     FREE(cmnd);
  1357. X      }
  1358. X   Suppress_temp_file = FALSE;
  1359. X
  1360. X   for( st=_st_head; st != NIL(KSTATE); st=st->st_next ) {
  1361. X      if(    st->st_nkey   == nkey
  1362. X      && st->st_dkey   == dkey
  1363. X      && st->st_count  == cp->ce_count
  1364. X      && !strcmp(cp->CE_NAME, st->st_name) )
  1365. X     break;
  1366. X   }
  1367. X
  1368. X   if( st == NIL(KSTATE) ) {
  1369. X      KSTATEPTR nst;
  1370. X
  1371. X      TALLOC(nst, 1, KSTATE);
  1372. X      nst->st_name = cp->CE_NAME;
  1373. X      nst->st_nkey = nkey;
  1374. X      nst->st_dkey = dkey;
  1375. X      nst->st_key  = thkey;
  1376. X      nst->st_count = cp->ce_count;
  1377. X
  1378. X      if( _st_head == NIL(KSTATE) )
  1379. X     _st_head = nst;
  1380. X      else
  1381. X     _st_tail->st_next = nst;
  1382. X
  1383. X      _st_tail = nst;
  1384. X      _st_upd  = TRUE;
  1385. X   }
  1386. X   else if( st->st_key != thkey ) {
  1387. X      st->st_key = thkey;
  1388. X      _st_upd = update = TRUE;
  1389. X   }
  1390. X
  1391. X   return(st != NIL(KSTATE) && update);
  1392. SHAR_EOF
  1393. true || echo 'restore of dmake/state.c failed'
  1394. fi
  1395. echo 'End of part 31, continue with part 32'
  1396. echo 32 > _shar_seq_.tmp
  1397. exit 0
  1398. exit 0 # Just in case...
  1399.