/*
**  This file is part of Zterp, and is
**  Copyright 1992, 1993 Charles Hannum
*/

#include <sys/types.h>
#include <stdio.h>
#include <assert.h>
#include "main.h"
#include "object.h"
#include "variable.h"
#include "property.h"

static zpointer
property_ptr (uword n)
{
  zpointer x = near_address (get_data (object_ptr (n)));
  return (x + (get_byte (x) << 1) + 1);
}

static zpointer
next_property_ptr (zpointer p)
{
  zbyte x = get_byte (p);
  p += 1;
  if (x & 0x80 && zil_version > 3)
    return (p + (get_byte (p) & property_number_mask) + 1);
  else
    return (p + ((x >> property_length_shift) + 1));
}

static zpointer
find_property_ptr (uword n, zbyte b)
{
  zpointer p = property_ptr (n);
  sbyte a;
  while ((a = get_byte (p) & property_number_mask) > (sbyte) b)
    p = next_property_ptr (p);
  return (p);
}

void
get_property (n, b)
  uword n, b;
{
  zpointer p = find_property_ptr (n, b);
  zbyte a = get_byte (p);
  if ((a & property_number_mask) == (zbyte) b)
  {
    p += 1;
    if (a & property_length_mask)
      store_variable_push (get_word (p));
    else
      store_variable_push_byte (get_byte (p));
  }
  else
    store_variable_push (get_word (property + (b << 1)));
}

void
get_property_address (n, b)
  uword n, b;
{
  zpointer p = find_property_ptr (n, b);
  zbyte a = get_byte (p);
  if ((a & property_number_mask) == (zbyte) b)
  {
    if (a & 0x80 && zil_version > 3)
      p += 2;
    else
      p += 1;
    store_variable_push ((uword) (p - game));
  }
  else
    store_variable_push (0);
}

void
get_next_property (n, b)
  uword n, b;
{
  zpointer p;
  if (b)
  {
    zbyte a;
    p = find_property_ptr (n, b);
    a = get_byte (p) & property_number_mask;
    assert (a == (zbyte) b);
    p = next_property_ptr (p);
  }
  else
    p = property_ptr (n);
  store_variable_push (get_byte (p) & property_number_mask);
}

void
set_property (n, b, c)
  uword n, b, c;
{
  zpointer p = find_property_ptr (n, b);
  zbyte a = get_byte (p);
  assert ((a & property_number_mask) == (zbyte) b);
  p += 1;
  if (a & property_length_mask)
    set_word (p, c);
  else
    set_byte (p, c);
}

void
get_property_length (a)
  uword a;
{
  zpointer p = near_address (a - 1);
  zbyte x = get_byte (p);
  if (x & 0x80 && zil_version > 3)
    store_variable_push (get_byte (p) & property_number_mask);
  else
    store_variable_push ((x >> property_length_shift) + 1);
}
