From e478baaf501d4e74bc194df28d2b4715929c87a9 Mon Sep 17 00:00:00 2001 From: wyld-sw Date: Fri, 12 Jan 2024 18:29:59 -0500 Subject: [PATCH 1/3] Adds {flag?} as counterpart to FLAG? - an refactors logic. --- include/db.h | 12 ++++++ include/mfun.h | 19 ++++++++++ src/db.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/mfuns2.c | 34 +++++++++++++++++ src/p_db.c | 87 +++----------------------------------------- 5 files changed, 169 insertions(+), 82 deletions(-) diff --git a/include/db.h b/include/db.h index f991ac4c..3e9f953d 100644 --- a/include/db.h +++ b/include/db.h @@ -2194,6 +2194,18 @@ int member(dbref thing, dbref list); */ dbref new_object(bool isplayer); +/** + * Returns true if the object has the given flag set (or reset). + * + * Understands flag alias and multiple not conditions (!!x = x, !!!x = !x). + * + * Checking "truewizard" is the same as checking "wizard" and "!quell". + * + * @param ref the object to check + * @param flag the flag (or alias) to check + */ +bool has_flag(dbref ref, const char *flag); + /** * Find a dbref in an objnode list * diff --git a/include/mfun.h b/include/mfun.h index c789a8d0..497ccab5 100644 --- a/include/mfun.h +++ b/include/mfun.h @@ -788,6 +788,24 @@ const char *mfn_exits(MFUNARGS); */ const char *mfn_filter(MFUNARGS); +/** + * MPI function that returns if an object if it has the given flag (re)set. + * + * @see has_flag + * + * @param descr the descriptor of the caller + * @param player the ref of the calling player + * @param what the dbref of the trigger + * @param perms the dbref for permission consideration + * @param argc the number of arguments + * @param argv the array of strings for arguments + * @param buf the working buffer + * @param buflen the size of the buffer + * @param mesgtyp the type of the message + * @return string parsed results + */ +const char *mfn_flagp(MFUNARGS); + /** * MPI function that returns the object flags for provided object as a string. * @@ -2985,6 +3003,7 @@ static struct mfun_dat mfun_list[] = { {"EXEC!", mfn_execbang, 1, 0, 1, 1, 2}, {"EXITS", mfn_exits, 1, 0, 1, 1, 1}, {"FILTER", mfn_filter, 0, 0, 0, 3, 5}, + {"FLAG?", mfn_flagp, 1, 0, 1, 2, 2}, {"FLAGS", mfn_flags, 1, 0, 1, 1, 1}, {"FOLD", mfn_fold, 0, 0, 0, 4, 5}, {"FOR", mfn_for, 0, 0, 0, 5, 5}, diff --git a/src/db.c b/src/db.c index a5e05e1c..78f1854b 100644 --- a/src/db.c +++ b/src/db.c @@ -2339,3 +2339,102 @@ env_distance(dbref from, dbref to) return distance; } + +/** + * Returns true if the object has the given flag set (or reset). + * + * Understands flag alias and multiple not conditions (!!x = x, !!!x = !x). + * + * Checking "truewizard" is the same as checking "wizard" and "!quell". + * + * @param ref the object to check + * @param flag the flag (or alias) to check + */ +bool +has_flag(dbref ref, const char *flag) +{ + object_flag_type tmp = 0; + int truwiz = 0; + bool result, negated = false; + + while (*flag == '!') { + flag++; + negated = (!negated); + } + + if (!*flag) { + return false; + } + + if (string_prefix("abode", flag) + || string_prefix("autostart", flag) + || string_prefix("abate", flag)) { + tmp = ABODE; + } else if (string_prefix("builder", flag) + || string_prefix("bound", flag)) { + tmp = BUILDER; + } else if (string_prefix("chown_ok", flag) + || string_prefix("color", flag)) { + tmp = CHOWN_OK; + } else if (string_prefix("dark", flag) + || string_prefix("debug", flag)) { + tmp = DARK; + } else if (string_prefix("guest", flag)) { + tmp = GUEST; + } else if (string_prefix("haven", flag) + || string_prefix("hide", flag) + || string_prefix("harduid", flag)) { + tmp = HAVEN; + } else if (string_prefix("interactive", flag)) { + tmp = INTERACTIVE; + } else if (string_prefix("jump_ok", flag)) { + tmp = JUMP_OK; + } else if (string_prefix("kill_ok", flag)) { + tmp = KILL_OK; + } else if (string_prefix("link_ok", flag)) { + tmp = LINK_OK; + } else if (string_prefix("mucker", flag)) { + tmp = MUCKER; + } else if (string_prefix("nucker", flag)) { + tmp = SMUCKER; + } else if (string_prefix("overt", flag)) { + tmp = (int)OVERT; + } else if (string_prefix("quell", flag)) { + tmp = QUELL; + } else if (string_prefix("sticky", flag) + || string_prefix("silent", flag) + || string_prefix("setuid", flag)) { + tmp = STICKY; + } else if (string_prefix("vehicle", flag) + || string_prefix("viewable", flag)) { + tmp = VEHICLE; + } else if (string_prefix("wizard", flag)) { + tmp = WIZARD; + } else if (string_prefix("truewizard", flag)) { + tmp = WIZARD; + truwiz = 1; + } else if (string_prefix("xforcible", flag) + || string_prefix("xpress", flag)) { + tmp = XFORCIBLE; + } else if (string_prefix("yield", flag)) { + tmp = YIELD; + } else if (string_prefix("zombie", flag)) { + tmp = ZOMBIE; + } + + if (negated) { + if ((!truwiz) && (tmp == WIZARD)) { + result = (!Wizard(ref)); + } else { + result = (tmp && ((FLAGS(ref) & tmp) == 0)); + } + } else { + if ((!truwiz) && (tmp == WIZARD)) { + result = Wizard(ref); + } else { + result = (tmp && ((FLAGS(ref) & tmp) != 0)); + } + } + + return result; +} diff --git a/src/mfuns2.c b/src/mfuns2.c index 99abf246..250cfc39 100644 --- a/src/mfuns2.c +++ b/src/mfuns2.c @@ -3460,3 +3460,37 @@ mfn_width(MFUNARGS) return buf; } + +/** + * MPI function that returns if an object if it has the given flag (re)set. + * + * @see has_flag + * + * @param descr the descriptor of the caller + * @param player the ref of the calling player + * @param what the dbref of the trigger + * @param perms the dbref for permission consideration + * @param argc the number of arguments + * @param argv the array of strings for arguments + * @param buf the working buffer + * @param buflen the size of the buffer + * @param mesgtyp the type of the message + * @return string parsed results + */ + +const char * +mfn_flagp(MFUNARGS) +{ + dbref obj = mesg_dbref_local(descr, player, what, perms, argv[0], mesgtyp); + + if (obj == PERMDENIED || obj == AMBIGUOUS || obj == UNKNOWN || obj == NOTHING || + obj == HOME) { + return "0"; + } + + if (has_flag(obj, argv[1])) { + return "1"; + } else { + return "0"; + } +} diff --git a/src/p_db.c b/src/p_db.c index 0ab30a63..f665938f 100644 --- a/src/p_db.c +++ b/src/p_db.c @@ -1234,99 +1234,22 @@ prim_mlevel(PRIM_PROTOTYPE) void prim_flagp(PRIM_PROTOTYPE) { - int truwiz = 0; - CHECKOP(2); oper1 = POP(); oper2 = POP(); - if (oper1->type != PROG_STRING) + if (oper1->type != PROG_STRING) { abort_interp("Invalid argument type (2)"); + } - if (!valid_object(oper2)) + if (!valid_object(oper2)) { abort_interp("Invalid object."); + } ref = oper2->data.objref; CHECKREMOTE(ref); - tmp = 0; - result = 0; - { - char *flag = DoNullInd(oper1->data.string); - - while (*flag == '!') { - flag++; - result = (!result); - } - - if (!*flag) - abort_interp("Unknown flag."); - - if (string_prefix("abode", flag) - || string_prefix("autostart", flag) - || string_prefix("abate", flag)) - tmp = ABODE; - else if (string_prefix("builder", flag)) - tmp = BUILDER; - else if (string_prefix("chown_ok", flag) - || string_prefix("color", flag)) - tmp = CHOWN_OK; - else if (string_prefix("dark", flag) - || string_prefix("debug", flag)) - tmp = DARK; - else if (string_prefix("guest", flag)) - tmp = GUEST; - else if (string_prefix("haven", flag) - || string_prefix("harduid", flag)) - tmp = HAVEN; - else if (string_prefix("interactive", flag)) - tmp = INTERACTIVE; - else if (string_prefix("jump_ok", flag)) - tmp = JUMP_OK; - else if (string_prefix("kill_ok", flag)) - tmp = KILL_OK; - else if (string_prefix("link_ok", flag)) - tmp = LINK_OK; - else if (string_prefix("mucker", flag)) - tmp = MUCKER; - else if (string_prefix("nucker", flag)) - tmp = SMUCKER; - else if (string_prefix("overt", flag)) - tmp = (int)OVERT; - else if (string_prefix("quell", flag)) - tmp = QUELL; - else if (string_prefix("sticky", flag) - || string_prefix("silent", flag)) - tmp = STICKY; - else if (string_prefix("vehicle", flag) - || string_prefix("viewable", flag)) - tmp = VEHICLE; - else if (string_prefix("wizard", flag)) - tmp = WIZARD; - else if (string_prefix("truewizard", flag)) { - tmp = WIZARD; - truwiz = 1; - } else if (string_prefix("xforcible", flag)) - tmp = XFORCIBLE; - else if (string_prefix("yield", flag)) - tmp = YIELD; - else if (string_prefix("zombie", flag)) - tmp = ZOMBIE; - } - - if (result) { - if ((!truwiz) && (tmp == WIZARD)) { - result = (!Wizard(ref)); - } else { - result = (tmp && ((FLAGS(ref) & tmp) == 0)); - } - } else { - if ((!truwiz) && (tmp == WIZARD)) { - result = Wizard(ref); - } else { - result = (tmp && ((FLAGS(ref) & tmp) != 0)); - } - } + result = has_flag(ref, DoNullInd(oper1->data.string)); CLEAR(oper1); CLEAR(oper2); From 4226d8058674a1f644796bb86a245c9f3f6f8c06 Mon Sep 17 00:00:00 2001 From: wyld-sw Date: Fri, 12 Jan 2024 18:48:26 -0500 Subject: [PATCH 2/3] Actually commit prim_set changes. --- src/p_db.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/p_db.c b/src/p_db.c index f665938f..30342dbf 100644 --- a/src/p_db.c +++ b/src/p_db.c @@ -1071,7 +1071,8 @@ prim_set(PRIM_PROTOTYPE) || string_prefix("autostart", flag) || string_prefix("abate", flag)) tmp = ABODE; - else if (string_prefix("builder", flag)) + else if (string_prefix("builder", flag) + || string_prefix("bound", flag)) tmp = BUILDER; else if (string_prefix("chown_ok", flag) || string_prefix("color", flag)) @@ -1082,6 +1083,7 @@ prim_set(PRIM_PROTOTYPE) else if (string_prefix("guest", flag)) tmp = GUEST; else if (string_prefix("haven", flag) + || string_prefix("hide", flag) || string_prefix("harduid", flag)) tmp = HAVEN; else if (string_prefix("interactive", flag)) @@ -1101,7 +1103,8 @@ prim_set(PRIM_PROTOTYPE) else if (string_prefix("quell", flag)) tmp = QUELL; else if (string_prefix("sticky", flag) - || string_prefix("silent", flag)) + || string_prefix("silent", flag) + || string_prefix("setuid", flag)) tmp = STICKY; else if (string_prefix("vehicle", flag) || string_prefix("viewable", flag)) @@ -1110,7 +1113,8 @@ prim_set(PRIM_PROTOTYPE) tmp = WIZARD; else if (string_prefix("truewizard", flag)) tmp = WIZARD; - else if (string_prefix("xforcible", flag)) + else if (string_prefix("xforcible", flag) + || string_prefix("xpress", flag)) tmp = XFORCIBLE; else if (string_prefix("yield", flag)) tmp = YIELD; From 66d515fc3139fcaf6be2c41bc301081a05328be1 Mon Sep 17 00:00:00 2001 From: wyld-sw Date: Sat, 13 Jan 2024 15:46:23 -0500 Subject: [PATCH 3/3] Extracts "flag to bit" logic into str_to_flag. Also changes {flag?} to abort when expected. --- include/db.h | 13 +++++ src/db.c | 142 ++++++++++++++++++++++++++++++--------------------- src/mfuns2.c | 2 +- src/p_db.c | 110 +++++++++------------------------------ 4 files changed, 122 insertions(+), 145 deletions(-) diff --git a/include/db.h b/include/db.h index 3e9f953d..a1e78326 100644 --- a/include/db.h +++ b/include/db.h @@ -2375,6 +2375,19 @@ void set_source(dbref action, dbref source); */ size_t size_object(dbref i, int load); +/** + * Returns the flag associated with the given string, if any. + * + * Understands flag alias prefixes. + * + * Passing "truewizard" here just returns the WIZARD flag. + * + * @param ref the object to check + * @param flag_string the flag (or alias) to check + * @return the flag corresponding to the string, or 0 if none match. + */ +object_flag_type str_to_flag(const char *flag_string); + /** * "Unparses" flags, or rather, gives a string representation of object flags * diff --git a/src/db.c b/src/db.c index 78f1854b..c9bf07f3 100644 --- a/src/db.c +++ b/src/db.c @@ -2340,15 +2340,93 @@ env_distance(dbref from, dbref to) return distance; } +/** + * Returns the flag associated with the given string, if any. + * + * Understands flag alias prefixes. + * + * Passing "truewizard" here just returns the WIZARD flag. + * + * @param ref the object to check + * @param flag_string the flag (or alias) to check + * @return the flag corresponding to the string, or 0 if none match. + */ +object_flag_type +str_to_flag(const char *flag_string) +{ + if (!*flag_string) { + return 0; + } + + if (string_prefix("abode", flag_string) + || string_prefix("autostart", flag_string) + || string_prefix("abate", flag_string)) { + return ABODE; + } else if (string_prefix("builder", flag_string) + || string_prefix("bound", flag_string)) { + return BUILDER; + } else if (string_prefix("chown_ok", flag_string) + || string_prefix("color", flag_string)) { + return CHOWN_OK; + } else if (string_prefix("dark", flag_string) + || string_prefix("debug", flag_string)) { + return DARK; + } else if (string_prefix("guest", flag_string)) { + return GUEST; + } else if (string_prefix("haven", flag_string) + || string_prefix("hide", flag_string) + || string_prefix("harduid", flag_string)) { + return HAVEN; + } else if (string_prefix("interactive", flag_string)) { + return INTERACTIVE; + } else if (string_prefix("jump_ok", flag_string)) { + return JUMP_OK; + } else if (string_prefix("kill_ok", flag_string)) { + return KILL_OK; + } else if (string_prefix("link_ok", flag_string)) { + return LINK_OK; + } else if (string_prefix("mucker", flag_string)) { + return MUCKER; + } else if (string_prefix("nucker", flag_string)) { + return SMUCKER; + } else if (string_prefix("overt", flag_string)) { + return (int)OVERT; + } else if (string_prefix("quell", flag_string)) { + return QUELL; + } else if (string_prefix("sticky", flag_string) + || string_prefix("silent", flag_string) + || string_prefix("setuid", flag_string)) { + return STICKY; + } else if (string_prefix("vehicle", flag_string) + || string_prefix("viewable", flag_string)) { + return VEHICLE; + } else if (string_prefix("wizard", flag_string)) { + return WIZARD; + } else if (string_prefix("truewizard", flag_string)) { + return WIZARD; + } else if (string_prefix("xforcible", flag_string) + || string_prefix("xpress", flag_string)) { + return XFORCIBLE; + } else if (string_prefix("yield", flag_string)) { + return YIELD; + } else if (string_prefix("zombie", flag_string)) { + return ZOMBIE; + } + + return 0; +} + + /** * Returns true if the object has the given flag set (or reset). * - * Understands flag alias and multiple not conditions (!!x = x, !!!x = !x). + * Understands flag alias prefixes and multiple not conditions (!!x = x). * * Checking "truewizard" is the same as checking "wizard" and "!quell". * * @param ref the object to check * @param flag the flag (or alias) to check + * @return if the object has the specific flag state */ bool has_flag(dbref ref, const char *flag) @@ -2357,71 +2435,17 @@ has_flag(dbref ref, const char *flag) int truwiz = 0; bool result, negated = false; - while (*flag == '!') { + while (*flag == NOT_TOKEN) { flag++; negated = (!negated); } - if (!*flag) { - return false; - } - - if (string_prefix("abode", flag) - || string_prefix("autostart", flag) - || string_prefix("abate", flag)) { - tmp = ABODE; - } else if (string_prefix("builder", flag) - || string_prefix("bound", flag)) { - tmp = BUILDER; - } else if (string_prefix("chown_ok", flag) - || string_prefix("color", flag)) { - tmp = CHOWN_OK; - } else if (string_prefix("dark", flag) - || string_prefix("debug", flag)) { - tmp = DARK; - } else if (string_prefix("guest", flag)) { - tmp = GUEST; - } else if (string_prefix("haven", flag) - || string_prefix("hide", flag) - || string_prefix("harduid", flag)) { - tmp = HAVEN; - } else if (string_prefix("interactive", flag)) { - tmp = INTERACTIVE; - } else if (string_prefix("jump_ok", flag)) { - tmp = JUMP_OK; - } else if (string_prefix("kill_ok", flag)) { - tmp = KILL_OK; - } else if (string_prefix("link_ok", flag)) { - tmp = LINK_OK; - } else if (string_prefix("mucker", flag)) { - tmp = MUCKER; - } else if (string_prefix("nucker", flag)) { - tmp = SMUCKER; - } else if (string_prefix("overt", flag)) { - tmp = (int)OVERT; - } else if (string_prefix("quell", flag)) { - tmp = QUELL; - } else if (string_prefix("sticky", flag) - || string_prefix("silent", flag) - || string_prefix("setuid", flag)) { - tmp = STICKY; - } else if (string_prefix("vehicle", flag) - || string_prefix("viewable", flag)) { - tmp = VEHICLE; - } else if (string_prefix("wizard", flag)) { - tmp = WIZARD; - } else if (string_prefix("truewizard", flag)) { - tmp = WIZARD; + if (string_prefix("truewizard", flag)) { truwiz = 1; - } else if (string_prefix("xforcible", flag) - || string_prefix("xpress", flag)) { - tmp = XFORCIBLE; - } else if (string_prefix("yield", flag)) { - tmp = YIELD; - } else if (string_prefix("zombie", flag)) { - tmp = ZOMBIE; } + tmp = str_to_flag(flag); + if (negated) { if ((!truwiz) && (tmp == WIZARD)) { result = (!Wizard(ref)); diff --git a/src/mfuns2.c b/src/mfuns2.c index 250cfc39..b5c952b1 100644 --- a/src/mfuns2.c +++ b/src/mfuns2.c @@ -3485,7 +3485,7 @@ mfn_flagp(MFUNARGS) if (obj == PERMDENIED || obj == AMBIGUOUS || obj == UNKNOWN || obj == NOTHING || obj == HOME) { - return "0"; + ABORT_MPI("FLAG?", "Failed match. (arg1)"); } if (has_flag(obj, argv[1])) { diff --git a/src/p_db.c b/src/p_db.c index 30342dbf..a9e5b617 100644 --- a/src/p_db.c +++ b/src/p_db.c @@ -1024,7 +1024,6 @@ prim_copyobj(PRIM_PROTOTYPE) * - interact with the OVERT flag on objects that aren't a thing or room * - interact with the YIELD flag on objects that aren't a thing or room * - * * "truewizard" is merely an alias for the WIZARD flag here. * * @param player the player running the MUF program @@ -1038,95 +1037,40 @@ prim_copyobj(PRIM_PROTOTYPE) void prim_set(PRIM_PROTOTYPE) { + object_flag_type tmp; + bool negated; + CHECKOP(2); oper1 = POP(); oper2 = POP(); - if (oper1->type != PROG_STRING) + if (oper1->type != PROG_STRING) { abort_interp("Invalid argument type (2)"); + } - if (!valid_object(oper2)) + if (!valid_object(oper2)) { abort_interp("Invalid object."); + } ref = oper2->data.objref; CHECKREMOTE(ref); - /** - * @TODO So, it would be nice if flags, their type aliases, basic - * restrictions, and perhaps error messages could be combined - * into a data structure. It could have MANY uses from do_examine - * to MUF. - */ - tmp = 0; - { - char *flag = DoNullInd(oper1->data.string); - result = (*flag == '!'); - - if (result) - flag++; - - if (!*flag) - tmp = 0; - if (string_prefix("abode", flag) - || string_prefix("autostart", flag) - || string_prefix("abate", flag)) - tmp = ABODE; - else if (string_prefix("builder", flag) - || string_prefix("bound", flag)) - tmp = BUILDER; - else if (string_prefix("chown_ok", flag) - || string_prefix("color", flag)) - tmp = CHOWN_OK; - else if (string_prefix("dark", flag) - || string_prefix("debug", flag)) - tmp = DARK; - else if (string_prefix("guest", flag)) - tmp = GUEST; - else if (string_prefix("haven", flag) - || string_prefix("hide", flag) - || string_prefix("harduid", flag)) - tmp = HAVEN; - else if (string_prefix("interactive", flag)) - tmp = INTERACTIVE; - else if (string_prefix("jump_ok", flag)) - tmp = JUMP_OK; - else if (string_prefix("kill_ok", flag)) - tmp = KILL_OK; - else if (string_prefix("link_ok", flag)) - tmp = LINK_OK; - else if (string_prefix("mucker", flag)) - tmp = MUCKER; - else if (string_prefix("nucker", flag)) - tmp = SMUCKER; - else if (string_prefix("overt", flag)) - tmp = (int)OVERT; - else if (string_prefix("quell", flag)) - tmp = QUELL; - else if (string_prefix("sticky", flag) - || string_prefix("silent", flag) - || string_prefix("setuid", flag)) - tmp = STICKY; - else if (string_prefix("vehicle", flag) - || string_prefix("viewable", flag)) - tmp = VEHICLE; - else if (string_prefix("wizard", flag)) - tmp = WIZARD; - else if (string_prefix("truewizard", flag)) - tmp = WIZARD; - else if (string_prefix("xforcible", flag) - || string_prefix("xpress", flag)) - tmp = XFORCIBLE; - else if (string_prefix("yield", flag)) - tmp = YIELD; - else if (string_prefix("zombie", flag)) - tmp = ZOMBIE; + if ((mlev < 4) && !permissions(ProgUID, ref)) { + abort_interp("Permission denied."); } - if (!tmp) - abort_interp("Unrecognized flag."); + const char *flag_string = DoNullInd(oper1->data.string); + negated = (*flag_string == NOT_TOKEN); - if ((mlev < 4) && !permissions(ProgUID, ref)) - abort_interp("Permission denied."); + if (negated) { + flag_string++; + } + + tmp = str_to_flag(flag_string); + + if (!tmp) { + abort_interp("Unrecognized flag."); + } /** * @TODO Shall we harmonize these checks with the restricted function? @@ -1142,8 +1086,9 @@ prim_set(PRIM_PROTOTYPE) || (tmp == GUEST))) || (tmp == WIZARD) || (tmp == QUELL) || (tmp == INTERACTIVE) || ((tmp == ABODE) && (Typeof(ref) == TYPE_PROGRAM)) - || (tmp == MUCKER) || (tmp == SMUCKER) || (tmp == XFORCIBLE)) + || (tmp == MUCKER) || (tmp == SMUCKER) || (tmp == XFORCIBLE)) { abort_interp("Permission denied."); + } if (((tmp == YIELD) || ((unsigned) tmp == OVERT)) && (Typeof(ref) != TYPE_THING && Typeof(ref) != TYPE_ROOM)) { @@ -1160,19 +1105,14 @@ prim_set(PRIM_PROTOTYPE) } } - if (!result) { + if (!negated) { FLAGS(ref) |= tmp; - - /** - * @TODO Move this DBDIRTY and the next outside the if. - */ - DBDIRTY(ref); } else { FLAGS(ref) &= ~tmp; - - DBDIRTY(ref); } + DBDIRTY(ref); + CLEAR(oper1); CLEAR(oper2); }