/
umud/DOC/
umud/DOC/examples/
umud/DOC/internals/
umud/DOC/wizard/
umud/MISC/
umud/MISC/dbchk/
umud/RWHO/rwhod/
/*
	Copyright (C) 1991, Marcus J. Ranum. All rights reserved.
*/

#ifndef	lint
static	char	RCSid[] = "$Header: /usr/users/mjr/hacks/umud/RCS/obj.c,v 1.2 91/08/07 00:48:38 mjr Exp $";
#endif

/* configure all options BEFORE including system stuff. */
#include	"config.h"


#include	"mud.h"


/* allocate a new object holder */
Obj
*objnew()
{
	Obj	*ret;

	if((ret = (Obj *)malloc(sizeof(Obj))) == (Obj *)0)
		return((Obj *)0);

	ret->ocnt = 0;
	ret->oap = (char **)0;
	return(ret);
}




/* free an object, its holder, and its attributes - actual free() is deferred */
void
objfree(obj)
Obj	*obj;
{
	int	x;

	if(obj == (Obj *)0)
		return;

	if(obj->ocnt > 0) {
		for(x = 0; x < obj->ocnt; x++)
			deferfree((mall_t)obj->oap[x]);

		deferfree((mall_t)obj->oap);
	}
	deferfree((mall_t)obj);
}




/*
search for attributes by name
*/
char	*
objattr(obj,attr,slot)
Obj	*obj;
char	*attr;
int	*slot;
{
	char	*p1;
	char	*p2;
	int	s = 0;

	for(; s < obj->ocnt; s++) {

		p2 = obj->oap[s];

		/* skip the type information */
		while(*p2 != ' ' && *p2 != '\0')
			p2++;
		if(*p2 != ' ')
			continue;

		p1 = attr;

		/* p2 is left pointing at the ' ' after the type */
		p2++;

		/* check matching chars */
		while(*p1 == *p2 && *p1 != '\0')
			p1++, p2++;

		/* validate match */
		if(*p1 != '\0' || *p2 != '=')
			continue;

		/* match */
		if(slot != (int *)0)
			*slot = s;

		return(obj->oap[s]);
	}

	if(slot != (int *)0)
		*slot = -1;

	return((char *)0);
}




int
objsetattr(o,aty,att,ada)
Obj	*o;
char	*aty;
char	*att;
char	*ada;
{
	char		**a;
	char		*ip;
	int		s;
	int		atlen;
	int		anlen;
	int		adlen;

	if(o == (Obj *)0 || aty == (char *)0 || att == (char *)0 || ada == (char *)0)
		return(-1);

	(void)objattr(o,att,&s);

	atlen = strlen(aty);
	anlen = strlen(att);
	adlen = strlen(ada);

	if((ip = (char *)malloc((unsigned)(atlen + anlen + adlen + 3))) == (char *)0)
		return(-1);

	/* copy the type string */
	(void)bcopy(aty,ip,atlen);

	/* add a space */
	*(ip + atlen) = ' ';

	/* copy the attribute name */
	(void)bcopy(att,ip + atlen + 1,anlen);

	/* add the equals sign */
	*(ip + atlen + anlen + 1) = '=';

	/* copy the data */
	(void)bcopy(ada,ip + atlen + anlen + 2,adlen);

	/* terminate */
	*(ip + atlen + anlen + adlen + 2) = '\0';

	if(s > -1 && s < o->ocnt && o->oap != (char **)0 && o->oap[s] != (char *)0)
		deferfree((mall_t)o->oap[s]);

	if(o->oap == (char **)0) {
		a = (char **)malloc(sizeof(char *));
		if(a == (char **)0)
			return(-1);
		o->oap = a;
		o->ocnt = 1;
		s = 0;
	} else 
	if(s == -1 || s >= o->ocnt) {
		a = (char **)realloc((mall_t)o->oap,(unsigned)((o->ocnt + 1) * sizeof(char *)));
		if(a == (char **)0)
			return(-1);
		o->oap = a;
		s = o->ocnt;
		o->ocnt++;
	}

	o->oap[s] = ip;
	return(0);
}




int
objunsetattr(obj,attr)
Obj	*obj;
char	*attr;
{
	int			slot;
	char			**a;

	if(objattr(obj,attr,&slot) == (char *)0)
		return(0);

	if(slot > -1 && slot < obj->ocnt && obj->oap[slot] != (char *)0)
		deferfree((mall_t)obj->oap[slot]);

	/* if none left, free it */
	if(obj->ocnt == 1) {
		deferfree((mall_t)obj->oap);
		obj->oap = (char **)0;
		obj->ocnt = 0;
		return(0);
	}

	/* shift all one slot down */
	while(slot < obj->ocnt - 1) {
		obj->oap[slot] = obj->oap[slot + 1];
		slot++;
	}

	/* realloc may pack memory. */
	a = (char **)realloc((mall_t)obj->oap,(unsigned)((obj->ocnt - 1) * sizeof(char *)));
	if(a == (char **)0)
		return(-1);

	obj->oap = a;
	(obj->ocnt)--;
	return(0);
}




objstuffattr(o,data,len)
Obj	*o;
char	*data;
int	len;
{
	char	*p;

	if(o->oap == (char **)0) {
		o->oap = (char **)malloc(sizeof(char *));
		o->ocnt = 1;
	} else { 
		o->oap = (char **)realloc((mall_t)o->oap,(o->ocnt + 1) * sizeof(char *));
		o->ocnt++;
	}

	if((p = (char *)malloc((unsigned)(len + 1))) == (char *)0)
		return(-1);

	(void)bcopy(data,p,len);
	p[len] = '\0';
	o->oap[o->ocnt - 1] = p;
	return(0);
}




/*
return nonzero if the variable is of the given type. simple
type-checking function.
*/
int
attistype(v,vt)
char	*v;
char	*vt;
{
	while(*v != '\0' && *v != ' ' && *vt != '\0' && *v == *vt)
		v++, vt++;

	if(*vt == '\0' && *v == ' ')
		return(1);
	return(0);
}





/*
return data part of an attribute. note that this does NOT return NULL
if the attribute is of zero-length.
*/
char	*
attdata(v)
char	*v;
{
	while(*v != '\0' && *v != ' ')
		v++;

	if(*v != ' ')
		return((char *)0);

	while(*v != '\0' && *v != '=')
		v++;

	if(*v != '=')
		return((char *)0);

	return(++v);
}

/*
return name part of an attribute. Note! suceeds even if name is zero length.
*/
attname(a,aname)
char	*a;
char	*aname;
{
	int i;

	while(*a != '\0' && *a != ' ')
		a++;

	if(*a != ' ')
		return(1);

	for(i = 0, ++a; i < MAXOID-1 && *a != '\0' && *a != '='; ++i, ++a)
		aname[i] = *a;
	aname[i] = '\0';
		
	return(0);
}