00001
00002
00003
00004
00005 #include "copyright.h"
00006 #include "config.h"
00007
00008 #include "db.h"
00009 #include "match.h"
00010 #include "mudconf.h"
00011 #include "externs.h"
00012 #include "interface.h"
00013 #include "attrs.h"
00014 #include "flags.h"
00015 #include "powers.h"
00016 #include "alloc.h"
00017
00018 static int parsing_internal = 0;
00019
00024 static int check_attr(dbref player, dbref lockobj, ATTR * attr, char *key)
00025 {
00026 char *buff;
00027 dbref aowner;
00028 int aflags, checkit;
00029
00030 buff = atr_pget(player, attr->number, &aowner, &aflags);
00031 checkit = 0;
00032
00033 if(attr->number == A_LENTER) {
00034
00035 checkit = 1;
00036 } else if(See_attr(lockobj, player, attr, aowner, aflags)) {
00037 checkit = 1;
00038 } else if(attr->number == A_NAME) {
00039 checkit = 1;
00040 }
00041 if(checkit && (!wild_match(key, buff))) {
00042 checkit = 0;
00043 }
00044 free_lbuf(buff);
00045 return checkit;
00046 }
00047
00048 int eval_boolexp(dbref player, dbref thing, dbref from, BOOLEXP * b)
00049 {
00050 dbref aowner, obj, source;
00051 int aflags, c, checkit;
00052 char *key, *buff, *buff2, *bp, *str;
00053 ATTR *a;
00054
00055 if(b == TRUE_BOOLEXP)
00056 return 1;
00057
00058 switch (b->type) {
00059 case BOOLEXP_AND:
00060 return (eval_boolexp(player, thing, from, b->sub1) &&
00061 eval_boolexp(player, thing, from, b->sub2));
00062 case BOOLEXP_OR:
00063 return (eval_boolexp(player, thing, from, b->sub1) ||
00064 eval_boolexp(player, thing, from, b->sub2));
00065 case BOOLEXP_NOT:
00066 return !eval_boolexp(player, thing, from, b->sub1);
00067 case BOOLEXP_INDIR:
00068
00069
00070
00071
00072
00073
00074 mudstate.lock_nest_lev++;
00075 if(mudstate.lock_nest_lev >= mudconf.lock_nest_lim) {
00076
00077 STARTLOG(LOG_BUGS, "BUG", "LOCK") {
00078 log_name_and_loc(player);
00079 log_text((char *) ": Lock exceeded recursion limit.");
00080 ENDLOG;
00081 } notify(player, "Sorry, broken lock!");
00082 mudstate.lock_nest_lev--;
00083 return (0);
00084 }
00085 if((b->sub1->type != BOOLEXP_CONST) || (b->sub1->thing < 0)) {
00086 STARTLOG(LOG_BUGS, "BUG", "LOCK") {
00087 log_name_and_loc(player);
00088 buff = alloc_mbuf("eval_boolexp.LOG.indir");
00089 sprintf(buff, ": Lock had bad indirection (%c, type %d)",
00090 INDIR_TOKEN, b->sub1->type);
00091 log_text(buff);
00092 free_mbuf(buff);
00093 ENDLOG;
00094 }
00095 notify(player, "Sorry, broken lock!");
00096 mudstate.lock_nest_lev--;
00097 return (0);
00098 }
00099 key = atr_get(b->sub1->thing, A_LOCK, &aowner, &aflags);
00100 c = eval_boolexp_atr(player, b->sub1->thing, from, key);
00101 free_lbuf(key);
00102 mudstate.lock_nest_lev--;
00103 return (c);
00104 case BOOLEXP_CONST:
00105 return (b->thing == player || member(b->thing, Contents(player)));
00106 case BOOLEXP_ATR:
00107 a = atr_num(b->thing);
00108 if(!a)
00109 return 0;
00110
00111
00112
00113
00114
00115
00116
00117 if(check_attr(player, from, a, (char *) b->sub1))
00118 return 1;
00119 DOLIST(obj, Contents(player)) {
00120 if(check_attr(obj, from, a, (char *) b->sub1))
00121 return 1;
00122 }
00123 return 0;
00124 case BOOLEXP_EVAL:
00125 a = atr_num(b->thing);
00126 if(!a)
00127 return 0;
00128
00129
00130 source = from;
00131 buff = atr_pget(from, a->number, &aowner, &aflags);
00132 if(!buff || !*buff) {
00133 free_lbuf(buff);
00134 buff = atr_pget(thing, a->number, &aowner, &aflags);
00135 source = thing;
00136 }
00137 checkit = 0;
00138
00139 if((a->number == A_NAME) || (a->number == A_LENTER)) {
00140 checkit = 1;
00141 } else if(Read_attr(source, source, a, aowner, aflags)) {
00142 checkit = 1;
00143 }
00144 if(checkit) {
00145 buff2 = bp = alloc_lbuf("eval_boolexp");
00146 str = buff;
00147 exec(buff2, &bp, 0, source, player,
00148 EV_FIGNORE | EV_EVAL | EV_TOP, &str, (char **) NULL, 0);
00149 *bp = '\0';
00150 checkit = !string_compare(buff2, (char *) b->sub1);
00151 free_lbuf(buff2);
00152 }
00153 free_lbuf(buff);
00154 return checkit;
00155 case BOOLEXP_IS:
00156
00157
00158
00159
00160
00161 if(b->sub1->type == BOOLEXP_CONST)
00162 return (b->sub1->thing == player);
00163
00164
00165
00166
00167
00168 a = atr_num(b->sub1->thing);
00169 if(!a)
00170 return 0;
00171 return (check_attr(player, from, a, (char *) (b->sub1)->sub1));
00172 case BOOLEXP_CARRY:
00173
00174
00175
00176
00177
00178 if(b->sub1->type == BOOLEXP_CONST)
00179 return (member(b->sub1->thing, Contents(player)));
00180
00181
00182
00183
00184
00185 a = atr_num(b->sub1->thing);
00186 if(!a)
00187 return 0;
00188 DOLIST(obj, Contents(player)) {
00189 if(check_attr(obj, from, a, (char *) (b->sub1)->sub1))
00190 return 1;
00191 }
00192 return 0;
00193 case BOOLEXP_OWNER:
00194 return (Owner(b->sub1->thing) == Owner(player));
00195 default:
00196 abort();
00197
00198
00199 return 0;
00200 }
00201 }
00202
00203 int eval_boolexp_atr(dbref player, dbref thing, dbref from, char *key)
00204 {
00205 BOOLEXP *b;
00206 int ret_value;
00207
00208 b = parse_boolexp(player, key, 1);
00209 if(b == NULL) {
00210 ret_value = 1;
00211 } else {
00212 ret_value = eval_boolexp(player, thing, from, b);
00213 free_boolexp(b);
00214 }
00215 return (ret_value);
00216 }
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226 static const char *parsebuf;
00227 static char parsestore[LBUF_SIZE];
00228 static dbref parse_player;
00229
00230 static void skip_whitespace(void)
00231 {
00232 while (*parsebuf && isspace(*parsebuf))
00233 parsebuf++;
00234 }
00235
00236 static BOOLEXP *parse_boolexp_E(void);
00237
00238 static BOOLEXP *test_atr(char *s)
00239 {
00240 ATTR *attrib;
00241 BOOLEXP *b;
00242 char *buff, *s1;
00243 int anum, locktype;
00244
00245 buff = alloc_lbuf("test_atr");
00246 StringCopy(buff, s);
00247 for(s = buff; *s && (*s != ':') && (*s != '/'); s++);
00248 if(!*s) {
00249 free_lbuf(buff);
00250 return ((BOOLEXP *) NULL);
00251 }
00252 if(*s == '/')
00253 locktype = BOOLEXP_EVAL;
00254 else
00255 locktype = BOOLEXP_ATR;
00256
00257 *s++ = '\0';
00258
00259
00260
00261
00262
00263
00264
00265 if(!(attrib = atr_str(buff))) {
00266
00267
00268
00269
00270 if(!God(parse_player)) {
00271 free_lbuf(buff);
00272 return ((BOOLEXP *) NULL);
00273 }
00274 s1 = buff;
00275 for(s1 = buff; isdigit(*s1); s1++);
00276 if(*s1) {
00277 free_lbuf(buff);
00278 return ((BOOLEXP *) NULL);
00279 }
00280 anum = atoi(buff);
00281 } else {
00282 anum = attrib->number;
00283 }
00284
00285
00286
00287
00288 b = alloc_bool("test_str");
00289 b->type = locktype;
00290 b->thing = (dbref) anum;
00291 b->sub1 = (BOOLEXP *) strsave(s);
00292 free_lbuf(buff);
00293 return (b);
00294 }
00295
00296
00297
00298
00299 static BOOLEXP *parse_boolexp_L(void)
00300 {
00301 BOOLEXP *b;
00302 char *p, *buf;
00303 MSTATE mstate;
00304
00305 buf = NULL;
00306 skip_whitespace();
00307
00308 switch (*parsebuf) {
00309 case '(':
00310 parsebuf++;
00311 b = parse_boolexp_E();
00312 skip_whitespace();
00313 if(b == TRUE_BOOLEXP || *parsebuf++ != ')') {
00314 free_boolexp(b);
00315 return TRUE_BOOLEXP;
00316 }
00317 break;
00318 default:
00319
00320
00321
00322
00323
00324
00325 buf = alloc_lbuf("parse_boolexp_L");
00326 p = buf;
00327 while (*parsebuf && (*parsebuf != AND_TOKEN) &&
00328 (*parsebuf != OR_TOKEN) && (*parsebuf != ')')) {
00329 *p++ = *parsebuf++;
00330 }
00331
00332
00333
00334
00335
00336 *p-- = '\0';
00337 while (isspace(*p))
00338 *p-- = '\0';
00339
00340
00341
00342
00343
00344 if((b = test_atr(buf)) != NULL) {
00345 free_lbuf(buf);
00346 return (b);
00347 }
00348 b = alloc_bool("parse_boolexp_L");
00349 b->type = BOOLEXP_CONST;
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361 if(parsing_internal) {
00362 if(buf[0] != '#') {
00363 free_lbuf(buf);
00364 free_bool(b);
00365 return TRUE_BOOLEXP;
00366 }
00367 b->thing = atoi(&buf[1]);
00368 if(!Good_obj(b->thing)) {
00369 free_lbuf(buf);
00370 free_bool(b);
00371 return TRUE_BOOLEXP;
00372 }
00373 } else {
00374 save_match_state(&mstate);
00375 init_match(parse_player, buf, TYPE_THING);
00376 match_everything(MAT_EXIT_PARENTS);
00377 b->thing = match_result();
00378 restore_match_state(&mstate);
00379 }
00380
00381 if(b->thing == NOTHING) {
00382 notify_printf(parse_player, "I don't see %s here.", buf);
00383 free_lbuf(buf);
00384 free_bool(b);
00385 return TRUE_BOOLEXP;
00386 }
00387 if(b->thing == AMBIGUOUS) {
00388 notify_printf(parse_player, "I don't know which %s you mean!",
00389 buf);
00390 free_lbuf(buf);
00391 free_bool(b);
00392 return TRUE_BOOLEXP;
00393 }
00394 free_lbuf(buf);
00395 }
00396 return b;
00397 }
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407 static BOOLEXP *parse_boolexp_F(void)
00408 {
00409 BOOLEXP *b2;
00410
00411 skip_whitespace();
00412 switch (*parsebuf) {
00413 case NOT_TOKEN:
00414 parsebuf++;
00415 b2 = alloc_bool("parse_boolexp_F.not");
00416 b2->type = BOOLEXP_NOT;
00417 if((b2->sub1 = parse_boolexp_F()) == TRUE_BOOLEXP) {
00418 free_boolexp(b2);
00419 return (TRUE_BOOLEXP);
00420 } else
00421 return (b2);
00422
00423
00424
00425 break;
00426 case INDIR_TOKEN:
00427 parsebuf++;
00428 b2 = alloc_bool("parse_boolexp_F.indir");
00429 b2->type = BOOLEXP_INDIR;
00430 b2->sub1 = parse_boolexp_L();
00431 if((b2->sub1) == TRUE_BOOLEXP) {
00432 free_boolexp(b2);
00433 return (TRUE_BOOLEXP);
00434 } else if((b2->sub1->type) != BOOLEXP_CONST) {
00435 free_boolexp(b2);
00436 return (TRUE_BOOLEXP);
00437 } else
00438 return (b2);
00439
00440
00441
00442 break;
00443 case IS_TOKEN:
00444 parsebuf++;
00445 b2 = alloc_bool("parse_boolexp_F.is");
00446 b2->type = BOOLEXP_IS;
00447 b2->sub1 = parse_boolexp_L();
00448 if((b2->sub1) == TRUE_BOOLEXP) {
00449 free_boolexp(b2);
00450 return (TRUE_BOOLEXP);
00451 } else if(((b2->sub1->type) != BOOLEXP_CONST) &&
00452 ((b2->sub1->type) != BOOLEXP_ATR)) {
00453 free_boolexp(b2);
00454 return (TRUE_BOOLEXP);
00455 } else
00456 return (b2);
00457
00458
00459
00460 break;
00461 case CARRY_TOKEN:
00462 parsebuf++;
00463 b2 = alloc_bool("parse_boolexp_F.carry");
00464 b2->type = BOOLEXP_CARRY;
00465 b2->sub1 = parse_boolexp_L();
00466 if((b2->sub1) == TRUE_BOOLEXP) {
00467 free_boolexp(b2);
00468 return (TRUE_BOOLEXP);
00469 } else if(((b2->sub1->type) != BOOLEXP_CONST) &&
00470 ((b2->sub1->type) != BOOLEXP_ATR)) {
00471 free_boolexp(b2);
00472 return (TRUE_BOOLEXP);
00473 } else
00474 return (b2);
00475
00476
00477
00478 break;
00479 case OWNER_TOKEN:
00480 parsebuf++;
00481 b2 = alloc_bool("parse_boolexp_F.owner");
00482 b2->type = BOOLEXP_OWNER;
00483 b2->sub1 = parse_boolexp_L();
00484 if((b2->sub1) == TRUE_BOOLEXP) {
00485 free_boolexp(b2);
00486 return (TRUE_BOOLEXP);
00487 } else if((b2->sub1->type) != BOOLEXP_CONST) {
00488 free_boolexp(b2);
00489 return (TRUE_BOOLEXP);
00490 } else
00491 return (b2);
00492
00493
00494
00495 break;
00496 default:
00497 return (parse_boolexp_L());
00498 }
00499 }
00500
00501
00502
00503
00504
00505 static BOOLEXP *parse_boolexp_T(void)
00506 {
00507 BOOLEXP *b, *b2;
00508
00509 if((b = parse_boolexp_F()) != TRUE_BOOLEXP) {
00510 skip_whitespace();
00511 if(*parsebuf == AND_TOKEN) {
00512 parsebuf++;
00513
00514 b2 = alloc_bool("parse_boolexp_T");
00515 b2->type = BOOLEXP_AND;
00516 b2->sub1 = b;
00517 if((b2->sub2 = parse_boolexp_T()) == TRUE_BOOLEXP) {
00518 free_boolexp(b2);
00519 return TRUE_BOOLEXP;
00520 }
00521 b = b2;
00522 }
00523 }
00524 return b;
00525 }
00526
00527
00528
00529
00530 static BOOLEXP *parse_boolexp_E(void)
00531 {
00532 BOOLEXP *b, *b2;
00533
00534 if((b = parse_boolexp_T()) != TRUE_BOOLEXP) {
00535 skip_whitespace();
00536 if(*parsebuf == OR_TOKEN) {
00537 parsebuf++;
00538
00539 b2 = alloc_bool("parse_boolexp_E");
00540 b2->type = BOOLEXP_OR;
00541 b2->sub1 = b;
00542 if((b2->sub2 = parse_boolexp_E()) == TRUE_BOOLEXP) {
00543 free_boolexp(b2);
00544 return TRUE_BOOLEXP;
00545 }
00546 b = b2;
00547 }
00548 }
00549 return b;
00550 }
00551
00552 BOOLEXP *parse_boolexp(dbref player, const char *buf, int internal)
00553 {
00554 StringCopy(parsestore, buf);
00555 parsebuf = parsestore;
00556 parse_player = player;
00557 if((buf == NULL) || (*buf == '\0'))
00558 return (TRUE_BOOLEXP);
00559 parsing_internal = internal;
00560 return parse_boolexp_E();
00561 }