home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume19 / shape / part21 < prev    next >
Encoding:
Internet Message Format  |  1989-05-31  |  40.6 KB

  1. Subject:  v19i034:  A software configuration management system, Part21/33
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Axel Mahler <unido!coma!axel>
  7. Posting-number: Volume 19, Issue 34
  8. Archive-name: shape/part21
  9.  
  10.  
  11.  
  12. #! /bin/sh
  13. # This is a shell archive.  Remove anything before this line, then unpack
  14. # it by saving it into a file and typing "sh file".  To overwrite existing
  15. # files, type "sh file -c".  You can also feed this as standard input via
  16. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  17. # will see the following message at the end:
  18. #        "End of archive 21 (of 33)."
  19. # Contents:  src/afs/afsets.c src/vc/vldovl.c
  20. # Wrapped by rsalz@papaya.bbn.com on Thu Jun  1 19:27:13 1989
  21. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  22. if test -f 'src/afs/afsets.c' -a "${1}" != "-c" ; then 
  23.   echo shar: Will not clobber existing file \"'src/afs/afsets.c'\"
  24. else
  25. echo shar: Extracting \"'src/afs/afsets.c'\" \(19377 characters\)
  26. sed "s/^X//" >'src/afs/afsets.c' <<'END_OF_FILE'
  27. X/*
  28. X * Copyright (C) 1989, 1990 W. Koch, A. Lampen, A. Mahler, W. Obst,
  29. X *  and U. Pralle
  30. X * 
  31. X * This software is published on an as-is basis. There is ABSOLUTELY NO
  32. X * WARRANTY for any part of this software to work correctly or as described
  33. X * in the manuals. We do not accept any liability for any kind of damage
  34. X * caused by use of this software, such as loss of data, time, money, or 
  35. X * effort.
  36. X * 
  37. X * Permission is granted to use, copy, modify, or distribute any part of
  38. X * this software as long as this is done without asking for charge, and
  39. X * provided that this copyright notice is retained as part of the source
  40. X * files. You may charge a distribution fee for the physical act of
  41. X * transferring a copy, and you may at your option offer warranty
  42. X * protection in exchange for a fee.
  43. X * 
  44. X * Direct questions to: Tech. Univ. Berlin
  45. X *              Wilfried Koch
  46. X *              Sekr. FR 5-6 
  47. X *              Franklinstr. 28/29
  48. X *              D-1000 Berlin 10, West Germany
  49. X * 
  50. X *              Tel: +49-30-314-22972
  51. X *              E-mail: shape@coma.uucp or shape@db0tui62.bitnet
  52. X */
  53. X/*LINTLIBRARY*/
  54. X/*
  55. X *    Shape/AFS
  56. X *
  57. X *    afsets.c -- Operations on keysets
  58. X *
  59. X *    Author: Andreas Lampen, TU-Berlin (andy@coma.UUCP)
  60. X *                      (andy@db0tui62.BITNET)
  61. X *
  62. X *    $Header: afsets.c[1.3] Wed Feb 22 16:27:56 1989 andy@coma published $
  63. X *
  64. X *    EXPORT:
  65. X *    af_initset -- initialize set descriptor
  66. X *      af_copyset -- copy sets
  67. X *    af_nrofkeys -- return number of keys in set
  68. X *    af_sortset -- sort set by attribute
  69. X *    af_dropset -- drop set
  70. X *      af_setgkey -- get key from set
  71. X *    af_setaddkey -- add key to set
  72. X *      af_setrmkey -- remove key from set
  73. X *      af_setposrmkey -- remove key (identified by position) from set
  74. X *      af_subset -- build subset
  75. X *      af_intersect -- build intersection of two sets
  76. X *      af_union -- build union of two sets
  77. X *      af_diff -- build difference between two sets
  78. X */
  79. X
  80. X#include <stdio.h>
  81. X#include <string.h>
  82. X#ifdef SUNOS_4_0
  83. X#include <strings.h>
  84. X#endif
  85. X
  86. X#include "typeconv.h"
  87. X#include "afsys.h"
  88. X#include "afs.h"
  89. X
  90. Xchar *malloc(), *realloc();
  91. X
  92. X/*================================================================
  93. X *    af_settest -- test plausibility of set descriptor
  94. X *                    returnes TRUE (ERROR) if set descr. is invalid,
  95. X *                    otherwise FALSE (AF_OK).
  96. X *
  97. X *================================================================*/
  98. X
  99. XLOCAL af_settest (set)
  100. X     Af_set *set;
  101. X{
  102. X  if ((set->af_nkeys < 0) || (set->af_setlen < 0))
  103. X    return (ERROR);
  104. X  /* if set is not empty, test if first key is valid */
  105. X  if (set->af_nkeys >= 1)
  106. X    if (af_keytest (&(set->af_klist[0])))
  107. X      return (ERROR);
  108. X
  109. X  return (AF_OK);
  110. X}
  111. X
  112. X/*================================================================
  113. X *    af_initset -- initialize set descriptor
  114. X *
  115. X *================================================================*/
  116. X
  117. XEXPORT af_initset (set)
  118. X     Af_set *set;
  119. X{
  120. X  set->af_nkeys = 0;
  121. X  set->af_setlen = 0;
  122. X  set->af_klist = (Af_key *)0;
  123. X}
  124. X
  125. X/*================================================================
  126. X *    af_copyset -- copy sets
  127. X *
  128. X *================================================================*/
  129. X
  130. XEXPORT af_copyset (set1, set2)
  131. X     Af_set *set1, *set2;
  132. X{
  133. X  int i;
  134. X
  135. X  if (af_settest (set1) || af_settest (set2))
  136. X    SFAIL ("copyset", "", AF_EINVSET, ERROR);
  137. X
  138. X  /* allocate memory for new set (incl. space for additional element) */
  139. X  set2->af_setlen = set1->af_nkeys + 1;
  140. X  if ((set2->af_klist = (Af_key *)malloc ((unsigned) (set2->af_setlen * sizeof(Af_key)))) == (Af_key *)0)
  141. X    FAIL ("copyset", "malloc", AF_ESYSERR, ERROR);
  142. X
  143. X  /* do copying */
  144. X  for (i=0; i<set1->af_nkeys; i++)
  145. X    {
  146. X      set2->af_klist[i] = set1->af_klist[i];
  147. X      /* increase refcount in list descriptor */
  148. X      VATTR((&(set2->af_klist[i]))).af_nlinks++;
  149. X      (set2->af_klist[i].af_ldes)->af_refcount++;
  150. X    }
  151. X  set2->af_nkeys = set1->af_nkeys;
  152. X  return (set2->af_nkeys);
  153. X}
  154. X
  155. X/*================================================================
  156. X *    af_nrofkeys -- return number of keys in set
  157. X *
  158. X *================================================================*/
  159. X
  160. XEXPORT af_nrofkeys (set)
  161. X     Af_set *set;
  162. X{
  163. X  if (af_settest (set))
  164. X    SFAIL ("nrofkeys", "", AF_EINVSET, ERROR);
  165. X  return (set->af_nkeys);
  166. X}
  167. X
  168. X/*================================================================
  169. X *    af_sortset -- sort set by attribute
  170. X *
  171. X *================================================================*/
  172. X
  173. Xextern struct cmpfun { int (*func) (); };
  174. X
  175. Xextern struct cmpfun af_cmpfuncts[];
  176. X
  177. Xextern char *af_attrlist[], af_udaname[];
  178. X
  179. XEXPORT af_sortset (set, attr)
  180. X     Af_set *set;
  181. X     char   *attr;
  182. X{
  183. X  int hi = AF_ATTNUM-1, lo=0, anum, res, af_cmpuda();
  184. X
  185. X  if (af_settest (set))
  186. X    SFAIL ("sortset", "", AF_EINVSET, ERROR);
  187. X  if (!attr)
  188. X    SFAIL ("sortset", "invalid attribute name", AF_EMISC, ERROR);
  189. X
  190. X  /* get attribute number (binary search) */
  191. X  anum = (hi+lo)/2;
  192. X  while (hi >= lo)
  193. X    {
  194. X      res = strcmp (attr, af_attrlist[anum]);
  195. X      if (res == 0)
  196. X    break;
  197. X      if (res < 0)
  198. X    hi = anum - 1;
  199. X      else lo = anum + 1;
  200. X      anum = (hi+lo)/2;
  201. X    }
  202. X  /* attribute names, that are not in the list of standard attributes */
  203. X  /* are assumed to be "user defined attributes" */
  204. X  if (res != 0)
  205. X    {
  206. X      (void) strcpy (af_udaname, attr);
  207. X      qsort ((char *)set->af_klist, set->af_nkeys, sizeof(Af_key), af_cmpuda); 
  208. X    }
  209. X  else
  210. X    {
  211. X      (void) strcpy (af_udaname, attr); 
  212. X      qsort ((char *)set->af_klist, set->af_nkeys, sizeof(Af_key), af_cmpfuncts[anum].func); 
  213. X    }
  214. X  return (AF_OK);
  215. X}
  216. X
  217. X/*================================================================
  218. X *    af_dropset -- drop set
  219. X *
  220. X *================================================================*/
  221. X
  222. XEXPORT af_dropset (set)
  223. X     Af_set *set;
  224. X{
  225. X  register i;
  226. X
  227. X  if (af_settest (set))
  228. X    SFAIL ("dropset", "", AF_EINVSET, ERROR);
  229. X
  230. X  for (i=0; i<set->af_nkeys; i++)
  231. X    {
  232. X      /* decrease reference count in corresponding archive */
  233. X      VATTR((&(set->af_klist[i]))).af_nlinks--;
  234. X      if (--(set->af_klist[i].af_ldes)->af_refcount <= 0)
  235. X    (void) af_detlist (set->af_klist[i].af_ldes);
  236. X    }
  237. X  if (set->af_setlen > 0)
  238. X    free ((char *)set->af_klist);
  239. X  return (AF_OK);
  240. X}
  241. X
  242. X/*================================================================
  243. X *    af_setgkey -- return key from set
  244. X *
  245. X *================================================================*/
  246. X
  247. XEXPORT af_setgkey (set, pos, key)
  248. X     Af_set *set;
  249. X     int    pos;
  250. X     Af_key *key; /* out */
  251. X{
  252. X  if (af_settest (set))
  253. X    SFAIL ("setgkey", "", AF_EINVSET, ERROR);
  254. X
  255. X  if ((pos >= set->af_nkeys) || (pos < 0))
  256. X    SFAIL ("setgkey", "", AF_ENOPOS, ERROR);
  257. X
  258. X  VATTR((&(set->af_klist[pos]))).af_nlinks++;
  259. X  (set->af_klist[pos].af_ldes)->af_refcount++;
  260. X  
  261. X  key->af_ldes = set->af_klist[pos].af_ldes;
  262. X  key->af_lpos = set->af_klist[pos].af_lpos;
  263. X  return (AF_OK);
  264. X}
  265. X
  266. X/*================================================================
  267. X *    af_setaddkey -- add key to set
  268. X *
  269. X *================================================================*/
  270. X
  271. XEXPORT af_setaddkey (set, pos, key)
  272. X     Af_set *set;
  273. X     int    pos;
  274. X     Af_key *key;
  275. X{
  276. X  register i;
  277. X
  278. X  if (af_settest (set))
  279. X    SFAIL ("setaddkey", "", AF_EINVSET, ERROR);
  280. X  if (af_keytest (key))
  281. X    SFAIL ("setaddkey", "", AF_EINVKEY, ERROR);
  282. X  if (((pos > set->af_nkeys) || (pos < 0)) && (pos != AF_LASTPOS))
  283. X    SFAIL ("setaddkey", "", AF_ENOPOS, ERROR);
  284. X
  285. X  if (pos == AF_LASTPOS)
  286. X    pos = set->af_nkeys;
  287. X
  288. X  /* if set is full, enlarge it */
  289. X  if (set->af_nkeys == set->af_setlen)
  290. X    {
  291. X      if (set->af_setlen == 0)
  292. X    {
  293. X      if ((set->af_klist = (Af_key *)malloc ((unsigned) (sizeof(Af_key) * AF_SEGLEN))) == (Af_key *)0)
  294. X        FAIL ("setaddkey", "malloc", AF_ESYSERR, ERROR);
  295. X    }
  296. X      else
  297. X    {
  298. X      if ((set->af_klist = (Af_key *)realloc ((char *)set->af_klist, (unsigned) (sizeof(Af_key) * (set->af_setlen + AF_SEGLEN)))) == (Af_key *)0)
  299. X        FAIL ("setaddkey", "realloc", AF_ESYSERR, ERROR);
  300. X    }
  301. X      set->af_setlen += AF_SEGLEN;
  302. X    }
  303. X  
  304. X  for ( i=set->af_nkeys; i>pos; i--)
  305. X    set->af_klist[i] = set->af_klist[i-1];
  306. X  set->af_klist[pos] = *key;
  307. X  set->af_nkeys++;
  308. X
  309. X  /* increase refcount */
  310. X  key->af_ldes->af_refcount++;
  311. X  VATTR(key).af_nlinks++;
  312. X
  313. X  return (AF_OK);
  314. X}
  315. X
  316. X/*================================================================
  317. X *    af_setrmkey -- remove key from set
  318. X *
  319. X *================================================================*/
  320. X
  321. XEXPORT af_setrmkey (set, key)
  322. X     Af_set *set;
  323. X     Af_key *key;
  324. X{
  325. X  register i;
  326. X  bool     found = FALSE;
  327. X
  328. X  if (af_settest (set))
  329. X    SFAIL ("setrmkey", "", AF_EINVSET, ERROR);
  330. X  if (af_keytest (key))
  331. X    SFAIL ("setrmkey", "", AF_EINVKEY, ERROR);
  332. X
  333. X  for (i=0; i<set->af_nkeys; i++)
  334. X    {
  335. X      if (!found)
  336. X    {
  337. X      if (!af_keycmp (&(set->af_klist[i]), key))
  338. X          found = TRUE;
  339. X    }
  340. X      else /* compress list */
  341. X    set->af_klist[i-1] = set->af_klist[i];
  342. X     }
  343. X  if (!found)
  344. X    SFAIL ("setrmkey", "", AF_ENOKEY, ERROR);
  345. X  set->af_nkeys--;
  346. X  VATTR(key).af_nlinks--;
  347. X  if (--key->af_ldes->af_refcount <= 0)
  348. X    (void) af_detlist (key->af_ldes);
  349. X
  350. X  return (AF_OK);
  351. X}
  352. X
  353. X/*================================================================
  354. X *    af_setposrmkey -- remove key (identified by position) from set
  355. X *
  356. X *================================================================*/
  357. X
  358. XEXPORT af_setposrmkey (set, pos)
  359. X     Af_set *set;
  360. X     int    pos;
  361. X{
  362. X  register i;
  363. X
  364. X  if (af_settest (set))
  365. X    SFAIL ("setposrmkey", "", AF_EINVSET, ERROR);
  366. X  if ((pos >= set->af_nkeys) || (pos < 0))
  367. X    SFAIL ("setposrmkey", "", AF_ENOPOS, ERROR);
  368. X
  369. X  VATTR((&(set->af_klist[pos]))).af_nlinks--;
  370. X  if (--(set->af_klist[pos].af_ldes)->af_refcount <= 0)
  371. X    (void) af_detlist (set->af_klist[pos].af_ldes);
  372. X
  373. X  for (i=pos; i<set->af_nkeys-1; i++)
  374. X    set->af_klist[i] = set->af_klist[i+1];
  375. X
  376. X  set->af_nkeys--;
  377. X
  378. X  return (AF_OK);
  379. X}
  380. X
  381. X/*================================================================
  382. X *    af_subset -- build subset
  383. X *
  384. X *================================================================*/
  385. X
  386. XEXPORT af_subset (set, attrbuf, newset)
  387. X     Af_set   *set, *newset;
  388. X     Af_attrs *attrbuf;
  389. X{
  390. X  register i, j=0, k=0;
  391. X  int match;
  392. X  Af_set tmpset;
  393. X
  394. X  if (af_settest (set))
  395. X    SFAIL ("subset", "", AF_EINVSET, ERROR);
  396. X
  397. X  /* allocate memory for new set */
  398. X  tmpset.af_setlen = set->af_nkeys;
  399. X  if ((tmpset.af_klist = (Af_key *)malloc ((unsigned) (tmpset.af_setlen * sizeof(Af_key)))) == (Af_key *)0)
  400. X    FAIL ("subset", "malloc", AF_ESYSERR, ERROR);
  401. X
  402. X  /* if there are no disqualifying attributes, add key to new set */
  403. X  for (i = 0; i < set->af_nkeys; i++)
  404. X    {
  405. X      /* if an attribute is set an does not match, continue with next key */
  406. X      /*** name ***/
  407. X      if ( (attrbuf->af_name[0] != '\0') &&
  408. X       (strcmp (attrbuf->af_name, VATTR((&(set->af_klist[i]))).af_name)) )
  409. X    continue;
  410. X
  411. X      /*** type ***/
  412. X      if ( (attrbuf->af_type[0] != '\0') &&
  413. X       (strcmp (attrbuf->af_type, NOTNIL(VATTR((&(set->af_klist[i]))).af_type))) )
  414. X    continue;
  415. X
  416. X      /*** syspath ***/
  417. X      if ( (attrbuf->af_syspath[0] != '\0') &&
  418. X       (strcmp (attrbuf->af_syspath, CATTR((&(set->af_klist[i]))).af_syspath)) )
  419. X    continue;
  420. X
  421. X      /*** generation number ***/
  422. X      if ( (attrbuf->af_gen != AF_NOVNUM) &&
  423. X       (attrbuf->af_gen != VATTR((&(set->af_klist[i]))).af_gen) )
  424. X    continue;
  425. X  
  426. X      /*** revision number ***/
  427. X      if ( (attrbuf->af_rev != AF_NOVNUM) &&
  428. X       (attrbuf->af_rev != VATTR((&(set->af_klist[i]))).af_rev) )
  429. X    continue;
  430. X
  431. X      /*** variant attribute ***/
  432. X      if ( (attrbuf->af_variant[0]) &&
  433. X       (strcmp (attrbuf->af_variant, NOTNIL(VATTR((&(set->af_klist[i]))).af_variant))) )
  434. X    continue;
  435. X
  436. X      /*** state ***/
  437. X      if ( (attrbuf->af_state != AF_NOSTATE) &&
  438. X       (attrbuf->af_state != VATTR((&(set->af_klist[i]))).af_state) )
  439. X    continue;
  440. X
  441. X      /*** owner ***/
  442. X      if ( (attrbuf->af_owner.af_username[0]) &&
  443. X       (strcmp (attrbuf->af_owner.af_username, CATTR((&(set->af_klist[i]))).af_ownname)) )
  444. X    continue;
  445. X      if ( (attrbuf->af_owner.af_userhost[0]) &&
  446. X       (strcmp (attrbuf->af_owner.af_userhost, CATTR((&(set->af_klist[i]))).af_ownhost)) )
  447. X    continue;
  448. X
  449. X      /*** author ***/
  450. X      if ( (attrbuf->af_author.af_username[0]) &&
  451. X       (strcmp (attrbuf->af_author.af_username, VATTR((&(set->af_klist[i]))).af_auname)) )
  452. X    continue;
  453. X      if ( (attrbuf->af_author.af_userhost[0]) &&
  454. X       (strcmp (attrbuf->af_author.af_userhost, VATTR((&(set->af_klist[i]))).af_auhost)) )
  455. X    continue;
  456. X
  457. X      /*** size ***/
  458. X      if ( (attrbuf->af_size != AF_NOSIZE) &&
  459. X       (attrbuf->af_size != VATTR((&(set->af_klist[i]))).af_fsize) )
  460. X    continue;
  461. X
  462. X      /*** mode ***/
  463. X      if ( (attrbuf->af_mode != AF_NOMODE) &&
  464. X       (attrbuf->af_mode != VATTR((&(set->af_klist[i]))).af_mode) )
  465. X    continue;
  466. X
  467. X      /*** locker ***/
  468. X      if ( (attrbuf->af_locker.af_username[0]) &&
  469. X       (strcmp (attrbuf->af_locker.af_username, NOTNIL(VATTR((&(set->af_klist[i]))).af_lckname))) )
  470. X    continue;
  471. X      if ( (attrbuf->af_locker.af_userhost[0]) &&
  472. X       (strcmp (attrbuf->af_locker.af_userhost, NOTNIL(VATTR((&(set->af_klist[i]))).af_lckhost))) )
  473. X    continue;
  474. X
  475. X      /*** date of last modification ***/
  476. X      if ( (attrbuf->af_mtime != AF_NOTIME) &&
  477. X       (attrbuf->af_mtime != VATTR((&(set->af_klist[i]))).af_mtime) )
  478. X    continue;
  479. X
  480. X      /*** date of last access ***/
  481. X      if ( (attrbuf->af_atime != AF_NOTIME) &&
  482. X       (attrbuf->af_atime != VATTR((&(set->af_klist[i]))).af_atime) )
  483. X    continue;
  484. X
  485. X      /*** date of last status change ***/
  486. X      if ( (attrbuf->af_ctime != AF_NOTIME) &&
  487. X       (attrbuf->af_ctime != VATTR((&(set->af_klist[i]))).af_ctime) )
  488. X    continue;
  489. X
  490. X      /*** saving date ***/
  491. X      if ( (attrbuf->af_stime != AF_NOTIME) &&
  492. X       (attrbuf->af_stime != VATTR((&(set->af_klist[i]))).af_stime) )
  493. X    continue;
  494. X
  495. X      /*** date of last lock change ***/
  496. X      if ( (attrbuf->af_ltime != AF_NOTIME) &&
  497. X       (attrbuf->af_ltime != VATTR((&(set->af_klist[i]))).af_ltime) )
  498. X    continue;
  499. X
  500. X      /*** user defined attributes ***/
  501. X      if (attrbuf->af_udattrs[0] != (char *)0)
  502. X    {
  503. X      /* if list of user defined attributes is not empty or there are */
  504. X                                                        /* attributes */
  505. X      match = TRUE;
  506. X      if ((attrbuf->af_udattrs[0][0] != '\0') ||
  507. X          (VATTR((&(set->af_klist[i]))).af_udanum != 0))
  508. X        {
  509. X          /* test all given entries */
  510. X          j=0;
  511. X          while ((attrbuf->af_udattrs[j] != (char *)0) 
  512. X             && (match = !af_match (attrbuf->af_udattrs[j],
  513. X             &(VATTR((&(set->af_klist[i]))).af_uhtab))))
  514. X        {
  515. X          j++;
  516. X        }
  517. X        } /* if */
  518. X      if (match == FALSE)
  519. X        continue;
  520. X    } /* if */
  521. X
  522. X
  523. X      /* add key to new set */
  524. X      tmpset.af_klist[k] = set->af_klist[i];
  525. X      /* increase number of links in list descriptor */
  526. X      (tmpset.af_klist[k].af_ldes)->af_refcount++;
  527. X      VATTR((&(tmpset.af_klist[k]))).af_nlinks++;
  528. X      k++;
  529. X
  530. X    } /* for */
  531. X  
  532. X  tmpset.af_nkeys = k;
  533. X
  534. X  /* if the resulting set shall be stored in the old set */
  535. X  if (set == newset)
  536. X    {
  537. X      (void) af_dropset (set);
  538. X      *set = tmpset;
  539. X    }
  540. X  else
  541. X    *newset = tmpset;
  542. X
  543. X  return (k);
  544. X}
  545. X
  546. X
  547. X/*================================================================
  548. X *    af_intersect -- build intersection of two sets
  549. X *
  550. X *================================================================*/
  551. X
  552. XEXPORT af_intersect (set1, set2, newset)
  553. X     Af_set *set1, *set2;
  554. X     Af_set *newset;
  555. X{
  556. X  register i, j, k;
  557. X  Af_set tmpset;
  558. X
  559. X  if (af_settest (set1) || af_settest (set2))
  560. X    SFAIL ("intersect", "", AF_EINVSET, ERROR);
  561. X
  562. X  /* allocate enough memory */
  563. X  if (set1->af_nkeys >= set2->af_nkeys)
  564. X    tmpset.af_setlen = set1->af_nkeys;
  565. X  else
  566. X    tmpset.af_setlen = set2->af_nkeys;
  567. X  if ((tmpset.af_klist = (Af_key *)malloc ((unsigned) (tmpset.af_setlen * sizeof(Af_key)))) == (Af_key *)0)
  568. X    FAIL ("intersect", "malloc", AF_ESYSERR, ERROR);
  569. X  /* build new set */
  570. X  k=0;
  571. X  for (i=0; i<set1->af_nkeys; i++)
  572. X    for (j=0; j<set2->af_nkeys; j++)
  573. X      {
  574. X    if (!af_keycmp (&(set1->af_klist[i]), &(set2->af_klist[j])))
  575. X      {
  576. X        tmpset.af_klist[k] = set1->af_klist[i];
  577. X        /* increase number of links in list descriptor */
  578. X        (tmpset.af_klist[k].af_ldes)->af_refcount++;
  579. X        VATTR((&(tmpset.af_klist[k]))).af_nlinks++;
  580. X        k++;
  581. X      }
  582. X      }
  583. X  tmpset.af_nkeys = k;
  584. X
  585. X  /* if the new set shall be stored in one of the old ones */
  586. X  if (newset == set1)
  587. X    {
  588. X      (void) af_dropset (set1);
  589. X      *set1 = tmpset;
  590. X    }
  591. X  else
  592. X    {
  593. X      if (newset == set2)
  594. X    {
  595. X      (void) af_dropset (set2);
  596. X      *set2 = tmpset;
  597. X    }
  598. X      else
  599. X    *newset = tmpset;
  600. X    }
  601. X
  602. X  return (k);
  603. X}
  604. X
  605. X/*================================================================
  606. X *    af_union -- build union of two sets
  607. X *
  608. X *================================================================*/
  609. X
  610. XEXPORT af_union (set1, set2, newset)
  611. X     Af_set *set1, *set2;
  612. X     Af_set *newset;
  613. X{
  614. X  register i, j, k;
  615. X  bool     dbl=FALSE;
  616. X  Af_set   tmpset;
  617. X
  618. X  if (af_settest (set1) || af_settest (set2))
  619. X    SFAIL ("union", "", AF_EINVSET, ERROR);
  620. X
  621. X  /* allocate enough memory */
  622. X  tmpset.af_setlen = set1->af_nkeys+set2->af_nkeys;
  623. X  if ((tmpset.af_klist = (Af_key *)malloc ((unsigned) (tmpset.af_setlen * sizeof(Af_key)))) == (Af_key *)0)
  624. X    FAIL ("union", "malloc", AF_ESYSERR, ERROR);
  625. X
  626. X  /* build new set */
  627. X  k=0;
  628. X  for (i=0; i<set1->af_nkeys; i++)
  629. X    {
  630. X      tmpset.af_klist[k] = set1->af_klist[i];
  631. X      /* increase number of links in list descriptor */
  632. X      (tmpset.af_klist[k].af_ldes)->af_refcount++;
  633. X      VATTR((&(tmpset.af_klist[k]))).af_nlinks++;
  634. X      k++;
  635. X    }
  636. X  for (j=0; j<set2->af_nkeys; j++)
  637. X    {
  638. X      for (i=0; i<set1->af_nkeys; i++)
  639. X    {
  640. X      if (!af_keycmp (&(tmpset.af_klist[i]), &(set2->af_klist[j])))
  641. X        dbl = TRUE;
  642. X    }
  643. X      if (dbl)
  644. X    dbl = FALSE;
  645. X      else
  646. X    {
  647. X      tmpset.af_klist[k] = set2->af_klist[j];
  648. X      /* increase number of links in list descriptor */
  649. X      (tmpset.af_klist[k].af_ldes)->af_refcount++;
  650. X      VATTR((&(tmpset.af_klist[k]))).af_nlinks++;
  651. X      k++;
  652. X    }
  653. X    }
  654. X  tmpset.af_nkeys = k;
  655. X
  656. X  /* if the new set shall be stored in one of the old ones */
  657. X  if (newset == set1)
  658. X    {
  659. X      (void) af_dropset (set1);
  660. X      *set1 = tmpset;
  661. X    }
  662. X  else
  663. X    {
  664. X      if (newset == set2)
  665. X    {
  666. X      (void) af_dropset (set2);
  667. X      *set2 = tmpset;
  668. X    }
  669. X      else
  670. X    *newset = tmpset;
  671. X    }
  672. X
  673. X  return (k);
  674. X}
  675. X
  676. X/*================================================================
  677. X *    af_diff -- build difference between two sets
  678. X *
  679. X *================================================================*/
  680. X
  681. XEXPORT af_diff (set1, set2, newset)
  682. X     Af_set *set1, *set2;
  683. X     Af_set *newset;
  684. X{
  685. X  register i, j, k;
  686. X  bool     found = FALSE;
  687. X  Af_set   tmpset;
  688. X
  689. X  if (af_settest (set1) || af_settest (set2))
  690. X    SFAIL ("diff", "", AF_EINVSET, ERROR);
  691. X
  692. X  /* allocate enough memory */
  693. X  tmpset.af_setlen = set1->af_nkeys;
  694. X  if ((tmpset.af_klist = (Af_key *)malloc ((unsigned) (tmpset.af_setlen * sizeof(Af_key)))) == (Af_key *)0)
  695. X    FAIL ("diff", "malloc", AF_ESYSERR, ERROR);
  696. X
  697. X  /* build new set */
  698. X  k=0;
  699. X  for (i=0; i<set1->af_nkeys; i++)
  700. X    {
  701. X      for (j=0; j<set2->af_nkeys; j++)
  702. X    {
  703. X      if (!af_keycmp (&(set1->af_klist[i]), &(set2->af_klist[j])))
  704. X        found = TRUE;
  705. X    }
  706. X      if (found)
  707. X    found = FALSE;
  708. X      else
  709. X    {
  710. X      tmpset.af_klist[k] = set1->af_klist[i];
  711. X      /* increase number of links in list descriptor */
  712. X      (tmpset.af_klist[k].af_ldes)->af_refcount++;
  713. X      VATTR((&(tmpset.af_klist[k]))).af_nlinks++;
  714. X      k++;
  715. X    }
  716. X    }
  717. X  tmpset.af_nkeys = k;
  718. X
  719. X  /* if the new set shall be stored in one of the old ones */
  720. X  if (newset == set1)
  721. X    {
  722. X      (void) af_dropset (set1);
  723. X      *set1 = tmpset;
  724. X    }
  725. X  else
  726. X    {
  727. X      if (newset == set2)
  728. X    {
  729. X      (void) af_dropset (set2);
  730. X      *set2 = tmpset;
  731. X    }
  732. X      else
  733. X    *newset = tmpset;
  734. X    }
  735. X
  736. X  return (k);
  737. X}
  738. END_OF_FILE
  739. if test 19377 -ne `wc -c <'src/afs/afsets.c'`; then
  740.     echo shar: \"'src/afs/afsets.c'\" unpacked with wrong size!
  741. fi
  742. # end of 'src/afs/afsets.c'
  743. fi
  744. if test -f 'src/vc/vldovl.c' -a "${1}" != "-c" ; then 
  745.   echo shar: Will not clobber existing file \"'src/vc/vldovl.c'\"
  746. else
  747. echo shar: Extracting \"'src/vc/vldovl.c'\" \(18709 characters\)
  748. sed "s/^X//" >'src/vc/vldovl.c' <<'END_OF_FILE'
  749. X/*
  750. X * Copyright (C) 1989, 1990 W. Koch, A. Lampen, A. Mahler, W. Obst,
  751. X *  and U. Pralle
  752. X * 
  753. X * This software is published on an as-is basis. There is ABSOLUTELY NO
  754. X * WARRANTY for any part of this software to work correctly or as described
  755. X * in the manuals. We do not accept any liability for any kind of damage
  756. X * caused by use of this software, such as loss of data, time, money, or 
  757. X * effort.
  758. X * 
  759. X * Permission is granted to use, copy, modify, or distribute any part of
  760. X * this software as long as this is done without asking for charge, and
  761. X * provided that this copyright notice is retained as part of the source
  762. X * files. You may charge a distribution fee for the physical act of
  763. X * transferring a copy, and you may at your option offer warranty
  764. X * protection in exchange for a fee.
  765. X * 
  766. X * Direct questions to: Tech. Univ. Berlin
  767. X *              Wilfried Koch
  768. X *              Sekr. FR 5-6 
  769. X *              Franklinstr. 28/29
  770. X *              D-1000 Berlin 10, West Germany
  771. X * 
  772. X *              Tel: +49-30-314-22972
  773. X *              E-mail: shape@coma.uucp or shape@db0tui62.bitnet
  774. X */
  775. X#ifndef lint
  776. Xstatic char *AFSid = "$Header: vldovl.c[3.10] Thu Feb 23 18:14:47 1989 axel@coma published $";
  777. X#ifdef CFFLGS
  778. Xstatic char *ConfFlg = CFFLGS;
  779. X    /* should be defined from within Makefile */
  780. X#endif
  781. X#endif
  782. X/*
  783. X * Log for /u/shape/dist-tape/src/vc/vldovl.c[3.4]
  784. X *     Thu Feb 23 18:14:48 1989 axel@coma published $
  785. X *  --- empty log message ---
  786. X *  vldovl.c[3.6] Thu Feb 23 18:14:48 1989 uli@coma published $
  787. X *  --- empty log message ---
  788. X *  vldovl.c[3.8] Thu Feb 23 18:14:48 1989 axel@coma published $
  789. X *  --- empty log message ---
  790. X *  vldovl.c[3.9] Thu Feb 23 18:14:48 1989 axel@coma save $
  791. X *  --- empty log message ---
  792. X *  vldovl.c[3.10] Thu Feb 23 18:14:48 1989 axel@coma published $
  793. X *  --- empty log message ---
  794. X */
  795. X
  796. X#include <stdio.h>
  797. X#include <strings.h>
  798. X#include <afs.h>
  799. X#include "vl.h"
  800. X
  801. Xextern int immediate_output;
  802. Xextern int version_number;
  803. X
  804. X/*
  805. X * Global variables
  806. X */
  807. X
  808. Xchar pathname_required = 0;
  809. Xextern char vl_cwd[];
  810. Xchar buf[1000];
  811. Xchar *pending_name;        /* Holds the name of a dir */
  812. Xint dir_pending = 0;
  813. X
  814. XAf_attrs AF_attrbuf;
  815. XAf_set AF_fileset;
  816. Xchar error_string[80];
  817. X
  818. Xvoid InitAttrs (AF_attrbuf, name)
  819. X     Af_attrs *AF_attrbuf;
  820. X     char *name;
  821. X     /*
  822. X      * Initializes the attribute buffer.
  823. X      */
  824. X     
  825. X{
  826. X  register int i;
  827. X  int vno;
  828. X  register char **udattrs;
  829. X  extern char *GetAuthoridFromAuthor(), *GetOwneridFromOwner(),
  830. X              *GetAuthorhostFromAuthor(), *GetOwnerhostFromOwner();
  831. X  char cstring[MAXNAMLEN], vstring[16];
  832. X
  833. X  af_initattrs (AF_attrbuf);
  834. X
  835. X  if (name && name[0] != '\0') {
  836. X    if (BoundVersion (name, cstring, vstring)) {
  837. X      /* This code kind of assumes, that directory names are not of */
  838. X      /* the kind 'dirname[2.9]' -- good luck! */
  839. X      vno = mkvno (vstring);
  840. X      AF_attrbuf->af_gen = gen(vno);
  841. X      AF_attrbuf->af_rev = rev(vno);
  842. X      (void)strcpy (AF_attrbuf->af_syspath, af_afpath (cstring));
  843. X      (void)strcpy (AF_attrbuf->af_name, af_afname (cstring));
  844. X      (void)strcpy (AF_attrbuf->af_type, af_aftype (cstring));
  845. X      /* No further options are considered in this case */
  846. X    }
  847. X    else {  /* no bound version notation (e.g. foo.c[4.3]) for 'name' */ 
  848. X      if (IsDirectory (name)) {
  849. X    (void)strcpy (AF_attrbuf->af_syspath, name);
  850. X      }
  851. X      else { /* 'name' is not a directory */
  852. X    (void)strcpy (AF_attrbuf->af_syspath, af_afpath (name));
  853. X    (void)strcpy (AF_attrbuf->af_name, af_afname (name));
  854. X    (void)strcpy (AF_attrbuf->af_type, af_aftype (name));
  855. X      }
  856. X    }
  857. X  }
  858. X  /* Invariant: syspath, name and type fields of AF_attrbuf initialized */
  859. X
  860. X  if (IsOptionSet(VL_O_UDAGIVEN)) {
  861. X    udattrs = GetUdattrs ();
  862. X    for (i = 0 ; udattrs[i] ; i++) {
  863. X      AF_attrbuf->af_udattrs[i] = udattrs[i];
  864. X    }
  865. X  }
  866. X
  867. X  if (IsOptionSet(VL_O_VERSIONNUM)) {
  868. X    if (! (IsOptionSet(VL_O_HISTLOG) || IsOptionSet(VL_O_LOGMSG))) {
  869. X      if ((i = gen(version_number)) >= 0) {
  870. X    AF_attrbuf->af_gen = i;
  871. X      }
  872. X      if ((i = rev(version_number)) >= 0) {
  873. X    AF_attrbuf->af_rev = i;
  874. X      }
  875. X    }
  876. X  }
  877. X
  878. X  if (IsOptionSet(VL_O_AUTHOR)) {
  879. X    (void)strcpy (AF_attrbuf->af_author.af_username, GetAuthoridFromAuthor());
  880. X    (void)strcpy (AF_attrbuf->af_author.af_userhost, GetAuthorhostFromAuthor());
  881. X  }
  882. X
  883. X  if (IsOptionSet(VL_O_OWNER)) {
  884. X    (void)strcpy (AF_attrbuf->af_owner.af_username, GetOwneridFromOwner());
  885. X    (void)strcpy (AF_attrbuf->af_owner.af_userhost, GetOwnerhostFromOwner());
  886. X  }
  887. X  return;
  888. X}
  889. X
  890. Xint PrintUDA (attrbuf)
  891. X     Af_attrs *attrbuf;
  892. X{
  893. X  register char *cp;
  894. X  register int i;
  895. X  register char Checkbyte;
  896. X  register first_uda_printed;
  897. X  
  898. X  if ( (attrbuf->af_udattrs == NULL) || (attrbuf->af_udattrs[0] == '\0'))
  899. X    return 0;            /* no user defined attributes */
  900. X  
  901. X  
  902. X  if (IsOptionSet(VL_O_LONGOUTPUT)) {
  903. X    PrintLongVinfo (attrbuf); printf (":\n");
  904. X  }
  905. X  else {
  906. X    PrintShortVinfo (attrbuf); printf (":");
  907. X  }
  908. X
  909. X  if (IsOptionSet(VL_O_LISTUDALONG)) {
  910. X    Checkbyte = '\0';
  911. X  }
  912. X  else {
  913. X    Checkbyte = '=';
  914. X  }
  915. X
  916. X  first_uda_printed = 0;    /* nothing yet printed */
  917. X  
  918. X  for (i = 0; attrbuf->af_udattrs[i]; i++){
  919. X    cp = attrbuf->af_udattrs[i];
  920. X
  921. X    if (!IsOptionSet(VL_O_LISTHIDDENUDAS) && IsHiddenUda (cp))
  922. X      continue;
  923. X    if (first_uda_printed) {
  924. X      (void)putchar (';');        /* seperate udas by ';' */
  925. X    }
  926. X    else {
  927. X      (void)putchar (' ');
  928. X      first_uda_printed = 1;
  929. X    }
  930. X    
  931. X    while (cp && *cp && *cp != Checkbyte) {
  932. X      if (*cp == AF_UDAVALDEL) {
  933. X    (void)putchar (',');        /* seperate values of uda by ','
  934. X                 */
  935. X      }
  936. X      else {
  937. X    (void)putchar (*cp);
  938. X      }
  939. X      cp++;
  940. X    }
  941. X  }
  942. X  (void)putchar ('\n');
  943. X  (void)fflush (stdout);
  944. X  return 1;
  945. X}
  946. X
  947. XPrintVinfo (attrbuf)
  948. X     Af_attrs *attrbuf;
  949. X{
  950. X  if (IsOptionSet(VL_O_LISTUDA|VL_O_LISTUDALONG)) {
  951. X    return PrintUDA (attrbuf);
  952. X  }
  953. X  
  954. X  if (IsOptionSet(VL_O_LONGOUTPUT)) {
  955. X    PrintLongVinfo (attrbuf);
  956. X    return 1;
  957. X  }
  958. X
  959. X  PrintShortVinfo (attrbuf);
  960. X  return 1;
  961. X}
  962. X
  963. XPrintShortVinfo (attrbuf)
  964. X     Af_attrs *attrbuf;
  965. X{
  966. X  if (immediate_output) {    /* set during option scanning */
  967. X    if (dir_pending) {    /*  now we can print the pending dir name */
  968. X      printf ("\n%s:\n", pending_name ? pending_name : ""); 
  969. X      dir_pending = 0;
  970. X    }
  971. X    
  972. X    printf ("%s%s%s%s%s%s%s%s", 
  973. X        (pathname_required) ? attrbuf->af_syspath : "",
  974. X        (pathname_required) ? "/" : "",
  975. X        attrbuf->af_name,
  976. X        (attrbuf->af_type && (attrbuf->af_type[0] != '\0') ? "." : ""),
  977. X        attrbuf->af_type,
  978. X        GetVersionId (attrbuf->af_gen, attrbuf->af_rev),
  979. X        (IsOptionSet(VL_O_VERSIONSTATE)) ? " -> " : "",
  980. X        (IsOptionSet(VL_O_VERSIONSTATE)) ? GetVersionState (attrbuf->af_state)
  981. X        : "");
  982. X  }
  983. X  else {
  984. X    (void)sprintf (buf, "%s%s%s%s%s%s%s%s", 
  985. X         (pathname_required) ? attrbuf->af_syspath : "",
  986. X         (pathname_required) ? "/" : "",
  987. X         attrbuf->af_name,
  988. X         (attrbuf->af_type && (attrbuf->af_type[0] != '\0') ? "." : ""),
  989. X         attrbuf->af_type,
  990. X         GetVersionId (attrbuf->af_gen, attrbuf->af_rev),
  991. X         (IsOptionSet(VL_O_VERSIONSTATE)) ? " -> " : "",
  992. X         (IsOptionSet(VL_O_VERSIONSTATE)) ? GetVersionState (attrbuf->af_state)
  993. X         : "");
  994. X    
  995. X    AddEntry (buf);
  996. X  }
  997. X}
  998. X
  999. XPrintLongVinfo (attrbuf)
  1000. X     Af_attrs *attrbuf;
  1001. X{
  1002. X  if (immediate_output) {    /* set during option scanning */
  1003. X    char *p1 = NULL, *p2 = NULL;
  1004. X    if (dir_pending) {    /*  now we can print the pending dir name */
  1005. X      printf ("\n%s:\n", pending_name ? pending_name : ""); 
  1006. X      dir_pending = 0;
  1007. X    }
  1008. X/* This is the place to put out the name of eventual lockholders */
  1009. X    printf ("%s %s %s %s %8d %s %s%s%s%s%s%s",
  1010. X        GetMode (attrbuf->af_mode),
  1011. X        GetVersionState (attrbuf->af_state),
  1012. X        p1=GetUserInfo (&(attrbuf->af_owner)),
  1013. X        (IsOptionSet(VL_O_AUTHOR))
  1014. X        ? p2=GetUserInfo (&(attrbuf->af_author)) : "",
  1015. X        attrbuf->af_size,
  1016. X        (attrbuf->af_state > AF_BUSY) ? GetDate (attrbuf->af_stime)
  1017. X        : GetDate (attrbuf->af_mtime),
  1018. X        (pathname_required) ? attrbuf->af_syspath : "",
  1019. X        (pathname_required) ? "/" : "",
  1020. X        attrbuf->af_name,
  1021. X        (attrbuf->af_type && (attrbuf->af_type[0] != '\0')) ?  "."
  1022. X        : "",
  1023. X        attrbuf->af_type,
  1024. X        GetVersionId (attrbuf->af_gen, attrbuf->af_rev));
  1025. X    if (p1) free (p1);
  1026. X    if (p2) free (p2);
  1027. X  }
  1028. X  else {
  1029. X    (void)sprintf (buf, "%s %s %s %s %8d %s %s%s%s%s%s%s",
  1030. X         GetMode (attrbuf->af_mode),
  1031. X         GetVersionState (attrbuf->af_state),
  1032. X         GetUserInfo (&(attrbuf->af_owner)),
  1033. X         (IsOptionSet(VL_O_AUTHOR))
  1034. X         ? GetUserInfo (&(attrbuf->af_author))  : "",
  1035. X         attrbuf->af_size,
  1036. X         (attrbuf->af_state > AF_BUSY) ? GetDate (attrbuf->af_stime)
  1037. X         : GetDate (attrbuf->af_mtime),
  1038. X         (pathname_required) ? attrbuf->af_syspath : "",
  1039. X         (pathname_required) ? "/" : "",
  1040. X         attrbuf->af_name,
  1041. X         (attrbuf->af_type && (attrbuf->af_type[0] != '\0')) ?  "."
  1042. X         : "",
  1043. X         attrbuf->af_type,
  1044. X         GetVersionId (attrbuf->af_gen, attrbuf->af_rev));
  1045. X    AddEntry (buf);
  1046. X  }
  1047. X}
  1048. X
  1049. XReportVersionInfo (name)
  1050. X     char *name;
  1051. X
  1052. X     /*
  1053. X      * Returns 0 if no info for name found, otherwise 1;
  1054. X      */
  1055. X{
  1056. X  register int i;
  1057. X  int numhits, Bnumhits=0;
  1058. X  int retcode = 1, rc;        /* assume failure */
  1059. X  char *cp;
  1060. X  Af_set AF_sfileset, AF_bfileset;
  1061. X  Af_key fkey;
  1062. X
  1063. X  af_initset (&AF_sfileset);
  1064. X  af_initset (&AF_bfileset);
  1065. X  if (name && *name) {
  1066. X    cp = af_afpath(name);
  1067. X    if ( (! IsDirectory (name))
  1068. X    && *cp
  1069. X    && strcmp (cp, vl_cwd)) {
  1070. X      /*
  1071. X       * name is a normal file and is not in current working dir
  1072. X       * require pathname on output
  1073. X       */
  1074. X      pathname_required = 1;
  1075. X    }
  1076. X    else {
  1077. X      pathname_required = 0;
  1078. X    }
  1079. X  }
  1080. X  if (IsOptionSet(VL_O_LASTVERS)) {
  1081. X    rc=af_getkey (af_afpath (name), af_afname (name), af_aftype (name),
  1082. X           AF_LASTVERS, AF_LASTVERS, "", &fkey);
  1083. X    if (rc < 0) {
  1084. X      numhits = 0;
  1085. X    }
  1086. X    else {
  1087. X      af_setaddkey (&AF_sfileset, 0, &fkey);
  1088. X      numhits = 1;
  1089. X    }
  1090. X  }
  1091. X  else {
  1092. X    InitAttrs (&AF_attrbuf, name);
  1093. X    
  1094. X    /* now go, and get some info.... */
  1095. X    if ((numhits = af_find (&AF_attrbuf, &AF_sfileset)) == -1) {
  1096. X      (void)sprintf (error_string,
  1097. X           "%s: in ReportVersionInfo(): af_find (%s)",
  1098. X           GetProgramName (), name);
  1099. X      af_perror (error_string);
  1100. X      return (1); /*exit (1);*/
  1101. X    }
  1102. X    if (IsOptionSet(VL_O_LISTBINARY)) {
  1103. X      if ((Bnumhits = af_bpfind (&AF_attrbuf, &AF_bfileset)) == -1) {
  1104. X    (void)sprintf (error_string,
  1105. X         "%s: in ReportVersionInfo(): af_find (%s)",
  1106. X         GetProgramName (), name);
  1107. X    af_perror (error_string);
  1108. X    return (1); /*exit (1);*/
  1109. X      }
  1110. X    }
  1111. X  }
  1112. X  if (af_union (&AF_sfileset, &AF_bfileset, &AF_fileset) < 0) {
  1113. X    af_perror ("af_union");
  1114. X    return 1;
  1115. X  }
  1116. X  numhits += Bnumhits;
  1117. X  af_dropset (&AF_sfileset);
  1118. X  af_dropset (&AF_bfileset);
  1119. X  /* nothing found ? */
  1120. X  if (numhits == 0) {
  1121. X    if (!IsOptionSet(VL_O_BEQUIET)) {
  1122. X      if (name && *name) {
  1123. X    if (! FileExists (name)) {
  1124. X      printf ("%s: %s: nothing appropriate found\n", GetProgramName (), name);
  1125. X    }
  1126. X      }
  1127. X    }
  1128. X    VinfoCleanup ();
  1129. X    return 1;            /* report failure */
  1130. X  }
  1131. X
  1132. X  if ((*name != '\0') && IsDirectory (name)) {
  1133. X    if (immediate_output) {
  1134. X      /*
  1135. X       * dir name must be printed, iff
  1136. X       * something is found. But we can determine
  1137. X       * this not yet.
  1138. X       */
  1139. X      dir_pending = 1;
  1140. X      pending_name = name;
  1141. X    }
  1142. X    else
  1143. X      AddClist (name);
  1144. X  }
  1145. X  
  1146. X  /*
  1147. X   * sort by name and version number. Busy version first then
  1148. X   * versions with increasing version numbers.
  1149. X   */
  1150. X
  1151. X  if (af_sortset (&AF_fileset, AF_ATTHUMAN) == -1) { 
  1152. X    (void)sprintf (error_string,
  1153. X         "%s: in ReportVersionInfo(): af_sortset by AF_ATTHIMAN",
  1154. X         GetProgramName);
  1155. X    af_perror (error_string);
  1156. X    exit (1);
  1157. X  }
  1158. X  
  1159. X  for (i = 0; i < AF_fileset.af_nkeys; i++) {
  1160. X    if (af_gattrs (&(AF_fileset.af_klist[i]), &AF_attrbuf) == -1) {
  1161. X      (void)sprintf (error_string, "%s: in ReportVersionInfo(): af_gattrs");
  1162. X      af_perror (error_string);
  1163. X      exit (1);
  1164. X    }
  1165. X    else {
  1166. X      if (IsHiddenFile(&AF_attrbuf) && !IsOptionSet(VL_O_LISTHIDDEN))
  1167. X    continue;
  1168. X
  1169. X      if (IsOptionSet(VL_O_STATEGIVEN)) {
  1170. X    if (!MatchesVersionStates (&AF_attrbuf))
  1171. X      continue;
  1172. X      }
  1173. X      
  1174. X      if (!IsOptionSet(VL_O_BEQUIET)) {
  1175. X    if (IsOptionSet(VL_O_LOGMSG)) {
  1176. X      if (IsInHistoryLogMsgList (&AF_attrbuf)) {
  1177. X        if (PrintVinfo (&AF_attrbuf)) {
  1178. X          (void)putchar (':'); (void)putchar ('\n');
  1179. X          PrintLogMsg (&(AF_fileset.af_klist[i]));
  1180. X          retcode = 0;    /* success */
  1181. X        }
  1182. X      }
  1183. X    }
  1184. X    else {
  1185. X      (void)PrintVinfo (&AF_attrbuf);
  1186. X      retcode = 0;    /* success */
  1187. X    }
  1188. X      }
  1189. X    }
  1190. X  }
  1191. X/*  VinfoCleanup (); */
  1192. X  return retcode;
  1193. X}
  1194. X
  1195. XInitReportVersion ()
  1196. X{
  1197. X  InitCList ();
  1198. X}
  1199. X
  1200. Xint PrintLogMsg (key)
  1201. X     Af_key *key;
  1202. X{
  1203. X  register char *logmsg;
  1204. X  
  1205. X  if ((logmsg = af_rnote (key)) == NULL) {
  1206. X    (void)sprintf (error_string, "%s: af_rnote", GetProgramName ());
  1207. X    af_perror (error_string);
  1208. X    exit (1);
  1209. X  }
  1210. X
  1211. X  printf ("%s", logmsg);
  1212. X  if (logmsg[strlen(logmsg)-1] != '\n') {
  1213. X    (void)putchar ('\n');
  1214. X    (void)fflush (stdout);
  1215. X  }
  1216. X  free (logmsg);
  1217. X
  1218. X}
  1219. X
  1220. Xint IsInHistoryLogMsgList (attrbuf)
  1221. X     Af_attrs *attrbuf;
  1222. X{
  1223. X  if (attrbuf->af_state == AF_BUSY)
  1224. X    return 0; /* is busy version */
  1225. X  if (IsOptionSet(VL_O_HISTLOG) &&
  1226. X      ! IsOptionSet(VL_O_VERSIONNUM)) 
  1227. X    return 1;
  1228. X
  1229. X  if (!IsOptionSet(VL_O_HISTLOG|VL_O_VERSIONNUM))
  1230. X    return 1;
  1231. X  else {
  1232. X    if (IsOptionSet(VL_O_HISTLOGPLUS)) {
  1233. X      if (attrbuf->af_gen > gen(version_number))
  1234. X    return 1;
  1235. X      if ((gen(version_number) == attrbuf->af_gen) &&
  1236. X      (attrbuf->af_rev > rev(version_number)))
  1237. X    return 1;
  1238. X    }
  1239. X    else {
  1240. X      if (attrbuf->af_gen < gen(version_number))
  1241. X    return 1;
  1242. X      if ((gen(version_number) == attrbuf->af_gen) &&
  1243. X      (attrbuf->af_rev < rev(version_number)))
  1244. X    return 1;
  1245. X    }
  1246. X    if ((gen(version_number) == attrbuf->af_gen) &&
  1247. X    (rev(version_number) == attrbuf->af_rev)) return 1;
  1248. X  }
  1249. X  return 0;
  1250. X}
  1251. X
  1252. Xstruct entry {
  1253. X  char *repr;
  1254. X  struct entry *next;
  1255. X};
  1256. X
  1257. Xstruct clist {            /* column list */
  1258. X  char *dir;            /* name of dir */
  1259. X  struct entry *entry;
  1260. X  struct clist *next;
  1261. X};
  1262. X
  1263. Xstruct clist *clistroot;
  1264. Xstruct clist *curclist;
  1265. Xstruct entry *curentry;
  1266. X
  1267. XInitCList ()
  1268. X{
  1269. X  if ((clistroot = (struct clist*) malloc (sizeof (struct clist))) == NULL) {
  1270. X    (void)strcpy (error_string, "in InitClist (): malloc,1");
  1271. X    perror (error_string);
  1272. X    exit (1);
  1273. X  }
  1274. X
  1275. X  clistroot->dir = NULL;    /* has never a name */
  1276. X
  1277. X/*  if ((clistroot->next = (struct clist*) malloc (sizeof (struct clist)))
  1278. X      == NULL) {
  1279. X    (void)strcpy (error_string, "in InitClist (): malloc,2");
  1280. X    perror (error_string);
  1281. X    exit (1);
  1282. X  }
  1283. X  */  
  1284. X  clistroot->next = NULL;
  1285. X  curclist = clistroot;
  1286. X  
  1287. X  if ((curentry = (struct entry*) malloc (sizeof (struct entry))) == NULL) {
  1288. X    (void)strcpy (error_string, "in InitClist (): malloc,3");
  1289. X    perror (error_string);
  1290. X    exit (1);
  1291. X  }
  1292. X  curentry->repr = NULL;
  1293. X  curentry->next = NULL;
  1294. X
  1295. X  clistroot->entry = curentry;
  1296. X}
  1297. X
  1298. XAddClist (name) 
  1299. X     char *name;
  1300. X{
  1301. X  struct clist *this_clist;
  1302. X
  1303. X  if ((this_clist = (struct clist*) malloc (sizeof (struct clist))) == NULL) {
  1304. X    (void)strcpy (error_string, "in AddCList (): malloc,1");
  1305. X    perror (error_string);
  1306. X    exit (1);
  1307. X  }
  1308. X
  1309. X  if ((this_clist->dir = malloc ((unsigned)(strlen (name)+1))) == NULL) {
  1310. X    (void)strcpy (error_string, "in AddCList (): malloc,2");
  1311. X    perror (error_string);
  1312. X    exit (1);
  1313. X  }
  1314. X
  1315. X  if ((this_clist->entry = (struct entry*) malloc (sizeof (struct entry)))
  1316. X      == NULL) {
  1317. X    (void)strcpy (error_string, "in AddCList (): malloc,2");
  1318. X    perror (error_string);
  1319. X    exit (1);
  1320. X  }
  1321. X      
  1322. X  (void)strcpy (this_clist->dir, name);
  1323. X  this_clist->next = NULL;
  1324. X  curentry = this_clist->entry;
  1325. X  curentry->repr = NULL;
  1326. X  curentry->next = NULL;
  1327. X
  1328. X  curclist->next = this_clist;
  1329. X  curclist = this_clist;
  1330. X  
  1331. X}
  1332. X  
  1333. XAddEntry (str)
  1334. X     char *str;
  1335. X{
  1336. X  struct entry* this_entry;
  1337. X
  1338. X  if ((curentry->repr = malloc ((unsigned)(strlen (str)+1))) == NULL) {
  1339. X    (void)strcpy (error_string, "in AddEntry (): malloc,2");
  1340. X    perror (error_string);
  1341. X    exit (1);
  1342. X  }
  1343. X
  1344. X  (void)strcpy (curentry->repr, str);
  1345. X
  1346. X  if ((this_entry = (struct entry*) malloc (sizeof (struct entry))) == NULL) {
  1347. X    (void)strcpy (error_string, "in AddEntry (): malloc,1");
  1348. X    perror (error_string);
  1349. X    exit (1);
  1350. X  }
  1351. X
  1352. X  this_entry->repr = NULL;
  1353. X  this_entry->next = NULL;
  1354. X  curentry->next = this_entry;
  1355. X  curentry = this_entry;
  1356. X}
  1357. X
  1358. Xint computemaxlength (root)
  1359. X  struct entry *root;
  1360. X{
  1361. X  struct entry *this_entry;
  1362. X  int length = 0, maxlength = 0;
  1363. X  
  1364. X  if (!root) return 0;
  1365. X
  1366. X  for (this_entry = root;
  1367. X       this_entry->repr && this_entry->next;
  1368. X       this_entry = this_entry->next) {
  1369. X    length = strlen (this_entry->repr);
  1370. X    if (length > maxlength) {
  1371. X      maxlength = length;
  1372. X    }
  1373. X  }
  1374. X  return maxlength;
  1375. X}
  1376. X
  1377. XPrintList (root, wordsperline, colwidth, newline_required, group_it)
  1378. X     struct clist *root;
  1379. X     int wordsperline, colwidth, newline_required, group_it;
  1380. X{
  1381. X  struct entry *this_entry;
  1382. X  int nwordsprinted = 0;    /* number of words per line yet printed */
  1383. X  int ntabs = 0;
  1384. X  int length;
  1385. X
  1386. X  if (/*root->entry && */root->entry->repr) {
  1387. X    if (root->dir) {
  1388. X      if (newline_required) (void)putchar ('\n');
  1389. X      
  1390. X      printf ("%s:\n", root->dir);
  1391. X    }
  1392. X  }
  1393. X  
  1394. X  if (!group_it) {
  1395. X    for (this_entry = root->entry;
  1396. X     this_entry->repr && this_entry->next;
  1397. X     this_entry = this_entry->next) {
  1398. X      printf ("%s\n", this_entry->repr);
  1399. X    }
  1400. X  }
  1401. X  else {
  1402. X    for (this_entry = root->entry;
  1403. X     this_entry->repr && this_entry->next;
  1404. X     this_entry = this_entry->next) {
  1405. X      nwordsprinted++;
  1406. X      if (!(nwordsprinted % wordsperline)) { /* if last word in this line */
  1407. X    printf ("%s\n", this_entry->repr);
  1408. X      }
  1409. X      else {
  1410. X    printf ("%s", this_entry->repr);
  1411. X    
  1412. X    /* compute #tabs to get to the next word position */
  1413. X    length = strlen (this_entry->repr);
  1414. X    ntabs = (colwidth - length) / 8;
  1415. X    if ((colwidth - length) % 8)
  1416. X      ntabs++;
  1417. X    
  1418. X    while (ntabs--) (void)putchar ('\t');      
  1419. X      }
  1420. X    }
  1421. X    if (nwordsprinted % wordsperline) printf ("\n");
  1422. X  }
  1423. X}
  1424. X
  1425. XFlushIt (root)
  1426. X     struct clist *root;
  1427. X{
  1428. X  struct clist *this_clist;
  1429. X  int colwidth = 0, wordsperline = 0;
  1430. X  int maxlength = 0, newline_required = 0;
  1431. X  
  1432. X  for (this_clist = root; this_clist; this_clist = this_clist->next) {
  1433. X
  1434. X    if (this_clist->entry && (this_clist->entry->repr == (char *) NULL))
  1435. X      continue;            /* skip empty list */
  1436. X
  1437. X    if (multicol_output_is_possible ()) {
  1438. X      /* compute length of longest word in this list */
  1439. X      maxlength = computemaxlength (this_clist->entry);
  1440. X      
  1441. X      /* compute length to next tab stop */
  1442. X      colwidth = (maxlength / 8) + 1;
  1443. X      colwidth *= 8;
  1444. X      
  1445. X      /* compute # words that fit in a line */
  1446. X#define maxcol 80
  1447. X      if (!(wordsperline = maxcol / colwidth)) wordsperline++;
  1448. X      
  1449. X    }
  1450. X    
  1451. X    PrintList (this_clist, wordsperline, colwidth, newline_required,
  1452. X           multicol_output_is_possible ());
  1453. X    newline_required++;
  1454. X  }
  1455. X}
  1456. X
  1457. Xvoid FlushInfo ()
  1458. X{
  1459. X  if (!immediate_output)
  1460. X    FlushIt (clistroot); /* Print now */
  1461. X}
  1462. END_OF_FILE
  1463. if test 18709 -ne `wc -c <'src/vc/vldovl.c'`; then
  1464.     echo shar: \"'src/vc/vldovl.c'\" unpacked with wrong size!
  1465. fi
  1466. # end of 'src/vc/vldovl.c'
  1467. fi
  1468. echo shar: End of archive 21 \(of 33\).
  1469. cp /dev/null ark21isdone
  1470. MISSING=""
  1471. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 ; do
  1472.     if test ! -f ark${I}isdone ; then
  1473.     MISSING="${MISSING} ${I}"
  1474.     fi
  1475. done
  1476. if test "${MISSING}" = "" ; then
  1477.     echo You have unpacked all 33 archives.
  1478.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1479. else
  1480.     echo You still need to unpack the following archives:
  1481.     echo "        " ${MISSING}
  1482. fi
  1483. ##  End of shell archive.
  1484. exit 0
  1485.