lpmoo-1.2/etc/
lpmoo-1.2/mudlib/
lpmoo-1.2/mudlib/etc/
lpmoo-1.2/mudlib/include/
lpmoo-1.2/mudlib/include/moo/
lpmoo-1.2/mudlib/lpc/
lpmoo-1.2/mudlib/std/auto/
lpmoo-1.2/mudlib/std/bfuns/
/*
 * NAME:	vartext.c
 * DESCRIPTION:	variable-to-text translators
 */

inherit "/std/string";
inherit "/std/eefun";

# include "vartext.h"
# include <dgd/type.h>

/*
 * NAME:	type_str()
 * DESCRIPTION:	return a string indicating value type
 */
static
string type_str(mixed var)
{
  switch (typeof(var))
    {
    case T_INT:
      return "int";
    case T_FLOAT:
      return "float";
    case T_STRING:
      return "string";
    case T_OBJECT:
      return "object";
    case T_ARRAY:
      return "mixed *";
    case T_MAPPING:
      return "mapping";
    default:
      error("Unknown return value from typeof()");
    }
}

/*
 * NAME:	elements_of_arr()
 * DESCRIPTION:	return a string representing the elements of an array
 */
private
string elements_of_arr(mixed *var)
{
  int i, sz;
  string str;

  str = "";
  for (i = 0, sz = sizeof(var); i < sz; ++i)
    str += " " + var2str(var[i]) + (i < sz - 1 ? "," : "");

  return str;
}

/*
 * NAME:	elements_of_map()
 * DESCRIPTION:	return a string representing the elements of a mapping
 */
private
string elements_of_map(mapping var)
{
  mixed *keys, *values;
  int i, sz;
  string str;

  keys = map_indices(var);
  values = map_values(var);

  str = "";
  for (i = 0, sz = sizeof(keys); i < sz; ++i)
    str += " " + var2str(keys[i]) + " : " + var2str(values[i]) +
      (i < sz - 1 ? "," : "");

  return str;
}

/*
 * NAME:	var2str()
 * DESCRIPTION:	given a variable of any type, return a string representation
 */
static
string var2str(mixed var)
{
  switch (typeof(var))
    {
    case T_INT:
      return (string) var;
    case T_FLOAT:
      return flt2str(var);
    case T_STRING:
      return "\"" + escape_str(var) + "\"";
    case T_OBJECT:
      return object_name(var);
    case T_ARRAY:
      return "({" + elements_of_arr((mixed *) var) + " })";
    case T_MAPPING:
      return "([" + elements_of_map(var) + " ])";
    default:
      return "#unknown";
    }
}

/*
 * NAME:	tokenize()
 * DESCRIPTION:	convert a string into an array of tokens
 */
private
mixed **tokenize(string str)
{
  mixed **tokens;
  int i, j, sz, val, neg, flt;
  float flval;

  tokens = ({ });
  for (i = 0, sz = strlen(str); i < sz; ++i)
    switch (str[i])
      {
      case ' ': case '\t': case '\n':
	continue;

      case ',':
	tokens += ({ ({ ',' }) });
	break;

      case ':':
	tokens += ({ ({ ':' }) });
	break;

      case '-': case '.':
      case '0': case '1': case '2': case '3': case '4':
      case '5': case '6': case '7': case '8': case '9':

	if (neg = (str[i] == '-'))
	  {
	    if (i == sz - 1)
	      break;
	    ++i;
	  }

	if (str[i] == '.')
	  {
	    val = 0;
	    --i;
	  }
	else
	  val = str[i] - '0';

	while (++i < sz && str[i] >= '0' && str[i] <= '9')
	  val = 10 * val + str[i] - '0';

	if (i < sz && str[i] == '.')
	  {
	    int hund;

	    flt = 1;
	    flval = (float) val;
	    hund = 1;
	    while (++i < sz && str[i] >= '0' && str[i] <= '9')
	      flval += (1.0 / ((float) (hund *= 10))) * (float) (str[i] - '0');
	  }
	else
	  flt = 0;

	if (i < sz - 1)
	  --i;

	if (flt)
	  {
	    if (neg)
	      flval = -flval;
	    tokens += ({ ({ '.', flval }) });
	  }
	else
	  {
	    if (neg)
	      val = -val;
	    tokens += ({ ({ '1', val }) });
	  }
	break;

      case '\"':
	if (i == sz - 1)
	  continue;
	for (j = i + 1; j < sz; ++j)
	  {
	    if (str[j] == '\\')
	      {
		++j;
		continue;
	      }
	    if (str[j] == '\"')
	      break;
	  }
	tokens += ({ ({ '\"', unescape_str(str[i + 1 .. j - 1]) }) });
	i = j;
	break;

      case '/':
      case '#':
	for (j = i + 1; j < sz; ++j)
	  {
	    if (str[j] == ' ' || str[j] == ',' || str[j] == ':' ||
		str[j] == '}' || str[j] == ']')
	      break;
	  }
	if (str[i] == '/')
	  tokens += ({ ({ '/', find_object(str[i .. j - 1]) }) });
	i = j - 1;
	break;

      case '(':
	if (i == sz - 1)
	  continue;
	if (str[++i] == '{')
	  tokens += ({ ({ '{' }) });
	else if (str[i] == '[')
	  tokens += ({ ({ '[' }) });
	break;

      case ']':
	if (i == sz - 1)
	  continue;
	if (str[++i] == ')')
	  tokens += ({ ({ ']' }) });
	break;

      case '}':
	if (i == sz - 1)
	  continue;
	if (str[++i] == ')')
	  tokens += ({ ({ '}' }) });
	break;
      }

  return tokens;
}

/*
 * NAME:	parse_element()
 * DESCRIPTION:	given an array of tokens, parse the first data element
 * RETURNS:	({ element, next_token_index })
 */
private
mixed *parse_element(mixed **tokens, int item)
{
  int i, sz;
  mixed *arr, *elem, *key;
  mapping map;

  sz = sizeof(tokens);
  if (sz == 0 || item >= sz)
    return ({ 0, item });

  switch (tokens[item][0])
    {
    case '1':
    case '.':
    case '\"':
    case '/':
      return ({ tokens[item][1], item + 1 });

    case '{':
      arr = ({ });
      for (i = item + 1; i < sz; ++i)
	{
	  switch (tokens[i][0])
	    {
	    case ',':
	      continue;
	    case '}':
	      break;
	    default:
	      elem = parse_element(tokens, i);
	      arr += ({ elem[0] });
	      i = elem[1] - 1;
	      continue;
	    }
	  break;
	}
      return ({ arr, i + 1 });

    case '[':
      map = ([ ]);
      for (i = item + 1; i < sz; ++i)
	{
	  if (tokens[i][0] == ':')
	    {
	      elem = parse_element(tokens, i + 1);
	      if (key != 0)
		{
		  map[key[0]] = elem[0];
		  key = 0;
		}
	      i = elem[1] - 1;
	      continue;
	    }
	  if (tokens[i][0] == ',')
	    continue;
	  if (tokens[i][0] == ']')
	    break;
	  key = parse_element(tokens, i);
	  i = key[1] - 1;
	}
      return ({ map, i + 1 });
    }

  return ({ 0, item + 1 });
}

/*
 * NAME:	str2var()
 * DESCRIPTION:	given a string representing a value, return that value
 */
static
mixed str2var(string str)
{
  if (str == 0)
    return 0;
  return parse_element(tokenize(str), 0)[0];
}