/* $Header: /belch_a/users/rearl/tinymuck/src/RCS/inst.c,v 1.9 90/09/28 12:26:25 rearl Exp $ */

/*
 * $Log:	inst.c,v $
 * Revision 1.9  90/09/28  12:26:25  rearl
 * Added hack to prevent direct call of JMP or PROGRAM words, added
 * shared program strings.
 * 
 * Revision 1.8  90/09/18  07:57:35  rearl
 * Changed the primitive table to work with the hash functions.
 * 
 * Revision 1.7	 90/09/13  06:24:14  rearl
 * Changed some erroneous primitive strings, added PUT and EXECUTE.
 * 
 * Revision 1.6	 90/09/05  02:32:04  rearl
 * Changed order of stack dump to actually reflect the stack...
 * 
 * Revision 1.5	 90/08/27  03:26:09  rearl
 * Changed P's to ?'s, added INSTR, RINSTR, OK? TIME.
 * 
 * Revision 1.4	 90/08/11  04:02:32  rearl
 * *** empty log message ***
 * 
 * Revision 1.3	 90/07/29  23:45:53  rearl
 * Added string primitives: strncmp, strcut, strlen.
 * 
 * Revision 1.2	 90/07/29  17:34:50  rearl
 * Added debugging code, also new primitives such as PRONOUN_SUB.
 * 
 * Revision 1.1	 90/07/19  23:03:40  casie
 * Initial revision
 * 
 *
 */

#include "copyright.h"
#include "config.h"

#include "db.h"
#include "inst.h"
#include "externs.h"
#include "interface.h"
#include "strings.h"

/* these arrays MUST agree with what's in inst.h */
const char *base_inst[] = {
  "IF",		/* 1 */
  "+",
  "-",
  "*",
  "/",		/* 5 */
  "POP",
  "DUP",
  "CALL",
  "NUMBER?",
  "STRCMP",		/* 10 */
  "STRINGCMP",
  "STRCAT",
  "ATOI",
  "AND",
  "OR",			/* 15 */
  "NOT",
  "READ",
  "NOTIFY",
  "NOTIFY_EXCEPT",
  "EXIT",		/* 20 */
  "JMP ",
  "ADDPENNIES",
  "@",
  "!",
  "GETPROPVAL",		/* 25 */
  "GETPROPSTR",
  "SETPROP",
  "REMOVE_PROP",
  "MOVETO",
  "PENNIES",		/* 30 */
  "<",
  ">",
  "=",
  "<=",
  ">=",			/* 35 */
  "RANDOM",
  "%",
  "INTOSTR",
  "DBCMP",
  "DBREF",		/* 40 */
  "INT",
  "VARIABLE",
  "SWAP",
  "CONTENTS",
  "NAME",		/* 45 */
  "SETNAME",
  "EXPLODE",
  "MATCH",
  "COPYOBJ",
  "SUBST",		/* 50 */
  "SET",
  "LOCATION",
  "PLAYER?",
  "THING?",
  "ROOM?",		/* 55 */
  "PROGRAM?",
  "EXIT?",
  "FLAG?",
  "OWNER",
  "RMATCH",		/* 60 */
  "OVER",
  "PICK",
  "PUT",
  "ROT",
  "ROTATE",		/* 65 */
  "GETLINK",
  "PRONOUN_SUB",
  "STRNCMP",
  "STRCUT",
  "STRLEN",		/* 70 */
  "INSTR",
  "RINSTR",
  "OK?",
  "TIME",
  "EXECUTE",		/* 75 */
  "EXITS",
  "NEXT",
  "PROGRAM ",
  "ONLINE",
  "AWAKE?",		/* 80 */
  "CONBOOT",
  "CONCOUNT",
  "CONDBREF",
  "CONHOST",
  "CONIDLE",		/* 85 */
  "CONNECTIONS",
  "CONTIME",
  "STRINGNCMP",
  "PROG",
  "SELF",		/* 90 */
  "SYSTIME",
  "STRFTIME",
  "DEPTH",
  "WILD_MATCH",
  "PRONOUN_EVAL",
  "CHECKFUNC",		/* 95 */
  "HALT",
  "TRIGOBJ",
  };

/* converts an instruction into a printable string, stores the string in
   an internal buffer and returns a pointer to it */
char *insttotext(struct inst *theinst)
{
  static char	buffer[64];
  
  switch(theinst->type) {
  case PROG_PRIMITIVE:
    if (theinst->data.number >= BASE_MIN &&
	theinst->data.number <= BASE_MAX)
      strcpy(buffer,base_inst[theinst->data.number-BASE_MIN]);
    else strcpy(buffer,"???");
    break;
  case PROG_STRING:
    if (!theinst->data.string) {
      strcpy(buffer, "\"\"");
      break; }
    sprintf(buffer,"\"%1.29s", theinst->data.string->data);
    if (theinst->data.string->length<=30)
      strcat(buffer,"\"");
    else
      strcat(buffer,"_");
    break;
  case PROG_INTEGER:
    sprintf(buffer,"%d", theinst->data.number);
    break;
  case PROG_ADD:
    strcpy(buffer, "addr");
    break;
  case PROG_OBJECT:
    sprintf(buffer,"#%d", theinst->data.objref);
    break;
  case PROG_VAR:
    sprintf(buffer,"V%d", theinst->data.number);
    break;
  case PROG_CON:
    sprintf(buffer, "C%d", theinst->data.con->descriptor);
    break;
  default:
    strcpy(buffer,"???");
    break; }
  return buffer;
}

/* produce one line summary of current state.  Note that sp is the next
   space on the stack -- 0..sp-1 is the current contents. */
char *debug_inst(struct inst *pc, struct inst *stack, int sp, dbref program)
{
  static char	buffer[512];
  int		count;
  int           i = (int) (pc - DBFETCH(program)->sp.program.code);
  static dbref  last;

  if(program != last) {
    sprintf(buffer, "#%-5d", (int) program);
    last = program;
  }
  else
    sprintf(buffer, "Debug ");

  if(i < 0)
    strcat(buffer, "[ RET ] S( ", (int) program);
  else
    sprintf(buffer, "%s[%5d] S( ", buffer, i);

  if (sp > 5) strcat(buffer, "..., ");
  count = (sp > 5) ? sp - 5 : 0;
  while (count < sp) {
    strcat(buffer, insttotext(stack + count));
    if (++count < sp) strcat(buffer, ", ");
  }
  strcat(buffer, " ) ");
  strcat(buffer, insttotext(pc));
  return(buffer);
}