00001
00002
00003
00004
00005 #include "copyright.h"
00006 #include "autoconf.h"
00007 #include "config.h"
00008 #include "externs.h"
00009
00010 #include "attrs.h"
00011
00012 static bool parsing_internal = false;
00013
00014
00015
00016
00017
00018
00019 static bool check_attr(dbref player, dbref lockobj, ATTR *attr, char *key)
00020 {
00021 dbref aowner;
00022 int aflags;
00023 bool bCheck = false;
00024
00025 char *buff = atr_pget(player, attr->number, &aowner, &aflags);
00026
00027 if (attr->number == A_LENTER)
00028 {
00029
00030
00031 bCheck = true;
00032 }
00033 else if (See_attr(lockobj, player, attr))
00034 {
00035 bCheck = true;
00036 }
00037 else if (attr->number == A_NAME)
00038 {
00039 bCheck = true;
00040 }
00041
00042 if ( bCheck
00043 && !wild_match(key, buff))
00044 {
00045 bCheck = false;
00046 }
00047 free_lbuf(buff);
00048 return bCheck;
00049 }
00050
00051 bool eval_boolexp(dbref player, dbref thing, dbref from, BOOLEXP *b)
00052 {
00053 if (b == TRUE_BOOLEXP)
00054 {
00055 return true;
00056 }
00057
00058 dbref aowner, obj, source;
00059 int aflags;
00060 char *key, *buff, *buff2, *bp, *str;
00061 ATTR *a;
00062 bool bCheck, c;
00063
00064 switch (b->type)
00065 {
00066 case BOOLEXP_AND:
00067 return eval_boolexp(player, thing, from, b->sub1)
00068 && eval_boolexp(player, thing, from, b->sub2);
00069
00070 case BOOLEXP_OR:
00071 return eval_boolexp(player, thing, from, b->sub1)
00072 || eval_boolexp(player, thing, from, b->sub2);
00073
00074 case BOOLEXP_NOT:
00075 return !eval_boolexp(player, thing, from, b->sub1);
00076
00077 case BOOLEXP_INDIR:
00078
00079
00080
00081
00082
00083 mudstate.lock_nest_lev++;
00084 if (mudstate.lock_nest_lev >= mudconf.lock_nest_lim)
00085 {
00086 if (mudstate.bStandAlone)
00087 {
00088 Log.WriteString("Lock exceeded recursion limit." ENDLINE);
00089 }
00090 else
00091 {
00092 STARTLOG(LOG_BUGS, "BUG", "LOCK");
00093 log_name_and_loc(player);
00094 log_text(": Lock exceeded recursion limit.");
00095 ENDLOG;
00096 notify(player, "Sorry, broken lock!");
00097 }
00098 mudstate.lock_nest_lev--;
00099 return false;
00100 }
00101 if ( b->sub1->type != BOOLEXP_CONST
00102 || b->sub1->thing < 0)
00103 {
00104 if (mudstate.bStandAlone)
00105 {
00106 Log.WriteString("Broken lock." ENDLINE);
00107 }
00108 else
00109 {
00110 STARTLOG(LOG_BUGS, "BUG", "LOCK");
00111 log_name_and_loc(player);
00112 buff = alloc_mbuf("eval_boolexp.LOG.indir");
00113 sprintf(buff, ": Lock had bad indirection (%c, type %d)",
00114 INDIR_TOKEN, b->sub1->type);
00115 log_text(buff);
00116 free_mbuf(buff);
00117 ENDLOG;
00118 notify(player, "Sorry, broken lock!");
00119 }
00120 mudstate.lock_nest_lev--;
00121 return false;
00122 }
00123 key = atr_get(b->sub1->thing, A_LOCK, &aowner, &aflags);
00124 c = eval_boolexp_atr(player, b->sub1->thing, from, key);
00125 free_lbuf(key);
00126 mudstate.lock_nest_lev--;
00127 return c;
00128
00129 case BOOLEXP_CONST:
00130 return b->thing == player
00131 || member(b->thing, Contents(player));
00132
00133 case BOOLEXP_ATR:
00134 a = atr_num(b->thing);
00135 if (!a)
00136 {
00137
00138
00139 return false;
00140 }
00141
00142
00143
00144 if (check_attr(player, from, a, (char *)b->sub1))
00145 {
00146 return true;
00147 }
00148 DOLIST(obj, Contents(player))
00149 {
00150 if (check_attr(obj, from, a, (char *)b->sub1))
00151 {
00152 return true;
00153 }
00154 }
00155 return false;
00156
00157 case BOOLEXP_EVAL:
00158
00159 a = atr_num(b->thing);
00160 if ( !a
00161 || MuxAlarm.bAlarmed)
00162 {
00163
00164
00165 return false;
00166 }
00167 source = from;
00168 buff = atr_pget(from, a->number, &aowner, &aflags);
00169 if (!buff || !*buff)
00170 {
00171 free_lbuf(buff);
00172 buff = atr_pget(thing, a->number, &aowner, &aflags);
00173 source = thing;
00174 }
00175 bCheck = false;
00176
00177 if ( a->number == A_NAME
00178 || a->number == A_LENTER)
00179 {
00180 bCheck = true;
00181 }
00182 else if (bCanReadAttr(source, source, a, false))
00183 {
00184 bCheck = true;
00185 }
00186 if (bCheck)
00187 {
00188 char **preserve = NULL;
00189 int *preserve_len = NULL;
00190 preserve = PushPointers(MAX_GLOBAL_REGS);
00191 preserve_len = PushIntegers(MAX_GLOBAL_REGS);
00192 save_global_regs("eval_boolexp_save", preserve, preserve_len);
00193
00194 buff2 = bp = alloc_lbuf("eval_boolexp");
00195 str = buff;
00196 mux_exec(buff2, &bp, source, player, player,
00197 EV_FIGNORE | EV_EVAL | EV_FCHECK | EV_TOP, &str,
00198 (char **)NULL, 0);
00199 *bp = '\0';
00200
00201 restore_global_regs("eval_boolexp_save", preserve, preserve_len);
00202 PopIntegers(preserve_len, MAX_GLOBAL_REGS);
00203 PopPointers(preserve, MAX_GLOBAL_REGS);
00204
00205 bCheck = !string_compare(buff2, (char *)b->sub1);
00206 free_lbuf(buff2);
00207 }
00208 free_lbuf(buff);
00209 return bCheck;
00210
00211 case BOOLEXP_IS:
00212
00213
00214
00215 if (b->sub1->type == BOOLEXP_CONST)
00216 {
00217 return (b->sub1->thing == player);
00218 }
00219
00220
00221
00222 a = atr_num(b->sub1->thing);
00223 if (!a)
00224 {
00225 return false;
00226 }
00227 return check_attr(player, from, a, (char *)(b->sub1)->sub1);
00228
00229 case BOOLEXP_CARRY:
00230
00231
00232
00233 if (b->sub1->type == BOOLEXP_CONST)
00234 {
00235 return member(b->sub1->thing, Contents(player));
00236 }
00237
00238
00239
00240 a = atr_num(b->sub1->thing);
00241 if (!a)
00242 {
00243 return false;
00244 }
00245 DOLIST(obj, Contents(player))
00246 {
00247 if (check_attr(obj, from, a, (char *)(b->sub1)->sub1))
00248 {
00249 return true;
00250 }
00251 }
00252 return false;
00253
00254 case BOOLEXP_OWNER:
00255
00256 return (Owner(b->sub1->thing) == Owner(player));
00257
00258 default:
00259
00260
00261
00262 mux_assert(0);
00263 return false;
00264 }
00265 }
00266
00267 bool eval_boolexp_atr(dbref player, dbref thing, dbref from, char *key)
00268 {
00269 bool ret_value;
00270
00271 BOOLEXP *b = parse_boolexp(player, key, true);
00272 if (b == NULL)
00273 {
00274 ret_value = true;
00275 }
00276 else
00277 {
00278 ret_value = eval_boolexp(player, thing, from, b);
00279 free_boolexp(b);
00280 }
00281 return ret_value;
00282 }
00283
00284
00285
00286
00287 static const char *parsebuf;
00288 static char parsestore[LBUF_SIZE];
00289 static dbref parse_player;
00290
00291 static void skip_whitespace(void)
00292 {
00293 while (mux_isspace(*parsebuf))
00294 {
00295 parsebuf++;
00296 }
00297 }
00298
00299
00300
00301 static BOOLEXP *parse_boolexp_E(void);
00302
00303 static BOOLEXP *test_atr(char *s)
00304 {
00305 char *s1;
00306 int anum;
00307 boolexp_type locktype;
00308
00309 char *buff = alloc_lbuf("test_atr");
00310 strcpy(buff, s);
00311 for (s = buff; *s && (*s != ':') && (*s != '/'); s++)
00312 {
00313 ;
00314 }
00315 if (!*s)
00316 {
00317 free_lbuf(buff);
00318 return TRUE_BOOLEXP;
00319 }
00320 if (*s == '/')
00321 {
00322 locktype = BOOLEXP_EVAL;
00323 }
00324 else
00325 {
00326 locktype = BOOLEXP_ATR;
00327 }
00328
00329 *s++ = '\0';
00330
00331
00332
00333
00334
00335 ATTR *attrib = atr_str(buff);
00336 if (!attrib)
00337 {
00338
00339
00340 if (!God(parse_player))
00341 {
00342 free_lbuf(buff);
00343 return TRUE_BOOLEXP;
00344 }
00345 for (s1 = buff; mux_isdigit(*s1); s1++)
00346 {
00347 ;
00348 }
00349 if (*s1)
00350 {
00351 free_lbuf(buff);
00352 return TRUE_BOOLEXP;
00353 }
00354 anum = mux_atol(buff);
00355 if (anum <= 0)
00356 {
00357 free_lbuf(buff);
00358 return TRUE_BOOLEXP;
00359 }
00360 }
00361 else
00362 {
00363 anum = attrib->number;
00364 }
00365
00366
00367
00368 BOOLEXP *b = alloc_bool("test_str");
00369 b->type = locktype;
00370 b->thing = (dbref) anum;
00371 b->sub1 = (BOOLEXP *) StringClone(s);
00372 free_lbuf(buff);
00373 return b;
00374 }
00375
00376
00377
00378 static BOOLEXP *parse_boolexp_L(void)
00379 {
00380 BOOLEXP *b;
00381 char *p;
00382 char *buf;
00383 MSTATE mstate;
00384
00385 buf = NULL;
00386 skip_whitespace();
00387
00388 switch (*parsebuf)
00389 {
00390 case '(':
00391 parsebuf++;
00392 b = parse_boolexp_E();
00393 skip_whitespace();
00394 if ( b == TRUE_BOOLEXP
00395 || *parsebuf++ != ')')
00396 {
00397 free_boolexp(b);
00398 return TRUE_BOOLEXP;
00399 }
00400 break;
00401 default:
00402
00403
00404
00405 buf = alloc_lbuf("parse_boolexp_L");
00406 p = buf;
00407 while ( *parsebuf
00408 && *parsebuf != AND_TOKEN
00409 && *parsebuf != OR_TOKEN
00410 && *parsebuf != ')'
00411 && p < buf + LBUF_SIZE)
00412 {
00413 *p++ = *parsebuf++;
00414 }
00415
00416
00417
00418 *p-- = '\0';
00419 while (mux_isspace(*p))
00420 {
00421 *p-- = '\0';
00422 }
00423
00424
00425
00426 if ((b = test_atr(buf)) != NULL)
00427 {
00428 free_lbuf(buf);
00429 return (b);
00430 }
00431 b = alloc_bool("parse_boolexp_L");
00432 b->type = BOOLEXP_CONST;
00433
00434
00435
00436
00437 if (!mudstate.bStandAlone)
00438 {
00439
00440
00441
00442
00443 if (parsing_internal)
00444 {
00445 if (buf[0] != '#')
00446 {
00447 free_lbuf(buf);
00448 free_bool(b);
00449 return TRUE_BOOLEXP;
00450 }
00451 b->thing = mux_atol(&buf[1]);
00452 if (!Good_dbref(b->thing))
00453 {
00454 free_lbuf(buf);
00455 free_bool(b);
00456 return TRUE_BOOLEXP;
00457 }
00458 }
00459 else
00460 {
00461 save_match_state(&mstate);
00462 init_match(parse_player, buf, TYPE_THING);
00463 match_everything(MAT_EXIT_PARENTS);
00464 b->thing = match_result();
00465 restore_match_state(&mstate);
00466 }
00467
00468 if (b->thing == NOTHING)
00469 {
00470 notify(parse_player, tprintf("I don't see %s here.", buf));
00471 free_lbuf(buf);
00472 free_bool(b);
00473 return TRUE_BOOLEXP;
00474 }
00475 if (b->thing == AMBIGUOUS)
00476 {
00477 notify(parse_player, tprintf("I don't know which %s you mean!",
00478 buf));
00479 free_lbuf(buf);
00480 free_bool(b);
00481 return TRUE_BOOLEXP;
00482 }
00483 }
00484 else
00485 {
00486
00487
00488 if (buf[0] != '#')
00489 {
00490 free_lbuf(buf);
00491 free_bool(b);
00492 return TRUE_BOOLEXP;
00493 }
00494 b->thing = mux_atol(&buf[1]);
00495 if (b->thing < 0)
00496 {
00497 free_lbuf(buf);
00498 free_bool(b);
00499 return TRUE_BOOLEXP;
00500 }
00501 }
00502 free_lbuf(buf);
00503 }
00504 return b;
00505 }
00506
00507
00508
00509
00510 static BOOLEXP *parse_boolexp_F(void)
00511 {
00512 BOOLEXP *b2;
00513
00514 skip_whitespace();
00515 switch (*parsebuf)
00516 {
00517 case NOT_TOKEN:
00518
00519 parsebuf++;
00520 b2 = alloc_bool("parse_boolexp_F.not");
00521 b2->type = BOOLEXP_NOT;
00522 if ((b2->sub1 = parse_boolexp_F()) == TRUE_BOOLEXP)
00523 {
00524 free_boolexp(b2);
00525 return (TRUE_BOOLEXP);
00526 }
00527 else
00528 {
00529 return (b2);
00530 }
00531
00532
00533
00534
00535 case INDIR_TOKEN:
00536
00537 parsebuf++;
00538 b2 = alloc_bool("parse_boolexp_F.indir");
00539 b2->type = BOOLEXP_INDIR;
00540 b2->sub1 = parse_boolexp_L();
00541 if ((b2->sub1) == TRUE_BOOLEXP)
00542 {
00543 free_boolexp(b2);
00544 return (TRUE_BOOLEXP);
00545 }
00546 else if ((b2->sub1->type) != BOOLEXP_CONST)
00547 {
00548 free_boolexp(b2);
00549 return (TRUE_BOOLEXP);
00550 }
00551 else
00552 {
00553 return (b2);
00554 }
00555
00556
00557
00558
00559 case IS_TOKEN:
00560
00561 parsebuf++;
00562 b2 = alloc_bool("parse_boolexp_F.is");
00563 b2->type = BOOLEXP_IS;
00564 b2->sub1 = parse_boolexp_L();
00565 if (b2->sub1 == TRUE_BOOLEXP)
00566 {
00567 free_boolexp(b2);
00568 return (TRUE_BOOLEXP);
00569 }
00570 else if ( b2->sub1->type != BOOLEXP_CONST
00571 && b2->sub1->type != BOOLEXP_ATR)
00572 {
00573 free_boolexp(b2);
00574 return TRUE_BOOLEXP;
00575 }
00576 else
00577 {
00578 return (b2);
00579 }
00580
00581
00582
00583
00584 case CARRY_TOKEN:
00585
00586 parsebuf++;
00587 b2 = alloc_bool("parse_boolexp_F.carry");
00588 b2->type = BOOLEXP_CARRY;
00589 b2->sub1 = parse_boolexp_L();
00590 if (b2->sub1 == TRUE_BOOLEXP)
00591 {
00592 free_boolexp(b2);
00593 return TRUE_BOOLEXP;
00594 }
00595 else if ( b2->sub1->type != BOOLEXP_CONST
00596 && b2->sub1->type != BOOLEXP_ATR)
00597 {
00598 free_boolexp(b2);
00599 return TRUE_BOOLEXP;
00600 }
00601 else
00602 {
00603 return b2;
00604 }
00605
00606
00607
00608
00609 case OWNER_TOKEN:
00610
00611 parsebuf++;
00612 b2 = alloc_bool("parse_boolexp_F.owner");
00613 b2->type = BOOLEXP_OWNER;
00614 b2->sub1 = parse_boolexp_L();
00615 if (b2->sub1 == TRUE_BOOLEXP)
00616 {
00617 free_boolexp(b2);
00618 return TRUE_BOOLEXP;
00619 }
00620 else if (b2->sub1->type != BOOLEXP_CONST)
00621 {
00622 free_boolexp(b2);
00623 return TRUE_BOOLEXP;
00624 }
00625 else
00626 {
00627 return b2;
00628 }
00629
00630
00631
00632
00633 default:
00634 return parse_boolexp_L();
00635 }
00636 }
00637
00638
00639
00640 static BOOLEXP *parse_boolexp_T(void)
00641 {
00642 BOOLEXP *b, *b2;
00643
00644 if ((b = parse_boolexp_F()) != TRUE_BOOLEXP)
00645 {
00646 skip_whitespace();
00647 if (*parsebuf == AND_TOKEN)
00648 {
00649 parsebuf++;
00650
00651 b2 = alloc_bool("parse_boolexp_T");
00652 b2->type = BOOLEXP_AND;
00653 b2->sub1 = b;
00654 if ((b2->sub2 = parse_boolexp_T()) == TRUE_BOOLEXP)
00655 {
00656 free_boolexp(b2);
00657 return TRUE_BOOLEXP;
00658 }
00659 b = b2;
00660 }
00661 }
00662 return b;
00663 }
00664
00665
00666
00667 static BOOLEXP *parse_boolexp_E(void)
00668 {
00669 BOOLEXP *b, *b2;
00670
00671 if ((b = parse_boolexp_T()) != TRUE_BOOLEXP)
00672 {
00673 skip_whitespace();
00674 if (*parsebuf == OR_TOKEN)
00675 {
00676 parsebuf++;
00677
00678 b2 = alloc_bool("parse_boolexp_E");
00679 b2->type = BOOLEXP_OR;
00680 b2->sub1 = b;
00681 if ((b2->sub2 = parse_boolexp_E()) == TRUE_BOOLEXP)
00682 {
00683 free_boolexp(b2);
00684 return TRUE_BOOLEXP;
00685 }
00686 b = b2;
00687 }
00688 }
00689 return b;
00690 }
00691
00692 BOOLEXP *parse_boolexp(dbref player, const char *buf, bool internal)
00693 {
00694 size_t n = strlen(buf);
00695 if (n > sizeof(parsestore)-1)
00696 {
00697 n = sizeof(parsestore)-1;
00698 }
00699 memcpy(parsestore, buf, n+1);
00700 parsebuf = parsestore;
00701 parse_player = player;
00702 if ( buf == NULL
00703 || *buf == '\0')
00704 {
00705 return TRUE_BOOLEXP;
00706 }
00707 if (!mudstate.bStandAlone)
00708 {
00709 parsing_internal = internal;
00710 }
00711 return parse_boolexp_E();
00712 }