]> granicus.if.org Git - nethack/commitdiff
get_table_str use
authorPatR <rankin@nethack.org>
Sun, 2 Feb 2020 01:33:50 +0000 (17:33 -0800)
committerPatR <rankin@nethack.org>
Sun, 2 Feb 2020 01:33:50 +0000 (17:33 -0800)
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.

src/dungeon.c
src/sp_lev.c

index 9505047322d865048eb0c8d04f39815e82399977..9546b7c3a5b5a9fab520c5943f77e3229b167271 100644 (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];
-
-                    debugpline4("LEVEL[%i]:%s,(%i,%i)", f, lvl_name, lvl_base, lvl_range);
+                    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);
                     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];
-
-                    debugpline4("BRANCH[%i]:%s,(%i,%i)", f, br_name, br_base, br_range);
+                    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);
                     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
index 5c653a8b005c877c224825243d6b3a0df8b1ce60..1e9bd75d0ad710614649189637fb753b23faf135 100644 (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)