/* Remove all aliases for a standard attr. */ static int free_standard_attr_aliases(ATTR *a) { bool found_alias; ATTR *curr; const char *aliasname; int count = 0; /* Annoyingly convoluted because the ptab_delete will screw with the * counter used by ptab_nextextry_new */ do { found_alias = 0; curr = ptab_firstentry_new(&ptab_attrib, &aliasname); for (; curr; curr = ptab_nextentry_new(&ptab_attrib, &aliasname)) { if (!strcmp(AL_NAME(curr), AL_NAME(a)) && strcmp(AL_NAME(curr), aliasname)) { found_alias = 1; ptab_delete(&ptab_attrib, aliasname); count++; break; } } } while (found_alias); return count; }
/** Delete an attribute from the attribute table. * \verbatim * Top-level function for @attrib/delete. * \endverbatim * \param player the enactor. * \param name the name of the attribute to delete. */ void do_attribute_delete(dbref player, char *name) { ATTR *ap; if (!name || !*name) { notify(player, T("Which attribute do you mean?")); return; } /* Is this attribute in the table? */ ap = (ATTR *) ptab_find_exact(&ptab_attrib, name); if (!ap) { notify(player, T("That attribute isn't in the attribute table")); return; } /* Free everything it uses. */ if (ap->data != NULL_CHUNK_REFERENCE) { chunk_delete(ap->data); } /* Ok, take it out of the hash table */ ptab_delete(&ptab_attrib, name); notify_format(player, T("Removed %s from attribute table."), name); return; }
/** Free all memory used by a standard attribute, and remove it from the hash * table if necessary. * \param a attr to remove * \param inserted has the attr been inserted into the hash table already? * \retval number of entries (including aliases) removed from the hash table */ static int free_standard_attr(ATTR *a, bool inserted) { int count = 0; if (!a) { return count; } /* If the attr has no name, there's no way it can be in the hash table */ if (AL_NAME(a)) { if (inserted) { count = free_standard_attr_aliases(a) + 1; ptab_delete(&ptab_attrib, AL_NAME(a)); } free((char *) AL_NAME(a)); } if (a->data != NULL_CHUNK_REFERENCE) { chunk_delete(a->data); } mush_free(a, "ATTR"); return count; }
/** Rename an attribute in the attribute table. * \verbatim * Top-level function for @attrib/rename. * \endverbatim * \param player the enactor. * \param old the name of the attribute to rename. * \param newname the new name (surprise!) */ void do_attribute_rename(dbref player, char *old, char *newname) { ATTR *ap; if (!old || !*old || !newname || !*newname) { notify(player, T("Which attributes do you mean?")); return; } upcasestr(old); upcasestr(newname); /* Is the new name valid? */ if (!good_atr_name(newname)) { notify(player, T("Invalid attribute name.")); return; } /* Is the new name already in use? */ ap = (ATTR *) ptab_find_exact(&ptab_attrib, newname); if (ap) { notify_format(player, T("The name %s is already used in the attribute table."), newname); return; } /* Is the old name a real attribute? */ ap = (ATTR *) ptab_find_exact(&ptab_attrib, old); if (!ap) { notify(player, T("That attribute isn't in the attribute table")); return; } /* Ok, take it out and put it back under the new name */ ptab_delete(&ptab_attrib, old); /* This causes a slight memory leak if you rename an attribute added via /access. But that doesn't happen often. Will fix someday. */ AL_NAME(ap) = strdup(newname); ptab_insert_one(&ptab_attrib, newname, ap); notify_format(player, T("Renamed %s to %s in attribute table."), old, newname); return; }