match_result attempt_match(const char* begin, const char* end, token_kind& kind, std::size_t& length) { auto result = [&] (match_result r, token_kind kind_, std::size_t length_) { kind = kind_; length = length_; return r; }; if (begin == end) { return result(match_result::unmatched, token_kind::unknown, 0); } switch (*begin) { case '[': return result(match_result::complete, token_kind::array_begin, 1); case ']': return result(match_result::complete, token_kind::array_end, 1); case '{': return result(match_result::complete, token_kind::object_begin, 1); case '}': return result(match_result::complete, token_kind::object_end, 1); case ':': return result(match_result::complete, token_kind::object_key_delimiter, 1); case ',': return result(match_result::complete, token_kind::separator, 1); case 't': return match_true( begin, end, kind, length); case 'f': return match_false(begin, end, kind, length); case 'n': return match_null( begin, end, kind, length); case '-': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': return match_number(begin, end, kind, length); case '\"': return match_string(begin, end, kind, length); case ' ': case '\t': case '\n': case '\r': return match_whitespace(begin, end, kind, length); case '/': return match_comment(begin, end, kind, length); default: return result(match_result::unmatched, token_kind::unknown, 1); } }
static dbref parse_linkable_dest(int descr, dbref player, dbref exit, const char *dest_name) { dbref dobj; /* destination room/player/thing/link */ char buf[BUFFER_LEN]; struct match_data md; init_match(descr, player, dest_name, NOTYPE, &md); match_absolute(&md); match_everything(&md); match_home(&md); match_null(&md); if ((dobj = match_result(&md)) == NOTHING || dobj == AMBIGUOUS) { sprintf(buf, CINFO "I couldn't find '%s'.", dest_name); anotify_nolisten2(player, buf); return NOTHING; } if (!tp_teleport_to_player && Typeof(dobj) == TYPE_PLAYER) { sprintf(buf, CFAIL "You can't link to players. Destination %s ignored.", unparse_object(player, dobj)); anotify_nolisten2(player, buf); return NOTHING; } if (!can_link(player, exit)) { anotify_nolisten2(player, CFAIL "You can't link that."); return NOTHING; } if (!can_link_to(player, Typeof(exit), dobj)) { sprintf(buf, CFAIL "You can't link to %s.", unparse_object(player, dobj)); anotify_nolisten2(player, buf); return NOTHING; } else return dobj; }
/* do_link * * Use this to link to a room that you own. It also sets home for * objects and things, and drop-to's for rooms. * It seizes ownership of an unlinked exit, and costs 1 penny * plus a penny transferred to the exit owner if they aren't you * * All destinations must either be owned by you, or be LINK_OK. */ void do_link(int descr, dbref player, const char *thing_name, const char *dest_name) { dbref good_dest[MAX_LINKS]; int ndest, i; struct match_data md; char buf[BUFFER_LEN]; dbref thing, dest; if (tp_db_readonly) { anotify_nolisten2(player, CFAIL DBRO_MESG); return; } if (Guest(player)) { anotify_fmt(player, CFAIL "%s", tp_noguest_mesg); return; } init_match(descr, player, thing_name, TYPE_EXIT, &md); match_all_exits(&md); match_neighbor(&md); match_possession(&md); match_me(&md); match_here(&md); match_absolute(&md); match_registered(&md); if (Mage(OWNER(player))) match_player(&md); if ((thing = noisy_match_result(&md)) == NOTHING) return; switch (Typeof(thing)) { case TYPE_EXIT: /* we're ok, check the usual stuff */ if (DBFETCH(thing)->sp.exit.ndest != 0) { if (controls(player, thing)) { if ((DBFETCH(thing)->sp.exit.dest)[0] != NIL) { anotify_nolisten2(player, CINFO "That exit is already linked."); return; } } else { anotify_fmt(player, CFAIL "%s", tp_noperm_mesg); return; } } /* handle costs */ if (OWNER(thing) == OWNER(player)) { if (!payfor(player, tp_link_cost)) { anotify_fmt(player, CFAIL "It costs %d %s to link this exit.", tp_link_cost, (tp_link_cost == 1) ? tp_penny : tp_pennies); return; } } else { if (!payfor(player, tp_link_cost + tp_exit_cost)) { anotify_fmt(player, CFAIL "It costs %d %s to link this exit.", (tp_link_cost + tp_exit_cost), (tp_link_cost + tp_exit_cost == 1) ? tp_penny : tp_pennies); return; } else if (!Builder(player)) { anotify_nolisten2(player, CFAIL NOBBIT_MESG); return; } else { /* pay the owner for his loss */ dbref owner = OWNER(thing); DBFETCH(owner)->sp.player.pennies += tp_exit_cost; DBDIRTY(owner); } } /* link has been validated and paid for; do it */ OWNER(thing) = OWNER(player); if (! (ndest = link_exit(descr, player, thing, (char *) dest_name, good_dest))) { anotify_nolisten2(player, CFAIL "No destinations linked."); DBFETCH(player)->sp.player.pennies += tp_link_cost; /* Refund! */ DBDIRTY(player); break; } DBFETCH(thing)->sp.exit.ndest = ndest; if (DBFETCH(thing)->sp.exit.dest) free(DBFETCH(thing)->sp.exit.dest); DBFETCH(thing)->sp.exit.dest = (dbref *) malloc(sizeof(dbref) * ndest); for (i = 0; i < ndest; i++) (DBFETCH(thing)->sp.exit.dest)[i] = good_dest[i]; break; case TYPE_THING: case TYPE_PLAYER: init_match(descr, player, dest_name, TYPE_ROOM, &md); match_neighbor(&md); match_absolute(&md); match_registered(&md); match_me(&md); match_here(&md); match_null(&md); if (Typeof(thing) == TYPE_THING) match_possession(&md); if ((dest = noisy_match_result(&md)) == NOTHING) return; if (Typeof(thing) == TYPE_THING && dest == NIL) { anotify_fmt(player, CFAIL "%s", "You cannot HOME a THING to NIL."); return; } if (!controls(player, thing) || !can_link_to(player, Typeof(thing), dest)) { anotify_fmt(player, CFAIL "%s", tp_noperm_mesg); return; } if (parent_loop_check(thing, dest)) { anotify_nolisten2(player, CFAIL "That would cause a parent paradox."); return; } /* do the link */ if (Typeof(thing) == TYPE_THING) { DBFETCH(thing)->sp.thing.home = dest; } else DBFETCH(thing)->sp.player.home = dest; sprintf(buf, CSUCC "%s's home set to %s.", NAME(thing), unparse_object(player, dest)); anotify_nolisten2(player, buf); break; case TYPE_ROOM: /* room dropto's */ init_match(descr, player, dest_name, TYPE_ROOM, &md); match_neighbor(&md); match_possession(&md); match_registered(&md); match_absolute(&md); match_home(&md); match_null(&md); if ((dest = noisy_match_result(&md)) == NOTHING) break; if (!controls(player, thing) || !can_link_to(player, Typeof(thing), dest) || (thing == dest)) { anotify_fmt(player, CFAIL "%s", tp_noperm_mesg); } else { DBFETCH(thing)->sp.room.dropto = dest; /* dropto */ sprintf(buf, CSUCC "%s's dropto set to %s.", NAME(thing), unparse_object(player, dest)); anotify_nolisten2(player, buf); } break; case TYPE_PROGRAM: anotify_nolisten2(player, CFAIL "You can't link programs to things!"); break; default: anotify_nolisten2(player, CFAIL "Weird object type."); log_status("*BUG: weird object: Typeof(%d) = %d\n", thing, Typeof(thing)); break; } DBDIRTY(thing); return; }