TinyMAZE/
TinyMAZE/config/
TinyMAZE/doc/
TinyMAZE/run/msgs/
TinyMAZE/src/
TinyMAZE/src/db/
TinyMAZE/src/ident/
TinyMAZE/src/io/
TinyMAZE/src/prog/
TinyMAZE/src/softcode/
TinyMAZE/src/util/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include "db.h"
#include "externs.h"
#include "softcode.h"

int parse_output(char *str, char *retbuf)
{
  char buf[4096];
  char *mbuf;
  char *p;
  int type = 1;

  if(!(p = is_math(str)) || *p)
  {
    p = str;
    while((p = is_string(p)));     /* Whole loop */

    if(p && *p)
      return(-1);

    type = 0;
  }

  if(type)
  {
    if(parse_statement(str, retbuf))
      return(-1);
    return(type);
  }

  strcpy(retbuf, str);
  mbuf = retbuf;

  while((p = is_string(retbuf)))
  {
    strncpy(buf, mbuf, p-mbuf);
    *(buf+(p-mbuf)) = '\0';

    extract_char(buf);
    extract_char(buf+strlen(buf)-1);

    sprintf(mbuf, "%s%s", buf, p);
    p = mbuf+strlen(buf);

    mbuf = p;
  }

  return(type);
}

char *is_string(char *str)
{
  char *p = str;

  if(!*p)
    return(NULL);

  while(*p)
  {
    if(*p++ != '"')
      return(NULL);
    while(*p && *p != '"')
      p++;
    if(*p++ != '"')
      return(NULL);
    break;
  }

  return(p);
}

static void add_part(char *str, int len, char ***parts, int *num_parts)
{
  char buf[4096];

  strncpy(buf, str, len);
  *(buf+len) = '\0';

  *parts = (char **)stack_realloc_tmp(*parts, sizeof(char *)*((*num_parts)+1));
  (*parts)[(*num_parts)++] = stack_string_alloc(buf, 0);
}

static int split_line(char *str, char ***parts)
{
  char *p;
  int num_parts = 0;

  *parts = (char **)stack_alloc(sizeof(char *), 0, 0);

  while(*str)
  {
    if(*str == '\"')
    {
      for(p = str+1;*p && *p != '\"';p++);
      if(!*p)
      {
        syntax_error();
        return(-1);
      }
      p++;
      add_part(str, p-str, parts, &num_parts);
    }
    else
    {
      if((p = strchr(str, '\"')))
        add_part(str, p-str, parts, &num_parts);
      else
      {
        add_part(str, strlen(str), parts, &num_parts);
        p = str+strlen(str);
      }
    }

    str = p;
  }

  return(num_parts);
}

void sc_do_print(char *arg1, char *arg2)
{
  OBJ *victim;
  char *msg;
  char buf[4096], output[4096] = "";
  char **parts;
  int i, num_parts;

  if(!*arg1)
  {
    victim = code_ptr->executor;
    msg = "\"\"";
  }
  else if(!*arg2)
  {
    victim = code_ptr->executor;
    msg = arg1;
  }
  else
  {
    victim = match_object(code_ptr->object, arg1, NOTYPE);
    if(!victim)
    {
      notify(code_ptr->executor, no_match(arg1));
      return;
    }
    msg = arg2;
  }

  if((num_parts = split_line(msg, &parts)) == -1)
    return;

  for(i = 0;i < num_parts;++i)
  {
    if(is_math(parts[i]))
    {
      if(parse_statement(parts[i], buf))
        return;
      strcat(output, buf);
    }
    else if(is_string(parts[i]))
    {
      extract_char(parts[i]);
      extract_char(last_char(parts[i]));
      strcat(output, parts[i]);
    }
    else if(!strcmp(parts[i], ";") && i+1 == num_parts)
      break;
    else
    {
      syntax_error();
      return;
    }
  }

  if(i != num_parts)
    raw_notify(victim, output, 0);
  else
    notify(victim, output);
}

void sc_do_let(char *arg1, char *arg2)
{
  char varname[4096];
  char buf[4096], parsed_arg2[4096] = "";
  SCVAR *var;
  char **parts;
  int i, num_parts;
  bool type;

  if(*(arg1++) != '~')
  {
    syntax_error();
    return;
  }

  if(!get_varname(arg1, varname))
  {
    syntax_error();
    return;
  }

  if((num_parts = split_line(arg2, &parts)) == -1)
    return;

  if(!num_parts)
  {
    syntax_error();
    return;
  }

  if(*last_char(varname) == '$')
  {
    type = VAR_STR;
    *last_char(varname) = '\0';           /* Get rid of the '$' */

    for(i = 0;i < num_parts;++i)
    {
      if(!is_string(parts[i]))
        break;
      extract_char(parts[i]);
      extract_char(last_char(parts[i]));
      strcat(parsed_arg2, parts[i]);
    }

    if(i != num_parts)
    {
      notify(code_ptr->executor,
        tprintf("|+R|Type Mismatch in |+Y|%d|+R|.",
        code_ptr->pline->line));
      notify(code_ptr->executor, tprintf("%d %s",
        code_ptr->pline->line, code_ptr->pline->code));
      end_program(code_ptr->program, 0);
      return;
    }
  }
  else
  {
    type = VAR_NUM;

    for(i = 0;i < num_parts;++i)
    {
      if(!is_math(parts[i]))
        break;
      if(parse_statement(parts[i], buf))
        return;
      strcat(parsed_arg2, buf);
    }

    if(i != num_parts)
    {
      notify(code_ptr->executor,
        tprintf("|+R|Type Mismatch in |+Y|%d|+R|.",
        code_ptr->pline->line));
      notify(code_ptr->executor, tprintf("%d %s",
        code_ptr->pline->line, code_ptr->pline->code));
      end_program(code_ptr->program, 0);
      return;
    }
  }

  var = find_var(varname, type);

  if(!var->can_modify)
  {
    notify(code_ptr->executor,
      tprintf("|+R|Attempt to modify a secure variable in |+Y|%d|+R|.",
      code_ptr->pline->line));
    notify(code_ptr->executor, tprintf("%d %s",
      code_ptr->pline->line, code_ptr->pline->code));
    end_program(code_ptr->program, 0);
    return;
  }

  if(type == VAR_STR)
    var->cvalue = stack_string_realloc(var->cvalue,
      tprintf("\"%s\"", parsed_arg2));
  else
    var->nvalue = atoi(parsed_arg2);
}

void sc_do_input(char *arg1, char *arg2)
{
  char *varname;
  OBJ *victim;
  SCINPUT *new_input;

  if(!*arg1)
  {
    victim = code_ptr->executor;
    varname = "\"\"";
  }
  else if(!*arg2)
  {
    victim = code_ptr->executor;
    varname = arg1;
  }
  else
  {
    if(!(victim = match_object(code_ptr->object, arg1, NOTYPE)))
    {
      notify(code_ptr->object, no_match(arg1));
      return;
    }
    varname = arg2;
  }

  if(*varname++ != '~')
  {
    syntax_error();
    return;
  }

  new_input = (SCINPUT *)stack_alloc(sizeof(SCINPUT), 1, 0);

  if(*last_char(varname) == '$')
  {
    *last_char(varname) = '$';

    cvar_val(varname);  /* Create the variable */

    if(!code_ptr)   /* cvar_val() NULLs this if varname is invalid */
      return;

    new_input->var = find_var(varname, VAR_STR);
  }
  else
  {
    ivar_val(varname);

    if(!code_ptr)
      return;

    new_input->var = find_var(varname, VAR_NUM);
  }

  new_input->next = code_ptr->input;
  code_ptr->input = new_input;
}

int check_softcode_input(OBJ *player, char *str)
{
  CODE *c;
  SCINPUT *freeme;

  for(c = code_list;c;c = c->next)
    if(c->input && c->executor == player)
      break;

  if(!c)
    return(0);

  if(!string_compare(str, "quit"))
  {
    code_ptr = c;
    notify(player, tprintf("Aborting program %s.", c->program->name));
    end_program(c->program, 1);
    return(1);
  }

  if(c->input->var->type == VAR_STR)
    c->input->var->cvalue = stack_string_realloc(c->input->var->cvalue,
      tprintf("\"%s\"", str));
  else
    c->input->var->nvalue = atoi(str);

  freeme = c->input;
  c->input = c->input->next;
  stack_free(freeme);

  return(1);
}