#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); } }