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

  1. Newsgroups: comp.sources.misc
  2. subject: v14i014: dmake version 3.5 part 4/21
  3. From: dvadura@watdragon.waterloo.edu (Dennis Vadura)
  4. Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  5.  
  6. Posting-number: Volume 14, Issue 14
  7. Submitted-by: dvadura@watdragon.waterloo.edu (Dennis Vadura)
  8. Archive-name: dmake/part04
  9.  
  10. #!/bin/sh
  11. # this is part 4 of a multipart archive
  12. # do not concatenate these parts, unpack them in order with /bin/sh
  13. # file struct.h continued
  14. #
  15. CurArch=4
  16. if test ! -r s2_seq_.tmp
  17. then echo "Please unpack part 1 first!"
  18.      exit 1; fi
  19. ( read Scheck
  20.   if test "$Scheck" != $CurArch
  21.   then echo "Please unpack part $Scheck next!"
  22.        exit 1;
  23.   else exit 0; fi
  24. ) < s2_seq_.tmp || exit 1
  25. echo "x - Continuing file struct.h"
  26. sed 's/^X//' << 'SHAR_EOF' >> struct.h
  27. X * It gets unlinked when Quit is called due to an execution error */
  28. Xtypedef struct flst {
  29. X   char        *fl_name;    /* file name         */
  30. X   FILE        *fl_file;    /* the open file    */
  31. X   struct flst  *fl_next;    /* pointer to next file */
  32. X} FILELIST, *FILELISTPTR;
  33. X
  34. X
  35. X
  36. X/* This is the structure of a target cell in the dag which represents the
  37. X * graph of dependencies.  Each possible target is represented as a cell.
  38. X * 
  39. X * Each cell contains a pointer to the hash table entry for this cell.
  40. X * The hash table entry records the name of the cell. */
  41. X
  42. Xtypedef struct tcell {
  43. X    struct tcell    *ce_link;    /* link for temporary list making   */
  44. X    struct tcell    *ce_all;    /* link for grouping UPDATEALL cells*/
  45. X    struct hcell    *ce_name;    /* name of this cell                */
  46. X    struct tcell    *ce_setdir;    /* .SETDIR root for this cell       */
  47. X    union {
  48. X        struct hwcell    *ce_how;/* tell all we need to make cell    */
  49. X        struct edge    *ce_edges;/* tell what we can infer */
  50. X    } how;
  51. X    char        *ce_lib;    /* archive name, if A_LIBRARYM      */
  52. X    char        *ce_fname;    /* file name associated with target */
  53. X    char        *ce_dir;    /* dir to set if A_SETDIR set       */
  54. X    int        ce_flag;    /* all kinds of goodies            */
  55. X    int        ce_attr;    /* attributes for this target        */
  56. X    time_t        ce_time;    /* time stamp value of target if any*/
  57. X} CELL, *CELLPTR;
  58. X
  59. X#define CE_NAME        ce_name->ht_name
  60. X#define CE_RECIPE       how.ce_how->hw_recipe
  61. X#define CE_PRQ        how.ce_how->hw_prq
  62. X#define CE_EDGES    how.ce_edges
  63. X#define CE_HOW        how.ce_how
  64. X
  65. X
  66. X
  67. X/* This struct represents that used by Get_token to return and control
  68. X * access to a token list inside a particular string.  This gives the
  69. X * ability to access non overlapping tokens simultaneously from
  70. X * multiple strings. */
  71. X    
  72. Xtypedef struct {
  73. X    char *tk_str;              /* the string to search for tokens  */
  74. X    char tk_cchar;             /* current char under *str          */
  75. X    int  tk_quote;               /* if we are scanning a quoted str  */
  76. X}  TKSTR, *TKSTRPTR;
  77. X
  78. X
  79. X
  80. X
  81. X/* This structure defines the necessary fields for handling the :: rules,
  82. X * any flags, and the fact that the target has been made using this
  83. X * set of rules.  All attributes active when making this target are
  84. X * defined in this struct. */
  85. X
  86. Xtypedef struct hwcell {
  87. X    struct hwcell    *hw_next;    /* next set of rules (::)    */
  88. X    struct lcell    *hw_prq;    /* the list of prerequisites    */
  89. X    struct lcell    *hw_indprq;    /* the list of glob prereqs    */
  90. X    struct str    *hw_recipe;    /* list of rules for making tg    */
  91. X    char        *hw_per;    /* value of % in % meta rules    */
  92. X    FILELISTPTR    hw_files;    /* temp files associated with tg*/
  93. X    int        hw_flag;    /* flags for using these rules  */
  94. X    int        hw_attr;    /* attrs for using these rules  */
  95. X} HOW, *HOWPTR;
  96. X
  97. X#define HW_FLAG        CE_HOW->hw_flag
  98. X#define HW_ATTR        CE_HOW->hw_attr
  99. X
  100. X
  101. X
  102. X
  103. X/* Below is the struct used to represent a string.  It points at possibly
  104. X * another string, since the set of rules for making a target is a collection
  105. X * of strings. */
  106. X
  107. X
  108. Xtypedef struct str {
  109. X    char        *st_string;    /* the string value */
  110. X    struct str    *st_next;    /* pointer to the next string */
  111. X    int        st_attr;    /* attr for rule operations */
  112. X} STRING, *STRINGPTR;
  113. X
  114. X
  115. X/* The next struct is used to link together prerequisite lists */
  116. X
  117. Xtypedef struct lcell {
  118. X    struct tcell    *cl_prq;    /* link to a prerequisite     */
  119. X    struct lcell    *cl_next;    /* next cell on dependency list */
  120. X    int        cl_flag;    /* flags for link cell        */
  121. X} LINK, *LINKPTR;
  122. X
  123. X
  124. X
  125. X/* This struct is used to define an edge in the graph of % rules */
  126. X
  127. Xtypedef struct edge {
  128. X    struct tcell    *ed_tg;        /* the % target            */
  129. X    struct tcell    *ed_prq;    /* the prerequisite for target    */
  130. X    struct hwcell    *ed_how;    /* chain of how pointers    */
  131. X    struct edge    *ed_next;    /* next edge of graph        */
  132. X    struct edge    *ed_link;    /* work list pointer         */
  133. X} EDGE, *EDGEPTR;
  134. X
  135. X
  136. X
  137. X
  138. X/* These structs are used in processing of the % rules, and in building
  139. X * the DFA machines that are used to match an arbitrary target string to
  140. X * one of the % rules that is represented by each DFA */
  141. X
  142. Xtypedef int16 statecnt;        /* limits the max number of dfa states    */
  143. X
  144. X
  145. X/* This struct stores a single state for the DFA machine */
  146. X
  147. Xtypedef struct {
  148. X    statecnt    no_match;    /* state to go to if no match */
  149. X    statecnt    next;        /* state to go to if we do match */
  150. X    char        symbol;        /* the symbol matched by this state */
  151. X    char        action;        /* action to perform if we match */
  152. X} STATE, *STATEPTR;
  153. X
  154. X
  155. X/* This struct stores the DFA machine, it's current state, and pointers
  156. X * indicating the extent of the % substring match */
  157. X
  158. Xtypedef struct {
  159. X    char        *pstart;    /* start of % string match */
  160. X    char        *pend;        /* end of % string match */
  161. X    statecnt    c_state;    /* current DFA state */
  162. X    statecnt    n_states;    /* number of states in this dfa */
  163. X    CELLPTR        node;        /* % target represented by this DFA */
  164. X    STATEPTR    states;        /* table of states for the DFA */
  165. X} DFA, *DFAPTR;
  166. X
  167. X
  168. X/* This struct represents the linked together DFA's which form one large
  169. X * NFA machine.  When a pattern match takes place all DFA's making up this
  170. X * NFA are run in parallel. */
  171. X
  172. Xtypedef struct nfa_machine {
  173. X    DFAPTR        dfa;    /* The DFA pointed at by epsilon trans */
  174. X    char        status;    /* DFA state:  -1 ==> fail, 4 ==> ACCEPT */
  175. X    struct nfa_machine *next; /* the next DFA in list */
  176. X} NFA, *NFAPTR;
  177. X
  178. X
  179. X
  180. X/* The next struct is used to link together DFA nodes for inference. */
  181. X
  182. Xtypedef struct dfal {
  183. X    struct tcell    *dl_meta;    /* link to %-meta cell        */
  184. X    struct dfal    *dl_next;    /* next cell on matched DFA list*/
  185. X    struct dfal    *dl_prev;    /* prev cell on matched DFA list*/
  186. X    struct dfal    *dl_member;    /* used during subset calc    */
  187. X    char        dl_delete;    /* used during subset calc    */
  188. X    char           *dl_per;    /* value of % for matched DFA   */
  189. X    statecnt        dl_state;    /* matched state of the DFA    */
  190. X    int        dl_prep;    /* repetion count for the cell    */
  191. X} DFALINK, *DFALINKPTR;
  192. X
  193. X
  194. X/* This struct is used to store the stack of DFA sets during inference */
  195. Xtypedef struct dfst {
  196. X   DFALINKPTR    df_set;            /* pointer to the set        */
  197. X   struct dfst *df_next;        /* next element in the stack    */
  198. X} DFASET, *DFASETPTR;
  199. X
  200. X
  201. X#endif
  202. SHAR_EOF
  203. echo "File struct.h is complete"
  204. chmod 0440 struct.h || echo "restore of struct.h fails"
  205. echo "x - extracting string.c (Text)"
  206. sed 's/^X//' << 'SHAR_EOF' > string.c &&
  207. X/* RCS      -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/string.c,v 1.1 90/07/19 13:53:35 dvadura Exp $
  208. X-- SYNOPSIS -- string handling code
  209. X-- 
  210. X-- DESCRIPTION
  211. X--    Routines to handle string manipulation.  This code is not specific
  212. X--    to dmake and has/and will be used in other programs.  The string
  213. X--    "" is considered the NULL string, if NIL(char) is received instead
  214. X--    undefined results may occurr.  (In reality NIL(char) is checked for
  215. X--    but in general it is not safe to assume NIL(char) ==  NULL)
  216. X-- 
  217. X-- AUTHOR
  218. X--      Dennis Vadura, dvadura@watdragon.uwaterloo.ca
  219. X--      CS DEPT, University of Waterloo, Waterloo, Ont., Canada
  220. X--
  221. X-- COPYRIGHT
  222. X--      Copyright (c) 1990 by Dennis Vadura.  All rights reserved.
  223. X-- 
  224. X--      This program is free software; you can redistribute it and/or
  225. X--      modify it under the terms of the GNU General Public License
  226. X--      (version 1), as published by the Free Software Foundation, and
  227. X--      found in the file 'LICENSE' included with this distribution.
  228. X-- 
  229. X--      This program is distributed in the hope that it will be useful,
  230. X--      but WITHOUT ANY WARRANTY; without even the implied warrant of
  231. X--      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  232. X--      GNU General Public License for more details.
  233. X-- 
  234. X--      You should have received a copy of the GNU General Public License
  235. X--      along with this program;  if not, write to the Free Software
  236. X--      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  237. X--
  238. X-- LOG
  239. X--     $Log:    string.c,v $
  240. X * Revision 1.1  90/07/19  13:53:35  dvadura
  241. X * Initial Revision of Version 3.5
  242. X * 
  243. X*/
  244. X
  245. X#include "extern.h"
  246. X#include "alloc.h"
  247. X#include "db.h"
  248. X
  249. Xchar *
  250. X_strjoin( src, data, n, fr )/*
  251. X==============================
  252. X   Join data to src according to value of n.
  253. X
  254. X      n = -1   - return strcat( src, data )
  255. X      n >= 0   - return strncat( src, data, n )
  256. X
  257. X   FREE original src if fr == TRUE, else leave it alone */
  258. X
  259. Xchar *src;
  260. Xchar *data;
  261. Xint  n;
  262. Xint  fr;
  263. X{
  264. X   char *t;
  265. X   int  l;
  266. X   int  flag = FALSE;
  267. X
  268. X   DB_ENTER( "_strjoin" );
  269. X   
  270. X   if( src  == NIL( char ) ) { src = ""; flag = TRUE; }
  271. X   if( data == NIL( char ) ) data = "";
  272. X   DB_PRINT( "str", ("Joining [%s] [%s] %d", src, data, n) );
  273. X
  274. X   if( n == -1 )  n = strlen( data );
  275. X
  276. X   l = strlen( src ) + n + 1;
  277. X   if( (t = MALLOC( l, char )) == NIL( char ) ) No_ram();
  278. X
  279. X   strcpy( t, src );
  280. X   if (n) strncat( t, data, n );
  281. X   t[ l-1 ] = '\0';
  282. X
  283. X   if( !flag && fr ) FREE( src );
  284. X
  285. X   DB_PRINT( "str", ("Result  [%s]", t) );
  286. X   DB_RETURN( t );
  287. X}
  288. X
  289. X
  290. X
  291. X
  292. Xchar *
  293. X_stradd( src, data, fr )/*
  294. X==========================
  295. X   append data to src with space in between if src is not NIL( char ) or ""
  296. X   and free both src and data if fr == TRUE, otherwise leave them be */
  297. X
  298. Xchar *src;
  299. Xchar *data;
  300. Xint  fr;
  301. X{
  302. X   char *t;
  303. X   int  l;
  304. X   int  sflag;
  305. X   int  dflag;
  306. X
  307. X   DB_ENTER( "_stradd" );
  308. X
  309. X   sflag = dflag = fr;
  310. X
  311. X   if( src  == NIL( char ) ) { src  = ""; sflag = FALSE; }
  312. X   if( data == NIL( char ) ) { data = ""; dflag = FALSE; }
  313. X   DB_PRINT( "str", ("Adding [%s] [%s] %d", src, data, fr) );
  314. X
  315. X   l = strlen(src) + strlen(data) + 1;
  316. X   if( *src ) l++;
  317. X
  318. X   if( (t = MALLOC( l, char )) == NIL( char ) ) No_ram();
  319. X
  320. X   strcpy( t, src );
  321. X   
  322. X   if( *data )
  323. X   {
  324. X      if( *src ) strcat( t,  " " );
  325. X      strcat( t, data );
  326. X   }
  327. X
  328. X   if( sflag )  FREE( src  );
  329. X   if( dflag )  FREE( data );
  330. X
  331. X   DB_PRINT( "str", ("Result  [%s]", t) );
  332. X   DB_RETURN( t );
  333. X}
  334. X
  335. X
  336. X
  337. Xchar *
  338. X_strapp( src1, src2 )/*
  339. X=======================
  340. X   Append two strings together, and return the result with a space between
  341. X   the two strings.  FREE the first string if it is not NIL and always
  342. X   leave the second string be. */
  343. Xchar *src1;
  344. Xchar *src2;
  345. X{
  346. X   src2 = _stradd( src1, src2, FALSE );
  347. X   if( src1 != NIL( char ) ) FREE( src1 );
  348. X   return( src2 );
  349. X}
  350. X
  351. X
  352. X
  353. Xchar *
  354. X_strdup( str )/*
  355. X================  Duplicate the contents of a string, by using malloc */
  356. Xchar *str;
  357. X{
  358. X   char *t;
  359. X
  360. X   if( str == NIL( char ) ) return( NIL( char ) );
  361. X   
  362. X   if( (t = MALLOC( strlen( str )+1, char )) == NIL( char ) ) No_ram();
  363. X   strcpy( t, str );
  364. X
  365. X   return( t );
  366. X}
  367. X
  368. X
  369. X
  370. X
  371. Xchar *
  372. X_strpbrk( s1, s2 )/*
  373. X====================
  374. X   find first occurence of char in s2 in string s1.
  375. X   Returns a pointer to the first occurrence.  NOTE '\0' is considered part
  376. X   of s2 and a pointer to it is returned if no other chars match. */
  377. X
  378. Xchar *s1;
  379. Xchar *s2;
  380. X{
  381. X   register char *t;
  382. X
  383. X   if( s1 == NIL( char ) ) return( "" );
  384. X
  385. X   for( t=s1; *t && (strchr( s2, *t ) == NIL( char )); t++ );
  386. X   return( t );
  387. X}
  388. X
  389. X
  390. X
  391. X
  392. Xchar *
  393. X_strspn( s1, s2 )/*
  394. X===================
  395. X   return pointer to first char in s1 that does not belong to s2.
  396. X   Returns the pointer if match found, else returns pointer to null char
  397. X   in s1. (ie. "" ) */
  398. X   
  399. Xchar *s1;
  400. Xchar *s2;
  401. X{
  402. X   register char *t;
  403. X
  404. X   if( s1 == NIL( char ) ) return( "" );
  405. X
  406. X   for( t=s1; *t && (strchr( s2, *t ) != NIL( char )); t++ );
  407. X   return( t );
  408. X}
  409. X
  410. X
  411. X
  412. X
  413. Xchar *
  414. X_strstr( s1, s2 )/*
  415. X==================  find first occurrence in s1 of s2 */
  416. Xchar *s1;
  417. Xchar *s2;
  418. X{
  419. X   register char *s;
  420. X   register char *p;
  421. X   register char *r;
  422. X
  423. X   if( s1 != NIL(char) && s2 != NIL(char) )
  424. X      for( s=s1; *s; s++ )
  425. X     if( *s == *s2 )
  426. X     {
  427. X        for( r=s+1, p = s2+1; *p && (*r == *p); r++, p++ );
  428. X        if( !*p ) return( s );
  429. X     }
  430. X   
  431. X   return( NIL( char ) );
  432. X}
  433. X
  434. X
  435. X
  436. Xchar *
  437. X_substr( s, e )/*
  438. X=================
  439. X      Return the string between the two pointers s and e, not including the
  440. X      char that e points to.  NOTE:  This routine assumes that s and e point
  441. X      into the same string. */
  442. X
  443. Xchar *s;
  444. Xchar *e;
  445. X{
  446. X   char save;
  447. X
  448. X   save = *e;
  449. X   *e   = '\0';
  450. X   s    = _strdup( s );
  451. X   *e   = save;
  452. X
  453. X   return( s );
  454. X}
  455. SHAR_EOF
  456. chmod 0440 string.c || echo "restore of string.c fails"
  457. echo "x - extracting stat.c (Text)"
  458. sed 's/^X//' << 'SHAR_EOF' > stat.c &&
  459. X/* RCS      -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/stat.c,v 1.1 90/07/19 13:53:34 dvadura Exp $
  460. X-- SYNOPSIS -- bind a target name to a file.
  461. X-- 
  462. X-- DESCRIPTION
  463. X--    This file contains the code to go and stat a target.  The stat rules
  464. X--    follow a predefined order defined in the comment for Stat_target.
  465. X-- 
  466. X-- AUTHOR
  467. X--      Dennis Vadura, dvadura@watdragon.uwaterloo.ca
  468. X--      CS DEPT, University of Waterloo, Waterloo, Ont., Canada
  469. X--
  470. X-- COPYRIGHT
  471. X--      Copyright (c) 1990 by Dennis Vadura.  All rights reserved.
  472. X-- 
  473. X--      This program is free software; you can redistribute it and/or
  474. X--      modify it under the terms of the GNU General Public License
  475. X--      (version 1), as published by the Free Software Foundation, and
  476. X--      found in the file 'LICENSE' included with this distribution.
  477. X-- 
  478. X--      This program is distributed in the hope that it will be useful,
  479. X--      but WITHOUT ANY WARRANTY; without even the implied warrant of
  480. X--      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  481. X--      GNU General Public License for more details.
  482. X-- 
  483. X--      You should have received a copy of the GNU General Public License
  484. X--      along with this program;  if not, write to the Free Software
  485. X--      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  486. X--
  487. X-- LOG
  488. X--     $Log:    stat.c,v $
  489. X * Revision 1.1  90/07/19  13:53:34  dvadura
  490. X * Initial Revision of Version 3.5
  491. X * 
  492. X*/
  493. X
  494. X#include "extern.h"
  495. X#include "alloc.h"
  496. X#include "db.h"
  497. X
  498. X
  499. Xstatic    int    _check_dir_list ANSI((CELLPTR, CELLPTR, int));
  500. X
  501. X#ifdef DBUG
  502. X   /* Just a little ditty for debugging this thing */
  503. X   static time_t
  504. X   _do_stat( name, lib, sym )
  505. X   char *name;
  506. X   char *lib;
  507. X   char **sym;
  508. X   {
  509. X      time_t res;
  510. X      DB_ENTER( "_do_stat" );
  511. X
  512. X      res = Do_stat(name, lib, sym);
  513. X      DB_PRINT( "stat", ("Statted [%s,%s,%d,%ld]", name, lib, sym, res) );
  514. X
  515. X      DB_RETURN( res );
  516. X   }   
  517. X#define DO_STAT(A,B,C)  _do_stat(A,B,C)
  518. X#else
  519. X#define DO_STAT(A,B,C)  Do_stat(A,B,C)
  520. X#endif
  521. X
  522. Xstatic char *_first;    /* local storage of first attempted path */
  523. X
  524. Xvoid
  525. XStat_target( cp, setfname )/*
  526. X=============================
  527. X    Stat a target.  When doing so follow the following rules, suppose
  528. X    that cp->CE_NAME points at a target called fred.o:
  529. X
  530. X        0.      If A_SYMBOL attribute set look into the library
  531. X            then do the steps 1 thru 4 on the resulting name.
  532. X        1.    Try path's obtained by prepending any dirs found as
  533. X            prerequisites for .SOURCE.o.
  534. X        2.    If not found, do same as 2 but use .SOURCE
  535. X        3.    If not found and .LIBRARYM attribute for the target is
  536. X            set then look for it in the corresponding library.
  537. X            4.    If found in step 0 thru 3, then ce_fname points at
  538. X            file name associate with target, else ce_fname points
  539. X            at a file name built by the first .SOURCE* dir that
  540. X            applied. */
  541. X
  542. XCELLPTR cp;
  543. Xint     setfname;
  544. X{
  545. X   register HASHPTR hp;
  546. X   static   HASHPTR srchp = NIL(HASH);
  547. X   char            *name;
  548. X   char            *tmp;
  549. X   int            res = 0;
  550. X
  551. X   DB_ENTER( "Stat_target" );
  552. X
  553. X   name = cp->CE_NAME;
  554. X   if( srchp == NIL(HASH) ) srchp = Get_name(".SOURCE",Defs,FALSE,NIL(CELL));
  555. X
  556. X   /* Look for a symbol of the form lib((symbol)) the name of the symbol
  557. X    * as entered in the hash table is (symbol) so pull out symbol and try
  558. X    * to find it's module.  If successful DO_STAT will return the module
  559. X    * as well as the archive member name (pointed at by tmp).  We then
  560. X    * replace the symbol name with the archive member name so that we
  561. X    * have the proper name for any future refrences. */
  562. X
  563. X   if( cp->ce_attr & A_SYMBOL ) {
  564. X      DB_PRINT( "stat", ("Binding lib symbol [%s]", name) );
  565. X      cp->ce_time = DO_STAT( name, cp->ce_lib, &tmp );
  566. X
  567. X      if( cp->ce_time != (time_t) 0L ) {
  568. X     /* stat the new member name below  note tmp must point at a string
  569. X      * returned by MALLOC... ie. the Do_stat code should use _strdup */
  570. X
  571. X     if( Verbose )
  572. X        printf( "%s:  Mapped ((%s)) to %s(%s)\n", Pname,
  573. X             name, cp->ce_lib, tmp );
  574. X
  575. X         FREE( name );        
  576. X     name = cp->CE_NAME = tmp;        
  577. X     cp->ce_attr &= ~(A_FFNAME | A_SYMBOL);
  578. X      }
  579. X      else
  580. X         { DB_VOID_RETURN; }
  581. X   }
  582. X
  583. X   _first = NIL(char);
  584. X   tmp = _strjoin( ".SOURCE", Get_suffix( name ), -1, FALSE);
  585. X
  586. X   /* Check .SOURCE.xxx target */
  587. X   if( (hp = Get_name(tmp, Defs, FALSE, NIL(CELL))) != NIL(HASH) )
  588. X      res = _check_dir_list( cp, hp->CP_OWNR, setfname );
  589. X
  590. X   /* Check just .SOURCE */
  591. X   if( !res && (srchp != NIL(HASH)) )
  592. X      res = _check_dir_list( cp, srchp->CP_OWNR, setfname );
  593. X
  594. X   /* If libmember and we haven't found it check the library */
  595. X   if( !res && (cp->ce_attr & A_LIBRARYM) )
  596. X       cp->ce_time = DO_STAT(name, cp->ce_lib, NIL(char *));
  597. X
  598. X   FREE( tmp );
  599. X
  600. X   if( (cp->ce_attr & A_FFNAME) && (cp->ce_fname != NIL(char)) )
  601. X      FREE( cp->ce_fname );
  602. X
  603. X   if( setfname )
  604. X      if( _first != NIL(char) ) {
  605. X     cp->ce_fname = _first;
  606. X     cp->ce_attr |= A_FFNAME;
  607. X      }
  608. X      else {
  609. X     cp->ce_fname = cp->CE_NAME;
  610. X     cp->ce_attr &= ~A_FFNAME;
  611. X      }
  612. X
  613. X   /* set it as stated only if successful, this way, we shall try again
  614. X    * later. */
  615. X   if( cp->ce_time != (time_t)0L ) cp->ce_flag |= F_STAT;
  616. X
  617. X   DB_VOID_RETURN;
  618. X}
  619. X
  620. X
  621. X
  622. Xstatic int
  623. X_check_dir_list( cp, sp, setfname )/*
  624. X=====================================
  625. X    Check the list of dir's given by the prerequisite list of sp, for a
  626. X    file pointed at by cp.  Returns 0 if path not bound, else returns
  627. X    1 and replaces old name for cell with new cell name. */
  628. X
  629. XCELLPTR cp;
  630. XCELLPTR sp;
  631. Xint     setfname;
  632. X{
  633. X   register LINKPTR lp;
  634. X   char *dir;
  635. X   char *path;
  636. X   char *name;
  637. X   int  res  = 0;
  638. X   int  fset = 0;
  639. X
  640. X   DB_ENTER( "_check_dir_list" );
  641. X   DB_PRINT( "mem", ("%s:-> mem %ld", cp->CE_NAME, (long) coreleft()) );
  642. X
  643. X   if( sp->CE_HOW != NIL(HOW) )        /* check prerequisites if any */
  644. X   {
  645. X      /* Use the real name instead of basename, this prevents silly
  646. X       * loops in inference code, and is consistent with man page */
  647. X      name = cp->CE_NAME;
  648. X
  649. X      /* Here we loop through each directory on the list, and try to stat
  650. X       * the target.  We always save the first pathname we try and stat in
  651. X       * _first.  If we subsequently get a match we then replace the value of
  652. X       * _first by the matched path name.  */
  653. X
  654. X      for( lp=sp->CE_PRQ; lp != NIL(LINK) && !res; lp=lp->cl_next ) {
  655. X     int  nodup = 0;
  656. X     dir  = lp->cl_prq->CE_NAME;
  657. X
  658. X     if( strchr( dir, '$' ) ) dir = Expand(dir);
  659. X     if( strcmp( dir, ".NULL" ) == 0 ) {
  660. X        nodup = 1;
  661. X        path = cp->CE_NAME;
  662. X     }
  663. X     else
  664. X        path = Build_path( dir, name );
  665. X
  666. X     res = ((cp->ce_time = DO_STAT(path,NIL(char),NIL(char *))) != (time_t)0L);
  667. X
  668. X     /* Have to use _strdup to set _first since Build_path, builds it's
  669. X      * path names inside a static buffer. */
  670. X     if( setfname )
  671. X        if( (_first == NIL(char) && !fset) || res ) {
  672. X           if( _first != NIL(char) ) FREE( _first );
  673. X           _first = nodup ? NIL(char) : _strdup(path);
  674. X           fset = 1;
  675. X        }
  676. X
  677. X     DB_PRINT( "stat", ("_first [%s], path [%s]", _first, path) );
  678. X     if( dir != lp->cl_prq->CE_NAME )  FREE(dir);
  679. X      }
  680. X   }
  681. X
  682. X   DB_PRINT( "mem", ("%s:-< mem %ld", cp->CE_NAME, (long) coreleft()) );
  683. X   DB_RETURN( res );
  684. X}
  685. SHAR_EOF
  686. chmod 0440 stat.c || echo "restore of stat.c fails"
  687. echo "x - extracting rulparse.c (Text)"
  688. sed 's/^X//' << 'SHAR_EOF' > rulparse.c &&
  689. X
  690. X/* RCS      -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/rulparse.c,v 1.1 90/07/21 11:06:33 dvadura Exp $
  691. X-- SYNOPSIS -- perform semantic analysis on input
  692. X-- 
  693. X-- DESCRIPTION
  694. X--    This code performs semantic analysis on the input, and builds
  695. X--    the complex internal datastructure that is used to represent
  696. X--    the user makefile.
  697. X-- 
  698. X-- AUTHOR
  699. X--      Dennis Vadura, dvadura@watdragon.uwaterloo.ca
  700. X--      CS DEPT, University of Waterloo, Waterloo, Ont., Canada
  701. X--
  702. X-- COPYRIGHT
  703. X--      Copyright (c) 1990 by Dennis Vadura.  All rights reserved.
  704. X-- 
  705. X--      This program is free software; you can redistribute it and/or
  706. X--      modify it under the terms of the GNU General Public License
  707. X--      (version 1), as published by the Free Software Foundation, and
  708. X--      found in the file 'LICENSE' included with this distribution.
  709. X-- 
  710. X--      This program is distributed in the hope that it will be useful,
  711. X--      but WITHOUT ANY WARRANTY; without even the implied warrant of
  712. X--      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  713. X--      GNU General Public License for more details.
  714. X-- 
  715. X--      You should have received a copy of the GNU General Public License
  716. X--      along with this program;  if not, write to the Free Software
  717. X--      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  718. X--
  719. X-- LOG
  720. X--     $Log:    rulparse.c,v $
  721. X * Revision 1.1  90/07/21  11:06:33  dvadura
  722. X * Initial Revision Version 3.5
  723. X * 
  724. X*/
  725. X
  726. X#include <ctype.h>
  727. X#include "extern.h"
  728. X#include "alloc.h"
  729. X#include "db.h"
  730. X
  731. X/* prototypes for local functions */
  732. Xstatic  void    _add_global_prereq ANSI((CELLPTR));
  733. Xstatic    void    _build_graph ANSI((int, CELLPTR, CELLPTR));
  734. Xstatic    char*    _build_meta ANSI((char*));
  735. Xstatic    int    _do_magic ANSI((int, char*, CELLPTR, CELLPTR, int, char*));
  736. Xstatic    void    _do_special ANSI((int, int, int, char*, CELLPTR, CELLPTR,int*));
  737. Xstatic    int    _do_targets ANSI((int, int, char*, CELLPTR, CELLPTR));
  738. Xstatic    int    _is_attribute ANSI((char*));
  739. Xstatic    int    _is_special ANSI((char*));
  740. Xstatic    char*    _is_magic ANSI((char*));
  741. Xstatic    int    _is_percent ANSI((char*));
  742. Xstatic    void    _set_attributes ANSI((int, char*, CELLPTR));
  743. Xstatic    void    _stick_at_head ANSI((HOWPTR, CELLPTR));
  744. Xstatic    void    _set_global_attr ANSI((int, char*));
  745. X
  746. X/* static variables that must persist across invocation of Parse_rule_def */
  747. Xstatic CELLPTR    _sv_targets = NIL(CELL);
  748. Xstatic STRINGPTR  _sv_rules   = NIL(STRING);
  749. Xstatic STRINGPTR  _sv_crule   = NIL(STRING);
  750. Xstatic EDGEPTR    _sv_edgel   = NIL(EDGE);
  751. Xstatic LINKPTR    _sv_glb_prq = NIL(LINK);
  752. Xstatic int      _sp_target  = FALSE;
  753. Xstatic int        _sv_attr;
  754. Xstatic int        _sv_attro;
  755. Xstatic int        _sv_flag;
  756. Xstatic int      _sv_op;
  757. Xstatic char      *_sv_setdir;
  758. Xstatic char      _sv_globprq_only = 0;
  759. X
  760. X
  761. Xint
  762. XParse_rule_def( state )/*
  763. X=========================
  764. X   Parse the rule definition contained in Buffer, and modify the state 
  765. X   if appropriate.  The function returns 0, if the definition is found to
  766. X   be an illegal rule definition, and it returns 1 if it is a rule definition.
  767. X   */
  768. Xint *state;
  769. X{
  770. X   TKSTR     input;        /* input string struct for token search      */
  771. X   CELLPTR    targets;    /* list of targets if any          */
  772. X   CELLPTR    prereq;        /* list of prereq if any          */
  773. X   CELLPTR    prereqtail;    /* tail of prerequisite list          */
  774. X   CELLPTR    cp;        /* temporary cell pointer for list making */
  775. X   char     *result;    /* temporary storage for result            */
  776. X   char        *tok;        /* temporary pointer for tokens          */
  777. X   char         *set_dir;       /* value of setdir attribute              */
  778. X   char        *brk;        /* break char list for Get_token      */
  779. X   char         *firstrcp;      /* first recipe line, from ; in rule line */
  780. X   int          attr;           /* sum of attribute flags for current tgts*/
  781. X   int        op;        /* rule operator              */
  782. X   int        at;        /* temp place to keep an attribute code      */
  783. X   int        special;    /* indicate special targets in rule      */
  784. X   int        percent;    /* indicate percent rule target          */
  785. X   int        mixed_glob_prq; /* indicate mixed %-rule prereq possible  */
  786. X
  787. X   DB_ENTER( "Parse_rule_def" );
  788. X
  789. X   op          = 0;
  790. X   attr       = 0;
  791. X   special    = 0;
  792. X   percent    = 0;
  793. X   set_dir    = NIL( char );
  794. X   targets    = NIL(CELL);
  795. X   prereq     = NIL(CELL);
  796. X   prereqtail = NIL(CELL);
  797. X   mixed_glob_prq = 0;
  798. X
  799. X   /* Check to see if the line is of the form:
  800. X    *    targets : prerequisites; first recipe line
  801. X    * If so remember the first_recipe part of the line. */
  802. X
  803. X   firstrcp = strchr( Buffer, ';' );
  804. X   if( firstrcp != NIL( char ) ) {
  805. X      *firstrcp++ = 0;
  806. X      firstrcp = _strspn( firstrcp, " \t" );
  807. X   }
  808. X
  809. X   result = Expand( Buffer );
  810. X   for( brk=strchr(result,'\\'); brk != NIL(char); brk=strchr(brk,'\\') )
  811. X      if( brk[1] == '\n' )
  812. X     *brk = ' ';
  813. X      else
  814. X         brk++;
  815. X
  816. X   DB_PRINT( "par", ("Scanning: [%s]", result) );
  817. X
  818. X   SET_TOKEN( &input, result );
  819. X   brk = ":-^!";
  820. X   Def_targets = TRUE;
  821. X   
  822. X   /* Scan the input rule line collecting targets, the operator, and any
  823. X    * prerequisites.  Stop when we run out of targets and prerequisites. */
  824. X
  825. X   while( *(tok = Get_token( &input, brk, TRUE )) != '\0' )
  826. X      if( !op ) {
  827. X     /* we are scanning targets and attributes
  828. X      * check to see if token is an operator.  */
  829. X
  830. X     op = Rule_op( tok );
  831. X
  832. X     if( !op ) {
  833. X        /* define a new cell, or get old cell  */
  834. X        cp = Def_cell(tok, NIL(CELL));
  835. X        DB_PRINT( "par", ("tg_cell [%s]", tok) );
  836. X        
  837. X        if( at = _is_attribute( tok ) ) {
  838. X           /* Logically OR the attributes specified into one main
  839. X            * ATTRIBUTE mask. */
  840. X
  841. X           if( at == A_SETDIR )
  842. X              if( set_dir != NIL( char ) )
  843. X                 Fatal( "Only one .SETDIR attribute allowed in rule line" );
  844. X              else
  845. X                 set_dir = _strdup( tok );
  846. X
  847. X           attr |= at;
  848. X        }
  849. X        else {
  850. X           int tmp;
  851. X           
  852. X           tmp = _is_special( tok );
  853. X           if( _is_percent( tok ) ) percent++;
  854. X
  855. X           if( percent )
  856. X              if( targets != NIL(CELL) )
  857. X             Fatal( "Multiple targets are not allowed in %% rules" );
  858. X          else
  859. X             cp->ce_flag |= F_PERCENT;
  860. X
  861. X           if( special )
  862. X              Fatal( "Special target must appear alone", tok );
  863. X           else if( !(cp->ce_flag & F_MARK) ) {
  864. X          cp->ce_link  = targets;  /* targets are stacked in this list*/
  865. X          cp->ce_flag |= F_MARK | F_EXPLICIT;
  866. X          targets      = cp;
  867. X
  868. X          special = tmp;
  869. X           }
  870. X           else if( !(cp->ce_attr & A_LIBRARY) )
  871. X          Warning("Duplicate entry [%s] in target list",cp->CE_NAME);
  872. X        }
  873. X     }
  874. X     else {
  875. X        /* found an operator so empty out break list
  876. X         * and clear mark bits on target list, setting them all to F_USED */
  877. X
  878. X        brk  = "";
  879. X        for( cp=targets; cp != NIL(CELL); cp=cp->ce_link ) {
  880. X           cp->ce_flag ^= F_MARK;
  881. X           cp->ce_flag |= F_USED;
  882. X        }
  883. X
  884. X        Def_targets = FALSE;
  885. X     }
  886. X      }
  887. X      else {
  888. X         /* Scanning prerequisites so build the prerequisite list.  We use
  889. X          * F_MARK flag to make certain we have only a single copy of the
  890. X          * prerequisite in the list */
  891. X
  892. X     cp = Def_cell( tok, NIL(CELL) );
  893. X
  894. X     if( _is_percent( tok ) ) {
  895. X        if( !percent && !attr )
  896. X           Fatal( "Syntax error in %% rule, missing %% target");
  897. X        mixed_glob_prq = 1;
  898. X     }
  899. X
  900. X     if( cp->ce_flag & F_USED ) {
  901. X        if( cp->ce_attr & A_COMPOSITE )
  902. X           continue;
  903. X        else
  904. X           Fatal( "Detected circular dependency in graph at [%s]",
  905. X              cp->CE_NAME );
  906. X     }
  907. X         else if( !(cp->ce_flag & F_MARK) ) {
  908. X        DB_PRINT( "par", ("pq_cell [%s]", tok) );
  909. X        cp->ce_flag |= F_MARK;
  910. X
  911. X        if( prereqtail == NIL(CELL) )    /* keep prereq's in order */
  912. X           prereq = cp;
  913. X        else
  914. X           prereqtail->ce_link = cp;
  915. X
  916. X        prereqtail = cp;
  917. X     }
  918. X     else if( !(cp->ce_attr & A_LIBRARY) )
  919. X        Warning("Duplicate entry [%s] in prerequisite list",cp->CE_NAME);
  920. X      }
  921. X      
  922. X   /* Check to see if we have a percent rule that has only global
  923. X    * prerequisites.  If so then set the flag so that later on, we don't issue
  924. X    * an error if such targets supply an empty set of rules. */
  925. X
  926. X   if( percent && !mixed_glob_prq && (prereq != NIL(CELL)) )
  927. X      _sv_globprq_only = 1;
  928. X
  929. X   /* It's ok to have targets with attributes, and no prerequisites, but it's
  930. X    * not ok to have no targets and no attributes, or no operator */
  931. X
  932. X   if( !op ) {
  933. X      CLEAR_TOKEN( &input );
  934. X      DB_PRINT( "par", ("Not a rule [%s]", Buffer) );
  935. X      DB_RETURN( 0 );
  936. X   }
  937. X
  938. X   if( !attr && targets == NIL(CELL) ) {
  939. X      Fatal( "Missing targets or attributes in rule" );
  940. X      if( set_dir != NIL( char )) FREE( set_dir );
  941. X      DB_RETURN( 0 );
  942. X   }
  943. X
  944. X   /* We have established we have a legal rules line, so we must process it.
  945. X    * In doing so we must handle any special targets.  Special targets must
  946. X    * appear alone possibly accompanied by attributes.
  947. X    * NOTE:  special != 0  ==> targets != NIL(CELL) */
  948. X    
  949. X   if( prereqtail != NIL(CELL) ) prereqtail->ce_link = NIL(CELL);
  950. X
  951. X   /* Clear out MARK bits used in duplicate checking.  I originally wanted
  952. X    * to do this as the lists get processed but that got too error prone
  953. X    * so I bit the bullit and added these two loops. */
  954. X
  955. X   for( cp=prereq;  cp != NIL(CELL); cp=cp->ce_link ) cp->ce_flag &= ~F_MARK;
  956. X   for( cp=targets; cp != NIL(CELL); cp=cp->ce_link ) cp->ce_flag &= ~F_USED;
  957. X
  958. X   /* Check to see if the previous rule line was bound if, not the call
  959. X    * Bind_rules_to_targets to go and bind the line */
  960. X
  961. X   if( _sv_rules != NIL(STRING) ) Bind_rules_to_targets( F_DEFAULT );
  962. X
  963. X   /* Add the first recipe line to the list */
  964. X   if( firstrcp != NIL( char ) )
  965. X      Add_recipe_to_list( firstrcp, TRUE, FALSE );
  966. X
  967. X   if( special )
  968. X      _do_special( special, op, attr, set_dir, targets, prereq, state );
  969. X   else
  970. X      *state = _do_targets( op, attr, set_dir, targets, prereq );
  971. X
  972. X   _sv_op     = op;
  973. X   _sv_setdir = set_dir;
  974. X   DB_RETURN( 1 );
  975. X}
  976. X
  977. X
  978. X
  979. X
  980. Xint
  981. XRule_op( op )/*
  982. X================
  983. X   Check the passed in op string and map it to one of the rule operators */
  984. Xchar *op;
  985. X{
  986. X   int ret = 0;
  987. X
  988. X   DB_ENTER( "rule_op" );
  989. X   
  990. X   if( *op == TGT_DEP_SEP ) {
  991. X      ret = R_OP_CL;
  992. X      op++;
  993. X
  994. X      /* All rule operations begin with a :, but may include any one of the
  995. X       * four modifiers.  In order for the rule to be properly mapped we must
  996. X       * check for each of the modifiers in turn, building up our return bit
  997. X       * string. */
  998. X
  999. X      while( *op && ret )
  1000. X         switch( *op ) {
  1001. X        case ':': ret |= R_OP_DCL; op++; break;
  1002. X        case '!': ret |= R_OP_BG;  op++; break;
  1003. X        case '^': ret |= R_OP_UP;  op++; break;
  1004. X        case '-': ret |= R_OP_MI;  op++; break;
  1005. X
  1006. X        default : ret  = 0;  /* an invalid modifier, chuck whole string */
  1007. X         }
  1008. X
  1009. X      if( *op != '\0' ) ret = 0;
  1010. X   }
  1011. X
  1012. X   DB_RETURN( ret );
  1013. X}
  1014. X
  1015. X
  1016. X
  1017. X
  1018. Xvoid
  1019. XAdd_recipe_to_list( rule, white_too, no_check )/*
  1020. X=================================================
  1021. X        Take the provided string and add it to the list of recipe lines
  1022. X    we are saving to be added to the list of targets we have built
  1023. X    previously.  If white_too == TRUE add the rule EVEN IF it contains only
  1024. X        whitespace. */
  1025. Xchar *rule;
  1026. Xint  white_too;
  1027. Xint  no_check;
  1028. X{
  1029. X   DB_ENTER( "Add_recipe_to_list" );
  1030. X
  1031. X   if( rule != NIL( char ) && (*rule != '\0' || white_too) ) {
  1032. X      DB_PRINT( "par", ("Adding recipe [%s]", rule) );
  1033. X      _sv_crule = Def_recipe( rule, _sv_crule, white_too, no_check );
  1034. X
  1035. X      if( _sv_rules == NIL(STRING) )
  1036. X         _sv_rules = _sv_crule;
  1037. X   }
  1038. X
  1039. X   DB_VOID_RETURN;
  1040. X}
  1041. X
  1042. X
  1043. X
  1044. Xvoid
  1045. XBind_rules_to_targets( flag )/*
  1046. X===============================
  1047. X        Take the rules we have defined and bind them with proper attributes
  1048. X        to the targets that were previously defined in the parse.  The
  1049. X        attributes that get passed here are merged with those that are were
  1050. X        previously defined.  (namely F_SINGLE) */
  1051. Xint flag;
  1052. X{
  1053. X   CELLPTR tg;             /* pointer to current target in list */
  1054. X   LINKPTR lp;           /* pointer to link cell        */
  1055. X   HOWPTR  how;           /* pointer to targets main HOW cell    */
  1056. X   int     magic;          /* TRUE if target is .xxx.yyy form   */
  1057. X   int     tflag;          /* TRUE if we assigned targets here  */
  1058. X
  1059. X   DB_ENTER( "Bind_rules_to_targets" );
  1060. X
  1061. X   /* This line is needed since Parse may call us twice when the last
  1062. X    * GROUP rule appears at the end of file.  In this case the rules
  1063. X    * have already been bound and we want to ignore them. */
  1064. X
  1065. X   if( _sv_targets == NIL(CELL) ) { DB_VOID_RETURN; }
  1066. X
  1067. X   tflag  = FALSE;
  1068. X   flag  |= (_sv_flag & F_SINGLE);
  1069. X
  1070. X   for( tg = _sv_targets; tg != NIL(CELL); tg = tg->ce_link ) {
  1071. X      DB_PRINT( "par", ("Binding to %s, %04x", tg->CE_NAME, tg->ce_flag) );
  1072. X      magic = tg->ce_flag & F_PERCENT;
  1073. X
  1074. X      /* Check to see if we had a rule of the form '%.o : a.h b.h ; xxx'
  1075. X       * In which case we must build a NULL prq node to hold the recipe */
  1076. X
  1077. X      if( _sv_globprq_only && (_sv_rules != NIL(STRING)) )
  1078. X     _build_graph( _sv_op, tg, NIL(CELL) );
  1079. X
  1080. X      /* NOTE:  For targets that are magic we ignore any previously defined
  1081. X       *        rules.  ie. We throw away the old definition and use the new. */
  1082. X
  1083. X      if( !(tg->ce_flag & F_MULTI) && !magic && (tg->CE_RECIPE != NIL(STRING))
  1084. X      && !_sp_target && (_sv_rules != NIL(STRING)) )
  1085. X         Fatal( "Multiply defined recipe for target %s", tg->CE_NAME );
  1086. X
  1087. X      if( (magic || _sp_target) && (_sv_rules == NIL(STRING)) &&
  1088. X      !(tg->ce_flag & F_SPECIAL) && !_sv_globprq_only )
  1089. X         Warning( "Empty recipe for special target %s", tg->CE_NAME );
  1090. X
  1091. X      if( magic ) {
  1092. X     EDGEPTR el;
  1093. X
  1094. X     for( el=_sv_edgel; el != NIL(EDGE); el=el->ed_link ) {
  1095. X        how = el->ed_how;
  1096. X        how->hw_flag |= flag;
  1097. X
  1098. X        _set_attributes( _sv_attro, _sv_setdir, el->ed_tg );
  1099. X
  1100. X        if( _sv_rules != NIL(STRING) ) {
  1101. X           how->hw_recipe  = _sv_rules;
  1102. X           how->hw_attr   |= _sv_attr & (A_SILENT | A_IGNORE);
  1103. X           how->hw_indprq = _sv_glb_prq;
  1104. X        }
  1105. X     }
  1106. X      }
  1107. X      else {
  1108. X     how = tg->CE_HOW;
  1109. X     how->hw_flag |= flag;
  1110. X
  1111. X     if( _sv_rules != NIL(STRING) ) {
  1112. X        how->hw_recipe  = _sv_rules;
  1113. X        how->hw_attr   |= _sv_attr & (A_SILENT | A_IGNORE);
  1114. X        tg->ce_flag    |= F_RULES | F_TARGET;
  1115. X
  1116. X        /* Bind the current set of prerequisites as belonging to the
  1117. X         * original recipe given for the target */
  1118. X
  1119. X        for( lp=how->hw_prq; lp != NIL(LINK); lp = lp->cl_next )
  1120. X          if( !(lp->cl_flag & F_USED) ) lp->cl_flag |= F_TARGET;
  1121. X         }
  1122. X     else
  1123. X        for( lp=how->hw_prq; lp != NIL(LINK); lp = lp->cl_next )
  1124. X          lp->cl_flag |= F_USED;
  1125. X      }
  1126. X
  1127. X      if( !Target && !magic && !(tg->ce_flag & F_SPECIAL) ) {
  1128. X     Add_fringe( tg );
  1129. X
  1130. X     tg->ce_flag |= F_TARGET;
  1131. X     tflag        = TRUE;
  1132. X      }
  1133. X
  1134. X      /* Break since all prerequisites are attached and all targets in the
  1135. X       * .UPDATEALL list point at the same HOW cell. */
  1136. X      if( tg->ce_all != NIL(CELL) ) {
  1137. X     CELLPTR tcp = tg;
  1138. X
  1139. X     /* Make sure all people participating in a .UPDATEALL prerequisite
  1140. X      * get marked as having rules and being a target if appropriate. */
  1141. X     do {
  1142. X        tcp->ce_flag |= tg->ce_flag & (F_RULES|F_TARGET);
  1143. X        tcp = tcp->ce_all;
  1144. X     }
  1145. X     while( tcp != tg );
  1146. X     break;
  1147. X      }
  1148. X   }
  1149. X
  1150. X   if( tflag ) Target = TRUE;
  1151. X   _sv_rules   = NIL(STRING);
  1152. X   _sv_crule   = NIL(STRING);
  1153. X   _sv_targets = NIL(CELL);
  1154. X   _sv_glb_prq = NIL(LINK);
  1155. X   _sv_edgel   = NIL(EDGE);
  1156. X   _sp_target  = FALSE;
  1157. X   _sv_globprq_only = 0;
  1158. X
  1159. X   DB_VOID_RETURN;
  1160. X}
  1161. X
  1162. X
  1163. X
  1164. Xint
  1165. XSet_group_attributes( list )/*
  1166. X==============================
  1167. X    Scan list looking for the standard @ and - (as in recipe line defs)
  1168. X    and set the flags accordingly so that they apply when we bind the
  1169. X    rules to the appropriate targets. */
  1170. Xchar *list;
  1171. X{
  1172. X   int done = FALSE;
  1173. X   int res  = FALSE;
  1174. X
  1175. X   DB_ENTER( "Set_group_attributes" );
  1176. X
  1177. X   while( !done )
  1178. X      switch( *list++ ) {
  1179. X     case '@' : _sv_attr |= A_SILENT; res = TRUE; break;
  1180. X     case '-' : _sv_attr |= A_IGNORE; res = TRUE; break;
  1181. X     case '[' :               res = TRUE; break;
  1182. X
  1183. X         case ' ' :
  1184. X     case '\t': break;
  1185. X
  1186. X     case '\0': done = TRUE; break;
  1187. X
  1188. X     default  : done = TRUE; res = FALSE; break;
  1189. X      }
  1190. X
  1191. X   DB_RETURN( res );
  1192. X}
  1193. X
  1194. X
  1195. X
  1196. Xstatic void
  1197. X_do_special( special, op, attr, set_dir, target, prereq, state )/*
  1198. X==================================================================
  1199. X   Process a special target.  So far the only special targets we have
  1200. X   are those recognized by the _is_special function.
  1201. X
  1202. X   target is always only a single special target.
  1203. X   
  1204. X   NOTE:  For the cases of .IMPORT, and .INCLUDE, the cells created by the
  1205. X         parser are never freed.  This is due to the fact that it is too much
  1206. X      trouble to get them out of the hash table once they are defined, and
  1207. X      if they are per chance used again it will be ok, anyway, since the
  1208. X      cell is not really used by the code below.  */
  1209. X
  1210. Xint    special;
  1211. Xint    op;
  1212. Xint    attr;
  1213. Xchar    *set_dir;
  1214. XCELLPTR target;
  1215. XCELLPTR prereq;
  1216. Xint     *state;
  1217. X{
  1218. X   HASHPTR    hp;        /* pointer to macro def cell        */
  1219. X   CELLPTR    cp;        /* temporary pointer into cells list    */
  1220. X   CELLPTR     dp;        /* pointer to directory dir cell    */
  1221. X   LINKPTR     lp;        /* pointer at prerequisite list     */
  1222. X   char        *dir;        /* current dir to prepend        */
  1223. X   char        *path;        /* resulting path to try to read    */
  1224. X   char     *name;        /* File name for processing a .INCLUDE    */
  1225. X   char        *tmp;        /* temporary string pointer        */
  1226. X   FILE     *fil;        /* File descriptor returned by Openfile    */
  1227. X
  1228. X   DB_ENTER( "_do_special" );
  1229. X
  1230. X   target->ce_flag = F_SPECIAL;    /* mark the target as special */
  1231. X
  1232. X   switch( special ) {
  1233. X      case ST_EXPORT:
  1234. X     for( ; prereq != NIL(CELL); prereq = prereq->ce_link ) {
  1235. X        DB_PRINT( "par", ("Exporting [%s]", prereq->CE_NAME) );
  1236. X        hp = GET_MACRO( prereq->CE_NAME );
  1237. X
  1238. X        if( hp != NIL(HASH) ) {
  1239. X           char *tmpstr = hp->ht_value;
  1240. X
  1241. X           if( tmpstr == NIL(char) ) tmpstr = "";
  1242. X
  1243. X           if( Write_env_string( prereq->CE_NAME, tmpstr ) != 0 )
  1244. X          Warning( "Could not export %s", prereq->CE_NAME );
  1245. X        }
  1246. X     }
  1247. X     break;
  1248. X
  1249. X      case ST_IMPORT:
  1250. X     if( prereq != NIL(CELL) && prereq->ce_link == NIL(CELL) &&
  1251. X         strcmp(prereq->CE_NAME, ".EVERYTHING") == 0 )
  1252. X     {
  1253. X        ReadEnvironment();
  1254. X     }
  1255. X     else {
  1256. X        char *tmpstr;
  1257. X
  1258. X        for( ; prereq != NIL(CELL); prereq = prereq->ce_link ) {
  1259. X           DB_PRINT( "par", ("Importing [%s]", prereq->CE_NAME) );
  1260. X
  1261. X           tmpstr = Read_env_string( prereq->CE_NAME );
  1262. X
  1263. X           if( tmpstr != NIL(char) )
  1264. X          Def_macro( prereq->CE_NAME, tmpstr, M_EXPANDED | M_LITERAL );
  1265. X           else
  1266. X              if( !((Glob_attr | attr) & A_IGNORE) )
  1267. X             Fatal( "Imported macro `%s' not found", prereq->CE_NAME );
  1268. X        }
  1269. X
  1270. X        attr &= ~A_IGNORE;
  1271. X     }
  1272. X     break;
  1273. X
  1274. X      case ST_INCLUDE:
  1275. X      {
  1276. X     int ignore = (Glob_attr | attr) & A_IGNORE;
  1277. X     int pushed = FALSE;
  1278. X     CELL inc;
  1279. X     HASH hcell;
  1280. X
  1281. X     if( prereq == NIL(CELL) )  Fatal( "No .INCLUDE file(s) specified" );
  1282. X
  1283. X     dp = Def_cell( ".INCLUDEDIRS", NIL(CELL) );
  1284. X
  1285. X     if( (attr & A_SETDIR) && *(dir = strchr(set_dir, '=')+1) ) {
  1286. X        hcell.ht_name = ".INCLUDE";
  1287. X        inc.ce_name   = &hcell;
  1288. X        inc.ce_dir    = dir;
  1289. X        pushed = Push_dir( &inc, ignore );
  1290. X     }
  1291. X
  1292. SHAR_EOF
  1293. echo "End of part 4"
  1294. echo "File rulparse.c is continued in part 5"
  1295. echo "5" > s2_seq_.tmp
  1296. exit 0
  1297.  
  1298.