home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume27 / jam / part02 < prev    next >
Encoding:
Text File  |  1993-11-15  |  57.0 KB  |  2,678 lines

  1. Newsgroups: comp.sources.unix
  2. From: seiwald@vix.com (Christopher Seiwald)
  3. Subject: v27i082: jam - just another make, Part02/05
  4. References: <1.753385306.22859@gw.home.vix.com>
  5. Sender: unix-sources-moderator@gw.home.vix.com
  6. Approved: vixie@gw.home.vix.com
  7.  
  8. Submitted-By: seiwald@vix.com (Christopher Seiwald)
  9. Posting-Number: Volume 27, Issue 82
  10. Archive-Name: jam/part02
  11.  
  12. Submitted-by: seiwald@vix.com
  13. Archive-name: jam - make(1) redux/part02
  14.  
  15. #!/bin/sh
  16. # This is part 02 of jam - make(1) redux
  17. # ============= compile.c ==============
  18. if test -f 'compile.c' -a X"$1" != X"-c"; then
  19.     echo 'x - skipping compile.c (File already exists)'
  20. else
  21. echo 'x - extracting compile.c (Text)'
  22. sed 's/^X//' << 'SHAR_EOF' > 'compile.c' &&
  23. X/*
  24. X * Copyright 1993 Christopher Seiwald.
  25. X */
  26. X
  27. X# include "jam.h"
  28. X
  29. X# include "lists.h"
  30. X# include "parse.h"
  31. X# include "compile.h"
  32. X# include "variable.h"
  33. X# include "rules.h"
  34. X# include "newstr.h"
  35. X# include "make.h"
  36. X
  37. X/*
  38. X * compile.c - compile parsed jam statements
  39. X *
  40. X * External routines:
  41. X *
  42. X *    compile_foreach() - compile the "for x in y" statement
  43. X *    compile_if() - compile 'if' rule
  44. X *    compile_include() - support for 'include' - call include() on file
  45. X *    compile_rule() - compile a single user defined rule
  46. X *    compile_rules() - compile a chain of rules
  47. X *    compile_set() - compile the "set variable" statement
  48. X *    compile_setcomp() - support for `compiles` - save parse tree 
  49. X *    compile_setexec() - support for `executes` - save execution string 
  50. X *    compile_settings() - compile the "on =" (set variable on exec) statement
  51. X *    compile_switch() - compile 'switch' rule
  52. X *
  53. X * Internal routines:
  54. X *
  55. X *    evaluate_if() - evaluate if to determine which leg to compile
  56. X *
  57. X *    builtin_depends() - DEPENDS rule
  58. X *    builtin_echo() - ECHO rule
  59. X *    builtin_includes() - INCLUDES rule
  60. X *    builtin_flags() - NOCARE, NOTIME, TEMPORARY rule
  61. X */
  62. X
  63. Xstatic int evaluate_if();
  64. X
  65. Xstatic void builtin_depends();
  66. Xstatic void builtin_echo();
  67. Xstatic void builtin_includes();
  68. Xstatic void builtin_flags();
  69. X
  70. X
  71. X
  72. X/*
  73. X * compile_builtin() - define builtin rules
  74. X */
  75. X
  76. X# define P0 (PARSE *)0
  77. X# define L0 (LIST *)0
  78. X# define C0 (char *)0
  79. X
  80. Xvoid
  81. Xcompile_builtins()
  82. X{
  83. X    bindrule( "DEPENDS" )->procedure = 
  84. X        parse_make( builtin_depends, P0, P0, C0, C0, L0, L0, 0 );
  85. X    bindrule( "ECHO" )->procedure = 
  86. X        parse_make( builtin_echo, P0, P0, C0, C0, L0, L0, 0 );
  87. X    bindrule( "INCLUDES" )->procedure = 
  88. X        parse_make( builtin_includes, P0, P0, C0, C0, L0, L0, 0 );
  89. X
  90. X    bindrule( "NOCARE" )->procedure = 
  91. X        parse_make( builtin_flags, P0, P0, C0, C0, L0, L0, T_FLAG_NOCARE );
  92. X    bindrule( "NOTIME" )->procedure = 
  93. X        parse_make( builtin_flags, P0, P0, C0, C0, L0, L0, T_FLAG_NOTIME );
  94. X    bindrule( "TEMPORARY" )->procedure = 
  95. X        parse_make( builtin_flags, P0, P0, C0, C0, L0, L0, T_FLAG_TEMP );
  96. X}
  97. X
  98. X/*
  99. X * compile_foreach() - compile the "for x in y" statement
  100. X *
  101. X * Compile_foreach() resets the given variable name to each specified
  102. X * value, executing the commands enclosed in braces for each iteration.
  103. X *
  104. X *    parse->string    index variable
  105. X *    parse->left    rule to compile
  106. X *    parse->llist    variable values
  107. X */
  108. X
  109. Xvoid
  110. Xcompile_foreach( parse, targets, sources )
  111. XPARSE        *parse;
  112. XLIST        *targets;
  113. XLIST        *sources;
  114. X{
  115. X    LIST    *nv = var_list( parse->llist, targets, sources );
  116. X    LIST    *l;
  117. X
  118. X    /* Call var_set to reset $(parse->string) for each val. */
  119. X
  120. X    for( l = nv; l; l = list_next( l ) )
  121. X    {
  122. X        LIST *val = list_new( (LIST *)0, copystr( l->string ) );
  123. X
  124. X        var_set( parse->string, val );
  125. X
  126. X        (*parse->left->func)( parse->left, targets, sources );
  127. X    }
  128. X
  129. X    list_free( nv );
  130. X}
  131. X
  132. X/*
  133. X * compile_if() - compile 'if' rule
  134. X *
  135. X *    parse->left        condition tree
  136. X *    parse->right->left    then tree
  137. X *    parse->right->right    else tree
  138. X */
  139. X
  140. Xvoid
  141. Xcompile_if( parse, targets, sources )
  142. XPARSE        *parse;
  143. XLIST        *targets;
  144. XLIST        *sources;
  145. X{
  146. X    PARSE    *then = parse->right;
  147. X
  148. X    if( evaluate_if( parse->left, targets, sources ) )
  149. X        (*then->left->func)( then->left, targets, sources );
  150. X    else if( then->right )
  151. X        (*then->right->func)( then->right, targets, sources );
  152. X}
  153. X
  154. X/*
  155. X * evaluate_if() - evaluate if to determine which leg to compile
  156. X *
  157. X * Returns:
  158. X *    !0    if expression true - compile 'then' clause
  159. X *    0    if expression false - compile 'else' clause
  160. X */
  161. X
  162. Xstatic int
  163. Xevaluate_if( parse, targets, sources )
  164. XPARSE        *parse;
  165. XLIST        *targets;
  166. XLIST        *sources;
  167. X{
  168. X    int    status;
  169. X
  170. X    if( parse->num <= COND_OR )
  171. X    {
  172. X        /* Handle one of the logical operators */
  173. X
  174. X        switch( parse->num )
  175. X        {
  176. X        case COND_NOT:
  177. X        status = !evaluate_if( parse->left, targets, sources );
  178. X        break;
  179. X
  180. X        case COND_AND:
  181. X        status = evaluate_if( parse->left, targets, sources ) &&
  182. X             evaluate_if( parse->right, targets, sources );
  183. X        break;
  184. X
  185. X        case COND_OR:
  186. X        status = evaluate_if( parse->left, targets, sources ) ||
  187. X             evaluate_if( parse->right, targets, sources );
  188. X        break;
  189. X        }
  190. X    }
  191. X    else
  192. X    {
  193. X        /* Handle one of the comparison operators */
  194. X
  195. X        LIST    *nt;
  196. X        LIST    *ns;
  197. X        char    *st;
  198. X        char    *ss;
  199. X
  200. X        /* Expand targets and sources */
  201. X
  202. X        st = ss = "";
  203. X
  204. X        if( nt = var_list( parse->llist, targets, sources ) )
  205. X        st = nt->string;
  206. X
  207. X        if( ns = var_list( parse->rlist, targets, sources ) )
  208. X        ss = ns->string;
  209. X
  210. X        status = strcmp( st, ss );
  211. X
  212. X        if( DEBUG_IF )
  213. X        printf( "if '%s' (%d) '%s'\n", st, status, ss );
  214. X
  215. X        list_free( nt );
  216. X        list_free( ns );
  217. X
  218. X        switch( parse->num )
  219. X        {
  220. X        case COND_EXISTS:    status = status > 0 ; break;
  221. X        case COND_EQUALS:    status = !status; break;
  222. X        case COND_NOTEQ:    status = status != 0; break;
  223. X        case COND_LESS:    status = status < 0; break;
  224. X        case COND_LESSEQ:    status = status <= 0; break;
  225. X        case COND_MORE:    status = status > 0; break;
  226. X        case COND_MOREEQ:    status = status >= 0; break;
  227. X        }
  228. X    }
  229. X
  230. X    return status;
  231. X}
  232. X
  233. X/*
  234. X * compile_include() - support for 'include' - call include() on file
  235. X *
  236. X *     parse->llist    list of files to include (can only do 1)
  237. X */
  238. X
  239. Xvoid
  240. Xcompile_include( parse, targets, sources )
  241. XPARSE        *parse;
  242. XLIST        *targets;
  243. XLIST        *sources;
  244. X{
  245. X    LIST    *nt = var_list( parse->llist, targets, sources );
  246. X
  247. X    if( DEBUG_COMPILE )
  248. X    {
  249. X        printf( "include " );
  250. X        list_print( nt );
  251. X        printf( "\n" );
  252. X    }
  253. X
  254. X    if( nt )
  255. X        yyfparse( nt->string );
  256. X
  257. X    list_free( nt );
  258. X}
  259. X
  260. X/*
  261. X * compile_rule() - compile a single user defined rule
  262. X *
  263. X *    parse->string    name of user defined rule
  264. X *    parse->llist    target of rule
  265. X *    parse->rlist    sources of rule
  266. X */
  267. X
  268. Xvoid
  269. Xcompile_rule( parse, targets, sources )
  270. XPARSE        *parse;
  271. XLIST        *targets;
  272. XLIST        *sources;
  273. X{
  274. X    LIST     *nt = var_list( parse->llist, targets, sources );
  275. X    LIST     *ns = var_list( parse->rlist, targets, sources );
  276. X    RULE    *rule = bindrule( parse->string );
  277. X
  278. X    if( DEBUG_COMPILE )
  279. X    {
  280. X        printf( ">>> %s ", parse->string );
  281. X        list_print( nt );
  282. X        printf( " : " );
  283. X        list_print( ns );
  284. X        printf( "\n" );
  285. X    }
  286. X
  287. X    if( !rule->actions && !rule->procedure )
  288. X        printf( "warning: unknown rule %s\n", rule->name );
  289. X
  290. X    /* If this rule will be executed for updating the targets */
  291. X    /* then construct the action for make(). */
  292. X
  293. X    if( rule->actions )
  294. X    {
  295. X        ACTION    *action;
  296. X
  297. X        /* The action is associated with this instance of this rule */
  298. X
  299. X        action = (ACTION *)malloc( sizeof( ACTION ) );
  300. X        memset( (char *)action, '\0', sizeof( *action ) );
  301. X
  302. X        action->rule = rule;
  303. X        action->targets = targetlist( (TARGETS *)0, nt );
  304. X        action->sources = targetlist( (TARGETS *)0, ns );
  305. X
  306. X        /* Append this action to the actions of each target */
  307. X
  308. X        actionlist( action->targets, action );
  309. X    }
  310. X
  311. X    /* Now recursively compile any parse tree associated with this rule */
  312. X
  313. X    if( rule->procedure )
  314. X        (*rule->procedure->func)( rule->procedure, nt, ns );
  315. X
  316. X    list_free( nt );
  317. X    list_free( ns );
  318. X
  319. X    if( DEBUG_COMPILE )
  320. X        printf( "<<< done\n" );
  321. X}
  322. X
  323. X/*
  324. X * compile_rules() - compile a chain of rules
  325. X *
  326. X *    parse->left    more compile_rules() by left-recursion
  327. X *    parse->right    single rule
  328. X */
  329. X
  330. Xvoid
  331. Xcompile_rules( parse, targets, sources )
  332. XPARSE        *parse;
  333. XLIST        *targets;
  334. XLIST        *sources;
  335. X{
  336. X    if( parse->left )
  337. X        (*parse->left->func)( parse->left, targets, sources );
  338. X
  339. X    if( parse->right )
  340. X        (*parse->right->func)( parse->right, targets, sources );
  341. X}
  342. X
  343. X/*
  344. X * compile_set() - compile the "set variable" statement
  345. X *
  346. X *    parse->llist    variable names
  347. X *    parse->rlist    variable values
  348. X */
  349. X
  350. Xvoid
  351. Xcompile_set( parse, targets, sources )
  352. XPARSE        *parse;
  353. XLIST        *targets;
  354. XLIST        *sources;
  355. X{
  356. X    LIST    *nt = var_list( parse->llist, targets, sources );
  357. X    LIST    *ns = var_list( parse->rlist, targets, sources );
  358. X    LIST    *l;
  359. X    int    count = 0;
  360. X
  361. X    if( DEBUG_COMPILE )
  362. X    {
  363. X        printf( ">>> set " );
  364. X        list_print( nt );
  365. X        printf( " = " );
  366. X        list_print( ns );
  367. X        printf( "\n" );
  368. X    }
  369. X
  370. X    /* Call var_set to set variable */
  371. X    /* var_set keeps ns, so need to copy it */
  372. X
  373. X    for( l = nt; l; l = list_next( l ) )
  374. X        var_set( l->string, count++ ? list_copy( (LIST*)0, ns ) : ns );
  375. X
  376. X    if( !count )
  377. X        list_free( ns );
  378. X
  379. X    list_free( nt );
  380. X}
  381. X
  382. X/*
  383. X * compile_setcomp() - support for `rule` - save parse tree 
  384. X *
  385. X *    parse->string    rule name
  386. X *    parse->left    rules for rule
  387. X */
  388. X
  389. Xvoid
  390. Xcompile_setcomp( parse, targets, sources )
  391. XPARSE        *parse;
  392. XLIST        *targets;
  393. XLIST        *sources;
  394. X{
  395. X    RULE    *rule = bindrule( parse->string );
  396. X
  397. X    /* Free old one, if present */
  398. X
  399. X    if( rule->procedure )
  400. X        parse_free( rule->procedure );
  401. X
  402. X    rule->procedure = parse->left;
  403. X
  404. X    /* we now own this parse tree */
  405. X    /* don't let parse_free() release it */
  406. X
  407. X    parse->left = 0;    
  408. X}
  409. X
  410. X/*
  411. X * compile_setdefault() - compile the "variable default =" statement
  412. X *
  413. X *    parse->llist    variable names
  414. X *    parse->rlist    variable values
  415. X */
  416. X
  417. Xvoid
  418. Xcompile_setdefault( parse, targets, sources )
  419. XPARSE        *parse;
  420. XLIST        *targets;
  421. XLIST        *sources;
  422. X{
  423. X    LIST    *nt = var_list( parse->llist, targets, sources );
  424. X    LIST    *ns = var_list( parse->rlist, targets, sources );
  425. X    LIST    *l;
  426. X    int    count = 0;
  427. X
  428. X    if( DEBUG_COMPILE )
  429. X    {
  430. X        printf( ">>> set " );
  431. X        list_print( nt );
  432. X        printf( " default = " );
  433. X        list_print( ns );
  434. X        printf( "\n" );
  435. X    }
  436. X
  437. X    /* Skip if variable already set */
  438. X    /* Call var_set to set variable */
  439. X    /* var_set keeps ns, so need to copy it */
  440. X
  441. X    for( l = nt; l; l = list_next( l ) )
  442. X        if( !var_get( l->string ) )
  443. X    {
  444. X        var_set( l->string, count++ ? list_copy( (LIST*)0, ns ) : ns );
  445. X    }
  446. X
  447. X    if( !count )
  448. X        list_free( ns );
  449. X
  450. X    list_free( nt );
  451. X}
  452. X
  453. X/*
  454. X * compile_setexec() - support for `actions` - save execution string 
  455. X *
  456. X *    parse->string    rule name
  457. X *    parse->string1    OS command string
  458. X *    parse->num    flags
  459. X *
  460. X * Note that the parse flags (as defined in compile.h) are transfered
  461. X * directly to the rule flags (as defined in rules.h).
  462. X */
  463. X
  464. Xvoid
  465. Xcompile_setexec( parse, targets, sources )
  466. XPARSE        *parse;
  467. XLIST        *targets;
  468. XLIST        *sources;
  469. X{
  470. X    RULE    *rule = bindrule( parse->string );
  471. X    
  472. X    /* Free old one, if present */
  473. X
  474. X    if( rule->actions )
  475. X        freestr( rule->actions );
  476. X
  477. X    rule->actions = copystr( parse->string1 );
  478. X    rule->flags |= parse->num; /* XXX */
  479. X}
  480. X
  481. X/*
  482. X * compile_settings() - compile the "on :=" (set variable on exec) statement
  483. X *
  484. X *    parse->llist        target names
  485. X *    parse->left->llist    variable names
  486. X *    parse->left->rlist    variable values
  487. X */
  488. X
  489. Xvoid
  490. Xcompile_settings( parse, targets, sources )
  491. XPARSE        *parse;
  492. XLIST        *targets;
  493. XLIST        *sources;
  494. X{
  495. X    LIST    *nt = var_list( parse->left->llist, targets, sources );
  496. X    LIST    *ns = var_list( parse->left->rlist, targets, sources );
  497. X    LIST    *ts;
  498. X    int    count = 0;
  499. X
  500. X    /* Reset targets */
  501. X
  502. X    targets = var_list( parse->llist, targets, sources );
  503. X
  504. X    if( DEBUG_COMPILE )
  505. X    {
  506. X        printf( ">>> settings " );
  507. X        list_print( nt );
  508. X        printf( "on " );
  509. X        list_print( targets );
  510. X        printf( " = " );
  511. X        list_print( ns );
  512. X        printf( "\n" );
  513. X    }
  514. X
  515. X    /* Call addsettings to save variable setting */
  516. X    /* addsettings keeps ns, so need to copy it */
  517. X
  518. X    for( ts = targets; ts; ts = list_next( ts ) )
  519. X    {
  520. X        TARGET     *t = bindtarget( ts->string );
  521. X        LIST    *l;
  522. X
  523. X        for( l = nt; l; l = list_next( l ), count++ )
  524. X        t->settings = addsettings( t->settings, l->string, 
  525. X                count ? list_copy( (LIST*)0, ns ) : ns );
  526. X    }
  527. X
  528. X    if( !count )
  529. X        list_free( ns );
  530. X
  531. X    list_free( nt );
  532. X    list_free( targets );
  533. X}
  534. X
  535. X/*
  536. X * compile_switch() - compile 'switch' rule
  537. X *
  538. X *    parse->llist    switch value (only 1st used)
  539. X *    parse->left    cases
  540. X *
  541. X *    cases->left    1st case
  542. X *    cases->right    next cases
  543. X *
  544. X *    case->string    argument to match
  545. X *    case->left    parse tree to execute
  546. X */
  547. X
  548. Xvoid
  549. Xcompile_switch( parse, targets, sources )
  550. XPARSE        *parse;
  551. XLIST        *targets;
  552. XLIST        *sources;
  553. X{
  554. X    LIST    *nt;
  555. X
  556. X    nt = var_list( parse->llist, targets, sources );
  557. X
  558. X    if( DEBUG_COMPILE )
  559. X    {
  560. X        printf( ">>> switch " );
  561. X        list_print( nt );
  562. X        printf( "\n" );
  563. X    }
  564. X
  565. X    /* Step through cases */
  566. X
  567. X    for( parse = parse->left; parse; parse = parse->right )
  568. X    {
  569. X        if( nt && 
  570. X        !strcmp( parse->left->string, nt->string ) ||
  571. X        !strcmp( parse->left->string, "*" ) )
  572. X        {
  573. X        /* Get & exec parse tree for this case */
  574. X        parse = parse->left->left;
  575. X        (*parse->func)( parse, targets, sources );
  576. X        break;
  577. X        }
  578. X    }
  579. X
  580. X    list_free( nt );
  581. X}
  582. X
  583. X
  584. X
  585. X/*
  586. X * builtin_depends() - DEPENDS rule
  587. X *
  588. X * The DEPENDS builtin rule appends each of the listed sources on the 
  589. X * dependency list of each of the listed targets.  It binds both the 
  590. X * targets and sources as TARGETs.
  591. X */
  592. X
  593. Xstatic void
  594. Xbuiltin_depends( parse, targets, sources )
  595. XPARSE        *parse;
  596. XLIST        *targets;
  597. XLIST        *sources;
  598. X{
  599. X    LIST *l;
  600. X
  601. X    for( l = targets; l; l = list_next( l ) )
  602. X    {
  603. X        TARGET *t = bindtarget( l->string );
  604. X        t->deps = targetlist( t->deps, sources );
  605. X    }
  606. X}
  607. X
  608. X/*
  609. X * builtin_echo() - ECHO rule
  610. X *
  611. X * The ECHO builtin rule echoes the targets to the user.  No other 
  612. X * actions are taken.
  613. X */
  614. X
  615. Xstatic void
  616. Xbuiltin_echo( parse, targets, sources )
  617. XPARSE        *parse;
  618. XLIST        *targets;
  619. XLIST        *sources;
  620. X{
  621. X    list_print( targets );
  622. X    printf( "\n" );
  623. X}
  624. X
  625. X/*
  626. X * builtin_includes() - INCLUDES rule
  627. X *
  628. X * The INCLUDES builtin rule appends each of the listed sources on the 
  629. X * headers list of each of the listed targets.  It binds both the 
  630. X * targets and sources as TARGETs.
  631. X */
  632. X
  633. Xstatic void
  634. Xbuiltin_includes( parse, targets, sources )
  635. XPARSE        *parse;
  636. XLIST        *targets;
  637. XLIST        *sources;
  638. X{
  639. X    LIST *l;
  640. X
  641. X    for( l = targets; l; l = list_next( l ) )
  642. X    {
  643. X        TARGET *t = bindtarget( l->string );
  644. X        t->headers = targetlist( t->headers, sources );
  645. X    }
  646. X}
  647. X
  648. X/*
  649. X * builtin_flags() - NOCARE, NOTIME, TEMPORARY rule
  650. X *
  651. X * Builtin_flags() marks the target with the appropriate flag, for use
  652. X * by make0().  It binds each target as a TARGET.
  653. X */
  654. X
  655. Xstatic void
  656. Xbuiltin_flags( parse, targets, sources )
  657. XPARSE        *parse;
  658. XLIST        *targets;
  659. XLIST        *sources;
  660. X{
  661. X    LIST *l;
  662. X
  663. X    for( l = targets; l; l = list_next( l ) )
  664. X        bindtarget( l->string )->flags |= parse->num;
  665. X}
  666. SHAR_EOF
  667. chmod 0444 compile.c ||
  668. echo 'restore of compile.c failed'
  669. Wc_c="`wc -c < 'compile.c'`"
  670. test 13686 -eq "$Wc_c" ||
  671.     echo 'compile.c: original size 13686, current size' "$Wc_c"
  672. fi
  673. # ============= compile.h ==============
  674. if test -f 'compile.h' -a X"$1" != X"-c"; then
  675.     echo 'x - skipping compile.h (File already exists)'
  676. else
  677. echo 'x - extracting compile.h (Text)'
  678. sed 's/^X//' << 'SHAR_EOF' > 'compile.h' &&
  679. X/*
  680. X * Copyright 1993 Christopher Seiwald.
  681. X */
  682. X
  683. X/*
  684. X * compile.h - compile parsed jam statements
  685. X */
  686. X
  687. Xvoid compile_builtins();
  688. Xvoid compile_foreach();
  689. Xvoid compile_if();
  690. Xvoid compile_include();
  691. Xvoid compile_rule();
  692. Xvoid compile_rules();
  693. Xvoid compile_set();
  694. Xvoid compile_setcomp();
  695. Xvoid compile_setdefault();
  696. Xvoid compile_setexec();
  697. Xvoid compile_settings();
  698. Xvoid compile_switch();
  699. X
  700. X/* Flags for compile_setexec() */
  701. X
  702. X# define EXEC_UPDATED    0x01    /* executes updated */
  703. X# define EXEC_TOGETHER    0x02    /* executes together */
  704. X# define EXEC_IGNORE    0x04    /* executes ignore */
  705. X# define EXEC_QUIETLY    0x08    /* executes quietly */
  706. X# define EXEC_PIECEMEAL    0x10    /* executes piecemeal */
  707. X
  708. X/* Conditions for compile_if() */
  709. X
  710. X# define COND_NOT    0    /* ! cond */
  711. X# define COND_AND    1    /* cond && cond */
  712. X# define COND_OR    2    /* cond || cond */
  713. X
  714. X# define COND_EXISTS    3    /* arg */
  715. X# define COND_EQUALS    4    /* arg = arg */
  716. X# define COND_NOTEQ    5    /* arg != arg */
  717. X# define COND_LESS    6    /* arg < arg  */
  718. X# define COND_LESSEQ    7    /* arg <= arg */
  719. X# define COND_MORE    8    /* arg > arg  */
  720. X# define COND_MOREEQ    9    /* arg >= arg */
  721. SHAR_EOF
  722. chmod 0444 compile.h ||
  723. echo 'restore of compile.h failed'
  724. Wc_c="`wc -c < 'compile.h'`"
  725. test 1082 -eq "$Wc_c" ||
  726.     echo 'compile.h: original size 1082, current size' "$Wc_c"
  727. fi
  728. # ============= execcmd.h ==============
  729. if test -f 'execcmd.h' -a X"$1" != X"-c"; then
  730.     echo 'x - skipping execcmd.h (File already exists)'
  731. else
  732. echo 'x - extracting execcmd.h (Text)'
  733. sed 's/^X//' << 'SHAR_EOF' > 'execcmd.h' &&
  734. X/*
  735. X * Copyright 1993 Christopher Seiwald.
  736. X */
  737. X
  738. X/*
  739. X * execcmd.h - execute a shell script
  740. X */
  741. X
  742. Xint execcmd();
  743. X
  744. X# define EXEC_CMD_OK    0
  745. X# define EXEC_CMD_FAIL    1
  746. X# define EXEC_CMD_INTR    2
  747. SHAR_EOF
  748. chmod 0444 execcmd.h ||
  749. echo 'restore of execcmd.h failed'
  750. Wc_c="`wc -c < 'execcmd.h'`"
  751. test 182 -eq "$Wc_c" ||
  752.     echo 'execcmd.h: original size 182, current size' "$Wc_c"
  753. fi
  754. # ============= execunix.c ==============
  755. if test -f 'execunix.c' -a X"$1" != X"-c"; then
  756.     echo 'x - skipping execunix.c (File already exists)'
  757. else
  758. echo 'x - extracting execunix.c (Text)'
  759. sed 's/^X//' << 'SHAR_EOF' > 'execunix.c' &&
  760. X/*
  761. X * Copyright 1993 Christopher Seiwald.
  762. X */
  763. X
  764. X# ifndef VMS
  765. X
  766. X# include "jam.h"
  767. X# include "execcmd.h"
  768. X
  769. X# if defined(__sgi)
  770. X# define vfork() fork()
  771. X# endif
  772. X
  773. X/*
  774. X * execunix.c - execute a shell script on UNIX
  775. X *
  776. X * Sets "interrupted" if the command was interrupted.
  777. X */
  778. X
  779. Xstatic int intr = 0;
  780. X
  781. Xvoid
  782. Xonintr()
  783. X{
  784. X    intr++;
  785. X}
  786. X    
  787. Xint
  788. Xexeccmd( string )
  789. Xchar *string;
  790. X{
  791. X    int status, pid, w, rstat;
  792. X    void (*istat)();
  793. X
  794. X    intr = 0;
  795. X
  796. X    if ((pid = vfork()) == 0) {
  797. X        execl("/bin/sh", "sh", "-c", string, 0);
  798. X        _exit(127);
  799. X    }
  800. X
  801. X    istat = signal( SIGINT, onintr );
  802. X    while ((w = wait(&status)) != pid && w != -1)
  803. X        ;
  804. X    signal( SIGINT, istat );
  805. X
  806. X    if( intr )
  807. X        return EXEC_CMD_INTR;
  808. X    else if( w == -1 || status != 0 )
  809. X        return EXEC_CMD_FAIL;
  810. X    else
  811. X        return EXEC_CMD_OK;
  812. X}
  813. X
  814. X# endif /* UNIX */
  815. SHAR_EOF
  816. chmod 0444 execunix.c ||
  817. echo 'restore of execunix.c failed'
  818. Wc_c="`wc -c < 'execunix.c'`"
  819. test 772 -eq "$Wc_c" ||
  820.     echo 'execunix.c: original size 772, current size' "$Wc_c"
  821. fi
  822. # ============= execvms.c ==============
  823. if test -f 'execvms.c' -a X"$1" != X"-c"; then
  824.     echo 'x - skipping execvms.c (File already exists)'
  825. else
  826. echo 'x - extracting execvms.c (Text)'
  827. sed 's/^X//' << 'SHAR_EOF' > 'execvms.c' &&
  828. X/* 
  829. X * Copyright 1993 Christopher Seiwald.
  830. X */
  831. X
  832. X# ifdef VMS
  833. X
  834. X# include "jam.h"
  835. X# include "execcmd.h"
  836. X
  837. X#include <stdio.h>
  838. X#include <string.h>
  839. X#include <stdlib.h>
  840. X#include <iodef.h>
  841. X#include <ssdef.h>
  842. X#include <descrip.h>
  843. X#include <dvidef.h>
  844. X#include <clidef.h>
  845. X
  846. X/*
  847. X * execvms.c - execute a shell script, ala VMS
  848. X */
  849. X
  850. X#define WRTLEN 240
  851. X
  852. X#define MIN( a, b )    ((a) < (b) ? (a) : (b))
  853. X
  854. X    /* macros to allocate and initialize VMS descriptors
  855. X     */
  856. X#define DESCALLOC( name ) struct dsc$descriptor_s \
  857. X    (name) = { 0, DSC$K_DTYPE_T, DSC$K_CLASS_D, NULL }
  858. X
  859. X
  860. Xint
  861. Xexeccmd( string )
  862. Xchar *string;
  863. X{
  864. X    /* Split string at newlines, and don't execute empty lines */
  865. X    /* Bail if any lines fail. */
  866. X
  867. X    while( *string )
  868. X    {
  869. X    char *s;
  870. X    char *os = string;
  871. X    int something = 0;
  872. X
  873. X    for( s = string; *s && *s != '\n'; s++ )
  874. X        if( !isspace( *s ) )
  875. X        something++;
  876. X
  877. X    string = *s ? s + 1 : s ;
  878. X
  879. X    if( something )
  880. X    {
  881. X        int status;
  882. X        int len;
  883. X
  884. X        *s = '\0';
  885. X
  886. X        if( ( len = strlen( os ) ) < WRTLEN )
  887. X        {
  888. X        status = system( os ) & 0x07;
  889. X        }
  890. X        else
  891. X        {
  892. X        FILE *f = fopen( "sys$scratch:jam.com", "w" );
  893. X
  894. X        if( !f )
  895. X        {
  896. X            printf( "can't open command file\n" );
  897. X            return EXEC_CMD_FAIL;
  898. X        }
  899. X
  900. X            fputc( '$', f );
  901. X
  902. X        while( len > 0 )
  903. X        {
  904. X            int l = MIN( len, WRTLEN );
  905. X
  906. X            fwrite( os, l, 1, f );
  907. X
  908. X            if( l < len )
  909. X            fputc( '-', f );
  910. X
  911. X            fputc( '\n', f );
  912. X
  913. X            len -= l;
  914. X            os += l;
  915. X        }
  916. X
  917. X        fclose( f );
  918. X
  919. X        status = system( "@sys$scratch:jam.com" ) & 0x07;
  920. X
  921. X        unlink( "sys$scratch:jam.com" );
  922. X
  923. X        }        
  924. X
  925. X        /* Fail for error or fatal error */
  926. X        /* OK on OK, warning, or info exit */
  927. X
  928. X        if( status == 2 || status == 4 )
  929. X        return EXEC_CMD_FAIL;
  930. X    }
  931. X    }
  932. X
  933. X    return EXEC_CMD_OK;
  934. X}
  935. X
  936. X# endif /* VMS */
  937. SHAR_EOF
  938. chmod 0444 execvms.c ||
  939. echo 'restore of execvms.c failed'
  940. Wc_c="`wc -c < 'execvms.c'`"
  941. test 1733 -eq "$Wc_c" ||
  942.     echo 'execvms.c: original size 1733, current size' "$Wc_c"
  943. fi
  944. # ============= expand.c ==============
  945. if test -f 'expand.c' -a X"$1" != X"-c"; then
  946.     echo 'x - skipping expand.c (File already exists)'
  947. else
  948. echo 'x - extracting expand.c (Text)'
  949. sed 's/^X//' << 'SHAR_EOF' > 'expand.c' &&
  950. X/*
  951. X * Copyright 1993 Christopher Seiwald.
  952. X */
  953. X
  954. X# include "jam.h"
  955. X# include "lists.h"
  956. X# include "variable.h"
  957. X# include "expand.h"
  958. X# include "filesys.h"
  959. X# include "newstr.h"
  960. X
  961. X/*
  962. X * expand.c - expand a buffer, given variable values
  963. X *
  964. X * External routines:
  965. X *
  966. X *     var_expand() - variable-expand input string into list of strings
  967. X *
  968. X * Internal routines:
  969. X *
  970. X *     var_edit() - copy input target name to output, performing : modifiers
  971. X *     var_mods() - parse : modifiers into FILENAME structure
  972. X */
  973. X
  974. Xstatic void    var_edit();
  975. Xstatic void    var_mods();
  976. X
  977. X# define MAGIC_COLON    '\001'
  978. X
  979. X/*
  980. X * var_expand() - variable-expand input string into list of strings
  981. X *
  982. X * Would just copy input to output, performing variable expansion, 
  983. X * except that since variables can contain multiple values the result
  984. X * of variable expansion may contain multiple values (a list).  Properly
  985. X * performs "product" operations that occur in "$(var1)xxx$(var2)" or
  986. X * even "$($(var2))".
  987. X *
  988. X * Returns a newly created list.
  989. X */
  990. X
  991. XLIST *
  992. Xvar_expand( l, in, end, targets, sources )
  993. XLIST    *l;
  994. Xchar    *in;
  995. Xchar    *end;
  996. XLIST    *targets;
  997. XLIST    *sources;
  998. X{
  999. X    char out_buf[ MAXSYM ];
  1000. X    char *out = out_buf;
  1001. X    char *ov;        /* for temp copy of variable in outbuf */
  1002. X    int depth;
  1003. X
  1004. X    if( DEBUG_VAREXP )
  1005. X        printf( "expand '%.*s'\n", end - in, in );
  1006. X
  1007. X    /* Just try simple copy of in to out. */
  1008. X
  1009. X    while( in < end )
  1010. X        if( ( *out++ = *in++ ) == '$' && *in == '(' ) 
  1011. X        goto expand;
  1012. X
  1013. X    /* No variables expanded - just add copy of input string to list. */
  1014. X
  1015. X    *out = '\0';
  1016. X
  1017. X    return list_new( l, newstr( out_buf ) );
  1018. X
  1019. X    expand:
  1020. X    /*
  1021. X     * Input so far (ignore blanks):
  1022. X     *
  1023. X     *    stuff-in-outbuf $(variable) remainder
  1024. X     *             ^                 ^
  1025. X     *             in             end
  1026. X     * Output so far:
  1027. X     *
  1028. X     *    stuff-in-outbuf $
  1029. X     *    ^             ^
  1030. X     *    out_buf          out
  1031. X     *
  1032. X     *
  1033. X     * We just copied the $ of $(...), so back up one on the output.
  1034. X     * We now find the matching close paren, copying the variable and
  1035. X     * modifiers between the $( and ) temporarily into out_buf, so that
  1036. X     * we can replace :'s with MAGIC_COLON.  This is necessary to avoid
  1037. X     * being confused by modifier values that are variables containing
  1038. X     * :'s.  Ugly.
  1039. X     */
  1040. X
  1041. X    depth = 1;
  1042. X    out--, in++;
  1043. X    ov = out;
  1044. X
  1045. X    while( in < end && depth )
  1046. X    {
  1047. X        switch( *ov++ = *in++ )
  1048. X        {
  1049. X        case '(': depth++; break;
  1050. X        case ')': depth--; break;
  1051. X        case ':': ov[-1] = MAGIC_COLON;
  1052. X        }
  1053. X    }
  1054. X
  1055. X    /* Copied ) - back up. */
  1056. X
  1057. X    ov--;
  1058. X
  1059. X    /*
  1060. X     * Input so far (ignore blanks):
  1061. X     *
  1062. X     *    stuff-in-outbuf $(variable) remainder
  1063. X     *                        ^        ^
  1064. X     *                        in       end
  1065. X     * Output so far:
  1066. X     *
  1067. X     *    stuff-in-outbuf variable
  1068. X     *    ^            ^       ^
  1069. X     *    out_buf         out    ov
  1070. X     *
  1071. X     * Later we will overwrite 'variable' in out_buf, but we'll be
  1072. X     * done with it by then.  'variable' may be a multi-element list, 
  1073. X     * so may each value for '$(variable element)', and so may 'remainder'.
  1074. X     * Thus we produce a product of three lists.
  1075. X     */
  1076. X
  1077. X    {
  1078. X        LIST *variables = 0;
  1079. X        LIST *remainder = 0;
  1080. X        LIST *vars;
  1081. X
  1082. X        /* Recursively expand variable name & rest of input */
  1083. X
  1084. X        if( out < ov )
  1085. X        variables = var_expand( (LIST *)0, out, ov, targets, sources );
  1086. X        if( in < end )
  1087. X        remainder = var_expand( (LIST *)0, in, end, targets, sources );
  1088. X
  1089. X        /* Now produce the result chain */
  1090. X
  1091. X        /* For each variable name */
  1092. X
  1093. X        for( vars = variables; vars; vars = list_next( vars ) )
  1094. X        {
  1095. X        LIST *value;
  1096. X        char *colon;
  1097. X        char *bracket;
  1098. X        char varname[ MAXSYM ];
  1099. X        int i, sub1, sub2;
  1100. X
  1101. X        /* Look for a : modifier in the variable name */
  1102. X        /* Must copy into varname so we can modify it */
  1103. X
  1104. X        strcpy( varname, vars->string );
  1105. X
  1106. X        if( colon = strchr( varname, MAGIC_COLON ) )
  1107. X            *colon = '\0';
  1108. X
  1109. X        if( bracket = strchr( varname, '[' ) )
  1110. X        {
  1111. X            char *dash;
  1112. X
  1113. X            if( dash = strchr( bracket + 1, '-' ) )
  1114. X            {
  1115. X            *dash = '\0';
  1116. X            sub1 = atoi( bracket + 1 );
  1117. X            sub2 = atoi( dash + 1 );
  1118. X            }
  1119. X            else
  1120. X            {
  1121. X            sub1 = sub2 = atoi( bracket + 1 );
  1122. X            }
  1123. X
  1124. X            *bracket = '\0';
  1125. X        }
  1126. X
  1127. X        /* Get variable value, specially handling $(<) and $(>) */
  1128. X        
  1129. X        if( !strcmp( varname, "<" ) )
  1130. X            value = targets;
  1131. X        else if( !strcmp( varname, ">" ) )
  1132. X            value = sources;
  1133. X        else 
  1134. X            value = var_get( varname );
  1135. X
  1136. X        /* The fast path: $(x) - just copy the variable value. */
  1137. X
  1138. X        if( out == out_buf && !bracket && !colon && !remainder )
  1139. X        {
  1140. X            l = list_copy( l, value );
  1141. X            continue;
  1142. X        }
  1143. X
  1144. X        /* For each variable value */
  1145. X
  1146. X        for( i = 1; value; i++, value = list_next( value ) )
  1147. X        {
  1148. X            LIST *rem;
  1149. X            char *out1;
  1150. X
  1151. X            /* Skip members not in subscript */
  1152. X
  1153. X            if( bracket && ( i < sub1 || sub2 && i > sub2 ) )
  1154. X            continue;
  1155. X
  1156. X            /* Apply : mods, if present */
  1157. X
  1158. X            if( colon )
  1159. X            var_edit( value->string, colon + 1, out );
  1160. X            else
  1161. X            strcpy( out, value->string );
  1162. X
  1163. X            /* If no remainder, append result to output chain. */
  1164. X
  1165. X            if( in == end )
  1166. X            {
  1167. X            l = list_new( l, newstr( out_buf ) );
  1168. X            continue;
  1169. X            }
  1170. X
  1171. X            /* Remember the end of the variable expansion so */
  1172. X            /* we can just tack on each instance of 'remainder' */
  1173. X
  1174. X            out1 = out + strlen( out );
  1175. X
  1176. X            /* For each remainder, or just once if no remainder, */
  1177. X            /* append the complete string to the output chain */
  1178. X
  1179. X            for( rem = remainder; rem; rem = list_next( rem ) )
  1180. X            {
  1181. X            strcpy( out1, rem->string );
  1182. X            l = list_new( l, newstr( out_buf ) );
  1183. X            }
  1184. X        }
  1185. X        }
  1186. X
  1187. X        /* variables & remainder were gifts from var_expand */
  1188. X        /* and must be freed */
  1189. X
  1190. X        if( variables )
  1191. X        list_free( variables );
  1192. X        if( remainder)
  1193. X        list_free( remainder );
  1194. X
  1195. X        if( DEBUG_VAREXP )
  1196. X        {
  1197. X        printf( "expanded to " );
  1198. X        list_print( l );
  1199. X        printf( "\n" );
  1200. X        }
  1201. X
  1202. X        return l;
  1203. X    }
  1204. X}
  1205. X
  1206. X/*
  1207. X * var_edit() - copy input target name to output, performing : modifiers
  1208. X */
  1209. X
  1210. Xstatic void
  1211. Xvar_edit( in, mods, out )
  1212. Xchar    *in;
  1213. Xchar    *mods;
  1214. Xchar    *out;
  1215. X{
  1216. X    FILENAME old, new;
  1217. X
  1218. X    /* Parse apart original filename, putting parts into "old" */
  1219. X
  1220. X    file_parse( in, &old );
  1221. X
  1222. X    /* Parse apart modifiers, putting them into "new" */
  1223. X
  1224. X    var_mods( mods, &new );
  1225. X
  1226. X    /* Replace any old with new */
  1227. X
  1228. X    if( new.f_grist.ptr )
  1229. X        old.f_grist = new.f_grist;
  1230. X
  1231. X    if( new.f_root.ptr )
  1232. X        old.f_root = new.f_root;
  1233. X
  1234. X    if( new.f_dir.ptr )
  1235. X        old.f_dir = new.f_dir;
  1236. X
  1237. X    if( new.f_base.ptr )
  1238. X        old.f_base = new.f_base;
  1239. X
  1240. X    if( new.f_suffix.ptr )
  1241. X        old.f_suffix = new.f_suffix;
  1242. X
  1243. X    if( new.f_member.ptr )
  1244. X        old.f_member = new.f_member;
  1245. X
  1246. X    /* Put filename back together */
  1247. X
  1248. X    file_build( &old, out );
  1249. X}
  1250. X
  1251. X
  1252. X/*
  1253. X * var_mods() - parse : modifiers into FILENAME structure
  1254. X *
  1255. X * The : modifiers in a $(varname:modifier) currently support replacing
  1256. X * or omitting elements of a filename, and so they are parsed into a 
  1257. X * FILENAME structure (which contains pointers into the original string).
  1258. X *
  1259. X * Modifiers of the form "X=value" replace the component X with
  1260. X * the given value.  Modifiers without the "=value" cause everything 
  1261. X * but the component X to be omitted.  X is one of:
  1262. X *
  1263. X *    G <grist>
  1264. X *    D directory name
  1265. X *    B base name
  1266. X *    S .suffix
  1267. X *    M (member)
  1268. X *    R root directory - prepended to whole path
  1269. X *
  1270. X * This routine sets:
  1271. X *
  1272. X *    f->f_xxx.ptr = 0
  1273. X *    f->f_xxx.len = 0
  1274. X *        -> leave the original component xxx
  1275. X *
  1276. X *    f->f_xxx.ptr = string
  1277. X *    f->f_xxx.len = strlen( string )
  1278. X *        -> replace component xxx with string
  1279. X *
  1280. X *    f->f_xxx.ptr = ""
  1281. X *    f->f_xxx.len = 0
  1282. X *        -> omit component xxx
  1283. X *
  1284. X * var_edit() above and file_build() obligingly follow this convention.
  1285. X */
  1286. X
  1287. Xstatic void
  1288. Xvar_mods( mods, f )
  1289. Xchar        *mods;
  1290. XFILENAME    *f;
  1291. X{
  1292. X    char *flags = "GRDBSM";
  1293. X    int havezeroed = 0;
  1294. X    memset( (char *)f, 0, sizeof( *f ) );
  1295. X
  1296. X    while( *mods )
  1297. X    {
  1298. X        char *fl;
  1299. X        struct filepart *fp;
  1300. X
  1301. X        if( !( fl = strchr( flags, *mods++ ) ) )
  1302. X        break;    /* should complain, but so what... */
  1303. X
  1304. X        fp = &f->part[ fl - flags ];
  1305. X
  1306. X        if( *mods++ != '=' )
  1307. X        {
  1308. X        /* :X - turn everything but X off */
  1309. X
  1310. X        int i;
  1311. X
  1312. X        mods--;
  1313. X
  1314. X        if( !havezeroed++ )
  1315. X            for( i = 0; i < 6; i++ )
  1316. X        {
  1317. X            f->part[ i ].len = 0;
  1318. X            f->part[ i ].ptr = "";
  1319. X        }
  1320. X
  1321. X        fp->ptr = 0;
  1322. X        }
  1323. X        else
  1324. X        {
  1325. X        /* :X=value - set X to value */
  1326. X
  1327. X        char *p;
  1328. X
  1329. X        if( p = strchr( mods, MAGIC_COLON ) )
  1330. X        {
  1331. X            fp->ptr = mods;
  1332. X            fp->len = p - mods;
  1333. X            mods = p + 1;
  1334. X        }
  1335. X        else
  1336. X        {
  1337. X            fp->ptr = mods;
  1338. X            fp->len = strlen( mods );
  1339. X            mods += fp->len;
  1340. X        }
  1341. X        }
  1342. X    }
  1343. X}
  1344. SHAR_EOF
  1345. chmod 0444 expand.c ||
  1346. echo 'restore of expand.c failed'
  1347. Wc_c="`wc -c < 'expand.c'`"
  1348. test 8227 -eq "$Wc_c" ||
  1349.     echo 'expand.c: original size 8227, current size' "$Wc_c"
  1350. fi
  1351. # ============= expand.h ==============
  1352. if test -f 'expand.h' -a X"$1" != X"-c"; then
  1353.     echo 'x - skipping expand.h (File already exists)'
  1354. else
  1355. echo 'x - extracting expand.h (Text)'
  1356. sed 's/^X//' << 'SHAR_EOF' > 'expand.h' &&
  1357. X/*
  1358. X * Copyright 1993 Christopher Seiwald.
  1359. X */
  1360. X
  1361. X/*
  1362. X * expand.h - expand a buffer, given variable values
  1363. X */
  1364. X
  1365. XLIST *var_expand();
  1366. SHAR_EOF
  1367. chmod 0444 expand.h ||
  1368. echo 'restore of expand.h failed'
  1369. Wc_c="`wc -c < 'expand.h'`"
  1370. test 128 -eq "$Wc_c" ||
  1371.     echo 'expand.h: original size 128, current size' "$Wc_c"
  1372. fi
  1373. # ============= filesys.h ==============
  1374. if test -f 'filesys.h' -a X"$1" != X"-c"; then
  1375.     echo 'x - skipping filesys.h (File already exists)'
  1376. else
  1377. echo 'x - extracting filesys.h (Text)'
  1378. sed 's/^X//' << 'SHAR_EOF' > 'filesys.h' &&
  1379. X/*
  1380. X * Copyright 1993 Christopher Seiwald.
  1381. X */
  1382. X
  1383. X/*
  1384. X * filesys.h - FILENAME struct and OS specific file routines 
  1385. X */
  1386. X
  1387. X/*
  1388. X * FILENAME - a name of a file, broken into <grist>dir/base/suffix(member)
  1389. X *
  1390. X * <grist> is salt to distinguish between targets that otherwise would
  1391. X * have the same name:  it never appears in the bound name of a target.
  1392. X * (member) is an archive member name: the syntax is arbitrary, but must 
  1393. X * agree in file_parse(), file_build() and the Jambase.
  1394. X */
  1395. X
  1396. Xtypedef struct _filename FILENAME;
  1397. X
  1398. Xstruct _filename {
  1399. X    struct filepart {
  1400. X        char    *ptr;
  1401. X        int    len;
  1402. X    } part[6];
  1403. X# define f_grist    part[0]
  1404. X# define f_root        part[1]
  1405. X# define f_dir        part[2]
  1406. X# define f_base        part[3]
  1407. X# define f_suffix    part[4]
  1408. X# define f_member    part[5]
  1409. X} ;
  1410. X
  1411. Xvoid file_parse();
  1412. Xvoid file_build();
  1413. X
  1414. Xvoid file_archscan();
  1415. Xvoid file_dirscan();
  1416. X
  1417. Xint file_time();
  1418. SHAR_EOF
  1419. chmod 0444 filesys.h ||
  1420. echo 'restore of filesys.h failed'
  1421. Wc_c="`wc -c < 'filesys.h'`"
  1422. test 842 -eq "$Wc_c" ||
  1423.     echo 'filesys.h: original size 842, current size' "$Wc_c"
  1424. fi
  1425. # ============= fileunix.c ==============
  1426. if test -f 'fileunix.c' -a X"$1" != X"-c"; then
  1427.     echo 'x - skipping fileunix.c (File already exists)'
  1428. else
  1429. echo 'x - extracting fileunix.c (Text)'
  1430. sed 's/^X//' << 'SHAR_EOF' > 'fileunix.c' &&
  1431. X/*
  1432. X * Copyright 1993 Christopher Seiwald.
  1433. X */
  1434. X
  1435. X# ifndef VMS
  1436. X
  1437. X# include "jam.h"
  1438. X# include "filesys.h"
  1439. X
  1440. X# if defined(_SEQUENT_) || defined(__DGUX__)
  1441. X# define PORTAR 1
  1442. X# endif
  1443. X
  1444. X# include <dirent.h>
  1445. X# include <ar.h>
  1446. X
  1447. X/*
  1448. X * fileunix.c - manipulate file names and scan directories on UNIX
  1449. X *
  1450. X * External routines:
  1451. X *
  1452. X *    file_parse() - split a file name into dir/base/suffix/member
  1453. X *    file_build() - build a filename given dir/base/suffix/member
  1454. X *    file_dirscan() - scan a directory for files
  1455. X *    file_time() - get timestamp of file, if not done by file_dirscan()
  1456. X *    file_archscan() - scan an archive for files
  1457. X *
  1458. X * File_parse() and file_build() just manipuate a string and a structure;
  1459. X * they do not make system calls.
  1460. X *
  1461. X * File_dirscan() and file_archscan() call back a caller provided function
  1462. X * for each file found.  A flag to this callback function lets file_dirscan()
  1463. X * and file_archscan() indicate that a timestamp is being provided with the
  1464. X * file.   If file_dirscan() or file_archscan() do not provide the file's
  1465. X * timestamp, interested parties may later call file_time().
  1466. X */
  1467. X
  1468. X/*
  1469. X * file_parse() - split a file name into dir/base/suffix/member
  1470. X */
  1471. X
  1472. Xvoid
  1473. Xfile_parse( file, f )
  1474. Xchar        *file;
  1475. XFILENAME    *f;
  1476. X{
  1477. X    char *p; 
  1478. X    char *end;
  1479. X    
  1480. X    memset( (char *)f, 0, sizeof( *f ) );
  1481. X
  1482. X    /* Look for <grist> */
  1483. X
  1484. X    if( file[0] == '<' && ( p = strchr( file, '>' ) ) )
  1485. X    {
  1486. X        f->f_grist.ptr = file + 1;
  1487. X        f->f_grist.len = p - file - 1;
  1488. X        file = p + 1;
  1489. X    }
  1490. X
  1491. X    /* Look for dir/ */
  1492. X
  1493. X    if( p = strrchr( file, '/' ) )
  1494. X    {
  1495. X        f->f_dir.ptr = file;
  1496. X        f->f_dir.len = p - file;
  1497. X        file = p + 1;
  1498. X    }
  1499. X
  1500. X    end = file + strlen( file );
  1501. X
  1502. X    /* Look for (member) */
  1503. X
  1504. X    if( ( p = strchr( file, '(' ) ) && end[-1] == ')' )
  1505. X    {
  1506. X        f->f_member.ptr = p + 1;
  1507. X        f->f_member.len = end - p - 2;
  1508. X        end = p;
  1509. X    } 
  1510. X
  1511. X    /* Look for .suffix */
  1512. X
  1513. X    if( ( p = strchr( file, '.' ) ) && p < end )
  1514. X    {
  1515. X        f->f_suffix.ptr = p;
  1516. X        f->f_suffix.len = end - p;
  1517. X        end = p;
  1518. X    }
  1519. X
  1520. X    /* Leaves base */
  1521. X
  1522. X    f->f_base.ptr = file;
  1523. X    f->f_base.len = end - file;
  1524. X}
  1525. X
  1526. X/*
  1527. X * file_build() - build a filename given dir/base/suffix/member
  1528. X */
  1529. X
  1530. Xvoid
  1531. Xfile_build( f, file )
  1532. XFILENAME    *f;
  1533. Xchar        *file;
  1534. X{
  1535. X    if( f->f_grist.len )
  1536. X    {
  1537. X        *file++ = '<';
  1538. X        memcpy( file, f->f_grist.ptr, f->f_grist.len );
  1539. X        file += f->f_grist.len;
  1540. X        *file++ = '>';
  1541. X    }
  1542. X
  1543. X    /* Don't prepend root if it's . or directory is rooted */
  1544. X
  1545. X    if( f->f_root.len 
  1546. X        && !( f->f_root.len == 1 && f->f_root.ptr[0] == '.' )
  1547. X        && !( f->f_dir.len && f->f_dir.ptr[0] == '/' ) )
  1548. X    {
  1549. X        memcpy( file, f->f_root.ptr, f->f_root.len );
  1550. X        file += f->f_root.len;
  1551. X        *file++ = '/';
  1552. X    }
  1553. X        
  1554. X    if( f->f_dir.len )
  1555. X    {
  1556. X        memcpy( file, f->f_dir.ptr, f->f_dir.len );
  1557. X        file += f->f_dir.len;
  1558. X    }
  1559. X
  1560. X    if( f->f_dir.len && f->f_base.len )
  1561. X        *file++ = '/';
  1562. X
  1563. X    if( f->f_base.len )
  1564. X    {
  1565. X        memcpy( file, f->f_base.ptr, f->f_base.len );
  1566. X        file += f->f_base.len;
  1567. X    }
  1568. X
  1569. X    if( f->f_suffix.len )
  1570. X    {
  1571. X        memcpy( file, f->f_suffix.ptr, f->f_suffix.len );
  1572. X        file += f->f_suffix.len;
  1573. X    }
  1574. X
  1575. X    if( f->f_member.len )
  1576. X    {
  1577. X        *file++ = '(';
  1578. X        memcpy( file, f->f_member.ptr, f->f_member.len );
  1579. X        file += f->f_member.len;
  1580. X        *file++ = ')';
  1581. X    }
  1582. X    *file = 0;
  1583. X}
  1584. X
  1585. X/*
  1586. X * file_dirscan() - scan a directory for files
  1587. X */
  1588. X
  1589. Xvoid
  1590. Xfile_dirscan( dir, func )
  1591. Xchar    *dir;
  1592. Xvoid    (*func)();
  1593. X{
  1594. X    FILENAME f;
  1595. X    DIR *d;
  1596. X    struct dirent *dirent;
  1597. X    char filename[ MAXPATH ];
  1598. X    struct stat statbuf;
  1599. X
  1600. X    /* First enter directory itself */
  1601. X
  1602. X    memset( (char *)&f, '\0', sizeof( f ) );
  1603. X
  1604. X    f.f_dir.ptr = dir;
  1605. X    f.f_dir.len = strlen(dir);
  1606. X
  1607. X    dir = *dir ? dir : ".";
  1608. X
  1609. X    /* Now enter contents of directory */
  1610. X
  1611. X    if( !( d = opendir( dir ) ) )
  1612. X        return;
  1613. X
  1614. X    if( DEBUG_BINDSCAN )
  1615. X        printf( "scan directory %s\n", dir );
  1616. X
  1617. X    while( dirent = readdir( d ) )
  1618. X    {
  1619. X        f.f_base.ptr = dirent->d_name;
  1620. X        f.f_base.len = strlen( dirent->d_name );
  1621. X
  1622. X        file_build( &f, filename );
  1623. X
  1624. X        (*func)( filename, 0 /* not stat()'ed */, (time_t)0 );
  1625. X    }
  1626. X
  1627. X    closedir( d );
  1628. X}
  1629. X
  1630. X/*
  1631. X * file_time() - get timestamp of file, if not done by file_dirscan()
  1632. X */
  1633. X
  1634. Xint
  1635. Xfile_time( filename, time )
  1636. Xchar    *filename;
  1637. Xtime_t    *time;
  1638. X{
  1639. X    struct stat statbuf;
  1640. X
  1641. X    if( stat( filename, &statbuf ) < 0 )
  1642. X        return -1;
  1643. X
  1644. X    *time = statbuf.st_mtime;
  1645. X    return 0;
  1646. X}
  1647. X
  1648. X/*
  1649. X * file_archscan() - scan an archive for files
  1650. X */
  1651. X
  1652. X# ifndef AIAMAG    /* God-fearing UNIX */
  1653. X
  1654. X# define SARFMAG 2
  1655. X# define SARHDR sizeof( struct ar_hdr )
  1656. X
  1657. Xvoid
  1658. Xfile_archscan( archive, func )
  1659. Xchar *archive;
  1660. Xvoid (*func)();
  1661. X{
  1662. X    struct ar_hdr ar_hdr;
  1663. X    char buf[ MAXPATH ];
  1664. X    long offset;
  1665. X    int fd;
  1666. X
  1667. X    if( ( fd = open( archive, O_RDONLY, 0 ) ) < 0 )
  1668. X        return;
  1669. X
  1670. X    if( read( fd, buf, SARMAG ) != SARMAG ||
  1671. X        strncmp( ARMAG, buf, SARMAG ) )
  1672. X    {
  1673. X        close( fd );
  1674. X        return;
  1675. X    }
  1676. X
  1677. X    offset = SARMAG;
  1678. X
  1679. X    if( DEBUG_BINDSCAN )
  1680. X        printf( "scan archive %s\n", archive );
  1681. X
  1682. X    while( read( fd, &ar_hdr, SARHDR ) == SARHDR &&
  1683. X           !memcmp( ar_hdr.ar_fmag, ARFMAG, SARFMAG ) )
  1684. X    {
  1685. X        char    lar_name[16];
  1686. X        long    lar_date;
  1687. X        long    lar_size;
  1688. X        char *c;
  1689. X
  1690. X        strncpy( lar_name, ar_hdr.ar_name, sizeof(ar_hdr.ar_name) );
  1691. X        c = lar_name + sizeof( lar_name );
  1692. X        while( *--c == ' ' || *c == '/' )
  1693. X            ;
  1694. X        *++c = '\0';
  1695. X
  1696. X        sscanf( ar_hdr.ar_date, "%ld", &lar_date );
  1697. X        sscanf( ar_hdr.ar_size, "%ld", &lar_size );
  1698. X
  1699. X        sprintf( buf, "%s(%s)", archive, lar_name );
  1700. X
  1701. X        (*func)( buf, 1 /* time valid */, (time_t)lar_date );
  1702. X
  1703. X        offset += SARHDR + ( ( lar_size + 1 ) & ~1 );
  1704. X        lseek( fd, offset, 0 );
  1705. X    }
  1706. X
  1707. X    close( fd );
  1708. X}
  1709. X
  1710. X# else /* AIAMAG - RS6000 AIX */
  1711. X
  1712. Xvoid
  1713. Xfile_archscan( archive, func )
  1714. Xchar *archive;
  1715. Xvoid (*func)();
  1716. X{
  1717. X    struct fl_hdr fl_hdr;
  1718. X
  1719. X    struct {
  1720. X        struct ar_hdr hdr;
  1721. X        char pad[ 256 ];
  1722. X    } ar_hdr ;
  1723. X
  1724. X    char buf[ MAXPATH ];
  1725. X    long offset;
  1726. X    int fd;
  1727. X
  1728. X    if( ( fd = open( archive, O_RDONLY, 0 ) ) < 0 )
  1729. X        return;
  1730. X
  1731. X    if( read( fd, (char *)&fl_hdr, FL_HSZ ) != FL_HSZ ||
  1732. X        strncmp( AIAMAG, fl_hdr.fl_magic, SAIAMAG ) )
  1733. X    {
  1734. X        close( fd );
  1735. X        return;
  1736. X    }
  1737. X
  1738. X    sscanf( fl_hdr.fl_fstmoff, "%ld", &offset );
  1739. X
  1740. X    if( DEBUG_BINDSCAN )
  1741. X        printf( "scan archive %s\n", archive );
  1742. X
  1743. X    while( offset > 0 &&
  1744. X           lseek( fd, offset, 0 ) >= 0 &&
  1745. X           read( fd, &ar_hdr, sizeof( ar_hdr ) ) >= sizeof( ar_hdr.hdr ) )
  1746. X    {
  1747. X        long    lar_date;
  1748. X        int        lar_namlen;
  1749. X
  1750. X        sscanf( ar_hdr.hdr.ar_namlen, "%d", &lar_namlen );
  1751. X        sscanf( ar_hdr.hdr.ar_date, "%ld", &lar_date );
  1752. X        sscanf( ar_hdr.hdr.ar_nxtmem, "%ld", &offset );
  1753. X
  1754. X        if( !lar_namlen )
  1755. X        continue;
  1756. X
  1757. X        ar_hdr.hdr._ar_name.ar_name[ lar_namlen ] = '\0';
  1758. X
  1759. X        sprintf( buf, "%s(%s)", archive, ar_hdr.hdr._ar_name.ar_name );
  1760. X
  1761. X        (*func)( buf, 1 /* time valid */, (time_t)lar_date );
  1762. X    }
  1763. X
  1764. X    close( fd );
  1765. X}
  1766. X
  1767. X# endif /* AIAMAG - RS6000 AIX */
  1768. X
  1769. X# endif /* UNIX */
  1770. SHAR_EOF
  1771. chmod 0444 fileunix.c ||
  1772. echo 'restore of fileunix.c failed'
  1773. Wc_c="`wc -c < 'fileunix.c'`"
  1774. test 6593 -eq "$Wc_c" ||
  1775.     echo 'fileunix.c: original size 6593, current size' "$Wc_c"
  1776. fi
  1777. # ============= filevms.c ==============
  1778. if test -f 'filevms.c' -a X"$1" != X"-c"; then
  1779.     echo 'x - skipping filevms.c (File already exists)'
  1780. else
  1781. echo 'x - extracting filevms.c (Text)'
  1782. sed 's/^X//' << 'SHAR_EOF' > 'filevms.c' &&
  1783. X/*
  1784. X * Copyright 1993 Christopher Seiwald.
  1785. X */
  1786. X
  1787. X# ifdef VMS
  1788. X
  1789. X/*
  1790. X * filevms.c - manipulate file names and scan directories on VMS
  1791. X */
  1792. X
  1793. X# include <rms.h>
  1794. X# include <iodef.h>
  1795. X# include <ssdef.h>
  1796. X# include <string.h>
  1797. X# include <stdlib.h>
  1798. X# include <ctype.h>
  1799. X# include <stdio.h>
  1800. X# include <descrip.h>
  1801. X
  1802. X#include <lbrdef.h>
  1803. X#include <credef.h>
  1804. X#include <mhddef.h>
  1805. X#include <lhidef.h>
  1806. X
  1807. X# include "jam.h"
  1808. X# include "filesys.h"
  1809. X
  1810. X/*
  1811. X * unlink() - remove a file
  1812. X */
  1813. X
  1814. Xunlink( f )
  1815. Xchar *f;
  1816. X{
  1817. X    remove( f );
  1818. X}
  1819. X
  1820. X/*
  1821. X * file_parse() - split a file name into dir/base/suffix/member
  1822. X */
  1823. X
  1824. Xvoid
  1825. Xfile_parse( file, f )
  1826. Xchar        *file;
  1827. XFILENAME    *f;
  1828. X{
  1829. X    char *p; 
  1830. X    char *end;
  1831. X    
  1832. X    memset( (char *)f, 0, sizeof( *f ) );
  1833. X
  1834. X    /* Look for <grist> */
  1835. X
  1836. X    if( file[0] == '<' && ( p = strchr( file, '>' ) ) )
  1837. X    {
  1838. X        f->f_grist.ptr = file + 1;
  1839. X        f->f_grist.len = p - file - 1;
  1840. X        file = p + 1;
  1841. X    }
  1842. X
  1843. X    /* Look for dev:[dir] or dev: */
  1844. X
  1845. X    if( ( p = strchr( file, ']' ) ) || ( p = strchr( file, ':' ) ) )
  1846. X    {
  1847. X        f->f_dir.ptr = file;
  1848. X        f->f_dir.len = p + 1 - file;
  1849. X        file = p + 1;
  1850. X    }
  1851. X
  1852. X    end = file + strlen( file );
  1853. X
  1854. X    /* Look for (member) */
  1855. X
  1856. X    if( ( p = strchr( file, '(' ) ) && end[-1] == ')' )
  1857. X    {
  1858. X        f->f_member.ptr = p + 1;
  1859. X        f->f_member.len = end - p - 2;
  1860. X        end = p;
  1861. X    } 
  1862. X
  1863. X    /* Look for .suffix */
  1864. X
  1865. X    if( ( p = strchr( file, '.' ) ) && p < end )
  1866. X    {
  1867. X        f->f_suffix.ptr = p;
  1868. X        f->f_suffix.len = end - p;
  1869. X        end = p;
  1870. X    }
  1871. X
  1872. X    /* Leaves base */
  1873. X
  1874. X    f->f_base.ptr = file;
  1875. X    f->f_base.len = end - file;
  1876. X}
  1877. X
  1878. X/*
  1879. X * file_flags() - find out what's in a directory name
  1880. X *
  1881. X * VMS directories get complicated.  Valid combinations of root
  1882. X * and dir are:
  1883. X *
  1884. X *    root        dir        result
  1885. X *    ----        ---        ------
  1886. X *                    
  1887. X *             [dir]        [dir]
  1888. X *    dev                dev:
  1889. X *    dev        [dir]        dev:[dir]
  1890. X *    dev:                dev:
  1891. X *    dev:        [dir]        dev:[dir]
  1892. X *    [dir]                [dir]
  1893. X *    [dir]        [dir]        [dir.dir]
  1894. X *    dev:[dir]            dev:[dir]
  1895. X *    dev:[dir]    [dir]        dev:[dir.dir]
  1896. X *
  1897. X *    *        dev        dev
  1898. X *    *        dev:        dev:
  1899. X *    *        dev:[dir]    dev:[dir]
  1900. X *
  1901. X */
  1902. X
  1903. X# define HAS_NOTHING    0
  1904. X# define HAS_DEV    0x01
  1905. X# define HAS_DIR    0x02
  1906. X# define HAS_COLON    0x04
  1907. X
  1908. Xstatic int
  1909. Xfile_flags( buf, len )
  1910. Xchar    *buf;
  1911. Xint    len;
  1912. X{
  1913. X    int flags = 0;
  1914. X
  1915. X    if( len && *buf != '[' )
  1916. X        flags |= HAS_DEV;
  1917. X
  1918. X    while( len-- )
  1919. X        switch( *buf++ )
  1920. X    {
  1921. X    case ':':    flags |= HAS_COLON; break;
  1922. X    case '[':    flags |= HAS_DIR; break;
  1923. X    }
  1924. X
  1925. X    return flags;
  1926. X}
  1927. X
  1928. X/*
  1929. X * file_build() - build a filename given dir/base/suffix/member
  1930. X */
  1931. X
  1932. Xvoid
  1933. Xfile_build( f, file )
  1934. XFILENAME    *f;
  1935. Xchar        *file;
  1936. X{
  1937. X
  1938. X    int dir_flags = HAS_DEV;
  1939. X    int root_flags = 0;
  1940. X
  1941. X    if( f->f_grist.len )
  1942. X    {
  1943. X        *file++ = '<';
  1944. X        memcpy( file, f->f_grist.ptr, f->f_grist.len );
  1945. X        file += f->f_grist.len;
  1946. X        *file++ = '>';
  1947. X    }
  1948. X
  1949. X    if( f->f_root.len )
  1950. X    {
  1951. X        root_flags = file_flags( f->f_root.ptr, f->f_root.len );
  1952. X        dir_flags = file_flags( f->f_dir.ptr, f->f_dir.len );
  1953. X    }
  1954. X
  1955. X    switch( dir_flags & 0x03 )
  1956. X    {
  1957. X    case HAS_DIR:
  1958. X    case HAS_NOTHING:
  1959. X        switch( root_flags & 0x03 )
  1960. X        {
  1961. X        case HAS_NOTHING:
  1962. X        break;
  1963. X
  1964. X        case HAS_DEV:
  1965. X        memcpy( file, f->f_root.ptr, f->f_root.len );
  1966. X        file += f->f_root.len;
  1967. X        if( !( root_flags & HAS_COLON ) )
  1968. X            *file++ = ':';
  1969. X        break;
  1970. X        
  1971. X        case HAS_DIR:
  1972. X        case HAS_DEV|HAS_DIR:
  1973. X        memcpy( file, f->f_root.ptr, f->f_root.len );
  1974. X        file += f->f_root.len;
  1975. X        break;
  1976. X        }
  1977. X
  1978. X        if( dir_flags & HAS_DIR )
  1979. X        {
  1980. X        if( root_flags & HAS_DIR )
  1981. X        {
  1982. X            file[-1] = '.';
  1983. X            memcpy( file, f->f_dir.ptr + 1, f->f_dir.len - 1 );
  1984. X            file += f->f_root.len - 1;
  1985. X        }
  1986. X        else
  1987. X        {
  1988. X            memcpy( file, f->f_dir.ptr, f->f_dir.len );
  1989. X            file += f->f_dir.len;
  1990. X        }
  1991. X        }
  1992. X
  1993. X        break;
  1994. X
  1995. X    case HAS_DEV:
  1996. X    case HAS_DEV|HAS_DIR:
  1997. X        memcpy( file, f->f_dir.ptr, f->f_dir.len );
  1998. X        file += f->f_dir.len;
  1999. X        break;
  2000. X    }
  2001. X
  2002. X    if( f->f_base.len )
  2003. X    {
  2004. X        memcpy( file, f->f_base.ptr, f->f_base.len );
  2005. X        file += f->f_base.len;
  2006. X    }
  2007. X
  2008. X    if( f->f_suffix.len )
  2009. X    {
  2010. X        memcpy( file, f->f_suffix.ptr, f->f_suffix.len );
  2011. X        file += f->f_suffix.len;
  2012. X    }
  2013. X
  2014. X    if( f->f_member.len )
  2015. X    {
  2016. X        *file++ = '(';
  2017. X        memcpy( file, f->f_member.ptr, f->f_member.len );
  2018. X        file += f->f_member.len;
  2019. X        *file++ = ')';
  2020. X    }
  2021. X    *file = 0;
  2022. X}
  2023. X
  2024. Xstatic void
  2025. Xfile_cvttime( curtime, unixtime )
  2026. Xunsigned int *curtime;
  2027. Xtime_t *unixtime;
  2028. X{
  2029. X    static const size_t divisor = 10000000;
  2030. X    static unsigned int bastim[2] = { 0x4BEB4000, 0x007C9567 }; /* 1/1/1970 */
  2031. X    int delta[2], remainder;
  2032. X
  2033. X    LIB$SUBX( curtime, bastim, delta );
  2034. X    LIB$EDIV( &divisor, delta, unixtime, &remainder );
  2035. X}
  2036. X
  2037. X# define DEFAULT_FILE_SPECIFICATION "[]*.*;0"
  2038. X
  2039. X# define min( a,b ) ((a)<(b)?(a):(b))
  2040. X
  2041. Xvoid
  2042. Xfile_dirscan( char *dir, void (*func)() )
  2043. X{
  2044. X    size_t SYS$PARSE( );
  2045. X    size_t SYS$SEARCH( );
  2046. X    size_t LIB$SIGNAL( );
  2047. X
  2048. X    struct FAB xfab;
  2049. X    struct NAM xnam;
  2050. X    struct XABDAT xab;
  2051. X    char esa[256];
  2052. X    char filename[256];
  2053. X    char filename2[256];
  2054. X    register status;
  2055. X    FILENAME f;
  2056. X
  2057. X    memset( (char *)&f, '\0', sizeof( f ) );
  2058. X
  2059. X    f.f_dir.ptr = dir;
  2060. X    f.f_dir.len = strlen( dir );
  2061. X
  2062. X    /* get the input file specification
  2063. X     */
  2064. X    xnam = cc$rms_nam;
  2065. X    xnam.nam$l_esa = esa;
  2066. X    xnam.nam$b_ess = sizeof( esa ) - 1;
  2067. X    xnam.nam$l_rsa = filename;
  2068. X    xnam.nam$b_rss = min( sizeof( filename ) - 1, NAM$C_MAXRSS );
  2069. X
  2070. X    xab = cc$rms_xabdat;                /* initialize extended attributes */
  2071. X    xab.xab$b_cod = XAB$C_DAT;        /* ask for date */
  2072. X    xab.xab$l_nxt = NULL;               /* terminate XAB chain      */
  2073. X
  2074. X    xfab = cc$rms_fab;
  2075. X    xfab.fab$l_dna = DEFAULT_FILE_SPECIFICATION;
  2076. X    xfab.fab$b_dns = sizeof( DEFAULT_FILE_SPECIFICATION ) - 1;
  2077. X    xfab.fab$l_fop = FAB$M_NAM;
  2078. X    xfab.fab$l_fna = dir;            /* address of file name        */
  2079. X    xfab.fab$b_fns = strlen( dir );        /* length of file name        */
  2080. X    xfab.fab$l_nam = &xnam;            /* address of NAB block        */
  2081. X    xfab.fab$l_xab = (char *)&xab;       /* address of XAB block     */
  2082. X
  2083. X
  2084. X    status = SYS$PARSE( &xfab );
  2085. X
  2086. X    if( DEBUG_BINDSCAN )
  2087. X    printf( "scan directory %s\n", dir );
  2088. X
  2089. X    if ( !( status & 1 ) )
  2090. X    return;
  2091. X
  2092. X    while ( (status = SYS$SEARCH( &xfab )) & 1 )
  2093. X    {
  2094. X    char *s;
  2095. X    time_t time;
  2096. X
  2097. X    /* "I think that might work" - eml */
  2098. X
  2099. X    sys$open( &xfab );
  2100. X    sys$close( &xfab );
  2101. X
  2102. X    filename[xnam.nam$b_rsl] = '\0';
  2103. X    for( s = xnam.nam$l_name; *s; s++ )
  2104. X        if( isupper( *s ) )
  2105. X        *s = tolower( *s );
  2106. X
  2107. X    f.f_base.ptr = xnam.nam$l_name;
  2108. X    f.f_base.len = xnam.nam$b_name;
  2109. X    f.f_suffix.ptr = xnam.nam$l_type;
  2110. X    f.f_suffix.len = xnam.nam$b_type;
  2111. X
  2112. X    file_build( &f, filename2 );
  2113. X
  2114. X    file_cvttime( &xab.xab$q_rdt, &time );
  2115. X
  2116. X    (*func)( filename2, 1 /* time valid */, time );
  2117. X    }
  2118. X
  2119. X    if ( status != RMS$_NMF && status != RMS$_FNF )
  2120. X    LIB$SIGNAL( xfab.fab$l_sts, xfab.fab$l_stv );
  2121. X}    
  2122. X
  2123. Xint
  2124. Xfile_time( filename, time )
  2125. Xchar    *filename;
  2126. Xtime_t    *time;
  2127. X{
  2128. X    /* This should never be called, as all files are */
  2129. X    /* timestampped in file_dirscan() and file_archscan() */
  2130. X    return -1;
  2131. X}
  2132. X
  2133. Xstatic char *VMS_archive = 0;
  2134. Xstatic void (*VMS_func)() = 0;
  2135. Xstatic void *context;
  2136. X
  2137. Xstatic int
  2138. Xfile_archmember( module, rfa )
  2139. Xstruct dsc$descriptor_s *module;
  2140. Xunsigned long *rfa;
  2141. X{
  2142. X    static struct dsc$descriptor_s bufdsc =
  2143. X          {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL};
  2144. X
  2145. X    struct mhddef *mhd;
  2146. X    char filename[128];
  2147. X    char buf[ MAXPATH ];
  2148. X
  2149. X    int library_date, status;
  2150. X
  2151. X    register int i;
  2152. X    register char *p;
  2153. X
  2154. X    bufdsc.dsc$a_pointer = filename;
  2155. X    bufdsc.dsc$w_length = sizeof( filename );
  2156. X    status = LBR$SET_MODULE( &context, rfa, &bufdsc,
  2157. X                 &bufdsc.dsc$w_length, NULL );
  2158. X    if ( !(status & 1) )
  2159. X    return ( 1 );
  2160. X
  2161. X    mhd = (struct mhddef *)filename;
  2162. X
  2163. X    file_cvttime( &mhd->mhd$l_datim, &library_date );
  2164. X
  2165. X    for ( i = 0, p = module->dsc$a_pointer; i < module->dsc$w_length; i++, p++ )
  2166. X    filename[i] = _tolower( *p );
  2167. X
  2168. X    filename[i] = '\0';
  2169. X
  2170. X    sprintf( buf, "%s(%s.obj)", VMS_archive, filename );
  2171. X
  2172. X    (*VMS_func)( buf, 1 /* time valid */, (time_t)library_date );
  2173. X
  2174. X    return ( 1 );
  2175. X}
  2176. X
  2177. Xvoid
  2178. Xfile_archscan( archive, func )
  2179. Xchar *archive;
  2180. Xvoid (*func)();
  2181. X{
  2182. X    static struct dsc$descriptor_s library =
  2183. X          {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL};
  2184. X
  2185. X    unsigned long lfunc = LBR$C_READ;
  2186. X    unsigned long typ = LBR$C_TYP_UNK;
  2187. X    unsigned long index = 1;
  2188. X
  2189. X    register status;
  2190. X
  2191. X    VMS_archive = archive;
  2192. X    VMS_func = func;
  2193. X
  2194. X    status = LBR$INI_CONTROL( &context, &lfunc, &typ, NULL );
  2195. X    if ( !( status & 1 ) )
  2196. X    return;
  2197. X
  2198. X    library.dsc$a_pointer = archive;
  2199. X    library.dsc$w_length = strlen( archive );
  2200. X
  2201. X    status = LBR$OPEN( &context, &library, NULL, NULL, NULL, NULL, NULL );
  2202. X    if ( !( status & 1 ) )
  2203. X    return;
  2204. X
  2205. X    (void) LBR$GET_INDEX( &context, &index, file_archmember, NULL );
  2206. X
  2207. X    (void) LBR$CLOSE( &context );
  2208. X}
  2209. X
  2210. X# endif /* VMS */
  2211. X
  2212. SHAR_EOF
  2213. chmod 0444 filevms.c ||
  2214. echo 'restore of filevms.c failed'
  2215. Wc_c="`wc -c < 'filevms.c'`"
  2216. test 8453 -eq "$Wc_c" ||
  2217.     echo 'filevms.c: original size 8453, current size' "$Wc_c"
  2218. fi
  2219. # ============= hash.c ==============
  2220. if test -f 'hash.c' -a X"$1" != X"-c"; then
  2221.     echo 'x - skipping hash.c (File already exists)'
  2222. else
  2223. echo 'x - extracting hash.c (Text)'
  2224. sed 's/^X//' << 'SHAR_EOF' > 'hash.c' &&
  2225. X/*
  2226. X * Copyright 1993 Christopher Seiwald.
  2227. X */
  2228. X
  2229. X# include "jam.h"
  2230. X# include "hash.h"
  2231. X
  2232. X/* 
  2233. X * hash.c - simple in-memory hashing routines 
  2234. X *
  2235. X * External routines:
  2236. X *
  2237. X *     hashinit() - initialize a hash table, returning a handle
  2238. X *     hashitem() - find a record in the table, and optionally enter a new one
  2239. X *     hashdone() - free a hash table, given its handle
  2240. X *
  2241. X * Internal routines:
  2242. X *
  2243. X *     hashrehash() - resize and rebuild hp->tab, the hash table
  2244. X *
  2245. X * 4/29/93 - ensure ITEM's are aligned
  2246. X */
  2247. X
  2248. Xchar     *hashsccssid="@(#)hash.c    1.14  ()  6/20/88";
  2249. X
  2250. X/* Header attached to all data items entered into a hash table. */
  2251. X
  2252. Xstruct hashhdr {
  2253. X    struct item *next;
  2254. X    int keyval;            /* for quick comparisons */
  2255. X} ;
  2256. X
  2257. X/* This structure overlays the one handed to hashenter(). */
  2258. X/* It's actual size is given to hashinit(). */
  2259. X
  2260. Xstruct hashdata {
  2261. X    char    *key;
  2262. X    /* rest of user data */
  2263. X} ;
  2264. X
  2265. Xtypedef struct item {
  2266. X    struct hashhdr hdr;
  2267. X    struct hashdata data;
  2268. X} ITEM ;
  2269. X
  2270. X# define MAX_LISTS 32
  2271. X
  2272. Xstruct hash 
  2273. X{
  2274. X    /*
  2275. X     * the hash table, just an array of item pointers
  2276. X     */
  2277. X    struct {
  2278. X        int nel;
  2279. X        ITEM **base;
  2280. X    } tab;
  2281. X
  2282. X    int bloat;    /* tab.nel / items.nel */
  2283. X    int inel;     /* initial number of elements */
  2284. X
  2285. X    /*
  2286. X     * the array of records, maintained by these routines
  2287. X     * essentially a microallocator
  2288. X     */ 
  2289. X    struct {
  2290. X        int more;    /* how many more ITEMs fit in lists[ list ] */
  2291. X        char *next;    /* where to put more ITEMs in lists[ list ] */
  2292. X        int datalen;    /* length of records in this hash table */
  2293. X        int size;    /* sizeof( ITEM ) + aligned datalen */
  2294. X        int nel;    /* total ITEMs held by all lists[] */
  2295. X        int list;    /* index into lists[] */
  2296. X
  2297. X        struct {
  2298. X            int nel;    /* total ITEMs held by this list */
  2299. X            char *base;    /* base of ITEMs array */
  2300. X        } lists[ MAX_LISTS ];
  2301. X    } items;
  2302. X
  2303. X    char *name;    /* just for hashstats() */
  2304. X} ;
  2305. X
  2306. Xstatic hashrehash();
  2307. X
  2308. X/*
  2309. X * hashitem() - find a record in the table, and optionally enter a new one
  2310. X */
  2311. X
  2312. Xint
  2313. Xhashitem( hp, data, enter )
  2314. Xregister struct hash *hp;
  2315. XHASHDATA **data;
  2316. X{
  2317. X    ITEM **base;
  2318. X    register ITEM *i;
  2319. X    char *b = (*data)->key;
  2320. X    int keyval = 0;
  2321. X
  2322. X    if( enter && !hp->items.more )
  2323. X        hashrehash( hp );
  2324. X
  2325. X    if( !enter && !hp->items.nel )
  2326. X        return 0;
  2327. X
  2328. X    while( *b )
  2329. X        keyval = ( ( keyval << 7 ) + ( keyval >> 25 ) ) + *b++;
  2330. X    keyval &= 0x7FFFFFFF;
  2331. X
  2332. X    base = hp->tab.base + ( keyval % hp->tab.nel );
  2333. X
  2334. X    for( i = *base; i; i = i->hdr.next )
  2335. X        if( keyval == i->hdr.keyval && 
  2336. X        !strcmp( i->data.key, (*data)->key ) )
  2337. X    {
  2338. X        *data = &i->data;
  2339. X        return !0;
  2340. X    }
  2341. X
  2342. X    if( enter ) 
  2343. X    {
  2344. X        i = (ITEM *)hp->items.next;
  2345. X        hp->items.next += hp->items.size;
  2346. X        hp->items.more--;
  2347. X        memcpy( (char *)&i->data, (char *)*data, hp->items.datalen );
  2348. X        i->hdr.keyval = keyval;
  2349. X        i->hdr.next = *base;
  2350. X        *base = i;
  2351. X        *data = &i->data;
  2352. X    }
  2353. X
  2354. X    return 0;
  2355. X}
  2356. X
  2357. X/*
  2358. X * hashrehash() - resize and rebuild hp->tab, the hash table
  2359. X */
  2360. X
  2361. Xstatic hashrehash( hp )
  2362. Xregister struct hash *hp;
  2363. X{
  2364. X    int i = ++hp->items.list;
  2365. X
  2366. X    hp->items.more = i ? 2 * hp->items.nel : hp->inel;
  2367. X    hp->items.next = (char *)malloc( hp->items.more * hp->items.size );
  2368. X
  2369. X    hp->items.lists[i].nel = hp->items.more;
  2370. X    hp->items.lists[i].base = hp->items.next;
  2371. X    hp->items.nel += hp->items.more;
  2372. X
  2373. X    if( hp->tab.base )
  2374. X        free( (char *)hp->tab.base );
  2375. X
  2376. X    hp->tab.nel = hp->items.nel * hp->bloat;
  2377. X    hp->tab.base = (ITEM **)malloc( hp->tab.nel * sizeof(ITEM **) );
  2378. X
  2379. X    memset( (char *)hp->tab.base, '\0', hp->tab.nel * sizeof( ITEM * ) );
  2380. X
  2381. X    for( i = 0; i < hp->items.list; i++ )
  2382. X    {
  2383. X        int nel = hp->items.lists[i].nel;
  2384. X        char *next = hp->items.lists[i].base;
  2385. X
  2386. X        for( ; nel--; next += hp->items.size )
  2387. X        {
  2388. X            register ITEM *i = (ITEM *)next;
  2389. X            ITEM **ip = hp->tab.base + i->hdr.keyval % hp->tab.nel;
  2390. X
  2391. X            i->hdr.next = *ip;
  2392. X            *ip = i;
  2393. X        }
  2394. X    }
  2395. X}
  2396. X
  2397. X/* --- */
  2398. X
  2399. X# define ALIGNED(x) ( ( x + sizeof( ITEM ) - 1 ) & ~( sizeof( ITEM ) - 1 ) )
  2400. X
  2401. X/*
  2402. X * hashinit() - initialize a hash table, returning a handle
  2403. X */
  2404. X
  2405. Xstruct hash *
  2406. Xhashinit( datalen, name )
  2407. Xchar *name;
  2408. X{
  2409. X    struct hash *hp = (struct hash *)malloc( sizeof( *hp ) );
  2410. X
  2411. X    hp->bloat = 3;
  2412. X    hp->tab.nel = 0;
  2413. X    hp->tab.base = (ITEM **)0;
  2414. X    hp->items.more = 0;
  2415. X    hp->items.datalen = datalen;
  2416. X    hp->items.size = sizeof( struct hashhdr ) + ALIGNED( datalen );
  2417. X    hp->items.list = -1;
  2418. X    hp->items.nel = 0;
  2419. X    hp->inel = 11;
  2420. X    hp->name = name;
  2421. X
  2422. X    return hp;
  2423. X}
  2424. X
  2425. X/*
  2426. X * hashdone() - free a hash table, given its handle
  2427. X */
  2428. X
  2429. Xvoid
  2430. Xhashdone( hp )
  2431. Xstruct hash *hp;
  2432. X{
  2433. X    int i;
  2434. X
  2435. X    if( !hp )
  2436. X        return;
  2437. X
  2438. X    if( DEBUG_MEM )
  2439. X        hashstat( hp );
  2440. X
  2441. X    if( hp->tab.base )
  2442. X        free( (char *)hp->tab.base );
  2443. X    for( i = 0; i <= hp->items.list; i++ )
  2444. X        free( hp->items.lists[i].base );
  2445. X    free( (char *)hp );
  2446. X}
  2447. X
  2448. X/* ---- */
  2449. X
  2450. Xhashstat( hp )
  2451. Xstruct hash *hp;
  2452. X{
  2453. X    ITEM **tab = hp->tab.base;
  2454. X    int nel = hp->tab.nel;
  2455. X    int count = 0;
  2456. X    int sets = 0;
  2457. X    int run = ( tab[ nel - 1 ] != (ITEM *)0 );
  2458. X    int i, here;
  2459. X
  2460. X    for( i = nel; i > 0; i-- )
  2461. X    {
  2462. X        if( here = ( *tab++ != (ITEM *)0 ) )
  2463. X            count++;
  2464. X        if( here && !run )
  2465. X            sets++;
  2466. X        run = here;
  2467. X    }
  2468. X
  2469. X    printf( "%s table: %d+%d+%d (%dK+%dK) items+table+hash, %f density\n",
  2470. X        hp->name, 
  2471. X        count, 
  2472. X        hp->items.nel,
  2473. X        hp->tab.nel,
  2474. X        hp->items.nel * hp->items.size / 1024,
  2475. X        hp->tab.nel * sizeof( ITEM ** ) / 1024,
  2476. X        (float)count / (float)sets );
  2477. X}
  2478. SHAR_EOF
  2479. chmod 0444 hash.c ||
  2480. echo 'restore of hash.c failed'
  2481. Wc_c="`wc -c < 'hash.c'`"
  2482. test 5071 -eq "$Wc_c" ||
  2483.     echo 'hash.c: original size 5071, current size' "$Wc_c"
  2484. fi
  2485. # ============= hash.h ==============
  2486. if test -f 'hash.h' -a X"$1" != X"-c"; then
  2487.     echo 'x - skipping hash.h (File already exists)'
  2488. else
  2489. echo 'x - extracting hash.h (Text)'
  2490. sed 's/^X//' << 'SHAR_EOF' > 'hash.h' &&
  2491. X/*
  2492. X * Copyright 1993 Christopher Seiwald.
  2493. X */
  2494. X
  2495. X/*
  2496. X * hash.h - simple in-memory hashing routines 
  2497. X */
  2498. X
  2499. Xtypedef struct hashdata HASHDATA;
  2500. X
  2501. Xstruct hash *    hashinit();
  2502. Xint        hashitem();
  2503. Xvoid        hashdone();
  2504. X
  2505. X# define    hashenter( hp, data ) !hashitem( hp, data, !0 )
  2506. X# define    hashcheck( hp, data ) hashitem( hp, data, 0 )
  2507. SHAR_EOF
  2508. chmod 0444 hash.h ||
  2509. echo 'restore of hash.h failed'
  2510. Wc_c="`wc -c < 'hash.h'`"
  2511. test 311 -eq "$Wc_c" ||
  2512.     echo 'hash.h: original size 311, current size' "$Wc_c"
  2513. fi
  2514. # ============= headers.c ==============
  2515. if test -f 'headers.c' -a X"$1" != X"-c"; then
  2516.     echo 'x - skipping headers.c (File already exists)'
  2517. else
  2518. echo 'x - extracting headers.c (Text)'
  2519. sed 's/^X//' << 'SHAR_EOF' > 'headers.c' &&
  2520. X/*
  2521. X * Copyright 1993 Christopher Seiwald.
  2522. X */
  2523. X
  2524. X# include "jam.h"
  2525. X# include "lists.h"
  2526. X# include "parse.h"
  2527. X# include "compile.h"
  2528. X# include "rules.h"
  2529. X# include "variable.h"
  2530. X# include "regexp.h"
  2531. X# include "headers.h"
  2532. X
  2533. X/*
  2534. X * headers.c - handle #includes in source files
  2535. X *
  2536. X * Using regular expressions provided as the variable $(HDRSCAN), 
  2537. X * headers() searches a file for #include files and phonies up a
  2538. X * rule invocation:
  2539. X * 
  2540. X *    $(HDRRULE) <target> : <include files> ;
  2541. X *
  2542. X * External routines:
  2543. X *    headers() - scan a target for include files and call HDRRULE
  2544. X *
  2545. X * Internal routines:
  2546. X *    headers1() - using regexp, scan a file and build include LIST
  2547. X */
  2548. X
  2549. Xstatic LIST *headers1();
  2550. X
  2551. X/*
  2552. X * headers() - scan a target for include files and call HDRRULE
  2553. X */
  2554. X
  2555. X# define MAXINC 10
  2556. X
  2557. Xvoid
  2558. Xheaders( t )
  2559. XTARGET *t;
  2560. X{
  2561. X    LIST    *hdrscan;
  2562. X    LIST    *hdrrule;
  2563. X    LIST    *headlist = 0;
  2564. X    PARSE    p[1];
  2565. X    regexp    *re[ MAXINC ];
  2566. X    int    rec = 0;
  2567. X    char    *fname = t->boundname ? t->boundname : t->name;
  2568. X
  2569. X    if( !( hdrscan = var_get( "HDRSCAN" ) ) || 
  2570. X        !( hdrrule = var_get( "HDRRULE" ) ) )
  2571. X            return;
  2572. X
  2573. X    if( DEBUG_HEADER )
  2574. X        printf( "header scan %s\n", t->name );
  2575. X
  2576. X    /* Compile all regular expressions in HDRSCAN */
  2577. X
  2578. X    while( rec < MAXINC && hdrscan )
  2579. X    {
  2580. X        re[rec++] = regcomp( hdrscan->string );
  2581. X        hdrscan = list_next( hdrscan );
  2582. X    }
  2583. X
  2584. X    /* Doctor up call to HDRRULE rule */
  2585. X    /* Call headers1() to get LIST of included files. */
  2586. X
  2587. X    p->llist = list_new( (LIST *)0, t->name );
  2588. X    p->rlist = headers1( headlist, fname, rec, re );
  2589. X    p->string = hdrrule->string;
  2590. X
  2591. X    if( p->rlist )
  2592. X        compile_rule( p, (LIST *)0, (LIST *)0 );
  2593. X
  2594. X    /* Clean up */
  2595. X
  2596. X    list_free( p->llist );
  2597. X    list_free( p->rlist );
  2598. X
  2599. X    while( rec )
  2600. X        free( (char *)re[--rec] );
  2601. X}
  2602. X
  2603. X/*
  2604. X * headers1() - using regexp, scan a file and build include LIST
  2605. X */
  2606. X
  2607. Xstatic LIST *
  2608. Xheaders1( l, file, rec, re )
  2609. XLIST    *l;
  2610. Xchar    *file;
  2611. Xint    rec;
  2612. Xregexp    *re[];
  2613. X{
  2614. X    FILE    *f;
  2615. X    char    buf[ 1024 ];
  2616. X    int        i;
  2617. X
  2618. X    if( !( f = fopen( file, "r" ) ) )
  2619. X    return l;
  2620. X
  2621. X    while( fgets( buf, sizeof( buf ), f ) )
  2622. X    {
  2623. X    for( i = 0; i < rec; i++ )
  2624. X        if( regexec( re[i], buf ) && re[i]->startp[1] )
  2625. X    {
  2626. X        re[i]->endp[1][0] = '\0';
  2627. X
  2628. X        if( DEBUG_HEADER )
  2629. X        printf( "header found: %s\n", re[i]->startp[1] );
  2630. X
  2631. X        l = list_new( l, newstr( re[i]->startp[1] ) );
  2632. X    }
  2633. X    }
  2634. X
  2635. X    fclose( f );
  2636. X
  2637. X    return l;
  2638. X}
  2639. X
  2640. Xvoid
  2641. Xregerror( s )
  2642. Xchar *s;
  2643. X{
  2644. X    printf( "re error %s\n", s );
  2645. X}
  2646. SHAR_EOF
  2647. chmod 0444 headers.c ||
  2648. echo 'restore of headers.c failed'
  2649. Wc_c="`wc -c < 'headers.c'`"
  2650. test 2368 -eq "$Wc_c" ||
  2651.     echo 'headers.c: original size 2368, current size' "$Wc_c"
  2652. fi
  2653. # ============= headers.h ==============
  2654. if test -f 'headers.h' -a X"$1" != X"-c"; then
  2655.     echo 'x - skipping headers.h (File already exists)'
  2656. else
  2657. echo 'x - extracting headers.h (Text)'
  2658. sed 's/^X//' << 'SHAR_EOF' > 'headers.h' &&
  2659. X/*
  2660. X * Copyright 1993 Christopher Seiwald.
  2661. X */
  2662. X
  2663. X/*
  2664. X * headers.h - handle #includes in source files
  2665. X */
  2666. X
  2667. Xvoid headers();
  2668. SHAR_EOF
  2669. chmod 0444 headers.h ||
  2670. echo 'restore of headers.h failed'
  2671. Wc_c="`wc -c < 'headers.h'`"
  2672. test 119 -eq "$Wc_c" ||
  2673.     echo 'headers.h: original size 119, current size' "$Wc_c"
  2674. fi
  2675. true || echo 'restore of lists.c failed'
  2676. echo End of part 2, continue with part 3
  2677. exit 0
  2678.