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:
144
src/dungeon.c
144
src/dungeon.c
@@ -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
|
||||
|
||||
40
src/sp_lev.c
40
src/sp_lev.c
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user