]> granicus.if.org Git - nethack/commitdiff
extend wizard-mode '#stats' command
authorPatR <rankin@nethack.org>
Sat, 16 Apr 2016 22:37:35 +0000 (15:37 -0700)
committerPatR <rankin@nethack.org>
Sat, 16 Apr 2016 22:37:35 +0000 (15:37 -0700)
Extend #stats beyond just monsters and objects.  Have it display
memory usage for traps, engravings, light sources, timers, pending
shop wall/floor repair, regions, bones tracking, named object types,
and dungeon overview.

No doubt there are other memory consumers that I've overlooked.

doc/fixes36.1
include/extern.h
src/cmd.c
src/dungeon.c
src/engrave.c
src/light.c
src/region.c
src/timeout.c

index a200273df4cae53b476e6cd46219520179bbe04e..c6b5bc7cf8ba5426db74550b6a36b50e306d1cf1 100644 (file)
@@ -294,6 +294,7 @@ REPRODUCIBLE_BUILD is new config.h setting to fetch build date+time from
 default value for vibrating square symbol changed from yellow '^' to purple '~'
 allow symbol set values to be specified via char within single quotes
 add symbols set "plain", same as default except it uses '+' for corner walls
+extend wizard-mode '#stats' command
 
 
 Platform- and/or Interface-Specific New Features
index 679d486e1e4f3309d71b4c500b8566415cf220db..3ac113ca832021a89cea438e83b11a4e51b317ff 100644 (file)
@@ -594,6 +594,7 @@ E void NDECL(recalc_mapseen);
 E void FDECL(mapseen_temple, (struct monst *));
 E void FDECL(room_discovered, (int));
 E void FDECL(recbranch_mapseen, (d_level *, d_level *));
+E void FDECL(overview_stats, (winid, const char *, long *, long *));
 E void FDECL(remdun_mapseen, (int));
 
 /* ### eat.c ### */
@@ -680,6 +681,7 @@ E int NDECL(doengrave);
 E void NDECL(sanitize_engravings);
 E void FDECL(save_engravings, (int, int));
 E void FDECL(rest_engravings, (int));
+E void FDECL(engr_stats, (const char *, char *, long *, long *));
 E void FDECL(del_engr, (struct engr *));
 E void FDECL(rloc_engr, (struct engr *));
 E void FDECL(make_grave, (int, int, const char *));
@@ -984,6 +986,7 @@ E void FDECL(do_light_sources, (char **));
 E struct monst *FDECL(find_mid, (unsigned, unsigned));
 E void FDECL(save_light_sources, (int, int, int));
 E void FDECL(restore_light_sources, (int));
+E void FDECL(light_stats, (const char *, char *, long *, long *));
 E void FDECL(relink_light_sources, (BOOLEAN_P));
 E void NDECL(light_sources_sanity_check);
 E void FDECL(obj_move_light_source, (struct obj *, struct obj *));
@@ -1963,6 +1966,7 @@ E NhRegion *FDECL(visible_region_at, (XCHAR_P, XCHAR_P));
 E void FDECL(show_region, (NhRegion *, XCHAR_P, XCHAR_P));
 E void FDECL(save_regions, (int, int));
 E void FDECL(rest_regions, (int, BOOLEAN_P));
+E void FDECL(region_stats, (const char *, char *, long *, long *));
 E NhRegion *FDECL(create_gas_cloud, (XCHAR_P, XCHAR_P, int, int));
 E boolean NDECL(region_danger);
 E void NDECL(region_safety);
@@ -2307,6 +2311,7 @@ E long FDECL(spot_time_left, (XCHAR_P, XCHAR_P, SHORT_P));
 E boolean FDECL(obj_is_local, (struct obj *));
 E void FDECL(save_timers, (int, int, int));
 E void FDECL(restore_timers, (int, int, BOOLEAN_P, long));
+E void FDECL(timer_stats, (const char *, char *, long *, long *));
 E void FDECL(relink_timers, (BOOLEAN_P));
 E int NDECL(wiz_timeout_queue);
 E void NDECL(timer_sanity_check);
index cdad0923757eb8fa57f3f220832073c0b41b1698..033e73cd61123732c0dc749df956bd08651927bd 100644 (file)
--- a/src/cmd.c
+++ b/src/cmd.c
@@ -149,12 +149,13 @@ STATIC_DCL int FDECL(size_obj, (struct obj *));
 STATIC_DCL void FDECL(count_obj, (struct obj *, long *, long *,
                                   BOOLEAN_P, BOOLEAN_P));
 STATIC_DCL void FDECL(obj_chain, (winid, const char *, struct obj *,
-                                  long *, long *));
+                                  BOOLEAN_P, long *, long *));
 STATIC_DCL void FDECL(mon_invent_chain, (winid, const char *, struct monst *,
                                          long *, long *));
 STATIC_DCL void FDECL(mon_chain, (winid, const char *, struct monst *,
-                                  long *, long *));
-STATIC_DCL void FDECL(contained, (winid, const char *, long *, long *));
+                                  BOOLEAN_P, long *, long *));
+STATIC_DCL void FDECL(contained_stats, (winid, const char *, long *, long *));
+STATIC_DCL void FDECL(misc_stats, (winid, long *, long *));
 STATIC_PTR int NDECL(wiz_show_stats);
 STATIC_DCL boolean FDECL(accept_menu_prefix, (int NDECL((*))));
 #ifdef PORT_DEBUG
@@ -2905,9 +2906,9 @@ int NDECL((*fn));
     return 0;
 }
 
-static const char template[] = "%-18s %4ld  %6ld";
-static const char count_str[] = "                   count  bytes";
-static const char separator[] = "------------------ -----  ------";
+static const char template[] = "%-27s  %4ld  %6ld";
+static const char stats_hdr[] = "                             count  bytes";
+static const char stats_sep[] = "---------------------------  ----- -------";
 
 STATIC_OVL int
 size_obj(otmp)
@@ -2955,21 +2956,25 @@ boolean recurse;
 }
 
 STATIC_OVL void
-obj_chain(win, src, chain, total_count, total_size)
+obj_chain(win, src, chain, force, total_count, total_size)
 winid win;
 const char *src;
 struct obj *chain;
+boolean force;
 long *total_count;
 long *total_size;
 {
     char buf[BUFSZ];
-    long count = 0, size = 0;
+    long count = 0L, size = 0L;
 
     count_obj(chain, &count, &size, TRUE, FALSE);
-    *total_count += count;
-    *total_size += size;
-    Sprintf(buf, template, src, count, size);
-    putstr(win, 0, buf);
+
+    if (count || size || force) {
+        *total_count += count;
+        *total_size += size;
+        Sprintf(buf, template, src, count, size);
+        putstr(win, 0, buf);
+    }
 }
 
 STATIC_OVL void
@@ -2986,14 +2991,17 @@ long *total_size;
 
     for (mon = chain; mon; mon = mon->nmon)
         count_obj(mon->minvent, &count, &size, TRUE, FALSE);
-    *total_count += count;
-    *total_size += size;
-    Sprintf(buf, template, src, count, size);
-    putstr(win, 0, buf);
+
+    if (count || size) {
+        *total_count += count;
+        *total_size += size;
+        Sprintf(buf, template, src, count, size);
+        putstr(win, 0, buf);
+    }
 }
 
 STATIC_OVL void
-contained(win, src, total_count, total_size)
+contained_stats(win, src, total_count, total_size)
 winid win;
 const char *src;
 long *total_count;
@@ -3014,11 +3022,12 @@ long *total_size;
     for (mon = migrating_mons; mon; mon = mon->nmon)
         count_obj(mon->minvent, &count, &size, FALSE, TRUE);
 
-    *total_count += count;
-    *total_size += size;
-
-    Sprintf(buf, template, src, count, size);
-    putstr(win, 0, buf);
+    if (count || size) {
+        *total_count += count;
+        *total_size += size;
+        Sprintf(buf, template, src, count, size);
+        putstr(win, 0, buf);
+    }
 }
 
 STATIC_OVL int
@@ -3047,10 +3056,11 @@ struct monst *mtmp;
 }
 
 STATIC_OVL void
-mon_chain(win, src, chain, total_count, total_size)
+mon_chain(win, src, chain, force, total_count, total_size)
 winid win;
 const char *src;
 struct monst *chain;
+boolean force;
 long *total_count;
 long *total_size;
 {
@@ -3058,14 +3068,121 @@ long *total_size;
     long count, size;
     struct monst *mon;
 
-    for (count = size = 0, mon = chain; mon; mon = mon->nmon) {
+    count = size = 0L;
+    for (mon = chain; mon; mon = mon->nmon) {
         count++;
         size += size_monst(mon);
     }
+    if (count || size || force) {
+        *total_count += count;
+        *total_size += size;
+        Sprintf(buf, template, src, count, size);
+        putstr(win, 0, buf);
+    }
+}
+
+STATIC_OVL void
+misc_stats(win, total_count, total_size)
+winid win;
+long *total_count;
+long *total_size;
+{
+    char buf[BUFSZ], hdrbuf[QBUFSZ];
+    long count, size;
+    int idx;
+    struct trap *tt;
+    struct damage *sd; /* shop damage */
+    struct cemetery *bi; /* bones info */
+
+    /* traps and engravings are output unconditionally;
+     * others only if nonzero
+     */
+    count = size = 0L;
+    for (tt = ftrap; tt; tt = tt->ntrap) {
+        ++count;
+        size += (long) sizeof *tt;
+    }
     *total_count += count;
     *total_size += size;
-    Sprintf(buf, template, src, count, size);
+    Sprintf(hdrbuf, "traps, size %ld", (long) sizeof (struct trap));
+    Sprintf(buf, template, hdrbuf, count, size);
     putstr(win, 0, buf);
+
+    count = size = 0L;
+    engr_stats("engravings, size %ld+text", hdrbuf, &count, &size);
+    *total_count += count;
+    *total_size += size;
+    Sprintf(buf, template, hdrbuf, count, size);
+    putstr(win, 0, buf);
+
+    count = size = 0L;
+    light_stats("light sources, size %ld", hdrbuf, &count, &size);
+    if (count || size) {
+        *total_count += count;
+        *total_size += size;
+        Sprintf(buf, template, hdrbuf, count, size);
+        putstr(win, 0, buf);
+    }
+
+    count = size = 0L;
+    timer_stats("timers, size %ld", hdrbuf, &count, &size);
+    if (count || size) {
+        *total_count += count;
+        *total_size += size;
+        Sprintf(buf, template, hdrbuf, count, size);
+        putstr(win, 0, buf);
+    }
+
+    count = size = 0L;
+    for (sd = level.damagelist; sd; sd = sd->next) {
+        ++count;
+        size += (long) sizeof *sd;
+    }
+    if (count || size) {
+        *total_count += count;
+        *total_size += size;
+        Sprintf(hdrbuf, "shop damage, size %ld",
+                (long) sizeof (struct damage));
+        Sprintf(buf, template, hdrbuf, count, size);
+        putstr(win, 0, buf);
+    }
+
+    count = size = 0L;
+    region_stats("regions, size %ld+%ld*rect+N", hdrbuf, &count, &size);
+    if (count || size) {
+        *total_count += count;
+        *total_size += size;
+        Sprintf(buf, template, hdrbuf, count, size);
+        putstr(win, 0, buf);
+    }
+
+    count = size = 0L;
+    for (bi = level.bonesinfo; bi; bi = bi->next) {
+        ++count;
+        size += (long) sizeof *bi;
+    }
+    if (count || size) {
+        *total_count += count;
+        *total_size += size;
+        Sprintf(hdrbuf, "bones history, size %ld",
+                (long) sizeof (struct cemetery));
+        Sprintf(buf, template, hdrbuf, count, size);
+        putstr(win, 0, buf);
+    }
+
+    count = size = 0L;
+    for (idx = 0; idx < NUM_OBJECTS; ++idx)
+        if (objects[idx].oc_uname) {
+            ++count;
+            size += (long) (strlen(objects[idx].oc_uname) + 1);
+        }
+    if (count || size) {
+        *total_count += count;
+        *total_size += size;
+        Strcpy(hdrbuf, "object type names, text");
+        Sprintf(buf, template, hdrbuf, count, size);
+        putstr(win, 0, buf);
+    }
 }
 
 /*
@@ -3076,45 +3193,73 @@ wiz_show_stats()
 {
     char buf[BUFSZ];
     winid win;
-    long total_obj_size = 0, total_obj_count = 0;
-    long total_mon_size = 0, total_mon_count = 0;
+    long total_obj_size, total_obj_count,
+         total_mon_size, total_mon_count,
+         total_ovr_size, total_ovr_count,
+         total_misc_size, total_misc_count;
 
     win = create_nhwindow(NHW_TEXT);
     putstr(win, 0, "Current memory statistics:");
-    putstr(win, 0, "");
-    Sprintf(buf, "Objects, size %d", (int) sizeof(struct obj));
+
+    total_obj_count = total_obj_size = 0L;
+    putstr(win, 0, stats_hdr);
+    Sprintf(buf, "  Objects, base size %ld", (long) sizeof (struct obj));
     putstr(win, 0, buf);
-    putstr(win, 0, "");
-    putstr(win, 0, count_str);
-
-    obj_chain(win, "invent", invent, &total_obj_count, &total_obj_size);
-    obj_chain(win, "fobj", fobj, &total_obj_count, &total_obj_size);
-    obj_chain(win, "buried", level.buriedobjlist, &total_obj_count,
-              &total_obj_size);
-    obj_chain(win, "migrating obj", migrating_objs, &total_obj_count,
-              &total_obj_size);
+    obj_chain(win, "invent", invent, TRUE, &total_obj_count, &total_obj_size);
+    obj_chain(win, "fobj", fobj, TRUE, &total_obj_count, &total_obj_size);
+    obj_chain(win, "buried", level.buriedobjlist, FALSE,
+              &total_obj_count, &total_obj_size);
+    obj_chain(win, "migrating obj", migrating_objs, FALSE,
+              &total_obj_count, &total_obj_size);
+    obj_chain(win, "billobjs", billobjs, FALSE,
+              &total_obj_count, &total_obj_size);
     mon_invent_chain(win, "minvent", fmon, &total_obj_count, &total_obj_size);
     mon_invent_chain(win, "migrating minvent", migrating_mons,
                      &total_obj_count, &total_obj_size);
-
-    contained(win, "contained", &total_obj_count, &total_obj_size);
-
-    putstr(win, 0, separator);
-    Sprintf(buf, template, "Total", total_obj_count, total_obj_size);
+    contained_stats(win, "contained", &total_obj_count, &total_obj_size);
+    putstr(win, 0, stats_sep);
+    Sprintf(buf, template, "  Obj total", total_obj_count, total_obj_size);
     putstr(win, 0, buf);
 
+    total_mon_count = total_mon_size = 0L;
     putstr(win, 0, "");
-    putstr(win, 0, "");
-    Sprintf(buf, "Monsters, size %d", (int) sizeof(struct monst));
+    Sprintf(buf, "  Monsters, base size %ld", (long) sizeof (struct monst));
     putstr(win, 0, buf);
+    mon_chain(win, "fmon", fmon, TRUE, &total_mon_count, &total_mon_size);
+    mon_chain(win, "migrating", migrating_mons, FALSE,
+              &total_mon_count, &total_mon_size);
+    /* 'mydogs' is only valid during level change or end of game disclosure,
+       but conceivably we've been called from within debugger at such time */
+    if (mydogs) /* monsters accompanying hero */
+        mon_chain(win, "mydogs", mydogs, FALSE,
+                  &total_mon_count, &total_mon_size);
+    putstr(win, 0, stats_sep);
+    Sprintf(buf, template, "  Mon total", total_mon_count, total_mon_size);
+    putstr(win, 0, buf);
+
+    total_ovr_count = total_ovr_size = 0L;
     putstr(win, 0, "");
+    putstr(win, 0, "  Overview");
+    overview_stats(win, template, &total_ovr_count, &total_ovr_size);
+    putstr(win, 0, stats_sep);
+    Sprintf(buf, template, "  Over total", total_ovr_count, total_ovr_size);
+    putstr(win, 0, buf);
 
-    mon_chain(win, "fmon", fmon, &total_mon_count, &total_mon_size);
-    mon_chain(win, "migrating", migrating_mons, &total_mon_count,
-              &total_mon_size);
+    total_misc_count = total_misc_size = 0L;
+    putstr(win, 0, "");
+    putstr(win, 0, "  Miscellaneous");
+    misc_stats(win, &total_misc_count, &total_misc_size);
+    putstr(win, 0, stats_sep);
+    Sprintf(buf, template, "  Misc total", total_misc_count, total_misc_size);
+    putstr(win, 0, buf);
 
-    putstr(win, 0, separator);
-    Sprintf(buf, template, "Total", total_mon_count, total_mon_size);
+    putstr(win, 0, "");
+    putstr(win, 0, stats_sep);
+    Sprintf(buf, template, "  Grand total",
+            (total_obj_count + total_mon_count
+             + total_ovr_count + total_misc_count),
+            (total_obj_size + total_mon_size
+             + total_ovr_size + total_misc_size));
     putstr(win, 0, buf);
 
 #if defined(__BORLANDC__) && !defined(_WIN32)
index d101651a058ec55880fe8aae26aba0ebab86dffe..82610573a6e33966b9592cd923f374896a32f392 100644 (file)
@@ -2119,6 +2119,50 @@ int fd;
     return load;
 }
 
+/* to support '#stats' wizard-mode command */
+void
+overview_stats(win, statsfmt, total_count, total_size)
+winid win;
+const char *statsfmt;
+long *total_count, *total_size;
+{
+    char buf[BUFSZ], hdrbuf[QBUFSZ];
+    long ocount, osize, bcount, bsize, acount, asize;
+    struct cemetery *ce;
+    mapseen *mptr = find_mapseen(&u.uz);
+
+    ocount = bcount = acount = osize = bsize = asize = 0L;
+    for (mptr = mapseenchn; mptr; mptr = mptr->next) {
+        ++ocount;
+        osize += (long) sizeof *mptr;
+        for (ce = mptr->final_resting_place; ce; ce = ce->next) {
+            ++bcount;
+            bsize += (long) sizeof *ce;
+        }
+        if (mptr->custom_lth) {
+            ++acount;
+            asize += (long) (mptr->custom_lth + 1);
+        }
+    }
+
+    Sprintf(hdrbuf, "general, size %ld", (long) sizeof (mapseen));
+    Sprintf(buf, statsfmt, hdrbuf, ocount, osize);
+    putstr(win, 0, buf);
+    if (bcount) {
+        Sprintf(hdrbuf, "cemetery, size %ld",
+                (long) sizeof (struct cemetery));
+        Sprintf(buf, statsfmt, hdrbuf, bcount, bsize);
+        putstr(win, 0, buf);
+    }
+    if (acount) {
+        Sprintf(hdrbuf, "annotations, text");
+        Sprintf(buf, statsfmt, hdrbuf, acount, asize);
+        putstr(win, 0, buf);
+    }
+    *total_count += ocount + bcount + acount;
+    *total_size += osize + bsize + asize;
+}
+
 /* Remove all mapseen objects for a particular dnum.
  * Useful during quest expulsion to remove quest levels.
  * [No longer deleted, just marked as unreachable.  #overview will
index a4a07bd5bb0930a7ba8d2a2df629423605db511e..5347d4968146ee1ca380095abdd16a0e648ec361 100644 (file)
@@ -1201,6 +1201,23 @@ int fd;
     }
 }
 
+/* to support '#stats' wizard-mode command */
+void
+engr_stats(hdrfmt, hdrbuf, count, size)
+const char *hdrfmt;
+char *hdrbuf;
+long *count, *size;
+{
+    struct engr *ep;
+
+    Sprintf(hdrbuf, hdrfmt, (long) sizeof (struct engr));
+    *count = *size = 0L;
+    for (ep = head_engr; ep; ep = ep->nxt_engr) {
+        ++*count;
+        *size += (long) sizeof *ep + (long) ep->engr_lth;
+    }
+}
+
 void
 del_engr(ep)
 register struct engr *ep;
index 469987cb24df34abced5738dacf97464e0804c32..446dc390eb81cc2c07b1feda45ac7510574f3482 100644 (file)
@@ -306,6 +306,23 @@ int fd;
     }
 }
 
+/* to support '#stats' wizard-mode command */
+void
+light_stats(hdrfmt, hdrbuf, count, size)
+const char *hdrfmt;
+char *hdrbuf;
+long *count, *size;
+{
+    light_source *ls;
+
+    Sprintf(hdrbuf, hdrfmt, (long) sizeof (light_source));
+    *count = *size = 0L;
+    for (ls = light_base; ls; ls = ls->next) {
+        ++*count;
+        *size += (long) sizeof *ls;
+    }
+}
+
 /* Relink all lights that are so marked. */
 void
 relink_light_sources(ghostly)
index 6699716c052d815ad35b310b7678f36f4d1f675e..240f7270c92bf357d6c1be19eabf49af5168a102 100644 (file)
@@ -95,14 +95,13 @@ int nrect;
     if (nrect > 0) {
         reg->bounding_box = rects[0];
     } else {
-        reg->bounding_box.lx = 99;
-        reg->bounding_box.ly = 99;
-        reg->bounding_box.hx = 0;
+        reg->bounding_box.lx = COLNO;
+        reg->bounding_box.ly = ROWNO;
+        reg->bounding_box.hx = 0; /* 1 */
         reg->bounding_box.hy = 0;
     }
     reg->nrects = nrect;
-    reg->rects =
-        nrect > 0 ? (NhRect *) alloc((sizeof(NhRect)) * nrect) : (NhRect *) 0;
+    reg->rects = (nrect > 0) ? (NhRect *) alloc(nrect * sizeof (NhRect)) : 0;
     for (i = 0; i < nrect; i++) {
         if (rects[i].lx < reg->bounding_box.lx)
             reg->bounding_box.lx = rects[i].lx;
@@ -145,10 +144,10 @@ NhRect *rect;
 {
     NhRect *tmp_rect;
 
-    tmp_rect = (NhRect *) alloc(sizeof(NhRect) * (reg->nrects + 1));
+    tmp_rect = (NhRect *) alloc((reg->nrects + 1) * sizeof (NhRect));
     if (reg->nrects > 0) {
         (void) memcpy((genericptr_t) tmp_rect, (genericptr_t) reg->rects,
-                      (sizeof(NhRect) * reg->nrects));
+                      reg->nrects * sizeof (NhRect));
         free((genericptr_t) reg->rects);
     }
     tmp_rect[reg->nrects] = *rect;
@@ -177,7 +176,7 @@ struct monst *mon;
     unsigned *tmp_m;
 
     if (reg->max_monst <= reg->n_monst) {
-        tmp_m = (unsigned *) alloc(sizeof(unsigned)
+        tmp_m = (unsigned *) alloc(sizeof (unsigned)
                                    * (reg->max_monst + MONST_INC));
         if (reg->max_monst > 0) {
             for (i = 0; i < reg->max_monst; i++)
@@ -297,10 +296,10 @@ NhRegion *reg;
     if (max_regions <= n_regions) {
         tmp_reg = regions;
         regions =
-            (NhRegion **) alloc(sizeof(NhRegion *) * (max_regions + 10));
+            (NhRegion **) alloc((max_regions + 10) * sizeof (NhRegion *));
         if (max_regions > 0) {
             (void) memcpy((genericptr_t) regions, (genericptr_t) tmp_reg,
-                          max_regions * sizeof(NhRegion *));
+                          max_regions * sizeof (NhRegion *));
             free((genericptr_t) tmp_reg);
         }
         max_regions += 10;
@@ -763,6 +762,32 @@ boolean ghostly; /* If a bones file restore */
             reset_region_mids(regions[i]);
 }
 
+/* to support '#stats' wizard-mode command */
+void
+region_stats(hdrfmt, hdrbuf, count, size)
+const char *hdrfmt;
+char *hdrbuf;
+long *count, *size;
+{
+    NhRegion *rg;
+    int i;
+
+    /* other stats formats take one parameter; this takes two */
+    Sprintf(hdrbuf, hdrfmt, (long) sizeof (NhRegion), (long) sizeof (NhRect));
+    *count = (long) n_regions; /* might be 0 even though max_regions isn't */
+    *size = (long) max_regions * (long) sizeof (NhRegion);
+    for (i = 0; i < n_regions; ++i) {
+        rg = regions[i];
+        *size += (long) rg->nrects * (long) sizeof (NhRect);
+        if (rg->enter_msg)
+            *size += (long) (strlen(rg->enter_msg) + 1);
+        if (rg->leave_msg)
+            *size += (long) (strlen(rg->leave_msg) + 1);
+        *size += (long) rg->max_monst * (long) sizeof *rg->monsters;
+    }
+    /* ? */
+}
+
 /* update monster IDs for region being loaded from bones; `ghostly' implied */
 STATIC_OVL void
 reset_region_mids(reg)
index cb93622d75f3a7c0620c877fc69134018b533997..d4192903d6c451c4883569c121eb7f2b6e49c716 100644 (file)
@@ -1998,6 +1998,23 @@ long adjust;     /* how much to adjust timeout */
     }
 }
 
+/* to support '#stats' wizard-mode command */
+void
+timer_stats(hdrfmt, hdrbuf, count, size)
+const char *hdrfmt;
+char *hdrbuf;
+long *count, *size;
+{
+    timer_element *te;
+
+    Sprintf(hdrbuf, hdrfmt, (long) sizeof (timer_element));
+    *count = *size = 0L;
+    for (te = timer_base; te; te = te->next) {
+        ++*count;
+        *size += (long) sizeof *te;
+    }
+}
+
 /* reset all timers that are marked for reseting */
 void
 relink_timers(ghostly)