/* boolexp.c */
#include "copyright.h"
#include <ctype.h>
#include <string.h>
#include "db.h"
#include "match.h"
#include "externs.h"
#include "config.h"
#include "interface.h"
int eval_boolexp(player, b, privs, nrecurs, locktype)
dbref player;
struct boolexp *b;
dbref privs;
int nrecurs;
int locktype;
{
ATTR *a;
char tbuf1[BUFFER_LEN], tbuf2[BUFFER_LEN];
if(player < 0 || player >= db_top)
return 0;
if (nrecurs > MAX_DEPTH) {
notify(player,"Sorry, broken lock!");
return 0;
}
if (b == TRUE_BOOLEXP) {
return 1;
} else {
switch (b->type) {
case BOOLEXP_IND:
if(b->sub1->type != BOOLEXP_CONST)
return 0;
nrecurs++;
switch (locktype) {
case BASICLOCK:
return (eval_boolexp(player, db[b->sub1->thing].key, privs, nrecurs,
locktype));
break;
case USELOCK:
return (eval_boolexp(player, db[b->sub1->thing].usekey, privs,
nrecurs, locktype));
break;
case ENTERLOCK:
return (eval_boolexp(player, db[b->sub1->thing].enterkey, privs,
nrecurs, locktype));
break;
default:
/* should never be reached */
notify(player, "Broken lock!");
break;
} break;
case BOOLEXP_AND:
return (eval_boolexp(player, b->sub1, privs, nrecurs, locktype)
&& eval_boolexp(player, b->sub2, privs, nrecurs, locktype));
case BOOLEXP_OR:
return (eval_boolexp(player, b->sub1, privs, nrecurs, locktype)
|| eval_boolexp(player, b->sub2, privs, nrecurs, locktype));
case BOOLEXP_NOT:
return !eval_boolexp(player, b->sub1, privs, nrecurs, locktype);
case BOOLEXP_CONST:
return (b->thing == player
|| member(b->thing, db[player].contents));
case BOOLEXP_IS:
return (b->sub1->thing == player);
case BOOLEXP_CARRY:
return (member(b->sub1->thing,db[player].contents));
case BOOLEXP_ATR:
a = atr_complete_match(player, b->atr_lock->name, privs);
if(!a)
return 0;
strcpy(tbuf1, uncompress(b->atr_lock->text));
strcpy(tbuf2, uncompress(a->value));
return (int) wild_match(tbuf1, tbuf2);
default:
fprintf(stderr, "ERROR: Bad Boolexp type! (continuing)\n");
report();
return 0;
} /* switch */
/* should never be reached */
fprintf(stderr,
"** ERROR ** Broken lock type %d in object called by player %d",
locktype, player);
return 0;
} /* else */
}
/* If the parser returns TRUE_BOOLEXP, you lose */
/* TRUE_BOOLEXP cannot be typed in by the user; use @unlock instead */
static const char *parsebuf;
static dbref parse_player;
static void skip_whitespace()
{
while (*parsebuf && isspace(*parsebuf))
parsebuf++;
}
static struct boolexp *parse_boolexp_E(); /* defined below */
static struct boolexp *test_atr(s)
char *s;
{
struct boolexp *b;
char tbuf1[BUFFER_LEN];
strcpy(tbuf1, s);
for (s = tbuf1; *s && (*s != ':'); s++) ;
if (!*s)
return (0);
*s++ = 0;
b = alloc_bool();
b->type = BOOLEXP_ATR;
/* !!! Possible portability problem!!!!! */
b->atr_lock = alloc_atr(tbuf1, s);
return (b);
}
/* L -> (E); L -> object identifier */
static struct boolexp *parse_boolexp_L()
{
struct boolexp *b;
char *p;
char tbuf1[BUFFER_LEN];
skip_whitespace();
switch (*parsebuf) {
case '(':
parsebuf++;
b = parse_boolexp_E();
skip_whitespace();
if (b == TRUE_BOOLEXP || *parsebuf++ != ')') {
free_boolexp(b);
return TRUE_BOOLEXP;
} else {
return b;
}
/* break; */
default:
/* must have hit an object ref */
/* load the name into our buffer */
p = tbuf1;
while (*parsebuf
&& *parsebuf != AND_TOKEN
&& *parsebuf != OR_TOKEN
&& *parsebuf != ')') {
*p++ = *parsebuf++;
}
/* strip trailing whitespace */
*p-- = '\0';
while (isspace(*p))
*p-- = '\0';
/* check for an attribute */
b = test_atr(tbuf1);
if (b)
return (b);
b = alloc_bool();
b->type = BOOLEXP_CONST;
/* do the match */
init_match(parse_player, tbuf1, TYPE_THING);
match_neighbor();
match_possession();
match_me();
match_absolute();
match_player();
b->thing = match_result();
if (b->thing == NOTHING) {
notify(parse_player,
tprintf("I don't see %s here.", tbuf1));
free_bool(b);
return TRUE_BOOLEXP;
} else if (b->thing == AMBIGUOUS) {
notify(parse_player,
tprintf("I don't know which %s you mean!", tbuf1));
free_bool(b);
return TRUE_BOOLEXP;
} else {
return b;
}
/* break */
}
}
/* C -> +Identifier ; C -> L */
static struct boolexp *parse_boolexp_C()
{
struct boolexp *b2;
skip_whitespace();
if(*parsebuf == IN_TOKEN) {
parsebuf++;
b2 = alloc_bool();
b2->type = BOOLEXP_CARRY;
if(((b2->sub1 = parse_boolexp_L()) == TRUE_BOOLEXP) ||
(b2->sub1->type != BOOLEXP_CONST)) {
free_boolexp(b2);
return(TRUE_BOOLEXP);
} else
return(b2);
}
return (parse_boolexp_L());
}
/* I -> =Identifier ; I -> C */
static struct boolexp *parse_boolexp_I()
{
struct boolexp *b2;
skip_whitespace();
if(*parsebuf == IS_TOKEN) {
parsebuf++;
b2 = alloc_bool();
b2->type = BOOLEXP_IS;
if(((b2->sub1 = parse_boolexp_L()) == TRUE_BOOLEXP) ||
(b2->sub1->type != BOOLEXP_CONST)){
free_boolexp(b2);
return(TRUE_BOOLEXP);
} else
return(b2);
}
return(parse_boolexp_C());
}
/* A -> @L; A -> I */
static struct boolexp *parse_boolexp_A()
{
struct boolexp *b2;
skip_whitespace();
if(*parsebuf == AT_TOKEN) {
parsebuf++;
b2 = alloc_bool();
b2->type = BOOLEXP_IND;
if(((b2->sub1 = parse_boolexp_L()) == TRUE_BOOLEXP) ||
(b2->sub1->type != BOOLEXP_CONST)) {
free_boolexp(b2);
return(TRUE_BOOLEXP);
} else
return (b2);
}
return(parse_boolexp_I());
}
/* F -> !F;F -> A */
static struct boolexp *parse_boolexp_F()
{
struct boolexp *b2;
skip_whitespace();
if (*parsebuf == NOT_TOKEN) {
parsebuf++;
b2 = alloc_bool();
b2->type = BOOLEXP_NOT;
if ((b2->sub1 = parse_boolexp_F()) == TRUE_BOOLEXP) {
free_boolexp(b2);
return (TRUE_BOOLEXP);
} else
return (b2);
}
return (parse_boolexp_A());
}
/* T -> F; T -> F & T */
static struct boolexp *parse_boolexp_T()
{
struct boolexp *b;
struct boolexp *b2;
if ((b = parse_boolexp_F()) == TRUE_BOOLEXP) {
return b;
} else {
skip_whitespace();
if (*parsebuf == AND_TOKEN) {
parsebuf++;
b2 = alloc_bool();
b2->type = BOOLEXP_AND;
b2->sub1 = b;
if ((b2->sub2 = parse_boolexp_T()) == TRUE_BOOLEXP) {
free_boolexp(b2);
return TRUE_BOOLEXP;
} else {
return b2;
}
} else {
return b;
}
}
}
/* E -> T; E -> T | E */
static struct boolexp *parse_boolexp_E()
{
struct boolexp *b;
struct boolexp *b2;
if ((b = parse_boolexp_T()) == TRUE_BOOLEXP) {
return b;
} else {
skip_whitespace();
if (*parsebuf == OR_TOKEN) {
parsebuf++;
b2 = alloc_bool();
b2->type = BOOLEXP_OR;
b2->sub1 = b;
if ((b2->sub2 = parse_boolexp_E()) == TRUE_BOOLEXP) {
free_boolexp(b2);
return TRUE_BOOLEXP;
} else {
return b2;
}
} else {
return b;
}
}
}
struct boolexp *parse_boolexp(player, buf)
dbref player;
const char *buf;
{
parsebuf = buf;
parse_player = player;
return parse_boolexp_E();
}