/* Copyright 1989, 1990 by James Aspnes, David Applegate, and Bennet Yee */
/* See the file COPYING for distribution information */
#include "db.h"
#include "config.h"
#include "bytecode.h"
#include "globals.h"
#include "interface.h"
#include "externs.h"

static datum sys_examine (void)
{
  struct object *o;
  char buf[MAX_STRLEN + MAX_STRLEN + 16];
  datum key;
  datum value;
  char *p;

  /* you examine me */
  if ((o = object (me)) == 0)
    return 0;

  FOREACH (o->vars, key, value) {
    strcpy (buf, string (key));
    strcat (buf, ": ");
    p = buf + strlen (buf);

    switch (*buf) {
    case STRING_MARKER:
      if (value != NOTHING) {
        strcpy (p, string (value));
      }
      break;
    case BOOL_MARKER:
      strcpy (p, value ? "TRUE" : "FALSE");
      break;
    case TIME_MARKER:
      strcpy (p, time_string (value));
      break;
    case NUM_MARKER:
    default:
      sprintf (p, "%ld", value);
      break;
    }

    notify (you, buf);
  }
  END_FOREACH;

  /* just dump the names of the sets */
  FOREACH (o->sets, key, value) {
    notify (you, string (key));
  }
  END_FOREACH;

  if (!isempty (o->actions)) {
    FOREACH (o->actions, key, value) {
      sprintf (buf, "%c%s", ACTION_MARKER, string (key));
      notify (you, buf);
    }
    END_FOREACH;
  }

  return 1;
}

static datum do_request (int *flag)
{
  if (flag_set (you, F_ADMIN)) {
    *flag = 1;
    return 1;
  } else {
    return 0;
  }
}

static datum sys_gc (void)
{
  return do_request (&please_gc);
}

static datum sys_checkpoint (void)
{
  return do_request (&please_checkpoint);
}

static datum sys_shutdown (void)
{
  return do_request (&shutdown_flag);
}

/* encrypt password on me */
static datum sys_encrypt_password (void)
{
  datum password;

  if ((password = lookup (me, PASSWORD_NAME)) == NOTHING) {
    return 0;
  }
  /* else */
  return set_variable (me, PASSWORD_NAME,
    intern (encrypt_password (string (password))));
}

/* checks all the code on me and reports errors to you */
static datum sys_verify (void)
{
  datum key;
  datum value;
  char buf[MAX_STRLEN];
  const char *s;
  datum *code;
  struct object *o;

  if ((o = object (me)) == 0)
    return 0;

  if (!isempty (o->actions)) {
    FOREACH (o->actions, key, value) {
      if ((s = string (value)) == 0) {
        sprintf (buf, "&%s: no code!", string (key));
        notify (you, buf);
      } else if ((code = compile (s)) == 0) {
        sprintf (buf, "&%s: %s", string (key), compile_error);
        notify (you, buf);
      } else {
        /* everything ok, free the compiled block */
        /* (it's not safe to call set_compiled_string down here) */
        free ((void *) code);
      }
    } END_FOREACH;
  }

  return 1;
}

static datum sys_remove_delays (void)
{
  remove_delays (me);
  return 1;
}

#define SYSFUNC_COUNT (7)

static datum (*sysfuncs[SYSFUNC_COUNT]) (void) = {
sys_examine,
    sys_gc,
    sys_checkpoint,
    sys_shutdown, sys_encrypt_password, sys_verify, sys_remove_delays,};

datum do_syscall (datum number)
{
  if (number <= 0 || number > SYSFUNC_COUNT) {
    return 0;
  } else {
    return (*sysfuncs[number - 1]) ();
  }
}