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

/* 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)
{
  int x;

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

  if (obj->ocnt > 0) {
    for (x = 0; x < (int) 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 * obj, char *attr, int *slot)
{
  char *p1;
  char *p2;
  int s = 0;

  for (; s < (int) 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 (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 < (int) 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 >= (int) 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 * obj, char *attr)
{
  int slot;
  char **a;

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

  if (slot > -1 && slot < (int) 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 < (int) 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);
}




int objstuffattr (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 (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 (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.
*/
int attname (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);
}