get_table_str use

Some cleanup when chasing a memory leak.  get_table_str() and
get_table_str_opt() return a value from dupstr() and it wasn't always
being freed.  I'm not sure that I found the problem--maybe it involved
pointers turned over to Lua garbage collection--but did find a couple
of suspicious things in dungeon setup.
This commit is contained in:
PatR
2020-02-01 17:33:50 -08:00
parent 32f0520fe0
commit 5d6b3b6f51
2 changed files with 108 additions and 76 deletions

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 dungeon.c $NHDT-Date: 1562187890 2019/07/03 21:04:50 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.105 $ */
/* NetHack 3.6 dungeon.c $NHDT-Date: 1580607225 2020/02/02 01:33:45 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.124 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2012. */
/* NetHack may be freely redistributed. See license for details. */
@@ -693,7 +693,7 @@ struct proto_dungeon *pd;
return FALSE;
}
struct level_map {
static struct level_map {
const char *lev_name;
d_level *lev_spec;
} level_map[] = { { "air", &air_level },
@@ -729,8 +729,10 @@ get_dgn_flags(L)
lua_State *L;
{
int dgn_flags = 0;
const char *const flagstrs[] = { "town", "hellish", "mazelike", "roguelike", NULL};
const int flagstrs2i[] = { TOWN, HELLISH, MAZELIKE, ROGUELIKE, 0 };
static const char *const flagstrs[] = {
"town", "hellish", "mazelike", "roguelike", NULL
};
static const int flagstrs2i[] = { TOWN, HELLISH, MAZELIKE, ROGUELIKE, 0 };
lua_getfield(L, -1, "flags");
if (lua_type(L, -1) == LUA_TTABLE) {
@@ -740,10 +742,11 @@ lua_State *L;
nflags = (int) lua_tointeger(L, -1);
lua_pop(L, 1);
for (f = 0; f < nflags; f++) {
lua_pushinteger(L, f+1);
lua_pushinteger(L, f + 1);
lua_gettable(L, -2);
if (lua_type(L, -1) == LUA_TSTRING) {
dgn_flags |= flagstrs2i[luaL_checkoption(L, -1, NULL, flagstrs)];
dgn_flags |= flagstrs2i[luaL_checkoption(L, -1, NULL,
flagstrs)];
lua_pop(L, 1);
} else
impossible("flags[%i] is not a string", f);
@@ -761,8 +764,13 @@ lua_State *L;
void
init_dungeons()
{
const char *const dgnaligns[] = { "unaligned", "noalign", "lawful", "neutral", "chaotic", NULL};
const int dgnaligns2i[] = { D_ALIGN_NONE, D_ALIGN_NONE, D_ALIGN_LAWFUL, D_ALIGN_NEUTRAL, D_ALIGN_CHAOTIC, D_ALIGN_NONE };
static const char *const dgnaligns[] = {
"unaligned", "noalign", "lawful", "neutral", "chaotic", NULL
};
static const int dgnaligns2i[] = {
D_ALIGN_NONE, D_ALIGN_NONE, D_ALIGN_LAWFUL,
D_ALIGN_NEUTRAL, D_ALIGN_CHAOTIC, D_ALIGN_NONE
};
lua_State *L;
register int i, cl = 0;
register s_level *x;
@@ -770,7 +778,7 @@ init_dungeons()
struct level_map *lev_map;
int tidx;
(void) memset(&pd, 0, sizeof(struct proto_dungeon));
(void) memset(&pd, 0, sizeof (struct proto_dungeon));
pd.n_levs = pd.n_brs = 0;
L = nhl_init();
@@ -843,47 +851,61 @@ init_dungeons()
dgn_protoname = get_table_str_opt(L, "protofile", emptystr);
dgn_base = get_table_int(L, "base");
dgn_range = get_table_int_opt(L, "range", 0);
dgn_align = dgnaligns2i[get_table_option(L, "alignment", "unaligned", dgnaligns)];
dgn_align = dgnaligns2i[get_table_option(L, "alignment",
"unaligned", dgnaligns)];
dgn_entry = get_table_int_opt(L, "entry", 0);
dgn_chance = get_table_int_opt(L, "chance", 100);
dgn_flags = get_dgn_flags(L);
dgn_fill = get_table_str_opt(L, "lvlfill", emptystr);
debugpline4("DUNGEON[%i]: %s, base=(%i,%i)", i, dgn_name, dgn_base, dgn_range);
debugpline4("DUNGEON[%i]: %s, base=(%i,%i)",
i, dgn_name, dgn_base, dgn_range);
if (!wizard && dgn_chance && (dgn_chance <= rn2(100))) {
debugpline1("IGNORING %s", dgn_name);
g.n_dgns--;
lua_pop(L, 1); /* pop the dungeon table */
free((genericptr_t) dgn_name);
free((genericptr_t) dgn_bonetag);
free((genericptr_t) dgn_protoname);
free((genericptr_t) dgn_fill);
continue;
}
/* levels begin */
lua_getfield(L, -1, "levels");
if (lua_type(L, -1) == LUA_TTABLE) {
int f, nlevels;
char *lvl_name, *lvl_bonetag, *lvl_chain;
int lvl_base, lvl_range, lvl_nlevels, lvl_chance,
lvl_align, lvl_flags;
struct tmplevel *tmpl;
int bi, f, nlevels;
lua_len(L, -1);
nlevels = (int) lua_tointeger(L, -1);
pd.tmpdungeon[i].levels = nlevels;
lua_pop(L, 1);
for (f = 0; f < nlevels; f++) {
lua_pushinteger(L, f+1);
lua_pushinteger(L, f + 1);
lua_gettable(L, -2);
if (lua_type(L, -1) == LUA_TTABLE) {
int bi;
char *lvl_name = get_table_str(L, "name");
char *lvl_bonetag = get_table_str_opt(L, "bonetag", emptystr);
int lvl_base = get_table_int(L, "base");
int lvl_range = get_table_int_opt(L, "range", 0);
int lvl_nlevels = get_table_int_opt(L, "nlevels", 0);
int lvl_chance = get_table_int_opt(L, "chance", 100);
char *lvl_chain = get_table_str_opt(L, "chainlevel", NULL);
int lvl_align = dgnaligns2i[get_table_option(L, "alignment", "unaligned", dgnaligns)];
int lvl_flags = get_dgn_flags(L);
struct tmplevel *tmpl = &pd.tmplevel[pd.n_levs + f];
lvl_name = get_table_str(L, "name");
lvl_bonetag = get_table_str_opt(L, "bonetag", emptystr);
lvl_chain = get_table_str_opt(L, "chainlevel", NULL);
lvl_base = get_table_int(L, "base");
lvl_range = get_table_int_opt(L, "range", 0);
lvl_nlevels = get_table_int_opt(L, "nlevels", 0);
lvl_chance = get_table_int_opt(L, "chance", 100);
lvl_align = dgnaligns2i[get_table_option(L, "alignment",
"unaligned", dgnaligns)];
lvl_flags = get_dgn_flags(L);
/* array index is offset by cumulative number of levels
defined for preceding branches (iterations of 'while'
loop we're inside, not branch connections below) */
tmpl = &pd.tmplevel[pd.n_levs + f];
debugpline4("LEVEL[%i]:%s,(%i,%i)", f, lvl_name, lvl_base, lvl_range);
debugpline4("LEVEL[%i]:%s,(%i,%i)",
f, lvl_name, lvl_base, lvl_range);
tmpl->name = lvl_name;
tmpl->chainlvl = lvl_chain;
tmpl->lev.base = lvl_base;
@@ -897,15 +919,17 @@ init_dungeons()
if (lvl_chain) {
debugpline1("CHAINLEVEL: %s", lvl_chain);
for (bi = 0; bi < pd.n_levs + f; bi++) {
debugpline2("checking(%i):%s", bi, pd.tmplevel[bi].name);
debugpline2("checking(%i):%s",
bi, pd.tmplevel[bi].name);
if (!strcmp(pd.tmplevel[bi].name, lvl_chain)) {
tmpl->chain = bi;
break;
}
}
if (tmpl->chain == -1)
panic("Could not chain level %s to %s", lvl_name, lvl_chain);
free(lvl_chain);
panic("Could not chain level %s to %s",
lvl_name, lvl_chain);
/* free(lvl_chain); -- recorded in pd.tmplevel[] */
}
} else
panic("dungeon[%i].levels[%i] is not a hash", i, f);
@@ -922,30 +946,39 @@ init_dungeons()
/* branches begin */
lua_getfield(L, -1, "branches");
if (lua_type(L, -1) == LUA_TTABLE) {
int f, nbranches;
static const char *const brdirstr[] = { "up", "down", 0 };
static const int brdirstr2i[] = { TRUE, FALSE, FALSE };
static const char *const brtypes[] = {
"stair", "portal", "no_down", "no_up", 0
};
static const int brtypes2i[] = {
TBR_STAIR, TBR_PORTAL, TBR_NO_DOWN, TBR_NO_UP, TBR_STAIR
};
char *br_name, *br_chain;
int br_base, br_range, br_type, br_up;
struct tmpbranch *tmpb;
int bi, f, nbranches;
lua_len(L, -1);
nbranches = (int) lua_tointeger(L, -1);
pd.tmpdungeon[i].branches = nbranches;
lua_pop(L, 1);
for (f = 0; f < nbranches; f++) {
lua_pushinteger(L, f+1);
lua_pushinteger(L, f + 1);
lua_gettable(L, -2);
if (lua_type(L, -1) == LUA_TTABLE) {
int bi;
const char *const brdirstr[] = { "up", "down", NULL };
const int brdirstr2i[] = { TRUE, FALSE, FALSE };
const char *const brtypes[] = { "stair", "portal", "no_down", "no_up", NULL };
const int brtypes2i[] = { TBR_STAIR, TBR_PORTAL, TBR_NO_DOWN, TBR_NO_UP, TBR_STAIR };
char *br_name = get_table_str(L, "name");
int br_base = get_table_int(L, "base");
int br_range = get_table_int_opt(L, "range", 0);
int br_type = brtypes2i[get_table_option(L, "branchtype", "stair", brtypes)];
int br_up = brdirstr2i[get_table_option(L, "direction", "down", brdirstr)];
char *br_chain = get_table_str_opt(L, "chainlevel", NULL);
struct tmpbranch *tmpb = &pd.tmpbranch[pd.n_brs + f];
br_name = get_table_str(L, "name");
br_chain = get_table_str_opt(L, "chainlevel", NULL);
br_base = get_table_int(L, "base");
br_range = get_table_int_opt(L, "range", 0);
br_type = brtypes2i[get_table_option(L, "branchtype",
"stair", brtypes)];
br_up = brdirstr2i[get_table_option(L, "direction",
"down", brdirstr)];
tmpb = &pd.tmpbranch[pd.n_brs + f];
debugpline4("BRANCH[%i]:%s,(%i,%i)", f, br_name, br_base, br_range);
debugpline4("BRANCH[%i]:%s,(%i,%i)",
f, br_name, br_base, br_range);
tmpb->name = br_name;
tmpb->lev.base = br_base;
tmpb->lev.rand = br_range;
@@ -960,7 +993,8 @@ init_dungeons()
break;
}
if (tmpb->chain == -1)
panic("Could not chain branch %s to level %s", br_name, br_chain);
panic("Could not chain branch %s to level %s",
br_name, br_chain);
free(br_chain);
}
} else
@@ -989,8 +1023,9 @@ init_dungeons()
Strcpy(g.dungeons[i].dname, dgn_name); /* FIXME: dname length */
Strcpy(g.dungeons[i].proto, dgn_protoname); /* FIXME: proto length */
g.dungeons[i].boneid = *dgn_bonetag ? *dgn_bonetag : 0;
free(dgn_protoname);
free(dgn_bonetag);
free((genericptr) dgn_fill);
/* free((genericptr) dgn_protoname); -- stored in pd.tmpdungeon[] */
free((genericptr) dgn_bonetag);
if (dgn_range)
g.dungeons[i].num_dunlevs = (xchar) rn1(dgn_range, dgn_base);
@@ -1100,7 +1135,8 @@ init_dungeons()
}
lua_pop(L, 1); /* get rid of the dungeon global */
debugpline2("init_dungeon lua DONE (n_levs=%i, n_brs=%i)", pd.n_levs, pd.n_brs);
debugpline2("init_dungeon lua DONE (n_levs=%i, n_brs=%i)",
pd.n_levs, pd.n_brs);
for (i = 0; i < 5; i++)
g.tune[i] = 'A' + rn2(7);
@@ -1124,9 +1160,8 @@ init_dungeons()
branch *br;
/*
* Kludge to allow floating Knox entrance. We
* specify a floating entrance by the fact that
* its entrance (end1) has a bogus dnum, namely
* n_dgns.
* specify a floating entrance by the fact that its
* entrance (end1) has a bogus dnum, namely n_dgns.
*/
for (br = g.branches; br; br = br->next)
if (on_level(&br->end2, &knox_level))
@@ -1163,13 +1198,16 @@ init_dungeons()
lua_close(L);
for (i = 0; i < pd.n_brs; i++) {
free(pd.tmpbranch[i].name);
free((genericptr_t) pd.tmpbranch[i].name);
}
for (i = 0; i < pd.n_levs; i++) {
free(pd.tmplevel[i].name);
free((genericptr_t) pd.tmplevel[i].name);
if (pd.tmplevel[i].chainlvl)
free((genericptr_t) pd.tmplevel[i].chainlvl);
}
for (i = 0; i < g.n_dgns; i++) {
free(pd.tmpdungeon[i].name);
free((genericptr_t) pd.tmpdungeon[i].name);
free((genericptr_t) pd.tmpdungeon[i].protoname);
}
#ifdef DEBUG

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 sp_lev.c $NHDT-Date: 1580600499 2020/02/01 23:41:39 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.151 $ */
/* NetHack 3.6 sp_lev.c $NHDT-Date: 1580607226 2020/02/02 01:33:46 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.152 $ */
/* Copyright (c) 1989 by Jean-Christophe Collet */
/* NetHack may be freely redistributed. See license for details. */
@@ -2372,7 +2372,6 @@ lua_State *L;
if (s && strlen(s) == 1)
ret = (int) *s;
Free(s);
return ret;
}
@@ -2797,11 +2796,11 @@ lua_State *L;
break;
}
}
free((genericptr_t) montype);
if (pm)
tmpobj.corpsenm = monsndx(pm);
else
nhl_error(L, "Unknown montype");
free(montype);
}
if (tmpobj.id == STATUE) {
if (get_table_boolean_opt(L, "historic", 0))
@@ -3045,16 +3044,17 @@ const char *name;
int defval;
{
char *roomstr = get_table_str_opt(L, name, emptystr);
int i, res = defval;
if (roomstr && *roomstr) {
int i;
for (i = 0; room_types[i].name; i++)
if (!strcmpi(roomstr, room_types[i].name)) {
Free(roomstr);
return room_types[i].type;
res = room_types[i].type;
break;
}
}
Free(roomstr);
return defval;
return res;
}
/* room({ type="ordinary", lit=1, x=3,y=3, xalign="center",yalign="center", w=11,h=9 }); */
@@ -3311,14 +3311,9 @@ lua_State *L;
if (isok(x, y) && !t_at(x, y)) {
levl[x][y].typ = GRAVE;
if (txt)
make_grave(x, y, txt);
else
make_grave(x, y, NULL);
make_grave(x, y, txt); /* note: 'txt' might be Null */
}
Free(txt);
return 0;
}
@@ -3406,18 +3401,17 @@ const char *name;
int defval;
{
char *trapstr = get_table_str_opt(L, name, emptystr);
int i, res = defval;
if (trapstr && *trapstr) {
int i;
for (i = 0; trap_types[i].name; i++)
if (!strcmpi(trapstr, trap_types[i].name)) {
Free(trapstr);
return trap_types[i].type;
res = trap_types[i].type;
break;
}
}
Free(trapstr);
return defval;
return res;
}
const char *
@@ -4732,19 +4726,19 @@ lev_region *lregion;
if (g.num_lregions) {
/* realloc the lregion space to add the new one */
lev_region *newl = (lev_region *) alloc(
sizeof(lev_region) * (unsigned) (1 + g.num_lregions));
sizeof (lev_region) * (unsigned) (1 + g.num_lregions));
(void) memcpy((genericptr_t) (newl), (genericptr_t) g.lregions,
sizeof(lev_region) * g.num_lregions);
sizeof (lev_region) * g.num_lregions);
Free(g.lregions);
g.num_lregions++;
g.lregions = newl;
} else {
g.num_lregions = 1;
g.lregions = (lev_region *) alloc(sizeof(lev_region));
g.lregions = (lev_region *) alloc(sizeof (lev_region));
}
(void) memcpy(&g.lregions[g.num_lregions - 1], lregion,
sizeof(lev_region));
sizeof (lev_region));
}
/* teleport_region({ region = { x1,y1, x2,y2} }); */
@@ -4840,7 +4834,6 @@ lua_State *L;
tmplregion.rname.str = get_table_str_opt(L, "name", NULL);
levregion_add(&tmplregion);
return 0;
}
@@ -5348,6 +5341,7 @@ TODO: g.coder->croom needs to be updated
tmps = mapdata;
while (tmps && *tmps) {
char *s1 = index(tmps, '\n');
if (maphei > MAP_Y_LIM)
break;
if (s1)