/* boolexp.c */ /* $Id: boolexp.c,v 1.6 1993/08/16 01:56:52 nils Exp $ */ #include <ctype.h> #include "db.h" #include "match.h" #include "externs.h" #include "config.h" #include "interface.h" #define RIGHT_DELIMITER(x) ((x == AND_TOKEN) || (x == OR_TOKEN) || \ (x == ':') || (x == '.') || (x == ')') || \ (x == '=') || (!x)) #define LEFT_DELIMITER(x) ((x == NOT_TOKEN) || (x == '(') || (x == AT_TOKEN) \ || (x == IS_TOKEN) || (x == CARRY_TOKEN)) #define IS_TYPE 0 #define CARRY_TYPE 1 #define _TYPE 2 int eval_boolexp1(); int eval_boolexp_OR(); int eval_boolexp_AND(); int eval_boolexp_REF(); dbref parse_player; dbref parse_object; dbref parse_zone; static int depth; /* recursion protection */ #define FUN_CALL 1 int get_word(d,s) char *d; char **s; { int type = 0; while (!RIGHT_DELIMITER(**s)) { if (**s == '[') { type = FUN_CALL; while (**s && (**s != ']')) *d++ = *(*s)++; } else *d++ = *(*s)++; } *d = '\0'; return type; } dbref match_dbref(player, name) dbref player; char *name; { init_match(player, name, NOTYPE); match_everything(); return noisy_match_result(); } char *process_lock(player, arg) dbref player; char *arg; { static char buffer[BUFFER_LEN]; char *s = arg, *t = buffer; int type; dbref thing; while (*s) { while (LEFT_DELIMITER(*s)) *t++ = *s++; /* time to get a literal */ type = get_word(t, &s); switch(*s) { case ':': /* a built in attribute */ if ((!builtin_atr_str(t)) && (type != FUN_CALL)) notify(player,tprintf("Warning: no such built in attribute '%s'", t)); t += strlen(t); *t++ = *s++; type = get_word(t, &s); t += strlen(t); break; case '.': /* a user defined attribute */ if ((thing = match_dbref(player, t)) < (dbref) 0) return NULL; sprintf(t, "#%d", thing); t += strlen(t); *t++ = *s++; type = get_word(t, &s); if ((!atr_str(player,thing,t)) && (type != FUN_CALL)) notify(player,tprintf("Warning: no such attribute '%s' on #%d", t,thing)); t += strlen(t); if (*s != ':') { notify(player,"I don't understand that key."); return NULL; } *t++ = *s++; type = get_word(t, &s); t += strlen(t); break; default: if (type != FUN_CALL) { if ((thing = match_dbref(player, t)) == NOTHING) return NULL; sprintf(t, "#%d", thing); } t += strlen(t); } while (*s && RIGHT_DELIMITER(*s)) *t++ = *s++; } *t = '\0'; return buffer; } #undef FUN_CALL char *unprocess_lock(player, arg) dbref player; char *arg; { static char buffer[BUFFER_LEN]; char *s = arg, *t = buffer, save, *p; dbref thing; while (*s) { if (*s == '#') { s++; for (p = s;isdigit(*s);s++); save = *s; *s++ = '\0'; thing = (dbref) atoi(p); if (thing>=db_top || thing<0) thing=NOTHING; sprintf(t, "%s", unparse_object(player, thing)); t += strlen(t); if (save != '\0') *t++ = save; else s--; } else if (*s == '[') { while (*s && (*s != ']')) *t++ = *s++; if (!*s) *t++ = *s++; } else *t++ = *s++; } *t = '\0'; return buffer; } void eval_fun(buffer, str, doer, privs) char *buffer; char *str; dbref doer; dbref privs; { char *s; for (s = str; *s;) { if (*s == '[') { s++; exec(&s, buffer, privs, doer, 0); buffer += strlen(buffer); if (*s) s++; } else *buffer++ = *s++; } *buffer = '\0'; } int eval_boolexp(player, object, key, zone) dbref player; dbref object; char *key; dbref zone; { static char keybuf[BUFFER_LEN]; depth = 0; parse_player = player; parse_object = object; parse_zone = zone; strcpy(keybuf, key); return eval_boolexp1(object, keybuf, zone); } int eval_boolexp1(object, key, zone) dbref object; char *key; dbref zone; { char buffer[BUFFER_LEN], *buf = buffer; if (!*key) return 1; if (++depth > 10) { notify(db[parse_object].owner, tprintf("Warning: recursion detected in %s lock.", unparse_object(db[parse_object].owner, object))); return 0; } eval_fun(buffer, key, parse_player, object); return eval_boolexp_OR(&buf); } int test_atr(buf,player,ind) char **buf; dbref player; int ind; { ATTR *attr; int result; char *s, save; for(s = *buf;!RIGHT_DELIMITER(*s) || (*s == '.');s++); if (!*s || (*s != ':')) return -1; *s++ = '\0'; if (strchr(*buf,'.')) attr = atr_str(player, NOTHING, *buf); else attr = builtin_atr_str(*buf); if (!(attr) || (attr->flags & AF_DARK) || ((ind) && !can_see_atr(parse_object,player,attr))) return -1; for(*buf = s;*s && (*s != AND_TOKEN) && (*s != OR_TOKEN) && (*s != ')');s++); save = *s; *s = '\0'; result = wild_match(*buf, atr_get(player, attr)); *s = save; *buf = s; return result; } int grab_num(buf) char **buf; { char *s, save; int num; for (s = *buf; *s && isdigit(*s); s++); save = *s; *s = '\0'; num = atoi(*buf); *s = save; *buf = s; return num; } dbref get_dbref(buf) char **buf; { char *s, save; dbref temp; for(s = *buf;!RIGHT_DELIMITER(*s) && (*s != '=');s++); save = *s; *s = '\0'; init_match(parse_object, *buf, NOTYPE); match_everything(); *s = save; *buf = s; temp = match_result(); return temp; } int eval_boolexp_OR(buf) char **buf; { int left; left = eval_boolexp_AND(buf); if (**buf == OR_TOKEN) { (*buf)++; return (eval_boolexp_OR(buf) || left); } else return left; } int eval_boolexp_AND(buf) char **buf; { int left; left = eval_boolexp_REF(buf); if (**buf == AND_TOKEN) { (*buf)++; return (eval_boolexp_AND(buf) && left); } else return left; } int eval_boolexp_REF(buf) char **buf; { dbref thing; int type, t; switch (**buf) { case '(': (*buf)++; t = eval_boolexp_OR(buf); if (**buf == ')') (*buf)++; return t; case NOT_TOKEN: (*buf)++; return !eval_boolexp_REF(buf); case AT_TOKEN: (*buf)++; if (**buf == '(') { /* an indirect attribute */ (*buf)++; thing = get_dbref(buf); if (**buf != '=') return eval_boolexp1(thing, atr_get(thing, A_LOCK), parse_zone); (*buf)++; t = test_atr(buf,thing,1); if (**buf == ')') (*buf)++; return (t == -1) ? 0 : t; } thing = get_dbref(buf); if (can_see_atr(parse_object,thing,A_LOCK)) { return eval_boolexp1(thing, atr_get(thing, A_LOCK), parse_zone); } else return 0; default: switch (**buf) { case IS_TOKEN: type = IS_TYPE; (*buf)++; break; case CARRY_TOKEN: type = CARRY_TYPE; (*buf)++; break; default: type = _TYPE; } if (isdigit(**buf)) return grab_num(buf); if ((t = test_atr(buf,parse_player,0)) != -1) return t; if ((thing = get_dbref(buf)) < (dbref) 0) return 0; switch (type) { case IS_TYPE: return (parse_player == thing) ? 1 : 0; case CARRY_TYPE: return member(thing, db[parse_player].contents); case _TYPE: return ((parse_player == thing) || (member(thing, db[parse_player].contents)) || (parse_zone == thing)); default: /* so gcc stops complaining */ return 0; } } }