dbm/
misc/
old-docs/
#include <stdio.h>
#include <ctype.h>
#include "teeny.h"

#define O_TYPE_ROOM	0x0
#define O_TYPE_THING	0x1
#define O_TYPE_EXIT	0x2
#define O_TYPE_PLAYER	0x3
#define O_TYPE_MASK	0x7
#define O_ANTILOCK	0x8
#define O_WIZARD	0x10
#define O_LINK_OK	0x20
#define O_DARK		0x40
#define O_TEMPLE	0x80
#define O_STICKY	0x100
#define O_BUILDER	0x200
#define O_HAVEN		0x400
#define O_ABODE		0x800
#define O_ROBOT		0x4000
#define O_GOD		0x40000
#define O_GENDER_MASK	0x3000
#define O_GENDER_SHIFT	12
#define O_GENDER_UNASSIGNED	0x0
#define O_GENDER_NEUTER	0x1
#define O_GENDER_FEMALE	0x2
#define O_GENDER_MALE	0x3
#ifdef GARBAGE
#define O_TYPE_GARBAGE	0x6

int             Garbage = 0;

#endif				/* GARBAGE */

extern char    *malloc();
extern void     free();

char            Name[BUFFSIZ + 16];
char            Password[BUFFSIZ + 16];
char            Description[BUFFSIZ + 16];
char            Fail[BUFFSIZ + 16];
char            Success[BUFFSIZ + 16];
char            Ofail[BUFFSIZ + 16];
char            Osuccess[BUFFSIZ + 16];
char            Gender[BUFFSIZ + 16];
char            Lockbuff[BUFFSIZ + 16];
int            *Lock = NULL;
int             Flags;
int             Next;
int             Pennies;
int             Location;
int             Exits;
int             Owner;
int             Contents;
int             Home;

#ifdef TIMESTAMPS
int             Timestamp;

#endif				/* TIMESTAMPS */

int             Increment = 0;
int             total_objects = 0;
char           *prog;

int             convert_file(in, out)
  FILE           *in;
  FILE           *out;
{
  int             i, objnum;
  int             done = 0;
  char            work[BUFFSIZ + 16];

  for (i = 0; !done; i++) {
    if (fgets(work, BUFFSIZ + 16, in) == NULL) {
      fprintf(stderr, "%s: unexpected EOF in input db.\n", prog);
      goto fail;
    }
    switch (work[0]) {
    case '#':
      objnum = atoi(work + 1);

      /*
       * if(objnum != i){ fprintf(stderr, "%s: input and output dbs are out
       * of synch.\n", prog); goto fail; }
       */
      if (fgets(Name, BUFFSIZ + 16, in) == NULL)
	goto fail;
      if (fgets(Description, BUFFSIZ + 16, in) == NULL)
	goto fail;
      if (fgets(work, BUFFSIZ + 16, in) == NULL)
	goto fail;
      Location = atoi(work);
      if (fgets(work, BUFFSIZ + 16, in) == NULL)
	goto fail;
      Contents = atoi(work);
      if (fgets(work, BUFFSIZ + 16, in) == NULL)
	goto fail;
      Exits = atoi(work);
      if (fgets(work, BUFFSIZ + 16, in) == NULL)
	goto fail;
      Next = atoi(work);
      if (fgets(Lockbuff, BUFFSIZ + 16, in) == NULL)
	goto fail;
      if (fgets(Fail, BUFFSIZ + 16, in) == NULL)
	goto fail;
      if (fgets(Success, BUFFSIZ + 16, in) == NULL)
	goto fail;
      if (fgets(Ofail, BUFFSIZ + 16, in) == NULL)
	goto fail;
      if (fgets(Osuccess, BUFFSIZ + 16, in) == NULL)
	goto fail;
      if (fgets(work, BUFFSIZ + 16, in) == NULL)
	goto fail;
      Owner = atoi(work);
      if (fgets(work, BUFFSIZ + 16, in) == NULL)
	goto fail;
      Pennies = atoi(work);
      if (fgets(work, BUFFSIZ + 16, in) == NULL)
	goto fail;
      Flags = atoi(work);
      if (fgets(Password, BUFFSIZ + 16, in) == NULL)
	goto fail;
#ifdef TIMESTAMPS
      if (fgets(work, BUFFSIZ + 16, in) == NULL)
	goto fail;
      if (fgets(work, BUFFSIZ + 16, in) == NULL)
	goto fail;
      Timestamp = (int) (atol(work) / 60);
      if (fgets(work, BUFFSIZ + 16, in) == NULL)
	goto fail;
#endif				/* TIMESTAMP */
      if (convert_object() == -1) {
	fprintf(stderr, "%s: failed to convert object #%d.\n", prog, i);
	goto fail;
      }
      if (write_object(objnum, out) == -1) {
	fprintf(stderr, "%s: failed to write object #%d.\n", prog, i);
	goto fail;
      }
      break;
    case '*':
      done = 1;
      break;
    default:
      fprintf(stderr, "%s: input db is totally fucked.\n", prog);
      goto fail;
    }
  }
  total_objects = i + 1;
  fclose(in);
  return 1;

fail:

  fclose(in);
  return -1;
}
int             convert_object()
{
  int             newflags;

  /* convert the flags first thing */
  switch (Flags & O_TYPE_MASK) {
  case O_TYPE_THING:
    newflags = TYP_THING;
    break;
  case O_TYPE_PLAYER:
    newflags = TYP_PLAYER;
    break;
  case O_TYPE_EXIT:
    newflags = TYP_EXIT;
    break;
#ifdef GARBAGE
  case O_TYPE_GARBAGE:
    Garbage = 1;
    return 1;
#endif				/* GARBAGE */
  default:
    newflags = TYP_ROOM;
  }
  if ((Flags & O_WIZARD) || (Flags & O_GOD))
    newflags |= WIZARD;
  if (Flags & O_LINK_OK)
    newflags |= LINK_OK;
  if (Flags & O_DARK)
    newflags |= DARK;
  if (Flags & O_TEMPLE)
    newflags |= TEMPLE;
  if (Flags & O_STICKY)
    newflags |= STICKY;
  if (Flags & O_HAVEN) {
    if ((newflags & TYPE_MASK) == TYP_PLAYER)
      newflags |= STICKY;
    else
      newflags |= HAVEN;
  }
  if (Flags & O_ABODE)
    newflags |= ABODE;
  if ((Flags & O_ROBOT) && ((newflags & TYPE_MASK) == TYP_PLAYER))
    newflags |= TEMPLE;
  if (Flags & O_BUILDER)
    newflags |= BUILDER;
  if ((((Flags & O_GENDER_MASK) >> O_GENDER_SHIFT) != O_GENDER_UNASSIGNED) &&
      ((newflags & TYPE_MASK) == TYP_PLAYER)) {
    switch ((Flags & O_GENDER_MASK) >> O_GENDER_SHIFT) {
    case O_GENDER_NEUTER:
      strcpy(Gender, "neuter\n");
      break;
    case O_GENDER_FEMALE:
      strcpy(Gender, "female\n");
      break;
    case O_GENDER_MALE:
      strcpy(Gender, "male\n");
      break;
    default:
      strcpy(Gender, "\n");
    }
  } else
    strcpy(Gender, "\n");

  if ((newflags & TYPE_MASK) == TYP_PLAYER) {
    char           *p;

    for (p = Name; *p && *p != '\n'; p++);
    *p = '\0';
    if (Password[0] != '\n') {
      strcat(Name, " ");
      strcat(Name, Password);
    } else {
      strcat(Name, " null\n");
    }
  }
  if (Lockbuff[0] != '\n') {
    char           *p;

    for (p = Lockbuff; *p && *p != '\n'; p++);
    *p = '\0';
  } else
    Lockbuff[0] = '\0';

  if (!strcmp(Lockbuff, "-1"))
    Lockbuff[0] = '\0';
  if ((Flags & O_ANTILOCK) && Lockbuff[0] != '\0') {
    char            temp[BUFFSIZ + 16];

    strcpy(temp, "!(");
    strcat(temp, Lockbuff);
    strcat(temp, ")");

    strcpy(Lockbuff, temp);
  }
  if (Lockbuff[0] != '\0') {
    if ((Lock = bool_parse(Lockbuff)) == NULL)
      return -1;
  }
  if ((newflags & TYPE_MASK) == TYP_EXIT) {
    Home = Location;
    Location = -1;		/* fucked */
  } else {
    if ((newflags & TYPE_MASK) != TYP_ROOM) {
      Home = Exits;
      Exits = -1;		/* no exits */
    } else {
      Home = Location;
      Location = 0;
    }
  }

  Flags = newflags;

  return 1;
}
int             write_object(objnum, out)
  int             objnum;
  FILE           *out;
{
  if (Increment > 0) {
    objnum += Increment;
    if (Location > 0)
      Location += Increment;
    Owner += Increment;
    if (Next > 0)
      Next += Increment;
    if (Exits > 0)
      Exits += Increment;
    if (Contents > 0)
      Contents += Increment;
    if (Home > 0)
      Home += Increment;
  }
#ifdef GARBAGE
  if (Garbage) {
    fprintf(out, "@%d\n", objnum);
    fflush(out);
    Garbage = 0;

    return 1;
  }
#endif				/* GARBAGE */

  fprintf(out, "#%d\n%d\n", objnum, Flags);
  fputs(Name, out);
  fprintf(out, "%d\n%d\n%d\n%d\n%d\n%d\n%d\n", Next, Pennies, Location, Home,
	  Owner, Contents, Exits);
#ifdef TIMESTAMPS
  fprintf(out, "%d\n", Timestamp);
#endif				/* TIMESTAMPS */
#ifdef KLUDGE
  fprintf(out, "%d\n", (int) (time(0) / 60));
#endif				/* KLUDGE */
  if (Lock != NULL)
    putlock(Lock, out);
  else
    fputs("\n", out);
  fputs(Success, out);
  fputs(Osuccess, out);
  fputs(Fail, out);
  fputs(Ofail, out);
  fputs(Description, out);
  fputs(Gender, out);

  fflush(out);
  if (Lock != NULL) {
    free((int *) Lock);
    Lock = NULL;
  }
  return 1;
}
void            main(argc, argv)
  int             argc;
  char          **argv;
{
  FILE           *in;
  FILE           *out;
  FILE           *temp;
  char            temp_path[80];
  char            work[BUFFSIZ + 16];

#ifdef PIPE
  char            out_cmmd[BUFSIZ];

#endif				/* PIPE */

  prog = argv[0];

  if (argc < 3 || argc > 5) {
    fprintf(stderr, "Usage: %s <input db> <output db> [<temp db>] [<#>]\n",
	    prog);
    exit(-1);
  }
  if (!strcmp(argv[1], "-")) {
    in = stdin;
  } else {
    if ((in = fopen(argv[1], "r")) == NULL) {
      fprintf(stderr, "%s: couldn't open %s.\n", prog, argv[1]);
      exit(-1);
    }
  }
#ifdef PIPE
  sprintf(out_cmmd, "compress > %s", argv[2]);
  if ((out = popen(out_cmmd, "w")) == NULL) {
    fprintf(stderr, "%s: couldn't execute %s.\n", prog, out_cmmd);
    exit(-1);
  }
#else				/* PIPE */
  if ((out = fopen(argv[2], "w")) == NULL) {
    fprintf(stderr, "%s: couldn't create %s.\n", prog, argv[2]);
    exit(-1);
  }
#endif				/* PIPE */
  if (argc > 3) {
    if (strlen(argv[3]) > 80) {
      fprintf(stderr, "%s: %s - path too long.\n", prog, argv[3]);
      exit(-1);
    }
    strcpy(temp_path, argv[3]);
  } else {
    sprintf(temp_path, "/tmp/cnvt%d", getpid());
  }
  if ((temp = fopen(temp_path, "w")) == NULL) {
    fprintf(stderr, "%s: couldn't create %s.\n", prog, temp_path);
    exit(-1);
  }
  if (argc == 5)
    Increment = atoi(argv[4]);
  if (convert_file(in, temp) == -1) {
    fprintf(stderr, "%s: conversion failed.\n", prog);
    exit(-1);
  }
  fclose(temp);
  if (Increment > 0) {
    fprintf(stderr, "%s: unfinished db left in %s, offset %d objects.\n",
	    prog, temp_path, Increment);
    exit(1);
  }
#ifdef TIMESTAMPS
  fprintf(out, "!\n! TinyMUD -> TeenyMUD converter dump\n!\n%%%d\n~2\n",
	  total_objects);
#else				/* TIMESTAMPS */
  fprintf(out, "!\n! TinyMUD -> TeenyMUD converter dump\n!\n%%%d\n~1\n",
	  total_objects);
#endif				/* TIMESTAMPS */
  fflush(out);
  if ((temp = fopen(temp_path, "r")) == NULL) {
    fprintf(stderr, "%s: couldn't reopen %s for read.\n", prog, temp_path);
    exit(-1);
  }
  while (fgets(work, BUFFSIZ + 16, temp) != NULL) {
    fputs(work, out);
  }
  fflush(out);
  fputs("*** End of converter dump ***\n", out);
  fflush(out);
#ifdef PIPE
  pclose(out);
#else				/* PIPE */
  fclose(out);
#endif				/* PIPE */
  fclose(temp);
  unlink(temp_path);

  exit(0);
}

putlock(lock, f)
  int            *lock;
  FILE           *f;
{
  int             count, i, space;
  char            work[BUFFSIZ], *p, *q;

  if (lock == NULL || lock[0] == 0) {
    fputs("\n", f);
    return;
  }
  space = BUFFSIZ;
  count = lock[0];		/* How many FOLLOW */
  p = work;

  p = ty_itoa(p, count);
  *p++ = ' ';
  space -= p - work;

  for (i = 1; count > 0 && space > 8; count--, i++) {
    q = p;
    p = ty_itoa(p, lock[i]);
    *p++ = ' ';
    space -= p - q;
  }
  p--;
  *p++ = '\n';
  *p = '\0';
  fputs(work, f);
}

/* Opcodes for our little Boolean expression evaluator. */

#define STOP -1
#define AND -2
#define OR -3
#define NOT -4
#define OPEN -5
#define CLOSE -6
#define BADREF -7

char           *get_tok();

int             stack[64];	/* Expressions can't be too big. */
static int      work[256];

/*
 * We use these structs, an array of them, to build parse trees from our
 * internal RPN locks so we can write them out in infix.
 * 
 */

struct tree {
  int             dat;
  short           left, right;	/* Array offsets */
};

/*
 * Parses a boolean expression, stuffs it into a hunk of memory, and returns
 * a pointer to said hunk. Returns NULL if it can't cope.
 * 
 */

int            *
                bool_parse(str)
  char           *str;
{
  int             wp, sp;
  int             tok, *thelock;

  sp = 0;
  wp = 1;

  do {
    str = get_tok(str, &tok);

    if (tok == BADREF) {
      fprintf(stderr, "%s: bad lock.\n", prog);
      return (NULL);
    }
    switch (tok) {
    case OPEN:
      if (sp < 63) {
	stack[sp++] = OPEN;
      } else {
	fprintf(stderr, "%s: lock too complex.\n", prog);
	return (NULL);
      }
      break;
    case CLOSE:
      while (sp > 0 && stack[sp - 1] != OPEN && wp < 255) {
	work[wp++] = stack[--sp];
      }
      if (sp == 0 || stack[sp - 1] != OPEN) {
	fprintf(stderr,
		"%s: lock to complex, or unbalanced parens.\n",
		prog);
	return (NULL);
      }
      sp--;
      break;
    case AND:
      while (sp > 0 && stack[sp - 1] == NOT && wp < 255) {
	work[wp++] = stack[--sp];
      }
      if (wp == 255) {
	fprintf(stderr, "%s: lock too complex.\n", prog);
	return (NULL);
      }
      if (sp < 63) {
	stack[sp++] = AND;
      } else {
	fprintf(stderr, "%s: lock too complex.\n", prog);
	return (NULL);
      }
      break;
    case OR:
      while (sp > 0 && (stack[sp - 1] == NOT
			|| stack[sp - 1] == AND) && wp < 255) {
	work[wp++] = stack[--sp];
      }
      if (wp == 255) {
	fprintf(stderr, "%s: lock too complex.\n", prog);
	return (NULL);
      }
      if (sp < 63) {
	stack[sp++] = OR;
      } else {
	fprintf(stderr, "%s: lock too complex.\n", prog);
	return (NULL);
      }
      break;
    case NOT:
      if (sp < 63) {
	stack[sp++] = NOT;
      } else {
	fprintf(stderr, "%s: lock too complex.\n");
	return (NULL);
      }
      break;
    case STOP:
      while (sp > 0 && wp < 255) {
	if (stack[sp - 1] != AND && stack[sp - 1] != OR
	    && stack[sp - 1] != NOT) {
	  fprintf(stderr, "%s: bad lock.\n", prog);
	  return (NULL);
	}
	work[wp++] = stack[--sp];
      }
      if (wp == 255) {
	fprintf(stderr, "%s: lock too complex.\n", prog);
	return (NULL);
      }
      work[wp++] = STOP;
      break;
    default:
      work[wp++] = tok;
      break;
    }
  } while (tok != STOP);

  /* Stow it away somewhere. */

  thelock = (int *) malloc(sizeof(int) * wp);
  thelock[0] = --wp;
  while (wp > 0) {
    thelock[wp] = work[wp];
    wp--;
  }
  return (thelock);
}

/*
 * Grabs the next token out a string, and returns a poointer to the next
 * thing in the string.
 * 
 */


char           *
                get_tok(p, tok)
  char           *p;
  int            *tok;

{
  char           *q, ch;
  int             obj;

  /* Skip white-boy space, Marcus-like */

  while (isspace(*p) && *p)
    p++;

  switch (*p) {
  case '&':
    *tok = AND;
    break;
  case '|':
    *tok = OR;
    break;
  case '!':
    *tok = NOT;
    break;
  case '(':
    *tok = OPEN;
    break;
  case ')':
    *tok = CLOSE;
    break;
  case '\0':
    *tok = STOP;
    break;
  default:
    /* Snarf out an object name */

    q = p;
    while (*p != '&' && *p != '|' && *p != '!' && *p != ')' && *p) {
      p++;
    }
    p--;
    while (isspace(*p))
      p--;
    ch = p[1];
    p[1] = '\0';
    obj = atoi(q);
    if (Increment > 0)
      obj += Increment;
    p[1] = ch;

    if (obj < 0) {
      *tok = BADREF;
    } else {
      *tok = obj;
    }
  }
  /* p points at the last char of the token. */

  p++;
  return (p);
}
char           *
                ty_itoa(p, i)
  char           *p;
  int             i;

{
  char           *ty_itoa_prim();

  if (i < 0) {
    i = -i;
    *p++ = '-';
  } else if (i == 0) {
    *p++ = '0';
    return (p);
  }
  return (ty_itoa_prim(p, i));
}

/* recursively does it to it. Hee! Russ would love me. */

char           *
                ty_itoa_prim(p, i)
  char           *p;
  int             i;
{
  if (i == 0) {
    return (p);
  } else {
    p = ty_itoa_prim(p, i / 10);
    *p++ = (char) (i % 10) + '0';
    return (p);
  }
}