pennmush/game/
pennmush/game/data/
pennmush/game/log/
pennmush/game/save/
pennmush/game/txt/evt/
pennmush/game/txt/nws/
pennmush/os2/
#include "copyrite.h"

#include "config.h"
#include <math.h>
#ifdef I_STRING
#include <string.h>
#else
#include <strings.h>
#endif
#include <ctype.h>
#include "externs.h"
#include "intrface.h"
#include "parse.h"
#include "confmagic.h"

#ifdef WIN32
#pragma warning( disable : 4761)	/* NJG: disable warning re conversion */
#endif


/* ARGSUSED */
FUNCTION(fun_add)
{
  int j;
  NVAL sum;

  if (!is_number(args[0])) {
    safe_str(e_nums, buff, bp);
    return;
  }
  sum = parse_number(args[0]);
  for (j = 1; j < nargs; j++) {
    if (!is_number(args[j])) {
      safe_str(e_nums, buff, bp);
      return;
    }
    sum += parse_number(args[j]);
  }
  safe_str(unparse_number(sum), buff, bp);
}

/* ARGSUSED */
FUNCTION(fun_sub)
{
  if (!is_number(args[0]) || !is_number(args[1])) {
    safe_str(e_nums, buff, bp);
    return;
  }
  safe_str(unparse_number(parse_number(args[0]) - parse_number(args[1])),
	   buff, bp);
}

/* ARGSUSED */
FUNCTION(fun_mul)
{
  int j;
  NVAL prod;

  if (!is_number(args[0])) {
    safe_str(e_nums, buff, bp);
    return;
  }
  prod = parse_number(args[0]);
  for (j = 1; j < nargs; j++) {
    if (!is_number(args[j])) {
      safe_str(e_nums, buff, bp);
      return;
    }
    prod *= parse_number(args[j]);
  }
  safe_str(unparse_number(prod), buff, bp);
}

/* ARGSUSED */
FUNCTION(fun_gt)
{
  if (!is_number(args[0]) || !is_number(args[1])) {
    safe_str(e_nums, buff, bp);
    return;
  }
  safe_chr((parse_number(args[0]) > parse_number(args[1])) ? '1' : '0',
	   buff, bp);
}

/* ARGSUSED */
FUNCTION(fun_gte)
{
  if (!is_number(args[0]) || !is_number(args[1])) {
    safe_str(e_nums, buff, bp);
    return;
  }
  safe_chr((parse_number(args[0]) >= parse_number(args[1])) ? '1' : '0',
	   buff, bp);
}

/* ARGSUSED */
FUNCTION(fun_lt)
{
  if (!is_number(args[0]) || !is_number(args[1])) {
    safe_str(e_nums, buff, bp);
    return;
  }
  safe_chr((parse_number(args[0]) < parse_number(args[1])) ? '1' : '0',
	   buff, bp);
}

/* ARGSUSED */
FUNCTION(fun_lte)
{
  if (!is_number(args[0]) || !is_number(args[1])) {
    safe_str(e_nums, buff, bp);
    return;
  }
  safe_chr((parse_number(args[0]) <= parse_number(args[1])) ? '1' : '0',
	   buff, bp);
}

/* ARGSUSED */
FUNCTION(fun_eq)
{
  if (!is_number(args[0]) || !is_number(args[1])) {
    safe_str(e_nums, buff, bp);
    return;
  }
  safe_chr((parse_number(args[0]) == parse_number(args[1])) ? '1' : '0',
	   buff, bp);
}

/* ARGSUSED */
FUNCTION(fun_neq)
{
  if (!is_number(args[0]) || !is_number(args[1])) {
    safe_str(e_nums, buff, bp);
    return;
  }
  safe_chr((parse_number(args[0]) != parse_number(args[1])) ? '1' : '0',
	   buff, bp);
}

/* ARGSUSED */
FUNCTION(fun_max)
{
  int j;
  NVAL max, num;

  if (!is_number(args[0])) {
    safe_str(e_nums, buff, bp);
    return;
  }
  max = parse_number(args[0]);
  for (j = 1; j < nargs; j++) {
    if (!is_number(args[j])) {
      safe_str(e_nums, buff, bp);
      return;
    }
    num = parse_number(args[j]);
    if (num > max)
      max = num;
  }
  safe_str(unparse_number(max), buff, bp);
}

/* ARGSUSED */
FUNCTION(fun_min)
{
  int j;
  NVAL min, num;

  if (!is_number(args[0])) {
    safe_str(e_nums, buff, bp);
    return;
  }
  min = parse_number(args[0]);
  for (j = 1; j < nargs; j++) {
    if (!is_number(args[j])) {
      safe_str(e_nums, buff, bp);
      return;
    }
    num = parse_number(args[j]);
    if (num < min)
      min = num;
  }
  safe_str(unparse_number(min), buff, bp);
}

/* ARGSUSED */
FUNCTION(fun_sign)
{
  NVAL x;

  if (!is_number(args[0])) {
    safe_str(e_num, buff, bp);
    return;
  }
  x = parse_number(args[0]);
  if (x == 0)
    safe_chr('0', buff, bp);
  else if (x > 0)
    safe_chr('1', buff, bp);
  else
    safe_str("-1", buff, bp);
}

/* ARGSUSED */
FUNCTION(fun_shl)
{
  if (!is_integer(args[0]) || !is_integer(args[1])) {
    safe_str(e_ints, buff, bp);
    return;
  }
  safe_str(unparse_integer(parse_integer(args[0]) << parse_integer(args[1])),
	   buff, bp);
}

/* ARGSUSED */
FUNCTION(fun_shr)
{
  if (!is_integer(args[0]) || !is_integer(args[1])) {
    safe_str(e_ints, buff, bp);
    return;
  }
  safe_str(unparse_integer(parse_integer(args[0]) >> parse_integer(args[1])),
	   buff, bp);
}

/* ARGSUSED */
FUNCTION(fun_inc)
{
  int num;
  char *p;
  /* Handle the case of a pure number */
  if (is_integer(args[0])) {
    safe_str(unparse_integer(parse_integer(args[0]) + 1), buff, bp);
    return;
  }
  p = args[0] + strlen(args[0]) - 1;
  if (!isdigit(*p)) {
    safe_str("#-1 ARGUMENT MUST END IN AN INTEGER", buff, bp);
    return;
  }
  while ((isdigit(*p) || (*p == '-')) && p != args[0]) {
    if (*p == '-') {
      p--;
      break;
    }
    p--;
  }
  /* p now points to the last non-numeric character in the string
   * Move it to the first numeric character
   */
  p++;
  num = parse_integer(p) + 1;
  *p = '\0';
  safe_str(args[0], buff, bp);
  safe_str(unparse_integer(num), buff, bp);
}

/* ARGSUSED */
FUNCTION(fun_dec)
{
  int num;
  char *p;
  /* Handle the case of a pure number */
  if (is_integer(args[0])) {
    safe_str(unparse_integer(parse_integer(args[0]) - 1), buff, bp);
    return;
  }
  p = args[0] + strlen(args[0]) - 1;
  if (!isdigit(*p)) {
    safe_str("#-1 ARGUMENT MUST END IN AN INTEGER", buff, bp);
    return;
  }
  while ((isdigit(*p) || (*p == '-')) && p != args[0]) {
    if (*p == '-') {
      p--;
      break;
    }
    p--;
  }
  /* p now points to the last non-numeric character in the string
   * Move it to the first numeric character
   */
  p++;
  num = parse_integer(p) - 1;
  *p = '\0';
  safe_str(args[0], buff, bp);
  safe_str(unparse_integer(num), buff, bp);
}

/* ARGSUSED */
FUNCTION(fun_trunc)
{
  /* This function does not have the non-number check because
   * the help file explicitly states that this function can
   * be used to turn "101dalmations" into "101".
   */
  safe_str(unparse_integer(parse_integer(args[0])), buff, bp);
}

/* ARGSUSED */
FUNCTION(fun_div)
{
  int bot;

  if (!is_integer(args[0]) || !is_integer(args[1])) {
    safe_str(e_ints, buff, bp);
    return;
  }
  bot = parse_integer(args[1]);
  if (bot == 0) {
    safe_str("#-1 DIVISION BY ZERO", buff, bp);
    return;
  }
  safe_str(unparse_integer(parse_integer(args[0]) / bot), buff, bp);
}

/* ARGSUSED */
FUNCTION(fun_mod)
{
  int bot;

  if (!is_integer(args[0]) || !is_integer(args[1])) {
    safe_str(e_ints, buff, bp);
    return;
  }
  bot = parse_integer(args[1]);
  if (bot == 0) {
    safe_str("#-1 DIVISION BY ZERO", buff, bp);
    return;
  }
  safe_str(unparse_integer(parse_integer(args[0]) % bot), buff, bp);
}

/* ARGSUSED */
FUNCTION(fun_abs)
{
  if (!is_number(args[0])) {
    safe_str(e_num, buff, bp);
    return;
  }
#ifdef FLOATING_POINTS
  safe_str(unparse_number(fabs(parse_number(args[0]))), buff, bp);
#else
  safe_str(unparse_number(abs(parse_number(args[0]))), buff, bp);
#endif
}

/* ARGSUSED */
FUNCTION(fun_dist2d)
{
  int d1, d2;
  double r;

  if (!is_integer(args[0]) || !is_integer(args[1]) ||
      !is_integer(args[2]) || !is_integer(args[3])) {
    safe_str(e_ints, buff, bp);
    return;
  }
  d1 = parse_integer(args[0]) - parse_integer(args[2]);
  d2 = parse_integer(args[1]) - parse_integer(args[3]);
  r = (double) d1 *d1 + (double) d2 *d2;
#ifndef HAS_IEEE_MATH
  /* You can overflow, which is bad. */
  if (r < 0) {
    safe_str("#-1 OVERFLOW ERROR", buff, bp);
    return;
  }
#endif
#ifdef FLOATING_POINTS
  safe_str(unparse_number(sqrt(r)), buff, bp);
#else
  safe_str(unparse_integer((int) sqrt(r)), buff, bp);
#endif
}

/* ARGSUSED */
FUNCTION(fun_dist3d)
{
  int d1, d2, d3;
  double r;

  if (!is_integer(args[0]) || !is_integer(args[1]) ||
      !is_integer(args[2]) || !is_integer(args[3]) ||
      !is_integer(args[4]) || !is_integer(args[5])) {
    safe_str(e_ints, buff, bp);
    return;
  }
  d1 = parse_integer(args[0]) - parse_integer(args[3]);
  d2 = parse_integer(args[1]) - parse_integer(args[4]);
  d3 = parse_integer(args[2]) - parse_integer(args[5]);
  r = (double) d1 *d1 + (double) d2 *d2 + (double) d3 *d3;
#ifndef HAS_IEEE_MATH
  /* You can overflow, which is bad. */
  if (r < 0) {
    safe_str("#-1 OVERFLOW ERROR", buff, bp);
    return;
  }
#endif
#ifdef FLOATING_POINTS
  safe_str(unparse_number(sqrt(r)), buff, bp);
#else
  safe_str(unparse_integer((int) sqrt(r)), buff, bp);
#endif
}

/* ------------------------------------------------------------------------
 * Dune's vector functions: VADD, VSUB, VMUL, VCROSS, VMAG, VUNIT, VDIM
 *  VCRAMER?
 * Vectors are space-separated numbers.
 */

#define MAXDIM	20

/* ARGSUSED */
FUNCTION(fun_vadd)
{
  char *p1, *p2;
  char *start;
  char sep;

  /* return if a list is empty */
  if (!args[0] || !args[1])
    return;

  if (!delim_check(buff, bp, nargs, args, 3, &sep))
    return;
  p1 = trim_space_sep(args[0], sep);
  p2 = trim_space_sep(args[1], sep);

  /* return if a list is empty */
  if (!*p1 || !*p2)
    return;

  /* add the vectors */
  start = *bp;
  safe_str(unparse_number(parse_number(split_token(&p1, sep)) +
			  parse_number(split_token(&p2, sep))), buff, bp);
  while (p1 && p2) {
    safe_chr(sep, buff, bp);
    safe_str(unparse_number(parse_number(split_token(&p1, sep)) +
			 parse_number(split_token(&p2, sep))), buff, bp);
  }

  /* make sure vectors were the same length */
  if (p1 || p2) {
    *bp = start;
    safe_str("#-1 VECTORS MUST BE SAME DIMENSIONS", buff, bp);
    return;
  }
}


/* ARGSUSED */
FUNCTION(fun_vsub)
{
  char *p1, *p2;
  char *start;
  char sep;

  /* return if a list is empty */
  if (!args[0] || !args[1])
    return;

  if (!delim_check(buff, bp, nargs, args, 3, &sep))
    return;
  p1 = trim_space_sep(args[0], sep);
  p2 = trim_space_sep(args[1], sep);

  /* return if a list is empty */
  if (!*p1 || !*p2)
    return;

  /* subtract the vectors */
  start = *bp;
  safe_str(unparse_number(parse_number(split_token(&p1, sep)) -
			  parse_number(split_token(&p2, sep))), buff, bp);
  while (p1 && p2) {
    safe_chr(sep, buff, bp);
    safe_str(unparse_number(parse_number(split_token(&p1, sep)) -
			 parse_number(split_token(&p2, sep))), buff, bp);
  }

  /* make sure vectors were the same length */
  if (p1 || p2) {
    *bp = start;
    safe_str("#-1 VECTORS MUST BE SAME DIMENSIONS", buff, bp);
    return;
  }
}

/* ARGSUSED */
FUNCTION(fun_vmul)
{
  NVAL e1, e2;
  char *p1, *p2;
  char *start;
  char sep;

  /* return if a list is empty */
  if (!args[0] || !args[1])
    return;

  if (!delim_check(buff, bp, nargs, args, 3, &sep))
    return;
  p1 = trim_space_sep(args[0], sep);
  p2 = trim_space_sep(args[1], sep);

  /* return if a list is empty */
  if (!*p1 || !*p2)
    return;

  /* multiply the vectors */
  start = *bp;
  e1 = parse_number(split_token(&p1, sep));
  e2 = parse_number(split_token(&p2, sep));
  if (!p1) {
    /* scalar * vector */
    safe_str(unparse_number(e1 * e2), buff, bp);
    while (p2) {
      safe_chr(sep, buff, bp);
      safe_str(unparse_number(e1 * parse_number(split_token(&p2, sep))),
	       buff, bp);
    }
  } else if (!p2) {
    /* vector * scalar */
    safe_str(unparse_number(e1 * e2), buff, bp);
    while (p1) {
      safe_chr(sep, buff, bp);
      safe_str(unparse_number(parse_number(split_token(&p1, sep)) * e2),
	       buff, bp);
    }
  } else {
    /* vector * vector elementwise product */
    safe_str(unparse_number(e1 * e2), buff, bp);
    while (p1 && p2) {
      safe_chr(sep, buff, bp);
      safe_str(unparse_number(parse_number(split_token(&p1, sep)) * parse_number(split_token(&p2, sep))), buff, bp);
    }
    /* make sure vectors were the same length */
    if (p1 || p2) {
      *bp = start;
      safe_str("#-1 VECTORS MUST BE SAME DIMENSIONS", buff, bp);
      return;
    }
  }
}


/* ARGSUSED */
FUNCTION(fun_vdot)
{
  NVAL product;
  char *p1, *p2;
  char sep;

  /* return if a list is empty */
  if (!args[0] || !args[1])
    return;

  if (!delim_check(buff, bp, nargs, args, 3, &sep))
    return;
  p1 = trim_space_sep(args[0], sep);
  p2 = trim_space_sep(args[1], sep);

  /* return if a list is empty */
  if (!*p1 || !*p2)
    return;

  /* multiply the vectors */
  product = 0;
  while (p1 && p2) {
    product += parse_number(split_token(&p1, sep)) *
      parse_number(split_token(&p2, sep));
  }
  if (p1 || p2) {
    safe_str("#-1 VECTORS MUST BE SAME DIMENSIONS", buff, bp);
    return;
  }
  safe_str(unparse_number(product), buff, bp);
}

/* ARGSUSED */
FUNCTION(fun_vmag)
{
  NVAL num, sum;
  char *p1;
  char sep;

  /* return if a list is empty */
  if (!args[0])
    return;

  if (!delim_check(buff, bp, nargs, args, 2, &sep))
    return;
  p1 = trim_space_sep(args[0], sep);

  /* return if a list is empty */
  if (!*p1)
    return;

  /* sum the squares */
  num = parse_number(split_token(&p1, sep));
  sum = num * num;
  while (p1) {
    num = parse_number(split_token(&p1, sep));
    sum += num * num;
  }

#ifdef FLOATING_POINTS
  safe_str(unparse_number(sqrt(sum)), buff, bp);
#else
  safe_str(unparse_number((int) (sqrt(sum) + 0.5)), buff, bp);
#endif				/* FLOATING_POINTS */
}

/* ARGSUSED */
FUNCTION(fun_vunit)
{
  /* This function is pretty useless without FLOATING_POINTS,
   * but I see no reason to disable it when FLOATING_POINTS
   * isn't defined...
   */
  NVAL num, sum;
  char tbuf[BUFFER_LEN];
  char *p1;
  char sep;

  /* return if a list is empty */
  if (!args[0])
    return;

  if (!delim_check(buff, bp, nargs, args, 2, &sep))
    return;
  p1 = trim_space_sep(args[0], sep);

  /* return if a list is empty */
  if (!*p1)
    return;

  /* copy the vector, since we have to walk it twice... */
  strcpy(tbuf, p1);

  /* find the magnitude */
  num = parse_number(split_token(&p1, sep));
  sum = num * num;
  while (p1) {
    num = parse_number(split_token(&p1, sep));
    sum += num * num;
  }
#ifdef FLOATING_POINTS
  sum = sqrt(sum);
#else
  sum = (NVAL) (sqrt(sum) + 0.5);
#endif				/* FLOATING_POINTS */

  if (!sum) {
    /* zero vector */
    p1 = tbuf;
    safe_chr('0', buff, bp);
    while (split_token(&p1, sep), p1) {
      safe_chr(sep, buff, bp);
      safe_chr('0', buff, bp);
    }
    return;
  }
  /* now make the unit vector */
  p1 = tbuf;
  safe_str(unparse_number(parse_number(split_token(&p1, sep)) / sum),
	   buff, bp);
  while (p1) {
    safe_chr(sep, buff, bp);
    safe_str(unparse_number(parse_number(split_token(&p1, sep)) / sum),
	     buff, bp);
  }
}


#ifdef FLOATING_POINTS

/* ARGSUSED */
FUNCTION(fun_fdiv)
{
  NVAL bot;

  if (!is_number(args[0]) || !is_number(args[1])) {
    safe_str(e_nums, buff, bp);
    return;
  }
  bot = parse_number(args[1]);
  if (bot == 0) {
    safe_str("#-1 DIVISION BY ZERO", buff, bp);
    return;
  }
  safe_str(unparse_number(parse_number(args[0]) / bot), buff, bp);
}

/* ARGSUSED */
FUNCTION(fun_floor)
{
  if (!is_number(args[0])) {
    safe_str(e_num, buff, bp);
    return;
  }
  safe_str(unparse_number(floor(parse_number(args[0]))), buff, bp);
}

/* ARGSUSED */
FUNCTION(fun_ceil)
{
  if (!is_number(args[0])) {
    safe_str(e_num, buff, bp);
    return;
  }
  safe_str(unparse_number(ceil(parse_number(args[0]))), buff, bp);
}

/* ARGSUSED */
FUNCTION(fun_round)
{
  char temp[BUFFER_LEN];
  const char *fstr;
  int places;

  if (!is_number(args[0])) {
    safe_str(e_num, buff, bp);
    return;
  }
  if (nargs == 2) {
    if (!is_integer(args[1])) {
      safe_str(e_int, buff, bp);
      return;
    }
    places = parse_integer(args[1]);
  } else
    places = 0;

  switch (places) {
  case 1:
    fstr = "%.1f";
    break;
  case 2:
    fstr = "%.2f";
    break;
  case 3:
    fstr = "%.3f";
    break;
  case 4:
    fstr = "%.4f";
    break;
  case 5:
    fstr = "%.5f";
    break;
  case 6:
    fstr = "%.6f";
    break;
  default:
    fstr = "%.0f";
    break;
  }
  /* The 0.0000001 is a kludge because .15 gets represented as .149999...
   * on many systems, and rounds down to .1. Lame. */
  sprintf(temp, fstr, parse_number(args[0]) + 0.0000001);

  /* Handle the bizarre "-0" sprintf problem. */
  if (!strcmp(temp, "-0"))
    safe_chr('0', buff, bp);
  else
    safe_str(temp, buff, bp);
}

/* ARGSUSED */
FUNCTION(fun_pi)
{
  safe_str("3.141593", buff, bp);
}

/* ARGSUSED */
FUNCTION(fun_e)
{
  safe_str("2.718282", buff, bp);
}

/* ARGSUSED */
FUNCTION(fun_sin)
{
  if (!is_number(args[0])) {
    safe_str(e_num, buff, bp);
    return;
  }
  safe_str(unparse_number(sin(parse_number(args[0]))), buff, bp);
}

/* ARGSUSED */
FUNCTION(fun_asin)
{
  NVAL num;
  if (!is_number(args[0])) {
    safe_str(e_num, buff, bp);
    return;
  }
  num = parse_number(args[0]);
  if ((num < -1) || (num > 1)) {
    safe_str("#-1 OUT OF RANGE", buff, bp);
    return;
  }
  safe_str(unparse_number(asin(num)), buff, bp);
}

/* ARGSUSED */
FUNCTION(fun_cos)
{
  if (!is_number(args[0])) {
    safe_str(e_num, buff, bp);
    return;
  }
  safe_str(unparse_number(cos(parse_number(args[0]))), buff, bp);
}

/* ARGSUSED */
FUNCTION(fun_acos)
{
  NVAL num;
  if (!is_number(args[0])) {
    safe_str(e_num, buff, bp);
    return;
  }
  num = parse_number(args[0]);
  if ((num < -1) || (num > 1)) {
    safe_str("#-1 OUT OF RANGE", buff, bp);
    return;
  }
  safe_str(unparse_number(acos(num)), buff, bp);
}

/* ARGSUSED */
FUNCTION(fun_tan)
{
  if (!is_number(args[0])) {
    safe_str(e_num, buff, bp);
    return;
  }
  safe_str(unparse_number(tan(parse_number(args[0]))), buff, bp);
}

/* ARGSUSED */
FUNCTION(fun_atan)
{
  if (!is_number(args[0])) {
    safe_str(e_num, buff, bp);
    return;
  }
  safe_str(unparse_number(atan(parse_number(args[0]))), buff, bp);
}

/* ARGSUSED */
FUNCTION(fun_exp)
{
  if (!is_number(args[0])) {
    safe_str(e_num, buff, bp);
    return;
  }
  safe_str(unparse_number(exp(parse_number(args[0]))), buff, bp);
}

/* ARGSUSED */
FUNCTION(fun_power)
{
  NVAL num;
  NVAL m;

  if (!is_number(args[0]) || !is_number(args[1])) {
    safe_str(e_nums, buff, bp);
    return;
  }
  num = parse_number(args[0]);
  m = parse_number(args[1]);
  if (num < 0 && (m != (int) m)) {
    safe_str("#-1 FRACTIONAL POWER OF NEGATIVE", buff, bp);
    return;
  }
#ifndef HAS_IEEE_MATH
  if ((num > 100) || (m > 100)) {
    safe_str("#-1 OUT OF RANGE", buff, bp);
    return;
  }
#endif
  safe_str(unparse_number(pow(num, m)), buff, bp);
}

/* ARGSUSED */
FUNCTION(fun_ln)
{
  NVAL num;
  if (!is_number(args[0])) {
    safe_str(e_num, buff, bp);
    return;
  }
  num = parse_number(args[0]);
  if (num < 0) {
    safe_str("#-1 OUT OF RANGE", buff, bp);
    return;
  }
  safe_str(unparse_number(log(num)), buff, bp);
}

/* ARGSUSED */
FUNCTION(fun_log)
{
  NVAL num;
  if (!is_number(args[0])) {
    safe_str(e_num, buff, bp);
    return;
  }
  num = parse_number(args[0]);
  if (num < 0) {
    safe_str("#-1 OUT OF RANGE", buff, bp);
    return;
  }
  safe_str(unparse_number(log10(num)), buff, bp);
}

/* ARGSUSED */
FUNCTION(fun_sqrt)
{
  NVAL num;
  if (!is_number(args[0])) {
    safe_str(e_num, buff, bp);
    return;
  }
  num = parse_number(args[0]);
  if (num < 0) {
    safe_str("#-1 SQUARE ROOT OF NEGATIVE", buff, bp);
    return;
  }
  safe_str(unparse_number(sqrt(num)), buff, bp);
}

#endif				/* FLOATING_POINTS */

/* ARGSUSED */
FUNCTION(fun_isnum)
{
  safe_chr(is_number(args[0]) ? '1' : '0', buff, bp);
}

/* ARGSUSED */
FUNCTION(fun_and)
{
  int j;

  for (j = 0; j < nargs; j++)
    if (!parse_boolean(args[j])) {
      safe_chr('0', buff, bp);
      return;
    }
  safe_chr('1', buff, bp);
}

/* ARGSUSED */
FUNCTION(fun_or)
{
  int j;

  for (j = 0; j < nargs; j++)
    if (parse_boolean(args[j])) {
      safe_chr('1', buff, bp);
      return;
    }
  safe_chr('0', buff, bp);
}

/* ARGSUSED */
FUNCTION(fun_cand)
{
  int j;
  char tbuf[BUFFER_LEN], *tp;
  char const *sp;

  for (j = 0; j < nargs; j++) {
    tp = tbuf;
    sp = args[j];
    process_expression(tbuf, &tp, &sp, executor, caller, enactor,
		       PE_DEFAULT, PT_DEFAULT, pe_info);
    *tp = '\0';
    if (!parse_boolean(tbuf)) {
      safe_chr('0', buff, bp);
      return;
    }
  }
  safe_chr('1', buff, bp);
}

/* ARGSUSED */
FUNCTION(fun_cor)
{
  int j;
  char tbuf[BUFFER_LEN], *tp;
  char const *sp;

  for (j = 0; j < nargs; j++) {
    tp = tbuf;
    sp = args[j];
    process_expression(tbuf, &tp, &sp, executor, caller, enactor,
		       PE_DEFAULT, PT_DEFAULT, pe_info);
    *tp = '\0';
    if (parse_boolean(tbuf)) {
      safe_chr('1', buff, bp);
      return;
    }
  }
  safe_chr('0', buff, bp);
}

/* ARGSUSED */
FUNCTION(fun_not)
{
  safe_chr(parse_boolean(args[0]) ? '0' : '1', buff, bp);
}

/* ARGSUSED */
FUNCTION(fun_t)
{
  safe_chr(parse_boolean(args[0]) ? '1' : '0', buff, bp);
}

/* ARGSUSED */
FUNCTION(fun_xor)
{
  int j, x;

  x = parse_boolean(args[0]);
  for (j = 1; j < nargs; j++)
    x ^= parse_boolean(args[j]);
  safe_chr(x ? '1' : '0', buff, bp);
}