[comp.sources.unix] v19i046: A software configuration management system, Part33/33

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

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



#! /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 33 (of 33)."
# Contents:  src/shape/attr.c
# Wrapped by rsalz@papaya.bbn.com on Thu Jun  1 19:27:22 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'src/shape/attr.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/shape/attr.c'\"
else
echo shar: Extracting \"'src/shape/attr.c'\" \(50463 characters\)
sed "s/^X//" >'src/shape/attr.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 *RCSid = "$Header: attr.c,v 3.1 89/02/08 12:45:55 wolfgang Exp $";
X#endif
X#ifndef lint
Xstatic char *ConfFlg = CFFLGS;	/* should be defined from within Makefile */
X#endif
X/*
X * $Log:	attr.c,v $
X * Revision 3.1  89/02/08  12:45:55  wolfgang
X * performance improved.
X * 
X * Revision 3.0  89/01/24  11:34:30  wolfgang
X * New System Generation
X * 
X * Revision 2.15  89/01/03  12:59:57  wolfgang
X * changes done for lint
X * 
X * Revision 2.14  88/12/21  14:57:30  wolfgang
X * changes done for lint
X * 
X * Revision 2.13  88/11/22  17:25:17  wolfgang
X * bug fixed in pattern().
X * 
X * Revision 2.11  88/11/21  15:51:50  wolfgang
X * return code of all malloc's checked
X * 
X * Revision 2.10  88/10/27  16:39:03  wolfgang
X * bug fixed (new variant handling).
X * 
X * Revision 2.9  88/09/20  10:05:30  wolfgang
X * biug fixed. the offset of 'real' vpath's wasn't correct, if 2 attrvars
X * occured.
X * 
X * Revision 2.8  88/09/19  18:10:19  wolfgang
X * concatenation of vflags added (if more than 1 attrvar occurs).
X * 
X * Revision 2.7  88/09/16  13:29:36  wolfgang
X * minor bug fixed in msg()
X * 
X * Revision 2.6  88/09/16  11:04:11  wolfgang
X * bug fixed in msg.
X * 
X * Revision 2.5  88/09/15  18:42:51  wolfgang
X * bugs in attrvar fixed.
X * 
X * Revision 2.4  88/09/15  12:43:12  wolfgang
X * bug fixed in attrvar.
X * 
X * Revision 2.3  88/09/14  14:04:46  wolfgang
X * new global variable introduced. decomposition of vpath added.
X * 
X * Revision 2.2  88/08/22  15:31:40  wolfgang
X * Handling of two types added: syspath & host; are necessary for the
X * production of confid's.
X * 
X * Revision 2.1  88/08/19  10:16:41  wolfgang
X * This version is part of a release
X * 
X */
X
X#include <stdio.h>
X
X#include "shape.h"
X#include "attr.h"
X
Xextern struct vardef *vardefs[];
Xextern char dollarplus[];
X
Xint err;
Xint pathi;
Xextern char *re_comp();
Xextern int re_exec();
Xextern char *replace();
Xextern char *malloc();
Xextern char *strcpy();
X
Xextern int errexit();
Xextern Bool check_vclass();
Xextern int get_attr_type();
Xextern int get_state_no();
X
XBool pattern(string, patt)
X     char *string;
X     char *patt;
X{
Xchar *retcode;
Xchar *pat;
X
Xif (string == NIL)
X  return(FALSE);
X
Xpat = replace(patt);
X
Xif ((retcode = re_comp(pat)) != 0)
X  {
X    (void) strcat(retcode, ": re_comp");
X    errexit(10, "re_comp");
X  }
X
X#ifdef DEBUG_ATTR
Xprintf("pattern: string = #%s#; pattern = #%s# ", string, pat);
X#endif DEBUG_ATTR
X
Xif (re_exec(string) == 1)
X    return (TRUE);
Xelse
X  return(FALSE);
X}
X
XBool msg(name, value, set)
X     char *name;
X     char *value;
X     /*ARGSUSED*/
X     Af_set *set;
X{
X  char *p;
X  char message2[256];
X  char *message;
X  int len;
X  (void) strcpy(message2,name);
X  if (strcmp(value,""))
X    {
X      (void) strcat(message2,", ");
X      (void) strcat(message2,value);
X    }
X  message = &message2[0];
X
X  len = strlen(message) - 1;
X  
X  if (((message[0] == '\'') && (message[len] == '\'')) ||
X      ((message[0] == '\"') && (message[len] == '\"')))
X    {
X      message[len] = '\0';
X      message++;
X    }
X
X  if (((p = index(message,'$')) != NIL) && (*(p+1) == '+'))
X    {
X      *p = '\0';
X      printf("%s%s%s", message, dollarplus, p+2);
X    }
X  else
X    {
X      if (strcmp(message,""))
X	printf("%s", message);
X    }
X  printf("\n");
X
X  (void) strcpy(dollarplus,"");
X
X  return(TRUE);
X}
X
XBool tunix(name, value, set)
X     /*ARGSUSED*/
X     char *name;
X     char *value;
X     Af_set *set;
X{
X  tunixflg = TRUE;
X  return (TRUE);
X}
X
XBool stopit(name, value, set)
X     /*ARGSUSED*/
X     char *name;
X     char *value;
X     Af_set *set;
X{
X  stopflg = TRUE;
X  return(TRUE);
X}
X
XBool attr(name, value, set)
X     char *name;
X     char *value;
X     Af_set *set;
X{
Xint attr_type;
Xint nrofkeys;
Xint cur_pos;
Xint pos1;
Xint i;
X
XAf_key cur_key;
X
XAf_attrs cur_attrbuf;
X
XBool last_match;
XBool found;
XBool attr_found;
X
Xchar val1[256];
Xchar *val2;
Xchar *val3;
X
X#ifdef DEBUG_ATTR
Xprintf("attr(): name = #%s#,  value = #%s#\n", name,value);
X#endif DEBUG_ATTR
X
X
Xattr_type = get_attr_type(name);
X
Xif ((nrofkeys = af_nrofkeys(set)) == -1)
X  errexit(10, "af_nrofkeys");
X
X#ifdef DEBUG_ATTR
Xprintf("nrofkeys = %d\n", nrofkeys);
X#endif DEBUG_ATTR
X
Xswitch (attr_type)
X  {
X  case 0 :
X    if ((af_sortset(set,AF_ATTGEN)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 1 :
X    if ((af_sortset(set,AF_ATTREV)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 2 :
X    if ((af_sortset(set,AF_ATTSTATE)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 3 :
X    if ((af_sortset(set,AF_ATTAUTHOR)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 4 :
X    errexit(10,"group id");
X    break;
X  case 5 :
X    if ((af_sortset(set,AF_ATTVERSION)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 6 :
X    if ((af_sortset(set,AF_ATTVARIANT)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 7:
X    if ((af_sortset(set,AF_ATTSPATH)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 8:
X    if ((af_sortset(set,AF_ATTHOST)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  default :
X    if ((af_sortset(set,name)) == -1)
X      errexit(10,"af_sortset");
X  }
X
Xcur_pos = 0;
Xlast_match = FALSE;
Xfound = FALSE;
X
Xwhile ((cur_pos < nrofkeys) && (!(last_match)))
X  {
X    if ((err = af_setgkey(set, cur_pos, &cur_key)) == -1)
X      errexit(10, "af_setgkey");
X    
X    if (af_gattrs(&cur_key, &cur_attrbuf) == -1)
X      errexit(10, "af_gattrs");
X
X    switch (attr_type)
X      {
X      case 0 :
X	if (cur_attrbuf.af_gen != atoi(value))
X	  {
X	    if (found)
X	      last_match = TRUE;
X	    else
X	      cur_pos++;    /* here probably better : */
X           /* if (cur_attrbuf.af_gen > atoi(value)) */
X           /*   cur_pos = nrofkeys;                  */
X           /* else                                   */
X           /*   cur_pos++;                           */
X	  }
X	else
X	  {
X	    if (!(found))
X	      {
X		found = TRUE;
X		pos1 = cur_pos;
X	      }
X	    cur_pos++;
X	  }
X	break;
X      case 1 :
X	if (cur_attrbuf.af_rev != atoi(value))
X	  {
X	    if (found)
X	      last_match = TRUE;
X	    else
X	      cur_pos++;
X	  }
X	else
X	  {
X	    if (!(found))
X	      {
X		found = TRUE;
X		pos1 = cur_pos;
X	      }
X	    cur_pos++;
X	  }
X	break;
X      case 2 :
X	if ((int) cur_attrbuf.af_state != get_state_no(value))
X	  {
X	    if (found)
X	      last_match = TRUE;
X	    else
X	      cur_pos++;
X	  }
X	else
X	  {
X	    if (!(found))
X	      {
X		found = TRUE;
X		pos1 = cur_pos;
X	      }
X	    cur_pos++;
X	  }
X	break;
X      case 3 :
X	if (strcmp(cur_attrbuf.af_author.af_username,value))
X	  {
X	    if (found)
X	      last_match = TRUE;
X	    else
X	      cur_pos++;
X	  }
X	else
X	  {
X	    if (!(found))
X	      {
X		found = TRUE;
X		pos1 = cur_pos;
X	      }
X	    cur_pos++;
X	  }
X	break;
X      case 4 :
X	errexit(10,"group id");
X	break;
X      case 5 :
X	(void) strcpy(val1, value);
X	if ((val2 = index(val1,'.')) == 0)
X	  errexit(9, value);
X	val2[0] = '\0';
X	val2++;
X	if ((atoi(val1) == cur_attrbuf.af_gen)
X	    && (atoi(val2) == cur_attrbuf.af_rev))
X	  {
X	    if (!(found))
X	      {
X		found = TRUE;
X		pos1 = cur_pos;
X	      }
X	    cur_pos++;
X	  }
X	else
X	  {
X	    if (found)
X	      last_match = TRUE;
X	    else
X	      cur_pos++;
X	  }
X	break;
X      case 6:
X	/* Variants */
X	if ((strcmp(cur_attrbuf.af_variant,value)) != 0)
X	  {
X	    if (found)
X	      last_match = TRUE;
X	    else
X	      cur_pos++;
X	  }
X	else
X	  {
X	    if (!(found))
X	      {
X		found = TRUE;
X		pos1 = cur_pos;
X	      }
X	    cur_pos++;
X	  }
X	break;
X      case 7 :
X	if (strcmp(cur_attrbuf.af_syspath,value))
X	  {
X	    if (found)
X	      last_match = TRUE;
X	    else
X	      cur_pos++;
X	  }
X	else
X	  {
X	    if (!(found))
X	      {
X		found = TRUE;
X		pos1 = cur_pos;
X	      }
X	    cur_pos++;
X	  }
X	break;
X      case 8 :
X	if (strcmp(cur_attrbuf.af_host,value))
X	  {
X	    if (found)
X	      last_match = TRUE;
X	    else
X	      cur_pos++;
X	  }
X	else
X	  {
X	    if (!(found))
X	      {
X		found = TRUE;
X		pos1 = cur_pos;
X	      }
X	    cur_pos++;
X	  }
X	break;
X      default :
X/* af_udattrs must contain a '=', even if they don't contain a value */
X/* currently only the first value (if existing) in the string is     */
X/* considered */
X	i = 0;
X	attr_found = FALSE;
X/* find name in list of udattrs */
X	while ((!(attr_found)) && (i < AF_MAXUDAS) &&
X	       (cur_attrbuf.af_udattrs[i] != NIL))
X	  {
X	    (void) strcpy(val1, cur_attrbuf.af_udattrs[i]);
X	    if ((val2 = index(val1, '=')) == 0)
X	      errexit(10, "attr");
X	    val2[0] = '\0';
X	    if (strcmp(name, val1) != 0)
X	      i++;
X	    else
X	      attr_found = TRUE;
X	  }
X/* name should be found now */
X	if (!(attr_found))
X	  errexit(10, "attr");
X
X/* value comparison */
X	val2++;
X	if (*val2 == '\0')        /* no value given is considered as != */
X	  {
X	    if (found)
X	      last_match = TRUE;
X	    else
X	      cur_pos++;
X	  }
X	else
X	  {
X	    if ((val3 = index(val2, AF_UDAVALDEL)) != 0) 
X	      val3[0] = '\0';     /* only first value in attrbuf is     */
X                                  /* considered; parameter value should */
X                                  /* contain only one value             */
X	    if (strcmp(value, val2) == 0)
X	      {
X		if (!(found))
X		  {
X		    found = TRUE;
X		    pos1 = cur_pos;
X		  }
X		cur_pos++;
X	      }
X	    else
X	      {
X		if (found)
X		  last_match = TRUE;
X		else
X		  cur_pos++;
X	      }
X	  }
X      }
X  }
X
Xif (!(found))
X  cur_pos = 0;
Xelse
X  {
X    i = pos1;
X    while (i > 0)
X      {
X	if (af_setposrmkey(set, 0) == -1)
X	  errexit(10, "af_setposrmkey");
X	i--;
X	cur_pos--;
X	nrofkeys--;
X      }
X  }
X
Xwhile (cur_pos < nrofkeys)
X  {
X    if (af_setposrmkey(set, cur_pos) == -1)
X      errexit(10, "af_setposrmkey");
X    nrofkeys--;
X  }
Xif (nrofkeys == 0)
X  {
X#ifdef DEBUG_ATTR
X    printf("no matches\n");
X#endif DEBUG_ATTR
X    return (FALSE);
X  }
Xelse
X  {
X#ifdef DEBUG_ATTR
X    printf("matches:\n");
X    nrofkeys = af_nrofkeys(set);
X    i = 0;
X    while (i < nrofkeys)
X      {
X	af_setgkey(set, i, &cur_key);
X	af_gattrs(&cur_key, &cur_attrbuf);
X	printf("version %d.%d\n", cur_attrbuf.af_gen, cur_attrbuf.af_rev);
X	i++;
X      }
X#endif DEBUG_ATTR
X    return (TRUE);
X  }
X}
X
XBool attrnot(name, value, set)
X     char *name;
X     char *value;
X     Af_set *set;
X{
Xint attr_type;
Xint nrofkeys;
Xint cur_pos;
Xint pos1;
Xint i;
X
XAf_key cur_key;
X
XAf_attrs cur_attrbuf;
X
XBool last_match;
XBool found;
XBool attr_found;
X
Xchar val1[256];
Xchar *val2;
Xchar *val3;
X
X#ifdef DEBUG_ATTR
Xprintf("attrnot(): name = #%s#,  value = #%s#\n", name,value);
X#endif DEBUG_ATTR
X
X
Xattr_type = get_attr_type(name);
X
Xif ((nrofkeys = af_nrofkeys(set)) == -1)
X  errexit(10, "af_nrofkeys");
X
X#ifdef DEBUG_ATTR
Xprintf("nrofkeys = %d\n", nrofkeys);
X#endif DEBUG_ATTR
X
Xswitch (attr_type)
X  {
X  case 0 :
X    if ((af_sortset(set,AF_ATTGEN)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 1 :
X    if ((af_sortset(set,AF_ATTREV)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 2 :
X    if ((af_sortset(set,AF_ATTSTATE)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 3 :
X    if ((af_sortset(set,AF_ATTAUTHOR)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 4 :
X    errexit(10,"group id");
X    break;
X  case 5 :
X    if ((af_sortset(set,AF_ATTVERSION)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 6 :
X    if ((af_sortset(set,AF_ATTVARIANT)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 7:
X    if ((af_sortset(set,AF_ATTSPATH)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 8:
X    if ((af_sortset(set,AF_ATTHOST)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  default :
X    if ((af_sortset(set,name)) == -1)
X      errexit(10,"af_sortset");
X  }
X
Xcur_pos = 0;
Xlast_match = FALSE;
Xfound = FALSE;
X
Xwhile ((cur_pos < nrofkeys) && (!(last_match)))
X  {
X    if ((err = af_setgkey(set, cur_pos, &cur_key) == -1))
X      errexit(10, "af_setgkey");
X    
X    if (af_gattrs(&cur_key, &cur_attrbuf) == -1)
X      errexit(10, "af_gattrs");
X
X#ifdef DEBUG_ATTR
X    printf("key[%d] -> version %d.%d\n", cur_pos, cur_attrbuf.af_gen, cur_attrbuf.af_rev);
X#endif DEBUG_ATTR
X
X    switch (attr_type)
X      {
X      case 0 :
X	if (cur_attrbuf.af_gen != atoi(value))
X	  {
X	    if (found)
X	      last_match = TRUE;
X	    else
X	      cur_pos++;    /* here probably better : */
X           /* if (cur_attrbuf.af_gen > atoi(value)) */
X           /*   cur_pos = nrofkeys;                  */
X           /* else                                   */
X           /*   cur_pos++;                           */
X	  }
X	else
X	  {
X	    if (!(found))
X	      {
X		found = TRUE;
X		pos1 = cur_pos;
X	      }
X	    cur_pos++;
X	  }
X	break;
X      case 1 :
X	if (cur_attrbuf.af_rev != atoi(value))
X	  {
X	    if (found)
X	      last_match = TRUE;
X	    else
X	      cur_pos++;
X	  }
X	else
X	  {
X	    if (!(found))
X	      {
X		found = TRUE;
X		pos1 = cur_pos;
X	      }
X	    cur_pos++;
X	  }
X	break;
X      case 2 :
X	if ((int) cur_attrbuf.af_state != atoi(value))
X	  {
X	    if (found)
X	      last_match = TRUE;
X	    else
X	      cur_pos++;
X	  }
X	else
X	  {
X	    if (!(found))
X	      {
X		found = TRUE;
X		pos1 = cur_pos;
X	      }
X	    cur_pos++;
X	  }
X	break;
X      case 3 :
X	if (strcmp(cur_attrbuf.af_author.af_username,value))
X	  {
X	    if (found)
X	      last_match = TRUE;
X	    else
X	      cur_pos++;
X	  }
X	else
X	  {
X	    if (!(found))
X	      {
X		found = TRUE;
X		pos1 = cur_pos;
X	      }
X	    cur_pos++;
X	  }
X	break;
X      case 4 :
X	errexit(10,"group id");
X	break;
X      case 5 :
X	(void) strcpy(val1, value);
X	if ((val2 = index(val1,'.')) == 0)
X	  errexit(9, value);
X	val2[0] = '\0';
X	val2++;
X	if ((atoi(val1) == cur_attrbuf.af_gen)
X	    && (atoi(val2) == cur_attrbuf.af_rev))
X	  {
X	    if (!(found))
X	      {
X		found = TRUE;
X		pos1 = cur_pos;
X	      }
X	    cur_pos++;
X	  }
X	else
X	  {
X	    if (found)
X	      last_match = TRUE;
X	    else
X	      cur_pos++;
X	  }
X	break;
X      case 6:
X	/* Variants */
X	if ((strcmp(cur_attrbuf.af_variant,value)) != 0)
X	  {
X	    if (found)
X	      last_match = TRUE;
X	    else
X	      cur_pos++;
X	  }
X	else
X	  {
X	    if (!(found))
X	      {
X		found = TRUE;
X		pos1 = cur_pos;
X	      }
X	    cur_pos++;
X	  }
X	break;
X      case 7 :
X	if (strcmp(cur_attrbuf.af_syspath,value))
X	  {
X	    if (found)
X	      last_match = TRUE;
X	    else
X	      cur_pos++;
X	  }
X	else
X	  {
X	    if (!(found))
X	      {
X		found = TRUE;
X		pos1 = cur_pos;
X	      }
X	    cur_pos++;
X	  }
X	break;
X      case 8 :
X	if (strcmp(cur_attrbuf.af_host,value))
X	  {
X	    if (found)
X	      last_match = TRUE;
X	    else
X	      cur_pos++;
X	  }
X	else
X	  {
X	    if (!(found))
X	      {
X		found = TRUE;
X		pos1 = cur_pos;
X	      }
X	    cur_pos++;
X	  }
X	break;
X      default :
X/* af_udattrs must contain a '=', even if they don't contain a value */
X/* currently only the first value (if existing) in the string is     */
X/* considered */
X	i = 0;
X	attr_found = FALSE;
X/* find name in list of udattrs */
X	while ((!(attr_found)) && (i < AF_MAXUDAS) &&
X	       (cur_attrbuf.af_udattrs[i] != NIL))
X	  {
X	    (void) strcpy(val1, cur_attrbuf.af_udattrs[i]);
X	    if ((val2 = index(val1, '=')) == 0)
X	      errexit(10, "attrnot");
X	    val2[0] = '\0';
X	    if (strcmp(name, val1) != 0)
X	      i++;
X	    else
X	      attr_found = TRUE;
X	  }
X/* name should be found now */
X	if (!(attr_found))
X	  errexit(10, "attrnot");
X
X/* value comparison */
X	val2++;
X	if (*val2 == '\0')        /* no value given is considered as != */
X	  {
X	    if (found)
X	      last_match = TRUE;
X	    else
X	      cur_pos++;
X	  }
X	else
X	  {
X	    if ((val3 = index(val2, AF_UDAVALDEL)) != 0) 
X	      val3[0] = '\0';     /* only first value in attrbuf is     */
X                                  /* considered; parameter value should */
X                                  /* contain only one value             */
X	    if (strcmp(value, val2) == 0)
X	      {
X		if (!(found))
X		  {
X		    found = TRUE;
X		    pos1 = cur_pos;
X		  }
X		cur_pos++;
X	      }
X	    else
X	      {
X		if (found)
X		  last_match = TRUE;
X		else
X		  cur_pos++;
X	      }
X	  }
X      }
X  }
X
Xif (!(found))
X  {
X#ifdef DEBUG_ATTR
X    printf("matches:\n");
X    i = 0;
X    while (i < nrofkeys)
X      {
X	af_setgkey(set, i, &cur_key);
X	af_gattrs(&cur_key, &cur_attrbuf);
X	printf("version %d.%d\n", cur_attrbuf.af_gen, cur_attrbuf.af_rev);
X	i++;
X      }
X#endif DEBUG_ATTR
X
X    return (TRUE);
X  }
Xelse
X  {
X    i = (cur_pos - pos1);
X    while (i > 0)
X      {
X	if (af_setposrmkey(set, pos1) == -1)
X	  errexit(10, "af_setposrmkey");
X	i--;
X	nrofkeys--;
X      }
X    if (nrofkeys == 0)
X      {
X#ifdef DEBUG_ATTR
X	printf("no match\n");
X#endif DEBUG_ATTR
X	return (FALSE);
X      }
X    else
X      {
X#ifdef DEBUG_ATTR
X	printf("matches:\n");
X	nrofkeys = af_nrofkeys(set);
X	i = 0;
X	while (i < nrofkeys)
X	  {
X	    af_setgkey(set, i, &cur_key);
X	    af_gattrs(&cur_key, &cur_attrbuf);
X	    printf("version %d.%d\n", cur_attrbuf.af_gen, cur_attrbuf.af_rev);
X	    i++;
X	  }
X#endif DEBUG_ATTR
X
X	return (TRUE);
X      }
X  }
X}
X
XBool attrlt(name, value, set)
X     char *name;
X     char *value;
X     Af_set *set;
X{
Xint attr_type;
Xint nrofkeys;
Xint cur_pos;
Xint i;
X
XAf_key cur_key;
X
XAf_attrs cur_attrbuf;
X
XBool match;
XBool found;
X
Xchar val1[256];
Xchar *val2;
Xchar *val3;
X
X#ifdef DEBUG_ATTR
Xprintf("attrlt(): name = #%s#,  value = #%s#\n", name,value);
X#endif DEBUG_ATTR
X
X
Xattr_type = get_attr_type(name);
X
Xif ((nrofkeys = af_nrofkeys(set)) == -1)
X  errexit(10, "af_nrofkeys");
X
X#ifdef DEBUG_ATTR
Xprintf("nrofkeys = %d\n", nrofkeys);
X#endif DEBUG_ATTR
X
Xswitch (attr_type)
X  {
X  case 0 :
X    if ((af_sortset(set,AF_ATTGEN)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 1 :
X    if ((af_sortset(set,AF_ATTREV)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 2 :
X    if ((af_sortset(set,AF_ATTSTATE)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 3 :
X    if ((af_sortset(set,AF_ATTAUTHOR)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 4 :
X    errexit(10,"group id");
X    break;
X  case 5 :
X    if ((af_sortset(set,AF_ATTVERSION)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 6 :
X    if ((af_sortset(set,AF_ATTVARIANT)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 7:
X    if ((af_sortset(set,AF_ATTSPATH)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 8:
X    if ((af_sortset(set,AF_ATTHOST)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  default :
X    if ((af_sortset(set,name)) == -1)
X      errexit(10,"af_sortset");
X  }
X
Xcur_pos = 0;
Xmatch = TRUE;
X
Xwhile ((cur_pos < nrofkeys) && match)
X  {
X    if ((err = af_setgkey(set, cur_pos, &cur_key)) == -1)
X      errexit(10, "af_setgkey");
X    
X    if (af_gattrs(&cur_key, &cur_attrbuf) == -1)
X      errexit(10, "af_gattrs");
X
X#ifdef DEBUG_ATTR
X    printf("key[%d] -> version %d.%d\n", cur_pos, cur_attrbuf.af_gen, cur_attrbuf.af_rev);
X#endif DEBUG_ATTR
X
X    switch (attr_type)
X      {
X      case 0 :
X	if (cur_attrbuf.af_gen < atoi(value))
X	  cur_pos++;
X	else
X	  match = FALSE;
X	break;
X      case 1 :
X	if (cur_attrbuf.af_rev < atoi(value))
X	  cur_pos++;
X	else
X	  match = FALSE;
X	break;
X      case 2 :
X	if ((int) cur_attrbuf.af_state < atoi(value))
X	  cur_pos++;
X	else
X	  match = FALSE;
X	break;
X      case 3 :
X	if ((strcmp(cur_attrbuf.af_author.af_username,value)) < 0)
X	  cur_pos++;
X	else
X	  match = FALSE;
X	break;
X      case 4 :
X	errexit(10,"group id");
X	break;
X      case 5 :
X	(void) strcpy(val1, value);
X	if ((val2 = index(val1,'.')) == 0)
X	  errexit(9, value);
X	val2[0] = '\0';
X	val2++;
X	if (atoi(val1) < cur_attrbuf.af_gen)
X	  match = FALSE;
X	else
X	  {
X	    if ((atoi(val1) == cur_attrbuf.af_gen) &&
X		(atoi(val2) <= cur_attrbuf.af_rev))
X	      match = FALSE;
X	    else
X	      cur_pos++;
X	  }
X	break;
X      case 6:
X	/* Variants */
X	if ((strcmp(cur_attrbuf.af_variant,value)) < 0)
X	  cur_pos++;
X	else
X	  match = FALSE;
X	break;
X      case 7 :
X	if ((strcmp(cur_attrbuf.af_syspath,value)) < 0)
X	  cur_pos++;
X	else
X	  match = FALSE;
X	break;
X      case 8 :
X	if ((strcmp(cur_attrbuf.af_host,value)) < 0 )
X	  cur_pos++;
X	else
X	  match = FALSE;
X	break;
X      default :
X/* af_udattrs must contain a '=', even if they don't contain a value */
X/* currently only the first value (if existing) in the string is     */
X/* considered */
X	i = 0;
X	found = FALSE;
X/* find name in list of udattrs */
X	while ((!(found)) && (i < AF_MAXUDAS) &&
X	       (cur_attrbuf.af_udattrs[i] != NIL))
X	  {
X	    (void) strcpy(val1, cur_attrbuf.af_udattrs[i]);
X	    if ((val2 = index(val1, '=')) == 0)
X	      errexit(10, "attrlt");
X	    val2[0] = '\0';
X	    if (strcmp(name, val1) != 0)
X	      i++;
X	    else
X	      found = TRUE;
X	  }
X/* name should be found now */
X	if (!(found))
X	  errexit(10, "attrlt");
X
X/* value comparison */
X	val2++;
X	if (*val2 == '\0')        /* no value given is considered as != */
X	  cur_pos++;
X	else
X	  {
X	    if ((val3 = index(val2, AF_UDAVALDEL)) != 0) 
X	      val3[0] = '\0';     /* only first value in attrbuf is     */
X                                  /* considered; parameter value should */
X                                  /* contain only one value             */
X	    if (strcmp(value, val2) <= 0)
X	      match = FALSE;
X	    else
X	      cur_pos++;
X	  }
X      }
X  }  
Xif (match)
X  {
X#ifdef DEBUG_ATTR
X    printf("matches:\n");
X    i = 0;
X    while (i < nrofkeys)
X      {
X	af_setgkey(set, i, &cur_key);
X	af_gattrs(&cur_key, &cur_attrbuf);
X	printf("version %d.%d\n", cur_attrbuf.af_gen, cur_attrbuf.af_rev);
X	i++;
X      }
X#endif DEBUG_ATTR
X
X    return (TRUE);
X  }
Xelse                             /* remove keys from set if necessary */
X  {
X    while (cur_pos < nrofkeys)
X      {
X	if (af_setposrmkey(set, cur_pos) == -1)
X	  errexit(10, "af_setposrmkey");
X	nrofkeys--;
X      }
X    if (nrofkeys == 0)
X      {
X#ifdef DEBUG_ATTR
X	printf("no matches\n");
X#endif DEBUG_ATTR
X
X	return (FALSE);
X      }
X    else
X      {
X#ifdef DEBUG_ATTR
X	printf("matches:\n");
X	nrofkeys = af_nrofkeys(set);
X	i = 0;
X	while (i < nrofkeys)
X	  {
X	    af_setgkey(set, i, &cur_key);
X	    af_gattrs(&cur_key, &cur_attrbuf);
X	    printf("version %d.%d\n", cur_attrbuf.af_gen, cur_attrbuf.af_rev);
X	    i++;
X	  }
X#endif DEBUG_ATTR
X
X	return (TRUE);
X      }
X  }
X
X}
X
XBool attrgt(name, value, set)
X     char *name;
X     char *value;
X     Af_set *set;
X{
Xint attr_type;
Xint nrofkeys;
Xint cur_pos;
Xint i;
X
XAf_key cur_key;
X
XAf_attrs cur_attrbuf;
X
XBool match;
XBool found;
X
Xchar val1[256];
Xchar *val2;
Xchar *val3;
X
X#ifdef DEBUG_ATTR
Xprintf("attrgt(): name = #%s#,  value = #%s#\n", name,value);
X#endif DEBUG_ATTR
X
Xattr_type = get_attr_type(name);
X
Xif ((nrofkeys = af_nrofkeys(set)) == -1)
X  errexit(10, "af_nrofkeys");
X
X#ifdef DEBUG_ATTR
Xprintf("nrofkeys = %d\n", nrofkeys);
X#endif DEBUG_ATTR
X
Xswitch (attr_type)
X  {
X  case 0 :
X    if ((af_sortset(set,AF_ATTGEN)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 1 :
X    if ((af_sortset(set,AF_ATTREV)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 2 :
X    if ((af_sortset(set,AF_ATTSTATE)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 3 :
X    if ((af_sortset(set,AF_ATTAUTHOR)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 4 :
X    errexit(10,"group id");
X    break;
X  case 5 :
X    if ((af_sortset(set,AF_ATTVERSION)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 6 :
X    if ((af_sortset(set,AF_ATTVARIANT)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 7:
X    if ((af_sortset(set,AF_ATTSPATH)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 8:
X    if ((af_sortset(set,AF_ATTHOST)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  default :
X    if ((af_sortset(set,name)) == -1)
X      errexit(10,"af_sortset");
X  }
X
Xcur_pos = (nrofkeys - 1);
Xmatch = TRUE;
X
Xwhile ((cur_pos >= 0) && match)
X  {
X    if ((err = af_setgkey(set, cur_pos, &cur_key)) == -1)
X      errexit(10, "af_setgkey");
X    
X    if (af_gattrs(&cur_key, &cur_attrbuf) == -1)
X      errexit(10, "af_gattrs");
X
X#ifdef DEBUG_ATTR
X    printf("key[%d] -> version %d.%d\n", cur_pos, cur_attrbuf.af_gen, cur_attrbuf.af_rev);
X#endif DEBUG_ATTR
X
X    switch (attr_type)
X      {
X      case 0 :
X	if (cur_attrbuf.af_gen > atoi(value))
X	  cur_pos--;
X	else
X	  match = FALSE;
X	break;
X      case 1 :
X	if (cur_attrbuf.af_rev > atoi(value))
X	  cur_pos--;
X	else
X	  match = FALSE;
X	break;
X      case 2 :
X	if ((int) cur_attrbuf.af_state > atoi(value))
X	  cur_pos--;
X	else
X	  match = FALSE;
X	break;
X      case 3 :
X	if ((strcmp(cur_attrbuf.af_author.af_username,value)) > 0)
X	  cur_pos--;
X	else
X	  match = FALSE;
X	break;
X      case 4 :
X	errexit(10,"group id");
X	break;
X      case 5 :
X	(void) strcpy(val1, value);
X	if ((val2 = index(val1,'.')) == 0)
X	  errexit(9, value);
X	val2[0] = '\0';
X	val2++;
X	if (atoi(val1) > cur_attrbuf.af_gen)
X	  match = FALSE;
X	else
X	  {
X	    if ((atoi(val1) == cur_attrbuf.af_gen) &&
X		(atoi(val2) >= cur_attrbuf.af_rev))
X	      match = FALSE;
X	    else
X	      cur_pos--;
X	  }
X	break;
X      case 6:
X	/* Variants */
X	if ((strcmp(cur_attrbuf.af_variant,value))  > 0)
X	  cur_pos--;
X	else
X	  match = FALSE;
X	break;
X      case 7 :
X	if ((strcmp(cur_attrbuf.af_syspath,value)) > 0)
X	  cur_pos--;
X	else
X	  match = FALSE;
X	break;
X      case 8 :
X	if ((strcmp(cur_attrbuf.af_host,value)) > 0)
X	  cur_pos--;
X	else
X	  match = FALSE;
X	break;
X      default :
X/* af_udattrs must contain a '=', even if they don't contain a value */
X/* currently only the first value (if existing) in the string is     */
X/* considered */
X	i = 0;
X	found = FALSE;
X/* find name in list of udattrs */
X	while ((!(found)) && (i < AF_MAXUDAS) &&
X	       (cur_attrbuf.af_udattrs[i] != NIL))
X	  {
X	    (void) strcpy(val1, cur_attrbuf.af_udattrs[i]);
X	    if ((val2 = index(val1, '=')) == 0)
X	      errexit(10, "attrgt");
X	    val2[0] = '\0';
X	    if (strcmp(name, val1) != 0)
X	      i++;
X	    else
X	      found = TRUE;
X	  }
X/* name should be found now */
X	if (!(found))
X	  errexit(10, "attrgt");
X
X/* value comparison */
X	val2++;
X	if (*val2 == '\0')        /* no value given is considered as < */
X	  match = FALSE;
X	else
X	  {
X	    if ((val3 = index(val2, AF_UDAVALDEL)) != 0) 
X	      val3[0] = '\0';     /* only first value is considered */
X	    if (strcmp(value, val2) >= 0)
X	      match = FALSE;
X	    else
X	      cur_pos--;
X	  }
X      }
X  }
Xif (match)
X  {
X#ifdef DEBUG_ATTR
X    printf("matches:\n");
X    i = 0;
X    while (i < nrofkeys)
X      {
X	af_setgkey(set, i, &cur_key);
X	af_gattrs(&cur_key, &cur_attrbuf);
X	printf("version %d.%d\n", cur_attrbuf.af_gen, cur_attrbuf.af_rev);
X	i++;
X      }
X#endif DEBUG_ATTR
X
X    return (TRUE);
X  }
Xelse                             /* remove keys from set if necessary */
X  {
X    while (cur_pos >= 0)
X      {
X	if (af_setposrmkey(set, cur_pos) == -1)
X	  errexit(10, "af_setposrmkey");
X	cur_pos--;
X	nrofkeys--;
X      }
X    if (nrofkeys == 0)
X      {
X#ifdef DEBUG_ATTR
X	printf("no matches\n");
X#endif DEBUG_ATTR
X
X	return (FALSE);
X      }
X    else
X      {
X#ifdef DEBUG_ATTR
X	printf("matches:\n");
X	nrofkeys = af_nrofkeys(set);
X	i = 0;
X	while (i < nrofkeys)
X	  {
X	    af_setgkey(set, i, &cur_key);
X	    af_gattrs(&cur_key, &cur_attrbuf);
X	    printf("version %d.%d\n", cur_attrbuf.af_gen, cur_attrbuf.af_rev);
X	    i++;
X	  }
X#endif DEBUG_ATTR
X
X	return (TRUE);
X      }
X  }
X}
X
XBool attrle(name, value, set)
X     char *name;
X     char *value;
X     Af_set *set;
X{
Xint attr_type;
Xint nrofkeys;
Xint cur_pos;
Xint i;
X
XAf_key cur_key;
X
XAf_attrs cur_attrbuf;
X
XBool match;
XBool found;
X
Xchar val1[256];
Xchar *val2;
Xchar *val3;
X
X#ifdef DEBUG_ATTR
Xprintf("attrle(): name = #%s#,  value = #%s#\n", name,value);
X#endif DEBUG_ATTR
X
Xattr_type = get_attr_type(name);
X
Xif ((nrofkeys = af_nrofkeys(set)) == -1)
X  errexit(10, "af_nrofkeys");
X
X#ifdef DEBUG_ATTR
Xprintf("nrofkeys = %d\n", nrofkeys);
X#endif DEBUG_ATTR
X
Xswitch (attr_type)
X  {
X  case 0 :
X    if ((af_sortset(set,AF_ATTGEN)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 1 :
X    if ((af_sortset(set,AF_ATTREV)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 2 :
X    if ((af_sortset(set,AF_ATTSTATE)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 3 :
X    if ((af_sortset(set,AF_ATTAUTHOR)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 4 :
X    errexit(10,"group id");
X    break;
X  case 5 :
X    if ((af_sortset(set,AF_ATTVERSION)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 6 :
X    if ((af_sortset(set,AF_ATTVARIANT)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 7:
X    if ((af_sortset(set,AF_ATTSPATH)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 8:
X    if ((af_sortset(set,AF_ATTHOST)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  default :
X    if ((af_sortset(set,name)) == -1)
X      errexit(10,"af_sortset");
X  }
X
Xcur_pos = 0;
Xmatch = TRUE;
X
Xwhile ((cur_pos < nrofkeys) && match)
X  {
X    if ((err = af_setgkey(set, cur_pos, &cur_key)) == -1)
X      errexit(10, "af_setgkey");
X    
X    if (af_gattrs(&cur_key, &cur_attrbuf) == -1)
X      errexit(10, "af_gattrs");
X
X#ifdef DEBUG_ATTR
X    printf("key[%d] -> version %d.%d\n", cur_pos, cur_attrbuf.af_gen, cur_attrbuf.af_rev);
X#endif DEBUG_ATTR
X
X    switch (attr_type)
X      {
X      case 0 :
X	if (cur_attrbuf.af_gen <= atoi(value))
X	  cur_pos++;
X	else
X	  match = FALSE;
X	break;
X      case 1 :
X	if (cur_attrbuf.af_rev <= atoi(value))
X	  cur_pos++;
X	else
X	  match = FALSE;
X	break;
X      case 2 :
X	if ((int) cur_attrbuf.af_state <= atoi(value))
X	  cur_pos++;
X	else
X	  match = FALSE;
X	break;
X      case 3 :
X	if ((strcmp(cur_attrbuf.af_author.af_username,value)) <= 0)
X	  cur_pos++;
X	else
X	  match = FALSE;
X	break;
X      case 4 :
X	errexit(10,"group id");
X	break;
X      case 5 :
X	(void) strcpy(val1, value);
X	if ((val2 = index(val1,'.')) == 0)
X	  errexit(9, value);
X	val2[0] = '\0';
X	val2++;
X	if (atoi(val1) < cur_attrbuf.af_gen)
X	  match = FALSE;
X	else
X	  {
X	    if ((atoi(val1) == cur_attrbuf.af_gen) &&
X		(atoi(val2) < cur_attrbuf.af_rev))
X	      match = FALSE;
X	    else
X	      cur_pos++;
X	  }
X	break;
X      case 6:
X	/* Variants */
X	if ((strcmp(cur_attrbuf.af_variant,value)) <= 0)
X	  cur_pos++;
X	else
X	  match = FALSE;
X	break;
X      case 7 :
X	if ((strcmp(cur_attrbuf.af_syspath,value)) <= 0)
X	  cur_pos++;
X	else
X	  match = FALSE;
X	break;
X      case 8 :
X	if ((strcmp(cur_attrbuf.af_host,value)) <= 0)
X	  cur_pos++;
X	else
X	  match = FALSE;
X	break;
X      default :
X/* af_udattrs must contain a '=', even if they don't contain a value */
X/* currently only the first value (if existing) in the string is     */
X/* considered */
X	i = 0;
X	found = FALSE;
X/* find name in list of udattrs */
X	while ((!(found)) && (i < AF_MAXUDAS) &&
X	       (cur_attrbuf.af_udattrs[i] != NIL))
X	  {
X	    (void) strcpy(val1, cur_attrbuf.af_udattrs[i]);
X	    if ((val2 = index(val1, '=')) == 0)
X	      errexit(10, "attrle");
X	    val2[0] = '\0';
X	    if (strcmp(name, val1) != 0)
X	      i++;
X	    else
X	      found = TRUE;
X	  }
X/* name should be found now */
X	if (!(found))
X	  errexit(10, "attrle");
X
X/* value comparison */
X	val2++;
X	if (*val2 == '\0')        /* no value given is considered as <= */
X	  cur_pos++;
X	else
X	  {
X	    if ((val3 = index(val2, AF_UDAVALDEL)) != 0) 
X	      val3[0] = '\0';     /* only first value is considered */
X	    if (strcmp(value, val2) < 0)
X	      match = FALSE;
X	    else
X	      cur_pos++;
X	  }
X      }
X  }  
Xif (match)
X  {
X#ifdef DEBUG_ATTR
X    printf("matches:\n");
X    i = 0;
X    while (i < nrofkeys)
X      {
X	af_setgkey(set, i, &cur_key);
X	af_gattrs(&cur_key, &cur_attrbuf);
X	printf("version %d.%d\n", cur_attrbuf.af_gen, cur_attrbuf.af_rev);
X	i++;
X      }
X#endif DEBUG_ATTR
X    return (TRUE);
X  }
Xelse                             /* remove keys from set if necessary */
X  {
X    while (cur_pos < nrofkeys)
X      {
X	if (af_setposrmkey(set, cur_pos) == -1)
X	  errexit(10, "af_setposrmkey");
X	nrofkeys--;
X      }
X    if (nrofkeys == 0)
X      {
X#ifdef DEBUG_ATTR
X	printf("no matches\n");
X#endif DEBUG_ATTR
X
X	return (FALSE);
X      }
X    else
X      {
X#ifdef DEBUG_ATTR
X	printf("matches:\n");
X	nrofkeys = af_nrofkeys(set);
X	i = 0;
X	while (i < nrofkeys)
X	  {
X	    af_setgkey(set, i, &cur_key);
X	    af_gattrs(&cur_key, &cur_attrbuf);
X	    printf("version %d.%d\n", cur_attrbuf.af_gen, cur_attrbuf.af_rev);
X	    i++;
X	  }
X#endif DEBUG_ATTR
X
X	return (TRUE);
X      }
X  }
X	    
X}
X
X
XBool attrge(name , value, set)
X     char *name;
X     char *value;
X     Af_set *set;
X{
Xint attr_type;
Xint nrofkeys;
Xint cur_pos;
Xint i;
X
XAf_key cur_key;
X
XAf_attrs cur_attrbuf;
X
XBool match;
XBool found;
X
Xchar val1[256];
Xchar *val2;
Xchar *val3;
X
X#ifdef DEBUG_ATTR
Xprintf("attrge(): name = #%s#,  value = #%s#\n", name,value);
X#endif DEBUG_ATTR
X
Xattr_type = get_attr_type(name);
X
Xif ((nrofkeys = af_nrofkeys(set)) == -1)
X  errexit(10, "af_nrofkeys");
X
X#ifdef DEBUG_ATTR
Xprintf("nrofkeys = %d\n", nrofkeys);
X#endif DEBUG_ATTR
X
Xswitch (attr_type)
X  {
X  case 0 :
X    if ((af_sortset(set,AF_ATTGEN)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 1 :
X    if ((af_sortset(set,AF_ATTREV)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 2 :
X    if ((af_sortset(set,AF_ATTSTATE)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 3 :
X    if ((af_sortset(set,AF_ATTAUTHOR)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 4 :
X    errexit(10,"group id");
X    break;
X  case 5 :
X    if ((af_sortset(set,AF_ATTVERSION)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 6 :
X    if ((af_sortset(set,AF_ATTVARIANT)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 7:
X    if ((af_sortset(set,AF_ATTSPATH)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 8:
X    if ((af_sortset(set,AF_ATTHOST)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  default :
X    if ((af_sortset(set,name)) == -1)
X      errexit(10,"af_sortset");
X  }
X
Xcur_pos = (nrofkeys - 1);
Xmatch = TRUE;
X
Xwhile ((cur_pos >= 0) && match)
X  {
X    if ((err = af_setgkey(set, cur_pos, &cur_key)) == -1)
X      errexit(10, "af_setgkey");
X    
X    if (af_gattrs(&cur_key, &cur_attrbuf) == -1)
X      errexit(10, "af_gattrs");
X
X#ifdef DEBUG_ATTR
X    printf("key[%d] -> version %d.%d\n", cur_pos, cur_attrbuf.af_gen, cur_attrbuf.af_rev);
X#endif DEBUG_ATTR
X
X    switch (attr_type)
X      {
X      case 0 :
X	if (cur_attrbuf.af_gen >= atoi(value))
X	  cur_pos--;
X	else
X	  match = FALSE;
X	break;
X      case 1 :
X	if (cur_attrbuf.af_rev >= atoi(value))
X	  cur_pos--;
X	else
X	  match = FALSE;
X	break;
X      case 2 :
X	if ((int) cur_attrbuf.af_state >= get_state_no(value))
X	  cur_pos--;
X	else
X	  match = FALSE;
X	break;
X      case 3 :
X	if ((strcmp(cur_attrbuf.af_author.af_username,value)) >= 0)
X	  cur_pos--;
X	else
X	  match = FALSE;
X	break;
X      case 4 :
X	errexit(10,"group id");
X	break;
X      case 5 :
X	(void) strcpy(val1, value);
X	if ((val2 = index(val1,'.')) == 0)
X	  errexit(9, value);
X	val2[0] = '\0';
X	val2++;
X	if (atoi(val1) > cur_attrbuf.af_gen)
X	  match = FALSE;
X	else
X	  {
X	    if ((atoi(val1) == cur_attrbuf.af_gen) &&
X		(atoi(val2) > cur_attrbuf.af_rev))
X	      match = FALSE;
X	    else
X	      cur_pos--;
X	  }
X	break;
X      case 6:
X	/* Variants */
X	if ((strcmp(cur_attrbuf.af_variant,value)) >= 0)
X	  cur_pos--;
X	else
X	  match = FALSE;
X	break;
X      case 7 :
X	if ((strcmp(cur_attrbuf.af_syspath,value)) >= 0)
X	  cur_pos--;
X	else
X	  match = FALSE;
X	break;
X      case 8 :
X	if ((strcmp(cur_attrbuf.af_host,value)) >= 0)
X	  cur_pos--;
X	else
X	  match = FALSE;
X	break;
X      default :
X/* af_udattrs must contain a '=', even if they don't contain a value */
X/* currently only the first value (if existing) in the string is     */
X/* considered */
X	i = 0;
X	found = FALSE;
X/* find name in list of udattrs */
X	while ((!(found)) && (i < AF_MAXUDAS) &&
X	       (cur_attrbuf.af_udattrs[i] != NIL))
X	  {
X	    (void) strcpy(val1, cur_attrbuf.af_udattrs[i]);
X	    if ((val2 = index(val1, '=')) == 0)
X	      errexit(10, "attrge");
X	    val2[0] = '\0';
X	    if (strcmp(name, val1) != 0)
X	      i++;
X	    else
X	      found = TRUE;
X	  }
X/* name should be found now */
X	if (!(found))
X	  errexit(10, "attrge");
X
X/* value comparison */
X	val2++;
X	if (*val2 == '\0')        /* no value given is considered as < */
X	  match = FALSE;
X	else
X	  {
X	    if ((val3 = index(val2, AF_UDAVALDEL)) != 0) 
X	      val3[0] = '\0';     /* only first value is considered */
X	    if (strcmp(value, val2) > 0)
X	      match = FALSE;
X	    else
X	      cur_pos--;
X	  }
X      }
X  }
Xif (match)
X  {
X#ifdef DEBUG_ATTR
X    printf("matches:\n");
X    i = 0;
X    while (i < nrofkeys)
X      {
X	af_setgkey(set, i, &cur_key);
X	af_gattrs(&cur_key, &cur_attrbuf);
X	printf("version %d.%d\n", cur_attrbuf.af_gen, cur_attrbuf.af_rev);
X	i++;
X      }
X#endif DEBUG_ATTR
X
X    return (TRUE);
X  }
Xelse                             /* remove keys from set if necessary */
X  {
X    while (cur_pos >= 0)
X      {
X	if (af_setposrmkey(set, cur_pos) == -1)
X	  errexit(10, "af_setposrmkey");
X	cur_pos--;
X	nrofkeys--;
X      }
X    if (nrofkeys == 0)
X      {
X#ifdef DEBUG_ATTR
X	printf("no matches\n");
X#endif DEBUG_ATTR
X
X	return (FALSE);
X      }
X    else
X      {
X#ifdef DEBUG_ATTR
X	printf("matches:\n");
X	nrofkeys = af_nrofkeys(set);
X	i = 0;
X	while (i < nrofkeys)
X	  {
X	    af_setgkey(set, i, &cur_key);
X	    af_gattrs(&cur_key, &cur_attrbuf);
X	    printf("version %d.%d\n", cur_attrbuf.af_gen, cur_attrbuf.af_rev);
X	    i++;
X	  }
X#endif DEBUG_ATTR
X
X	return (TRUE);
X      }
X  }
X
X}
X
X
X
XBool attrmax(name, value, set)
X     char *name;
X     char *value;
X     Af_set *set;
X{
Xint attr_type;
Xint nrofkeys;
Xint cur_pos;
Xint i;
Xint udattr_pos;
X
XAf_key cur_key;
X
XAf_attrs cur_attrbuf;
XAf_attrs max_attrbuf;
X
XBool match;
XBool found;
X
Xchar val1[256];
Xchar *val2;
X
X#ifdef DEBUG_ATTR
Xprintf("attrmax(): name = #%s#\n", name);
X#endif DEBUG_ATTR
X
Xattr_type = get_attr_type(name);
X
Xif ((nrofkeys = af_nrofkeys(set)) == -1)
X  errexit(10, "af_nrofkeys");
X
X#ifdef DEBUG_ATTR
Xprintf("nrofkeys = %d\n", nrofkeys);
X#endif DEBUG_ATTR
X
Xswitch (attr_type)
X  {
X  case 0 :
X    if ((af_sortset(set,AF_ATTGEN)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 1 :
X    if ((af_sortset(set,AF_ATTREV)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 2 :
X    if ((af_sortset(set,AF_ATTSTATE)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 3 :
X    if ((af_sortset(set,AF_ATTAUTHOR)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 4 :
X    errexit(10,"group id");
X    break;
X  case 5 :
X    if ((af_sortset(set,AF_ATTVERSION)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 6 :
X    if ((af_sortset(set,AF_ATTVARIANT)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 7:
X    if ((af_sortset(set,AF_ATTSPATH)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 8:
X    if ((af_sortset(set,AF_ATTHOST)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  default :
X    if ((af_sortset(set,name)) == -1)
X      errexit(10,"af_sortset");
X  }
X
Xif (nrofkeys == 1)
X  {
X#ifdef DEBUG_ATTR
X    printf("one match :\n");
X    af_setgkey(set, 0, &cur_key);
X    af_gattrs(&cur_key, &cur_attrbuf);
X    printf("version %d.%d\n", cur_attrbuf.af_gen, cur_attrbuf.af_rev);
X#endif DEBUG_ATTR
X
X    return (TRUE);
X  }
Xelse
X  {
X    if (nrofkeys == 0)
X      {
X#ifdef DEBUG_ATTR
X	printf("no match\n");
X#endif DEBUG_ATTR
X	return (FALSE);
X      }
X  }
X
Xcur_pos = (nrofkeys - 1);
Xmatch = TRUE;
X
Xif ((err = af_setgkey(set, cur_pos, &cur_key)) == -1)
X  errexit(10, "af_setgkey");
Xif (af_gattrs(&cur_key, &max_attrbuf) == -1)
X  errexit(10, "af_gattrs");
Xcur_pos--;
X
Xif (attr_type > STD_ATTRS)  /* if looking for udattrs  */
X/* name has to be found in list of udattrs     */
X  {
X    udattr_pos = 0;
X    found = FALSE;
X/* find name in list of udattrs */
X    while ((!(found)) && (udattr_pos < AF_MAXUDAS) &&
X	   (max_attrbuf.af_udattrs[udattr_pos] != NIL))
X      {
X	(void) strcpy(val1, max_attrbuf.af_udattrs[udattr_pos]);
X	if ((val2 = index(val1, '=')) == 0)
X	  errexit(10, "attrmax");
X	val2[0] = '\0';
X	if (strcmp(name, val1) != 0)
X	  udattr_pos++;
X	else
X	  found = TRUE;
X      }
X/* name should be found now */
X    if (!(found))
X      errexit(10, "attrmax");
X  }
X
Xwhile ((cur_pos >= 0) && match)
X  {
X    if ((err = af_setgkey(set, cur_pos, &cur_key)) == -1)
X      errexit(10, "af_setgkey");
X    
X    if (af_gattrs(&cur_key, &cur_attrbuf) == -1)
X      errexit(10, "af_gattrs");
X
X#ifdef DEBUG_ATTR
X    printf("key[%d] -> version %d.%d\n", cur_pos, cur_attrbuf.af_gen, cur_attrbuf.af_rev);
X#endif DEBUG_ATTR
X
X    switch (attr_type)
X      {
X      case 0 :
X	if (cur_attrbuf.af_gen == max_attrbuf.af_gen)
X	  cur_pos--;
X	else
X	  match = FALSE;
X	break;
X      case 1 :
X	if (cur_attrbuf.af_rev == max_attrbuf.af_rev)
X	  cur_pos--;
X	else
X	  match = FALSE;
X	break;
X      case 2 :
X	if (cur_attrbuf.af_state == max_attrbuf.af_state)
X	  cur_pos--;
X	else
X	  match = FALSE;
X	break;
X      case 3 :
X	if(!strcmp(cur_attrbuf.af_author.af_username,max_attrbuf.af_author.af_username))
X	  cur_pos--;
X	else
X	  match = FALSE;
X	break;
X      case 4 :
X	errexit(10,"group id");
X	break;
X      case 5 :
X	if ((cur_attrbuf.af_gen == max_attrbuf.af_gen) &&
X	    (cur_attrbuf.af_rev == max_attrbuf.af_rev))
X	  cur_pos--;
X	else
X	  match = FALSE;
X	break;
X      case 6:
X	/* Variants */
X	if ((strcmp(cur_attrbuf.af_variant,max_attrbuf.af_variant) == 0))
X	  cur_pos--;
X	else
X	  match = FALSE;
X	break;
X      case 7 :
X	if ((strcmp(cur_attrbuf.af_syspath,value)) == 0)
X	  cur_pos--;
X	else
X	  match = FALSE;
X	break;
X      case 8 :
X	if ((strcmp(cur_attrbuf.af_host,value)) == 0)
X	  cur_pos--;
X	else
X	  match = FALSE;
X	break;
X      default :
X/* af_udattrs must contain a '=', even if they don't contain a value */
X/* currently only the first value (if existing) in the string is     */
X/* considered */
X	i = 0;
X	found = FALSE;
X/* find name in list of udattrs */
X	while ((!(found)) && (i < AF_MAXUDAS) &&
X	       (cur_attrbuf.af_udattrs[i] != NIL))
X	  {
X	    (void) strcpy(val1, cur_attrbuf.af_udattrs[i]);
X	    if ((val2 = index(val1, '=')) == 0)
X	      errexit(10, "attrle");
X	    val2[0] = '\0';
X	    if (strcmp(name, val1) != 0)
X	      i++;
X	    else
X	      found = TRUE;
X	  }
X/* name should be found now */
X	if (!(found))
X	  errexit(10, "attrmax");
X
X/* value comparison */
X	if (strcmp(cur_attrbuf.af_udattrs[i], 
X		   max_attrbuf.af_udattrs[udattr_pos]) != 0)
X	  match = FALSE;
X	else
X	  cur_pos--;
X     
X      }
X  }
X
X/* remove keys from set if necessary */
Xi = cur_pos + 1;
Xwhile (i > 0)
X  {
X    if (af_setposrmkey(set, 0) == -1)
X      errexit(10, "af_setposrmkey");
X    i--;
X  }
X
X#ifdef DEBUG_ATTR
Xprintf("matches:\n");
Xnrofkeys = af_nrofkeys(set);
Xi = 0;
Xwhile (i < nrofkeys)
X  {
X    af_setgkey(set, i, &cur_key);
X    af_gattrs(&cur_key, &cur_attrbuf);
X    printf("version %d.%d\n", cur_attrbuf.af_gen, cur_attrbuf.af_rev);
X    i++;
X   }
X#endif DEBUG_ATTR
X  
Xreturn (TRUE);
X
X}
X
XBool attrmin(name, value, set)
X     char *name;
X     char *value;
X     Af_set *set;
X{
Xint attr_type;
Xint nrofkeys;
Xint cur_pos;
Xint i;
Xint udattr_pos;
X
XAf_key cur_key;
X
XAf_attrs cur_attrbuf;
XAf_attrs max_attrbuf;
X
XBool match;
XBool found;
X
Xchar val1[256];
Xchar *val2;
X
X#ifdef DEBUG_ATTR
Xprintf("attrmin(): name = #%s#\n", name);
X#endif DEBUG_ATTR
X
Xattr_type = get_attr_type(name);
X
Xif ((nrofkeys = af_nrofkeys(set)) == -1)
X  errexit(10, "af_nrofkeys");
X
X#ifdef DEBUG_ATTR
Xprintf("nrofkeys = %d\n", nrofkeys);
X#endif DEBUG_ATTR
X
Xif (nrofkeys == 1)
X  {
X#ifdef DEBUG_ATTR
X    printf("one match :\n");
X    af_setgkey(set, 0, &cur_key);
X    af_gattrs(&cur_key, &cur_attrbuf);
X    printf("version %d.%d\n", cur_attrbuf.af_gen, cur_attrbuf.af_rev);
X#endif DEBUG_ATTR
X
X    return (TRUE);
X  }
X
Xswitch (attr_type)
X  {
X  case 0 :
X    if ((af_sortset(set,AF_ATTGEN)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 1 :
X    if ((af_sortset(set,AF_ATTREV)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 2 :
X    if ((af_sortset(set,AF_ATTSTATE)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 3 :
X    if ((af_sortset(set,AF_ATTAUTHOR)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 4 :
X    errexit(10,"group id");
X    break;
X  case 5 :
X    if ((af_sortset(set,AF_ATTVERSION)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 6 :
X    if ((af_sortset(set,AF_ATTVARIANT)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 7:
X    if ((af_sortset(set,AF_ATTSPATH)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  case 8:
X    if ((af_sortset(set,AF_ATTHOST)) == -1)
X      errexit(10,"af_sortset");
X    break;
X  default :
X    if ((af_sortset(set,name)) == -1)
X      errexit(10,"af_sortset");
X  }
X
Xcur_pos = (0);
Xmatch = TRUE;
X
Xif ((err = af_setgkey(set, cur_pos, &cur_key)) == -1)
X  errexit(10, "af_setgkey");
Xif (af_gattrs(&cur_key, &max_attrbuf) == -1)
X  errexit(10, "af_gattrs");
Xcur_pos++;
X
Xif (attr_type > STD_ATTRS)  /* if looking for udattrs  */
X/* name has to be found in list of udattrs     */
X  {
X    udattr_pos = 0;
X    found = FALSE;
X/* find name in list of udattrs */
X    while ((!(found)) && (udattr_pos < AF_MAXUDAS) &&
X	   (max_attrbuf.af_udattrs[udattr_pos] != NIL))
X      {
X	(void) strcpy(val1, max_attrbuf.af_udattrs[udattr_pos]);
X	if ((val2 = index(val1, '=')) == 0)
X	  errexit(10, "attrmin");
X	val2[0] = '\0';
X	if (strcmp(name, val1) != 0)
X	  udattr_pos++;
X	else
X	  found = TRUE;
X      }
X/* name should be found now */
X    if (!(found))
X      errexit(10, "attrmin");
X  }
X
Xwhile ((cur_pos < nrofkeys) && match)
X  {
X    if ((err = af_setgkey(set, cur_pos, &cur_key)) == -1)
X      errexit(10, "af_setgkey");
X    
X    if (af_gattrs(&cur_key, &cur_attrbuf) == -1)
X      errexit(10, "af_gattrs");
X
X#ifdef DEBUG_ATTR
X    printf("key[%d] -> version %d.%d\n", cur_pos, cur_attrbuf.af_gen, cur_attrbuf.af_rev);
X#endif DEBUG_ATTR
X
X    switch (attr_type)
X      {
X      case 0 :
X	if (cur_attrbuf.af_gen == max_attrbuf.af_gen)
X	  cur_pos++;
X	else
X	  match = FALSE;
X	break;
X      case 1 :
X	if (cur_attrbuf.af_rev == max_attrbuf.af_rev)
X	  cur_pos++;
X	else
X	  match = FALSE;
X	break;
X      case 2 :
X	if (cur_attrbuf.af_state == max_attrbuf.af_state)
X	  cur_pos++;
X	else
X	  match = FALSE;
X	break;
X      case 3 :
X	if (!strcmp(cur_attrbuf.af_author.af_username,max_attrbuf.af_author.af_username))
X	  cur_pos++;
X	else
X	  match = FALSE;
X	break;
X      case 4 :
X	errexit(10,"group id");
X	break;
X      case 5 :
X	if ((cur_attrbuf.af_gen == max_attrbuf.af_gen) &&
X	    (cur_attrbuf.af_rev == max_attrbuf.af_rev))
X	  cur_pos++;
X	else
X	  match = FALSE;
X	break;
X      case 6:
X	/* Variants */
X	if ((strcmp(cur_attrbuf.af_variant,max_attrbuf.af_variant) == 0))
X	  cur_pos++;
X	else
X	  match = FALSE;
X	break;
X      case 7 :
X	if ((strcmp(cur_attrbuf.af_syspath,value)) == 0)
X	  cur_pos++;
X	else
X	  match = FALSE;
X	break;
X      case 8 :
X	if ((strcmp(cur_attrbuf.af_host,value)) == 0)
X	  cur_pos++;
X	else
X	  match = FALSE;
X	break;
X      default :
X/* af_udattrs must contain a '=', even if they don't contain a value */
X/* currently only the first value (if existing) in the string is     */
X/* considered */
X	i = 0;
X	found = FALSE;
X/* find name in list of udattrs */
X	while ((!(found)) && (i < AF_MAXUDAS) &&
X	       (cur_attrbuf.af_udattrs[i] != NIL))
X	  {
X	    (void) strcpy(val1, cur_attrbuf.af_udattrs[i]);
X	    if ((val2 = index(val1, '=')) == 0)
X	      errexit(10, "attrle");
X	    val2[0] = '\0';
X	    if (strcmp(name, val1) != 0)
X	      i++;
X	    else
X	      found = TRUE;
X	  }	
X/* name should be found now */
X	if (!(found))
X	  errexit(10, "attrmax");
X
X/* value comparison */
X	if (strcmp(cur_attrbuf.af_udattrs[i], 
X		   max_attrbuf.af_udattrs[udattr_pos]) != 0)
X	  match = FALSE;
X	else
X	  cur_pos++;
X     
X      }
X  }
X
X/* remove keys from set if necessary */
Xwhile (cur_pos < nrofkeys)
X  {
X    if (af_setposrmkey(set, cur_pos) == -1)
X      errexit(10, "af_setposrmkey");
X    nrofkeys--;
X  }
X
X#ifdef DEBUG_ATTR
Xprintf("matches:\n");
Xnrofkeys = af_nrofkeys(set);
Xi = 0;
Xwhile (i < nrofkeys)
X  {
X    af_setgkey(set, i, &cur_key);
X    af_gattrs(&cur_key, &cur_attrbuf);
X    printf("version %d.%d\n", cur_attrbuf.af_gen, cur_attrbuf.af_rev);
X    i++;
X   }
X#endif DEBUG_ATTR
X
Xreturn (TRUE);
X
X}
X
X
XBool getfromcid()
X{
X/* not yet implemented */
X;
X}
X
XBool attrvar(name, value, set)
X     char *name;
X     /*ARGSUSED*/
X     char *value;
X     Af_set *set;
X{
X/* set variant path & variant flags */
Xint k = 0;
Xint i = 0;
Xchar *ind;
Xchar pathlist[256];
X
Xif (check_vclass(name) != TRUE)
X  errexit(30,name);
X
Xwhile( vardefs[k] != (struct vardef *) NIL)
X  {
X    if (strcmp (vardefs[k]->name, name) != 0)
X      k++;
X    else
X      {
X	while(curvpath[i] != NIL)
X	  i++;
X	if (vardefs[k]->vpath != NIL)
X	  {
X	    (void) strcpy(pathlist,vardefs[k]->vpath);
X	
X	    while(( ind = index(pathlist,':')) != NIL)
X	      {
X		*ind = '\0';
X		if ((curvpath[i] = malloc((unsigned) (strlen(pathlist) + sizeof(char)))) == NIL)
X		  errexit(10,"malloc");
X		(void) strcpy(curvpath[i],pathlist);
X		ind++;
X		(void) strcpy(pathlist,ind);
X		i++;
X	      }
X	    if ((curvpath[i] = malloc((unsigned) (strlen(pathlist) + sizeof(char)))) == NIL)
X	      errexit(10,"malloc");
X	    (void) strcpy(curvpath[i],pathlist);
X	  }
X/*	strcpy(p,"vflags=");
X	(void) strcat(p,expandmacro("$(vflags)"));
X	(void) strcat(p," ");
X	(void) strcat(p,vardefs[k]->vflags);
X	macrodef(p);
X	free(p); */
X	break;
X      }
X  }
X
Xif (vardefs[k] != (struct vardef *) NIL)
X  {
X    if (strcmp(vardefs[k]->name, name) == 0)
X      return (TRUE);
X  }
Xelse
X  errexit(19,name);
X/*NOTREACHED*/
X}
X
X
X
Xchar *replace(patt)
X     char *patt;
X{
X
X/* converts shell-like pattern to ex-like pattern */
X/* not yet complete ???? */
X/* a{bc,d,e}f mactches abcf adf & aef not implemented */
X  int i,j;
X  char result[128];
X  char tmp_result[64];
X
X  static char rechars[] = "^.$?*[]{}";
X
X  j = 0;
X  
X  for(i = 0; i < strlen(patt); i++)
X    {
X      switch (patt[i])
X	{
X	case '?':
X	  tmp_result[j++]='.';
X	  break;
X	case '*':
X	  tmp_result[j++]='.';
X  	  tmp_result[j++]='*'; 
X	  break;
X	case '.':
X	  tmp_result[j++]='\\';
X	  tmp_result[j++]='.';
X	  break;
X	default:
X	  tmp_result[j++]=patt[i];
X      }
X  }
Xtmp_result[j]='\0';
X
X(void) sprintf(result,"%s%s%s",(!(index(rechars,tmp_result[0]))) ? "^" : "",
X	tmp_result, (!(index(rechars,tmp_result[strlen(tmp_result) - 1]))) ? 
X	"$" : "");
X  
Xreturn(result);
X}
X
END_OF_FILE
if test 50463 -ne `wc -c <'src/shape/attr.c'`; then
    echo shar: \"'src/shape/attr.c'\" unpacked with wrong size!
fi
# end of 'src/shape/attr.c'
fi
echo shar: End of archive 33 \(of 33\).
cp /dev/null ark33isdone
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.