/* boolexp.c */ #include "os.h" #include "copyright.h" #include "db.h" #include "match.h" #include "externs.h" #include "config.h" #include "interface.h" int eval_boolexp (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 (void) { while (*parsebuf && isspace ((int)*parsebuf)) parsebuf++; } static struct boolexp *parse_boolexp_E (void); /* defined below */ static struct boolexp *test_atr (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 (void) { 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 ((int)*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 (void) { 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 (void) { 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 (void) { 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 (void) { 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 (void) { 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 (void) { 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 (dbref player, const char *buf) { parsebuf = buf; parse_player = player; return parse_boolexp_E (); }