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

  1. Newsgroups: comp.sources.misc
  2. subject: v14i027: dmake version 3.5 part 17/21
  3. From: dvadura@watdragon.waterloo.edu (Dennis Vadura)
  4. Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  5.  
  6. Posting-number: Volume 14, Issue 27
  7. Submitted-by: dvadura@watdragon.waterloo.edu (Dennis Vadura)
  8. Archive-name: dmake/part17
  9.  
  10. #!/bin/sh
  11. # this is part 17 of a multipart archive
  12. # do not concatenate these parts, unpack them in order with /bin/sh
  13. # file expand.c continued
  14. #
  15. CurArch=17
  16. if test ! -r s2_seq_.tmp
  17. then echo "Please unpack part 1 first!"
  18.      exit 1; fi
  19. ( read Scheck
  20.   if test "$Scheck" != $CurArch
  21.   then echo "Please unpack part $Scheck next!"
  22.        exit 1;
  23.   else exit 0; fi
  24. ) < s2_seq_.tmp || exit 1
  25. echo "x - Continuing file expand.c"
  26. sed 's/^X//' << 'SHAR_EOF' >> expand.c
  27. X   }
  28. X}
  29. X
  30. X
  31. X
  32. Xstatic char*
  33. X_scan_token( s, ps )/*
  34. X======================
  35. X      This routine scans the token characters one at a time and identifies
  36. X      macros starting with $( and ${ and calls _scan_macro to expand their
  37. X      value.   the string1{ token_list }string2 expansion is also handled.
  38. X      In this case a temporary result is maintained so that we can take it's
  39. X      cross product with any other token_lists that may possibly appear. */
  40. X      
  41. Xchar *s;        /* pointer to start of src string */
  42. Xchar **ps;        /* pointer to start pointer      */
  43. X{
  44. X   char *res;                 /* pointer to result          */
  45. X   char *start;               /* pointer to start of prefix */
  46. X   int  crossproduct = 0;     /* if 1 then computing X-prod */
  47. X
  48. X   start = s;
  49. X   res   = _strdup( "" );
  50. X   while( 1 )
  51. X      switch( *s ) {
  52. X         /* Termination, We halt at seeing a space or a tab or end of string.
  53. X          * We return the value of the result with any new macro's we scanned
  54. X          * or if we were computing cross_products then we return the new
  55. X          * cross_product.
  56. X          * NOTE:  Once we start computing cross products it is impossible to
  57. X          *        stop.  ie. the semantics are such that once a {} pair is
  58. X          *        seen we compute cross products until termination. */
  59. X
  60. X         case ' ':
  61. X         case '\t':
  62. X     case '\n':
  63. X         case '\0': 
  64. X     {
  65. X        char *tmp;
  66. X
  67. X        *ps = s;
  68. X        if( !crossproduct )
  69. X           tmp = _strjoin( res, start, (s-start), TRUE );
  70. X        else
  71. X        {
  72. X           tmp = _substr( start, s );
  73. X           tmp = _cross_prod( res, tmp );
  74. X        }
  75. X        return( tmp );
  76. X     }
  77. X         
  78. X         case '$':
  79. X         case '{':
  80. X     {
  81. X        /* Handle if it's a macro or if it's a {} construct.
  82. X         * The results of a macro expansion are handled differently based
  83. X         * on whether we have seen a {} beforehand. */
  84. X        
  85. X        char *tmp;
  86. X        tmp = _substr( start, s );          /* save the prefix */
  87. X
  88. X        if( *s == '$' ) {
  89. X           start = _scan_macro( s+1, &s );
  90. X
  91. X           if( crossproduct )
  92. X          res = _cross_prod( res, _strjoin( tmp, start, -1, TRUE ) );
  93. X           else {
  94. X          res = _strjoin(res,tmp = _strjoin(tmp,start,-1,TRUE),-1,TRUE);
  95. X          FREE( tmp );
  96. X           }
  97. X           FREE( start );
  98. X        }
  99. X        else if( s[1] != '{' ) {
  100. X           int ok;
  101. X           start = _scan_brace( s+1, &s, &ok );
  102. X          
  103. X           if( ok ) {
  104. X          res = _cross_prod( res, _cross_prod(tmp, start) );
  105. X          crossproduct = TRUE;
  106. X           }
  107. X           else {
  108. X          res =_strjoin(res,tmp=_strjoin(tmp,start,-1,TRUE),-1,TRUE);
  109. X          FREE( start );
  110. X          FREE( tmp   );
  111. X           }
  112. X        }
  113. X        else {    /* handle the {{ case */
  114. X           res = _strjoin( res, start, (s-start+1), TRUE );
  115. X           s  += 2;
  116. X           FREE( tmp );
  117. X        }
  118. X
  119. X        start = s;
  120. X     }
  121. X     break;
  122. X
  123. X     case '}':
  124. X        if( s[1] != '}' ) {
  125. X           /* error malformed macro expansion */
  126. X           s++;
  127. X        }
  128. X        else {    /* handle the }} case */
  129. X           res = _strjoin( res, start, (s-start+1), TRUE );
  130. X           s += 2;
  131. X           start = s;
  132. X        }
  133. X        break;
  134. X         
  135. X         default: s++;
  136. X      }
  137. X}
  138. X
  139. X
  140. X
  141. Xstatic char*
  142. X_scan_macro( s, ps )/*
  143. X======================
  144. X    This routine scans a macro use and expands it to the value.  It
  145. X    returns the macro's expanded value and modifies the pointer into the
  146. X    src string to point at the first character after the macro use.
  147. X    The types of uses recognized are:
  148. X
  149. X        $$        - expands to $
  150. X        $(name)        - expands to value of name
  151. X        ${name}        - same as above
  152. X        $($(name))    - recurses on macro names (any level)
  153. X    and 
  154. X            $(name:modifier_list:modifier_list:...)
  155. X        
  156. X    see comment for Expand for description of valid modifiers.
  157. X
  158. X    NOTE that once a macro name bounded by ( or { is found only
  159. X    the appropriate terminator (ie. ( or } is searched for. */
  160. X
  161. Xchar *s;        /* pointer to start of src string   */
  162. Xchar **ps;        /* pointer to start pointer        */
  163. X{
  164. X   char sdelim;         /* start of macro delimiter         */
  165. X   char edelim;         /* corresponding end macro delim    */
  166. X   char *start;         /* start of prefix                  */
  167. X   char *macro_name;    /* temporary macro name             */
  168. X   char *recurse_name;  /* recursive macro name             */
  169. X   char *result;    /* result for macro expansion        */
  170. X   int  bflag = 0;      /* brace flag, ==0 => $A type macro */
  171. X   int  done  = 0;      /* != 0 => done macro search        */
  172. X   int  lev   = 0;      /* brace level                      */
  173. X   int  mflag = 0;      /* != 0 => modifiers present in mac */
  174. X   HASHPTR hp;        /* hash table pointer for macros    */
  175. X   
  176. X   DB_ENTER( "_scan_macro" );
  177. X
  178. X   /* Check for the simple $ at end of line case */
  179. X   if( !*s ) {
  180. X      *ps = s;
  181. X      DB_RETURN( _strdup("") );
  182. X   }
  183. X
  184. X   if( *s == '$' ) {    /* Take care of the simple $$ case. */
  185. X      *ps = s+1;
  186. X      DB_RETURN( _strdup("$") );
  187. X   }
  188. X
  189. X   sdelim = *s;         /* set and remember start/end delim */
  190. X   if( sdelim == '(' )
  191. X      edelim = ')';
  192. X   else
  193. X      edelim = '}';
  194. X
  195. X   start = s;           /* build up macro name, find its end*/
  196. X   while( !done ) {
  197. X      switch( *s ) {
  198. X         case '(':                /* open macro brace  */
  199. X         case '{':
  200. X        if( *s == sdelim ) {
  201. X           lev++;
  202. X           bflag++;
  203. X        }
  204. X        break;
  205. X         
  206. X         case ':':                              /* halt at modifier          */
  207. X            if( lev == 1 ) {
  208. X               done = TRUE;
  209. X               mflag = 1;
  210. X            }
  211. X            break;
  212. X            
  213. X     case '\0':                /* check for EOLN and spaces */
  214. X     case ' ':                /* inside a macro name          */
  215. X     case '\t':
  216. X     case '\n':
  217. X        *ps = s;
  218. X        if( lev ) {
  219. X           done  = TRUE;
  220. X           bflag = 0;
  221. X           s     = start;
  222. X        }
  223. X        break;
  224. X         
  225. X         case ')':                /* close macro brace */
  226. X         case '}':
  227. X        if( *s == edelim && lev ) --lev;
  228. X     /*FALLTHROUGH*/
  229. X
  230. X         default:
  231. X        done = !lev;
  232. X      }
  233. X      s++;
  234. X   }
  235. X
  236. X   /* Check if this is a $A type macro.  If so then we have to
  237. X    * handle it a little differently. */
  238. X
  239. X   if( bflag )
  240. X      macro_name = _substr( start+1, s-1 );
  241. X   else
  242. X      macro_name = _substr( start, s );
  243. X
  244. X
  245. X   /* Check if the macro is a recursive macro name, if so then
  246. X    * EXPAND the name before expanding the value */
  247. X
  248. X   if( strchr( macro_name, '$' ) != NIL(char) ) {
  249. X      recurse_name = Expand( macro_name );
  250. X      FREE( macro_name );
  251. X      macro_name = recurse_name;
  252. X   }
  253. X
  254. X   /* Code to do value expansion goes here, NOTE:  macros whose assign bit
  255. X      is one have been evaluated and assigned, they contain no further
  256. X      expansions and thus do not need their values expanded again. */
  257. X
  258. X   if( (hp = GET_MACRO( macro_name )) != NIL(HASH) ) {
  259. X      if( hp->ht_flag & M_MARK )
  260. X     Fatal( "Detected circular macro [%s]", hp->ht_name );
  261. X
  262. X      /* for M_MULTI macro variable assignments */
  263. X      If_multi = hp->ht_flag & M_MULTI;
  264. X
  265. X      if( !(hp->ht_flag & M_EXPANDED) ) {
  266. X     hp->ht_flag |= M_MARK;
  267. X     result = Expand( hp->ht_value );
  268. X     hp->ht_flag ^= M_MARK;
  269. X      }
  270. X      else if( hp->ht_value != NIL(char) )
  271. X     result = _strdup( hp->ht_value );
  272. X      else
  273. X     result = _strdup( "" );
  274. X
  275. X      /*
  276. X       * Mark macros as used only if we are not expanding them for
  277. X       * the purpose of a .IF test, so we can warn about redef after use*/
  278. X
  279. X      if( !If_expand ) hp->ht_flag |= M_USED;
  280. X   }
  281. X   else
  282. X      result = _strdup( "" );
  283. X
  284. X   if( mflag ) {
  285. X      char separator;
  286. X      int  modifier_list = 0;
  287. X      int  aug_mod       = FALSE;
  288. X      char *pat1;
  289. X      char *pat2;
  290. X      char *p;
  291. X
  292. X      /* Yet another brain damaged AUGMAKE kludge.  We should accept the 
  293. X       * AUGMAKE bullshit of $(f:pat=sub) form of macro expansion.  In
  294. X       * order to do this we will forgo the normal processing if the
  295. X       * AUGMAKE solution pans out, otherwise we will try to process the
  296. X       * modifiers ala dmake.
  297. X       *
  298. X       * So we look for = in modifier string.
  299. X       * If found we process it and not do the normal stuff */
  300. X
  301. X      for( p=s; *p && *p != '=' && *p != edelim; p++ );
  302. X
  303. X      if( *p == '=' ) {
  304. X     pat1 = _substr( s, p );
  305. X     for( s=p=p+1; (*p != edelim); p++ );
  306. X
  307. X     pat2   = _substr( s, p );
  308. X     result = Apply_edit( result, pat1, pat2, TRUE, TRUE );
  309. X     FREE( pat1 );
  310. X     FREE( pat2 );
  311. X     s = p;
  312. X     aug_mod = TRUE;
  313. X      }
  314. X
  315. X      if( !aug_mod )
  316. X     while( *s && *s != edelim ) {        /* while not at end of macro */
  317. X        switch( *s++ ) {
  318. X           case 'b':
  319. X           case 'B': modifier_list |= FILE_FLAG;            break;
  320. X
  321. X           case 'd':
  322. X           case 'D': modifier_list |= DIRECTORY_FLAG;         break;
  323. X
  324. X           case 'f':
  325. X           case 'F': modifier_list |= FILE_FLAG | SUFFIX_FLAG; break;
  326. X
  327. X           case 'S':
  328. X           case 's':
  329. X          if( modifier_list ) {
  330. X             Warning( "Edit modifier must appear alone, ignored");
  331. X             modifier_list = 0;
  332. X          }
  333. X          else {
  334. X             separator = *s++;
  335. X             for( p=s; *p != separator && *p != edelim; p++ );
  336. X
  337. X             if( *p == edelim )
  338. X                Warning("Syntax error in edit pattern, ignored");
  339. X             else {
  340. X            char *t1, *t2;
  341. X            pat1 = _substr( s, p );
  342. X            for(s=p=p+1; (*p != separator) && (*p != edelim); p++ );
  343. X            pat2 = _substr( s, p );
  344. X            t1 = Expand(pat1); FREE(pat1);
  345. X            t2 = Expand(pat2); FREE(pat2);
  346. X            result = Apply_edit( result, t1, t2, TRUE, FALSE );
  347. X            FREE( t1 );
  348. X            FREE( t2 );
  349. X             }
  350. X             s = p;
  351. X          }
  352. X          /* find the end of the macro spec, or the start of a new
  353. X           * modifier list for further processing of the result */
  354. X
  355. X          for( ; (*s != edelim) && (*s != ':'); s++ );
  356. X          if( *s == ':' ) s++;
  357. X          break;
  358. X
  359. X           case 'T':
  360. X           case 't':
  361. X          if( modifier_list ) {
  362. X             Warning( "Tokenize modifier must appear alone, ignored");
  363. X             modifier_list = 0;
  364. X          }
  365. X          else {
  366. X             char *msg = "Separator string must be quoted";
  367. X
  368. X             separator = *s++;
  369. X
  370. X             if( separator != '\"' )
  371. X            Warning( msg );
  372. X             else {
  373. X            /* we change the semantics to allow $(v:t")") */
  374. X            for (p = s; *p && *p != separator; p++)
  375. X               if (*p == '\\')
  376. X                  if (p[1] == '\\' || p[1] == '"')
  377. X                 p++;
  378. X            if( *p == 0 )
  379. X               Fatal( "Unterminated separator string" );
  380. X            else {
  381. X               pat1 = _substr( s, p );
  382. X               result = _tokenize( result, pat1 );
  383. X               FREE( pat1 );
  384. X            }
  385. X            s = p;
  386. X             }
  387. X
  388. X             /* find the end of the macro spec, or the start of a new
  389. X              * modifier list for further processing of the result */
  390. X
  391. X             for( ; (*s != edelim) && (*s != ':'); s++ );
  392. X             if( *s == ':' ) s++;
  393. X          }
  394. X          break;
  395. X
  396. X           case ':':
  397. X          if( modifier_list ) {
  398. X             result = _apply_modifiers( modifier_list, result );
  399. X             modifier_list = 0;
  400. X          }
  401. X          break;
  402. X
  403. X           default:
  404. X          Warning( "Illegal modifier in macro, ignored" );
  405. X          break;
  406. X        }
  407. X     }
  408. X
  409. X      if( modifier_list ) /* apply modifier */
  410. X         result = _apply_modifiers( modifier_list, result );
  411. X      
  412. X      s++;
  413. X   }
  414. X
  415. X   *ps = s;
  416. X   FREE( macro_name );
  417. X   DB_RETURN( result );
  418. X}
  419. X
  420. X
  421. X
  422. Xstatic char*
  423. X_scan_brace( s, ps, flag )/*
  424. X============================
  425. X      This routine scans for { token_list } pairs.  It expands the value of
  426. X      token_list by calling Expand on it.  Token_list may be anything at all.
  427. X      Note that the routine count's ballanced parentheses.  This means you
  428. X      cannot have something like { fred { joe }, if that is what you really
  429. X      need the write it as { fred {{ joe }, flag is set to 1 if all ok
  430. X      and to 0 if the braces were unballanced. */
  431. X      
  432. Xchar *s;
  433. Xchar **ps;
  434. Xint  *flag;
  435. X{
  436. X   char *t;
  437. X   char *start;
  438. X   char *res;
  439. X   int  lev  = 1;
  440. X   int  done = 0;
  441. X   
  442. X   DB_ENTER( "_scan_brace" );
  443. X
  444. X   start = s;
  445. X   while( !done )
  446. X      switch( *s++ ) {
  447. X         case '{': 
  448. X            if( *s == '{' ) break;              /* ignore {{ */
  449. X            lev++;
  450. X            break;
  451. X            
  452. X         case '}': 
  453. X            if( *s == '}' ) break;              /* ignore }} */
  454. X        if( lev )
  455. X           if( --lev == 0 ) done = TRUE;
  456. X        break;
  457. X
  458. X     case '$':
  459. X        if( *s == '{' || *s == '}' ) {
  460. X          if( (t = strchr(s,'}')) != NIL(char) )
  461. X             s = t;
  462. X          s++;
  463. X        }
  464. X        break;
  465. X         
  466. X         case '\0':
  467. X        if( lev ) {
  468. X           done = TRUE;
  469. X           s--;
  470. X           /* error malformed macro expansion */
  471. X        }
  472. X        break;
  473. X      }
  474. X
  475. X   start = _substr( start, (lev) ? s : s-1 );
  476. X
  477. X   if( lev ) {
  478. X      /* Braces were not ballanced so just return the string.
  479. X       * Do not expand it. */
  480. X       
  481. X      res   = _strjoin( "{", start, -1, FALSE );
  482. X      *flag = 0;
  483. X   }
  484. X   else {
  485. X      *flag = 1;
  486. X      res   = Expand( start );
  487. X
  488. X      if( (t = _strspn( res, " \t" )) != res ) strcpy( res, t );
  489. X   }
  490. X
  491. X   FREE( start );       /* this is ok! start is assigned a _substr above */
  492. X   *ps = s;
  493. X
  494. X   DB_RETURN( res );
  495. X}
  496. X
  497. X
  498. X
  499. Xstatic char*
  500. X_cross_prod( x, y )/*
  501. X=====================
  502. X      Given two strings x and y compute the cross-product of the tokens found
  503. X      in each string.  ie. if x = "a b" and y = "c d" return "ac ad bc bd".
  504. X
  505. X         NOTE:  buf will continue to grow until it is big enough to handle
  506. X                all cross product requests.  It is never freed!  (maybe I
  507. X            will fix this someday) */
  508. X      
  509. Xchar *x;
  510. Xchar *y;
  511. X{
  512. X   static char *buf;
  513. X   static int  buf_siz = 0;
  514. X   char *brkx;
  515. X   char *brky;
  516. X   char *cy;
  517. X   char *cx;
  518. X   char *res;
  519. X   int  i;
  520. X
  521. X   if( *x && *y ) {
  522. X      res = _strdup( "" ); cx = x;
  523. X      while( *cx ) {
  524. X     cy = y;
  525. X         brkx = _strpbrk( cx, " \t\n" );
  526. X     if( (brkx-cx == 2) && *cx == '\"' && *(cx+1) == '\"' ) cx = brkx;
  527. X
  528. X     while( *cy ) {
  529. X        brky = _strpbrk( cy, " \t\n" );
  530. X        if( (brky-cy == 2) && *cy == '\"' && *(cy+1) == '\"' ) cy = brky;
  531. X        i    = brkx-cx + brky-cy + 2;
  532. X
  533. X        if( i > buf_siz ) {        /* grow buf to the correct size */
  534. X           if( buf != NIL(char) ) FREE( buf );
  535. X           if( (buf = MALLOC( i, char )) == NIL(char))  No_ram();
  536. X           buf_siz = i;
  537. X        }
  538. X
  539. X        strncpy( buf, cx, (i = brkx-cx) );
  540. X        buf[i] = '\0';
  541. X        if (brky-cy > 0) strncat( buf, cy, brky-cy );
  542. X        strcat( buf, " " );
  543. X        res = _strjoin( res, buf, -1, TRUE );
  544. X        cy = _strspn( brky, " \t\n" );
  545. X     }
  546. X     cx = _strspn( brkx, " \t\n" );
  547. X      }
  548. X
  549. X      FREE( x );
  550. X      res[ strlen(res)-1 ] = '\0';
  551. X   }
  552. X   else
  553. X      res = _strjoin( x, y, -1, TRUE );
  554. X
  555. X   FREE( y );
  556. X   return( res );
  557. X}
  558. X
  559. X
  560. X
  561. Xstatic char*
  562. X_apply_modifiers( mod, src )/*
  563. X==============================
  564. X   This routine applies the appropriate modifiers to the string src
  565. X   and returns the proper result string */
  566. X
  567. Xint  mod;
  568. Xchar *src;
  569. X{
  570. X   char       *s;
  571. X   char    *e;
  572. X   TKSTR   str;
  573. X
  574. X   DB_ENTER( "_apply_modifiers" );
  575. X
  576. X   if( mod == (SUFFIX_FLAG | DIRECTORY_FLAG | FILE_FLAG) )
  577. X      DB_RETURN( src );
  578. X
  579. X   SET_TOKEN( &str, src );
  580. X   DB_PRINT( "mod", ("Source string [%s]", src) );
  581. X
  582. X   while( *(s = Get_token( &str, "", FALSE )) != '\0' ) {
  583. X      /* search for the directory portion of the filename.  If the
  584. X       * DIRECTORY_FLAG is set, then we want to keep the directory portion
  585. X       * othewise throw it away and blank out to the end of the token */
  586. X
  587. X      if( (e = basename(s)) != s)
  588. X     if( !(mod & DIRECTORY_FLAG) ) {
  589. X        strcpy(s, e);
  590. X        e = s+(str.tk_str-e);
  591. X        for(; e != str.tk_str; e++)
  592. X               *e = ' ';
  593. X     }
  594. X     else
  595. X        s = e;
  596. X
  597. X      /* search for the suffix, if there is none, treat it as a NULL suffix.
  598. X       * if no file name treat it as a NULL file name.  same copy op as
  599. X       * for directory case above */
  600. X
  601. X      e = strrchr( s, '.' );            /* NULL suffix if e=0 */
  602. X      if( e == NIL(char) ) e = s+strlen(s);
  603. X
  604. X      if( !(mod & FILE_FLAG) ) {
  605. X     strcpy( s, e );
  606. X     e = s+(str.tk_str-e);
  607. X     for( ; e != str.tk_str; e++ ) *e = ' ';
  608. X      }
  609. X      else
  610. X     s = e;
  611. X
  612. X      /* The last and final part.  This is the suffix case, if we don't want
  613. X       * it then just erase to the end of the token. */
  614. X
  615. X      if( s != NIL(char) )
  616. X     if( !(mod & SUFFIX_FLAG) )
  617. X        for( ; s != str.tk_str; s++ ) *s = ' ';
  618. X   }
  619. X
  620. X   /* delete the extra white space, it looks ugly */
  621. X   for( s = src, e = NIL(char); *s; s++ )
  622. X      if( *s == ' ' || *s == '\t' || *s == '\n' ) {
  623. X     if( e == NIL(char) )
  624. X        e = s;
  625. X      }
  626. X      else {
  627. X     if( e != NIL(char) ) {
  628. X        if( e+1 < s ) {
  629. X           strcpy( e+1, s );
  630. X           s = e+1;
  631. X           *e = ' ';
  632. X        }
  633. X        e = NIL(char);
  634. X     }
  635. X      }
  636. X
  637. X   if( e != NIL(char) )
  638. X      if( e < s )
  639. X     strcpy( e, s );
  640. X
  641. X   DB_PRINT( "mod", ("Result string [%s]", src) );
  642. X   DB_RETURN( src );
  643. X}
  644. X
  645. X
  646. X
  647. Xstatic char*
  648. X_tokenize( src, separator )/*
  649. X=============================
  650. X    Tokenize the input of src and join each token found together with
  651. X    the next token separated by the separator string.
  652. X
  653. X    When doing the tokenization, <sp>, <tab>, <nl>, and \<nl> all
  654. X    constitute white space. */
  655. X
  656. Xchar *src;
  657. Xchar *separator;
  658. X{
  659. X   TKSTR    tokens;
  660. X   char        *tok;
  661. X   char        *res;
  662. X   int        first = TRUE;
  663. X
  664. X   DB_ENTER( "_tokenize" );
  665. X
  666. X   SET_TOKEN( &tokens, src );
  667. X
  668. X
  669. X   /* map the escape codes in the separator string first */
  670. X
  671. X   for(tok=separator; (tok = strchr(tok,CONTINUATION_CHAR)) != NIL(char); tok++)
  672. X      Map_esc( tok );
  673. X
  674. X   DB_PRINT( "exp", ("Separator [%s]", separator) );
  675. X
  676. X   /* Build the token list */
  677. X   res = _strdup( "" );
  678. X   while( *(tok = Get_token( &tokens, "", FALSE )) != '\0' ) {
  679. X      DB_PRINT( "exp", ("Tokenizing [%s]", tok) );
  680. X
  681. X      if( first ) {
  682. X     FREE( res );
  683. X     res   = _strdup( tok );
  684. X     first = FALSE;
  685. X      }
  686. X      else {
  687. X           char *x;
  688. X     res = _strjoin(res, x =_strjoin(separator, tok, -1, FALSE), -1, TRUE);
  689. X     FREE( x );
  690. X      }
  691. X   }
  692. X
  693. X   FREE( src );
  694. X   DB_RETURN( res );
  695. X}
  696. SHAR_EOF
  697. echo "File expand.c is complete"
  698. chmod 0440 expand.c || echo "restore of expand.c fails"
  699. echo "x - extracting dump.c (Text)"
  700. sed 's/^X//' << 'SHAR_EOF' > dump.c &&
  701. X/* RCS      -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/dump.c,v 1.1 90/07/21 11:06:32 dvadura Exp $
  702. X-- SYNOPSIS -- dump the internal dag to stdout.
  703. X-- 
  704. X-- DESCRIPTION
  705. X--    This file contains the routine that is called to dump a version of
  706. X--    the digested makefile to the standard output.  May be useful perhaps
  707. X--    to the ordinary user, and invaluable for debugging make.
  708. X-- 
  709. X-- AUTHOR
  710. X--      Dennis Vadura, dvadura@watdragon.uwaterloo.ca
  711. X--      CS DEPT, University of Waterloo, Waterloo, Ont., Canada
  712. X--
  713. X-- COPYRIGHT
  714. X--      Copyright (c) 1990 by Dennis Vadura.  All rights reserved.
  715. X-- 
  716. X--      This program is free software; you can redistribute it and/or
  717. X--      modify it under the terms of the GNU General Public License
  718. X--      (version 1), as published by the Free Software Foundation, and
  719. X--      found in the file 'LICENSE' included with this distribution.
  720. X-- 
  721. X--      This program is distributed in the hope that it will be useful,
  722. X--      but WITHOUT ANY WARRANTY; without even the implied warrant of
  723. X--      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  724. X--      GNU General Public License for more details.
  725. X-- 
  726. X--      You should have received a copy of the GNU General Public License
  727. X--      along with this program;  if not, write to the Free Software
  728. X--      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  729. X--
  730. X-- LOG
  731. X--     $Log:    dump.c,v $
  732. X * Revision 1.1  90/07/21  11:06:32  dvadura
  733. X * Initial Revision Version 3.5
  734. X * 
  735. X*/
  736. X
  737. X#include "db.h"
  738. X#include "extern.h"
  739. X
  740. X#define M_TEST    (M_PRECIOUS | M_VAR_MASK)
  741. X
  742. Xstatic    void    dump_normal_target ANSI((CELLPTR, HOWPTR, CELLPTR));
  743. Xstatic    void    dump_graph_node ANSI((CELLPTR));
  744. Xstatic    void    dump_name ANSI((HASHPTR, int));
  745. X
  746. X
  747. Xvoid
  748. XDump()/*
  749. X========  Dump onto standard output the digested makefile.  Note that
  750. X      the form of the dump is not representative of the contents
  751. X      of the original makefile contents at all */
  752. X{
  753. X   HASHPTR      hp;
  754. X   int          i;
  755. X
  756. X   DB_ENTER( "Dump" );
  757. X
  758. X   puts( "# Dump of dmake macro variables:" );
  759. X   for( i=0; i<HASH_TABLE_SIZE; i++)
  760. X      for( hp=Macs[i]; hp != NIL(HASH); hp = hp->ht_next ) {
  761. X     int flag = hp->ht_flag;
  762. X
  763. X     printf( "%s ", hp->ht_name );
  764. X     if( flag & M_EXPANDED ) putchar( ':' );
  765. X     printf( "= " );
  766. X     if( hp->ht_value != NIL(char) ) printf( hp->ht_value );
  767. X     if( flag & M_PRECIOUS )
  768. X        printf( "\t # PRECIOUS " );
  769. X     putchar( '\n' );
  770. X      }
  771. X
  772. X   puts( "\n#====================================" );
  773. X   puts( "# Dump of targets:\n" );
  774. X
  775. X   for( i=0; i<HASH_TABLE_SIZE; i++ )
  776. X      for( hp = Defs[i]; hp != NIL(HASH); hp = hp->ht_next )
  777. X         if( !(hp->CP_OWNR->ce_flag & F_PERCENT) ) {
  778. X        if( hp->CP_OWNR == Fringe_hd->cl_prq )
  779. X           puts( "# ******* FIRST TARGET ********" );
  780. X        dump_normal_target( hp->CP_OWNR, hp->CP_OWNR->CE_HOW, NIL(CELL) );
  781. X     }
  782. X
  783. X   puts( "\n#====================================" );
  784. X   puts( "# Dump of inference graph\n" );
  785. X
  786. X   for( i=0; i<HASH_TABLE_SIZE; i++ )
  787. X      for( hp = Defs[i]; hp != NIL(HASH); hp = hp->ht_next )
  788. X         if( (hp->CP_OWNR->ce_flag & F_PERCENT) &&
  789. X        !(hp->CP_OWNR->ce_flag & F_MAGIC) )
  790. X        dump_graph_node( hp->CP_OWNR );
  791. X
  792. X   DB_VOID_RETURN;
  793. X}
  794. X
  795. X
  796. X
  797. Xvoid
  798. XDump_recipe( sp )/*
  799. X===================
  800. X   Given a string pointer print the recipe line out */
  801. XSTRINGPTR sp;
  802. X{
  803. X   char *st;
  804. X   char *nl;
  805. X
  806. X   if( sp == NIL(STRING) ) return;
  807. X
  808. X   putchar( '\t' );
  809. X   if( sp->st_attr & A_SILENT ) putchar( '@' );
  810. X   if( sp->st_attr & A_IGNORE ) putchar( '-' );
  811. X
  812. X   st = sp->st_string;
  813. X   for( nl=strchr(st,'\n'); nl != NIL( char); nl=strchr(st,'\n') ) {
  814. X      *nl = '\0';
  815. X      printf( "%s\\\n", st );
  816. X      *nl = '\n';
  817. X      st  = nl+1;
  818. X   }
  819. X   printf( "%s\n", st );
  820. X}
  821. X
  822. X
  823. Xstatic char *_attrs[] = { ".PRECIOUS ", ".SILENT ", ".LIBRARY ",
  824. X   ".EPILOG ", ".PROLOG ", ".IGNORE ", ".SYMBOL ", ".NOINFER ",
  825. X   ".UPDATEALL ", ".SEQUENTIAL " };
  826. X
  827. Xstatic void
  828. Xdump_normal_target( cp, hw, prq )/*
  829. X===================================
  830. X    Dump in makefile like format the dag information */
  831. XCELLPTR cp;
  832. XHOWPTR  hw;
  833. XCELLPTR prq;
  834. X{
  835. X   register LINKPTR   lp;
  836. X   register STRINGPTR sp;
  837. X   unsigned int          attr, k;
  838. X
  839. X   DB_ENTER( "dump_normal_target" );
  840. X
  841. X   if( hw == NIL(HOW) ) { DB_VOID_RETURN; }
  842. X   if( hw->hw_next != NIL(HOW) ) dump_normal_target( cp, hw->hw_next, prq );
  843. X
  844. X   dump_name( cp->ce_name, FALSE );
  845. X
  846. X   for( k=0, attr=1; attr < MAX_ATTR; attr <<= 1, k++ )
  847. X      if( cp->ce_attr & attr )
  848. X         printf( _attrs[k] );
  849. X         
  850. X   if( cp->ce_attr & A_SETDIR )
  851. X      printf( ".SETDIR=%s ", cp->ce_dir ? cp->ce_dir : "" );
  852. X
  853. X   putchar( ':' );
  854. X
  855. X   if( cp->ce_flag & F_MULTI )  putchar( ':' );
  856. X   if( hw->hw_flag & F_SINGLE ) putchar( '!' );
  857. X   putchar( ' ' );
  858. X
  859. X   if( prq != NIL(CELL) ) dump_name( prq->ce_name, FALSE );
  860. X   for( lp = hw->hw_prq; lp != NIL(LINK); lp = lp->cl_next )
  861. X      dump_name( lp->cl_prq->ce_name, FALSE );
  862. X
  863. X   if( (lp = hw->hw_indprq) != NIL(LINK) ) {
  864. X      for( ; lp != NIL(LINK); lp = lp->cl_next )
  865. X     dump_name( lp->cl_prq->ce_name, TRUE );
  866. X   }
  867. X
  868. X   putchar( '\n' );
  869. X   if( hw->hw_flag & F_GROUP ) {
  870. X      if( hw->hw_attr & A_IGNORE ) putchar( '-' );
  871. X      if( hw->hw_attr & A_SILENT ) putchar( '@' );
  872. X      puts( "[" );
  873. X   }
  874. X
  875. X   for( sp = hw->hw_recipe; sp != NIL(STRING); sp = sp->st_next )
  876. X      Dump_recipe( sp );
  877. X   if( hw->hw_flag & F_GROUP ) puts( "]" );
  878. X
  879. X   putchar( '\n' );
  880. X   DB_VOID_RETURN;
  881. X}
  882. X
  883. X
  884. Xstatic void
  885. Xdump_name( hp, quote )/*
  886. X========================
  887. X    print out a name */
  888. XHASHPTR hp;
  889. Xint     quote;
  890. X{
  891. X   if( quote ) putchar('\'');
  892. X   printf( "%s", hp->ht_name );
  893. X   if( quote ) putchar('\'');
  894. X   putchar(' ');
  895. X}
  896. X
  897. X
  898. Xstatic void
  899. Xdump_graph_node( cp )/*
  900. X=======================*/
  901. XCELLPTR cp;
  902. X{
  903. X   EDGEPTR    pe;
  904. X
  905. X   pe = cp->CE_EDGES; 
  906. X
  907. X   if( pe != NIL(EDGE) )
  908. X      do {
  909. X     dump_normal_target( cp, pe->ed_how, pe->ed_prq );
  910. X     pe = pe->ed_next;
  911. X      }
  912. X      while( pe != cp->CE_EDGES );
  913. X}
  914. SHAR_EOF
  915. chmod 0440 dump.c || echo "restore of dump.c fails"
  916. echo "x - extracting dmake.h (Text)"
  917. sed 's/^X//' << 'SHAR_EOF' > dmake.h &&
  918. X/* RCS      -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/dmake.h,v 1.1 90/07/19 13:55:27 dvadura Exp $
  919. X-- SYNOPSIS -- global defines for dmake.
  920. X-- 
  921. X-- DESCRIPTION
  922. X--     All the interesting bits and flags that dmake uses are defined here.
  923. X--
  924. X-- AUTHOR
  925. X--      Dennis Vadura, dvadura@watdragon.uwaterloo.ca
  926. X--      CS DEPT, University of Waterloo, Waterloo, Ont., Canada
  927. X--
  928. X-- COPYRIGHT
  929. X--      Copyright (c) 1990 by Dennis Vadura.  All rights reserved.
  930. X-- 
  931. X--      This program is free software; you can redistribute it and/or
  932. X--      modify it under the terms of the GNU General Public License
  933. X--      (version 1), as published by the Free Software Foundation, and
  934. X--      found in the file 'LICENSE' included with this distribution.
  935. X-- 
  936. X--      This program is distributed in the hope that it will be useful,
  937. X--      but WITHOUT ANY WARRANTY; without even the implied warrant of
  938. X--      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  939. X--      GNU General Public License for more details.
  940. X-- 
  941. X--      You should have received a copy of the GNU General Public License
  942. X--      along with this program;  if not, write to the Free Software
  943. X--      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  944. X--
  945. X-- LOG
  946. X--     $Log:    dmake.h,v $
  947. X * Revision 1.1  90/07/19  13:55:27  dvadura
  948. X * Initial Revision of Version 3.5
  949. X * 
  950. X*/
  951. X
  952. X#ifndef _DMAKE_INCLUDED_
  953. X#define _DMAKE_INCLUDED_
  954. X
  955. X#define MAX_INC_DEPTH     10     /* max of ten nested include files      */
  956. X#define MAX_COND_DEPTH      20     /* max nesting level of conditionals    */
  957. X#define ERROR_EXIT_VALUE  255     /* return code of aborted make         */
  958. X#define CONTINUATION_CHAR '\\'   /* line continuation \<nl>              */
  959. X#define ESCAPE_CHAR       '\\'   /* escape char for used chars           */
  960. X#define COMMENT_CHAR      '#'    /* start of comment chars               */
  961. X#define TGT_DEP_SEP       ':'    /* separator for targets and dependents */
  962. X#define CONDSTART      '.'     /* start of conditional token    eg .IF     */
  963. X#define DEF_MAKE_PNAME    "dmake"/* default name to use as name of make  */
  964. X
  965. X
  966. X/* ............... Hashing function constants ......................... */
  967. X#define HASH_TABLE_SIZE  200            /* See hash.c for description   */
  968. X
  969. X
  970. X/* Bit flags for cells and macro definitions. */
  971. X#define M_DEFAULT        0x0000         /* default flag value           */
  972. X#define M_MARK           0x0001         /* mark for circularity checks  */
  973. X#define M_PRECIOUS       0x0002         /* keep macro, same as A_PRE... */
  974. X#define M_MULTI          0x0004         /* multiple redefinitions ok!   */
  975. X#define M_EXPANDED       0x0008         /* macro has been assigned      */
  976. X#define M_USED         0x0010        /* macro has been expanded    */
  977. X#define M_LITERAL     0x0020        /* don't strip w/s on macro def */
  978. X#define    M_NOEXPORT     0x0040        /* don't export macro for -x    */
  979. X#define M_FORCE         0x0080        /* Force a macro redefinition    */
  980. X#define M_VAR_BIT        0x1000         /* macro bit variable           */
  981. X#define M_VAR_CHAR       0x2000         /* macro char variable          */
  982. X#define M_VAR_STRING     0x4000         /* macro string variable        */
  983. X#define M_VAR_INT     0x8000        /* macro integer variable    */
  984. X
  985. X#define M_VAR_MASK       0xf000         /* macro variable mask          */
  986. X
  987. X
  988. X
  989. X/* Global and target attribute flag definitions.
  990. X * If you change the values of these or re-order them make appropriate changes
  991. X * in dump.c so that the output of dmake -p matches the attribute info for a
  992. X * target. */
  993. X
  994. X#define A_DEFAULT        0x0000         /* default flag value           */
  995. X#define A_PRECIOUS       0x0001         /* object is precious           */
  996. X#define A_SILENT         0x0002         /* don't echo commands          */
  997. X#define A_LIBRARY        0x0004         /* target is an archive        */
  998. X#define A_EPILOG         0x0008         /* insert shell epilog code     */
  999. X#define A_PROLOG         0x0010         /* insert shell prolog code     */
  1000. X#define A_IGNORE         0x0020         /* ignore errors                */
  1001. X#define A_SYMBOL     0x0040        /* lib member is a symbol    */
  1002. X#define A_NOINFER     0x0080        /* no trans closure from cell    */
  1003. X#define A_UPDATEALL     0x0100        /* all targets of rule modified */
  1004. X#define A_SEQ         0x0200        /* sequential make attribute    */
  1005. X#define A_SETDIR         0x0400         /* cd to dir when making target */
  1006. X#define MAX_ATTR     A_SETDIR    /* highest valid attribute    */
  1007. X#define A_LIBRARYM       0x0800         /* target is an archive member  */
  1008. X#define A_FRINGE     0x1000        /* cell is on the fringe    */
  1009. X#define A_COMPOSITE     0x2000        /* member of lib(targ) name    */
  1010. X#define A_FFNAME     0x4000        /* if set, free ce_fname in stat*/
  1011. X#define A_UPDATED     0x8000        /* Used to mark cell as updated */
  1012. X
  1013. X
  1014. X/* Global and target bit flag definitions */
  1015. X
  1016. X#define F_DEFAULT        0x0000         /* default flag value           */
  1017. X#define F_MARK         0x0001        /* circularity check mark    */
  1018. X#define F_MULTI         0x0002        /* multiple rules for target    */
  1019. X#define F_SINGLE     0x0004        /* exec rules one/prerequisite  */
  1020. X#define F_TARGET     0x0008        /* marks a target        */
  1021. X#define F_RULES          0x0010         /* indicates target has rules   */
  1022. X#define F_GROUP          0x0020         /* indicates that rules are to  */
  1023. X                        /* fed to the shell as a group  */
  1024. X
  1025. X#define F_TRANS         0x0040        /* same as F_STAT not used tgthr*/
  1026. X#define F_STAT         0x0040        /* target already stated    */
  1027. X#define F_VISITED     0x0080        /* target scheduled for make    */
  1028. X#define F_USED         0x0080        /* used in releparse.c        */
  1029. X#define F_SPECIAL     0x0100        /* marks a special target    */
  1030. X#define F_DFA          0x0200        /* bit for marking added DFA    */
  1031. X#define F_EXPLICIT     0x0400        /* explicit target in makefile  */
  1032. X#define F_PERCENT     0x0800        /* marks a target as a % rule    */
  1033. X#define F_REMOVE     0x1000        /* marks an intermediate target */
  1034. X#define F_MAGIC         0x2000        /* marks a magic target        */
  1035. X#define F_INFER         0x4000        /* target is result of inference*/
  1036. X#define F_MADE         0x8000        /* target is manufactured    */
  1037. X
  1038. X
  1039. X/* Definitions for the Parser states */
  1040. X#define NORMAL_SCAN    0     /* normal processing state */
  1041. X#define RULE_SCAN      1     /* scan of rule text       */
  1042. X
  1043. X/* definitions for macro operator types */
  1044. X#define M_OP_EQ  1           /* macro operation is '='  */
  1045. X#define M_OP_CL  2           /* macro operation is ':=' */
  1046. X#define M_OP_PL  4           /* macro operation is '+=' */
  1047. X#define M_OP_PLCL 8          /* macro operation is '+:='*/
  1048. X
  1049. X/* definitions for rule operator types */
  1050. X#define R_OP_CL   1           /* rule operation is ':'   */
  1051. X#define R_OP_DCL  2           /* rule operation is '::'  */
  1052. X#define R_OP_BG   4           /* rule operation is ':!'  */
  1053. X#define R_OP_UP   8           /* rule operation is ':^'  */
  1054. X#define R_OP_MI  16           /* rule operation is ':-'  */
  1055. X
  1056. X
  1057. X/* special target definitions for use inside dmake */
  1058. X#define ST_IF        1
  1059. X#define ST_ELSE        2
  1060. X#define ST_END        3
  1061. X#define ST_REST        4    /* remaining special targets */
  1062. X#define ST_INCLUDE    5
  1063. X#define ST_SOURCE    7
  1064. X#define ST_EXPORT    8
  1065. X#define ST_IMPORT    9
  1066. X
  1067. X/* Macro definitions for use inside dmake */
  1068. X#define SET_TOKEN(A, B)  (A)->tk_str = (B); (A)->tk_cchar = *(B);\
  1069. X             (A)->tk_quote = 1;
  1070. X#define CLEAR_TOKEN(A)   *(A)->tk_str = (A)->tk_cchar
  1071. X#define GET_MACRO(A)     Get_name(A, Macs, FALSE, NIL(CELL))
  1072. X#define iswhite(C)     ((C == ' ') || (C == '\t'))
  1073. X
  1074. X#endif
  1075. X
  1076. SHAR_EOF
  1077. chmod 0440 dmake.h || echo "restore of dmake.h fails"
  1078. echo "x - extracting dmake.c (Text)"
  1079. sed 's/^X//' << 'SHAR_EOF' > dmake.c &&
  1080. X/* RCS      -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/dmake.c,v 1.1 90/07/19 13:53:05 dvadura Exp $
  1081. X-- SYNOPSIS -- The main program.
  1082. X-- 
  1083. X-- DESCRIPTION
  1084. X-- 
  1085. X--     dmake [-#dbug_string] [ options ]
  1086. X--             [ macro definitions ] [ target ... ]
  1087. X-- 
  1088. X--     This file contains the main command line parser for the
  1089. X--     make utility.  The valid flags recognized are as follows:
  1090. X-- 
  1091. X--     -f file         - use file as the makefile
  1092. X--     -#dbug_string   - dump out debugging info, see below
  1093. X-- 
  1094. X--      options: (can be catenated, ie -irn == -i -r -n)
  1095. X-- 
  1096. X--    -A        - enable AUGMAKE special target mapping
  1097. X--     -i              - ignore errors
  1098. X--     -n              - trace and print, do not execute commands
  1099. X--     -t              - touch, update dates without executing commands
  1100. X--     -T              - do not apply transitive closure
  1101. X--     -r              - don't use internal rules
  1102. X--     -s              - do your work silently
  1103. X--    -S        - force Sequential make, overrides -P
  1104. X--     -q              - check if target is up to date.  Does not
  1105. X--               do anything.  Returns 0 if up to date, -1
  1106. X--               otherwise.
  1107. X--     -p              - print out a version of the makefile
  1108. X--    -P#        - set value of MAXPROCESS
  1109. X--     -e              - define environment strings as macros
  1110. X--     -E              - as -e but done after parsing makefile
  1111. X--     -u              - force unconditional update of target
  1112. X--     -k              - make all independent targets even if errors
  1113. X--     -V              - print out this make version number
  1114. X--     -v        - verbose, print what we are doing, as we do it.
  1115. X--     -M        - Microsoft make compatibility, (* disabled *)
  1116. X--     -h              - print out usage info
  1117. X--     -x        - export macro defs to environment
  1118. X-- 
  1119. X--     NOTE:  - #ddbug_string is only availabe for versions of dmake that
  1120. X--         have been compiled with -DDBUG switch on.  Not the case for
  1121. X--         distributed versions.  Any such versions must be linked
  1122. X--         together with a version of Fred Fish's debug code.
  1123. X--              
  1124. X--     NOTE:  - in order to compile the code the include file stddef.h
  1125. X--         must be shipped with the bundled code.
  1126. X-- 
  1127. X-- AUTHOR
  1128. X--      Dennis Vadura, dvadura@watdragon.uwaterloo.ca
  1129. X--      CS DEPT, University of Waterloo, Waterloo, Ont., Canada
  1130. X--
  1131. X-- COPYRIGHT
  1132. X--      Copyright (c) 1990 by Dennis Vadura.  All rights reserved.
  1133. X-- 
  1134. X--      This program is free software; you can redistribute it and/or
  1135. X--      modify it under the terms of the GNU General Public License
  1136. X--      (version 1), as published by the Free Software Foundation, and
  1137. X--      found in the file 'LICENSE' included with this distribution.
  1138. X-- 
  1139. X--      This program is distributed in the hope that it will be useful,
  1140. X--      but WITHOUT ANY WARRANTY; without even the implied warrant of
  1141. X--      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  1142. X--      GNU General Public License for more details.
  1143. X-- 
  1144. X--      You should have received a copy of the GNU General Public License
  1145. X--      along with this program;  if not, write to the Free Software
  1146. X--      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  1147. X--
  1148. X-- LOG
  1149. X--     $Log:    dmake.c,v $
  1150. X * Revision 1.1  90/07/19  13:53:05  dvadura
  1151. X * Initial Revision of Version 3.5
  1152. X * 
  1153. X*/
  1154. X
  1155. X/* Set this flag to one, and the global variables in vextern.h will not
  1156. X * be defined as 'extern', instead they will be defined as global vars
  1157. X * when this module is compiled. */
  1158. X#define _DEFINE_GLOBALS_ 1
  1159. X
  1160. X#include <ctype.h>
  1161. X#include <stdarg.h>
  1162. X#include "extern.h"
  1163. X#include "alloc.h"
  1164. X#include "db.h"
  1165. X#include "patchlvl.h"
  1166. X#include "version.h"
  1167. X
  1168. X#ifdef HELP
  1169. X#define USAGE \
  1170. X"Usage: %s [-AeEhiknpqrsStTuvVx] [-P#] [-f file] [macro=value ...] [target ...]\n"
  1171. X#define COPYRIGHT "Copyright (c) 1990 by Dennis Vadura"
  1172. X#endif
  1173. X
  1174. Xstatic char *sccid = COPYRIGHT;
  1175. Xstatic char _warn  = TRUE;        /* warnings on by default */
  1176. X
  1177. Xstatic    void    _do_VPATH();
  1178. Xstatic    void    _do_ReadEnvironment();
  1179. X
  1180. Xmain(argc, argv)
  1181. Xint  argc;
  1182. Xchar **argv;
  1183. X{
  1184. X   char*   fil_name = NIL(char);
  1185. X   char*   cmdmacs;
  1186. X   FILE*   mkfil;
  1187. X   int     ex_val;
  1188. X   int     m_export;
  1189. X   HASHPTR hp;
  1190. X
  1191. X   DB_ENTER("main");
  1192. X
  1193. X   /* Initialize Global variables to their default values       */
  1194. X   Prolog(argc, argv);
  1195. X   Create_macro_vars();
  1196. X   Catch_signals(Quit);
  1197. X
  1198. X   Def_macro( "MAKECMD", Pname, M_PRECIOUS|M_NOEXPORT );
  1199. X   Pname = basename(Pname);
  1200. X
  1201. X   DB_PROCESS(Pname);
  1202. X   (void) setvbuf(stdout, NULL, _IOLBF, BUFSIZ); /* stdout line buffered */
  1203. X
  1204. X   Continue  = FALSE;
  1205. X   Get_env   = FALSE;
  1206. X   Force     = FALSE;
  1207. X   Target    = FALSE;
  1208. X   If_expand = FALSE;
  1209. X   Listing   = FALSE;
  1210. X   Readenv   = FALSE;
  1211. X   Rules     = TRUE;
  1212. X   Trace     = FALSE;
  1213. X   Touch     = FALSE;
  1214. X   Check     = FALSE;
  1215. X   Microsoft = FALSE;
  1216. X   Verbose   = FALSE;
  1217. X   Makemkf   = FALSE;
  1218. X   m_export  = FALSE;
  1219. X   cmdmacs   = NIL(char);
  1220. X
  1221. X   Transitive     = TRUE;
  1222. X   Nest_level     = 0;
  1223. X   Line_number    = 0;
  1224. X
  1225. X   while( --argc > 0 ) {
  1226. X      register char *p;
  1227. X      char *q;
  1228. X
  1229. X      if( *(p = *++argv) == '-' ) {
  1230. X         if( p[1] == '\0' ) Fatal("Missing option letter");
  1231. X
  1232. X         /* copy options to Buffer for $(MFLAGS), strip 'f' */
  1233. X         q = strchr(Buffer, 0);
  1234. X         while (*p != 0)
  1235. X            if( (*q++ = *p++) == 'f' ) q--;
  1236. X
  1237. X     if( *(q-1) == '-' )
  1238. X        q--;
  1239. X     else
  1240. X            *q++ = ' ';
  1241. X
  1242. X     *q = 0;
  1243. X
  1244. X         for( p = *argv+1; *p; p++) switch (*p) {
  1245. X        case 'f':
  1246. X           if( fil_name == NIL(char) ) {
  1247. X          if( *++argv != NIL(char) ) {
  1248. X             fil_name = *argv;
  1249. X             argc--;
  1250. X          } else
  1251. X             Fatal("No file name for -f");
  1252. X           } else
  1253. X          Fatal("Only one `-f file' allowed");
  1254. X           break;
  1255. X
  1256. X        case 'k': Continue   = TRUE;  break;
  1257. X        case 'p': Listing    = TRUE;  break;
  1258. X        case 'r': Rules      = FALSE; break;
  1259. X        case 'n': Trace      = TRUE;  break;
  1260. X        case 't': Touch      = TRUE;  break;
  1261. X        case 'q': Check      = TRUE;  break;
  1262. X        case 'u': Force      = TRUE;  break;
  1263. X        case 'v': Verbose    = TRUE;  break;
  1264. X        case 'x': m_export   = TRUE;  break;
  1265. X        case 'T': Transitive = FALSE; break;
  1266. X        case 'e': Get_env    = 'e';   break;
  1267. X        case 'E': Get_env    = 'E';   break;
  1268. X
  1269. X        case 'V': Version();  Quit(NIL(CELL));  break;
  1270. X        case 'A': Def_macro("AUGMAKE", "y", M_EXPANDED); break;
  1271. X        case 'i': Def_macro(".IGNORE", "y", M_EXPANDED); break;
  1272. X        case 's': Def_macro(".SILENT", "y", M_EXPANDED); break;
  1273. X        case 'S': Def_macro(".SEQUENTIAL", "y", M_EXPANDED); break;
  1274. X
  1275. X        case 'P':
  1276. X           if( p[1] ) {
  1277. X          Def_macro( "MAXPROCESS", p+1, M_MULTI|M_EXPANDED );
  1278. X          p += strlen(p)-1;
  1279. X           }
  1280. X           else
  1281. X          Fatal( "Missing number for -P flag" );
  1282. X           break;
  1283. X
  1284. X#if 0   /*** disabled */
  1285. X        case 'M': Microsoft  = TRUE;  break;
  1286. X#endif
  1287. X#ifdef HELP
  1288. X        case 'h': Usage();  Quit(NIL(CELL));  break;
  1289. X#endif
  1290. X#ifdef DBUG
  1291. X        case '#':
  1292. X           DB_PUSH(p+1);
  1293. X           p += strlen(p)-1;
  1294. X           break;
  1295. X#endif
  1296. X
  1297. X        default:
  1298. X           fprintf(stderr, USAGE, Pname);
  1299. X           Quit(NIL(CELL));
  1300. X           break;
  1301. X     }
  1302. X      }
  1303. X      else if( (q = strchr(p, '=')) != NIL(char) ) {
  1304. X     cmdmacs = _stradd( cmdmacs, _strdup(p), FALSE );
  1305. X     Parse_macro( p, M_PRECIOUS );
  1306. X      }
  1307. X      else {
  1308. X     register CELLPTR cp;
  1309. X     Add_fringe(cp = Def_cell(p, NIL(CELL)));
  1310. X     cp->ce_flag |= F_TARGET;
  1311. X     Target = TRUE;
  1312. X      }
  1313. X   }
  1314. X
  1315. X   Def_macro( "MAKEMACROS", cmdmacs, M_PRECIOUS|M_NOEXPORT );
  1316. X   if( cmdmacs != NIL(char) ) FREE(cmdmacs);
  1317. X
  1318. X   Def_macro( "MFLAGS", Buffer, M_PRECIOUS|M_NOEXPORT );
  1319. X   Def_macro( "%", "$@", M_PRECIOUS|M_NOEXPORT );
  1320. X
  1321. X   if( *Buffer ) Def_macro( "MAKEFLAGS", Buffer+1, M_PRECIOUS|M_NOEXPORT );
  1322. X
  1323. X   _warn  = FALSE;      /* disable warnings for builtin rules */
  1324. SHAR_EOF
  1325. echo "End of part 17"
  1326. echo "File dmake.c is continued in part 18"
  1327. echo "18" > s2_seq_.tmp
  1328. exit 0
  1329.  
  1330.