# # Patch name: indirect_commands.patch # Patch version: 2 # Author's name: Kurt Fitzner # Author's email: kfitzner@nexus.v-wave.com # Version of PennMUSH: 1.7.2p22 # Date patch made: Fri Apr 9 00:01:30 1999 # Author is willing to support (yes/no): yes # Patch format: diff -u5 # # # This is a contributed PennMUSH patch. Its use is subject to the # same restrictions found in PennMUSH's hdrs/copyrite.h file. # # No warranty is given for this patch. It is not necessarily going # to work on your system, with any version of PennMUSH other than # the one above, etc. # # If the author given above was willing to support the patch, you # should write to the author if you have any questions or problems. Do # *NOT* send email messages to Javelin or any PennMUSH mailing list about # this patch! # # Below this line is the author's description of the patch, # followed by the patch itself. If the patch is in context diff # format, you'll probably apply it by typing: patch < patchfile # in your top-level MUSH directory, unless instructed otherwise # below. # # # indirect_commands.patch # This patch adds a mechanism for $ command and ^ listen # indirection. Setting: # # &TEST obj1=$TC:!TEST2 # # and # # &TEST2 obj1=$TC2:@emit This is on attribute TEST2 # # will give you two commands, TC, and TC2 that both execute # the same code. The $command on the TEST attribute has been # redirected to the TEST2 attribute. # # You can redirect to other objects as well, with: # # &attr object1=$COMMAND:!object2/attr2 # # You can redirect $ commands to ^ listens, or vice versa. Or, # you can redirect either of them to straight triggerable code. # You can also have multiple levels of indirection. # The only limitation is that the pattern matching variables # (%0, %1, etc) are matched on the first command. So the # %0 vars need to be coded on the directed-to attribute the way # it is matched on the directed-from attribute. # --- ../testmush/src/attrib.c Fri Apr 2 10:54:44 1999 +++ src/attrib.c Fri Apr 9 00:01:30 1999 @@ -39,10 +39,11 @@ void atr_cpy _((dbref dest, dbref source)); char const *const convert_atr _((int oldatr)); int atr_comm_match _((dbref thing, dbref player, int type, int end, char const *str, int just_match)); +int indirect_parse _((dbref thing, char *aget, dbref player, int end, int rdepth)); int do_set_atr _((dbref thing, char const *atr, char const *s, dbref player, int flags)); void do_atrlock _((dbref player, char const *arg1, char const *arg2)); void do_atrchown _((dbref player, char const *arg1, char const *arg2)); @@ -774,12 +775,19 @@ *s++ = '\0'; if ((AL_FLAGS(ptr) & AF_REGEXP) ? regexp_match_case(tbuf1 + 1, str, (AL_FLAGS(ptr) & AF_CASE)) : wild_match_case(tbuf1 + 1, str, (AL_FLAGS(ptr) & AF_CASE))) { match++; - if (!just_match) - parse_que(thing, s, player); + if (!just_match) { + if (*s == '!') { + if (!indirect_parse(thing, s + 1, player, end, MAX_PARENTS)) { + match--; + } + } else { + parse_que(thing, s, player); + } + } } } if (!parent_depth) return match; @@ -810,19 +818,69 @@ *s++ = '\0'; if ((AL_FLAGS(ptr) & AF_REGEXP) ? regexp_match_case(tbuf1 + 1, str, (AL_FLAGS(ptr) & AF_CASE)) : wild_match_case(tbuf1 + 1, str, (AL_FLAGS(ptr) & AF_CASE))) { match++; - if (!just_match) - parse_que(thing, s, player); + if (!just_match) { + if (*s == '!') { + if (!indirect_parse(thing, s + 1, player, end, parent_depth)) { + match--; + } + } else { + parse_que(thing, s, player); + } + } } } } atr_hash_free(); return match; } + + +int +indirect_parse(thing, aget, player, end, rdepth) + dbref thing; + char *aget; + dbref player; + int end; + int rdepth; +{ + ATTR *attrib; + dbref obj; + char tbuf1[BUFFER_LEN]; + char *s; + + parse_attrib(thing, aget, &obj, &attrib); + + if (attrib && Can_Read_Attr(thing, obj, attrib)) { + + /* check for lots of easy ways out... wait, didn't I just say that? */ + if (!rdepth || Halted(obj) || !eval_lock(thing, obj, Use_Lock) || + AL_FLAGS(attrib) & AF_NOPROG) + return 0; + + strcpy(tbuf1, uncompress(AL_STR(attrib))); + s = tbuf1; + if (*s == '^' || *s == '$') { + do { + s = strchr(s + 1, end); + } while (s && s[-1] == '\\'); + if (!s) + return 0; + *s++ = '\0'; + } + if (*s == '!') + return indirect_parse(obj, s + 1, player, end, rdepth - 1); + parse_que(thing, s, player); + return 1; + } else { + return 0; + } +} + /*======================================================================*/ /* This is a new interface (as of 1.6.9p0) for setting attributes, * which takes care of case-fixing, object-level flag munging,