[comp.sources.unix] v19i034: A software configuration management system, Part21/33

rsalz@uunet.uu.net (Rich Salz) (06/05/89)

Submitted-by: Axel Mahler <unido!coma!axel>
Posting-number: Volume 19, Issue 34
Archive-name: shape/part21



#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 21 (of 33)."
# Contents:  src/afs/afsets.c src/vc/vldovl.c
# Wrapped by rsalz@papaya.bbn.com on Thu Jun  1 19:27:13 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'src/afs/afsets.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/afs/afsets.c'\"
else
echo shar: Extracting \"'src/afs/afsets.c'\" \(19377 characters\)
sed "s/^X//" >'src/afs/afsets.c' <<'END_OF_FILE'
X/*
X * Copyright (C) 1989, 1990 W. Koch, A. Lampen, A. Mahler, W. Obst,
X *  and U. Pralle
X * 
X * This software is published on an as-is basis. There is ABSOLUTELY NO
X * WARRANTY for any part of this software to work correctly or as described
X * in the manuals. We do not accept any liability for any kind of damage
X * caused by use of this software, such as loss of data, time, money, or 
X * effort.
X * 
X * Permission is granted to use, copy, modify, or distribute any part of
X * this software as long as this is done without asking for charge, and
X * provided that this copyright notice is retained as part of the source
X * files. You may charge a distribution fee for the physical act of
X * transferring a copy, and you may at your option offer warranty
X * protection in exchange for a fee.
X * 
X * Direct questions to: Tech. Univ. Berlin
X * 		     Wilfried Koch
X * 		     Sekr. FR 5-6 
X * 		     Franklinstr. 28/29
X * 		     D-1000 Berlin 10, West Germany
X * 
X * 		     Tel: +49-30-314-22972
X * 		     E-mail: shape@coma.uucp or shape@db0tui62.bitnet
X */
X/*LINTLIBRARY*/
X/*
X *	Shape/AFS
X *
X *	afsets.c -- Operations on keysets
X *
X *	Author: Andreas Lampen, TU-Berlin (andy@coma.UUCP)
X *					  (andy@db0tui62.BITNET)
X *
X *	$Header: afsets.c[1.3] Wed Feb 22 16:27:56 1989 andy@coma published $
X *
X *	EXPORT:
X *	af_initset -- initialize set descriptor
X *      af_copyset -- copy sets
X *	af_nrofkeys -- return number of keys in set
X *	af_sortset -- sort set by attribute
X *	af_dropset -- drop set
X *      af_setgkey -- get key from set
X *	af_setaddkey -- add key to set
X *      af_setrmkey -- remove key from set
X *      af_setposrmkey -- remove key (identified by position) from set
X *      af_subset -- build subset
X *      af_intersect -- build intersection of two sets
X *      af_union -- build union of two sets
X *      af_diff -- build difference between two sets
X */
X
X#include <stdio.h>
X#include <string.h>
X#ifdef SUNOS_4_0
X#include <strings.h>
X#endif
X
X#include "typeconv.h"
X#include "afsys.h"
X#include "afs.h"
X
Xchar *malloc(), *realloc();
X
X/*================================================================
X *	af_settest -- test plausibility of set descriptor
X *                    returnes TRUE (ERROR) if set descr. is invalid,
X *                    otherwise FALSE (AF_OK).
X *
X *================================================================*/
X
XLOCAL af_settest (set)
X     Af_set *set;
X{
X  if ((set->af_nkeys < 0) || (set->af_setlen < 0))
X    return (ERROR);
X  /* if set is not empty, test if first key is valid */
X  if (set->af_nkeys >= 1)
X    if (af_keytest (&(set->af_klist[0])))
X      return (ERROR);
X
X  return (AF_OK);
X}
X
X/*================================================================
X *	af_initset -- initialize set descriptor
X *
X *================================================================*/
X
XEXPORT af_initset (set)
X     Af_set *set;
X{
X  set->af_nkeys = 0;
X  set->af_setlen = 0;
X  set->af_klist = (Af_key *)0;
X}
X
X/*================================================================
X *	af_copyset -- copy sets
X *
X *================================================================*/
X
XEXPORT af_copyset (set1, set2)
X     Af_set *set1, *set2;
X{
X  int i;
X
X  if (af_settest (set1) || af_settest (set2))
X    SFAIL ("copyset", "", AF_EINVSET, ERROR);
X
X  /* allocate memory for new set (incl. space for additional element) */
X  set2->af_setlen = set1->af_nkeys + 1;
X  if ((set2->af_klist = (Af_key *)malloc ((unsigned) (set2->af_setlen * sizeof(Af_key)))) == (Af_key *)0)
X    FAIL ("copyset", "malloc", AF_ESYSERR, ERROR);
X
X  /* do copying */
X  for (i=0; i<set1->af_nkeys; i++)
X    {
X      set2->af_klist[i] = set1->af_klist[i];
X      /* increase refcount in list descriptor */
X      VATTR((&(set2->af_klist[i]))).af_nlinks++;
X      (set2->af_klist[i].af_ldes)->af_refcount++;
X    }
X  set2->af_nkeys = set1->af_nkeys;
X  return (set2->af_nkeys);
X}
X
X/*================================================================
X *	af_nrofkeys -- return number of keys in set
X *
X *================================================================*/
X
XEXPORT af_nrofkeys (set)
X     Af_set *set;
X{
X  if (af_settest (set))
X    SFAIL ("nrofkeys", "", AF_EINVSET, ERROR);
X  return (set->af_nkeys);
X}
X
X/*================================================================
X *	af_sortset -- sort set by attribute
X *
X *================================================================*/
X
Xextern struct cmpfun { int (*func) (); };
X
Xextern struct cmpfun af_cmpfuncts[];
X
Xextern char *af_attrlist[], af_udaname[];
X
XEXPORT af_sortset (set, attr)
X     Af_set *set;
X     char   *attr;
X{
X  int hi = AF_ATTNUM-1, lo=0, anum, res, af_cmpuda();
X
X  if (af_settest (set))
X    SFAIL ("sortset", "", AF_EINVSET, ERROR);
X  if (!attr)
X    SFAIL ("sortset", "invalid attribute name", AF_EMISC, ERROR);
X
X  /* get attribute number (binary search) */
X  anum = (hi+lo)/2;
X  while (hi >= lo)
X    {
X      res = strcmp (attr, af_attrlist[anum]);
X      if (res == 0)
X	break;
X      if (res < 0)
X	hi = anum - 1;
X      else lo = anum + 1;
X      anum = (hi+lo)/2;
X    }
X  /* attribute names, that are not in the list of standard attributes */
X  /* are assumed to be "user defined attributes" */
X  if (res != 0)
X    {
X      (void) strcpy (af_udaname, attr);
X      qsort ((char *)set->af_klist, set->af_nkeys, sizeof(Af_key), af_cmpuda); 
X    }
X  else
X    {
X      (void) strcpy (af_udaname, attr); 
X      qsort ((char *)set->af_klist, set->af_nkeys, sizeof(Af_key), af_cmpfuncts[anum].func); 
X    }
X  return (AF_OK);
X}
X
X/*================================================================
X *	af_dropset -- drop set
X *
X *================================================================*/
X
XEXPORT af_dropset (set)
X     Af_set *set;
X{
X  register i;
X
X  if (af_settest (set))
X    SFAIL ("dropset", "", AF_EINVSET, ERROR);
X
X  for (i=0; i<set->af_nkeys; i++)
X    {
X      /* decrease reference count in corresponding archive */
X      VATTR((&(set->af_klist[i]))).af_nlinks--;
X      if (--(set->af_klist[i].af_ldes)->af_refcount <= 0)
X	(void) af_detlist (set->af_klist[i].af_ldes);
X    }
X  if (set->af_setlen > 0)
X    free ((char *)set->af_klist);
X  return (AF_OK);
X}
X
X/*================================================================
X *	af_setgkey -- return key from set
X *
X *================================================================*/
X
XEXPORT af_setgkey (set, pos, key)
X     Af_set *set;
X     int    pos;
X     Af_key *key; /* out */
X{
X  if (af_settest (set))
X    SFAIL ("setgkey", "", AF_EINVSET, ERROR);
X
X  if ((pos >= set->af_nkeys) || (pos < 0))
X    SFAIL ("setgkey", "", AF_ENOPOS, ERROR);
X
X  VATTR((&(set->af_klist[pos]))).af_nlinks++;
X  (set->af_klist[pos].af_ldes)->af_refcount++;
X  
X  key->af_ldes = set->af_klist[pos].af_ldes;
X  key->af_lpos = set->af_klist[pos].af_lpos;
X  return (AF_OK);
X}
X
X/*================================================================
X *	af_setaddkey -- add key to set
X *
X *================================================================*/
X
XEXPORT af_setaddkey (set, pos, key)
X     Af_set *set;
X     int    pos;
X     Af_key *key;
X{
X  register i;
X
X  if (af_settest (set))
X    SFAIL ("setaddkey", "", AF_EINVSET, ERROR);
X  if (af_keytest (key))
X    SFAIL ("setaddkey", "", AF_EINVKEY, ERROR);
X  if (((pos > set->af_nkeys) || (pos < 0)) && (pos != AF_LASTPOS))
X    SFAIL ("setaddkey", "", AF_ENOPOS, ERROR);
X
X  if (pos == AF_LASTPOS)
X    pos = set->af_nkeys;
X
X  /* if set is full, enlarge it */
X  if (set->af_nkeys == set->af_setlen)
X    {
X      if (set->af_setlen == 0)
X	{
X	  if ((set->af_klist = (Af_key *)malloc ((unsigned) (sizeof(Af_key) * AF_SEGLEN))) == (Af_key *)0)
X	    FAIL ("setaddkey", "malloc", AF_ESYSERR, ERROR);
X	}
X      else
X	{
X	  if ((set->af_klist = (Af_key *)realloc ((char *)set->af_klist, (unsigned) (sizeof(Af_key) * (set->af_setlen + AF_SEGLEN)))) == (Af_key *)0)
X	    FAIL ("setaddkey", "realloc", AF_ESYSERR, ERROR);
X	}
X      set->af_setlen += AF_SEGLEN;
X    }
X  
X  for ( i=set->af_nkeys; i>pos; i--)
X    set->af_klist[i] = set->af_klist[i-1];
X  set->af_klist[pos] = *key;
X  set->af_nkeys++;
X
X  /* increase refcount */
X  key->af_ldes->af_refcount++;
X  VATTR(key).af_nlinks++;
X
X  return (AF_OK);
X}
X
X/*================================================================
X *	af_setrmkey -- remove key from set
X *
X *================================================================*/
X
XEXPORT af_setrmkey (set, key)
X     Af_set *set;
X     Af_key *key;
X{
X  register i;
X  bool     found = FALSE;
X
X  if (af_settest (set))
X    SFAIL ("setrmkey", "", AF_EINVSET, ERROR);
X  if (af_keytest (key))
X    SFAIL ("setrmkey", "", AF_EINVKEY, ERROR);
X
X  for (i=0; i<set->af_nkeys; i++)
X    {
X      if (!found)
X	{
X	  if (!af_keycmp (&(set->af_klist[i]), key))
X	      found = TRUE;
X	}
X      else /* compress list */
X	set->af_klist[i-1] = set->af_klist[i];
X     }
X  if (!found)
X    SFAIL ("setrmkey", "", AF_ENOKEY, ERROR);
X  set->af_nkeys--;
X  VATTR(key).af_nlinks--;
X  if (--key->af_ldes->af_refcount <= 0)
X    (void) af_detlist (key->af_ldes);
X
X  return (AF_OK);
X}
X
X/*================================================================
X *	af_setposrmkey -- remove key (identified by position) from set
X *
X *================================================================*/
X
XEXPORT af_setposrmkey (set, pos)
X     Af_set *set;
X     int    pos;
X{
X  register i;
X
X  if (af_settest (set))
X    SFAIL ("setposrmkey", "", AF_EINVSET, ERROR);
X  if ((pos >= set->af_nkeys) || (pos < 0))
X    SFAIL ("setposrmkey", "", AF_ENOPOS, ERROR);
X
X  VATTR((&(set->af_klist[pos]))).af_nlinks--;
X  if (--(set->af_klist[pos].af_ldes)->af_refcount <= 0)
X    (void) af_detlist (set->af_klist[pos].af_ldes);
X
X  for (i=pos; i<set->af_nkeys-1; i++)
X    set->af_klist[i] = set->af_klist[i+1];
X
X  set->af_nkeys--;
X
X  return (AF_OK);
X}
X
X/*================================================================
X *	af_subset -- build subset
X *
X *================================================================*/
X
XEXPORT af_subset (set, attrbuf, newset)
X     Af_set   *set, *newset;
X     Af_attrs *attrbuf;
X{
X  register i, j=0, k=0;
X  int match;
X  Af_set tmpset;
X
X  if (af_settest (set))
X    SFAIL ("subset", "", AF_EINVSET, ERROR);
X
X  /* allocate memory for new set */
X  tmpset.af_setlen = set->af_nkeys;
X  if ((tmpset.af_klist = (Af_key *)malloc ((unsigned) (tmpset.af_setlen * sizeof(Af_key)))) == (Af_key *)0)
X    FAIL ("subset", "malloc", AF_ESYSERR, ERROR);
X
X  /* if there are no disqualifying attributes, add key to new set */
X  for (i = 0; i < set->af_nkeys; i++)
X    {
X      /* if an attribute is set an does not match, continue with next key */
X      /*** name ***/
X      if ( (attrbuf->af_name[0] != '\0') &&
X	   (strcmp (attrbuf->af_name, VATTR((&(set->af_klist[i]))).af_name)) )
X	continue;
X
X      /*** type ***/
X      if ( (attrbuf->af_type[0] != '\0') &&
X	   (strcmp (attrbuf->af_type, NOTNIL(VATTR((&(set->af_klist[i]))).af_type))) )
X	continue;
X
X      /*** syspath ***/
X      if ( (attrbuf->af_syspath[0] != '\0') &&
X	   (strcmp (attrbuf->af_syspath, CATTR((&(set->af_klist[i]))).af_syspath)) )
X	continue;
X
X      /*** generation number ***/
X      if ( (attrbuf->af_gen != AF_NOVNUM) &&
X	   (attrbuf->af_gen != VATTR((&(set->af_klist[i]))).af_gen) )
X	continue;
X  
X      /*** revision number ***/
X      if ( (attrbuf->af_rev != AF_NOVNUM) &&
X	   (attrbuf->af_rev != VATTR((&(set->af_klist[i]))).af_rev) )
X	continue;
X
X      /*** variant attribute ***/
X      if ( (attrbuf->af_variant[0]) &&
X	   (strcmp (attrbuf->af_variant, NOTNIL(VATTR((&(set->af_klist[i]))).af_variant))) )
X	continue;
X
X      /*** state ***/
X      if ( (attrbuf->af_state != AF_NOSTATE) &&
X	   (attrbuf->af_state != VATTR((&(set->af_klist[i]))).af_state) )
X	continue;
X
X      /*** owner ***/
X      if ( (attrbuf->af_owner.af_username[0]) &&
X	   (strcmp (attrbuf->af_owner.af_username, CATTR((&(set->af_klist[i]))).af_ownname)) )
X	continue;
X      if ( (attrbuf->af_owner.af_userhost[0]) &&
X	   (strcmp (attrbuf->af_owner.af_userhost, CATTR((&(set->af_klist[i]))).af_ownhost)) )
X	continue;
X
X      /*** author ***/
X      if ( (attrbuf->af_author.af_username[0]) &&
X	   (strcmp (attrbuf->af_author.af_username, VATTR((&(set->af_klist[i]))).af_auname)) )
X	continue;
X      if ( (attrbuf->af_author.af_userhost[0]) &&
X	   (strcmp (attrbuf->af_author.af_userhost, VATTR((&(set->af_klist[i]))).af_auhost)) )
X	continue;
X
X      /*** size ***/
X      if ( (attrbuf->af_size != AF_NOSIZE) &&
X	   (attrbuf->af_size != VATTR((&(set->af_klist[i]))).af_fsize) )
X	continue;
X
X      /*** mode ***/
X      if ( (attrbuf->af_mode != AF_NOMODE) &&
X	   (attrbuf->af_mode != VATTR((&(set->af_klist[i]))).af_mode) )
X	continue;
X
X      /*** locker ***/
X      if ( (attrbuf->af_locker.af_username[0]) &&
X	   (strcmp (attrbuf->af_locker.af_username, NOTNIL(VATTR((&(set->af_klist[i]))).af_lckname))) )
X	continue;
X      if ( (attrbuf->af_locker.af_userhost[0]) &&
X	   (strcmp (attrbuf->af_locker.af_userhost, NOTNIL(VATTR((&(set->af_klist[i]))).af_lckhost))) )
X	continue;
X
X      /*** date of last modification ***/
X      if ( (attrbuf->af_mtime != AF_NOTIME) &&
X	   (attrbuf->af_mtime != VATTR((&(set->af_klist[i]))).af_mtime) )
X	continue;
X
X      /*** date of last access ***/
X      if ( (attrbuf->af_atime != AF_NOTIME) &&
X	   (attrbuf->af_atime != VATTR((&(set->af_klist[i]))).af_atime) )
X	continue;
X
X      /*** date of last status change ***/
X      if ( (attrbuf->af_ctime != AF_NOTIME) &&
X	   (attrbuf->af_ctime != VATTR((&(set->af_klist[i]))).af_ctime) )
X	continue;
X
X      /*** saving date ***/
X      if ( (attrbuf->af_stime != AF_NOTIME) &&
X	   (attrbuf->af_stime != VATTR((&(set->af_klist[i]))).af_stime) )
X	continue;
X
X      /*** date of last lock change ***/
X      if ( (attrbuf->af_ltime != AF_NOTIME) &&
X	   (attrbuf->af_ltime != VATTR((&(set->af_klist[i]))).af_ltime) )
X	continue;
X
X      /*** user defined attributes ***/
X      if (attrbuf->af_udattrs[0] != (char *)0)
X	{
X	  /* if list of user defined attributes is not empty or there are */
X	                                                    /* attributes */
X	  match = TRUE;
X	  if ((attrbuf->af_udattrs[0][0] != '\0') ||
X	      (VATTR((&(set->af_klist[i]))).af_udanum != 0))
X	    {
X	      /* test all given entries */
X	      j=0;
X	      while ((attrbuf->af_udattrs[j] != (char *)0) 
X		     && (match = !af_match (attrbuf->af_udattrs[j],
X			 &(VATTR((&(set->af_klist[i]))).af_uhtab))))
X		{
X		  j++;
X		}
X	    } /* if */
X	  if (match == FALSE)
X	    continue;
X	} /* if */
X
X
X      /* add key to new set */
X      tmpset.af_klist[k] = set->af_klist[i];
X      /* increase number of links in list descriptor */
X      (tmpset.af_klist[k].af_ldes)->af_refcount++;
X      VATTR((&(tmpset.af_klist[k]))).af_nlinks++;
X      k++;
X
X    } /* for */
X  
X  tmpset.af_nkeys = k;
X
X  /* if the resulting set shall be stored in the old set */
X  if (set == newset)
X    {
X      (void) af_dropset (set);
X      *set = tmpset;
X    }
X  else
X    *newset = tmpset;
X
X  return (k);
X}
X
X
X/*================================================================
X *	af_intersect -- build intersection of two sets
X *
X *================================================================*/
X
XEXPORT af_intersect (set1, set2, newset)
X     Af_set *set1, *set2;
X     Af_set *newset;
X{
X  register i, j, k;
X  Af_set tmpset;
X
X  if (af_settest (set1) || af_settest (set2))
X    SFAIL ("intersect", "", AF_EINVSET, ERROR);
X
X  /* allocate enough memory */
X  if (set1->af_nkeys >= set2->af_nkeys)
X    tmpset.af_setlen = set1->af_nkeys;
X  else
X    tmpset.af_setlen = set2->af_nkeys;
X  if ((tmpset.af_klist = (Af_key *)malloc ((unsigned) (tmpset.af_setlen * sizeof(Af_key)))) == (Af_key *)0)
X    FAIL ("intersect", "malloc", AF_ESYSERR, ERROR);
X 
X  /* build new set */
X  k=0;
X  for (i=0; i<set1->af_nkeys; i++)
X    for (j=0; j<set2->af_nkeys; j++)
X      {
X	if (!af_keycmp (&(set1->af_klist[i]), &(set2->af_klist[j])))
X	  {
X	    tmpset.af_klist[k] = set1->af_klist[i];
X	    /* increase number of links in list descriptor */
X	    (tmpset.af_klist[k].af_ldes)->af_refcount++;
X	    VATTR((&(tmpset.af_klist[k]))).af_nlinks++;
X	    k++;
X	  }
X      }
X  tmpset.af_nkeys = k;
X
X  /* if the new set shall be stored in one of the old ones */
X  if (newset == set1)
X    {
X      (void) af_dropset (set1);
X      *set1 = tmpset;
X    }
X  else
X    {
X      if (newset == set2)
X	{
X	  (void) af_dropset (set2);
X	  *set2 = tmpset;
X	}
X      else
X	*newset = tmpset;
X    }
X
X  return (k);
X}
X
X/*================================================================
X *	af_union -- build union of two sets
X *
X *================================================================*/
X
XEXPORT af_union (set1, set2, newset)
X     Af_set *set1, *set2;
X     Af_set *newset;
X{
X  register i, j, k;
X  bool     dbl=FALSE;
X  Af_set   tmpset;
X
X  if (af_settest (set1) || af_settest (set2))
X    SFAIL ("union", "", AF_EINVSET, ERROR);
X
X  /* allocate enough memory */
X  tmpset.af_setlen = set1->af_nkeys+set2->af_nkeys;
X  if ((tmpset.af_klist = (Af_key *)malloc ((unsigned) (tmpset.af_setlen * sizeof(Af_key)))) == (Af_key *)0)
X    FAIL ("union", "malloc", AF_ESYSERR, ERROR);
X
X  /* build new set */
X  k=0;
X  for (i=0; i<set1->af_nkeys; i++)
X    {
X      tmpset.af_klist[k] = set1->af_klist[i];
X      /* increase number of links in list descriptor */
X      (tmpset.af_klist[k].af_ldes)->af_refcount++;
X      VATTR((&(tmpset.af_klist[k]))).af_nlinks++;
X      k++;
X    }
X  for (j=0; j<set2->af_nkeys; j++)
X    {
X      for (i=0; i<set1->af_nkeys; i++)
X	{
X	  if (!af_keycmp (&(tmpset.af_klist[i]), &(set2->af_klist[j])))
X	    dbl = TRUE;
X	}
X      if (dbl)
X	dbl = FALSE;
X      else
X	{
X	  tmpset.af_klist[k] = set2->af_klist[j];
X	  /* increase number of links in list descriptor */
X	  (tmpset.af_klist[k].af_ldes)->af_refcount++;
X	  VATTR((&(tmpset.af_klist[k]))).af_nlinks++;
X	  k++;
X	}
X    }
X  tmpset.af_nkeys = k;
X
X  /* if the new set shall be stored in one of the old ones */
X  if (newset == set1)
X    {
X      (void) af_dropset (set1);
X      *set1 = tmpset;
X    }
X  else
X    {
X      if (newset == set2)
X	{
X	  (void) af_dropset (set2);
X	  *set2 = tmpset;
X	}
X      else
X	*newset = tmpset;
X    }
X
X  return (k);
X}
X
X/*================================================================
X *	af_diff -- build difference between two sets
X *
X *================================================================*/
X
XEXPORT af_diff (set1, set2, newset)
X     Af_set *set1, *set2;
X     Af_set *newset;
X{
X  register i, j, k;
X  bool     found = FALSE;
X  Af_set   tmpset;
X
X  if (af_settest (set1) || af_settest (set2))
X    SFAIL ("diff", "", AF_EINVSET, ERROR);
X
X  /* allocate enough memory */
X  tmpset.af_setlen = set1->af_nkeys;
X  if ((tmpset.af_klist = (Af_key *)malloc ((unsigned) (tmpset.af_setlen * sizeof(Af_key)))) == (Af_key *)0)
X    FAIL ("diff", "malloc", AF_ESYSERR, ERROR);
X
X  /* build new set */
X  k=0;
X  for (i=0; i<set1->af_nkeys; i++)
X    {
X      for (j=0; j<set2->af_nkeys; j++)
X	{
X	  if (!af_keycmp (&(set1->af_klist[i]), &(set2->af_klist[j])))
X	    found = TRUE;
X	}
X      if (found)
X	found = FALSE;
X      else
X	{
X	  tmpset.af_klist[k] = set1->af_klist[i];
X	  /* increase number of links in list descriptor */
X	  (tmpset.af_klist[k].af_ldes)->af_refcount++;
X	  VATTR((&(tmpset.af_klist[k]))).af_nlinks++;
X	  k++;
X	}
X    }
X  tmpset.af_nkeys = k;
X
X  /* if the new set shall be stored in one of the old ones */
X  if (newset == set1)
X    {
X      (void) af_dropset (set1);
X      *set1 = tmpset;
X    }
X  else
X    {
X      if (newset == set2)
X	{
X	  (void) af_dropset (set2);
X	  *set2 = tmpset;
X	}
X      else
X	*newset = tmpset;
X    }
X
X  return (k);
X}
END_OF_FILE
if test 19377 -ne `wc -c <'src/afs/afsets.c'`; then
    echo shar: \"'src/afs/afsets.c'\" unpacked with wrong size!
fi
# end of 'src/afs/afsets.c'
fi
if test -f 'src/vc/vldovl.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/vc/vldovl.c'\"
else
echo shar: Extracting \"'src/vc/vldovl.c'\" \(18709 characters\)
sed "s/^X//" >'src/vc/vldovl.c' <<'END_OF_FILE'
X/*
X * Copyright (C) 1989, 1990 W. Koch, A. Lampen, A. Mahler, W. Obst,
X *  and U. Pralle
X * 
X * This software is published on an as-is basis. There is ABSOLUTELY NO
X * WARRANTY for any part of this software to work correctly or as described
X * in the manuals. We do not accept any liability for any kind of damage
X * caused by use of this software, such as loss of data, time, money, or 
X * effort.
X * 
X * Permission is granted to use, copy, modify, or distribute any part of
X * this software as long as this is done without asking for charge, and
X * provided that this copyright notice is retained as part of the source
X * files. You may charge a distribution fee for the physical act of
X * transferring a copy, and you may at your option offer warranty
X * protection in exchange for a fee.
X * 
X * Direct questions to: Tech. Univ. Berlin
X * 		     Wilfried Koch
X * 		     Sekr. FR 5-6 
X * 		     Franklinstr. 28/29
X * 		     D-1000 Berlin 10, West Germany
X * 
X * 		     Tel: +49-30-314-22972
X * 		     E-mail: shape@coma.uucp or shape@db0tui62.bitnet
X */
X#ifndef lint
Xstatic char *AFSid = "$Header: vldovl.c[3.10] Thu Feb 23 18:14:47 1989 axel@coma published $";
X#ifdef CFFLGS
Xstatic char *ConfFlg = CFFLGS;
X	/* should be defined from within Makefile */
X#endif
X#endif
X/*
X * Log for /u/shape/dist-tape/src/vc/vldovl.c[3.4]
X * 	Thu Feb 23 18:14:48 1989 axel@coma published $
X *  --- empty log message ---
X *  vldovl.c[3.6] Thu Feb 23 18:14:48 1989 uli@coma published $
X *  --- empty log message ---
X *  vldovl.c[3.8] Thu Feb 23 18:14:48 1989 axel@coma published $
X *  --- empty log message ---
X *  vldovl.c[3.9] Thu Feb 23 18:14:48 1989 axel@coma save $
X *  --- empty log message ---
X *  vldovl.c[3.10] Thu Feb 23 18:14:48 1989 axel@coma published $
X *  --- empty log message ---
X */
X
X#include <stdio.h>
X#include <strings.h>
X#include <afs.h>
X#include "vl.h"
X
Xextern int immediate_output;
Xextern int version_number;
X
X/*
X * Global variables
X */
X
Xchar pathname_required = 0;
Xextern char vl_cwd[];
Xchar buf[1000];
Xchar *pending_name;		/* Holds the name of a dir */
Xint dir_pending = 0;
X
XAf_attrs AF_attrbuf;
XAf_set AF_fileset;
Xchar error_string[80];
X
Xvoid InitAttrs (AF_attrbuf, name)
X     Af_attrs *AF_attrbuf;
X     char *name;
X     /*
X      * Initializes the attribute buffer.
X      */
X     
X{
X  register int i;
X  int vno;
X  register char **udattrs;
X  extern char *GetAuthoridFromAuthor(), *GetOwneridFromOwner(),
X              *GetAuthorhostFromAuthor(), *GetOwnerhostFromOwner();
X  char cstring[MAXNAMLEN], vstring[16];
X
X  af_initattrs (AF_attrbuf);
X
X  if (name && name[0] != '\0') {
X    if (BoundVersion (name, cstring, vstring)) {
X      /* This code kind of assumes, that directory names are not of */
X      /* the kind 'dirname[2.9]' -- good luck! */
X      vno = mkvno (vstring);
X      AF_attrbuf->af_gen = gen(vno);
X      AF_attrbuf->af_rev = rev(vno);
X      (void)strcpy (AF_attrbuf->af_syspath, af_afpath (cstring));
X      (void)strcpy (AF_attrbuf->af_name, af_afname (cstring));
X      (void)strcpy (AF_attrbuf->af_type, af_aftype (cstring));
X      /* No further options are considered in this case */
X    }
X    else {  /* no bound version notation (e.g. foo.c[4.3]) for 'name' */ 
X      if (IsDirectory (name)) {
X	(void)strcpy (AF_attrbuf->af_syspath, name);
X      }
X      else { /* 'name' is not a directory */
X	(void)strcpy (AF_attrbuf->af_syspath, af_afpath (name));
X	(void)strcpy (AF_attrbuf->af_name, af_afname (name));
X	(void)strcpy (AF_attrbuf->af_type, af_aftype (name));
X      }
X    }
X  }
X  /* Invariant: syspath, name and type fields of AF_attrbuf initialized */
X
X  if (IsOptionSet(VL_O_UDAGIVEN)) {
X    udattrs = GetUdattrs ();
X    for (i = 0 ; udattrs[i] ; i++) {
X      AF_attrbuf->af_udattrs[i] = udattrs[i];
X    }
X  }
X
X  if (IsOptionSet(VL_O_VERSIONNUM)) {
X    if (! (IsOptionSet(VL_O_HISTLOG) || IsOptionSet(VL_O_LOGMSG))) {
X      if ((i = gen(version_number)) >= 0) {
X	AF_attrbuf->af_gen = i;
X      }
X      if ((i = rev(version_number)) >= 0) {
X	AF_attrbuf->af_rev = i;
X      }
X    }
X  }
X
X  if (IsOptionSet(VL_O_AUTHOR)) {
X    (void)strcpy (AF_attrbuf->af_author.af_username, GetAuthoridFromAuthor());
X    (void)strcpy (AF_attrbuf->af_author.af_userhost, GetAuthorhostFromAuthor());
X  }
X
X  if (IsOptionSet(VL_O_OWNER)) {
X    (void)strcpy (AF_attrbuf->af_owner.af_username, GetOwneridFromOwner());
X    (void)strcpy (AF_attrbuf->af_owner.af_userhost, GetOwnerhostFromOwner());
X  }
X  return;
X}
X
Xint PrintUDA (attrbuf)
X     Af_attrs *attrbuf;
X{
X  register char *cp;
X  register int i;
X  register char Checkbyte;
X  register first_uda_printed;
X  
X  if ( (attrbuf->af_udattrs == NULL) || (attrbuf->af_udattrs[0] == '\0'))
X    return 0;			/* no user defined attributes */
X  
X  
X  if (IsOptionSet(VL_O_LONGOUTPUT)) {
X    PrintLongVinfo (attrbuf); printf (":\n");
X  }
X  else {
X    PrintShortVinfo (attrbuf); printf (":");
X  }
X
X  if (IsOptionSet(VL_O_LISTUDALONG)) {
X    Checkbyte = '\0';
X  }
X  else {
X    Checkbyte = '=';
X  }
X
X  first_uda_printed = 0;	/* nothing yet printed */
X  
X  for (i = 0; attrbuf->af_udattrs[i]; i++){
X    cp = attrbuf->af_udattrs[i];
X
X    if (!IsOptionSet(VL_O_LISTHIDDENUDAS) && IsHiddenUda (cp))
X	  continue;
X    if (first_uda_printed) {
X      (void)putchar (';');		/* seperate udas by ';' */
X    }
X    else {
X      (void)putchar (' ');
X      first_uda_printed = 1;
X    }
X    
X    while (cp && *cp && *cp != Checkbyte) {
X      if (*cp == AF_UDAVALDEL) {
X	(void)putchar (',');		/* seperate values of uda by ','
X				 */
X      }
X      else {
X	(void)putchar (*cp);
X      }
X      cp++;
X    }
X  }
X  (void)putchar ('\n');
X  (void)fflush (stdout);
X  return 1;
X}
X
XPrintVinfo (attrbuf)
X     Af_attrs *attrbuf;
X{
X  if (IsOptionSet(VL_O_LISTUDA|VL_O_LISTUDALONG)) {
X    return PrintUDA (attrbuf);
X  }
X  
X  if (IsOptionSet(VL_O_LONGOUTPUT)) {
X    PrintLongVinfo (attrbuf);
X    return 1;
X  }
X
X  PrintShortVinfo (attrbuf);
X  return 1;
X}
X
XPrintShortVinfo (attrbuf)
X     Af_attrs *attrbuf;
X{
X  if (immediate_output) {	/* set during option scanning */
X    if (dir_pending) {	/*  now we can print the pending dir name */
X      printf ("\n%s:\n", pending_name ? pending_name : ""); 
X      dir_pending = 0;
X    }
X    
X    printf ("%s%s%s%s%s%s%s%s", 
X	    (pathname_required) ? attrbuf->af_syspath : "",
X	    (pathname_required) ? "/" : "",
X	    attrbuf->af_name,
X	    (attrbuf->af_type && (attrbuf->af_type[0] != '\0') ? "." : ""),
X	    attrbuf->af_type,
X	    GetVersionId (attrbuf->af_gen, attrbuf->af_rev),
X	    (IsOptionSet(VL_O_VERSIONSTATE)) ? " -> " : "",
X	    (IsOptionSet(VL_O_VERSIONSTATE)) ? GetVersionState (attrbuf->af_state)
X	    : "");
X  }
X  else {
X    (void)sprintf (buf, "%s%s%s%s%s%s%s%s", 
X	     (pathname_required) ? attrbuf->af_syspath : "",
X	     (pathname_required) ? "/" : "",
X	     attrbuf->af_name,
X	     (attrbuf->af_type && (attrbuf->af_type[0] != '\0') ? "." : ""),
X	     attrbuf->af_type,
X	     GetVersionId (attrbuf->af_gen, attrbuf->af_rev),
X	     (IsOptionSet(VL_O_VERSIONSTATE)) ? " -> " : "",
X	     (IsOptionSet(VL_O_VERSIONSTATE)) ? GetVersionState (attrbuf->af_state)
X	     : "");
X    
X    AddEntry (buf);
X  }
X}
X
XPrintLongVinfo (attrbuf)
X     Af_attrs *attrbuf;
X{
X  if (immediate_output) {	/* set during option scanning */
X    char *p1 = NULL, *p2 = NULL;
X    if (dir_pending) {	/*  now we can print the pending dir name */
X      printf ("\n%s:\n", pending_name ? pending_name : ""); 
X      dir_pending = 0;
X    }
X/* This is the place to put out the name of eventual lockholders */
X    printf ("%s %s %s %s %8d %s %s%s%s%s%s%s",
X	    GetMode (attrbuf->af_mode),
X	    GetVersionState (attrbuf->af_state),
X	    p1=GetUserInfo (&(attrbuf->af_owner)),
X	    (IsOptionSet(VL_O_AUTHOR))
X	    ? p2=GetUserInfo (&(attrbuf->af_author)) : "",
X	    attrbuf->af_size,
X	    (attrbuf->af_state > AF_BUSY) ? GetDate (attrbuf->af_stime)
X	    : GetDate (attrbuf->af_mtime),
X	    (pathname_required) ? attrbuf->af_syspath : "",
X	    (pathname_required) ? "/" : "",
X	    attrbuf->af_name,
X	    (attrbuf->af_type && (attrbuf->af_type[0] != '\0')) ?  "."
X	    : "",
X	    attrbuf->af_type,
X	    GetVersionId (attrbuf->af_gen, attrbuf->af_rev));
X    if (p1) free (p1);
X    if (p2) free (p2);
X  }
X  else {
X    (void)sprintf (buf, "%s %s %s %s %8d %s %s%s%s%s%s%s",
X	     GetMode (attrbuf->af_mode),
X	     GetVersionState (attrbuf->af_state),
X	     GetUserInfo (&(attrbuf->af_owner)),
X	     (IsOptionSet(VL_O_AUTHOR))
X	     ? GetUserInfo (&(attrbuf->af_author))  : "",
X	     attrbuf->af_size,
X	     (attrbuf->af_state > AF_BUSY) ? GetDate (attrbuf->af_stime)
X	     : GetDate (attrbuf->af_mtime),
X	     (pathname_required) ? attrbuf->af_syspath : "",
X	     (pathname_required) ? "/" : "",
X	     attrbuf->af_name,
X	     (attrbuf->af_type && (attrbuf->af_type[0] != '\0')) ?  "."
X	     : "",
X	     attrbuf->af_type,
X	     GetVersionId (attrbuf->af_gen, attrbuf->af_rev));
X    AddEntry (buf);
X  }
X}
X
XReportVersionInfo (name)
X     char *name;
X
X     /*
X      * Returns 0 if no info for name found, otherwise 1;
X      */
X{
X  register int i;
X  int numhits, Bnumhits=0;
X  int retcode = 1, rc;		/* assume failure */
X  char *cp;
X  Af_set AF_sfileset, AF_bfileset;
X  Af_key fkey;
X
X  af_initset (&AF_sfileset);
X  af_initset (&AF_bfileset);
X  if (name && *name) {
X    cp = af_afpath(name);
X    if ( (! IsDirectory (name))
X	&& *cp
X	&& strcmp (cp, vl_cwd)) {
X      /*
X       * name is a normal file and is not in current working dir
X       * require pathname on output
X       */
X      pathname_required = 1;
X    }
X    else {
X      pathname_required = 0;
X    }
X  }
X  if (IsOptionSet(VL_O_LASTVERS)) {
X    rc=af_getkey (af_afpath (name), af_afname (name), af_aftype (name),
X	       AF_LASTVERS, AF_LASTVERS, "", &fkey);
X    if (rc < 0) {
X      numhits = 0;
X    }
X    else {
X      af_setaddkey (&AF_sfileset, 0, &fkey);
X      numhits = 1;
X    }
X  }
X  else {
X    InitAttrs (&AF_attrbuf, name);
X    
X    /* now go, and get some info.... */
X    if ((numhits = af_find (&AF_attrbuf, &AF_sfileset)) == -1) {
X      (void)sprintf (error_string,
X	       "%s: in ReportVersionInfo(): af_find (%s)",
X	       GetProgramName (), name);
X      af_perror (error_string);
X      return (1); /*exit (1);*/
X    }
X    if (IsOptionSet(VL_O_LISTBINARY)) {
X      if ((Bnumhits = af_bpfind (&AF_attrbuf, &AF_bfileset)) == -1) {
X	(void)sprintf (error_string,
X		 "%s: in ReportVersionInfo(): af_find (%s)",
X		 GetProgramName (), name);
X	af_perror (error_string);
X	return (1); /*exit (1);*/
X      }
X    }
X  }
X  if (af_union (&AF_sfileset, &AF_bfileset, &AF_fileset) < 0) {
X    af_perror ("af_union");
X    return 1;
X  }
X  numhits += Bnumhits;
X  af_dropset (&AF_sfileset);
X  af_dropset (&AF_bfileset);
X  /* nothing found ? */
X  if (numhits == 0) {
X    if (!IsOptionSet(VL_O_BEQUIET)) {
X      if (name && *name) {
X	if (! FileExists (name)) {
X	  printf ("%s: %s: nothing appropriate found\n", GetProgramName (), name);
X	}
X      }
X    }
X    VinfoCleanup ();
X    return 1;			/* report failure */
X  }
X
X  if ((*name != '\0') && IsDirectory (name)) {
X    if (immediate_output) {
X      /*
X       * dir name must be printed, iff
X       * something is found. But we can determine
X       * this not yet.
X       */
X      dir_pending = 1;
X      pending_name = name;
X    }
X    else
X      AddClist (name);
X  }
X  
X  /*
X   * sort by name and version number. Busy version first then
X   * versions with increasing version numbers.
X   */
X
X  if (af_sortset (&AF_fileset, AF_ATTHUMAN) == -1) { 
X    (void)sprintf (error_string,
X	     "%s: in ReportVersionInfo(): af_sortset by AF_ATTHIMAN",
X	     GetProgramName);
X    af_perror (error_string);
X    exit (1);
X  }
X  
X  for (i = 0; i < AF_fileset.af_nkeys; i++) {
X    if (af_gattrs (&(AF_fileset.af_klist[i]), &AF_attrbuf) == -1) {
X      (void)sprintf (error_string, "%s: in ReportVersionInfo(): af_gattrs");
X      af_perror (error_string);
X      exit (1);
X    }
X    else {
X      if (IsHiddenFile(&AF_attrbuf) && !IsOptionSet(VL_O_LISTHIDDEN))
X	continue;
X
X      if (IsOptionSet(VL_O_STATEGIVEN)) {
X	if (!MatchesVersionStates (&AF_attrbuf))
X	  continue;
X      }
X      
X      if (!IsOptionSet(VL_O_BEQUIET)) {
X	if (IsOptionSet(VL_O_LOGMSG)) {
X	  if (IsInHistoryLogMsgList (&AF_attrbuf)) {
X	    if (PrintVinfo (&AF_attrbuf)) {
X	      (void)putchar (':'); (void)putchar ('\n');
X	      PrintLogMsg (&(AF_fileset.af_klist[i]));
X	      retcode = 0;	/* success */
X	    }
X	  }
X	}
X	else {
X	  (void)PrintVinfo (&AF_attrbuf);
X	  retcode = 0;	/* success */
X	}
X      }
X    }
X  }
X/*  VinfoCleanup (); */
X  return retcode;
X}
X
XInitReportVersion ()
X{
X  InitCList ();
X}
X
Xint PrintLogMsg (key)
X     Af_key *key;
X{
X  register char *logmsg;
X  
X  if ((logmsg = af_rnote (key)) == NULL) {
X    (void)sprintf (error_string, "%s: af_rnote", GetProgramName ());
X    af_perror (error_string);
X    exit (1);
X  }
X
X  printf ("%s", logmsg);
X  if (logmsg[strlen(logmsg)-1] != '\n') {
X    (void)putchar ('\n');
X    (void)fflush (stdout);
X  }
X  free (logmsg);
X
X}
X
Xint IsInHistoryLogMsgList (attrbuf)
X     Af_attrs *attrbuf;
X{
X  if (attrbuf->af_state == AF_BUSY)
X    return 0; /* is busy version */
X  if (IsOptionSet(VL_O_HISTLOG) &&
X      ! IsOptionSet(VL_O_VERSIONNUM)) 
X    return 1;
X
X  if (!IsOptionSet(VL_O_HISTLOG|VL_O_VERSIONNUM))
X    return 1;
X  else {
X    if (IsOptionSet(VL_O_HISTLOGPLUS)) {
X      if (attrbuf->af_gen > gen(version_number))
X	return 1;
X      if ((gen(version_number) == attrbuf->af_gen) &&
X	  (attrbuf->af_rev > rev(version_number)))
X	return 1;
X    }
X    else {
X      if (attrbuf->af_gen < gen(version_number))
X	return 1;
X      if ((gen(version_number) == attrbuf->af_gen) &&
X	  (attrbuf->af_rev < rev(version_number)))
X	return 1;
X    }
X    if ((gen(version_number) == attrbuf->af_gen) &&
X	(rev(version_number) == attrbuf->af_rev)) return 1;
X  }
X  return 0;
X}
X
Xstruct entry {
X  char *repr;
X  struct entry *next;
X};
X
Xstruct clist {			/* column list */
X  char *dir;			/* name of dir */
X  struct entry *entry;
X  struct clist *next;
X};
X
Xstruct clist *clistroot;
Xstruct clist *curclist;
Xstruct entry *curentry;
X
XInitCList ()
X{
X  if ((clistroot = (struct clist*) malloc (sizeof (struct clist))) == NULL) {
X    (void)strcpy (error_string, "in InitClist (): malloc,1");
X    perror (error_string);
X    exit (1);
X  }
X
X  clistroot->dir = NULL;	/* has never a name */
X
X/*  if ((clistroot->next = (struct clist*) malloc (sizeof (struct clist)))
X      == NULL) {
X    (void)strcpy (error_string, "in InitClist (): malloc,2");
X    perror (error_string);
X    exit (1);
X  }
X  */  
X  clistroot->next = NULL;
X  curclist = clistroot;
X  
X  if ((curentry = (struct entry*) malloc (sizeof (struct entry))) == NULL) {
X    (void)strcpy (error_string, "in InitClist (): malloc,3");
X    perror (error_string);
X    exit (1);
X  }
X  curentry->repr = NULL;
X  curentry->next = NULL;
X
X  clistroot->entry = curentry;
X}
X
XAddClist (name) 
X     char *name;
X{
X  struct clist *this_clist;
X
X  if ((this_clist = (struct clist*) malloc (sizeof (struct clist))) == NULL) {
X    (void)strcpy (error_string, "in AddCList (): malloc,1");
X    perror (error_string);
X    exit (1);
X  }
X
X  if ((this_clist->dir = malloc ((unsigned)(strlen (name)+1))) == NULL) {
X    (void)strcpy (error_string, "in AddCList (): malloc,2");
X    perror (error_string);
X    exit (1);
X  }
X
X  if ((this_clist->entry = (struct entry*) malloc (sizeof (struct entry)))
X      == NULL) {
X    (void)strcpy (error_string, "in AddCList (): malloc,2");
X    perror (error_string);
X    exit (1);
X  }
X      
X  (void)strcpy (this_clist->dir, name);
X  this_clist->next = NULL;
X  curentry = this_clist->entry;
X  curentry->repr = NULL;
X  curentry->next = NULL;
X
X  curclist->next = this_clist;
X  curclist = this_clist;
X  
X}
X  
XAddEntry (str)
X     char *str;
X{
X  struct entry* this_entry;
X
X  if ((curentry->repr = malloc ((unsigned)(strlen (str)+1))) == NULL) {
X    (void)strcpy (error_string, "in AddEntry (): malloc,2");
X    perror (error_string);
X    exit (1);
X  }
X
X  (void)strcpy (curentry->repr, str);
X
X  if ((this_entry = (struct entry*) malloc (sizeof (struct entry))) == NULL) {
X    (void)strcpy (error_string, "in AddEntry (): malloc,1");
X    perror (error_string);
X    exit (1);
X  }
X
X  this_entry->repr = NULL;
X  this_entry->next = NULL;
X  curentry->next = this_entry;
X  curentry = this_entry;
X}
X
Xint computemaxlength (root)
X  struct entry *root;
X{
X  struct entry *this_entry;
X  int length = 0, maxlength = 0;
X  
X  if (!root) return 0;
X
X  for (this_entry = root;
X       this_entry->repr && this_entry->next;
X       this_entry = this_entry->next) {
X    length = strlen (this_entry->repr);
X    if (length > maxlength) {
X      maxlength = length;
X    }
X  }
X  return maxlength;
X}
X
XPrintList (root, wordsperline, colwidth, newline_required, group_it)
X     struct clist *root;
X     int wordsperline, colwidth, newline_required, group_it;
X{
X  struct entry *this_entry;
X  int nwordsprinted = 0;	/* number of words per line yet printed */
X  int ntabs = 0;
X  int length;
X
X  if (/*root->entry && */root->entry->repr) {
X    if (root->dir) {
X      if (newline_required) (void)putchar ('\n');
X      
X      printf ("%s:\n", root->dir);
X    }
X  }
X  
X  if (!group_it) {
X    for (this_entry = root->entry;
X	 this_entry->repr && this_entry->next;
X	 this_entry = this_entry->next) {
X      printf ("%s\n", this_entry->repr);
X    }
X  }
X  else {
X    for (this_entry = root->entry;
X	 this_entry->repr && this_entry->next;
X	 this_entry = this_entry->next) {
X      nwordsprinted++;
X      if (!(nwordsprinted % wordsperline)) { /* if last word in this line */
X	printf ("%s\n", this_entry->repr);
X      }
X      else {
X	printf ("%s", this_entry->repr);
X	
X	/* compute #tabs to get to the next word position */
X	length = strlen (this_entry->repr);
X	ntabs = (colwidth - length) / 8;
X	if ((colwidth - length) % 8)
X	  ntabs++;
X	
X	while (ntabs--) (void)putchar ('\t');	  
X      }
X    }
X    if (nwordsprinted % wordsperline) printf ("\n");
X  }
X}
X
XFlushIt (root)
X     struct clist *root;
X{
X  struct clist *this_clist;
X  int colwidth = 0, wordsperline = 0;
X  int maxlength = 0, newline_required = 0;
X  
X  for (this_clist = root; this_clist; this_clist = this_clist->next) {
X
X    if (this_clist->entry && (this_clist->entry->repr == (char *) NULL))
X      continue;			/* skip empty list */
X
X    if (multicol_output_is_possible ()) {
X      /* compute length of longest word in this list */
X      maxlength = computemaxlength (this_clist->entry);
X      
X      /* compute length to next tab stop */
X      colwidth = (maxlength / 8) + 1;
X      colwidth *= 8;
X      
X      /* compute # words that fit in a line */
X#define maxcol 80
X      if (!(wordsperline = maxcol / colwidth)) wordsperline++;
X      
X    }
X    
X    PrintList (this_clist, wordsperline, colwidth, newline_required,
X	       multicol_output_is_possible ());
X    newline_required++;
X  }
X}
X
Xvoid FlushInfo ()
X{
X  if (!immediate_output)
X    FlushIt (clistroot); /* Print now */
X}
END_OF_FILE
if test 18709 -ne `wc -c <'src/vc/vldovl.c'`; then
    echo shar: \"'src/vc/vldovl.c'\" unpacked with wrong size!
fi
# end of 'src/vc/vldovl.c'
fi
echo shar: End of archive 21 \(of 33\).
cp /dev/null ark21isdone
MISSING=""
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
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 33 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.