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

  1. Newsgroups: comp.sources.misc
  2. From: Dennis Vadura <dvadura@watdragon.waterloo.edu>
  3. Subject:  v19i032:  dmake - dmake version 3.7, Part11/37
  4. Message-ID: <1991May10.185852.22718@sparky.IMD.Sterling.COM>
  5. Date: Fri, 10 May 1991 18:58:52 GMT
  6. Approved: kent@sparky.imd.sterling.com
  7.  
  8. Submitted-by: Dennis Vadura <dvadura@watdragon.waterloo.edu>
  9. Posting-number: Volume 19, Issue 32
  10. Archive-name: dmake/part11
  11. Supersedes: dmake-3.6: Volume 15, Issue 52-77
  12.  
  13. ---- Cut Here and feed the following to sh ----
  14. #!/bin/sh
  15. # this is dmake.shar.11 (part 11 of a multipart archive)
  16. # do not concatenate these parts, unpack them in order with /bin/sh
  17. # file dmake/macparse.c continued
  18. #
  19. if test ! -r _shar_seq_.tmp; then
  20.     echo 'Please unpack part 1 first!'
  21.     exit 1
  22. fi
  23. (read Scheck
  24.  if test "$Scheck" != 11; then
  25.     echo Please unpack part "$Scheck" next!
  26.     exit 1
  27.  else
  28.     exit 0
  29.  fi
  30. ) < _shar_seq_.tmp || exit 1
  31. if test -f _shar_wnt_.tmp; then
  32. sed 's/^X//' << 'SHAR_EOF' >> 'dmake/macparse.c' &&
  33. X * dmake Release Version 3.7
  34. X * 
  35. */
  36. X
  37. #include "extern.h"
  38. X
  39. PUBLIC int
  40. Parse_macro( buffer, flag )/*
  41. =============================
  42. X   Parse the string in buffer and define it as a macro if it is a valid macro.
  43. X   Note especially the string .SETDIR= since it is an attribute, but looks a
  44. X   lot like a macro definition.  This would not be a problem if make used
  45. X   white space as token separators, since this is not the case we must do
  46. X   something about it. */
  47. char *buffer;
  48. int  flag;
  49. {
  50. X   register char *tok1;        /* temporary place to keep a token */
  51. X   register char *tok2;        /* temporary place to keep a token */
  52. X   char         *result;    /* temporary pointer for strings   */
  53. X   TKSTR          input;        /* place to scan the buffer from   */
  54. X   HASHPTR      hv;        /* pointer to hash table value       */
  55. X   int          operator;    /* what macro operator do we have  */
  56. X
  57. X   DB_ENTER( "Parse_macro" );
  58. X
  59. X   SET_TOKEN( &input, buffer );
  60. X   tok1 = Get_token( &input, "=+:*", -1 );
  61. X
  62. X   if( Macro_op( tok1 ) ) {
  63. X      Error( "No macro name" );
  64. X      CLEAR_TOKEN( &input );
  65. X      DB_RETURN( 1 );
  66. X   }
  67. X
  68. X   tok1 = _strdup( tok1 );
  69. X   tok2 = Get_token( &input, "=+:*", -1 );
  70. X   if( !(operator = Macro_op(tok2)) || 
  71. X      (!strcmp(tok1, ".SETDIR") &&
  72. X         ((operator != M_OP_CL) || (operator != M_OP_PLCL) ||
  73. X          (operator != M_OP_DFCL))) ) {
  74. X      CLEAR_TOKEN( &input );
  75. X      FREE( tok1 );
  76. X      DB_RETURN( 0 );
  77. X   }
  78. X
  79. X   tok2 = Expand(tok1); FREE(tok1); tok1 = tok2;
  80. X   tok2 = Get_token( &input, NIL( char ), FALSE );
  81. X
  82. X   switch( operator ) {
  83. X      case M_OP_PLCL:
  84. X      tok2 = Expand( tok2 );
  85. X      /* Fall thru */
  86. X
  87. X      case M_OP_PL:
  88. X     /* Add to an existing macro, if it is not defined, though, then
  89. X      * just define a new macro */
  90. X
  91. X     if( (hv = GET_MACRO(tok1)) == NIL(HASH) || hv->ht_value == NIL(char) )
  92. X        Def_macro( tok1, tok2, flag );
  93. X     else {
  94. X        result = _stradd( hv->ht_value, tok2, FALSE );
  95. X        Def_macro( tok1, result, flag );
  96. X        FREE( result );
  97. X     }
  98. X     if( operator == M_OP_PLCL ) FREE(tok2);
  99. X     break;
  100. X
  101. X      case M_OP_DF:
  102. X      if( (hv = GET_MACRO(tok1)) != NIL(HASH) )
  103. X        break;
  104. X     /* else FALLTHRU */
  105. X
  106. X      case M_OP_EQ:
  107. X     Def_macro( tok1, tok2, flag );
  108. X     break;
  109. X
  110. X      case M_OP_DFCL:
  111. X      if( (hv = GET_MACRO(tok1)) != NIL(HASH) )
  112. X        break;
  113. X     /* else FALLTHRU */
  114. X
  115. X      case M_OP_CL:
  116. X     /* If the macro we are assigning from is a single control
  117. X      * macro with nothing else, then we propagate the M_MULTI
  118. X      * flag to the macro we are assigning the value to so that
  119. X      * the same macro can be used to do this over and over. */
  120. X     If_multi = 0;
  121. X     tok2 = Expand( tok2 );
  122. X     Def_macro( tok1, tok2, M_EXPANDED | flag | If_multi );
  123. X     FREE( tok2 );
  124. X     break;
  125. X   }
  126. X        
  127. X   FREE( tok1 );
  128. X
  129. X   DB_RETURN( 1 );
  130. }
  131. X
  132. X
  133. X
  134. PUBLIC int
  135. Macro_op( op )/*
  136. ================
  137. X   Check the passed in op string and map it to one of the macro operators */
  138. char *op;
  139. {
  140. X   int ret = 0;
  141. X
  142. X   DB_ENTER( "macro_op" );
  143. X
  144. X   switch( *op ) {
  145. X      case '=': ret = M_OP_EQ; break;
  146. X      case ':': ret = M_OP_CL; op++; break;
  147. X
  148. X      case '+':
  149. X         ret = M_OP_PL; op++;
  150. X         if( *op == ':' ) { ret = M_OP_PLCL; op++; }
  151. X         break;
  152. X
  153. X      case '*':
  154. X         ret = M_OP_DF; op++;
  155. X         if( *op == ':' ) { ret = M_OP_DFCL; op++; }
  156. X         break;
  157. X   }
  158. X
  159. X   if( *op++ != '=' )
  160. X      ret = 0;
  161. X   else if( *op != '\0' )
  162. X      ret = 0;
  163. X
  164. X   DB_RETURN( ret );
  165. }
  166. X
  167. SHAR_EOF
  168. chmod 0640 dmake/macparse.c ||
  169. echo 'restore of dmake/macparse.c failed'
  170. Wc_c="`wc -c < 'dmake/macparse.c'`"
  171. test 4771 -eq "$Wc_c" ||
  172.     echo 'dmake/macparse.c: original size 4771, current size' "$Wc_c"
  173. rm -f _shar_wnt_.tmp
  174. fi
  175. # ============= dmake/make.bat ==============
  176. if test -f 'dmake/make.bat' -a X"$1" != X"-c"; then
  177.     echo 'x - skipping dmake/make.bat (File already exists)'
  178.     rm -f _shar_wnt_.tmp
  179. else
  180. > _shar_wnt_.tmp
  181. sed 's/^X//' << 'SHAR_EOF' > 'dmake/make.bat' &&
  182. echo off
  183. cls
  184. rem  *** This is the make batchfile that is used under MSDOS to make the
  185. rem  *** first version of dmake.  It isn't pretty but it does work, assuming
  186. rem  *** the compilers have been correctly setup.  See the warning below
  187. rem  *** concerning tlink, if you are making the Turbo C version.
  188. rem
  189. X
  190. if %0%1 == %0 goto error
  191. if %1 == tcc goto mktcc
  192. if %1 == tccswp goto mktccswp
  193. if %1 == bcc goto mkbcc
  194. if %1 == bccswp goto mkbccswp
  195. if %1 == msc40 goto mkmsc40
  196. if %1 == msc40swp goto mkmsc40swp
  197. if %1 == msc50 goto mkmsc50
  198. if %1 == msc50swp goto mkmsc50swp
  199. if %1 == msc51 goto mkmsc51
  200. if %1 == msc51swp goto mkmsc51swp
  201. if %1 == msc60 goto mkmsc60
  202. if %1 == msc60swp goto mkmsc60swp
  203. X
  204. rem label the possible DOS variations for dmake here.
  205. :error
  206. echo MSDOS:  You must specify 'make target' where target is one of:
  207. echo -------------
  208. echo    tcc       - Turbo C 2.0 compile.
  209. echo    tccswp    - Turbo C 2.0 compile of swapping dmake.
  210. echo    bcc       - Borland C++ 2.0 compile.
  211. echo    bccswp    - Borland C++ 2.0 compile of swapping dmake.
  212. echo    msc40     - Microsoft C 4.0 compile.
  213. echo    msc50     - Microsoft C 5.0 compile.
  214. echo    msc51     - Microsoft C 5.1 compile.
  215. echo    msc60     - Microsoft C 6.0 compile.
  216. echo    msc40swp  - Microsoft C 4.0, MASM 5.1 compile of swapping dmake.
  217. echo    msc50swp  - Microsoft C 5.0, MASM 5.1 compile of swapping dmake.
  218. echo    msc51swp  - Microsoft C 5.1, MASM 5.1 compile of swapping dmake.
  219. echo    msc60swp  - Microsoft C 6.0, MASM 5.1 compile of swapping dmake.
  220. goto end
  221. X
  222. rem This is the script that makes dmake using Microsoft C 4.0
  223. :mkmsc40
  224. msdos\mscdos\mk40.bat
  225. goto end
  226. X
  227. :mkmsc40swp
  228. msdos\mscdos\mk40swp.bat
  229. goto end
  230. X
  231. rem This is the script that makes dmake using Microsoft C 5.0
  232. :mkmsc50
  233. msdos\mscdos\mk50.bat
  234. goto end
  235. X
  236. :mkmsc50swp
  237. msdos\mscdos\mk50swp.bat
  238. goto end
  239. X
  240. rem This is the script that makes dmake using Microsoft C 5.1
  241. :mkmsc51
  242. msdos\mscdos\mk51.bat
  243. goto end
  244. X
  245. :mkmsc51swp
  246. msdos\mscdos\mk51swp.bat
  247. goto end
  248. X
  249. rem This is the script that makes dmake using Microsoft C 6.0
  250. :mkmsc60
  251. msdos\mscdos\mk60.bat
  252. goto end
  253. X
  254. :mkmsc60swp
  255. msdos\mscdos\mk60swp.bat
  256. goto end
  257. X
  258. rem This is the script that makes dmake using Turbo C 2.0 or higher.
  259. :mktcc
  260. cls
  261. echo WARNING:
  262. echo    The default response files:
  263. echo        msdos\tccdos\obj.rsp
  264. echo        msdos\tccdos\lib.rsp
  265. echo    contain absolute paths to TURBO-C runtime startup objects, and to
  266. echo    the standard libraries.  You should check that these files contain
  267. echo    the correct path names for your installation of Turbo-C before
  268. echo    proceeding further.  Also check that the mkdir command at the start
  269. echo    of the response file and the copy command at the end of the response
  270. echo    file will work on your system.
  271. echo --
  272. echo Continue if ok, or abort and edit the response files.
  273. pause
  274. msdos\tccdos\mk.bat
  275. goto end
  276. X
  277. :mktccswp
  278. cls
  279. echo WARNING:
  280. echo    The default response files:
  281. echo        msdos\tccdos\objswp.rsp
  282. echo        msdos\tccdos\libswp.rsp
  283. echo    contain absolute paths to TURBO-C runtime startup objects, and to
  284. echo    the standard libraries.  You should check that these files contain
  285. echo    the correct path names for your installation of Turbo-C before
  286. echo    proceeding further.  Also check that the mkdir command at the start
  287. echo    of the response file and the copy command at the end of the response
  288. echo    file will work on your system.
  289. echo --
  290. echo Continue if ok, or abort and edit the response files.
  291. pause
  292. msdos\tccdos\mkswp.bat
  293. goto end
  294. X
  295. rem This is the script that makes dmake using Turbo C++ 2.0.
  296. :mkbcc
  297. cls
  298. echo WARNING:
  299. echo    The default response files:
  300. echo        msdos\bccdos\obj.rsp
  301. echo        msdos\bccdos\lib.rsp
  302. echo    contain absolute paths to Borland C++ runtime startup objects, and to
  303. echo    the standard libraries.  You should check that these files contain
  304. echo    the correct path names for your installation of Borland C++ before
  305. echo    proceeding further.  Also check that the mkdir command at the start
  306. echo    of the response file and the copy command at the end of the response
  307. echo    file will work on your system.
  308. echo --
  309. echo Continue if ok, or abort and edit the response files.
  310. pause
  311. msdos\bccdos\mk.bat
  312. goto end
  313. X
  314. :mkbccswp
  315. cls
  316. echo WARNING:
  317. echo    proceeding further.  Also check that the mkdir command at the start
  318. echo    of the response file and the copy command at the end of the response
  319. echo    file will work on your system.
  320. echo    The default response files:
  321. echo        msdos\bccdos\objswp.rsp
  322. echo        msdos\bccdos\libswp.rsp
  323. echo    contain absolute paths to Borland C++ runtime startup objects, and to
  324. echo    the standard libraries.  You should check that these files contain
  325. echo    the correct path names for your installation of Borland C++ before
  326. echo    proceeding further.  Also check that the mkdir command at the start
  327. echo    of the response file and the copy command at the end of the response
  328. echo    file will work on your system.
  329. echo --
  330. echo Continue if ok, or abort and edit the response files.
  331. pause
  332. msdos\bccdos\mkswp.bat
  333. goto end
  334. X
  335. rem All done!
  336. :end
  337. SHAR_EOF
  338. chmod 0640 dmake/make.bat ||
  339. echo 'restore of dmake/make.bat failed'
  340. Wc_c="`wc -c < 'dmake/make.bat'`"
  341. test 5076 -eq "$Wc_c" ||
  342.     echo 'dmake/make.bat: original size 5076, current size' "$Wc_c"
  343. rm -f _shar_wnt_.tmp
  344. fi
  345. # ============= dmake/make.c ==============
  346. if test -f 'dmake/make.c' -a X"$1" != X"-c"; then
  347.     echo 'x - skipping dmake/make.c (File already exists)'
  348.     rm -f _shar_wnt_.tmp
  349. else
  350. > _shar_wnt_.tmp
  351. sed 's/^X//' << 'SHAR_EOF' > 'dmake/make.c' &&
  352. /* RCS      -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/make.c,v 1.1 91/05/06 15:23:19 dvadura Exp $
  353. -- SYNOPSIS -- perform the update of all outdated targets.
  354. -- 
  355. -- DESCRIPTION
  356. --    This is where we traverse the make graph looking for targets that
  357. --    are out of date, and we try to infer how to make them if we can.
  358. --    The usual make macros are understood, as well as some new ones:
  359. --
  360. --        $$    - expands to $
  361. --        $@      - full target name
  362. --        $*      - target name with no suffix, same as $(@:db)
  363. --              or, the value of % in % meta rule recipes
  364. --        $?      - list of out of date prerequisites
  365. --        $<      - all prerequisites associated with rules line
  366. --        $&    - all prerequisites associated with target
  367. --        $>      - library name for target (if any)
  368. --        $^    - out of date prerequisites taken from value of $<
  369. --        {{    - expands to {
  370. --        }}    - expands to }
  371. --        \#    - expands to #
  372. -- 
  373. -- AUTHOR
  374. --      Dennis Vadura, dvadura@watdragon.uwaterloo.ca
  375. --      CS DEPT, University of Waterloo, Waterloo, Ont., Canada
  376. --
  377. -- COPYRIGHT
  378. --      Copyright (c) 1990 by Dennis Vadura.  All rights reserved.
  379. -- 
  380. --      This program is free software; you can redistribute it and/or
  381. --      modify it under the terms of the GNU General Public License
  382. --      (version 1), as published by the Free Software Foundation, and
  383. --      found in the file 'LICENSE' included with this distribution.
  384. -- 
  385. --      This program is distributed in the hope that it will be useful,
  386. --      but WITHOUT ANY WARRANTY; without even the implied warrant of
  387. --      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  388. --      GNU General Public License for more details.
  389. -- 
  390. --      You should have received a copy of the GNU General Public License
  391. --      along with this program;  if not, write to the Free Software
  392. --      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  393. --
  394. -- LOG
  395. --     $Log:    make.c,v $
  396. X * Revision 1.1  91/05/06  15:23:19  dvadura
  397. X * dmake Release Version 3.7
  398. X * 
  399. */
  400. X
  401. #include "extern.h"
  402. X
  403. static    void    _drop_mac ANSI((HASHPTR));
  404. static    void    _print_cmnd ANSI((char*, int, int));
  405. static    void    _set_recipe ANSI((char*, int));
  406. static    void    _set_tmd ANSI(());
  407. static    void    _append_file ANSI((STRINGPTR, FILE*, char*, int));
  408. static  LINKPTR _dup_prq ANSI((LINKPTR));
  409. static  char*   _prefix ANSI((char *, char *));
  410. static  char*   _pool_lookup ANSI((char *));
  411. X
  412. #define RP_GPPROLOG    0
  413. #define RP_RECIPE    1
  414. #define RP_GPEPILOG    2
  415. #define NUM_RECIPES    3
  416. X
  417. static STRINGPTR _recipes[ NUM_RECIPES ];
  418. X
  419. X
  420. PUBLIC int
  421. Make_targets()/*
  422. ================
  423. X   Actually go and make the targets on the target list */
  424. {
  425. X   LINKPTR lp;
  426. X   int     done = 0;
  427. X
  428. X   DB_ENTER( "Make_targets" );
  429. X
  430. X   Read_state();
  431. X   _set_recipe( ".GROUPPROLOG", RP_GPPROLOG );
  432. X   _set_recipe( ".GROUPEPILOG", RP_GPEPILOG );
  433. X
  434. X   Root->ce_flag  |= F_RULES|F_TARGET|F_STAT;
  435. X   Root->ce_attr  |= A_NOSTATE;
  436. X   Root->ce_time   = Do_time();
  437. X   TALLOC( Root->ce_recipe, 1, STRING );
  438. X   Root->ce_recipe->st_string = "";
  439. X
  440. X   for( lp = Root->ce_prq; lp != NIL(LINK); lp = lp->cl_next )
  441. X      lp->cl_prq->ce_attr |= A_ROOT;
  442. X
  443. X   while( !done ) {
  444. X      int rval;
  445. X
  446. X      if( (rval = Make(Root, NIL(LINK), NIL(CELL))) == -1 )
  447. X     DB_RETURN(1);
  448. X      else
  449. X     done = Root->ce_flag & F_MADE;
  450. X
  451. X      if( !rval && !done ) Wait_for_child( FALSE, -1 );
  452. X   }
  453. X
  454. X   for( lp = Root->ce_prq; lp != NIL(LINK); lp = lp->cl_next ) {
  455. X      CELLPTR root = lp->cl_prq;
  456. X      if( !(root->ce_attr & A_UPDATED) )
  457. X     printf( "`%s' is up to date\n", root->CE_NAME );
  458. X   }
  459. X
  460. X   DB_RETURN( 0 );
  461. }
  462. X
  463. X
  464. X
  465. int
  466. Make( cp, parent, setdirroot )/*
  467. ================================  Make a specified target */
  468. CELLPTR cp;
  469. LINKPTR parent;
  470. CELLPTR setdirroot;
  471. {
  472. X   register LINKPTR dp;
  473. X   register CELLPTR tcp;
  474. X   CELLPTR          nsetdirroot;
  475. X   char            *name, *lib;
  476. X   HASHPTR        m_at, m_q, m_b, m_g, m_l, m_bb, m_up;
  477. X   char             *all    = NIL(char);
  478. X   char             *inf    = NIL(char);
  479. X   char             *outall = NIL(char);
  480. X   char             *imm    = NIL(char);
  481. X   int              rval    = 0;
  482. X   int            push    = 0;
  483. X   int            ignore;
  484. X   time_t           otime   = (time_t) 1L;
  485. X   time_t        ttime   = (time_t) 1L;
  486. X   int            mark_made = FALSE;
  487. X
  488. X   DB_ENTER( "Make" );
  489. X   DB_PRINT( "mem", ("%s:-> mem %ld", cp->CE_NAME, (long) coreleft()) );
  490. X
  491. X   m_q = m_b = m_g = m_l = m_bb = m_up = m_at = NIL(HASH);
  492. X
  493. X   /* Check to see if we have made the node already.  If so then don't do
  494. X    * it again, except if the cell's ce_setdir field is set to something other
  495. X    * than the value of setdirroot.  If they differ then, and we have made it
  496. X    * already, then make it again and set the cell's stat bit to off so that
  497. X    * we do the stat again. */
  498. X
  499. X   if( cp->ce_flag & F_VISITED ) {
  500. X      /* we may return if we made it already from the same setdir location,
  501. X       * or if it is not a library member whose lib field is non NULL.  (if
  502. X       * it is such a member then we have a line of the form:
  503. X       *    lib1 lib2 .LIBRARY : member_list...
  504. X       * and we have to make sure all members are up to date in both libs. */
  505. X
  506. X      if( cp->ce_setdir == setdirroot &&
  507. X      !((cp->ce_attr & A_LIBRARYM) && (cp->ce_lib != NIL(char))) )
  508. X     DB_RETURN( 0 );
  509. X
  510. X
  511. X      /* We check to make sure that we are comming from a truly different
  512. X       * directory, ie. ".SETDIR=joe : a.c b.c d.c" are all assumed to come
  513. X       * from the same directory, even though setdirroot is different when
  514. X       * making dependents of each of these targets. */
  515. X
  516. X      if( cp->ce_setdir != NIL(CELL) && setdirroot != NIL(CELL) &&
  517. X          !strcmp(cp->ce_dir, setdirroot->ce_dir) )
  518. X         DB_RETURN( 0 );
  519. X
  520. X      if( Max_proc > 1 ) {
  521. X     if( parent == NIL(LINK) )
  522. X        Fatal( "Internal Error:  NIL parent in Make()" );
  523. X
  524. X     TALLOC(parent->cl_prq, 1, CELL);
  525. X     *parent->cl_prq = *cp;
  526. X     cp = parent->cl_prq;
  527. X     cp->ce_prq = _dup_prq(cp->ce_prq);
  528. X      }
  529. X      cp->ce_flag  &= ~(F_STAT|F_VISITED|F_MADE);
  530. X   }
  531. X
  532. X
  533. X   /* If we are supposed to change directories for this target then do so.
  534. X    * If we do change dir, then modify the setdirroot variable to reflect
  535. X    * that fact for all of the prerequisites that we will be making. */
  536. X
  537. X   nsetdirroot = setdirroot;
  538. X   ignore = (((cp->ce_attr|Glob_attr)&A_IGNORE) != 0);
  539. X
  540. X   if( cp->ce_attr & A_SETDIR ) {
  541. X      /* Change directory only if the previous .SETDIR is a different
  542. X      /* directory from the current one.  ie. all cells with the same .SETDIR
  543. X      /* attribute are assumed to come from the same directory. */
  544. X
  545. X      if( (setdirroot == NIL(CELL) || setdirroot->ce_dir != cp->ce_dir) &&
  546. X          (push = Push_dir(cp->ce_dir,cp->CE_NAME,ignore)) )
  547. X     setdirroot = cp;
  548. X   }
  549. X
  550. X   DB_PRINT( "mem", ("%s:-A mem %ld", cp->CE_NAME, (long) coreleft()) );
  551. X   if( (cp->ce_recipe == NIL(STRING) && !(cp->ce_flag & F_INFER)) ) {
  552. X      char *dir = cp->ce_dir;
  553. X      
  554. X      if( Verbose & V_MAKE )
  555. X     printf( "%s:  Infering prerequisite(s) and recipe for [%s]\n", Pname,
  556. X          cp->CE_NAME );
  557. X
  558. X      Infer_recipe( cp, setdirroot );
  559. X
  560. X      /* See if the directory has changed, if it has then make sure we
  561. X       * push it. */
  562. X      if( dir != cp->ce_dir ) {
  563. X     if( push ) Pop_dir(FALSE);
  564. X         push = Push_dir( cp->ce_dir, cp->CE_NAME, ignore );
  565. X     setdirroot = cp;
  566. X      }
  567. X   }
  568. X
  569. X   tcp = cp;
  570. X   do {
  571. X      if( push ) {
  572. X     if( tcp->ce_dir ) FREE( tcp->ce_dir );
  573. X     tcp->ce_dir   = _pool_lookup(Pwd);
  574. X     tcp->ce_attr |= A_SETDIR;
  575. X      }
  576. X      tcp->ce_setdir = nsetdirroot;
  577. X      tcp = tcp->ce_all;
  578. X   }
  579. X   while( tcp != NIL(CELL) && tcp != cp );
  580. X
  581. X   DB_PRINT( "mem", ("%s:-A mem %ld", cp->CE_NAME, (long) coreleft()) );
  582. X   /* If we have not yet statted the target then do so. */
  583. X   if( !(cp->ce_flag & F_STAT) && !(cp->ce_attr&A_PHONY) ) {
  584. X      time_t itime = cp->ce_time;
  585. X      Stat_target( cp, TRUE );
  586. X
  587. X      if( cp->ce_time == (time_t)0L ) {
  588. X         if( cp->ce_flag & F_INFER )
  589. X        cp->ce_time = itime;
  590. X      }
  591. X      else
  592. X         cp->ce_attr |= A_PRECIOUS;  /* File exists so don't remove it later. */
  593. X
  594. X      if( Verbose & V_MAKE )
  595. X     printf("%s:  Time stamp of [%s] is %ld\n",Pname,cp->CE_NAME,
  596. X            cp->ce_time);
  597. X   }
  598. X
  599. X   DB_PRINT( "make", ("(%s, %ld, 0x%08x, 0x%04x)", cp->CE_NAME,
  600. X            cp->ce_time, cp->ce_attr, cp->ce_flag) );
  601. X
  602. X   if( !(cp->ce_flag & F_TARGET) && (cp->ce_time == (time_t) 0L) )
  603. X      if( Makemkf ) {
  604. X     rval = -1;
  605. X     goto stop_making_it;
  606. X      }
  607. X      else if(cp->ce_prq != NIL(LINK)||(Augmake && (cp->ce_flag&F_EXPLICIT)))
  608. X     /* Assume an empty recipe for a target that we have run inference on
  609. X      * but do not have a set of rules for but for which we have inferred
  610. X      * a list of prerequisites. */
  611. X     cp->ce_flag |= F_RULES;
  612. X      else
  613. X     Fatal( "`%s' not found, and can't be made", cp->CE_NAME );
  614. X
  615. X   DB_PRINT( "mem", ("%s:-A mem %ld", cp->CE_NAME, (long) coreleft()) );
  616. X
  617. X   /* set value of $* if we have not infered a recipe, in this case $* is
  618. X    * the same as $(@:db), this allows us to be compatible with BSD make */
  619. X   if( cp->ce_per == NIL(char) ) cp->ce_per = "$(@:db)";
  620. X
  621. X   for( dp = cp->ce_prq; dp != NIL(LINK); dp = dp->cl_next ) {
  622. X      int seq;
  623. X
  624. X      /* Make the prerequisite, note that if the current target has the
  625. X       * .LIBRARY attribute set we pass on to the prerequisite the .LIBRARYM
  626. X       * attribute and pass on the name of the current target as the library
  627. X       * name, and we take it away when we are done.  */
  628. X
  629. X      tcp = dp->cl_prq;
  630. X      seq = (((cp->ce_attr | Glob_attr) & A_SEQ) != 0);
  631. X
  632. X      if( tcp->ce_flag & F_VISITED )
  633. X     if( tcp->ce_flag & F_MADE ) {
  634. X        if( tcp->ce_time > ttime ) ttime = tcp->ce_time;
  635. X        continue;
  636. X     }
  637. X     else
  638. X        goto stop_making_it;
  639. X
  640. X      if( strchr(tcp->CE_NAME, '$') ) {
  641. X     /* Make this prerequisite link point at the real prerequisite we
  642. X      * are after, ie figure out what the dynamic one is and point at it. */
  643. X
  644. X     m_at = Def_macro( "@", cp->ce_fname, M_MULTI );
  645. X     name = Expand( tcp->CE_NAME );
  646. X
  647. X     tcp = dp->cl_prq = Def_cell( name );
  648. X     FREE( name );
  649. X      }
  650. X
  651. X      if( cp->ce_attr & A_LIBRARY ) {
  652. X         tcp->ce_attr |= A_LIBRARYM;
  653. X     tcp->ce_lib   = cp->ce_fname;
  654. X      }
  655. X
  656. X      if( (tcp->ce_flag & (F_INFER|F_STAT))==F_INFER && cp->ce_time >= ttime )
  657. X     tcp->ce_time = cp->ce_time;
  658. X
  659. X      /* Propagate parents F_REMOVE and F_INFER attribute to children.
  660. X       * Make certain you do this AFTER propagating the time, since the
  661. X       * time propagation test above uses the F_INFER flag to decide if
  662. X       * it should do so. */
  663. X      tcp->ce_flag |= cp->ce_flag & (F_REMOVE|F_INFER);
  664. X
  665. X      rval |= Make(tcp, dp, setdirroot);
  666. X
  667. X      if( cp->ce_attr & A_LIBRARY )
  668. X         tcp->ce_attr ^= A_LIBRARYM;
  669. X
  670. X      if( rval == -1 || (seq && (rval == 1)) )
  671. X     goto stop_making_it;
  672. X
  673. X      if( tcp->ce_time > ttime ) ttime = tcp->ce_time;
  674. X   }
  675. X
  676. X
  677. X   /* Do the loop again.  We are most definitely going to make the current
  678. X    * cell now.  NOTE:  doing this loop here also results in a reduction
  679. X    * in peak memory usage by the algorithm. */
  680. X
  681. X   for( dp = cp->ce_prq; dp != NIL(LINK); dp = dp->cl_next ) {
  682. X      int  tgflg;
  683. X      tcp  = dp->cl_prq;
  684. X      name = tcp->ce_fname;
  685. X
  686. X      /* make certain that all prerequisites are made prior to advancing. */
  687. X      if( !(tcp->ce_flag & F_MADE) ) goto stop_making_it;
  688. X
  689. X      /* If the target is a library, then check to make certain that a member
  690. X       * is newer than an object file sitting on disk.  If the disk version
  691. X       * is newer then set the time stamps so that the archived member is
  692. X       * replaced. */
  693. X      if( cp->ce_attr & A_LIBRARY )
  694. X     if( tcp->ce_time < cp->ce_time ) {
  695. X        time_t mtime = Do_stat( name, tcp->ce_lib, NIL(char *) );
  696. X        if( mtime < tcp->ce_time ) tcp->ce_time = cp->ce_time+1L;
  697. X     }
  698. X
  699. X      if( tcp->ce_time > otime ) otime = tcp->ce_time;
  700. X
  701. X      all = _strapp( all, name );
  702. X      if( tgflg = (dp->cl_flag & F_TARGET) ) inf = _strapp( inf, name );
  703. X
  704. X      if((cp->ce_time<tcp->ce_time) || ((tcp->ce_flag & F_TARGET) && Force)) {
  705. X         outall = _strapp( outall, name );
  706. X         if( tgflg ) imm = _strapp( imm, name );
  707. X      }
  708. X   }
  709. X
  710. X   DB_PRINT( "mem", ("%s:-C mem %ld", cp->CE_NAME, (long) coreleft()) );
  711. X   DB_PRINT( "make", ("I make '%s' if %ld > %ld", cp->CE_NAME, otime,
  712. X          cp->ce_time) );
  713. X
  714. X   if( Verbose & V_MAKE )
  715. X      printf( "%s:  >>>> Making [%s]\n", Pname, cp->CE_NAME );
  716. X
  717. X   m_at = Def_macro( "@", cp->ce_fname, M_MULTI );
  718. X   m_g  = Def_macro( ">", cp->ce_lib,   M_MULTI );
  719. X   m_q  = Def_macro( "?", outall,       M_MULTI );
  720. X   m_b  = Def_macro( "<", inf,          M_MULTI );
  721. X   m_l  = Def_macro( "&", all,          M_MULTI );
  722. X   m_bb = Def_macro( "*", cp->ce_per,   M_MULTI );
  723. X   m_up = Def_macro( "^", imm,          M_MULTI );
  724. X
  725. X   _recipes[ RP_RECIPE ] = cp->ce_recipe;
  726. X
  727. X   /* We attempt to make the target if
  728. X    *   1. it has a newer prerequisite
  729. X    *   2. It is a target and Force is set
  730. X    *   3. It's set of recipe lines has changed.
  731. X    */
  732. X   if(    Check_state(cp, _recipes, NUM_RECIPES )
  733. X      || (cp->ce_time < otime)
  734. X      || ((cp->ce_flag & F_TARGET) && Force)
  735. X     ) {
  736. X
  737. X      /* Only checking so stop as soon as we determine we will make something */
  738. X      if( Check ) {
  739. X     rval = -1;
  740. X     goto stop_making_it;
  741. X      }
  742. X
  743. X      if( Verbose & V_MAKE )
  744. X     printf( "%s:  Updating [%s], (%ld > %ld)\n", Pname,
  745. X         cp->CE_NAME, otime, cp->ce_time );
  746. X
  747. X      if( Touch ) {
  748. X     name = cp->ce_fname;
  749. X     lib  = cp->ce_lib;
  750. X
  751. X     if( !(Glob_attr & A_SILENT) || !Trace )
  752. X        if( lib == NIL(char) )
  753. X           printf("touch(%s)", name );
  754. X        else if( cp->ce_attr & A_SYMBOL )
  755. X           printf("touch(%s((%s)))", lib, name );
  756. X        else
  757. X           printf("touch(%s(%s))", lib, name );
  758. X
  759. X     if( !Trace )
  760. X        if( Do_touch( name, lib,
  761. X        (cp->ce_attr & A_SYMBOL) ? &name : NIL(char *) ) != 0 )
  762. X           printf( "  not touched - non-existant" );
  763. X
  764. X     printf( "\n" );
  765. X     Update_time_stamp( cp );
  766. X      }
  767. X      else if( cp->ce_recipe != NIL(STRING) ) {
  768. X     if( !(cp->ce_flag & F_SINGLE) )
  769. X           rval = Exec_commands( cp );
  770. X     else {
  771. X        TKSTR tk;
  772. X
  773. X        _drop_mac( m_q );
  774. X        SET_TOKEN( &tk, outall );
  775. X
  776. X        Doing_bang = TRUE;
  777. X        name = Get_token( &tk, "", FALSE );
  778. X        do {
  779. X           m_q->ht_value = name;
  780. X
  781. X           Wait_for_completion = TRUE;    /* Reset in Exec_commands */
  782. X           rval = Exec_commands( cp );
  783. X           Unlink_temp_files(cp);
  784. X        }
  785. X        while( *(name = Get_token( &tk, "", FALSE )) != '\0' );
  786. X        Doing_bang = FALSE;
  787. X        Update_time_stamp( cp );
  788. X
  789. X        m_q->ht_value = NIL(char);
  790. X     }
  791. X      }
  792. X      else if( !(cp->ce_flag & F_RULES) && !(cp->ce_flag & F_STAT) &&
  793. X           (!(cp->ce_attr & A_ROOT) || !(cp->ce_flag & F_EXPLICIT)) )
  794. X     Fatal( "Don't know how to make `%s'",cp->CE_NAME );
  795. X      else {
  796. X         /* Empty recipe, set the flag as MADE and update the time stamp */
  797. X     Update_time_stamp( cp );
  798. X      }
  799. X   }
  800. X   else
  801. X      mark_made = TRUE;
  802. X
  803. X   /* Make sure everyone gets remade if Force is set */
  804. X   tcp = cp;
  805. X   do {
  806. X      if( !(tcp->ce_flag & F_TARGET) && Force ) tcp->ce_time = Do_time();
  807. X      if( mark_made ) tcp->ce_flag |= F_MADE;
  808. X
  809. X      tcp->ce_flag |= F_VISITED;
  810. X
  811. X      /* Note:  If the prerequisite was made using a .SETDIR= attribute
  812. X       *     directory then we will include the directory in the fname
  813. X       *        of the target.  */
  814. X      if( push ) {
  815. X     char *nname = Build_path(_prefix(Makedir,tcp->ce_dir), tcp->ce_fname);
  816. X
  817. X     if( (tcp->ce_attr & A_FFNAME) && (tcp->ce_fname != NIL(char)) )
  818. X        FREE( tcp->ce_fname );
  819. X
  820. X     tcp->ce_fname = _strdup(nname);
  821. X     tcp->ce_attr |= A_FFNAME;
  822. X      }
  823. X
  824. X      tcp = tcp->ce_all;
  825. X   }
  826. X   while( tcp != NIL(CELL) && tcp != cp );
  827. X
  828. stop_making_it:
  829. X   _drop_mac( m_g  );
  830. X   _drop_mac( m_q  );
  831. X   _drop_mac( m_b  );
  832. X   _drop_mac( m_l  );
  833. X   _drop_mac( m_bb );
  834. X   _drop_mac( m_up );
  835. X   _drop_mac( m_at );
  836. X
  837. X   while( push-- )  Pop_dir(FALSE);
  838. X
  839. X   if( inf    != NIL(char) ) FREE( inf    );
  840. X   if( all    != NIL(char) ) FREE( all    );
  841. X   if( imm    != NIL(char) ) FREE( imm    );
  842. X   if( outall != NIL(char) ) FREE( outall );
  843. X
  844. X   DB_PRINT( "mem", ("%s:-< mem %ld", cp->CE_NAME, (long) coreleft()) );
  845. X   DB_RETURN( rval );
  846. }
  847. X
  848. X
  849. static char *
  850. _prefix( pfx, pat )
  851. char *pfx;
  852. char *pat;
  853. {
  854. X   char *opat = pat;
  855. X   while( *pfx && *pat && *pfx++ == *pat++ );
  856. X
  857. X   return( !*pfx ? _strspn(pat,DirBrkStr) : opat );
  858. }
  859. X
  860. X
  861. static LINKPTR
  862. _dup_prq( lp )
  863. LINKPTR lp;
  864. {
  865. X   LINKPTR tlp;
  866. X
  867. X   if( lp == NIL(LINK) ) return(lp);
  868. X
  869. X   TALLOC(tlp, 1, LINK);
  870. X   *tlp = *lp;
  871. X   tlp->cl_next = _dup_prq( lp->cl_next );
  872. X
  873. X   return(tlp);
  874. }
  875. X
  876. X
  877. static void
  878. _drop_mac( hp )/*
  879. ================ set a macro value to zero. */
  880. HASHPTR hp;
  881. {
  882. X   if( hp && hp->ht_value != NIL(char) ) {
  883. X      FREE( hp->ht_value );
  884. X      hp->ht_value = NIL(char);
  885. X   }
  886. }
  887. X
  888. X
  889. X
  890. PUBLIC int
  891. Exec_commands( cp )/*
  892. =====================
  893. X  Execute the commands one at a time that are pointed to by the rules pointer
  894. X  of the target cp. If a group is indicated, then the ce_attr determines
  895. X  .IGNORE and .SILENT treatment for the group.
  896. X  
  897. X  The function returns 0, if the command is executed and has successfully
  898. X  returned, and returns 1 if the command is executing but has not yet
  899. X  returned (for parallel makes).
  900. X  
  901. X  The F_MADE bit in the cell is guaranteed set when the command has
  902. X  successfully completed.  */
  903. CELLPTR cp;
  904. {
  905. X   static HASHPTR useshell = NIL(HASH);
  906. X   static HASHPTR command  = NIL(HASH);
  907. X   static         int   read_cmnd = 0;
  908. X   register STRINGPTR    rp;
  909. X   STRINGPTR            orp;
  910. X   char            *cmnd;
  911. X   char            *groupfile;
  912. X   FILE            *tmpfile;
  913. X   int            do_it;
  914. X   t_attr        attr;
  915. X   int            group;
  916. X   int            trace;
  917. X   int            rval  = 0;
  918. X
  919. X   DB_ENTER( "Exec_commands" );
  920. X
  921. X   Current_target = cp;
  922. X   attr  = Glob_attr | cp->ce_attr;
  923. X   trace = Trace || !(attr & A_SILENT);
  924. X   group = cp->ce_flag & F_GROUP;
  925. X
  926. X   /* Do it again here for those that call us from places other than Make()
  927. X    * above. */
  928. X   orp = _recipes[ RP_RECIPE ];
  929. X   _recipes[ RP_RECIPE ] = cp->ce_recipe;
  930. X
  931. X   if( group ) {
  932. X      trace  = Trace || !(attr & A_SILENT);
  933. X
  934. X      if( !Trace ) tmpfile = Start_temp( Grp_suff, cp, &groupfile );
  935. X      if( trace )  fputs( "[\n", stdout );
  936. X
  937. X      /* Emit group prolog */
  938. X      if( attr & A_PROLOG )
  939. X         _append_file( _recipes[RP_GPPROLOG], tmpfile, cp->CE_NAME, trace );
  940. X   }
  941. X
  942. X   if( !useshell  ) useshell=Def_macro("USESHELL",NIL(char),M_MULTI|M_EXPANDED);
  943. X   if( !read_cmnd ) {command = GET_MACRO("COMMAND"); read_cmnd = 1;}
  944. X
  945. X   /* Process commands in recipe. If in group, merely append to file.
  946. X    * Otherwise, run them.  */
  947. X   for( rp = _recipes[RP_RECIPE]; rp != NIL(STRING); rp=rp->st_next,FREE(cmnd)){
  948. X      t_attr a_attr = A_DEFAULT;
  949. X      char   *p;
  950. X      int    new_attr = FALSE;
  951. X      int    shell;
  952. X
  953. X      /* Only check for +,-,%,@ if the recipe line begins with a '$' macro
  954. X       * expansion.  Otherwise there is no way it is going to find these
  955. X       * now. */
  956. X      if( *rp->st_string == '$' && !group ) {
  957. X         t_attr s_attr = Glob_attr;
  958. X     Glob_attr |= A_SILENT;
  959. X     Suppress_temp_file = TRUE;
  960. X     cmnd = Expand(rp->st_string);
  961. X     Suppress_temp_file = FALSE;
  962. X     a_attr |= Rcp_attribute(cmnd);
  963. X     FREE(cmnd);
  964. X     ++new_attr;
  965. X     Glob_attr = s_attr;
  966. X      }
  967. X
  968. X      attr |= a_attr|rp->st_attr;
  969. X      shell = ((attr & A_SHELL) != 0);
  970. X      useshell->ht_value = (group||shell)?"yes":"no";
  971. X
  972. X      cmnd = Expand( rp->st_string );
  973. X
  974. X      if( new_attr ) {
  975. X     char *ecmnd = cmnd;
  976. X     cmnd = _strdup(_strspn(cmnd, " \t\n+-@%"));
  977. X     FREE(ecmnd);
  978. X      }
  979. X
  980. X      /* COMMAND macro is set to "$(CMNDNAME) $(CMNDARGS)" by default, it is
  981. X       * possible for the user to reset it to, for example
  982. X       *    COMMAND = $(CMNDNAME) @$(mktmp $(CMNDARGS))
  983. X       * in order to get a different interface for his command execution. */
  984. X      if( command != NIL(HASH) && !group && *(p = _strpbrk(cmnd, " \t\n")) ) {
  985. X     char *cname = cmnd;
  986. X
  987. X     *p = '\0';
  988. X     (void) Def_macro("CMNDNAME",cname,M_MULTI|M_EXPANDED);
  989. X     (void) Def_macro("CMNDARGS",p+1,M_MULTI|M_EXPANDED);
  990. X
  991. X     cmnd = Expand("$(COMMAND)");
  992. X     FREE(cname);             /* cname == cmnd at this point. */
  993. X      }
  994. X
  995. X      Swap_on_exec = ((attr & A_SWAP) != 0);      /* Swapping for DOS only */
  996. X      do_it = !Trace;
  997. X
  998. X      if( !group && Trace && _strstr(rp->st_string,"$(MAKE)") ) {
  999. X     Wait_for_completion |= Trace;
  1000. X     do_it = TRUE;
  1001. X      }
  1002. X
  1003. X      if( group )
  1004. X         Append_line( cmnd, TRUE, tmpfile, cp->CE_NAME, trace, 0 );
  1005. X      else {
  1006. X     if( *_strspn(cmnd, " \t") != '\0' )
  1007. X        _print_cmnd(cmnd, !(do_it && (attr & A_SILENT)), 0);
  1008. X     else
  1009. X        do_it = FALSE;
  1010. X
  1011. X     rval=Do_cmnd(cmnd,FALSE,do_it,cp,(attr&A_IGNORE)!=0, shell,
  1012. X              rp->st_next == NIL(STRING) );
  1013. X      }
  1014. X   }
  1015. X
  1016. X   /* If it is a group then output the EPILOG if required and possibly
  1017. X    * execute the command */
  1018. X   if( group ) {
  1019. X      if( attr & A_EPILOG )    /* emit epilog */
  1020. X     _append_file( _recipes[RP_GPEPILOG], tmpfile, cp->CE_NAME, trace );
  1021. X
  1022. X      if( trace ) fputs("]\n", stdout);
  1023. X
  1024. X      if( do_it = !Trace ) Close_temp( cp, tmpfile );
  1025. X      rval = Do_cmnd(groupfile, TRUE, do_it, cp, (attr & A_IGNORE)!=0,
  1026. X             TRUE, TRUE);
  1027. X   }
  1028. X
  1029. X   Wait_for_completion = FALSE;
  1030. X   _recipes[ RP_RECIPE ] = orp;
  1031. X   DB_RETURN( rval );
  1032. }
  1033. X
  1034. X
  1035. static void
  1036. _print_cmnd( cmnd, echo, map )/*
  1037. ================================
  1038. X   This routine is called to print out the command to stdout.  If echo is
  1039. X   false the printing to stdout is supressed, but the new lines in the command
  1040. X   are still deleted. */
  1041. char *cmnd;
  1042. int  echo;
  1043. int  map;
  1044. {
  1045. X   register char *p;
  1046. X   register char *n;
  1047. X
  1048. X   DB_ENTER( "_print_cmnd" );
  1049. X
  1050. X   if( echo ) {
  1051. X      printf( "%s\n", cmnd  );
  1052. X      fflush(stdout);
  1053. X   }
  1054. X
  1055. X   for( p=cmnd; (n = strchr(p, CONTINUATION_CHAR)) != NIL(char); )
  1056. X      if(n[1] == '\n') {
  1057. X     DB_PRINT( "make", ("fixing [%s]", p) );
  1058. X     strcpy( n, n+2 );
  1059. X     p = n;
  1060. X      }
  1061. X      else {
  1062. X     if( map ) Map_esc( n );
  1063. X     p = n+1;
  1064. X      }
  1065. X
  1066. X   DB_VOID_RETURN;
  1067. }
  1068. X
  1069. X
  1070. X
  1071. /* These routines are used to maintain a stack of directories when making
  1072. X * the targets.  If a target cd's to the directory then it is assumed that
  1073. X * it will undo it when it is finished making itself. */
  1074. X
  1075. static STRINGPTR dir_stack = NIL(STRING);
  1076. X
  1077. int
  1078. Push_dir( dir, name, ignore )/*
  1079. ===============================
  1080. X   Change the current working directory to dir and save the current
  1081. X   working directory on the stack so that we can come back.
  1082. X   
  1083. X   If ignore is TRUE then do not complain about _ch_dir if not possible.*/
  1084. char *dir;
  1085. char *name;
  1086. int  ignore;
  1087. {
  1088. X   STRINGPTR   new_dir;
  1089. X
  1090. X   DB_ENTER( "Push_dir" );
  1091. X
  1092. X   if( dir == NIL(char) ) dir = Pwd;
  1093. X   if( *dir == '\'' && dir[strlen(dir)-1] == '\'' ) {
  1094. X      dir = _strdup(dir+1);
  1095. X      dir[strlen(dir)-1]='\0';
  1096. X   }
  1097. X   else
  1098. X      dir = Expand(dir);
  1099. X
  1100. X   if( Set_dir(dir) ) {
  1101. X      if( !ignore )
  1102. X         Fatal( "Unable to change to directory `%s', target is [%s]",
  1103. X            dir, name );
  1104. X      FREE(dir);
  1105. X      DB_RETURN( 0 );
  1106. X   }
  1107. X
  1108. X   DB_PRINT( "dir", ("Push: [%s]", dir) );
  1109. X   if( Verbose & V_PRINT_DIR )
  1110. X      printf( "%s:  Changed to directory [%s]\n", Pname, dir  );
  1111. X
  1112. X   FREE( dir );
  1113. X   TALLOC( new_dir, 1, STRING );
  1114. X   new_dir->st_next   = dir_stack;
  1115. X   dir_stack          = new_dir;
  1116. X   new_dir->st_string = _strdup( Pwd );
  1117. X
  1118. X   Def_macro( "PWD", Get_current_dir(), M_MULTI | M_EXPANDED );
  1119. X   _set_tmd();
  1120. X
  1121. X   DB_RETURN( 1 );
  1122. }
  1123. X
  1124. X
  1125. X
  1126. PUBLIC void
  1127. Pop_dir(ignore)/*
  1128. =================
  1129. X   Change the current working directory to the previous saved dir. */
  1130. int ignore;
  1131. {
  1132. X   STRINGPTR old_dir;
  1133. X   char      *dir;
  1134. X
  1135. X   DB_ENTER( "Pop_dir" );
  1136. X
  1137. X   if( dir_stack == NIL(STRING) )
  1138. X      if( ignore ) {
  1139. X         DB_VOID_RETURN;
  1140. X      }
  1141. X      else
  1142. X     Error( "Directory stack empty for return from .SETDIR" );
  1143. X
  1144. X   if( Set_dir(dir = dir_stack->st_string) )
  1145. X      Fatal( "Could not change to directory `%s'", dir );
  1146. X
  1147. X   Def_macro( "PWD", dir, M_MULTI | M_EXPANDED );
  1148. X   DB_PRINT( "dir", ("Pop: [%s]", dir) );
  1149. X   if( Verbose & V_PRINT_DIR )
  1150. X      printf( "%s:  Changed back to directory [%s]\n", Pname, dir);
  1151. X
  1152. X   old_dir   = dir_stack;
  1153. X   dir_stack = dir_stack->st_next;
  1154. X
  1155. X   FREE( old_dir->st_string );
  1156. X   FREE( old_dir );
  1157. X   _set_tmd();
  1158. X
  1159. X   DB_VOID_RETURN;
  1160. }
  1161. X
  1162. X
  1163. X
  1164. static void
  1165. _set_tmd()/*
  1166. ============
  1167. X   Set the TWD Macro */
  1168. {
  1169. X   TKSTR md, pd;
  1170. X   char  *m, *p;
  1171. X   char  *tmd;
  1172. X   int   is_sep;
  1173. X   int   first = 1;
  1174. X
  1175. X   SET_TOKEN( &md, Makedir );
  1176. X   SET_TOKEN( &pd, Pwd );
  1177. X
  1178. X   m = Get_token( &md, DirBrkStr, FALSE );
  1179. X   (void) Get_token( &pd, DirBrkStr, FALSE );
  1180. X   is_sep = (strchr(DirBrkStr, *m) != NIL(char));
  1181. X   tmd = _strdup( "" );
  1182. X
  1183. X   do {
  1184. X      m = Get_token( &md, DirBrkStr, FALSE );
  1185. X      p = Get_token( &pd, DirBrkStr, FALSE );
  1186. X
  1187. X      if( !is_sep && strcmp(m, p) ) {    /* they differ */
  1188. X     char *tmp;
  1189. X     if( first ) {        /* They differ in the first component    */
  1190. X        tmd = Makedir;    /* In this case use the full path    */
  1191. X        break;
  1192. X     }
  1193. X
  1194. X     if( *p ) tmp = Build_path( "..", tmd );
  1195. X     if( *m ) tmp = Build_path( tmd, m );
  1196. X     FREE( tmd );
  1197. X     tmd = _strdup( tmp );
  1198. X      }
  1199. X
  1200. X      is_sep = 1-is_sep;
  1201. X      first  = 0;
  1202. X   } while (*m || *p);
  1203. X
  1204. X   CLEAR_TOKEN( &md );
  1205. X   CLEAR_TOKEN( &pd );
  1206. X
  1207. X   Def_macro( "TMD", tmd, M_MULTI | M_EXPANDED );
  1208. X   if( tmd != Makedir ) FREE( tmd );
  1209. }
  1210. X
  1211. X
  1212. static void
  1213. _set_recipe( target, ind )/*
  1214. ============================
  1215. X   Set up the _recipes static variable so that the slot passed in points
  1216. X   at the rules corresponding to the target supplied. */
  1217. char *target;
  1218. int  ind;
  1219. {
  1220. X   CELLPTR cp;
  1221. X   HASHPTR hp;
  1222. X
  1223. X   if( (hp = Get_name(target, Defs, FALSE)) != NIL(HASH) ) {
  1224. X      cp = hp->CP_OWNR;
  1225. X      _recipes[ ind ] = cp->ce_recipe;
  1226. X   }
  1227. X   else
  1228. X      _recipes[ ind ] = NIL(STRING);
  1229. }
  1230. X
  1231. X
  1232. X
  1233. PUBLIC void
  1234. Append_line( cmnd, newline, tmpfile, name, printit, map )
  1235. char *cmnd;
  1236. int  newline;
  1237. FILE *tmpfile;
  1238. char *name;
  1239. int  printit;
  1240. int  map;
  1241. {
  1242. X   _print_cmnd( cmnd, printit, map );
  1243. X
  1244. X   if( Trace ) return;
  1245. X
  1246. X   fputs(cmnd, tmpfile);
  1247. X   if( newline ) fputc('\n', tmpfile);
  1248. X   fflush(tmpfile);
  1249. X
  1250. X   if( ferror(tmpfile) )
  1251. X      Fatal("Write error on temporary file, while processing `%s'", name);
  1252. }
  1253. X
  1254. X
  1255. X
  1256. static void
  1257. _append_file( rp, tmpfile, name, printit )
  1258. register STRINGPTR rp;
  1259. FILE            *tmpfile;
  1260. char            *name;
  1261. int            printit;
  1262. {
  1263. X   char *cmnd;
  1264. X
  1265. X   while( rp != NIL(STRING) ) {
  1266. X      Append_line(cmnd = Expand(rp->st_string), TRUE, tmpfile, name, printit,0);
  1267. X      FREE(cmnd);
  1268. X      rp = rp->st_next;
  1269. X   }
  1270. }
  1271. X
  1272. X
  1273. #define NUM_BUCKETS    20
  1274. X
  1275. typedef struct strpool {
  1276. X   char       *string;    /* a pointer to the string value */
  1277. X   uint32      keyval;    /* the strings hash value     */
  1278. X   struct strpool *next;    /* hash table link pointer     */
  1279. } POOL, *POOLPTR;
  1280. X
  1281. static POOLPTR strings[ NUM_BUCKETS ];
  1282. X
  1283. static char *
  1284. _pool_lookup( str )/*
  1285. =====================
  1286. X   Scan down the list of chained strings and see if one of them matches
  1287. X   the string we are looking for. */
  1288. char    *str;
  1289. {
  1290. X   register POOLPTR key;
  1291. X   uint32   keyval;
  1292. X   uint16   hv;
  1293. X   uint16   keyindex;
  1294. X   char     *string;
  1295. X
  1296. X   DB_ENTER( "_pool_lookup" );
  1297. X
  1298. X   if( str == NIL(char) ) DB_RETURN("");
  1299. X
  1300. X   hv  = Hash(str, &keyval);
  1301. X   key = strings[ keyindex = (hv % NUM_BUCKETS) ];
  1302. X
  1303. X   while( key != NIL(POOL) )
  1304. X      if( (key->keyval != keyval) || strcmp(str, key->string) )
  1305. X     key = key->next;
  1306. X      else
  1307. X     break;
  1308. X
  1309. X   if( key == NIL(POOL) ) {
  1310. X      DB_PRINT( "pool", ("Adding string [%s]", str) );
  1311. X      TALLOC( key, 1, POOL );            /* not found so add string */
  1312. X      
  1313. X      key->string = string = _strdup(str);
  1314. X      key->keyval = keyval;
  1315. X
  1316. X      key->next           = strings[ keyindex ];
  1317. X      strings[ keyindex ] = key;
  1318. X   }
  1319. X   else {
  1320. X      DB_PRINT( "pool", ("Found string [%s], key->string") );
  1321. X      string = key->string;
  1322. X   }
  1323. X
  1324. X   DB_RETURN( string );
  1325. }
  1326. SHAR_EOF
  1327. chmod 0640 dmake/make.c ||
  1328. echo 'restore of dmake/make.c failed'
  1329. Wc_c="`wc -c < 'dmake/make.c'`"
  1330. test 27141 -eq "$Wc_c" ||
  1331.     echo 'dmake/make.c: original size 27141, current size' "$Wc_c"
  1332. rm -f _shar_wnt_.tmp
  1333. fi
  1334. # ============= dmake/make.cmd ==============
  1335. if test -f 'dmake/make.cmd' -a X"$1" != X"-c"; then
  1336.     echo 'x - skipping dmake/make.cmd (File already exists)'
  1337.     rm -f _shar_wnt_.tmp
  1338. else
  1339. > _shar_wnt_.tmp
  1340. sed 's/^X//' << 'SHAR_EOF' > 'dmake/make.cmd' &&
  1341. echo off
  1342. rem  *** This is the make command file that is used under OS/2 to make the
  1343. rem  *** first version of dmake.  It isn't pretty but it does work, assuming
  1344. rem  *** the compilers have been correctly setup.
  1345. rem
  1346. echo Running make.cmd script to make a %1 copy of dmake.
  1347. X
  1348. if %0%1 == %0 goto error
  1349. if %1 == msc40 goto mkmsc40
  1350. if %1 == msc50 goto mkmsc50
  1351. if %1 == msc51 goto mkmsc51
  1352. if %1 == msc60 goto mkmsc60
  1353. X
  1354. rem label the possible DOS variations for dmake here.
  1355. :error
  1356. echo OS/2 INDEX:  You must specify one of:
  1357. echo    msc40    - Microsoft C 4.0 compile.
  1358. echo    msc50    - Microsoft C 5.0 compile.
  1359. echo    msc51    - Microsoft C 5.1 compile.
  1360. echo    msc60    - Microsoft C 6.0 compile.
  1361. goto end
  1362. X
  1363. rem This is the script that makes dmake using Microsoft C 4.0
  1364. :mkmsc40
  1365. os2\mscdos\mk40.cmd
  1366. goto end
  1367. X
  1368. rem This is the script that makes dmake using Microsoft C 5.0
  1369. :mkmsc50
  1370. os2\mscdos\mk50.cmd
  1371. goto end
  1372. X
  1373. rem This is the script that makes dmake using Microsoft C 5.1
  1374. :mkmsc51
  1375. os2\mscdos\mk51.cmd
  1376. goto end
  1377. X
  1378. rem This is the script that makes dmake using Microsoft C 6.0
  1379. :mkmsc60
  1380. os2\mscdos\mk60.cmd
  1381. goto end
  1382. X
  1383. rem All done!
  1384. :end
  1385. SHAR_EOF
  1386. chmod 0640 dmake/make.cmd ||
  1387. echo 'restore of dmake/make.cmd failed'
  1388. Wc_c="`wc -c < 'dmake/make.cmd'`"
  1389. test 1124 -eq "$Wc_c" ||
  1390.     echo 'dmake/make.cmd: original size 1124, current size' "$Wc_c"
  1391. rm -f _shar_wnt_.tmp
  1392. fi
  1393. # ============= dmake/makefile.mk ==============
  1394. if test -f 'dmake/makefile.mk' -a X"$1" != X"-c"; then
  1395.     echo 'x - skipping dmake/makefile.mk (File already exists)'
  1396.     rm -f _shar_wnt_.tmp
  1397. else
  1398. > _shar_wnt_.tmp
  1399. sed 's/^X//' << 'SHAR_EOF' > 'dmake/makefile.mk' &&
  1400. #             //// Makefile for DMAKE. \\\\
  1401. # The target system is characterized by the following macros imported from
  1402. # the environment.
  1403. #
  1404. #    OS          - gives the class of operating system
  1405. SHAR_EOF
  1406. true || echo 'restore of dmake/makefile.mk failed'
  1407. fi
  1408. echo 'End of part 11, continue with part 12'
  1409. echo 12 > _shar_seq_.tmp
  1410. exit 0
  1411.  
  1412. exit 0 # Just in case...
  1413. -- 
  1414. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  1415. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  1416. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  1417. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  1418.