home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume19 / dmake / part29 < prev    next >
Encoding:
Text File  |  1991-05-12  |  40.2 KB  |  1,354 lines

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