home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume27 / dmake / part32 < prev    next >
Encoding:
Text File  |  1992-01-29  |  40.0 KB  |  1,474 lines

  1. Newsgroups: comp.sources.misc
  2. From: dvadura@plg.waterloo.edu (Dennis Vadura)
  3. Subject:  v27i133:  dmake - dmake Version 3.8, Part32/41
  4. Message-ID: <1992Jan29.164849.1352@sparky.imd.sterling.com>
  5. X-Md4-Signature: 26404e9c6416b5207ceb89bdb00110db
  6. Date: Wed, 29 Jan 1992 16:48:49 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: dvadura@plg.waterloo.edu (Dennis Vadura)
  10. Posting-number: Volume 27, Issue 133
  11. Archive-name: dmake/part32
  12. Environment: Atari-ST, Coherent, Mac, MSDOS, OS/2, UNIX
  13. Supersedes: dmake: Volume 19, Issue 22-58
  14.  
  15. ---- Cut Here and feed the following to sh ----
  16. # this is dmake.shar.32 (part 32 of a multipart archive)
  17. # do not concatenate these parts, unpack them in order with /bin/sh
  18. # file dmake/state.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" != 32; 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/state.c' &&
  34. }
  35. X
  36. X
  37. static int
  38. _my_fgets(buf, size, fp)
  39. char *buf;
  40. int  size;
  41. FILE *fp;
  42. {
  43. X   char *p;
  44. X
  45. X   if( fgets(buf, size, fp) == NULL ) return(0);
  46. X
  47. X   if( (p=strrchr(buf,'\n')) != NIL(char) ) *p='\0';
  48. X   return(1);
  49. }
  50. SHAR_EOF
  51. chmod 0640 dmake/state.c ||
  52. echo 'restore of dmake/state.c failed'
  53. Wc_c="`wc -c < 'dmake/state.c'`"
  54. test 5527 -eq "$Wc_c" ||
  55.     echo 'dmake/state.c: original size 5527, current size' "$Wc_c"
  56. rm -f _shar_wnt_.tmp
  57. fi
  58. # ============= dmake/stdmacs.h ==============
  59. if test -f 'dmake/stdmacs.h' -a X"$1" != X"-c"; then
  60.     echo 'x - skipping dmake/stdmacs.h (File already exists)'
  61.     rm -f _shar_wnt_.tmp
  62. else
  63. > _shar_wnt_.tmp
  64. sed 's/^X//' << 'SHAR_EOF' > 'dmake/stdmacs.h' &&
  65. /* RCS      -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/stdmacs.h,v 1.1 1992/01/24 03:29:36 dvadura Exp $
  66. -- SYNOPSIS -- general use macros.
  67. -- 
  68. -- DESCRIPTION
  69. --     ANSI macro relies on the fact that it can be replaced by (), or by
  70. --    its value, where the value is one value due to the preprocessors
  71. --    handling of arguments that are surrounded by ()'s as a single
  72. --    argument.
  73. --
  74. -- AUTHOR
  75. --      Dennis Vadura, dvadura@watdragon.uwaterloo.ca
  76. --      CS DEPT, University of Waterloo, Waterloo, Ont., Canada
  77. --
  78. -- COPYRIGHT
  79. --      Copyright (c) 1990 by Dennis Vadura.  All rights reserved.
  80. -- 
  81. --      This program is free software; you can redistribute it and/or
  82. --      modify it under the terms of the GNU General Public License
  83. --      (version 1), as published by the Free Software Foundation, and
  84. --      found in the file 'LICENSE' included with this distribution.
  85. -- 
  86. --      This program is distributed in the hope that it will be useful,
  87. --      but WITHOUT ANY WARRANTY; without even the implied warrant of
  88. --      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  89. --      GNU General Public License for more details.
  90. -- 
  91. --      You should have received a copy of the GNU General Public License
  92. --      along with this program;  if not, write to the Free Software
  93. --      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  94. --
  95. -- LOG
  96. --     $Log: stdmacs.h,v $
  97. X * Revision 1.1  1992/01/24  03:29:36  dvadura
  98. X * dmake Version 3.8, Initial revision
  99. X *
  100. */
  101. X
  102. #ifndef    MACROS_h
  103. #define    MACROS_h
  104. X
  105. /* stupid AIX and Mac MPW define __STDC__ as special, but defined(__STDC__) is false, and
  106. X * it's value is nothing */
  107. #if !defined(__STDC__) && !defined(_AIX) && !defined(_MPW)
  108. #define __STDC__ 0
  109. #endif
  110. X
  111. #if __STDC__ || defined(__TURBOC__)
  112. #define    ANSI(x)    x
  113. #else
  114. #define    ANSI(x)    ()
  115. #endif
  116. X
  117. #define    NIL(p)    ((p*)NULL)
  118. X
  119. #if !defined(atarist)
  120. #define    offsetof(type,id) ((size_t)&((type*)NULL)->id)
  121. #endif
  122. X
  123. #define    FALSE    0
  124. #define    TRUE    1
  125. X
  126. #define PUBLIC
  127. X
  128. #endif
  129. X
  130. SHAR_EOF
  131. chmod 0640 dmake/stdmacs.h ||
  132. echo 'restore of dmake/stdmacs.h failed'
  133. Wc_c="`wc -c < 'dmake/stdmacs.h'`"
  134. test 1985 -eq "$Wc_c" ||
  135.     echo 'dmake/stdmacs.h: original size 1985, current size' "$Wc_c"
  136. rm -f _shar_wnt_.tmp
  137. fi
  138. # ============= dmake/struct.h ==============
  139. if test -f 'dmake/struct.h' -a X"$1" != X"-c"; then
  140.     echo 'x - skipping dmake/struct.h (File already exists)'
  141.     rm -f _shar_wnt_.tmp
  142. else
  143. > _shar_wnt_.tmp
  144. sed 's/^X//' << 'SHAR_EOF' > 'dmake/struct.h' &&
  145. /* RCS      -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/struct.h,v 1.1 1992/01/24 03:29:32 dvadura Exp $
  146. -- SYNOPSIS -- structure definitions
  147. -- 
  148. -- DESCRIPTION
  149. --    dmake main data structure definitions.  See each of the individual
  150. --    struct declarations for more detailed information on the defined
  151. --    fields and their use.
  152. -- 
  153. -- AUTHOR
  154. --      Dennis Vadura, dvadura@watdragon.uwaterloo.ca
  155. --      CS DEPT, University of Waterloo, Waterloo, Ont., Canada
  156. --
  157. -- COPYRIGHT
  158. --      Copyright (c) 1990 by Dennis Vadura.  All rights reserved.
  159. -- 
  160. --      This program is free software; you can redistribute it and/or
  161. --      modify it under the terms of the GNU General Public License
  162. --      (version 1), as published by the Free Software Foundation, and
  163. --      found in the file 'LICENSE' included with this distribution.
  164. -- 
  165. --      This program is distributed in the hope that it will be useful,
  166. --      but WITHOUT ANY WARRANTY; without even the implied warrant of
  167. --      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  168. --      GNU General Public License for more details.
  169. -- 
  170. --      You should have received a copy of the GNU General Public License
  171. --      along with this program;  if not, write to the Free Software
  172. --      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  173. --
  174. -- LOG
  175. --     $Log: struct.h,v $
  176. X * Revision 1.1  1992/01/24  03:29:32  dvadura
  177. X * dmake Version 3.8, Initial revision
  178. X *
  179. */
  180. X
  181. #ifndef _STRUCT_INCLUDED_
  182. #define _STRUCT_INCLUDED_
  183. X
  184. typedef uint32 t_attr;
  185. X
  186. /* The following struct is the cell used in the hash table.
  187. X * NOTE:  It contains the actual hash value.  This allows the hash table
  188. X *        insertion to compare hash values and to do a string compare only
  189. X *        for entries that have matching hash_key values.  This elliminates
  190. X *        99.9999% of all extraneous string compare operations when searching
  191. X *        a hash table chain for matching entries.  */
  192. X
  193. typedef struct hcell {
  194. X    struct hcell    *ht_next;    /* next entry in the hash table */
  195. X    char        *ht_name;    /* name of this cell */
  196. X    char        *ht_value;    /* cell value if and */
  197. X    uint32        ht_hash;    /* actual hash_value of cell */
  198. X    int        ht_flag;    /* flags belonging to hash entry */
  199. X
  200. X    /* NOTE: some macros have corresponding variables defined
  201. X     * that control program behaviour.  For these macros a
  202. X     * bit of ht_flag indicates the variable value will be set, and the
  203. X     * type of the value that will be set.
  204. X     *
  205. X     * The struct below contains a mask for bit variables, and a
  206. X     * pointer to the global STATIC location for that variable.
  207. X     * String and char variables point to the same place as ht_value
  208. X     * and must be updated when ht_value changes, bit variables must
  209. X     * have their value recomputed. See Def_macro code for more
  210. X     * details.
  211. X     *
  212. X     * NOTE:  Macro variables and Targets are always distinct.  Thus
  213. X     * the value union contains pointers back at cells that own
  214. X     * a particular name entry.  A conflict in this can never
  215. X     * arise, ie pointers at cells will never be used as
  216. X     * values for a macro variable, since the cell and macro
  217. X     * name spaces are completely distinct. */
  218. X
  219. X    struct {
  220. X        int    mv_mask;    /* bit mask for bit variable      */
  221. X        union {
  222. X             char**    mv_svar;/* ptr to string valued glob var  */
  223. X            char*    mv_cvar;/* ptr to char   valued glob var */
  224. X            t_attr*    mv_bvar;/* ptr to bit    valued glob var */
  225. X             int*    mv_ivar;/* ptr to int    valued glob var  */
  226. X
  227. X            struct {
  228. X               struct tcell*  ht_owner;/* ptr to CELL owning name */
  229. X               struct tcell*  ht_root; /* root ptr for explode */
  230. X            } ht;
  231. X        } val;
  232. X    } var;                /* variable's static equivalent */
  233. } HASH, *HASHPTR;
  234. X
  235. #define MV_MASK        var.mv_mask
  236. #define MV_SVAR     var.val.mv_svar
  237. #define MV_CVAR     var.val.mv_cvar
  238. #define MV_BVAR     var.val.mv_bvar
  239. #define MV_IVAR     var.val.mv_ivar
  240. #define CP_OWNR         var.val.ht.ht_owner
  241. #define CP_ROOT         var.val.ht.ht_root
  242. X
  243. X
  244. X
  245. /* This struct holds the list of temporary files that have been created.
  246. X * It gets unlinked when Quit is called due to an execution error */
  247. typedef struct flst {
  248. X   char        *fl_name;    /* file name         */
  249. X   FILE        *fl_file;    /* the open file    */
  250. X   struct flst  *fl_next;    /* pointer to next file */
  251. } FILELIST, *FILELISTPTR;
  252. X
  253. X
  254. X
  255. /* This is the structure of a target cell in the dag which represents the
  256. X * graph of dependencies.  Each possible target is represented as a cell.
  257. X * 
  258. X * Each cell contains a pointer to the hash table entry for this cell.
  259. X * The hash table entry records the name of the cell. */
  260. X
  261. typedef struct tcell {
  262. X    struct hcell    *ce_name;    /* name of this cell                */
  263. X
  264. X    struct tcell    *ce_all;    /* link for grouping UPDATEALL cells*/
  265. X    struct tcell    *ce_setdir;    /* SETDIR ROOT pointer for this cell*/
  266. X    struct tcell    *ce_link;    /* link for temporary list making   */
  267. X
  268. X    struct lcell    *ce_prq;    /* list of prerequisites for cell   */
  269. X    struct lcell    *ce_indprq;    /* indirect prerequisites for % cell*/
  270. X
  271. X    struct str      *ce_recipe;    /* recipe for making this cell      */
  272. X    FILELISTPTR     ce_files;    /* list of temporary files for cell */
  273. X
  274. X    char         *ce_per;    /* value of % in %-meta expansion   */
  275. X    char        *ce_fname;    /* file name associated with target */
  276. X    char        *ce_lib;    /* archive name, if A_LIBRARYM      */
  277. X    char        *ce_dir;    /* value for .SETDIR attribute      */
  278. X
  279. X    int        ce_count;    /* value for :: recipe set          */
  280. X    int        ce_index;    /* value of count for next :: child */
  281. X    int           ce_flag;    /* all kinds of goodies            */
  282. X    t_attr        ce_attr;    /* attributes for this target        */
  283. X    time_t        ce_time;    /* time stamp value of target if any*/
  284. } CELL, *CELLPTR;
  285. X
  286. #define CE_NAME        ce_name->ht_name
  287. #define CE_RECIPE       ce_recipe
  288. #define CE_PRQ          ce_prq
  289. X
  290. X
  291. /* This struct represents that used by Get_token to return and control
  292. X * access to a token list inside a particular string.  This gives the
  293. X * ability to access non overlapping tokens simultaneously from
  294. X * multiple strings. */
  295. X    
  296. typedef struct {
  297. X    char *tk_str;              /* the string to search for tokens  */
  298. X    char tk_cchar;             /* current char under *str          */
  299. X    int  tk_quote;               /* if we are scanning a quoted str  */
  300. }  TKSTR, *TKSTRPTR;
  301. X
  302. X
  303. X
  304. /* Below is the struct used to represent a string.  It points at possibly
  305. X * another string, since the set of rules for making a target is a collection
  306. X * of strings. */
  307. X
  308. X
  309. typedef struct str {
  310. X    char        *st_string;    /* the string value */
  311. X    struct str    *st_next;    /* pointer to the next string */
  312. X    t_attr        st_attr;    /* attr for rule operations */
  313. } STRING, *STRINGPTR;
  314. X
  315. X
  316. /* The next struct is used to link together prerequisite lists */
  317. X
  318. typedef struct lcell {
  319. X    struct tcell    *cl_prq;    /* link to a prerequisite     */
  320. X    struct lcell    *cl_next;    /* next cell on dependency list */
  321. X    int        cl_flag;    /* flags for link cell        */
  322. } LINK, *LINKPTR;
  323. X
  324. X
  325. X
  326. /* These structs are used in processing of the % rules, and in building
  327. X * the NFA machine that is used to match an arbitrary target string to
  328. X * one of the % rules that is represented by each DFA */
  329. X
  330. typedef int16 statecnt;        /* limits the max number of dfa states    */
  331. X
  332. X
  333. /* Each state of the DFA contains four pieces of information. */
  334. typedef struct st {
  335. X    struct st    *no_match;    /* state to go to if no match */
  336. X    struct st    *match;        /* state to go to if we do match */
  337. X    char        symbol;        /* symbol on which we transit */
  338. X    char        action;        /* action to perform if match */
  339. } STATE, *STATEPTR;
  340. X
  341. X
  342. /* Each DFA machine looks like this.  It must have two pointers that represent
  343. X * the value of % in the matched string, and it contains a pointer into the
  344. X * current state, as well as the array of all states. */
  345. typedef struct {
  346. X    char        *pstart;    /* start of % string match */
  347. X    char        *pend;        /* end of % string match */
  348. X    STATEPTR    c_state;    /* current DFA state */
  349. X    CELLPTR        node;        /* % target represented by this DFA */
  350. X    STATEPTR    states;        /* table of states for the DFA */
  351. } DFA, *DFAPTR;
  352. X
  353. X
  354. /* An NFA is a collection of DFA's.  For each DFA we must know it's current
  355. X * state and where the next NFA is. */
  356. typedef struct nfa_machine {
  357. X    DFAPTR        dfa;        /* The DFA for this eps transition */
  358. X    char        status;        /* DFA state */
  359. X    struct nfa_machine *next;     /* the next DFA in NFA */
  360. } NFA, *NFAPTR;
  361. X
  362. X
  363. X
  364. /* The next struct is used to link together DFA nodes for inference. */
  365. X
  366. typedef struct dfal {
  367. X    struct tcell    *dl_meta;    /* link to %-meta cell        */
  368. X    struct dfal    *dl_next;    /* next cell on matched DFA list*/
  369. X    struct dfal    *dl_prev;    /* prev cell on matched DFA list*/
  370. X    struct dfal    *dl_member;    /* used during subset calc    */
  371. X    char        dl_delete;    /* used during subset calc    */
  372. X    char           *dl_per;    /* value of % for matched DFA   */
  373. X    statecnt        dl_state;    /* matched state of the DFA    */
  374. X    int        dl_prep;    /* repetion count for the cell    */
  375. } DFALINK, *DFALINKPTR;
  376. X
  377. X
  378. /* This struct is used to store the stack of DFA sets during inference */
  379. typedef struct dfst {
  380. X   DFALINKPTR    df_set;            /* pointer to the set        */
  381. X   struct dfst *df_next;        /* next element in the stack    */
  382. } DFASET, *DFASETPTR;
  383. X
  384. X
  385. /* We need sets of items during inference, here is the item, we form sets
  386. X * by linking them together. */
  387. X
  388. typedef struct ic {
  389. X   CELLPTR    ic_meta;        /* Edge we used to make this cell*/
  390. X   DFALINKPTR   ic_dfa;            /* Dfa that we matched against     */
  391. X   CELLPTR    ic_setdirroot;        /* setdir root pointer for cell     */
  392. X   DFASET       ic_dfastack;        /* set of dfas we're working with*/
  393. X   int        ic_dmax;        /* max depth of cycles in graph  */
  394. X   char           *ic_name;        /* name of the cell to insert    */
  395. X   char        *ic_dir;            /* dir to CD to prior to recurse */
  396. X   struct ic   *ic_next;        /* next pointer to link         */
  397. X   struct ic   *ic_link;        /* link all ICELL'S together     */
  398. X   struct ic   *ic_parent;        /* pointer to post-requisite     */
  399. X   char        ic_flag;        /* flag, used for NOINFER only     */
  400. X   char         ic_exists;        /* TRUE if prerequisite exists     */
  401. } ICELL, *ICELLPTR;
  402. X
  403. #endif
  404. SHAR_EOF
  405. chmod 0640 dmake/struct.h ||
  406. echo 'restore of dmake/struct.h failed'
  407. Wc_c="`wc -c < 'dmake/struct.h'`"
  408. test 9761 -eq "$Wc_c" ||
  409.     echo 'dmake/struct.h: original size 9761, current size' "$Wc_c"
  410. rm -f _shar_wnt_.tmp
  411. fi
  412. # ============= dmake/sysintf.c ==============
  413. if test -f 'dmake/sysintf.c' -a X"$1" != X"-c"; then
  414.     echo 'x - skipping dmake/sysintf.c (File already exists)'
  415.     rm -f _shar_wnt_.tmp
  416. else
  417. > _shar_wnt_.tmp
  418. sed 's/^X//' << 'SHAR_EOF' > 'dmake/sysintf.c' &&
  419. /* RCS      -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/sysintf.c,v 1.1 1992/01/24 03:27:08 dvadura Exp $
  420. -- SYNOPSIS -- system independent interface
  421. -- 
  422. -- DESCRIPTION
  423. --    These are the routines constituting the system interface.
  424. --    The system is taken to be essentially POSIX conformant.
  425. --    The original code was extensively revised by T J Thompson at MKS,
  426. --    and the library cacheing was added by Eric Gisin at MKS.  I then
  427. --    revised the code yet again, to improve the lib cacheing, and to
  428. --    make it more portable.
  429. --
  430. --    The following is a list of routines that are required by this file
  431. --    in order to work.  These routines are provided as functions by the
  432. --    standard C lib of the target system or as #defines in system/sysintf.h
  433. --    or via appropriate C code in the system/ directory for the given
  434. --    system.
  435. --
  436. --    The first group must be provided by a file in the system/ directory
  437. --    the second group is ideally provided by the C lib.  However, there
  438. --    are instances where the C lib implementation of the specified routine
  439. --    does not exist, or is incorrect.  In these instances the routine
  440. --    must be provided by the the user in the system/ directory of dmake.
  441. --    (For example, the bsd/ dir contains code for putenv(), and tempnam())
  442. --
  443. --    DMAKE SPECIFIC:
  444. --        seek_arch()
  445. --        touch_arch()
  446. --        void_lcache()
  447. --        runargv()
  448. --        STAT()
  449. --        Remove_prq()
  450. --
  451. --    C-LIB SPECIFIC:  (should be present in your C-lib)
  452. --        utime()
  453. --        time()
  454. --        getenv()
  455. --        putenv()
  456. --        getcwd()
  457. --        signal()
  458. --        chdir()
  459. --        tempnam()
  460. -- 
  461. -- AUTHOR
  462. --      Dennis Vadura, dvadura@watdragon.uwaterloo.ca
  463. --      CS DEPT, University of Waterloo, Waterloo, Ont., Canada
  464. --
  465. -- COPYRIGHT
  466. --      Copyright (c) 1990 by Dennis Vadura.  All rights reserved.
  467. -- 
  468. --      This program is free software; you can redistribute it and/or
  469. --      modify it under the terms of the GNU General Public License
  470. --      (version 1), as published by the Free Software Foundation, and
  471. --      found in the file 'LICENSE' included with this distribution.
  472. -- 
  473. --      This program is distributed in the hope that it will be useful,
  474. --      but WITHOUT ANY WARRANTY; without even the implied warrant of
  475. --      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  476. --      GNU General Public License for more details.
  477. -- 
  478. --      You should have received a copy of the GNU General Public License
  479. --      along with this program;  if not, write to the Free Software
  480. --      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  481. --
  482. -- LOG
  483. --     $Log: sysintf.c,v $
  484. X * Revision 1.1  1992/01/24  03:27:08  dvadura
  485. X * dmake Version 3.8, Initial revision
  486. X *
  487. */
  488. X
  489. #include "extern.h"
  490. #include "sysintf.h"
  491. X
  492. /*
  493. ** Tries to stat the file name.  Returns 0 if the file
  494. ** does not exist.  Note that if lib is not null it tries to stat
  495. ** the name found inside lib.
  496. **
  497. ** If member is NOT nil then look for the library object which defines the
  498. ** symbol given by name.  If found _strdup the name and return make the
  499. ** pointer pointed at by sym point at it.  Not handled for now!
  500. */
  501. PUBLIC time_t
  502. Do_stat(name, lib, member)
  503. char *name;
  504. char *lib;
  505. char **member;
  506. {
  507. X   struct stat buf;
  508. X   time_t seek_arch();
  509. X
  510. X   if( member != NIL(char *) )
  511. X      Fatal("Library symbol names not supported");
  512. X
  513. X   buf.st_mtime = (time_t)0L;
  514. X   if( lib != NIL(char) )
  515. X      return( seek_arch(basename(name), lib) );
  516. X   else if( strlen(basename(name)) > _POSIX_NAME_MAX )
  517. X      return((time_t)0L);
  518. X   else
  519. X      return( (STAT(name,&buf)==-1 || (Augmake && (buf.st_mode & S_IFDIR)))
  520. X          ? (time_t)0L
  521. X          : (time_t) buf.st_mtime
  522. X        );
  523. }
  524. X
  525. X
  526. X
  527. /* Touch existing file to force modify time to present.
  528. X */
  529. PUBLIC int
  530. Do_touch(name, lib, member)
  531. char *name;
  532. char *lib;
  533. char **member;
  534. {
  535. X   if( member != NIL(char *) )
  536. X      Fatal("Library symbol names not supported");
  537. X
  538. X   if (lib != NIL(char))
  539. X      return( touch_arch(basename(name), lib) );
  540. X   else
  541. X      return( utime(name, NIL(time_t)) );
  542. }
  543. X
  544. X
  545. X
  546. PUBLIC void
  547. Void_lib_cache( lib_name, member_name )/*
  548. =========================================
  549. X   Void the library cache for lib lib_name, and member member_name. */
  550. char *lib_name;
  551. char *member_name;
  552. {
  553. X   VOID_LCACHE( lib_name, member_name );
  554. }
  555. X
  556. X
  557. X
  558. /*
  559. ** return the current time
  560. */
  561. PUBLIC time_t
  562. Do_time()
  563. {
  564. X   extern time_t time();
  565. X   return (time((time_t*)0));
  566. }
  567. X
  568. X
  569. X
  570. /*
  571. ** Execute the string passed in as a command and return
  572. ** the return code. The command line arguments are
  573. ** assumed to be separated by spaces or tabs.  The first
  574. ** such argument is assumed to be the command.
  575. **
  576. ** If group is true then this is a group of commands to be fed to the
  577. ** the shell as a single unit.  In this case cmd is of the form
  578. ** "file" indicating the file that should be read by the shell
  579. ** in order to execute the command group.
  580. */
  581. PUBLIC int
  582. Do_cmnd(cmd, group, do_it, target, ignore, shell, last)
  583. char   *cmd;
  584. int     group;
  585. int    do_it;
  586. CELLPTR target;
  587. int     ignore;
  588. int     shell;
  589. int    last;
  590. {
  591. X   int  i;
  592. X
  593. X   if( !do_it ) {
  594. X      if( last && !Doing_bang ) {
  595. X         Update_time_stamp( target );
  596. X      }
  597. X      return(0);
  598. X   }
  599. X
  600. X   if( Max_proc == 1 ) Wait_for_completion = TRUE;
  601. X
  602. X   if( (i = runargv(target, ignore, group, last, shell, cmd)) == -1 )
  603. X      Quit();
  604. X
  605. X   /* NOTE:  runargv must return either 0 or 1, 0 ==> command executed, and
  606. X    * we waited for it to return, 1 ==> command started and is running
  607. X    * concurrently with make process. */
  608. X   return(i);
  609. }
  610. X
  611. X
  612. #define MINARGV 64
  613. /* Take a command and pack it into an argument vector to be executed. */
  614. PUBLIC char **
  615. Pack_argv( group, shell, cmd )
  616. int    group;
  617. int    shell;
  618. char  *cmd;
  619. {
  620. X   static char **av = NIL(char *);
  621. X   static int   avs = 0;
  622. X   int i = 0;
  623. X
  624. X   if( av == NIL(char *) ) {
  625. X      TALLOC(av, MINARGV, char*);
  626. X      avs = MINARGV;
  627. X   }
  628. X
  629. X   if( (Packed_shell = shell||group||(*_strpbrk(cmd, Shell_metas)!='\0')) ) {
  630. X      char* sh = group ? GShell : Shell;
  631. X
  632. X      if( sh != NIL(char) ) {
  633. X         av[i++] = sh;
  634. X         if( (av[i] = (group?GShell_flags:Shell_flags)) != NIL(char) ) i++;
  635. X
  636. X     av[i++] = cmd;
  637. X     av[i]   = NIL(char);
  638. X      }
  639. X      else
  640. X     Fatal("%sSHELL macro not defined", group?"GROUP":"");
  641. X   }
  642. X   else {
  643. X      do {
  644. X         while( iswhite(*cmd) ) ++cmd;
  645. X         if( *cmd ) av[i++] = cmd;
  646. X
  647. X         while( *cmd != '\0' && !iswhite(*cmd) ) ++cmd;
  648. X         if( *cmd ) *cmd++ = '\0';
  649. X
  650. X     if( i == avs ) {
  651. X        avs += MINARGV;
  652. X        av = (char **) realloc( av, avs*sizeof(char *) );
  653. X     }
  654. X      } while( *cmd );
  655. X
  656. X      av[i] = NIL(char);
  657. X   }
  658. X
  659. X   return(av);
  660. }
  661. X
  662. X
  663. /*
  664. ** Return the value of ename from the environment
  665. ** if ename is not defined in the environment then
  666. ** NIL(char) should be returned
  667. */
  668. PUBLIC char *
  669. Read_env_string(ename)
  670. char *ename;
  671. {
  672. #if !defined(_MSC_VER) || _MSC_VER < 600
  673. X   extern char *getenv();
  674. #endif
  675. X   return( getenv(ename) );
  676. }
  677. X
  678. X
  679. X
  680. /*
  681. ** Set the value of the environment string ename to value.
  682. **  Returns 0 if success, non-zero if failure
  683. */
  684. PUBLIC int
  685. Write_env_string(ename, value)
  686. char *ename;
  687. char *value;
  688. {
  689. X   extern int putenv();
  690. X   char*   p;
  691. X   char*   envstr = _stradd(ename, value, FALSE);
  692. X
  693. X   p = envstr+strlen(ename);    /* Don't change this code, _stradd does not */
  694. X   *p++ = '=';            /* add the space if *value is 0, it does    */
  695. X   if( !*value ) *p = '\0';    /* allocate enough memory for one though.   */
  696. X
  697. X   return( putenv(envstr) );
  698. }
  699. X
  700. X
  701. X
  702. PUBLIC void
  703. ReadEnvironment()
  704. {
  705. X   extern char **Rule_tab;
  706. #if !defined(_MSC_VER)
  707. X   extern char **environ;
  708. #endif
  709. X   char **rsave;
  710. X
  711. #if !defined(__ZTC__) && !defined(_MPW)
  712. # define make_env()
  713. # define free_env()
  714. #else
  715. X   void make_env();
  716. X   void free_env();
  717. #endif
  718. X
  719. X   make_env();
  720. X
  721. X   rsave    = Rule_tab;
  722. X   Rule_tab = environ;
  723. X   Readenv  = TRUE;
  724. X
  725. X   Parse( NIL(FILE) );
  726. X
  727. X   Readenv  = FALSE;
  728. X   Rule_tab = rsave;
  729. X
  730. X   free_env();
  731. }
  732. X
  733. X
  734. X
  735. /*
  736. ** All we have to catch is SIG_INT
  737. */
  738. PUBLIC void
  739. Catch_signals(fn)
  740. void (*fn)();
  741. {
  742. X   if( signal(SIGINT, SIG_IGN) != SIG_IGN )
  743. X      signal( SIGINT, fn );
  744. X   if( signal(SIGQUIT, SIG_IGN) != SIG_IGN )
  745. X      signal( SIGQUIT, fn );
  746. }
  747. X
  748. X
  749. X
  750. /*
  751. ** Clear any previously set signals
  752. */
  753. PUBLIC void
  754. Clear_signals()
  755. {
  756. X   if( signal(SIGINT, SIG_IGN) != SIG_IGN )
  757. X      signal( SIGINT, SIG_DFL );
  758. X   if( signal(SIGQUIT, SIG_IGN) != SIG_IGN )
  759. X      signal( SIGQUIT, SIG_DFL );
  760. }
  761. X
  762. X
  763. X
  764. /*
  765. ** Set program name
  766. */
  767. PUBLIC void
  768. Prolog(argc, argv)
  769. int   argc;
  770. char* argv[];
  771. {
  772. X   char buf[50];
  773. X
  774. X   Pname = (argc == 0) ? DEF_MAKE_PNAME : argv[0];
  775. X   sprintf( buf, "dmake-%d-root", GETPID );
  776. X   Root = Def_cell( buf );
  777. X   tzset();
  778. }
  779. X
  780. X
  781. X
  782. /*
  783. ** Do any clean up for exit.
  784. */
  785. PUBLIC void
  786. Epilog(ret_code)
  787. int ret_code;
  788. {
  789. X   Write_state();
  790. X   Unlink_temp_files(Root);
  791. X   Hook_std_writes(NIL(char));        /* For MSDOS tee (-F option) */
  792. X   exit( ret_code );
  793. }
  794. X
  795. X
  796. X
  797. /*
  798. ** Use the built-in functions of the operating system to get the current
  799. ** working directory.
  800. */
  801. PUBLIC char *
  802. Get_current_dir()
  803. {
  804. X   static char buf[MAX_PATH_LEN+2];
  805. X   return(getcwd(buf, sizeof(buf)));
  806. }
  807. X
  808. X
  809. X
  810. /*
  811. ** change working directory
  812. */
  813. PUBLIC int
  814. Set_dir(path)
  815. char*   path;
  816. {
  817. X   return( chdir(path) );
  818. }
  819. X
  820. X
  821. X
  822. /*
  823. ** return switch char
  824. */
  825. PUBLIC char
  826. Get_switch_char()
  827. {
  828. X   return( getswitchar() );
  829. }
  830. X
  831. X
  832. X
  833. /*
  834. ** Generate a temporary file name and open the file for writing.
  835. ** If a name cannot be generated or the file cannot be opened
  836. ** return -1, else return the fileno of the open file.
  837. ** and update the source file pointer to point at the new file name.
  838. ** Note that the new name should be freed when the file is removed.
  839. */
  840. PUBLIC FILE*
  841. Get_temp(path, suff, op)
  842. char **path;
  843. char *suff;
  844. int  op;
  845. {
  846. X   extern char *tempnam();
  847. X
  848. X   *path = _strjoin( tempnam(NIL(char), "mk"), suff, -1, TRUE );
  849. X   Def_macro( "TMPFILE", *path, M_MULTI|M_EXPANDED );
  850. X
  851. X   return( op?fopen(*path, "w"):NIL(FILE) );
  852. }
  853. X
  854. X
  855. /*
  856. ** Open a new temporary file and set it up for writing.
  857. */
  858. PUBLIC FILE *
  859. Start_temp( suffix, cp, fname )
  860. char     *suffix;
  861. CELLPTR   cp;
  862. char    **fname;
  863. {
  864. X   FILE           *fp;
  865. X   char        *tmpname;
  866. X   char           *name;
  867. X
  868. X   name = (cp != NIL(CELL))?cp->CE_NAME:"makefile text";
  869. X
  870. X   if( (fp = Get_temp(&tmpname, suffix, TRUE)) == NIL(FILE) )
  871. X      Open_temp_error( tmpname, name );
  872. X
  873. X   Link_temp( cp, fp, tmpname );
  874. X   *fname = tmpname;
  875. X
  876. X   return( fp );
  877. }
  878. X
  879. X
  880. /*
  881. ** Issue an error on failing to open a temporary file
  882. */
  883. PUBLIC void
  884. Open_temp_error( tmpname, name )
  885. char *tmpname;
  886. char *name;
  887. {
  888. X   Fatal("Cannot open temp file `%s' while processing `%s'", tmpname, name );
  889. }
  890. X
  891. X
  892. /*
  893. ** Link a temp file onto the list of files.
  894. */
  895. PUBLIC void
  896. Link_temp( cp, fp, fname )
  897. CELLPTR cp;
  898. FILE   *fp;
  899. char   *fname;
  900. {
  901. X   FILELISTPTR new;
  902. X
  903. X   if( cp == NIL(CELL) ) cp = Root;
  904. X
  905. X   TALLOC( new, 1, FILELIST );
  906. X
  907. X   new->fl_next = cp->ce_files;
  908. X   new->fl_name = fname;
  909. X   new->fl_file = fp;        /* indicates temp file is open */
  910. X
  911. X   cp->ce_files = new;
  912. }
  913. X
  914. X
  915. /*
  916. ** Close a previously used temporary file.
  917. */
  918. PUBLIC void
  919. Close_temp(cp, file)
  920. CELLPTR cp;
  921. FILE    *file;
  922. {
  923. X   FILELISTPTR fl;
  924. X   if( cp == NIL(CELL) ) cp = Root;
  925. X
  926. X   for( fl=cp->ce_files; fl && fl->fl_file != file; fl=fl->fl_next );
  927. X   if( fl ) {
  928. X      fl->fl_file = NIL(FILE);
  929. X      fclose(file);
  930. X   }
  931. }
  932. X
  933. X
  934. /*
  935. ** Clean-up, and close all temporary files associated with a target.
  936. */
  937. PUBLIC void
  938. Unlink_temp_files( cp )/*
  939. ==========================
  940. X   Unlink the tempfiles if any exist.  Make sure you close the files first
  941. X   though.  This ensures that under DOS there is no disk space lost. */
  942. CELLPTR cp;
  943. {
  944. X   FILELISTPTR cur, next;
  945. X
  946. X   if( cp == NIL(CELL) || cp->ce_files == NIL(FILELIST) ) return;
  947. X
  948. X   for( cur=cp->ce_files; cur != NIL(FILELIST); cur=next ) {
  949. X      next = cur->fl_next;
  950. X
  951. X      if( cur->fl_file ) fclose( cur->fl_file );
  952. X
  953. X      if( Verbose & V_LEAVE_TMP )
  954. X         printf( "%s:  Left temp file [%s]\n", Pname, cur->fl_name );
  955. X      else
  956. X         (void) Remove_file( cur->fl_name );
  957. X
  958. X      FREE(cur->fl_name);
  959. X      FREE(cur);
  960. X   }
  961. X
  962. X   cp->ce_files = NIL(FILELIST);
  963. }
  964. X
  965. X
  966. PUBLIC void
  967. Handle_result(status, ignore, abort_flg, target)
  968. int    status;
  969. int    ignore;
  970. int    abort_flg;
  971. CELLPTR target;
  972. {
  973. X   status = ((status&0xff)==0 ? status>>8
  974. X        : (status & 0xff)==SIGTERM ? -1
  975. X        : (status & 0x7f)+128);
  976. X
  977. X   if( status )
  978. X      if( !abort_flg ) {
  979. X     fprintf( stderr, "%s:  Error code %d, while making '%s'",
  980. X          Pname, status, target->ce_fname );
  981. X
  982. X     if( ignore || Continue ) {
  983. X        fputs( " (Ignored)\n", stderr );
  984. X     }
  985. X     else {
  986. X        fputc( '\n', stderr );
  987. X
  988. X        if( !(target->ce_attr & A_PRECIOUS) )
  989. X           if( Remove_file( target->ce_fname ) == 0 )
  990. X          fprintf(stderr,"%s:  '%s' removed.\n",Pname,target->ce_fname);
  991. X
  992. X        Quit();
  993. X     }
  994. X      }
  995. X      else if( !(target->ce_attr & A_PRECIOUS) )
  996. X     Remove_file( target->ce_fname );
  997. }
  998. X
  999. X
  1000. PUBLIC void
  1001. Update_time_stamp( cp )
  1002. CELLPTR cp;
  1003. {
  1004. X   HASHPTR hp;
  1005. X   CELLPTR tcp;
  1006. X   int     tmpflg; 
  1007. X   int     phony = ((cp->ce_attr&A_PHONY) != 0);
  1008. X
  1009. X   tcp = cp;
  1010. X   do {
  1011. X      if( tcp->ce_attr & A_LIBRARY )
  1012. X     Void_lib_cache( tcp->ce_fname, NIL(char) );
  1013. X      else if( !Touch && (tcp->ce_attr & A_LIBRARYM) )
  1014. X     Void_lib_cache( tcp->ce_lib, tcp->ce_fname );
  1015. X
  1016. X      if( !phony )
  1017. X     Stat_target(tcp, -1);
  1018. X
  1019. X      if( tcp->ce_time == (time_t) 0L )
  1020. X     tcp->ce_time = Do_time();
  1021. X
  1022. X      if( Trace )
  1023. X     tcp->ce_flag |= F_STAT;        /* pretend we stated ok */
  1024. X
  1025. X      if( Verbose & V_MAKE )
  1026. X     printf( "%s:  <<<< Set [%s] time stamp to %ld\n",
  1027. X         Pname, tcp->CE_NAME, tcp->ce_time );
  1028. X
  1029. X      Unlink_temp_files( tcp );
  1030. X      tcp->ce_flag |= F_MADE;
  1031. X      tcp->ce_attr |= A_UPDATED;
  1032. X      tcp = tcp->ce_all;
  1033. X   }
  1034. X   while( tcp != NIL(CELL) && tcp != cp );
  1035. X
  1036. X
  1037. X   /* Scan the list of prerequisites and if we find one that is
  1038. X    * marked as being removable, (ie. an inferred intermediate node
  1039. X    * then remove it.  We remove a prerequisite by running the recipe
  1040. X    * associated with the special target .REMOVE, with $< set to
  1041. X    * the list of prerequisites to remove. */
  1042. X
  1043. X   /* Make sure we don't try to remove prerequisites for the .REMOVE
  1044. X    * target. */
  1045. X   if( strcmp(cp->CE_NAME,".REMOVE") != 0 &&
  1046. X       (hp = Get_name( ".REMOVE", Defs, FALSE )) != NIL(HASH) ) {
  1047. X      register LINKPTR dp;
  1048. X      int flag = FALSE;
  1049. X      int rem;
  1050. X      t_attr attr;
  1051. X
  1052. X      tcp = hp->CP_OWNR;
  1053. X
  1054. X      tcp->ce_flag |= F_TARGET;
  1055. X      Clear_prerequisites( tcp );
  1056. X
  1057. X      for( dp = cp->ce_prq; dp != NIL(LINK); dp = dp->cl_next ) {
  1058. X     register CELLPTR prq = dp->cl_prq;
  1059. X
  1060. X     attr = Glob_attr | prq->ce_attr;
  1061. X     rem  = (prq->ce_flag & F_REMOVE) &&
  1062. X        (prq->ce_flag & F_MADE  ) &&
  1063. X        !(prq->ce_attr & A_PHONY) &&
  1064. X        !(attr & A_PRECIOUS) &&
  1065. X        !Force;
  1066. X
  1067. X     if( rem ) {
  1068. X        CELLPTR tmp = prq;
  1069. X        do {
  1070. X           (Add_prerequisite(tcp,prq,FALSE,FALSE))->cl_flag |= F_TARGET;
  1071. X           prq->ce_flag &= ~F_REMOVE;
  1072. X           prq = prq->ce_all;
  1073. X        }
  1074. X        while( prq != NIL(CELL) && prq != tmp );
  1075. X        flag = TRUE;
  1076. X     }
  1077. X      }
  1078. X
  1079. X      if( flag ) {
  1080. X     Remove_prq( tcp );
  1081. X
  1082. X     for( dp=tcp->ce_prq; dp != NIL(LINK); dp=dp->cl_next ) {
  1083. X        register CELLPTR prq = dp->cl_prq;
  1084. X
  1085. X        prq->ce_flag &= ~(F_MADE|F_VISITED|F_STAT);
  1086. X        prq->ce_flag |= F_REMOVE;
  1087. X        prq->ce_time  = (time_t)0L;
  1088. X     }
  1089. X      }
  1090. X   }
  1091. }
  1092. X
  1093. X
  1094. PUBLIC int
  1095. Remove_file( name )
  1096. char *name;
  1097. {
  1098. X   struct stat buf;
  1099. X
  1100. X   if( stat(name, &buf) != 0 )
  1101. X      return 1;
  1102. X   if( (buf.st_mode & S_IFMT) == S_IFDIR )
  1103. X      return 1;
  1104. X   return(unlink(name));
  1105. }
  1106. SHAR_EOF
  1107. chmod 0640 dmake/sysintf.c ||
  1108. echo 'restore of dmake/sysintf.c failed'
  1109. Wc_c="`wc -c < 'dmake/sysintf.c'`"
  1110. test 15102 -eq "$Wc_c" ||
  1111.     echo 'dmake/sysintf.c: original size 15102, current size' "$Wc_c"
  1112. rm -f _shar_wnt_.tmp
  1113. fi
  1114. # ============= dmake/tos/arlib.c ==============
  1115. if test ! -d 'dmake/tos'; then
  1116.     mkdir 'dmake/tos'
  1117. fi
  1118. if test -f 'dmake/tos/arlib.c' -a X"$1" != X"-c"; then
  1119.     echo 'x - skipping dmake/tos/arlib.c (File already exists)'
  1120.     rm -f _shar_wnt_.tmp
  1121. else
  1122. > _shar_wnt_.tmp
  1123. sed 's/^X//' << 'SHAR_EOF' > 'dmake/tos/arlib.c' &&
  1124. /* RCS      -- $Header: /u2/dvadura/src/generic/dmake/src/tos/arlib.c,v 1.1 1992/01/24 03:27:09 dvadura Exp $
  1125. -- SYNOPSIS -- Unix archive manipulation code.
  1126. -- 
  1127. -- DESCRIPTION
  1128. --     Originally this code was provided by Eric Gisin of MKS.  I took
  1129. --    his code and completely rewrote it adding cacheing of lib members
  1130. --    and other various optimizations.  I kept the overal functional
  1131. --    idea of the library routines as they are similar to those in GNU
  1132. --    make and felt it advantageous to maintain a similar interface.
  1133. --
  1134. -- AUTHOR
  1135. --      Dennis Vadura, dvadura@watdragon.uwaterloo.ca
  1136. --      CS DEPT, University of Waterloo, Waterloo, Ont., Canada
  1137. --
  1138. -- COPYRIGHT
  1139. --      Copyright (c) 1990 by Dennis Vadura.  All rights reserved.
  1140. -- 
  1141. --      This program is free software; you can redistribute it and/or
  1142. --      modify it under the terms of the GNU General Public License
  1143. --      (version 1), as published by the Free Software Foundation, and
  1144. --      found in the file 'LICENSE' included with this distribution.
  1145. -- 
  1146. --      This program is distributed in the hope that it will be useful,
  1147. --      but WITHOUT ANY WARRANTY; without even the implied warrant of
  1148. --      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  1149. --      GNU General Public License for more details.
  1150. -- 
  1151. --      You should have received a copy of the GNU General Public License
  1152. --      along with this program;  if not, write to the Free Software
  1153. --      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  1154. --
  1155. -- LOG
  1156. --     $Log: arlib.c,v $
  1157. X * Revision 1.1  1992/01/24  03:27:09  dvadura
  1158. X * dmake Version 3.8, Initial revision
  1159. X *
  1160. */
  1161. X
  1162. #include <ar.h>
  1163. #include "extern.h"
  1164. #include "sysintf.h"
  1165. X
  1166. /* By defining the defines below it is possible to configure the library
  1167. X * code for library cacheing/non-cacheing, ASCII archive headers, and a full
  1168. X * decode of the ar_hdr fields in the scan_ar function. */
  1169. X
  1170. #define ASCARCH            1    /* ASCII time stored in archive    */
  1171. #define LC            1    /* Turn on library cacheing    */
  1172. #define DECODE_ALL_AR_FIELDS    0    /* decode only fields make needs*/
  1173. X
  1174. #if LC
  1175. #  define FOUND_MEMBER    FALSE
  1176. #else
  1177. #  define FOUND_MEMBER    TRUE
  1178. #  define _cache_member(a, b, c)
  1179. #  define _check_cache(a, b, c, d)    FALSE
  1180. #endif
  1181. X
  1182. #define    MAXFNAME    32    /* Longest file name in archive    */
  1183. #define    MAXMNAME    8    /* Max module name < MAXFNAME    */
  1184. X
  1185. X
  1186. /* This struct is used to pass the library and member information about the
  1187. X * routines that perform the library seeking/cacheing */
  1188. struct ar_args {
  1189. X   char   *lib;
  1190. X   char   *member;
  1191. X   time_t time;
  1192. };
  1193. X
  1194. X
  1195. typedef struct AR {
  1196. X   char    ar_name[MAXFNAME+1];      /* File name */
  1197. X   long    ar_size;                  /* Size in bytes */
  1198. X   time_t  ar_time;                  /* Modification time */
  1199. X
  1200. #ifdef DOS
  1201. X   char    ar_modname[MAXMNAME+1];   /* DOS module name */
  1202. #endif
  1203. X
  1204. #if DECODE_ALL_AR_FIELDS
  1205. X   uint16  ar_mode;                  /* File mode */
  1206. X   uint16  ar_uid;                     /* File owner */
  1207. X   uint16  ar_gid;                   /* File group owner */
  1208. #endif
  1209. } AR, *ARPTR;
  1210. X
  1211. X
  1212. static int ar_scan  ANSI((FILE *,
  1213. X              int (*) ANSI((FILE *, struct AR *, struct ar_args *)),
  1214. X              struct ar_args *));
  1215. static int ar_touch ANSI(( FILE *, time_t ));
  1216. static int time_function  ANSI(( FILE *, struct AR *, struct ar_args * ));
  1217. static int touch_function ANSI(( FILE *, struct AR *, struct ar_args * ));
  1218. X
  1219. #if LC
  1220. static int _cache_member ANSI((char *, char *, time_t));
  1221. static int _check_cache  ANSI((char *, char *, time_t *, int));
  1222. #endif
  1223. X
  1224. /* decoded archive header */
  1225. static AR _ar;
  1226. X
  1227. X
  1228. PUBLIC time_t
  1229. seek_arch(name, lib)/*
  1230. ======================
  1231. X   Look for module 'name' inside 'lib'.  If compiled with cacheing then first
  1232. X   check to see if the specified lib is cached.  If so then return that time
  1233. X   stamp instead of looking into the library. */
  1234. char    *name;
  1235. char     *lib;
  1236. {
  1237. X   FILE   *f;
  1238. X   int    rv;
  1239. X   time_t mtime;
  1240. X   struct ar_args args;
  1241. X
  1242. X   /* Check the cache first (if there is a cache) */
  1243. X   if( _check_cache(name, lib, &mtime, FALSE) )  return( mtime );
  1244. X
  1245. X   /* Open the lib file and perform the scan of the members, looking
  1246. X    * for our particular member.  If cacheing is enabled it will be
  1247. X    * taken care of automatically during the scan. */
  1248. X
  1249. X   args.lib    = lib;
  1250. X   args.member = name;
  1251. X   args.time   = (time_t)0L;
  1252. X
  1253. X   if( (f = fopen(lib, "rb")) == NIL(FILE) ) return( (time_t)0L );
  1254. X   rv = ar_scan(f, time_function, &args );
  1255. X   fclose( f );
  1256. X
  1257. X   if( rv < 0 ) Fatal("(%s): Invalid library format", lib);
  1258. X
  1259. X   return( args.time );
  1260. }
  1261. X
  1262. X
  1263. PUBLIC int
  1264. touch_arch(name, lib)/*
  1265. =======================
  1266. X   Look for module 'name' inside 'lib'.  If compiled with cacheing then first
  1267. X   check to see if the specified lib is cached.  If so then set that time
  1268. X   stamp and write it into the library.  Returns 0 on success, non-zero
  1269. X   on failure. */
  1270. char   *name;
  1271. char   *lib;
  1272. {
  1273. X   FILE   *f;
  1274. X   int    rv;
  1275. X   struct ar_args args;
  1276. X
  1277. X   /* Open the lib file and perform the scan of the members, looking
  1278. X    * for our particular member.  If cacheing is enabled it will be
  1279. X    * taken care of automatically during the scan. */
  1280. X
  1281. X   args.lib    = lib;
  1282. X   args.member = name;
  1283. X   args.time   = (time_t)0L;
  1284. X
  1285. X   if( (f = fopen(lib, "rb+")) == NIL(FILE) ) return( (time_t)1L );
  1286. X   rv = ar_scan(f, touch_function, &args );
  1287. X   fclose( f );
  1288. X
  1289. X   if( rv < 0 ) Fatal("(%s): Invalid library format", lib);
  1290. X
  1291. X   return( 0 );
  1292. }
  1293. X
  1294. X
  1295. X
  1296. static int
  1297. time_function(f, arp, argp)/*
  1298. =============================
  1299. X   get library member's time, if it matches than return it in argp, if
  1300. X   cacheing is enabled than cache the library members also. */
  1301. FILE           *f;      /* library file          */
  1302. struct AR      *arp;    /* library member header */
  1303. struct ar_args *argp;
  1304. {
  1305. X   int rv = _cache_member( arp->ar_name, argp->lib, arp->ar_time );
  1306. X
  1307. X   if( strcmp(argp->member, arp->ar_name) == 0 ) {
  1308. X      argp->time = arp->ar_time;
  1309. X
  1310. X      if( arp->ar_time == 0 && !(Glob_attr & A_SILENT) )
  1311. X         Warning( "(%s): Can't extract library member timestamp; using EPOCH",
  1312. X              argp->member);
  1313. X
  1314. X      return( rv );  /* 1 => no cacheing, 0 => cacheing */
  1315. X   }
  1316. X
  1317. X   return( FALSE ); /* continue scan */
  1318. }
  1319. X
  1320. X
  1321. X
  1322. static int
  1323. touch_function(f, arp, argp)/*
  1324. ==============================
  1325. X   Update library member's time stamp, and write new time value into cache
  1326. X   if required. */
  1327. FILE           *f;      /* library file */
  1328. struct AR      *arp;    /* library member header */
  1329. struct ar_args *argp;
  1330. {
  1331. X   extern time_t time ANSI(( time_t * ));
  1332. X   time_t now = time((time_t*) NULL);  /* Current time.          */
  1333. X
  1334. X   if( strcmp(argp->member, arp->ar_name) == 0 ) {
  1335. X      _check_cache( argp->member, argp->lib, &now, TRUE );
  1336. X      ar_touch(f, now );
  1337. X
  1338. X      return( TRUE );
  1339. X   }
  1340. X
  1341. X   return( FALSE ); /* continue scan */
  1342. }
  1343. X
  1344. X
  1345. X
  1346. X
  1347. static int
  1348. ar_scan(f, function, arg)/*
  1349. ===========================
  1350. X   Scan the opened archive, and call the given function for each member found.
  1351. X   The function will be called with the file positioned at the beginning of
  1352. X   the member and it can read up to arp->ar_size bytes of the archive member.
  1353. X   If the function returns 1, we stop and return 1.  We return 0 at the end
  1354. X   of the archive, or -1 if the archive has invalid format.  This interface
  1355. X   is more general than required by "make", but it can be used by other
  1356. X   utilities.  */
  1357. register FILE *f;
  1358. int      (*function) ANSI((FILE *, struct AR *, struct ar_args *));
  1359. struct ar_args *arg;
  1360. {
  1361. X   extern long atol ANSI((char *));
  1362. X   register char *p;
  1363. X   struct ar_hdr arhdr;   /* external archive header */
  1364. X   off_t         offset;  /* member seek offset      */
  1365. X
  1366. #if ASCARCH
  1367. X   char magic[SARMAG];
  1368. #else
  1369. X   unsigned short word;
  1370. #endif
  1371. X
  1372. X   fseek( f, 0L, 0 );    /* Start at the beginning of the archive file */
  1373. X
  1374. #if ASCARCH
  1375. X   fread( magic, sizeof(magic), 1, f );
  1376. X   if( strncmp(magic, ARMAG, SARMAG) != 0 ) return( -1 );
  1377. #else
  1378. X   fread( (char*)&word, sizeof(word), 1, f );
  1379. X   if( word != ARMAG ) return( -1 );
  1380. #endif
  1381. X
  1382. X   /* scan the library, calling `function' for each member
  1383. X    */
  1384. X   while( 1 ) {
  1385. X      if( fread((char*) &arhdr, sizeof(arhdr), 1, f) != 1 ) break;
  1386. X      offset = ftell(f);
  1387. X      strncpy(_ar.ar_name, arhdr.ar_name, sizeof(arhdr.ar_name));
  1388. X
  1389. X      for( p = &_ar.ar_name[sizeof(arhdr.ar_name)];
  1390. X           --p >= _ar.ar_name && *p == ' ';);
  1391. X
  1392. X      p[1] = '\0';
  1393. X      if( *p == '/' ) *p = 0;     /* Only SysV has trailing '/' */
  1394. X
  1395. #if ASCARCH
  1396. X      if( strncmp(arhdr.ar_fmag, ARFMAG, sizeof(arhdr.ar_fmag)) != 0 )
  1397. X         return( -1 );
  1398. X      _ar.ar_time = atol(arhdr.ar_date);
  1399. X      _ar.ar_size = atol(arhdr.ar_size);
  1400. #else
  1401. X      _ar.ar_time = arhdr.ar_date;
  1402. X      _ar.ar_size = arhdr.ar_size;
  1403. #endif
  1404. X
  1405. X
  1406. #if DECODE_ALL_AR_FIELDS
  1407. #if ASCARCH
  1408. X      _ar.ar_mode = atoi(arhdr.ar_mode);
  1409. X      _ar.ar_uid  = atoi(arhdr.ar_uid);
  1410. X      _ar.ar_gid  = atoi(arhdr.ar_gid);
  1411. #else
  1412. X      _ar.ar_mode = arhdr.ar_mode;
  1413. X      _ar.ar_size = arhdr.ar_size;
  1414. X      _ar.ar_uid = arhdr.ar_uid;
  1415. X      _ar.ar_gid = arhdr.ar_gid;
  1416. #endif
  1417. #endif
  1418. X
  1419. X      if( (*function)(f, &_ar, arg) ) return( 1 );
  1420. X      fseek( f, offset + (_ar.ar_size+1 & ~1L), 0 );
  1421. X   }
  1422. X
  1423. X   if( !feof(f) ) return( -1 );
  1424. X   return 0;
  1425. }
  1426. X
  1427. X
  1428. X
  1429. static int
  1430. ar_touch( f, now )/*
  1431. ====================
  1432. X   touch module header timestamp. */
  1433. FILE   *f;
  1434. time_t now;
  1435. {
  1436. X   struct ar_hdr arhdr;                /* external archive header */
  1437. X
  1438. X   fseek(f, - (off_t) (sizeof(arhdr) - sizeof(arhdr.ar_name)), 1);
  1439. X
  1440. #if ASCARCH
  1441. X   fprintf(f, "%lu", now);
  1442. #else
  1443. X   fwrite((char *)now, sizeof(now), 1, f);
  1444. #endif
  1445. X
  1446. X   return( ferror(f) ? 0 : 1 );
  1447. }
  1448. X
  1449. X
  1450. #if LC
  1451. typedef struct mem {
  1452. X   time_t    m_time;        /* modify time of member*/
  1453. X   struct mem    *m_next;    /* next member in lib    */
  1454. X   char        m_valid;    /* valid cache entry    */
  1455. X   char     m_name[1];    /* lib member name    */
  1456. } MEM, *MEMPTR;
  1457. X
  1458. typedef struct lib {
  1459. X   struct lib    *lb_next;    /* next library in list */
  1460. X   struct mem    *lb_members;    /* list of lib members    */
  1461. X   char        lb_valid;    /* valid cache entry    */
  1462. X   char     *lb_name;    /* library name        */
  1463. } LIB, *LIBPTR;
  1464. X
  1465. static LIBPTR _cache = NIL(LIB);
  1466. static MEMPTR _find_member ANSI(( LIBPTR, char * ));
  1467. SHAR_EOF
  1468. true || echo 'restore of dmake/tos/arlib.c failed'
  1469. fi
  1470. echo 'End of part 32, continue with part 33'
  1471. echo 33 > _shar_seq_.tmp
  1472. exit 0
  1473. exit 0 # Just in case...
  1474.