/* 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(); }