[Sep 25 2007] - Rumble
  Added set/not set to extra descriptions menu in oedit so a builder can tell if
  they exist or not without having to enter the extra desc menu or stat the object.
  Replaced [TRIG] flag (showvnum enabled) with [T<vnum>] to make things easier to stat.
[Sep 24 2007] - Rumble
  Added %is_pc% to return -1 for objects. (thanks Jamdog)
  Fixed do_gen_comm color bleed into last apostrophe in gossip/shout/grat/etc.
  Fixed bug where object keywords took precedence over door keywords. i.e. open door would try to open an object with keyword door. (thanks Trulight)
[Sep 23 2007] - Rumble
  Fixed minlev checks in do_grab, do_wield, and do_wear. (thanks Trulight)
  Added trigedit variables(modifiable) Hunger, Thirst, and Drunk.
[Sep 15 2007] - Rumble
  Fixed bug in unlimited drinks showing as empty. (thanks AaronGoulet)
This commit is contained in:
Rumble 2007-09-26 19:40:22 +00:00
parent 6c84a36236
commit 1f7a7b4182
25 changed files with 259 additions and 194 deletions

View file

@ -516,7 +516,8 @@ ACMD(do_gen_comm)
send_to_char(ch, "%s", CONFIG_OK);
else {
if (!first_word_is_name(ch, argument)) {
snprintf(buf1, sizeof(buf1), "%sYou %s, '%s'%s", COLOR_LEV(ch) >= C_CMP ? color_on : "", com_msgs[subcmd][1], argument, CCNRM(ch, C_CMP));
snprintf(buf1, sizeof(buf1), "%sYou %s, '%s%s'%s", COLOR_LEV(ch) >= C_CMP ? color_on : "", com_msgs[subcmd][1], argument, COLOR_LEV(ch) >= C_CMP
? color_on : "", CCNRM(ch, C_CMP));
} else {
emoting = TRUE;
snprintf(buf1, sizeof(buf1), "%s%s: %s%s", COLOR_LEV(ch) >= C_CMP ? color_on : "", com_msgs[subcmd][1], CAP(argument), CCNRM(ch, C_CMP));

View file

@ -131,17 +131,21 @@ void show_obj_to_char(struct obj_data *obj, struct char_data *ch, int mode)
if (*obj->description == '.' && (IS_NPC(ch) || !PRF_FLAGGED(ch, PRF_HOLYLIGHT)))
return;
if (!IS_NPC(ch) && PRF_FLAGGED(ch, PRF_SHOWVNUMS))
send_to_char(ch, "[%d] %s", GET_OBJ_VNUM(obj), SCRIPT(obj) ? "[TRIG] " : "");
if (!IS_NPC(ch) && PRF_FLAGGED(ch, PRF_SHOWVNUMS)) {
send_to_char(ch, "[%d] ", GET_OBJ_VNUM(obj));
if (SCRIPT(obj))
send_to_char(ch, "[T%d] ", obj->proto_script->vnum);
}
send_to_char(ch, "%s", CCGRN(ch, C_NRM));
send_to_char(ch, "%s", obj->description);
break;
case SHOW_OBJ_SHORT:
if (!IS_NPC(ch) && PRF_FLAGGED(ch, PRF_SHOWVNUMS))
send_to_char(ch, "[%d] %s", GET_OBJ_VNUM(obj), SCRIPT(obj) ? "[TRIG] " : "");
if (!IS_NPC(ch) && PRF_FLAGGED(ch, PRF_SHOWVNUMS)) {
send_to_char(ch, "[%d] ", GET_OBJ_VNUM(obj));
if (SCRIPT(obj))
send_to_char(ch, "[T%d] ", obj->proto_script->vnum);
}
send_to_char(ch, "%s", obj->short_description);
break;
@ -321,8 +325,11 @@ void list_one_char(struct char_data *i, struct char_data *ch)
" is standing here."
};
if (!IS_NPC(ch) && PRF_FLAGGED(ch, PRF_SHOWVNUMS) && IS_NPC(i))
send_to_char(ch, "[%d] %s", GET_MOB_VNUM(i), SCRIPT(i) ? "[TRIG] " : "");
if (!IS_NPC(ch) && PRF_FLAGGED(ch, PRF_SHOWVNUMS) && IS_NPC(i)) {
send_to_char(ch, "[%d]", GET_MOB_VNUM(i));
if (SCRIPT(i))
send_to_char(ch, "[T%d] ", i->proto_script->vnum);
}
if (IS_NPC(i) && i->player.long_descr && GET_POS(i) == GET_DEFAULT_POS(i)) {
if (AFF_FLAGGED(i, AFF_INVISIBLE))
@ -488,8 +495,10 @@ void look_at_room(struct char_data *ch, int ignore_brief)
sprintbitarray(ROOM_FLAGS(IN_ROOM(ch)), room_bits, RF_ARRAY_MAX, buf);
send_to_char(ch, "[%5d] ", GET_ROOM_VNUM(IN_ROOM(ch)));
send_to_char(ch, "%s%s [ %s]",
SCRIPT(rm) ? "[TRIG] " : "",
if (SCRIPT(rm))
send_to_char(ch, "[T%d] ", rm->proto_script->vnum);
send_to_char(ch, "%s [ %s]",
world[IN_ROOM(ch)].name, buf);
} else
send_to_char(ch, "%s", world[IN_ROOM(ch)].name);
@ -561,7 +570,7 @@ void look_in_obj(struct char_data *ch, char *arg)
list_obj_to_char(obj->contains, ch, SHOW_OBJ_SHORT, TRUE);
}
} else { /* item must be a fountain or drink container */
if (GET_OBJ_VAL(obj, 1) <= 0)
if ((GET_OBJ_VAL(obj, 1) == 0) && (!GET_OBJ_VAL(obj, 0) == 1))
send_to_char(ch, "It is empty.\r\n");
else {
if (GET_OBJ_VAL(obj, 0) < 0)
@ -1554,7 +1563,7 @@ void print_object_location(int num, struct obj_data *obj, struct char_data *ch,
send_to_char(ch, "%33s", " - ");
if (obj->proto_script)
send_to_char(ch, "[TRIG]");
send_to_char(ch, "[%d]", obj->proto_script->vnum);
if (IN_ROOM(obj) != NOWHERE)
send_to_char(ch, "[%5d] %s%s\r\n", GET_ROOM_VNUM(IN_ROOM(obj)), world[IN_ROOM(obj)].name, QNRM);
@ -1595,9 +1604,11 @@ void perform_immort_where(struct char_data *ch, char *arg)
for (i = character_list; i; i = i->next)
if (CAN_SEE(ch, i) && IN_ROOM(i) != NOWHERE && isname(arg, i->player.name)) {
found = 1;
send_to_char(ch, "M%3d. %-25s%s - [%5d] %-25s%s %s\r\n", ++num, GET_NAME(i), QNRM,
GET_ROOM_VNUM(IN_ROOM(i)), world[IN_ROOM(i)].name, QNRM,
(IS_NPC(i) && i->proto_script) ? "[TRIG]" : "");
send_to_char(ch, "M%3d. %-25s%s - [%5d] %-25s%s", ++num, GET_NAME(i), QNRM,
GET_ROOM_VNUM(IN_ROOM(i)), world[IN_ROOM(i)].name, QNRM);
if (SCRIPT(i))
send_to_char(ch, "[T%d] ", i->proto_script->vnum);
send_to_char(ch, "%s\r\n", QNRM);
}
for (num = 0, k = object_list; k; k = k->next)
if (CAN_SEE_OBJ(ch, k) && isname(arg, k->name)) {

View file

@ -854,8 +854,8 @@ ACMD(do_drink)
send_to_char(ch, "Your stomach can't contain anymore!\r\n");
return;
}
if (!GET_OBJ_VAL(temp, 1)) {
send_to_char(ch, "It's empty.\r\n");
if ((GET_OBJ_VAL(temp, 1) == 0) && (!GET_OBJ_VAL(temp, 0) == 1)) {
send_to_char(ch, "It is empty.\r\n");
return;
}
@ -1330,8 +1330,12 @@ ACMD(do_wear)
for (obj = ch->carrying; obj; obj = next_obj) {
next_obj = obj->next_content;
if (CAN_SEE_OBJ(ch, obj) && (where = find_eq_pos(ch, obj, 0)) >= 0) {
items_worn++;
perform_wear(ch, obj, where);
if (GET_LEVEL(ch) < GET_OBJ_LEVEL(obj))
send_to_char(ch, "You are not experienced enough to use that.\r\n");
else {
items_worn++;
perform_wear(ch, obj, where);
}
}
}
if (!items_worn)
@ -1357,6 +1361,8 @@ ACMD(do_wear)
} else {
if (!(obj = get_obj_in_list_vis(ch, arg1, NULL, ch->carrying)))
send_to_char(ch, "You don't seem to have %s %s.\r\n", AN(arg1), arg1);
else if (GET_LEVEL(ch) < GET_OBJ_LEVEL(obj))
send_to_char(ch, "You are not experienced enough to use that.\r\n");
else {
if ((where = find_eq_pos(ch, obj, arg2)) >= 0)
perform_wear(ch, obj, where);
@ -1382,6 +1388,8 @@ ACMD(do_wield)
send_to_char(ch, "You can't wield that.\r\n");
else if (GET_OBJ_WEIGHT(obj) > str_app[STRENGTH_APPLY_INDEX(ch)].wield_w)
send_to_char(ch, "It's too heavy for you to use.\r\n");
else if (GET_LEVEL(ch) < GET_OBJ_LEVEL(obj))
send_to_char(ch, "You are not experienced enough to use that.\r\n");
else
perform_wear(ch, obj, WEAR_WIELD);
}
@ -1398,6 +1406,8 @@ ACMD(do_grab)
send_to_char(ch, "Hold what?\r\n");
else if (!(obj = get_obj_in_list_vis(ch, arg, NULL, ch->carrying)))
send_to_char(ch, "You don't seem to have %s %s.\r\n", AN(arg), arg);
else if (GET_LEVEL(ch) < GET_OBJ_LEVEL(obj))
send_to_char(ch, "You are not experienced enough to use that.\r\n");
else {
if (GET_OBJ_TYPE(obj) == ITEM_LIGHT)
perform_wear(ch, obj, WEAR_LIGHT);

View file

@ -509,6 +509,11 @@ ACMD(do_gen_door)
if (!generic_find(type, FIND_OBJ_INV | FIND_OBJ_ROOM, ch, &victim, &obj))
door = find_door(ch, type, dir, cmd_door[subcmd]);
if ((obj) && (GET_OBJ_TYPE(obj) != ITEM_CONTAINER)) {
obj = NULL;
door = find_door(ch, type, dir, cmd_door[subcmd]);
}
if ((obj) || (door >= 0)) {
keynum = DOOR_KEY(ch, obj, door);
if (!(DOOR_IS_OPENABLE(ch, obj, door)))

View file

@ -1521,8 +1521,14 @@ ACMD(do_advance)
GET_LEVEL(victim) = newlevel;
send_to_char(victim, "You are momentarily enveloped by darkness!\r\nYou feel somewhat diminished.\r\n");
} else {
act("$n advances you.\r\n" , FALSE, ch, 0, victim, TO_VICT);
}
act("$n makes some strange gestures. A strange feeling comes upon you,\r\n"
"Like a giant hand, light comes down from above, grabbing your body,\r\n"
"that begins to pulse with colored lights from inside.\r\n\r\n"
"Your head seems to be filled with demons from another plane as your\r\n"
"your body dissolves to the elements of time and space itself.\r\n"
"Suddenly a silent explosion of light snaps you back to reality.\r\n\r\n"
"You feel slightly different.", FALSE, ch, 0, victim, TO_VICT);
}
send_to_char(ch, "%s", CONFIG_OK);
@ -3033,7 +3039,11 @@ int perform_set(struct char_data *ch, struct char_data *vict, int mode, char *va
case 38: /* poofin */
if ((vict == ch) || (GET_LEVEL(ch) == LVL_IMPL)) {
skip_spaces(&val_arg);
if (!*val_arg)
if (POOFIN(vict))
free(POOFIN(vict));
if (!*val_arg)
POOFIN(vict) = NULL;
else
POOFIN(vict) = strdup(val_arg);
@ -3042,7 +3052,11 @@ int perform_set(struct char_data *ch, struct char_data *vict, int mode, char *va
case 39: /* poofout */
if ((vict == ch) || (GET_LEVEL(ch) == LVL_IMPL)) {
skip_spaces(&val_arg);
if (!*val_arg)
if (POOFOUT(vict))
free(POOFOUT(vict));
if (!*val_arg)
POOFOUT(vict) = NULL;
else
POOFOUT(vict) = strdup(val_arg);

View file

@ -2100,7 +2100,7 @@ void free_help_table(void)
{
if (help_table) {
int hp;
for (hp = 0; hp <= top_of_helpt; hp++) {
for (hp = 0; hp < top_of_helpt; hp++) {
if (help_table[hp].keywords)
free(help_table[hp].keywords);
if (help_table[hp].entry && !help_table[hp].duplicate)

View file

@ -810,7 +810,7 @@ void script_stat (char_data *ch, struct script_data *sc)
void do_sstat_room(struct char_data * ch, struct room_data *rm)
{
send_to_char(ch, "Script information:\r\n");
send_to_char(ch, "Triggers:\r\n");
if (!SCRIPT(rm)) {
send_to_char(ch, " None.\r\n");
return;
@ -821,7 +821,7 @@ void do_sstat_room(struct char_data * ch, struct room_data *rm)
void do_sstat_object(char_data *ch, obj_data *j)
{
send_to_char(ch, "Script information:\r\n");
send_to_char(ch, "Triggers:\r\n");
if (!SCRIPT(j)) {
send_to_char(ch, " None.\r\n");
return;
@ -832,7 +832,7 @@ void do_sstat_object(char_data *ch, obj_data *j)
void do_sstat_character(char_data *ch, char_data *k)
{
send_to_char(ch, "Script information:\r\n");
send_to_char(ch, "Triggers:\r\n");
if (!SCRIPT(k)) {
send_to_char(ch, " None.\r\n");
return;

View file

@ -604,6 +604,13 @@ void find_replacement(void *go, struct script_data *sc, trig_data *trig,
}
snprintf(str, slen, "%d", GET_DEX(c));
}
else if (!str_cmp(field, "drunk")) {
if (subfield && *subfield) {
int addition = atoi(subfield);
GET_COND(c, DRUNK) = MAX(-1, MIN(addition, 24));
}
snprintf(str, slen, "%d", GET_COND(c, DRUNK));
}
break;
case 'e':
if (!str_cmp(field, "exp")) {
@ -682,6 +689,13 @@ void find_replacement(void *go, struct script_data *sc, trig_data *trig,
}
snprintf(str, slen, "%d", GET_HIT(c));
}
else if (!str_cmp(field, "hunger")) {
if (subfield && *subfield) {
int addition = atoi(subfield);
GET_COND(c, HUNGER) = MAX(-1, MIN(addition, 24));
}
snprintf(str, slen, "%d", GET_COND(c, HUNGER));
}
break;
case 'i':
if (!str_cmp(field, "id"))
@ -970,7 +984,15 @@ void find_replacement(void *go, struct script_data *sc, trig_data *trig,
}
snprintf(str, slen, "%s", IS_NPC(c) ? "" : GET_TITLE(c));
}
case 'v':
else if (!str_cmp(field, "thirst")) {
if (subfield && *subfield) {
int addition = atoi(subfield);
GET_COND(c, THIRST) = MAX(-1, MIN(addition, 24));
}
snprintf(str, slen, "%d", GET_COND(c, THIRST));
}
break;
case 'v':
if (!str_cmp(field, "vnum")) {
if (subfield && *subfield) {
snprintf(str, slen, "%d", IS_NPC(c) ? (int)(GET_MOB_VNUM(c) == atoi(subfield)) : -1 );
@ -1099,7 +1121,10 @@ o->contains) ? "1" : "0"));
else
*str = '\0';
}
break;
else if (!str_cmp(field, "is_pc")) {
strcpy(str, "-1");
}
break;
case 'n':
if (!str_cmp(field, "name"))
snprintf(str, slen, "%s", o->name);

View file

@ -160,7 +160,7 @@ int add_to_save_list(zone_vnum zone, int type)
rznum = real_zone(zone);
if (rznum == NOWHERE || rznum > top_of_zone_table) {
if (zone != AEDIT_PERMISSION) {
if (zone != AEDIT_PERMISSION || zone != HEDIT_PERMISSION) {
log("SYSERR: add_to_save_list: Invalid zone number passed. (%d => %d, 0-%d)", zone, rznum, top_of_zone_table);
return FALSE;
}

View file

@ -141,7 +141,7 @@ void hedit_save_internally(struct descriptor_data *d)
int i;
CREATE(new_help_table, struct help_index_element, top_of_helpt + 2);
for (i = 0; i <= top_of_helpt; i++)
for (i = 0; i < top_of_helpt; i++)
new_help_table[i] = help_table[i];
new_help_table[++top_of_helpt] = *OLC_HELP(d);
free(help_table);
@ -165,7 +165,7 @@ void hedit_save_to_disk(struct descriptor_data *d)
return;
}
for (i = 0; i <= top_of_helpt; i++) {
for (i = 0; i < top_of_helpt; i++) {
if (help_table[i].duplicate)
continue;
strncpy(buf1, help_table[i].entry ? help_table[i].entry : "Empty\r\n", sizeof(buf1) - 1);
@ -245,7 +245,7 @@ void hedit_parse(struct descriptor_data *d, char *arg)
break;
case 'n': case 'N':
OLC_ZNUM(d)++;
for (; OLC_ZNUM(d) <= top_of_helpt; OLC_ZNUM(d)++)
for (; OLC_ZNUM(d) < top_of_helpt; OLC_ZNUM(d)++)
if (is_abbrev(OLC_STORAGE(d), help_table[OLC_ZNUM(d)].keywords))
break;
else
@ -310,7 +310,7 @@ void hedit_parse(struct descriptor_data *d, char *arg)
string_write(d, &OLC_HELP(d)->entry, MAX_MESSAGE_LENGTH, 0, oldtext);
OLC_VAL(d) = 1;
break;
case 'M':
case '2':
write_to_output(d, "Enter min level : ");
OLC_MODE(d) = HEDIT_MIN_LEVEL;
break;
@ -408,7 +408,7 @@ ACMD(do_hindex)
}
len = sprintf(buf, "Help index entries based on '%s':\r\n", argument);
for (i = 0; i <= top_of_helpt; i++)
for (i = 0; i < top_of_helpt; i++)
if (is_abbrev(argument, help_table[i].keywords)
&& (GET_LEVEL(ch) >= help_table[i].min_level))
len +=

View file

@ -1375,6 +1375,9 @@ void nanny(struct descriptor_data *d, char *arg)
CREATE(d->character, struct char_data, 1);
clear_char(d->character);
CREATE(d->character->player_specials, struct player_special_data, 1);
if (GET_HOST(d->character))
free(GET_HOST(d->character));
GET_HOST(d->character) = strdup(d->host);
d->character->desc = d;

View file

@ -328,7 +328,7 @@ void oedit_disp_extradesc_menu(struct descriptor_data *d)
grn, nrm, yel, (extra_desc->keyword && *extra_desc->keyword) ? extra_desc->keyword : "<NONE>",
grn, nrm, yel, (extra_desc->description && *extra_desc->description) ? extra_desc->description : "<NONE>",
grn, nrm, !extra_desc->next ? "<Not set>\r\n" : "Set.", grn, nrm);
grn, nrm, !extra_desc->next ? "Not set." : "Set.", grn, nrm);
OLC_MODE(d) = OEDIT_EXTRADESC_MENU;
}
@ -444,7 +444,7 @@ void oedit_disp_val1_menu(struct descriptor_data *d)
break;
case ITEM_DRINKCON:
case ITEM_FOUNTAIN:
write_to_output(d, "Max drink units : ");
write_to_output(d, "Max drink units (-1 for unlimited) : ");
break;
case ITEM_FOOD:
write_to_output(d, "Hours to fill stomach : ");
@ -488,7 +488,7 @@ void oedit_disp_val2_menu(struct descriptor_data *d)
break;
case ITEM_DRINKCON:
case ITEM_FOUNTAIN:
write_to_output(d, "Initial drink units (-1 for unlimited) : ");
write_to_output(d, "Initial drink units : ");
break;
default:
oedit_disp_menu(d);
@ -648,7 +648,7 @@ void oedit_disp_menu(struct descriptor_data *d)
grn, nrm, yel, (obj->name && *obj->name) ? obj->name : "undefined",
grn, nrm, yel, (obj->short_description && *obj->short_description) ? obj->short_description : "undefined",
grn, nrm, yel, (obj->description && *obj->description) ? obj->description : "undefined",
grn, nrm, yel, (obj->action_description && *obj->action_description) ? obj->action_description : "<not set>\r\n",
grn, nrm, yel, (obj->action_description && *obj->action_description) ? obj->action_description : "Not Set.\r\n",
grn, nrm, cyn, buf1,
grn, nrm, cyn, buf2
);
@ -664,7 +664,7 @@ void oedit_disp_menu(struct descriptor_data *d)
"%sB%s) Timer : %s%d\r\n"
"%sC%s) Values : %s%d %d %d %d\r\n"
"%sD%s) Applies menu\r\n"
"%sE%s) Extra descriptions menu\r\n"
"%sE%s) Extra descriptions menu: %s%s%s\r\n"
"%sM%s) Min Level : %s%d\r\n"
"%sP%s) Perm Affects: %s%s\r\n"
"%sS%s) Script : %s%s\r\n"
@ -681,7 +681,7 @@ void oedit_disp_menu(struct descriptor_data *d)
GET_OBJ_VAL(obj, 1),
GET_OBJ_VAL(obj, 2),
GET_OBJ_VAL(obj, 3),
grn, nrm, grn, nrm,
grn, nrm, grn, nrm, cyn, GET_OBJ_EXTRA(obj) ? "Set." : "Not Set.", grn,
grn, nrm, cyn, GET_OBJ_LEVEL(obj),
grn, nrm, cyn, buf2,
grn, nrm, cyn, OLC_SCRIPT(d) ? "Set." : "Not Set.",

View file

@ -374,22 +374,14 @@ int load_char(const char *name, struct char_data *ch)
else if (!strcmp(tag, "Plyd")) ch->player.time.played = atoi(line);
else if (!strcmp(tag, "PfIn")) POOFIN(ch) = strdup(line);
else if (!strcmp(tag, "PfOt")) POOFOUT(ch) = strdup(line);
/* else if (!strcmp(tag, "Pref"))
sscanf(line, "%s %s %s %s", f1, f2, f3, f4);
PRF_FLAGS(ch)[0] = asciiflag_conv(f1);
PRF_FLAGS(ch)[1] = asciiflag_conv(f2);
PRF_FLAGS(ch)[2] = asciiflag_conv(f3);
PRF_FLAGS(ch)[3] = asciiflag_conv(f4);
*/
else if (!strcmp(tag, "Pref")) {
char *temp = line;
temp = one_argument(temp, line);
for (i = 0; *line && i < PR_ARRAY_MAX; i++) {
PRF_FLAGS(ch)[i] = asciiflag_conv(line);
temp = one_argument(temp, line);
}
}
break;
else if (!strcmp(tag, "Pref"))
if (sscanf(line, "%s %s %s %s", f1, f2, f3, f4) == 4) {
PRF_FLAGS(ch)[0] = asciiflag_conv(f1);
PRF_FLAGS(ch)[1] = asciiflag_conv(f2);
PRF_FLAGS(ch)[2] = asciiflag_conv(f3);
PRF_FLAGS(ch)[3] = asciiflag_conv(f4);
}
break;
case 'Q':
if (!strcmp(tag, "Qstp")) GET_QUESTPOINTS(ch) = atoi(line);

View file

@ -315,7 +315,7 @@ void redit_disp_extradesc_menu(struct descriptor_data *d)
grn, nrm
);
write_to_output(d, !extra_desc->next ? "<NOT SET>\r\n" : "Set.\r\n");
write_to_output(d, !extra_desc->next ? "Not Set.\r\n" : "Set.\r\n");
write_to_output(d, "Enter choice (0 to quit) : ");
OLC_MODE(d) = REDIT_EXTRADESC_MENU;
}

View file

@ -2,21 +2,14 @@
* File: zmalloc.c Part of tbaMUD *
* Usage: A simple memory allocation monitor. *
* *
* Version 2. Copyright 1996, 1998, 1999, 2000 Eric Murray. *
* Version 2. Copyright 1996, 1998, 1999, 2000 Eric Murray ericm@lne.com *
**************************************************************************/
/*
** Zmalloc, a simple memory-allocation monitor.
**
** Copyright 1996,1998,1999,2000 Eric Murray, ericm@lne.com
** You may make free use of this code but please give me credit.
** Documentation: http://www.lne.com/ericm/zmalloc
*
* Usage: to enable call zmalloc_init() at the very start of your
* program to open the logfile and call zmalloc_check() at the end
* to display memory leaks and free all allocated mem.
* See the main() test function at the bottom for an example.
*/
/* Usage: To run tbaMUD in debug mode change the flags line in your Makefile
* as below, make clean, and reboot.
*
* Makefile: # Any special flags you want to pass to the compiler
* Makefile: MYFLAGS = -Wall -DMEMORY_DEBUG */
/* protect our calloc() and free() calls from recursive redefinition: */
#define ZMALLOC_H
@ -26,6 +19,9 @@
#include <string.h>
#include <ctype.h>
#define NUM_ZBUCKETS 256
#define GET_ZBUCKET(addr) (((int)(addr) >> 3) & 0xFF)
//#define NO_MEMORY_PADDING
#ifndef NO_MEMORY_PADDING
@ -47,7 +43,7 @@ typedef struct meminfo {
int line; /* line in the code where malloc was called */
} meminfo;
static meminfo *memlist = NULL;
static meminfo *memlist[NUM_ZBUCKETS];
/*
* 0 = only end summary
@ -69,7 +65,13 @@ void pad_check(meminfo *m);
void zmalloc_free_list(meminfo *m);
void zmalloc_init(void) {
void zmalloc_init(void)
{
int i;
for (i = 0; i < NUM_ZBUCKETS; i++)
memlist[i] = NULL;
zfd = fopen("zmalloc.log","w+");
}
@ -146,18 +148,18 @@ unsigned char *zmalloc(int len, char *file, int line)
return NULL;
}
m->line = line;
m->next = memlist;
memlist = m;
m->next = memlist[GET_ZBUCKET(ret)];
memlist[GET_ZBUCKET(ret)] = m;
return (ret);
}
unsigned char *zrealloc(unsigned char *what, int len, char *file, int line)
{
unsigned char *ret;
meminfo *m;
meminfo *m, *prev_m;
if (what) {
for (m = memlist; m; m = m->next) {
for (prev_m = NULL, m = memlist[GET_ZBUCKET(what)]; m; prev_m = m, m = m->next) {
if (m->addr == what) {
#ifndef NO_MEMORY_PADDING
ret = (unsigned char *) realloc(what - sizeof(beginPad), len + sizeof(beginPad) + sizeof(endPad));
@ -186,6 +188,17 @@ unsigned char *zrealloc(unsigned char *what, int len, char *file, int line)
if (m->file) free(m->file);
m->file = strdup(file);
m->line = line;
/* detach node */
if (prev_m)
prev_m->next = m->next;
else
memlist[GET_ZBUCKET(what)] = m->next;
/* readd to proper bucket */
m->next = memlist[GET_ZBUCKET(ret)];
memlist[GET_ZBUCKET(ret)] = m;
/* could continue the loop to check for multiply-allocd memory */
/* but that's highly improbable so lets just return instead. */
return (ret);
@ -212,7 +225,7 @@ void zfree(unsigned char *what, char *file, int line)
}
/* look up allocated mem in list: */
for (m = memlist; m; m = m->next) {
for (m = memlist[GET_ZBUCKET(what)]; m; m = m->next) {
if (m->addr == what) {
/* got it. Print it if verbose: */
if (zmalloclogging > 2) {
@ -268,26 +281,36 @@ char *zstrdup(const char *src, char *file, int line)
void zmalloc_check()
{
meminfo *m;
meminfo *m, *next_m;
char *admonishemnt;
int total_leak = 0;
int num_leaks = 0;
int total_leak = 0, num_leaks = 0, i;
fprintf(zfd, "\n------------ Checking leaks ------------\n\n");
/* look up allocated mem in list: */
for(m = memlist; m; m = m->next) {
if (m->addr != 0 && m->frees <= 0) {
fprintf(zfd,"zmalloc: UNfreed memory 0x%4.4x %d bytes mallocd at %s:%d\n",
for (i = 0; i < NUM_ZBUCKETS; i++) {
for (m = memlist[i]; m; m = next_m) {
next_m = m->next;
if (m->addr != 0 && m->frees <= 0) {
fprintf(zfd,"zmalloc: UNfreed memory 0x%4.4x %d bytes mallocd at %s:%d\n",
(int)m->addr, m->size, m->file, m->line);
if (zmalloclogging > 1) zdump(m);
if (zmalloclogging > 1) zdump(m);
/* check padding on un-freed memory too: */
pad_check(m);
/* check padding on un-freed memory too: */
pad_check(m);
total_leak += m->size;
num_leaks++;
total_leak += m->size;
num_leaks++;
}
#ifndef NO_MEMORY_PADDING
if (m->addr) free(m->addr - sizeof(beginPad));
#else
if (m->addr) free(m->addr);
#endif
if (m->file) free(m->file);
free(m);
}
}
if (total_leak) {
if (total_leak > 10000)
admonishemnt = "you must work for Microsoft.";
@ -306,9 +329,6 @@ void zmalloc_check()
fprintf(zfd,"zmalloc: Congratulations: leak-free code!\n");
}
/* free up our own internal list */
zmalloc_free_list(memlist);
if (zfd) {
fflush(zfd);
fclose(zfd);
@ -331,22 +351,6 @@ void pad_check(meminfo *m)
}
void zmalloc_free_list(meminfo *m)
{
meminfo *next_m;
for (; m; m = next_m) {
next_m = m->next;
#ifndef NO_MEMORY_PADDING
if (m->addr) free(m->addr - sizeof(beginPad));
#else
if (m->addr) free(m->addr);
#endif
if (m->file) free(m->file);
free(m);
}
}
#ifdef ZTEST
#undef ZMALLOC_H

View file

@ -1,16 +1,9 @@
/**************************************************************************
* File: zmalloc.h Part of tbaMUD *
* Usage: A simple memory allocation monitor, header. *
* *
* Version 1.1 Copyright 1996, 1998, 1999, 2000 Eric Murray. *
* File: zmalloc.h Part of tbaMUD *
* Usage: A simple memory allocation monitor, header. *
* *
* Version 1.1 Copyright 1996, 1998, 1999, 2000 Eric Murray ericm@lne.com *
**************************************************************************/
/*
** Zmalloc, a simple memory-allocation monitor.
**
** Copyright 1996 Eric Murray, ericm@lne.com
** You may make free use of this code but please give me credit.
** Documentation: http://www.lne.com/ericm/zmalloc
*/
#ifndef ZMALLOC_H
#define ZMALLOC_H