dmuck0.15-beta/docs/muf/
dmuck0.15-beta/game/
dmuck0.15-beta/game/logs/
dmuck0.15-beta/game/muf/
dmuck0.15-beta/game/muf/text/
#include "prims.h"
#include "config.h"
#include "mush.h"

/* private globals */
extern inst *p_oper1, *p_oper2, *p_oper3, *p_oper4;
extern int p_nargs;
extern int p_result;
extern frame *frame_list;
extern dbref p_ref;
extern char p_buf[BUFFER_LEN];

line *get_new_line();
void do_insert_quit(dbref player, dbref p_ref, int flag);

void prims_notify (__P_PROTO)
{
  CHECKOP(2);
  p_oper1 = POP();
  p_oper2 = POP();
  if (!valid_object(p_oper2)) abort_interp("Non-object argument (1)");
  if (p_oper1->type != PROG_STRING)
    abort_interp("Non-string argument (2)");

  if (p_oper1->data.string)
#ifdef HOWARD
/* FIX ME! */
    notify(player, p_oper2->data.objref, p_oper1->data.string);
#else
    notify(player, p_oper2->data.objref, p_oper1->data.string);
#endif

  CLEAR(p_oper1);
  CLEAR(p_oper2);
}

void prims_notify_nolisten (__P_PROTO)
{
  CHECKOP(2);
  p_oper1 = POP();
  p_oper2 = POP();
  if (!valid_object(p_oper2)) abort_interp("Non-object argument (1)");
  if (p_oper1->type != PROG_STRING) abort_interp("Non-string argument (2)");
  if (!p_oper1->data.string) abort_interp("Null string argument (2)");
  if (!fr->wizard) abort_interp("Permission denied.");

    notify_nolisten(p_oper2->data.objref, p_oper1->data.string);

  CLEAR(p_oper1);
  CLEAR(p_oper2);
}

void prims_notify_except (__P_PROTO)
{
  CHECKOP(3);
  p_oper1 = POP();
  p_oper2 = POP();
  p_oper3 = POP();
  if (!valid_object(p_oper3)) abort_interp("Invalid argument (1)");
  if (p_oper2->type != PROG_OBJECT) abort_interp("Invalid object argument (2)");
  if (p_oper1->type != PROG_STRING) abort_interp("Non-string argument (3)");

  if (p_oper1->data.string)
    notify_except(player, p_oper3->data.objref,
         p_oper2->data.objref, p_oper1->data.string);

  CLEAR(p_oper1);
  CLEAR(p_oper2);
  CLEAR(p_oper3);
}

void prims_notify_except_nolisten (__P_PROTO)
{
  CHECKOP(3);
  p_oper1 = POP();
  p_oper2 = POP();
  p_oper3 = POP();
  if (!valid_object(p_oper3)) abort_interp("Invalid argument (1)");
  if (p_oper2->type != PROG_OBJECT) abort_interp("Invalid object argument (2)");
  if (p_oper1->type != PROG_STRING) abort_interp("Non-string argument (3)");
  if (!p_oper1->data.string) abort_interp("Null string argument (3)");
  if (!fr->wizard) abort_interp("Permission denied.");

  notify_except_nolisten(player, p_oper3->data.objref, p_oper2->data.objref, 
                         p_oper1->data.string);

  CLEAR(p_oper1);
  CLEAR(p_oper2);
  CLEAR(p_oper3);
}

/* FORCE ( d s -- ) <- forces a dbref to do an action */
void prims_force (__P_PROTO)
{
 char str[BUFFER_LEN];
 dbref who;
    
  CHECKOP(2);
  p_oper2 = POP();
  p_oper1 = POP();
  if(!valid_object(p_oper1)) abort_interp("Invalid argument (1)");
  if(p_oper2->type != PROG_STRING) abort_interp("Non-string argument (2)");
  if(!p_oper2->data.string) abort_interp("Empty string argument (2)");

  if(!controls(fr->euid, p_oper1->data.objref) &&
     (!(FLAGS(program) & GOD) && !(FLAGS(OWNER(program)) & GOD)))
    abort_interp("Permission denied.");
    
  who=p_oper1->data.objref;
  if(FLAGS(who) & INTERACTIVE) abort_interp("Object is in interactive mode.");
  strcpy(str, p_oper2->data.string);
#ifdef MUSH
 if((FLAGS(who) & HAVEN) && Typeof(who) != TYPE_PLAYER)
   abort_interp("Object is set HALT.");
     
/* parse_que(who, str, who); */
   process_command(who, str, who);
#else
 process_command(who, str, who);
#endif  /* MUSH */
 
  CLEAR(p_oper1);
  CLEAR(p_oper2);
}   

/* From here on out are prims to control/get info on running MUF processes */

void prims_processes(__P_PROTO)
{
 int frames;
 frame *fr1;

    for(fr1 = frame_list, frames = 0; fr1; fr1 = fr1->next) {
    if (*top >= STACK_SIZE) abort_interp("Stack Overflow!");
      p_result = fr1->pid;
      push(arg, top, PROG_INTEGER, MIPSCAST &p_result);
      frames++;
   }
   if (*top >= STACK_SIZE) abort_interp("Stack Overflow!");
   push(arg, top, PROG_INTEGER, MIPSCAST &frames);
}

void prims_pidkill(__P_PROTO)
{
 frame *fr1;
  CHECKOP(1);
  p_oper1 = POP();
  if (p_oper1->type != PROG_INTEGER) abort_interp("Operand not an integer.");

  switch(p_oper1->data.number)
  {
    case -2:
      if (fr->wizard)
      {
	for(fr1 = frame_list; fr1; fr1 = fr1->next)
	  fr1->status = STATUS_DEAD;
      }
      else abort_interp("Permission denied.");
      return;
    case -1:
      for(fr1 = frame_list; fr1; fr1 = fr1->next)
      {
        if (fr1->player == player) fr1->status = STATUS_DEAD;
      }
      return;
    default:
      if((fr1 = find_frame(p_oper1->data.number)))
      {
        if (controls(player, fr1->euid))
        {
          if((FLAGS(fr1->player) & INTERACTIVE) &&
            (fr1->pid == DBFETCH(fr1->player)->sp.player.pid))
            FLAGS(fr1->player) &= ~INTERACTIVE;
            free_frame(fr1);
            CLEAR(p_oper1);
        }
        else abort_interp("Permission denied.");
      }
      else abort_interp ("No such process.");
  }
}

void prims_go(__P_PROTO)
{
 frame *fr1;
  CHECKOP(1);
  p_oper1 = POP();
  if (p_oper1->type != PROG_INTEGER) abort_interp("Operand not an integer.");

  if((fr1 = find_frame(p_oper1->data.number)))
  {
    if ((fr->wizard) || (fr1->player == player))
    {
      fr1->status = STATUS_RUN;
    }
    else abort_interp("Permission denied.");
  }
  else abort_interp ("No such process.");
}

void prims_sleeptime(__P_PROTO)
{
 frame *fr1;
  CHECKOP(1);
  p_oper1 = POP();
  if (p_oper1->type != PROG_INTEGER) abort_interp("Operand not an integer.");

  if((fr1 = find_frame(p_oper1->data.number)))
  {
    if (fr1->status == STATUS_SLEEP) p_result = (fr1->sleeptime - time(NULL));
    else p_result = 0;

    push(arg, top, PROG_INTEGER, MIPSCAST &p_result);
  }
  else abort_interp ("No such process.");
}

void prims_piddbref (__P_PROTO)
{
 frame *fr1;
  CHECKOP(1);
  p_oper1 = POP();
  if (!p_oper1->type == PROG_INTEGER) abort_interp("Operand not an integer.");

    if ((fr1 = find_frame(p_oper1->data.number))) p_ref=fr1->prog;
    else p_ref = (dbref)0;

  push(arg, top, PROG_OBJECT, MIPSCAST &p_ref);
  CLEAR(p_oper1);
}

void prims_pid(__P_PROTO)
{
    p_result = fr->pid;
    push(arg, top, PROG_INTEGER, MIPSCAST &p_result);
}

void prims_isapid(__P_PROTO)
{
    CHECKOP(1);
    p_oper1 = POP();
    if (p_oper1->type != PROG_INTEGER) abort_interp("Non-integer argument");
    p_result = find_a_frame(p_oper1->data.number);
    CLEAR(p_oper1);
    push(arg, top, PROG_INTEGER, MIPSCAST &p_result);
}

void prims_foreground(__P_PROTO)
{
  if(fr->wizard) 
     fr->endless = '1';
  else
     abort_interp("Permission denied.");
}

void prims_compile(__P_PROTO)
{
    CHECKOP(1);
    p_oper1 = POP();
    if(!valid_object(p_oper1)) abort_interp("Invalid argument (1)");

    p_ref =p_oper1->data.objref;
    if(Typeof(p_ref) != TYPE_PROGRAM) 
             abort_interp("Non-program argument");
    if(!fr->wizard  || !controls(player, p_ref))
       abort_interp("Permission denied.");

    /* try to compile it... */
    DBSTORE(p_ref, sp.program.first, read_program(p_ref));
    do_compile(player, p_ref);
    free_prog_text(DBFETCH(p_ref)->sp.program.first);

    if (DBFETCH(p_ref)->sp.program.start == 0)
        p_result = 0;
    else
      p_result =  DBFETCH(p_oper1->data.objref)->sp.program.siz;

    CLEAR(p_oper1);
    push(arg, top, PROG_INTEGER, MIPSCAST &p_result);
}

void prims_uncompile(__P_PROTO)
{
 char buf[200];

    CHECKOP(1);
    p_oper1 = POP();
    if(!valid_object(p_oper1)) abort_interp("Invalid argument (1)");
    p_ref =p_oper1->data.objref;
    if(Typeof(p_ref) != TYPE_PROGRAM) 
             abort_interp("Non-program argument");
    if(!fr->wizard  || !controls(player, p_ref))
       abort_interp("Permission denied.");

    sprintf (buf, "Program %s uncompiled by %s", unparse_name(p_ref),
                     unparse_name(player));
    bump_frames(buf, p_ref, player);
    free_prog(DBFETCH(p_ref)->sp.program.code, DBFETCH(p_ref)->sp.program.siz);
/*  cleanpubs(DBFETCH(p_ref)->sp.program.pubs); */
/*  DBFETCH(p_ref)->sp.program.pubs = NULL; */
    DBFETCH(p_ref)->sp.program.first = 0;
    DBFETCH(p_ref)->sp.program.curr_line = 0;
    DBFETCH(p_ref)->sp.program.siz = 0;
    DBFETCH(p_ref)->sp.program.code = 0;
    DBFETCH(p_ref)->sp.program.start = 0;

    CLEAR(p_oper1);
    push(arg, top, PROG_INTEGER, MIPSCAST &p_result);
}

void prims_newprogram(__P_PROTO)
{
  char buf[300];
    CHECKOP(1);
    p_oper1 = POP();

   if (p_oper1->type != PROG_STRING) abort_interp("Non-string argument.");
   if (!p_oper1->data.string) abort_interp("NULL argument");
   if (!Wizard(fr->euid) || Typeof(fr->euid) != TYPE_PLAYER)
      abort_interp("Permission denied");
  
    p_ref = new_object();
    DBSTORE(p_ref, name, dup_string(p_oper1->data.string));
    sprintf(buf, "A scroll containing a spell called %s", 
    p_oper1->data.string);
#ifndef USE_DBP_STR
    DBSTORE(p_ref, desc, dup_string(buf));
#else
    add_property(p_ref, "desc", buf, PERMS_COREAD | PERMS_COWRITE |
           PERMS_OTREAD, ACCESS_CO);
#endif
    DBSTORE(p_ref, location, fr->euid);
    DBSTORE(p_ref, link, fr->euid);
    add_backlinks(p_ref);
    DBSTORE(p_ref, owner, fr->euid);
    add_ownerlist(p_ref);
    FLAGS(p_ref) = TYPE_PROGRAM;
    DBSTORE(p_ref, sp.program.first, 0);
    DBSTORE(p_ref, sp.program.curr_line, 0);
    DBSTORE(p_ref, sp.program.siz, 0);
    DBSTORE(p_ref, sp.program.code, 0);
    DBSTORE(p_ref, sp.program.start, 0);
    DBSTORE(p_ref, sp.program.editlocks, NULL);
/*  DBSTORE(fr->euid, curr_prog, p_ref); */
    PUSH(p_ref, DBFETCH(fr->euid)->contents);
    DBDIRTY(p_ref);
    DBDIRTY(fr->euid);
    p_result = (int) p_ref;

    CLEAR(p_oper1);
    push(arg, top, PROG_INTEGER, MIPSCAST &p_result);
}

void prims_prog_size(__P_PROTO)
{
    if (*top >= STACK_SIZE) abort_interp("Stack Overflow!");
    p_result =  DBFETCH(p_oper1->data.objref)->sp.program.siz;
    push(arg, top, PROG_INTEGER, MIPSCAST &p_result);
}

void prims_new_macro(__P_PROTO)
{
  macrotable *newmacro;
  CHECKOP(2);
  p_oper1 = POP();
  p_oper2 = POP();

   if (p_oper1->type != PROG_STRING || p_oper2->type != PROG_STRING)
       abort_interp("Non-string argument.");
   if (!p_oper1->data.string || !p_oper1->data.string)
       abort_interp("NULL argument.");

   newmacro = new_macro (p_oper2->data.string, p_oper1->data.string, fr->euid);
   if (!macrotop) macrotop = newmacro;
   else if (!grow_macro_tree(macrotop, newmacro))
     p_result = 0;
   else 
     p_result = 1;

    CLEAR(p_oper1);
    CLEAR(p_oper2);
    push(arg, top, PROG_INTEGER, MIPSCAST &p_result);
}

void prims_kill_macro(__P_PROTO)
{
  char tmp[BUFFER_LEN];
  CHECKOP(1);
  p_oper1 = POP();

  if (p_oper1->type != PROG_STRING) abort_interp("Non-string argument.");
  if (!p_oper1->data.string) abort_interp("NULL argument.");
  if (!fr->wizard) abort_interp("Permission denied");

  strcpy(tmp, p_oper1->data.string);

  if (!string_compare(tmp, macrotop->name))
  {
    macrotable *macrotemp = macrotop;
    int whichway = (macrotop->left) ? 1 : 0;
    macrotop = whichway ? macrotop->left : macrotop->right;
    if (macrotop && (whichway ? macrotemp->right : macrotemp->left))
      grow_macro_tree(macrotop, whichway ?
        macrotemp->right : macrotemp->left);
    free ((void *) macrotemp);
    p_result =1;
  }
  else if (erase_node(macrotop, macrotop, tmp))
    p_result =1;
  else 
    p_result =0;

    CLEAR(p_oper1);
    push(arg, top, PROG_INTEGER, MIPSCAST &p_result);
}

void prims_get_macro(__P_PROTO)
{
  char *tmp;
  CHECKOP(1);
  p_oper1 = POP();

  if (p_oper1->type != PROG_STRING) abort_interp("Non-string argument.");
  if (!p_oper1->data.string) abort_interp("NULL argument.");

  if (!(tmp = (char *)macro_expansion(macrotop, p_oper1->data.string)))
     strcpy(p_buf, "");
  else
     strcpy(p_buf, tmp);

  CLEAR(p_oper1);
  push(arg, top, PROG_STRING, MIPSCAST dup_string(p_buf));
}

void prims_delete(__P_PROTO)
{
  line   *curr, *temp;
  int   i, one=0, two=0, flag=0;

  CHECKOP(2);
  p_oper1 = POP();
  p_oper2 = POP();

  if (p_oper1->type != PROG_INTEGER) abort_interp("Non-interger argument.");
  if (p_oper2->type == PROG_INTEGER)  {
     CHECKOP(1);
     p_oper3 = POP();
     if (!valid_object(p_oper3)) abort_interp("Non-object argument (3)");
     one = p_oper2->data.number;
     if (one <= 0) abort_interp("Negative/zero line number.(2)");
     flag++;
  }

  two = p_oper1->data.number;
  if (two <= 0) abort_interp("Negative/zero line number.(1)");
  if(flag)
     p_ref = p_oper3->data.objref;
  else
     p_ref = p_oper2->data.objref;

  if (Typeof(p_ref) != TYPE_PROGRAM) abort_interp("Invalid PROGRAM(2)");
  if (!controls(player, p_ref)) abort_interp("Permission denied");
  if (DBFETCH(p_ref)->sp.program.editlocks != NULL)
      abort_interp("That program is being edited.");

  if(!flag)
    one = two;
  if (one > two) abort_interp("Nonsensical arguments.");

  DBSTORE(p_ref, sp.program.first, read_program(p_ref));
  DBSTORE(player, curr_prog, p_ref);
  DBSTORE(p_ref, sp.program.editlocks,
    dbreflist_add(DBFETCH(p_ref)->sp.program.editlocks, player));
  DBDIRTY(player);
  DBDIRTY(p_ref);

      i = one - 1;
      for (curr = DBFETCH(p_ref)->sp.program.first; curr && i; i--)
        curr = curr->next;
      if (curr)
      {
        DBFETCH(p_ref)->sp.program.curr_line = one;
        i = two - one + 1;
          /* delete n lines */
        while (i && curr)
        {
          temp = curr;
          if (curr->prev) curr->prev->next = curr->next;
          else DBFETCH(p_ref)->sp.program.first = curr->next;
          if (curr->next) curr->next->prev = curr->prev;
          curr = curr->next;
          free_line(temp);
          i--;
        }
        p_result = two - one - i + 1;
      }
      else p_result = 0;

  do_insert_quit(player, p_ref, flag);
  push(arg, top, PROG_INTEGER, MIPSCAST &p_result);
}

void prims_insert(__P_PROTO)
{
  dbref edprog;
  int  i;
  line *curr;
  line *new_line;

  CHECKOP(3);
  p_oper1 = POP();
  p_oper2 = POP();
  p_oper3 = POP();

  if (!valid_object(p_oper3)) abort_interp("Non-object argument (1)");
  if (p_oper2->type != PROG_INTEGER) abort_interp("Non-integer argument (2)");
  if (p_oper1->type != PROG_STRING) abort_interp("Non-string argument (3)");

  p_result = p_oper2->data.number;
  if (p_result <= 0) abort_interp("Negative/zero line number.(1)");

  p_ref = p_oper3->data.objref;
  if (Typeof(p_ref) != TYPE_PROGRAM) abort_interp("Invalid PROGRAM(2)");
  if (!controls(fr->euid, p_ref)) abort_interp("Permission denied");
  if (DBFETCH(p_ref)->sp.program.editlocks != NULL)
      abort_interp("That program is being edited.");

  if(!p_oper1->data.string)  abort_interp("NULL argument. (3)");
    strcpy(p_buf, p_oper1->data.string);

  DBFETCH(player)->sp.player.insert_mode++;
  DBSTORE(p_ref, sp.program.first, read_program(p_ref));
  DBSTORE(player, curr_prog, p_ref);
  DBSTORE(p_ref, sp.program.editlocks,
    dbreflist_add(DBFETCH(p_ref)->sp.program.editlocks, player));
  DBDIRTY(player);
  DBDIRTY(p_ref);

  edprog = DBFETCH(player)->curr_prog;
  i = DBFETCH(edprog)->sp.program.curr_line - 1;
  for (curr = DBFETCH(edprog)->sp.program.first;
    curr && i && i + 1;
    i--, curr = curr->next);
  new_line = get_new_line();         /* initialize line */
  new_line->this_line = dup_string(p_buf);
  if (!DBFETCH(edprog)->sp.program.first)
  /* nothing --- insert in front */
  {
    DBFETCH(edprog)->sp.program.first = new_line;
    DBFETCH(edprog)->sp.program.curr_line  = 2;        /* insert at the end */
    DBDIRTY(edprog);
    do_insert_quit(player, p_ref, 1);
    return;
  }
  if (!curr)                 /* insert at the end */
  {
    i = 1;
    for (curr = DBFETCH(edprog)->sp.program.first;
      curr->next;
      curr = curr->next, i++);
    DBFETCH(edprog)->sp.program.curr_line = i + 2;
    new_line->prev = curr;
    curr->next = new_line;
    DBDIRTY(edprog);
    do_insert_quit(player, p_ref, 1);
    return;
  }
  if (!DBFETCH(edprog)->sp.program.curr_line)   /* insert at the beginning */
  {
    DBFETCH(edprog)->sp.program.curr_line = 1; /* insert after this new line */
    new_line->next = DBFETCH(edprog)->sp.program.first;
    DBFETCH(edprog)->sp.program.first = new_line;
    DBDIRTY(edprog);
    do_insert_quit(player, p_ref, 1);
    return;
  }
  /* inserting in the middle */
  DBFETCH(edprog)->sp.program.curr_line++;
  new_line->prev = curr;
  new_line->next = curr->next;
  if (new_line->next) new_line->next->prev = new_line;
  curr->next = new_line;
  DBDIRTY(edprog);
  do_insert_quit(player, p_ref, 1);
}

void do_insert_quit(dbref player, dbref p_ref, int flag)
{
  write_program(DBFETCH(p_ref)->sp.program.first, p_ref);
  free_prog_text(DBFETCH(p_ref)->sp.program.first);
  DBSTORE(p_ref, sp.program.editlocks,
    dbreflist_remove(DBFETCH(p_ref)->sp.program.editlocks, player));
  DBSTORE(player, curr_prog, NOTHING);
  DBFETCH(player)->sp.player.insert_mode =0;
  DBDIRTY(player);
  DBDIRTY(p_ref);
  CLEAR(p_oper1);
  CLEAR(p_oper2);
  if(flag)
    CLEAR(p_oper3);
}

void prims_getlines(__P_PROTO)
{
  line *curr;
  int   i, count, one, two;

  CHECKOP(3);
  p_oper1 = POP();
  p_oper2 = POP();
  p_oper3 = POP();

  if (!valid_object(p_oper3)) abort_interp("Non-object argument (1)");
  if (p_oper2->type != PROG_INTEGER || p_oper1->type != PROG_INTEGER) 
     abort_interp("Non-integer arguments");

  one = p_oper2->data.number;
  two = p_oper1->data.number;
  p_ref = p_oper3->data.objref;

  if (Typeof(p_ref) != TYPE_PROGRAM) abort_interp("Non-program object");
  if (!(controls(player, p_ref) || Linkable(p_ref)))
    abort_interp("Permission denied.");
  if (DBFETCH(p_ref)->sp.program.editlocks != NULL)
      abort_interp("That program is being edited.");

      if ((one > two) && (two != -1))
          abort_interp("Arguments don't make sense!");
      DBSTORE(p_ref, sp.program.first, read_program(p_ref));
      DBDIRTY(p_ref);
      i = one - 1;
      for (curr = DBFETCH(p_ref)->sp.program.first;
	i && curr;
	i--, curr = curr->next);
      if (curr)
      {
        i = two - one + 1;
        /* display n lines */
        for (count = one; curr && (i || (two == -1)); i--)
        {
          if (*top >= STACK_SIZE) abort_interp("Stack Overflow!");
          sprintf(p_buf, "%s", DoNull(curr->this_line));
          push(arg, top, PROG_STRING, MIPSCAST dup_string(p_buf));
          count++;
          curr = curr->next;
        }
          if (*top >= STACK_SIZE) abort_interp("Stack Overflow!");
          p_result = count - one;
          push(arg, top, PROG_INTEGER, MIPSCAST &p_result);
      }
      else abort_interp("Line not available.");

  if (!(FLAGS(p_ref) & INTERNAL))
    free_prog_text(DBFETCH(p_ref)->sp.program.first);
  CLEAR(p_oper1);
  CLEAR(p_oper2);
  CLEAR(p_oper3);
}

void prims_prog_lines(__P_PROTO)
{
  line *curr;
  CHECKOP(1);
  p_oper1 = POP();
  if (!valid_object(p_oper1)) abort_interp("Non-object argument (1)");
  p_ref = p_oper1->data.objref;
  if(Typeof(p_ref) != TYPE_PROGRAM) abort_interp("Non-program object");

  if (DBFETCH(p_ref)->sp.program.editlocks != NULL)
      abort_interp("That program is being edited.");

      DBSTORE(p_ref, sp.program.first, read_program(p_ref));
      DBDIRTY(p_ref);
      curr = DBFETCH(p_ref)->sp.program.first;
      if (curr)
        for(p_result = 0; curr; curr = curr->next) 
            p_result++;

      else p_result=0;

      if (*top >= STACK_SIZE) abort_interp("Stack Overflow!");
      push(arg, top, PROG_INTEGER, MIPSCAST &p_result);

  if (!(FLAGS(p_ref) & INTERNAL))
     free_prog_text(DBFETCH(p_ref)->sp.program.first);
  CLEAR(p_oper1);
}