From e3270d463de7eebd9f5ae20c85495e3cb5b69a9f Mon Sep 17 00:00:00 2001
From: Jim Warner <james.warner@comcast.net>
Date: Fri, 5 Aug 2016 00:00:00 -0500
Subject: [PATCH] library: provide for validating result type references

During development, we now have a means for validating
that a type referenced in application code matches the
actual type set by the library. The new feature can be
activated through either of the following two methods:

1) ./configure CFLAGS='-DXTRA_PROCPS_DEBUG' (all pgms)

2) an #include <proc/xtra-procps-debug.h> (single pgm)

[ in the future, one could add a formal configure.ac ]
[ provision. but for now a manual approach is safer. ]

Lastly, for any module which provides a sort function,
the handling for both 'noop' & 'extra' enumerators was
made consistent. Now, 'noop' is not sorted and 'extra'
will be sorted as that module's widest supported type.

Signed-off-by: Jim Warner <james.warner@comcast.net>
---
 Makefile.am              |   6 +-
 proc/diskstats.c         | 118 ++++++---
 proc/libprocps.sym       |  11 +
 proc/meminfo.c           | 244 +++++++++++-------
 proc/pids.c              | 285 ++++++++++++---------
 proc/procps.h            |   4 +
 proc/slabinfo.c          | 135 +++++++---
 proc/stat.c              | 133 +++++++---
 proc/vmstat.c            | 540 ++++++++++++++++++++++-----------------
 proc/xtra-procps-debug.h | 194 ++++++++++++++
 10 files changed, 1103 insertions(+), 567 deletions(-)
 create mode 100644 proc/xtra-procps-debug.h

diff --git a/Makefile.am b/Makefile.am
index ae072b77..a2cb7ec5 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -206,7 +206,8 @@ proc_libprocps_la_SOURCES = \
 	proc/wchan.c \
 	proc/wchan.h \
 	proc/uptime.c \
-	proc/uptime.h
+	proc/uptime.h \
+	proc/xtra-procps-debug.h
 
 proc_libprocps_la_includedir = $(includedir)/proc/
 proc_libprocps_la_include_HEADERS = \
@@ -223,7 +224,8 @@ proc_libprocps_la_include_HEADERS = \
 	proc/uptime.h \
 	proc/version.h \
 	proc/vmstat.h \
-	proc/wchan.h
+	proc/wchan.h \
+	proc/xtra-procps-debug.h
 
 dist_man_MANS += \
 	proc/openproc.3 \
diff --git a/proc/diskstats.c b/proc/diskstats.c
index 07abb609..019b5fd6 100644
--- a/proc/diskstats.c
+++ b/proc/diskstats.c
@@ -206,6 +206,9 @@ typedef void (*SET_t)(struct diskstats_result *, struct dev_node *);
 typedef int  (*QSR_t)(const void *, const void *, void *);
 #define QS(t) (QSR_t)srtNAME(t)
 
+#define TS(t) STRINGIFY(t)
+#define TS_noop ""
+
         /*
          * Need it be said?
          * This table must be kept in the exact same order as
@@ -213,43 +216,44 @@ typedef int  (*QSR_t)(const void *, const void *, void *);
 static struct {
     SET_t setsfunc;              // the actual result setting routine
     QSR_t sortfunc;              // sort cmp func for a specific type
+    char *type2str;              // the result type as a string value
 } Item_table[] = {
-/*  setsfunc                            sortfunc
-    ----------------------------------  ---------  */
-  { RS(noop),                           QS(ul_int) },
-  { RS(extra),                          QS(noop)   },
+/*  setsfunc                            sortfunc     type2str
+    ----------------------------------  -----------  ---------- */
+  { RS(noop),                           QS(noop),    TS_noop    },
+  { RS(extra),                          QS(ul_int),  TS_noop    },
 
-  { RS(DISKSTATS_NAME),                 QS(str)    },
-  { RS(DISKSTATS_TYPE),                 QS(s_int)  },
-  { RS(DISKSTATS_MAJOR),                QS(s_int)  },
-  { RS(DISKSTATS_MINOR),                QS(s_int)  },
+  { RS(DISKSTATS_NAME),                 QS(str),     TS(str)    },
+  { RS(DISKSTATS_TYPE),                 QS(s_int),   TS(s_int)  },
+  { RS(DISKSTATS_MAJOR),                QS(s_int),   TS(s_int)  },
+  { RS(DISKSTATS_MINOR),                QS(s_int),   TS(s_int)  },
 
-  { RS(DISKSTATS_READS),                QS(ul_int) },
-  { RS(DISKSTATS_READS_MERGED),         QS(ul_int) },
-  { RS(DISKSTATS_READ_SECTORS),         QS(ul_int) },
-  { RS(DISKSTATS_READ_TIME),            QS(ul_int) },
-  { RS(DISKSTATS_WRITES),               QS(ul_int) },
-  { RS(DISKSTATS_WRITES_MERGED),        QS(ul_int) },
-  { RS(DISKSTATS_WRITE_SECTORS),        QS(ul_int) },
-  { RS(DISKSTATS_WRITE_TIME),           QS(ul_int) },
-  { RS(DISKSTATS_IO_TIME),              QS(ul_int) },
-  { RS(DISKSTATS_IO_WTIME),             QS(ul_int) },
+  { RS(DISKSTATS_READS),                QS(ul_int),  TS(ul_int) },
+  { RS(DISKSTATS_READS_MERGED),         QS(ul_int),  TS(ul_int) },
+  { RS(DISKSTATS_READ_SECTORS),         QS(ul_int),  TS(ul_int) },
+  { RS(DISKSTATS_READ_TIME),            QS(ul_int),  TS(ul_int) },
+  { RS(DISKSTATS_WRITES),               QS(ul_int),  TS(ul_int) },
+  { RS(DISKSTATS_WRITES_MERGED),        QS(ul_int),  TS(ul_int) },
+  { RS(DISKSTATS_WRITE_SECTORS),        QS(ul_int),  TS(ul_int) },
+  { RS(DISKSTATS_WRITE_TIME),           QS(ul_int),  TS(ul_int) },
+  { RS(DISKSTATS_IO_TIME),              QS(ul_int),  TS(ul_int) },
+  { RS(DISKSTATS_IO_WTIME),             QS(ul_int),  TS(ul_int) },
 
-  { RS(DISKSTATS_IO_INPROGRESS),        QS(s_int)  },
+  { RS(DISKSTATS_IO_INPROGRESS),        QS(s_int),   TS(s_int)  },
 
-  { RS(DISKSTATS_DELTA_READS),          QS(s_int)  },
-  { RS(DISKSTATS_DELTA_READS_MERGED),   QS(s_int)  },
-  { RS(DISKSTATS_DELTA_READ_SECTORS),   QS(s_int)  },
-  { RS(DISKSTATS_DELTA_READ_TIME),      QS(s_int)  },
-  { RS(DISKSTATS_DELTA_WRITES),         QS(s_int)  },
-  { RS(DISKSTATS_DELTA_WRITES_MERGED),  QS(s_int)  },
-  { RS(DISKSTATS_DELTA_WRITE_SECTORS),  QS(s_int)  },
-  { RS(DISKSTATS_DELTA_WRITE_TIME),     QS(s_int)  },
-  { RS(DISKSTATS_DELTA_IO_TIME),        QS(s_int)  },
-  { RS(DISKSTATS_DELTA_IO_WTIME),       QS(s_int)  },
+  { RS(DISKSTATS_DELTA_READS),          QS(s_int),   TS(s_int)  },
+  { RS(DISKSTATS_DELTA_READS_MERGED),   QS(s_int),   TS(s_int)  },
+  { RS(DISKSTATS_DELTA_READ_SECTORS),   QS(s_int),   TS(s_int)  },
+  { RS(DISKSTATS_DELTA_READ_TIME),      QS(s_int),   TS(s_int)  },
+  { RS(DISKSTATS_DELTA_WRITES),         QS(s_int),   TS(s_int)  },
+  { RS(DISKSTATS_DELTA_WRITES_MERGED),  QS(s_int),   TS(s_int)  },
+  { RS(DISKSTATS_DELTA_WRITE_SECTORS),  QS(s_int),   TS(s_int)  },
+  { RS(DISKSTATS_DELTA_WRITE_TIME),     QS(s_int),   TS(s_int)  },
+  { RS(DISKSTATS_DELTA_IO_TIME),        QS(s_int),   TS(s_int)  },
+  { RS(DISKSTATS_DELTA_IO_WTIME),       QS(s_int),   TS(s_int)  },
 
  // dummy entry corresponding to DISKSTATS_logical_end ...
-  { NULL,                               NULL       }
+  { NULL,                               NULL,        NULL      }
 };
 
     /* please note,
@@ -974,3 +978,57 @@ PROCPS_EXPORT struct diskstats_stack **procps_diskstats_sort (
     qsort_r(stacks, numstacked, sizeof(void *), (QSR_t)Item_table[p->item].sortfunc, &parms);
     return stacks;
 } // end: procps_diskstats_sort
+
+
+// --- special debugging function(s) ------------------------------------------
+/*
+ *  The following isn't part of the normal programming interface.  Rather,
+ *  it exists to validate result types referenced in application programs.
+ *
+ *  It's used only when:
+ *      1) the 'XTRA_PROCPS_DEBUG' has been defined, or
+ *      2) the '#include <proc/xtra-procps-debug.h>' used
+ */
+
+PROCPS_EXPORT struct diskstats_result *xtra_diskstats_get (
+        struct diskstats_info *info,
+        const char *name,
+        enum diskstats_item actual_enum,
+        const char *typestr,
+        const char *file,
+        int lineno)
+{
+    struct diskstats_result *r = procps_diskstats_get(info, name, actual_enum);
+
+    if (r) {
+        char *str = Item_table[r->item].type2str;
+        if (str[0]
+        && (strcmp(typestr, str)))
+            fprintf(stderr, "%s line %d: was %s, expected %s\n", file, lineno, typestr, str);
+    }
+    return r;
+} // end: xtra_diskstats_get_
+
+
+PROCPS_EXPORT void xtra_diskstats_val (
+        int relative_enum,
+        const char *typestr,
+        const struct diskstats_stack *stack,
+        struct diskstats_info *info,
+        const char *file,
+        int lineno)
+{
+    struct diskstats_result *r;
+    char *str;
+
+    r = &stack->head[relative_enum];
+    if (r->item < 0 || r->item >= DISKSTATS_logical_end) {
+        fprintf(stderr, "%s line %d: invalid item = %d, relative_enum = %d, type = %s\n"
+            , file, lineno, r->item, relative_enum, typestr);
+        return;
+    }
+    str = Item_table[r->item].type2str;
+    if (str[0]
+    && (strcmp(typestr, str)))
+        fprintf(stderr, "%s line %d: was %s, expected %s\n", file, lineno, typestr, str);
+} // end: xtra_diskstats_val
diff --git a/proc/libprocps.sym b/proc/libprocps.sym
index 6707ce3a..8853048d 100644
--- a/proc/libprocps.sym
+++ b/proc/libprocps.sym
@@ -52,6 +52,17 @@ global:
 	procps_vmstat_unref;
 	procps_vmstat_get;
 	procps_vmstat_select;
+	xtra_diskstats_get;
+	xtra_diskstats_val;
+	xtra_meminfo_get;
+	xtra_meminfo_val;
+	xtra_pids_val;
+	xtra_slabinfo_get;
+	xtra_slabinfo_val;
+	xtra_stat_get;
+	xtra_stat_val;
+	xtra_vmstat_get;
+	xtra_vmstat_val;
 local:
 	*;
 };
diff --git a/proc/meminfo.c b/proc/meminfo.c
index d0153cdb..fd58349d 100644
--- a/proc/meminfo.c
+++ b/proc/meminfo.c
@@ -235,112 +235,117 @@ MEM_set(SWAP_USED,              ul_int,  derived_swap_used)
 typedef void (*SET_t)(struct meminfo_result *, struct mem_hist *);
 #define RS(e) (SET_t)setNAME(e)
 
+#define TS(t) STRINGIFY(t)
+#define TS_noop ""
+
         /*
          * Need it be said?
          * This table must be kept in the exact same order as
          * those 'enum meminfo_item' guys ! */
 static struct {
     SET_t setsfunc;              // the actual result setting routine
+    char *type2str;              // the result type as a string value
 } Item_table[] = {
-/*  setsfunc
-    -------------------------- */
-  { RS(noop)                 },
-  { RS(extra)                },
+/*  setsfunc                   type2str
+    -------------------------  ---------- */
+  { RS(noop),                  TS_noop    },
+  { RS(extra),                 TS_noop    },
 
-  { RS(MEM_ACTIVE)           },
-  { RS(MEM_ACTIVE_ANON)      },
-  { RS(MEM_ACTIVE_FILE)      },
-  { RS(MEM_ANON)             },
-  { RS(MEM_AVAILABLE)        },
-  { RS(MEM_BOUNCE)           },
-  { RS(MEM_BUFFERS)          },
-  { RS(MEM_CACHED)           },
-  { RS(MEM_COMMIT_LIMIT)     },
-  { RS(MEM_COMMITTED_AS)     },
-  { RS(MEM_HARD_CORRUPTED)   },
-  { RS(MEM_DIRTY)            },
-  { RS(MEM_FREE)             },
-  { RS(MEM_HUGE_ANON)        },
-  { RS(MEM_HUGE_FREE)        },
-  { RS(MEM_HUGE_RSVD)        },
-  { RS(MEM_HUGE_SIZE)        },
-  { RS(MEM_HUGE_SURPLUS)     },
-  { RS(MEM_HUGE_TOTAL)       },
-  { RS(MEM_INACTIVE)         },
-  { RS(MEM_INACTIVE_ANON)    },
-  { RS(MEM_INACTIVE_FILE)    },
-  { RS(MEM_KERNEL_STACK)     },
-  { RS(MEM_LOCKED)           },
-  { RS(MEM_MAPPED)           },
-  { RS(MEM_NFS_UNSTABLE)     },
-  { RS(MEM_PAGE_TABLES)      },
-  { RS(MEM_SHARED)           },
-  { RS(MEM_SLAB)             },
-  { RS(MEM_SLAB_RECLAIM)     },
-  { RS(MEM_SLAB_UNRECLAIM)   },
-  { RS(MEM_TOTAL)            },
-  { RS(MEM_UNEVICTABLE)      },
-  { RS(MEM_USED)             },
-  { RS(MEM_VM_ALLOC_CHUNK)   },
-  { RS(MEM_VM_ALLOC_TOTAL)   },
-  { RS(MEM_VM_ALLOC_USED)    },
-  { RS(MEM_WRITEBACK)        },
-  { RS(MEM_WRITEBACK_TMP)    },
+  { RS(MEM_ACTIVE),            TS(ul_int) },
+  { RS(MEM_ACTIVE_ANON),       TS(ul_int) },
+  { RS(MEM_ACTIVE_FILE),       TS(ul_int) },
+  { RS(MEM_ANON),              TS(ul_int) },
+  { RS(MEM_AVAILABLE),         TS(ul_int) },
+  { RS(MEM_BOUNCE),            TS(ul_int) },
+  { RS(MEM_BUFFERS),           TS(ul_int) },
+  { RS(MEM_CACHED),            TS(ul_int) },
+  { RS(MEM_COMMIT_LIMIT),      TS(ul_int) },
+  { RS(MEM_COMMITTED_AS),      TS(ul_int) },
+  { RS(MEM_HARD_CORRUPTED),    TS(ul_int) },
+  { RS(MEM_DIRTY),             TS(ul_int) },
+  { RS(MEM_FREE),              TS(ul_int) },
+  { RS(MEM_HUGE_ANON),         TS(ul_int) },
+  { RS(MEM_HUGE_FREE),         TS(ul_int) },
+  { RS(MEM_HUGE_RSVD),         TS(ul_int) },
+  { RS(MEM_HUGE_SIZE),         TS(ul_int) },
+  { RS(MEM_HUGE_SURPLUS),      TS(ul_int) },
+  { RS(MEM_HUGE_TOTAL),        TS(ul_int) },
+  { RS(MEM_INACTIVE),          TS(ul_int) },
+  { RS(MEM_INACTIVE_ANON),     TS(ul_int) },
+  { RS(MEM_INACTIVE_FILE),     TS(ul_int) },
+  { RS(MEM_KERNEL_STACK),      TS(ul_int) },
+  { RS(MEM_LOCKED),            TS(ul_int) },
+  { RS(MEM_MAPPED),            TS(ul_int) },
+  { RS(MEM_NFS_UNSTABLE),      TS(ul_int) },
+  { RS(MEM_PAGE_TABLES),       TS(ul_int) },
+  { RS(MEM_SHARED),            TS(ul_int) },
+  { RS(MEM_SLAB),              TS(ul_int) },
+  { RS(MEM_SLAB_RECLAIM),      TS(ul_int) },
+  { RS(MEM_SLAB_UNRECLAIM),    TS(ul_int) },
+  { RS(MEM_TOTAL),             TS(ul_int) },
+  { RS(MEM_UNEVICTABLE),       TS(ul_int) },
+  { RS(MEM_USED),              TS(ul_int) },
+  { RS(MEM_VM_ALLOC_CHUNK),    TS(ul_int) },
+  { RS(MEM_VM_ALLOC_TOTAL),    TS(ul_int) },
+  { RS(MEM_VM_ALLOC_USED),     TS(ul_int) },
+  { RS(MEM_WRITEBACK),         TS(ul_int) },
+  { RS(MEM_WRITEBACK_TMP),     TS(ul_int) },
 
-  { RS(DELTA_ACTIVE)         },
-  { RS(DELTA_ACTIVE_ANON)    },
-  { RS(DELTA_ACTIVE_FILE)    },
-  { RS(DELTA_ANON)           },
-  { RS(DELTA_AVAILABLE)      },
-  { RS(DELTA_BOUNCE)         },
-  { RS(DELTA_BUFFERS)        },
-  { RS(DELTA_CACHED)         },
-  { RS(DELTA_COMMIT_LIMIT)   },
-  { RS(DELTA_COMMITTED_AS)   },
-  { RS(DELTA_HARD_CORRUPTED) },
-  { RS(DELTA_DIRTY)          },
-  { RS(DELTA_FREE)           },
-  { RS(DELTA_HUGE_ANON)      },
-  { RS(DELTA_HUGE_FREE)      },
-  { RS(DELTA_HUGE_RSVD)      },
-  { RS(DELTA_HUGE_SIZE)      },
-  { RS(DELTA_HUGE_SURPLUS)   },
-  { RS(DELTA_HUGE_TOTAL)     },
-  { RS(DELTA_INACTIVE)       },
-  { RS(DELTA_INACTIVE_ANON)  },
-  { RS(DELTA_INACTIVE_FILE)  },
-  { RS(DELTA_KERNEL_STACK)   },
-  { RS(DELTA_LOCKED)         },
-  { RS(DELTA_MAPPED)         },
-  { RS(DELTA_NFS_UNSTABLE)   },
-  { RS(DELTA_PAGE_TABLES)    },
-  { RS(DELTA_SHARED)         },
-  { RS(DELTA_SLAB)           },
-  { RS(DELTA_SLAB_RECLAIM)   },
-  { RS(DELTA_SLAB_UNRECLAIM) },
-  { RS(DELTA_TOTAL)          },
-  { RS(DELTA_UNEVICTABLE)    },
-  { RS(DELTA_USED)           },
-  { RS(DELTA_VM_ALLOC_CHUNK) },
-  { RS(DELTA_VM_ALLOC_TOTAL) },
-  { RS(DELTA_VM_ALLOC_USED)  },
-  { RS(DELTA_WRITEBACK)      },
-  { RS(DELTA_WRITEBACK_TMP)  },
+  { RS(DELTA_ACTIVE),          TS(s_int)  },
+  { RS(DELTA_ACTIVE_ANON),     TS(s_int)  },
+  { RS(DELTA_ACTIVE_FILE),     TS(s_int)  },
+  { RS(DELTA_ANON),            TS(s_int)  },
+  { RS(DELTA_AVAILABLE),       TS(s_int)  },
+  { RS(DELTA_BOUNCE),          TS(s_int)  },
+  { RS(DELTA_BUFFERS),         TS(s_int)  },
+  { RS(DELTA_CACHED),          TS(s_int)  },
+  { RS(DELTA_COMMIT_LIMIT),    TS(s_int)  },
+  { RS(DELTA_COMMITTED_AS),    TS(s_int)  },
+  { RS(DELTA_HARD_CORRUPTED),  TS(s_int)  },
+  { RS(DELTA_DIRTY),           TS(s_int)  },
+  { RS(DELTA_FREE),            TS(s_int)  },
+  { RS(DELTA_HUGE_ANON),       TS(s_int)  },
+  { RS(DELTA_HUGE_FREE),       TS(s_int)  },
+  { RS(DELTA_HUGE_RSVD),       TS(s_int)  },
+  { RS(DELTA_HUGE_SIZE),       TS(s_int)  },
+  { RS(DELTA_HUGE_SURPLUS),    TS(s_int)  },
+  { RS(DELTA_HUGE_TOTAL),      TS(s_int)  },
+  { RS(DELTA_INACTIVE),        TS(s_int)  },
+  { RS(DELTA_INACTIVE_ANON),   TS(s_int)  },
+  { RS(DELTA_INACTIVE_FILE),   TS(s_int)  },
+  { RS(DELTA_KERNEL_STACK),    TS(s_int)  },
+  { RS(DELTA_LOCKED),          TS(s_int)  },
+  { RS(DELTA_MAPPED),          TS(s_int)  },
+  { RS(DELTA_NFS_UNSTABLE),    TS(s_int)  },
+  { RS(DELTA_PAGE_TABLES),     TS(s_int)  },
+  { RS(DELTA_SHARED),          TS(s_int)  },
+  { RS(DELTA_SLAB),            TS(s_int)  },
+  { RS(DELTA_SLAB_RECLAIM),    TS(s_int)  },
+  { RS(DELTA_SLAB_UNRECLAIM),  TS(s_int)  },
+  { RS(DELTA_TOTAL),           TS(s_int)  },
+  { RS(DELTA_UNEVICTABLE),     TS(s_int)  },
+  { RS(DELTA_USED),            TS(s_int)  },
+  { RS(DELTA_VM_ALLOC_CHUNK),  TS(s_int)  },
+  { RS(DELTA_VM_ALLOC_TOTAL),  TS(s_int)  },
+  { RS(DELTA_VM_ALLOC_USED),   TS(s_int)  },
+  { RS(DELTA_WRITEBACK),       TS(s_int)  },
+  { RS(DELTA_WRITEBACK_TMP),   TS(s_int)  },
 
-  { RS(MEMHI_FREE)           },
-  { RS(MEMHI_TOTAL)          },
-  { RS(MEMHI_USED)           },
-  { RS(MEMLO_FREE)           },
-  { RS(MEMLO_TOTAL)          },
-  { RS(MEMLO_USED)           },
+  { RS(MEMHI_FREE),            TS(ul_int) },
+  { RS(MEMHI_TOTAL),           TS(ul_int) },
+  { RS(MEMHI_USED),            TS(ul_int) },
 
-  { RS(SWAP_CACHED)          },
-  { RS(SWAP_FREE)            },
-  { RS(SWAP_TOTAL)           },
-  { RS(SWAP_USED)            },
+  { RS(MEMLO_FREE),            TS(ul_int) },
+  { RS(MEMLO_TOTAL),           TS(ul_int) },
+  { RS(MEMLO_USED),            TS(ul_int) },
+
+  { RS(SWAP_CACHED),           TS(ul_int) },
+  { RS(SWAP_FREE),             TS(ul_int) },
+  { RS(SWAP_TOTAL),            TS(ul_int) },
+  { RS(SWAP_USED),             TS(ul_int) },
 
  // dummy entry corresponding to MEMINFO_logical_end ...
-  { NULL,                    }
+  { NULL,                      NULL       }
 };
 
     /* please note,
@@ -846,3 +851,56 @@ PROCPS_EXPORT struct meminfo_stack *procps_meminfo_select (
 
     return info->extents->stacks[0];
 } // end: procps_meminfo_select
+
+
+// --- special debugging function(s) ------------------------------------------
+/*
+ *  The following isn't part of the normal programming interface.  Rather,
+ *  it exists to validate result types referenced in application programs.
+ *
+ *  It's used only when:
+ *      1) the 'XTRA_PROCPS_DEBUG' has been defined, or
+ *      2) the '#include <proc/xtra-procps-debug.h>' used
+ */
+
+PROCPS_EXPORT struct meminfo_result *xtra_meminfo_get (
+        struct meminfo_info *info,
+        enum meminfo_item actual_enum,
+        const char *typestr,
+        const char *file,
+        int lineno)
+{
+    struct meminfo_result *r = procps_meminfo_get(info, actual_enum);
+
+    if (r) {
+        char *str = Item_table[r->item].type2str;
+        if (str[0]
+        && (strcmp(typestr, str)))
+            fprintf(stderr, "%s line %d: was %s, expected %s\n", file, lineno, typestr, str);
+    }
+    return r;
+} // end: xtra_meminfo_get_
+
+
+PROCPS_EXPORT void xtra_meminfo_val (
+        int relative_enum,
+        const char *typestr,
+        const struct meminfo_stack *stack,
+        struct meminfo_info *info,
+        const char *file,
+        int lineno)
+{
+    struct meminfo_result *r;
+    char *str;
+
+    r = &stack->head[relative_enum];
+    if (r->item < 0 || r->item >= MEMINFO_logical_end) {
+        fprintf(stderr, "%s line %d: invalid item = %d, relative_enum = %d, type = %s\n"
+            , file, lineno, r->item, relative_enum, typestr);
+        return;
+    }
+    str = Item_table[r->item].type2str;
+    if (str[0]
+    && (strcmp(typestr, str)))
+        fprintf(stderr, "%s line %d: was %s, expected %s\n", file, lineno, typestr, str);
+} // end: xtra_meminfo_val
diff --git a/proc/pids.c b/proc/pids.c
index 9260a8ca..f3c33939 100644
--- a/proc/pids.c
+++ b/proc/pids.c
@@ -369,6 +369,8 @@ typedef int  (*QSR_t)(const void *, const void *, void *);
 #define RS(e) (SET_t)setNAME(e)
 #define FF(t) (FRE_t)freNAME(t)
 #define QS(t) (QSR_t)srtNAME(t)
+#define TS(t) STRINGIFY(t)
+#define TS_noop ""
 
         /*
          * Need it be said?
@@ -380,134 +382,135 @@ static struct {
     FRE_t    freefunc;            // free function for strings storage
     QSR_t    sortfunc;            // sort cmp func for a specific type
     int      needhist;            // a result requires history support
+    char    *type2str;            // the result type as a string value
 } Item_table[] = {
-/*    setsfunc               oldflags    freefunc   sortfunc       needhist
-      ---------------------  ----------  ---------  -------------  -------- */
-    { RS(noop),              0,          NULL,      QS(noop),      0        }, // user only, never altered
-    { RS(extra),             0,          NULL,      QS(ull_int),   0        }, // user only, reset to zero
+/*    setsfunc               oldflags    freefunc   sortfunc       needhist  type2str
+      ---------------------  ----------  ---------  -------------  --------  ----------- */
+    { RS(noop),              0,          NULL,      QS(noop),      0,        TS_noop     }, // user only, never altered
+    { RS(extra),             0,          NULL,      QS(ull_int),   0,        TS_noop     }, // user only, reset to zero
 
-    { RS(ADDR_END_CODE),     f_stat,     NULL,      QS(ul_int),    0        },
-    { RS(ADDR_KSTK_EIP),     f_stat,     NULL,      QS(ul_int),    0        },
-    { RS(ADDR_KSTK_ESP),     f_stat,     NULL,      QS(ul_int),    0        },
-    { RS(ADDR_START_CODE),   f_stat,     NULL,      QS(ul_int),    0        },
-    { RS(ADDR_START_STACK),  f_stat,     NULL,      QS(ul_int),    0        },
-    { RS(ALARM),             f_stat,     NULL,      QS(ul_int),    0        },
-    { RS(CGNAME),            x_cgroup,   FF(str),   QS(str),       0        },
-    { RS(CGROUP),            x_cgroup,   FF(str),   QS(str),       0        },
-    { RS(CGROUP_V),          v_cgroup,   FF(strv),  QS(strv),      0        },
-    { RS(CMD),               f_either,   FF(str),   QS(str),       0        },
-    { RS(CMDLINE),           x_cmdline,  FF(str),   QS(str),       0        },
-    { RS(CMDLINE_V),         v_arg,      FF(strv),  QS(strv),      0        },
-    { RS(ENVIRON),           x_environ,  FF(str),   QS(str),       0        },
-    { RS(ENVIRON_V),         v_env,      FF(strv),  QS(strv),      0        },
-    { RS(EXIT_SIGNAL),       f_stat,     NULL,      QS(s_int),     0        },
-    { RS(FLAGS),             f_stat,     NULL,      QS(ul_int),    0        },
-    { RS(FLT_MAJ),           f_stat,     NULL,      QS(ul_int),    0        },
-    { RS(FLT_MAJ_C),         f_stat,     NULL,      QS(ul_int),    0        },
-    { RS(FLT_MAJ_DELTA),     f_stat,     NULL,      QS(s_int),     +1       },
-    { RS(FLT_MIN),           f_stat,     NULL,      QS(ul_int),    0        },
-    { RS(FLT_MIN_C),         f_stat,     NULL,      QS(ul_int),    0        },
-    { RS(FLT_MIN_DELTA),     f_stat,     NULL,      QS(s_int),     +1       },
-    { RS(ID_EGID),           0,          NULL,      QS(u_int),     0        }, // oldflags: free w/ simple_read
-    { RS(ID_EGROUP),         f_grp,      NULL,      QS(str),       0        },
-    { RS(ID_EUID),           0,          NULL,      QS(u_int),     0        }, // oldflags: free w/ simple_read
-    { RS(ID_EUSER),          f_usr,      NULL,      QS(str),       0        }, // freefunc NULL w/ cached string
-    { RS(ID_FGID),           f_status,   NULL,      QS(u_int),     0        },
-    { RS(ID_FGROUP),         x_ogroup,   NULL,      QS(str),       0        },
-    { RS(ID_FUID),           f_status,   NULL,      QS(u_int),     0        },
-    { RS(ID_FUSER),          x_ouser,    NULL,      QS(str),       0        }, // freefunc NULL w/ cached string
-    { RS(ID_PGRP),           f_stat,     NULL,      QS(s_int),     0        },
-    { RS(ID_PID),            0,          NULL,      QS(s_int),     0        }, // oldflags: free w/ simple_nextpid
-    { RS(ID_PPID),           f_either,   NULL,      QS(s_int),     0        },
-    { RS(ID_RGID),           f_status,   NULL,      QS(u_int),     0        },
-    { RS(ID_RGROUP),         x_ogroup,   NULL,      QS(str),       0        },
-    { RS(ID_RUID),           f_status,   NULL,      QS(u_int),     0        },
-    { RS(ID_RUSER),          x_ouser,    NULL,      QS(str),       0        }, // freefunc NULL w/ cached string
-    { RS(ID_SESSION),        f_stat,     NULL,      QS(s_int),     0        },
-    { RS(ID_SGID),           f_status,   NULL,      QS(u_int),     0        },
-    { RS(ID_SGROUP),         x_ogroup,   NULL,      QS(str),       0        },
-    { RS(ID_SUID),           f_status,   NULL,      QS(u_int),     0        },
-    { RS(ID_SUSER),          x_ouser,    NULL,      QS(str),       0        }, // freefunc NULL w/ cached string
-    { RS(ID_TGID),           0,          NULL,      QS(s_int),     0        }, // oldflags: free w/ simple_nextpid
-    { RS(ID_TPGID),          f_stat,     NULL,      QS(s_int),     0        },
-    { RS(LXCNAME),           f_lxc,      NULL,      QS(str),       0        }, // freefunc NULL w/ cached string
-    { RS(MEM_CODE),          f_statm,    NULL,      QS(ul_int),    0        },
-    { RS(MEM_CODE_PGS),      f_statm,    NULL,      QS(ul_int),    0        },
-    { RS(MEM_DATA),          f_statm,    NULL,      QS(ul_int),    0        },
-    { RS(MEM_DATA_PGS),      f_statm,    NULL,      QS(ul_int),    0        },
-    { RS(MEM_DT_PGS),        f_statm,    NULL,      QS(ul_int),    0        },  // ( always 0 w/ since 2.6 )
-    { RS(MEM_LRS_PGS),       f_statm,    NULL,      QS(ul_int),    0        },
-    { RS(MEM_RES),           f_statm,    NULL,      QS(ul_int),    0        },
-    { RS(MEM_RES_PGS),       f_statm,    NULL,      QS(ul_int),    0        },
-    { RS(MEM_SHR),           f_statm,    NULL,      QS(ul_int),    0        },
-    { RS(MEM_SHR_PGS),       f_statm,    NULL,      QS(ul_int),    0        },
-    { RS(MEM_VIRT),          f_statm,    NULL,      QS(ul_int),    0        },
-    { RS(MEM_VIRT_PGS),      f_statm,    NULL,      QS(ul_int),    0        },
-    { RS(NICE),              f_stat,     NULL,      QS(s_int),     0        },
-    { RS(NLWP),              f_either,   NULL,      QS(s_int),     0        },
-    { RS(NS_IPC),            f_ns,       NULL,      QS(ul_int),    0        },
-    { RS(NS_MNT),            f_ns,       NULL,      QS(ul_int),    0        },
-    { RS(NS_NET),            f_ns,       NULL,      QS(ul_int),    0        },
-    { RS(NS_PID),            f_ns,       NULL,      QS(ul_int),    0        },
-    { RS(NS_USER),           f_ns,       NULL,      QS(ul_int),    0        },
-    { RS(NS_UTS),            f_ns,       NULL,      QS(ul_int),    0        },
-    { RS(OOM_ADJ),           f_oom,      NULL,      QS(s_int),     0        },
-    { RS(OOM_SCORE),         f_oom,      NULL,      QS(s_int),     0        },
-    { RS(PRIORITY),          f_stat,     NULL,      QS(s_int),     0        },
-    { RS(PROCESSOR),         f_stat,     NULL,      QS(u_int),     0        },
-    { RS(RSS),               f_stat,     NULL,      QS(ul_int),    0        },
-    { RS(RSS_RLIM),          f_stat,     NULL,      QS(ul_int),    0        },
-    { RS(RTPRIO),            f_stat,     NULL,      QS(s_int),     0        },
-    { RS(SCHED_CLASS),       f_stat,     NULL,      QS(s_int),     0        },
-    { RS(SD_MACH),           f_systemd,  FF(str),   QS(str),       0        },
-    { RS(SD_OUID),           f_systemd,  FF(str),   QS(str),       0        },
-    { RS(SD_SEAT),           f_systemd,  FF(str),   QS(str),       0        },
-    { RS(SD_SESS),           f_systemd,  FF(str),   QS(str),       0        },
-    { RS(SD_SLICE),          f_systemd,  FF(str),   QS(str),       0        },
-    { RS(SD_UNIT),           f_systemd,  FF(str),   QS(str),       0        },
-    { RS(SD_UUNIT),          f_systemd,  FF(str),   QS(str),       0        },
-    { RS(SIGBLOCKED),        f_status,   FF(str),   QS(str),       0        },
-    { RS(SIGCATCH),          f_status,   FF(str),   QS(str),       0        },
-    { RS(SIGIGNORE),         f_status,   FF(str),   QS(str),       0        },
-    { RS(SIGNALS),           f_status,   FF(str),   QS(str),       0        },
-    { RS(SIGPENDING),        f_status,   FF(str),   QS(str),       0        },
-    { RS(STATE),             f_either,   NULL,      QS(s_ch),      0        },
-    { RS(SUPGIDS),           f_status,   FF(str),   QS(str),       0        },
-    { RS(SUPGROUPS),         x_supgrp,   FF(str),   QS(str),       0        },
-    { RS(TICS_ALL),          f_stat,     NULL,      QS(ull_int),   0        },
-    { RS(TICS_ALL_C),        f_stat,     NULL,      QS(ull_int),   0        },
-    { RS(TICS_ALL_DELTA),    f_stat,     NULL,      QS(s_int),     +1       },
-    { RS(TICS_BLKIO),        f_stat,     NULL,      QS(ull_int),   0        },
-    { RS(TICS_GUEST),        f_stat,     NULL,      QS(ull_int),   0        },
-    { RS(TICS_GUEST_C),      f_stat,     NULL,      QS(ull_int),   0        },
-    { RS(TICS_SYSTEM),       f_stat,     NULL,      QS(ull_int),   0        },
-    { RS(TICS_SYSTEM_C),     f_stat,     NULL,      QS(ull_int),   0        },
-    { RS(TICS_USER),         f_stat,     NULL,      QS(ull_int),   0        },
-    { RS(TICS_USER_C),       f_stat,     NULL,      QS(ull_int),   0        },
-    { RS(TIME_ALL),          f_stat,     NULL,      QS(ull_int),   0        },
-    { RS(TIME_ELAPSED),      f_stat,     NULL,      QS(ull_int),   0        },
-    { RS(TIME_START),        f_stat,     NULL,      QS(ull_int),   0        },
-    { RS(TTY),               f_stat,     NULL,      QS(s_int),     0        },
-    { RS(TTY_NAME),          f_stat,     FF(str),   QS(strvers),   0        },
-    { RS(TTY_NUMBER),        f_stat,     FF(str),   QS(strvers),   0        },
-    { RS(VM_DATA),           f_status,   NULL,      QS(ul_int),    0        },
-    { RS(VM_EXE),            f_status,   NULL,      QS(ul_int),    0        },
-    { RS(VM_LIB),            f_status,   NULL,      QS(ul_int),    0        },
-    { RS(VM_RSS),            f_status,   NULL,      QS(ul_int),    0        },
-    { RS(VM_RSS_ANON),       f_status,   NULL,      QS(ul_int),    0        },
-    { RS(VM_RSS_FILE),       f_status,   NULL,      QS(ul_int),    0        },
-    { RS(VM_RSS_LOCKED),     f_status,   NULL,      QS(ul_int),    0        },
-    { RS(VM_RSS_SHARED),     f_status,   NULL,      QS(ul_int),    0        },
-    { RS(VM_SIZE),           f_status,   NULL,      QS(ul_int),    0        },
-    { RS(VM_STACK),          f_status,   NULL,      QS(ul_int),    0        },
-    { RS(VM_SWAP),           f_status,   NULL,      QS(ul_int),    0        },
-    { RS(VM_USED),           f_status,   NULL,      QS(ul_int),    0        },
-    { RS(VSIZE_PGS),         f_stat,     NULL,      QS(ul_int),    0        },
-    { RS(WCHAN_ADDR),        0,          NULL,      QS(ul_int),    0        }, // oldflags: was f_stat, but linux obsoleted
-    { RS(WCHAN_NAME),        0,          FF(str),   QS(str),       0        }, // oldflags: tid already free
+    { RS(ADDR_END_CODE),     f_stat,     NULL,      QS(ul_int),    0,        TS(ul_int)  },
+    { RS(ADDR_KSTK_EIP),     f_stat,     NULL,      QS(ul_int),    0,        TS(ul_int)  },
+    { RS(ADDR_KSTK_ESP),     f_stat,     NULL,      QS(ul_int),    0,        TS(ul_int)  },
+    { RS(ADDR_START_CODE),   f_stat,     NULL,      QS(ul_int),    0,        TS(ul_int)  },
+    { RS(ADDR_START_STACK),  f_stat,     NULL,      QS(ul_int),    0,        TS(ul_int)  },
+    { RS(ALARM),             f_stat,     NULL,      QS(ul_int),    0,        TS(ul_int)  },
+    { RS(CGNAME),            x_cgroup,   FF(str),   QS(str),       0,        TS(str)     },
+    { RS(CGROUP),            x_cgroup,   FF(str),   QS(str),       0,        TS(str)     },
+    { RS(CGROUP_V),          v_cgroup,   FF(strv),  QS(strv),      0,        TS(strv)    },
+    { RS(CMD),               f_either,   FF(str),   QS(str),       0,        TS(str)     },
+    { RS(CMDLINE),           x_cmdline,  FF(str),   QS(str),       0,        TS(str)     },
+    { RS(CMDLINE_V),         v_arg,      FF(strv),  QS(strv),      0,        TS(strv)    },
+    { RS(ENVIRON),           x_environ,  FF(str),   QS(str),       0,        TS(str)     },
+    { RS(ENVIRON_V),         v_env,      FF(strv),  QS(strv),      0,        TS(strv)    },
+    { RS(EXIT_SIGNAL),       f_stat,     NULL,      QS(s_int),     0,        TS(s_int)   },
+    { RS(FLAGS),             f_stat,     NULL,      QS(ul_int),    0,        TS(ul_int)  },
+    { RS(FLT_MAJ),           f_stat,     NULL,      QS(ul_int),    0,        TS(ul_int)  },
+    { RS(FLT_MAJ_C),         f_stat,     NULL,      QS(ul_int),    0,        TS(ul_int)  },
+    { RS(FLT_MAJ_DELTA),     f_stat,     NULL,      QS(s_int),     +1,       TS(s_int)   },
+    { RS(FLT_MIN),           f_stat,     NULL,      QS(ul_int),    0,        TS(ul_int)  },
+    { RS(FLT_MIN_C),         f_stat,     NULL,      QS(ul_int),    0,        TS(ul_int)  },
+    { RS(FLT_MIN_DELTA),     f_stat,     NULL,      QS(s_int),     +1,       TS(s_int)   },
+    { RS(ID_EGID),           0,          NULL,      QS(u_int),     0,        TS(u_int)   }, // oldflags: free w/ simple_read
+    { RS(ID_EGROUP),         f_grp,      NULL,      QS(str),       0,        TS(str)     },
+    { RS(ID_EUID),           0,          NULL,      QS(u_int),     0,        TS(u_int)   }, // oldflags: free w/ simple_read
+    { RS(ID_EUSER),          f_usr,      NULL,      QS(str),       0,        TS(str)     }, // freefunc NULL w/ cached string
+    { RS(ID_FGID),           f_status,   NULL,      QS(u_int),     0,        TS(u_int)   },
+    { RS(ID_FGROUP),         x_ogroup,   NULL,      QS(str),       0,        TS(str)     },
+    { RS(ID_FUID),           f_status,   NULL,      QS(u_int),     0,        TS(u_int)   },
+    { RS(ID_FUSER),          x_ouser,    NULL,      QS(str),       0,        TS(str)     }, // freefunc NULL w/ cached string
+    { RS(ID_PGRP),           f_stat,     NULL,      QS(s_int),     0,        TS(s_int)   },
+    { RS(ID_PID),            0,          NULL,      QS(s_int),     0,        TS(s_int)   }, // oldflags: free w/ simple_nextpid
+    { RS(ID_PPID),           f_either,   NULL,      QS(s_int),     0,        TS(s_int)   },
+    { RS(ID_RGID),           f_status,   NULL,      QS(u_int),     0,        TS(u_int)   },
+    { RS(ID_RGROUP),         x_ogroup,   NULL,      QS(str),       0,        TS(str)     },
+    { RS(ID_RUID),           f_status,   NULL,      QS(u_int),     0,        TS(u_int)   },
+    { RS(ID_RUSER),          x_ouser,    NULL,      QS(str),       0,        TS(str)     }, // freefunc NULL w/ cached string
+    { RS(ID_SESSION),        f_stat,     NULL,      QS(s_int),     0,        TS(s_int)   },
+    { RS(ID_SGID),           f_status,   NULL,      QS(u_int),     0,        TS(u_int)   },
+    { RS(ID_SGROUP),         x_ogroup,   NULL,      QS(str),       0,        TS(str)     },
+    { RS(ID_SUID),           f_status,   NULL,      QS(u_int),     0,        TS(u_int)   },
+    { RS(ID_SUSER),          x_ouser,    NULL,      QS(str),       0,        TS(str)     }, // freefunc NULL w/ cached string
+    { RS(ID_TGID),           0,          NULL,      QS(s_int),     0,        TS(s_int)   }, // oldflags: free w/ simple_nextpid
+    { RS(ID_TPGID),          f_stat,     NULL,      QS(s_int),     0,        TS(s_int)   },
+    { RS(LXCNAME),           f_lxc,      NULL,      QS(str),       0,        TS(str)     }, // freefunc NULL w/ cached string
+    { RS(MEM_CODE),          f_statm,    NULL,      QS(ul_int),    0,        TS(ul_int)  },
+    { RS(MEM_CODE_PGS),      f_statm,    NULL,      QS(ul_int),    0,        TS(ul_int)  },
+    { RS(MEM_DATA),          f_statm,    NULL,      QS(ul_int),    0,        TS(ul_int)  },
+    { RS(MEM_DATA_PGS),      f_statm,    NULL,      QS(ul_int),    0,        TS(ul_int)  },
+    { RS(MEM_DT_PGS),        f_statm,    NULL,      QS(ul_int),    0,        TS(ul_int)  },  // ( always 0 w/ since 2.6 )
+    { RS(MEM_LRS_PGS),       f_statm,    NULL,      QS(ul_int),    0,        TS(ul_int)  },
+    { RS(MEM_RES),           f_statm,    NULL,      QS(ul_int),    0,        TS(ul_int)  },
+    { RS(MEM_RES_PGS),       f_statm,    NULL,      QS(ul_int),    0,        TS(ul_int)  },
+    { RS(MEM_SHR),           f_statm,    NULL,      QS(ul_int),    0,        TS(ul_int)  },
+    { RS(MEM_SHR_PGS),       f_statm,    NULL,      QS(ul_int),    0,        TS(ul_int)  },
+    { RS(MEM_VIRT),          f_statm,    NULL,      QS(ul_int),    0,        TS(ul_int)  },
+    { RS(MEM_VIRT_PGS),      f_statm,    NULL,      QS(ul_int),    0,        TS(ul_int)  },
+    { RS(NICE),              f_stat,     NULL,      QS(s_int),     0,        TS(s_int)   },
+    { RS(NLWP),              f_either,   NULL,      QS(s_int),     0,        TS(s_int)   },
+    { RS(NS_IPC),            f_ns,       NULL,      QS(ul_int),    0,        TS(ul_int)  },
+    { RS(NS_MNT),            f_ns,       NULL,      QS(ul_int),    0,        TS(ul_int)  },
+    { RS(NS_NET),            f_ns,       NULL,      QS(ul_int),    0,        TS(ul_int)  },
+    { RS(NS_PID),            f_ns,       NULL,      QS(ul_int),    0,        TS(ul_int)  },
+    { RS(NS_USER),           f_ns,       NULL,      QS(ul_int),    0,        TS(ul_int)  },
+    { RS(NS_UTS),            f_ns,       NULL,      QS(ul_int),    0,        TS(ul_int)  },
+    { RS(OOM_ADJ),           f_oom,      NULL,      QS(s_int),     0,        TS(s_int)   },
+    { RS(OOM_SCORE),         f_oom,      NULL,      QS(s_int),     0,        TS(s_int)   },
+    { RS(PRIORITY),          f_stat,     NULL,      QS(s_int),     0,        TS(s_int)   },
+    { RS(PROCESSOR),         f_stat,     NULL,      QS(u_int),     0,        TS(u_int)   },
+    { RS(RSS),               f_stat,     NULL,      QS(ul_int),    0,        TS(ul_int)  },
+    { RS(RSS_RLIM),          f_stat,     NULL,      QS(ul_int),    0,        TS(ul_int)  },
+    { RS(RTPRIO),            f_stat,     NULL,      QS(s_int),     0,        TS(s_int)   },
+    { RS(SCHED_CLASS),       f_stat,     NULL,      QS(s_int),     0,        TS(s_int)   },
+    { RS(SD_MACH),           f_systemd,  FF(str),   QS(str),       0,        TS(str)     },
+    { RS(SD_OUID),           f_systemd,  FF(str),   QS(str),       0,        TS(str)     },
+    { RS(SD_SEAT),           f_systemd,  FF(str),   QS(str),       0,        TS(str)     },
+    { RS(SD_SESS),           f_systemd,  FF(str),   QS(str),       0,        TS(str)     },
+    { RS(SD_SLICE),          f_systemd,  FF(str),   QS(str),       0,        TS(str)     },
+    { RS(SD_UNIT),           f_systemd,  FF(str),   QS(str),       0,        TS(str)     },
+    { RS(SD_UUNIT),          f_systemd,  FF(str),   QS(str),       0,        TS(str)     },
+    { RS(SIGBLOCKED),        f_status,   FF(str),   QS(str),       0,        TS(str)     },
+    { RS(SIGCATCH),          f_status,   FF(str),   QS(str),       0,        TS(str)     },
+    { RS(SIGIGNORE),         f_status,   FF(str),   QS(str),       0,        TS(str)     },
+    { RS(SIGNALS),           f_status,   FF(str),   QS(str),       0,        TS(str)     },
+    { RS(SIGPENDING),        f_status,   FF(str),   QS(str),       0,        TS(str)     },
+    { RS(STATE),             f_either,   NULL,      QS(s_ch),      0,        TS(s_ch)    },
+    { RS(SUPGIDS),           f_status,   FF(str),   QS(str),       0,        TS(str)     },
+    { RS(SUPGROUPS),         x_supgrp,   FF(str),   QS(str),       0,        TS(str)     },
+    { RS(TICS_ALL),          f_stat,     NULL,      QS(ull_int),   0,        TS(ull_int) },
+    { RS(TICS_ALL_C),        f_stat,     NULL,      QS(ull_int),   0,        TS(ull_int) },
+    { RS(TICS_ALL_DELTA),    f_stat,     NULL,      QS(s_int),     +1,       TS(s_int)   },
+    { RS(TICS_BLKIO),        f_stat,     NULL,      QS(ull_int),   0,        TS(ull_int) },
+    { RS(TICS_GUEST),        f_stat,     NULL,      QS(ull_int),   0,        TS(ull_int) },
+    { RS(TICS_GUEST_C),      f_stat,     NULL,      QS(ull_int),   0,        TS(ull_int) },
+    { RS(TICS_SYSTEM),       f_stat,     NULL,      QS(ull_int),   0,        TS(ull_int) },
+    { RS(TICS_SYSTEM_C),     f_stat,     NULL,      QS(ull_int),   0,        TS(ull_int) },
+    { RS(TICS_USER),         f_stat,     NULL,      QS(ull_int),   0,        TS(ull_int) },
+    { RS(TICS_USER_C),       f_stat,     NULL,      QS(ull_int),   0,        TS(ull_int) },
+    { RS(TIME_ALL),          f_stat,     NULL,      QS(ull_int),   0,        TS(ull_int) },
+    { RS(TIME_ELAPSED),      f_stat,     NULL,      QS(ull_int),   0,        TS(ull_int) },
+    { RS(TIME_START),        f_stat,     NULL,      QS(ull_int),   0,        TS(ull_int) },
+    { RS(TTY),               f_stat,     NULL,      QS(s_int),     0,        TS(s_int)   },
+    { RS(TTY_NAME),          f_stat,     FF(str),   QS(strvers),   0,        TS(str)     },
+    { RS(TTY_NUMBER),        f_stat,     FF(str),   QS(strvers),   0,        TS(str)     },
+    { RS(VM_DATA),           f_status,   NULL,      QS(ul_int),    0,        TS(ul_int)  },
+    { RS(VM_EXE),            f_status,   NULL,      QS(ul_int),    0,        TS(ul_int)  },
+    { RS(VM_LIB),            f_status,   NULL,      QS(ul_int),    0,        TS(ul_int)  },
+    { RS(VM_RSS),            f_status,   NULL,      QS(ul_int),    0,        TS(ul_int)  },
+    { RS(VM_RSS_ANON),       f_status,   NULL,      QS(ul_int),    0,        TS(ul_int)  },
+    { RS(VM_RSS_FILE),       f_status,   NULL,      QS(ul_int),    0,        TS(ul_int)  },
+    { RS(VM_RSS_LOCKED),     f_status,   NULL,      QS(ul_int),    0,        TS(ul_int)  },
+    { RS(VM_RSS_SHARED),     f_status,   NULL,      QS(ul_int),    0,        TS(ul_int)  },
+    { RS(VM_SIZE),           f_status,   NULL,      QS(ul_int),    0,        TS(ul_int)  },
+    { RS(VM_STACK),          f_status,   NULL,      QS(ul_int),    0,        TS(ul_int)  },
+    { RS(VM_SWAP),           f_status,   NULL,      QS(ul_int),    0,        TS(ul_int)  },
+    { RS(VM_USED),           f_status,   NULL,      QS(ul_int),    0,        TS(ul_int)  },
+    { RS(VSIZE_PGS),         f_stat,     NULL,      QS(ul_int),    0,        TS(ul_int)  },
+    { RS(WCHAN_ADDR),        0,          NULL,      QS(ul_int),    0,        TS(ul_int)  }, // oldflags: was f_stat, but linux obsoleted
+    { RS(WCHAN_NAME),        0,          FF(str),   QS(str),       0,        TS(str)     }, // oldflags: tid already free
 
    // dummy entry corresponding to PIDS_logical_end ...
-    { NULL,                  0,          NULL,      NULL,          0        }
+    { NULL,                  0,          NULL,      NULL,          0,        NULL        }
 };
 
     /* please note,
@@ -1488,3 +1491,37 @@ PROCPS_EXPORT struct pids_stack **procps_pids_sort (
     qsort_r(stacks, numstacked, sizeof(void *), (QSR_t)Item_table[p->item].sortfunc, &parms);
     return stacks;
 } // end: procps_pids_sort
+
+
+// --- special debugging function(s) ------------------------------------------
+/*
+ *  The following isn't part of the normal programming interface.  Rather,
+ *  it exists to validate result types referenced in application programs.
+ *
+ *  It's used only when:
+ *      1) the 'XTRA_PROCPS_DEBUG' has been defined, or
+ *      2) the '#include <proc/xtra-procps-debug.h>' used
+ */
+
+PROCPS_EXPORT void xtra_pids_val (
+        int relative_enum,
+        const char *typestr,
+        const struct pids_stack *stack,
+        struct pids_info *info,
+        const char *file,
+        int lineno)
+{
+    struct pids_result *r;
+    char *str;
+
+    r = &stack->head[relative_enum];
+    if (r->item < 0 || r->item >= PIDS_logical_end) {
+        fprintf(stderr, "%s line %d: invalid item = %d, relative_enum = %d, type = %s\n"
+            , file, lineno, r->item, relative_enum, typestr);
+        return;
+    }
+    str = Item_table[r->item].type2str;
+    if (str[0]
+    && (strcmp(typestr, str)))
+        fprintf(stderr, "%s line %d: was %s, expected %s\n", file, lineno, typestr, str);
+} // end: xtra_pids_val
diff --git a/proc/procps.h b/proc/procps.h
index 53033e98..0b8da284 100644
--- a/proc/procps.h
+++ b/proc/procps.h
@@ -34,4 +34,8 @@
 #define ESC_STRETCH 1  // since we mangle to '?' this is 1 (would be 4 for octal escapes)
 int escape_str(char *__restrict dst, const char *__restrict src, int bufsize, int *maxcells);
 
+#ifdef XTRA_PROCPS_DEBUG
+#include <proc/xtra-procps-debug.h>
+#endif
+
 #endif
diff --git a/proc/slabinfo.c b/proc/slabinfo.c
index b603ac1f..985b5075 100644
--- a/proc/slabinfo.c
+++ b/proc/slabinfo.c
@@ -241,6 +241,9 @@ typedef void (*SET_t)(struct slabinfo_result *, struct slabs_hist *, struct slab
 typedef int  (*QSR_t)(const void *, const void *, void *);
 #define QS(t) (QSR_t)srtNAME(t)
 
+#define TS(t) STRINGIFY(t)
+#define TS_noop ""
+
         /*
          * Need it be said?
          * This table must be kept in the exact same order as
@@ -248,51 +251,52 @@ typedef int  (*QSR_t)(const void *, const void *, void *);
 static struct {
     SET_t setsfunc;              // the actual result setting routine
     QSR_t sortfunc;              // sort cmp func for a specific type
+    char *type2str;              // the result type as a string value
 } Item_table[] = {
-/*  setsfunc                     sortfunc
-    ---------------------------  ---------  */
-  { RS(noop),                    QS(ul_int) },
-  { RS(extra),                   QS(noop)   },
+/*  setsfunc                      sortfunc   type2str
+    ----------------------------  -----------  ---------- */
+  { RS(noop),                     QS(noop),    TS_noop    },
+  { RS(extra),                    QS(ul_int),  TS_noop    },
 
-  { RS(SLABS_OBJS),              QS(noop)   },
-  { RS(SLABS_AOBJS),             QS(noop)   },
-  { RS(SLABS_PAGES),             QS(noop)   },
-  { RS(SLABS_SLABS),             QS(noop)   },
-  { RS(SLABS_ASLABS),            QS(noop)   },
-  { RS(SLABS_CACHES),            QS(noop)   },
-  { RS(SLABS_ACACHES),           QS(noop)   },
-  { RS(SLABS_SIZE_AVG),          QS(noop)   },
-  { RS(SLABS_SIZE_MIN),          QS(noop)   },
-  { RS(SLABS_SIZE_MAX),          QS(noop)   },
-  { RS(SLABS_SIZE_ACTIVE),       QS(noop)   },
-  { RS(SLABS_SIZE_TOTAL),        QS(noop)   },
+  { RS(SLABS_OBJS),               QS(noop),    TS(u_int)  },
+  { RS(SLABS_AOBJS),              QS(noop),    TS(u_int)  },
+  { RS(SLABS_PAGES),              QS(noop),    TS(u_int)  },
+  { RS(SLABS_SLABS),              QS(noop),    TS(u_int)  },
+  { RS(SLABS_ASLABS),             QS(noop),    TS(u_int)  },
+  { RS(SLABS_CACHES),             QS(noop),    TS(u_int)  },
+  { RS(SLABS_ACACHES),            QS(noop),    TS(u_int)  },
+  { RS(SLABS_SIZE_AVG),           QS(noop),    TS(u_int)  },
+  { RS(SLABS_SIZE_MIN),           QS(noop),    TS(u_int)  },
+  { RS(SLABS_SIZE_MAX),           QS(noop),    TS(u_int)  },
+  { RS(SLABS_SIZE_ACTIVE),        QS(noop),    TS(ul_int) },
+  { RS(SLABS_SIZE_TOTAL),         QS(noop),    TS(ul_int) },
 
-  { RS(SLABS_DELTA_OBJS),        QS(noop)   },
-  { RS(SLABS_DELTA_AOBJS),       QS(noop)   },
-  { RS(SLABS_DELTA_PAGES),       QS(noop)   },
-  { RS(SLABS_DELTA_SLABS),       QS(noop)   },
-  { RS(SLABS_DELTA_ASLABS),      QS(noop)   },
-  { RS(SLABS_DELTA_CACHES),      QS(noop)   },
-  { RS(SLABS_DELTA_ACACHES),     QS(noop)   },
-  { RS(SLABS_DELTA_SIZE_AVG),    QS(noop)   },
-  { RS(SLABS_DELTA_SIZE_MIN),    QS(noop)   },
-  { RS(SLABS_DELTA_SIZE_MAX),    QS(noop)   },
-  { RS(SLABS_DELTA_SIZE_ACTIVE), QS(noop)   },
-  { RS(SLABS_DELTA_SIZE_TOTAL),  QS(noop)   },
+  { RS(SLABS_DELTA_OBJS),         QS(noop),    TS(s_int)  },
+  { RS(SLABS_DELTA_AOBJS),        QS(noop),    TS(s_int)  },
+  { RS(SLABS_DELTA_PAGES),        QS(noop),    TS(s_int)  },
+  { RS(SLABS_DELTA_SLABS),        QS(noop),    TS(s_int)  },
+  { RS(SLABS_DELTA_ASLABS),       QS(noop),    TS(s_int)  },
+  { RS(SLABS_DELTA_CACHES),       QS(noop),    TS(s_int)  },
+  { RS(SLABS_DELTA_ACACHES),      QS(noop),    TS(s_int)  },
+  { RS(SLABS_DELTA_SIZE_AVG),     QS(noop),    TS(s_int)  },
+  { RS(SLABS_DELTA_SIZE_MIN),     QS(noop),    TS(s_int)  },
+  { RS(SLABS_DELTA_SIZE_MAX),     QS(noop),    TS(s_int)  },
+  { RS(SLABS_DELTA_SIZE_ACTIVE),  QS(noop),    TS(s_int)  },
+  { RS(SLABS_DELTA_SIZE_TOTAL),   QS(noop),    TS(s_int)  },
 
-  { RS(SLABNODE_NAME),           QS(str)    },
-  { RS(SLABNODE_OBJS),           QS(u_int)  },
-  { RS(SLABNODE_AOBJS),          QS(u_int)  },
-  { RS(SLABNODE_OBJ_SIZE),       QS(u_int)  },
-  { RS(SLABNODE_OBJS_PER_SLAB),  QS(u_int)  },
-  { RS(SLABNODE_PAGES_PER_SLAB), QS(u_int)  },
-  { RS(SLABNODE_SLABS),          QS(u_int)  },
-  { RS(SLABNODE_ASLABS),         QS(u_int)  },
-  { RS(SLABNODE_USE),            QS(u_int)  },
-  { RS(SLABNODE_SIZE),           QS(ul_int) },
+  { RS(SLABNODE_NAME),            QS(str),     TS(str)    },
+  { RS(SLABNODE_OBJS),            QS(u_int),   TS(u_int)  },
+  { RS(SLABNODE_AOBJS),           QS(u_int),   TS(u_int)  },
+  { RS(SLABNODE_OBJ_SIZE),        QS(u_int),   TS(u_int)  },
+  { RS(SLABNODE_OBJS_PER_SLAB),   QS(u_int),   TS(u_int)  },
+  { RS(SLABNODE_PAGES_PER_SLAB),  QS(u_int),   TS(u_int)  },
+  { RS(SLABNODE_SLABS),           QS(u_int),   TS(u_int)  },
+  { RS(SLABNODE_ASLABS),          QS(u_int),   TS(u_int)  },
+  { RS(SLABNODE_USE),             QS(u_int),   TS(u_int)  },
+  { RS(SLABNODE_SIZE),            QS(ul_int),  TS(ul_int) },
 
  // dummy entry corresponding to SLABINFO_logical_end ...
-  { NULL,                        NULL       }
+  { NULL,                         NULL,        NULL       }
 };
 
     /* please note,
@@ -1004,3 +1008,56 @@ PROCPS_EXPORT struct slabinfo_stack **procps_slabinfo_sort (
     qsort_r(stacks, numstacked, sizeof(void *), (QSR_t)Item_table[p->item].sortfunc, &parms);
     return stacks;
 } // end: procps_slabinfo_sort
+
+
+// --- special debugging function(s) ------------------------------------------
+/*
+ *  The following isn't part of the normal programming interface.  Rather,
+ *  it exists to validate result types referenced in application programs.
+ *
+ *  It's used only when:
+ *      1) the 'XTRA_PROCPS_DEBUG' has been defined, or
+ *      2) the '#include <proc/xtra-procps-debug.h>' used
+ */
+
+PROCPS_EXPORT struct slabinfo_result *xtra_slabinfo_get (
+        struct slabinfo_info *info,
+        enum slabinfo_item actual_enum,
+        const char *typestr,
+        const char *file,
+        int lineno)
+{
+    struct slabinfo_result *r = procps_slabinfo_get(info, actual_enum);
+
+    if (r) {
+        char *str = Item_table[r->item].type2str;
+        if (str[0]
+        && (strcmp(typestr, str)))
+            fprintf(stderr, "%s line %d: was %s, expected %s\n", file, lineno, typestr, str);
+    }
+    return r;
+} // end: xtra_slabinfo_get_
+
+
+PROCPS_EXPORT void xtra_slabinfo_val (
+        int relative_enum,
+        const char *typestr,
+        const struct slabinfo_stack *stack,
+        struct slabinfo_info *info,
+        const char *file,
+        int lineno)
+{
+    struct slabinfo_result *r;
+    char *str;
+
+    r = &stack->head[relative_enum];
+    if (r->item < 0 || r->item >= SLABINFO_logical_end) {
+        fprintf(stderr, "%s line %d: invalid item = %d, relative_enum = %d, type = %s\n"
+            , file, lineno, r->item, relative_enum, typestr);
+        return;
+    }
+    str = Item_table[r->item].type2str;
+    if (str[0]
+    && (strcmp(typestr, str)))
+        fprintf(stderr, "%s line %d: was %s, expected %s\n", file, lineno, typestr, str);
+} // end: xtra_slabinfo_val
diff --git a/proc/stat.c b/proc/stat.c
index 653e22f9..003c1e53 100644
--- a/proc/stat.c
+++ b/proc/stat.c
@@ -255,6 +255,9 @@ typedef void (*SET_t)(struct stat_result *, struct hist_sys *, struct hist_tic *
 typedef int  (*QSR_t)(const void *, const void *, void *);
 #define QS(t) (QSR_t)srtNAME(t)
 
+#define TS(t) STRINGIFY(t)
+#define TS_noop ""
+
         /*
          * Need it be said?
          * This table must be kept in the exact same order as
@@ -262,51 +265,52 @@ typedef int  (*QSR_t)(const void *, const void *, void *);
 static struct {
     SET_t setsfunc;              // the actual result setting routine
     QSR_t sortfunc;              // sort cmp func for a specific type
+    char *type2str;              // the result type as a string value
 } Item_table[] = {
-/*  setsfunc                     sortfunc
-    --------------------------   ---------  */
-  { RS(noop),                    QS(ul_int)  },
-  { RS(extra),                   QS(noop)    },
+/*  setsfunc                     sortfunc      type2str
+    ---------------------------  ------------  ----------- */
+  { RS(noop),                    QS(noop),     TS_noop     },
+  { RS(extra),                   QS(ull_int),  TS_noop     },
 
-  { RS(TIC_ID),                  QS(s_int)   },
-  { RS(TIC_NUMA_NODE),           QS(s_int)   },
-  { RS(TIC_USER),                QS(ull_int) },
-  { RS(TIC_NICE),                QS(ull_int) },
-  { RS(TIC_SYSTEM),              QS(ull_int) },
-  { RS(TIC_IDLE),                QS(ull_int) },
-  { RS(TIC_IOWAIT),              QS(ull_int) },
-  { RS(TIC_IRQ),                 QS(ull_int) },
-  { RS(TIC_SOFTIRQ),             QS(ull_int) },
-  { RS(TIC_STOLEN),              QS(ull_int) },
-  { RS(TIC_GUEST),               QS(ull_int) },
-  { RS(TIC_GUEST_NICE),          QS(ull_int) },
+  { RS(TIC_ID),                  QS(s_int),    TS(s_int)   },
+  { RS(TIC_NUMA_NODE),           QS(s_int),    TS(s_int)   },
+  { RS(TIC_USER),                QS(ull_int),  TS(ull_int) },
+  { RS(TIC_NICE),                QS(ull_int),  TS(ull_int) },
+  { RS(TIC_SYSTEM),              QS(ull_int),  TS(ull_int) },
+  { RS(TIC_IDLE),                QS(ull_int),  TS(ull_int) },
+  { RS(TIC_IOWAIT),              QS(ull_int),  TS(ull_int) },
+  { RS(TIC_IRQ),                 QS(ull_int),  TS(ull_int) },
+  { RS(TIC_SOFTIRQ),             QS(ull_int),  TS(ull_int) },
+  { RS(TIC_STOLEN),              QS(ull_int),  TS(ull_int) },
+  { RS(TIC_GUEST),               QS(ull_int),  TS(ull_int) },
+  { RS(TIC_GUEST_NICE),          QS(ull_int),  TS(ull_int) },
 
-  { RS(TIC_DELTA_USER),          QS(sl_int)  },
-  { RS(TIC_DELTA_NICE),          QS(sl_int)  },
-  { RS(TIC_DELTA_SYSTEM),        QS(sl_int)  },
-  { RS(TIC_DELTA_IDLE),          QS(sl_int)  },
-  { RS(TIC_DELTA_IOWAIT),        QS(sl_int)  },
-  { RS(TIC_DELTA_IRQ),           QS(sl_int)  },
-  { RS(TIC_DELTA_SOFTIRQ),       QS(sl_int)  },
-  { RS(TIC_DELTA_STOLEN),        QS(sl_int)  },
-  { RS(TIC_DELTA_GUEST),         QS(sl_int)  },
-  { RS(TIC_DELTA_GUEST_NICE),    QS(sl_int)  },
+  { RS(TIC_DELTA_USER),          QS(sl_int),   TS(sl_int)  },
+  { RS(TIC_DELTA_NICE),          QS(sl_int),   TS(sl_int)  },
+  { RS(TIC_DELTA_SYSTEM),        QS(sl_int),   TS(sl_int)  },
+  { RS(TIC_DELTA_IDLE),          QS(sl_int),   TS(sl_int)  },
+  { RS(TIC_DELTA_IOWAIT),        QS(sl_int),   TS(sl_int)  },
+  { RS(TIC_DELTA_IRQ),           QS(sl_int),   TS(sl_int)  },
+  { RS(TIC_DELTA_SOFTIRQ),       QS(sl_int),   TS(sl_int)  },
+  { RS(TIC_DELTA_STOLEN),        QS(sl_int),   TS(sl_int)  },
+  { RS(TIC_DELTA_GUEST),         QS(sl_int),   TS(sl_int)  },
+  { RS(TIC_DELTA_GUEST_NICE),    QS(sl_int),   TS(sl_int)  },
 
-  { RS(SYS_CTX_SWITCHES),        QS(ul_int)  },
-  { RS(SYS_INTERRUPTS),          QS(ul_int)  },
-  { RS(SYS_PROC_BLOCKED),        QS(ul_int)  },
-  { RS(SYS_PROC_CREATED),        QS(ul_int)  },
-  { RS(SYS_PROC_RUNNING),        QS(ul_int)  },
-  { RS(SYS_TIME_OF_BOOT),        QS(ul_int)  },
+  { RS(SYS_CTX_SWITCHES),        QS(ul_int),   TS(ul_int)  },
+  { RS(SYS_INTERRUPTS),          QS(ul_int),   TS(ul_int)  },
+  { RS(SYS_PROC_BLOCKED),        QS(ul_int),   TS(ul_int)  },
+  { RS(SYS_PROC_CREATED),        QS(ul_int),   TS(ul_int)  },
+  { RS(SYS_PROC_RUNNING),        QS(ul_int),   TS(ul_int)  },
+  { RS(SYS_TIME_OF_BOOT),        QS(ul_int),   TS(ul_int)  },
 
-  { RS(SYS_DELTA_CTX_SWITCHES),  QS(s_int)   },
-  { RS(SYS_DELTA_INTERRUPTS),    QS(s_int)   },
-  { RS(SYS_DELTA_PROC_BLOCKED),  QS(s_int)   },
-  { RS(SYS_DELTA_PROC_CREATED),  QS(s_int)   },
-  { RS(SYS_DELTA_PROC_RUNNING),  QS(s_int)   },
+  { RS(SYS_DELTA_CTX_SWITCHES),  QS(s_int),    TS(s_int)   },
+  { RS(SYS_DELTA_INTERRUPTS),    QS(s_int),    TS(s_int)   },
+  { RS(SYS_DELTA_PROC_BLOCKED),  QS(s_int),    TS(s_int)   },
+  { RS(SYS_DELTA_PROC_CREATED),  QS(s_int),    TS(s_int)   },
+  { RS(SYS_DELTA_PROC_RUNNING),  QS(s_int),    TS(s_int)   },
 
  // dummy entry corresponding to STAT_logical_end ...
-  { NULL,                        NULL        }
+  { NULL,                        NULL,         NULL        }
 };
 
     /* please note,
@@ -1122,3 +1126,56 @@ PROCPS_EXPORT struct stat_stack **procps_stat_sort (
     qsort_r(stacks, numstacked, sizeof(void *), (QSR_t)Item_table[p->item].sortfunc, &parms);
     return stacks;
 } // end: procps_stat_sort
+
+
+// --- special debugging function(s) ------------------------------------------
+/*
+ *  The following isn't part of the normal programming interface.  Rather,
+ *  it exists to validate result types referenced in application programs.
+ *
+ *  It's used only when:
+ *      1) the 'XTRA_PROCPS_DEBUG' has been defined, or
+ *      2) the '#include <proc/xtra-procps-debug.h>' used
+ */
+
+PROCPS_EXPORT struct stat_result *xtra_stat_get (
+        struct stat_info *info,
+        enum stat_item actual_enum,
+        const char *typestr,
+        const char *file,
+        int lineno)
+{
+    struct stat_result *r = procps_stat_get(info, actual_enum);
+
+    if (r) {
+        char *str = Item_table[r->item].type2str;
+        if (str[0]
+        && (strcmp(typestr, str)))
+            fprintf(stderr, "%s line %d: was %s, expected %s\n", file, lineno, typestr, str);
+    }
+    return r;
+} // end: xtra_stat_get_
+
+
+PROCPS_EXPORT void xtra_stat_val (
+        int relative_enum,
+        const char *typestr,
+        const struct stat_stack *stack,
+        struct stat_info *info,
+        const char *file,
+        int lineno)
+{
+    struct stat_result *r;
+    char *str;
+
+    r = &stack->head[relative_enum];
+    if (r->item < 0 || r->item >= STAT_logical_end) {
+        fprintf(stderr, "%s line %d: invalid item = %d, relative_enum = %d, type = %s\n"
+            , file, lineno, r->item, relative_enum, typestr);
+        return;
+    }
+    str = Item_table[r->item].type2str;
+    if (str[0]
+    && (strcmp(typestr, str)))
+        fprintf(stderr, "%s line %d: was %s, expected %s\n", file, lineno, typestr, str);
+} // end: xtra_stat_val
diff --git a/proc/vmstat.c b/proc/vmstat.c
index 612894d3..3b21bdd3 100644
--- a/proc/vmstat.c
+++ b/proc/vmstat.c
@@ -25,6 +25,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <search.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <time.h>
@@ -454,258 +455,262 @@ HST_set(DELTA_ZONE_RECLAIM_FAILED,            zone_reclaim_failed)
 typedef void (*SET_t)(struct vmstat_result *, struct vmstat_hist *);
 #define RS(e) (SET_t)setNAME(e)
 
+#define TS(t) STRINGIFY(t)
+#define TS_noop ""
+
         /*
          * Need it be said?
          * This table must be kept in the exact same order as
          * those 'enum vmstat_item' guys ! */
 static struct {
     SET_t setsfunc;              // the actual result setting routine
+    char *type2str;              // the result type as a string value
 } Item_table[] = {
-/*  setsfunc
-    --------------------------------------- */
-  { RS(noop)                                },
-  { RS(extra)                               },
+/*  setsfunc                                  type2str
+    ----------------------------------------  ---------- */
+  { RS(noop),                                 TS_noop    },
+  { RS(extra),                                TS_noop    },
 
-  { RS(ALLOCSTALL)                          },
-  { RS(BALLOON_DEFLATE)                     },
-  { RS(BALLOON_INFLATE)                     },
-  { RS(BALLOON_MIGRATE)                     },
-  { RS(COMPACT_FAIL)                        },
-  { RS(COMPACT_FREE_SCANNED)                },
-  { RS(COMPACT_ISOLATED)                    },
-  { RS(COMPACT_MIGRATE_SCANNED)             },
-  { RS(COMPACT_STALL)                       },
-  { RS(COMPACT_SUCCESS)                     },
-  { RS(DROP_PAGECACHE)                      },
-  { RS(DROP_SLAB)                           },
-  { RS(HTLB_BUDDY_ALLOC_FAIL)               },
-  { RS(HTLB_BUDDY_ALLOC_SUCCESS)            },
-  { RS(KSWAPD_HIGH_WMARK_HIT_QUICKLY)       },
-  { RS(KSWAPD_INODESTEAL)                   },
-  { RS(KSWAPD_LOW_WMARK_HIT_QUICKLY)        },
-  { RS(NR_ACTIVE_ANON)                      },
-  { RS(NR_ACTIVE_FILE)                      },
-  { RS(NR_ALLOC_BATCH)                      },
-  { RS(NR_ANON_PAGES)                       },
-  { RS(NR_ANON_TRANSPARENT_HUGEPAGES)       },
-  { RS(NR_BOUNCE)                           },
-  { RS(NR_DIRTIED)                          },
-  { RS(NR_DIRTY)                            },
-  { RS(NR_DIRTY_BACKGROUND_THRESHOLD)       },
-  { RS(NR_DIRTY_THRESHOLD)                  },
-  { RS(NR_FILE_PAGES)                       },
-  { RS(NR_FREE_CMA)                         },
-  { RS(NR_FREE_PAGES)                       },
-  { RS(NR_INACTIVE_ANON)                    },
-  { RS(NR_INACTIVE_FILE)                    },
-  { RS(NR_ISOLATED_ANON)                    },
-  { RS(NR_ISOLATED_FILE)                    },
-  { RS(NR_KERNEL_STACK)                     },
-  { RS(NR_MAPPED)                           },
-  { RS(NR_MLOCK)                            },
-  { RS(NR_PAGES_SCANNED)                    },
-  { RS(NR_PAGE_TABLE_PAGES)                 },
-  { RS(NR_SHMEM)                            },
-  { RS(NR_SLAB_RECLAIMABLE)                 },
-  { RS(NR_SLAB_UNRECLAIMABLE)               },
-  { RS(NR_UNEVICTABLE)                      },
-  { RS(NR_UNSTABLE)                         },
-  { RS(NR_VMSCAN_IMMEDIATE_RECLAIM)         },
-  { RS(NR_VMSCAN_WRITE)                     },
-  { RS(NR_WRITEBACK)                        },
-  { RS(NR_WRITEBACK_TEMP)                   },
-  { RS(NR_WRITTEN)                          },
-  { RS(NUMA_FOREIGN)                        },
-  { RS(NUMA_HINT_FAULTS)                    },
-  { RS(NUMA_HINT_FAULTS_LOCAL)              },
-  { RS(NUMA_HIT)                            },
-  { RS(NUMA_HUGE_PTE_UPDATES)               },
-  { RS(NUMA_INTERLEAVE)                     },
-  { RS(NUMA_LOCAL)                          },
-  { RS(NUMA_MISS)                           },
-  { RS(NUMA_OTHER)                          },
-  { RS(NUMA_PAGES_MIGRATED)                 },
-  { RS(NUMA_PTE_UPDATES)                    },
-  { RS(PAGEOUTRUN)                          },
-  { RS(PGACTIVATE)                          },
-  { RS(PGALLOC_DMA)                         },
-  { RS(PGALLOC_DMA32)                       },
-  { RS(PGALLOC_MOVABLE)                     },
-  { RS(PGALLOC_NORMAL)                      },
-  { RS(PGDEACTIVATE)                        },
-  { RS(PGFAULT)                             },
-  { RS(PGFREE)                              },
-  { RS(PGINODESTEAL)                        },
-  { RS(PGMAJFAULT)                          },
-  { RS(PGMIGRATE_FAIL)                      },
-  { RS(PGMIGRATE_SUCCESS)                   },
-  { RS(PGPGIN)                              },
-  { RS(PGPGOUT)                             },
-  { RS(PGREFILL_DMA)                        },
-  { RS(PGREFILL_DMA32)                      },
-  { RS(PGREFILL_MOVABLE)                    },
-  { RS(PGREFILL_NORMAL)                     },
-  { RS(PGROTATED)                           },
-  { RS(PGSCAN_DIRECT_DMA)                   },
-  { RS(PGSCAN_DIRECT_DMA32)                 },
-  { RS(PGSCAN_DIRECT_MOVABLE)               },
-  { RS(PGSCAN_DIRECT_NORMAL)                },
-  { RS(PGSCAN_DIRECT_THROTTLE)              },
-  { RS(PGSCAN_KSWAPD_DMA)                   },
-  { RS(PGSCAN_KSWAPD_DMA32)                 },
-  { RS(PGSCAN_KSWAPD_MOVEABLE)              },
-  { RS(PGSCAN_KSWAPD_NORMAL)                },
-  { RS(PGSTEAL_DIRECT_DMA)                  },
-  { RS(PGSTEAL_DIRECT_DMA32)                },
-  { RS(PGSTEAL_DIRECT_MOVABLE)              },
-  { RS(PGSTEAL_DIRECT_NORMAL)               },
-  { RS(PGSTEAL_KSWAPD_DMA)                  },
-  { RS(PGSTEAL_KSWAPD_DMA32)                },
-  { RS(PGSTEAL_KSWAPD_MOVABLE)              },
-  { RS(PGSTEAL_KSWAPD_NORMAL)               },
-  { RS(PSWPIN)                              },
-  { RS(PSWPOUT)                             },
-  { RS(SLABS_SCANNED)                       },
-  { RS(THP_COLLAPSE_ALLOC)                  },
-  { RS(THP_COLLAPSE_ALLOC_FAILED)           },
-  { RS(THP_FAULT_ALLOC)                     },
-  { RS(THP_FAULT_FALLBACK)                  },
-  { RS(THP_SPLIT)                           },
-  { RS(THP_ZERO_PAGE_ALLOC)                 },
-  { RS(THP_ZERO_PAGE_ALLOC_FAILED)          },
-  { RS(UNEVICTABLE_PGS_CLEARED)             },
-  { RS(UNEVICTABLE_PGS_CULLED)              },
-  { RS(UNEVICTABLE_PGS_MLOCKED)             },
-  { RS(UNEVICTABLE_PGS_MUNLOCKED)           },
-  { RS(UNEVICTABLE_PGS_RESCUED)             },
-  { RS(UNEVICTABLE_PGS_SCANNED)             },
-  { RS(UNEVICTABLE_PGS_STRANDED)            },
-  { RS(WORKINGSET_ACTIVATE)                 },
-  { RS(WORKINGSET_NODERECLAIM)              },
-  { RS(WORKINGSET_REFAULT)                  },
-  { RS(ZONE_RECLAIM_FAILED)                 },
+  { RS(ALLOCSTALL),                           TS(ul_int) },
+  { RS(BALLOON_DEFLATE),                      TS(ul_int) },
+  { RS(BALLOON_INFLATE),                      TS(ul_int) },
+  { RS(BALLOON_MIGRATE),                      TS(ul_int) },
+  { RS(COMPACT_FAIL),                         TS(ul_int) },
+  { RS(COMPACT_FREE_SCANNED),                 TS(ul_int) },
+  { RS(COMPACT_ISOLATED),                     TS(ul_int) },
+  { RS(COMPACT_MIGRATE_SCANNED),              TS(ul_int) },
+  { RS(COMPACT_STALL),                        TS(ul_int) },
+  { RS(COMPACT_SUCCESS),                      TS(ul_int) },
+  { RS(DROP_PAGECACHE),                       TS(ul_int) },
+  { RS(DROP_SLAB),                            TS(ul_int) },
+  { RS(HTLB_BUDDY_ALLOC_FAIL),                TS(ul_int) },
+  { RS(HTLB_BUDDY_ALLOC_SUCCESS),             TS(ul_int) },
+  { RS(KSWAPD_HIGH_WMARK_HIT_QUICKLY),        TS(ul_int) },
+  { RS(KSWAPD_INODESTEAL),                    TS(ul_int) },
+  { RS(KSWAPD_LOW_WMARK_HIT_QUICKLY),         TS(ul_int) },
+  { RS(NR_ACTIVE_ANON),                       TS(ul_int) },
+  { RS(NR_ACTIVE_FILE),                       TS(ul_int) },
+  { RS(NR_ALLOC_BATCH),                       TS(ul_int) },
+  { RS(NR_ANON_PAGES),                        TS(ul_int) },
+  { RS(NR_ANON_TRANSPARENT_HUGEPAGES),        TS(ul_int) },
+  { RS(NR_BOUNCE),                            TS(ul_int) },
+  { RS(NR_DIRTIED),                           TS(ul_int) },
+  { RS(NR_DIRTY),                             TS(ul_int) },
+  { RS(NR_DIRTY_BACKGROUND_THRESHOLD),        TS(ul_int) },
+  { RS(NR_DIRTY_THRESHOLD),                   TS(ul_int) },
+  { RS(NR_FILE_PAGES),                        TS(ul_int) },
+  { RS(NR_FREE_CMA),                          TS(ul_int) },
+  { RS(NR_FREE_PAGES),                        TS(ul_int) },
+  { RS(NR_INACTIVE_ANON),                     TS(ul_int) },
+  { RS(NR_INACTIVE_FILE),                     TS(ul_int) },
+  { RS(NR_ISOLATED_ANON),                     TS(ul_int) },
+  { RS(NR_ISOLATED_FILE),                     TS(ul_int) },
+  { RS(NR_KERNEL_STACK),                      TS(ul_int) },
+  { RS(NR_MAPPED),                            TS(ul_int) },
+  { RS(NR_MLOCK),                             TS(ul_int) },
+  { RS(NR_PAGES_SCANNED),                     TS(ul_int) },
+  { RS(NR_PAGE_TABLE_PAGES),                  TS(ul_int) },
+  { RS(NR_SHMEM),                             TS(ul_int) },
+  { RS(NR_SLAB_RECLAIMABLE),                  TS(ul_int) },
+  { RS(NR_SLAB_UNRECLAIMABLE),                TS(ul_int) },
+  { RS(NR_UNEVICTABLE),                       TS(ul_int) },
+  { RS(NR_UNSTABLE),                          TS(ul_int) },
+  { RS(NR_VMSCAN_IMMEDIATE_RECLAIM),          TS(ul_int) },
+  { RS(NR_VMSCAN_WRITE),                      TS(ul_int) },
+  { RS(NR_WRITEBACK),                         TS(ul_int) },
+  { RS(NR_WRITEBACK_TEMP),                    TS(ul_int) },
+  { RS(NR_WRITTEN),                           TS(ul_int) },
+  { RS(NUMA_FOREIGN),                         TS(ul_int) },
+  { RS(NUMA_HINT_FAULTS),                     TS(ul_int) },
+  { RS(NUMA_HINT_FAULTS_LOCAL),               TS(ul_int) },
+  { RS(NUMA_HIT),                             TS(ul_int) },
+  { RS(NUMA_HUGE_PTE_UPDATES),                TS(ul_int) },
+  { RS(NUMA_INTERLEAVE),                      TS(ul_int) },
+  { RS(NUMA_LOCAL),                           TS(ul_int) },
+  { RS(NUMA_MISS),                            TS(ul_int) },
+  { RS(NUMA_OTHER),                           TS(ul_int) },
+  { RS(NUMA_PAGES_MIGRATED),                  TS(ul_int) },
+  { RS(NUMA_PTE_UPDATES),                     TS(ul_int) },
+  { RS(PAGEOUTRUN),                           TS(ul_int) },
+  { RS(PGACTIVATE),                           TS(ul_int) },
+  { RS(PGALLOC_DMA),                          TS(ul_int) },
+  { RS(PGALLOC_DMA32),                        TS(ul_int) },
+  { RS(PGALLOC_MOVABLE),                      TS(ul_int) },
+  { RS(PGALLOC_NORMAL),                       TS(ul_int) },
+  { RS(PGDEACTIVATE),                         TS(ul_int) },
+  { RS(PGFAULT),                              TS(ul_int) },
+  { RS(PGFREE),                               TS(ul_int) },
+  { RS(PGINODESTEAL),                         TS(ul_int) },
+  { RS(PGMAJFAULT),                           TS(ul_int) },
+  { RS(PGMIGRATE_FAIL),                       TS(ul_int) },
+  { RS(PGMIGRATE_SUCCESS),                    TS(ul_int) },
+  { RS(PGPGIN),                               TS(ul_int) },
+  { RS(PGPGOUT),                              TS(ul_int) },
+  { RS(PGREFILL_DMA),                         TS(ul_int) },
+  { RS(PGREFILL_DMA32),                       TS(ul_int) },
+  { RS(PGREFILL_MOVABLE),                     TS(ul_int) },
+  { RS(PGREFILL_NORMAL),                      TS(ul_int) },
+  { RS(PGROTATED),                            TS(ul_int) },
+  { RS(PGSCAN_DIRECT_DMA),                    TS(ul_int) },
+  { RS(PGSCAN_DIRECT_DMA32),                  TS(ul_int) },
+  { RS(PGSCAN_DIRECT_MOVABLE),                TS(ul_int) },
+  { RS(PGSCAN_DIRECT_NORMAL),                 TS(ul_int) },
+  { RS(PGSCAN_DIRECT_THROTTLE),               TS(ul_int) },
+  { RS(PGSCAN_KSWAPD_DMA),                    TS(ul_int) },
+  { RS(PGSCAN_KSWAPD_DMA32),                  TS(ul_int) },
+  { RS(PGSCAN_KSWAPD_MOVEABLE),               TS(ul_int) },
+  { RS(PGSCAN_KSWAPD_NORMAL),                 TS(ul_int) },
+  { RS(PGSTEAL_DIRECT_DMA),                   TS(ul_int) },
+  { RS(PGSTEAL_DIRECT_DMA32),                 TS(ul_int) },
+  { RS(PGSTEAL_DIRECT_MOVABLE),               TS(ul_int) },
+  { RS(PGSTEAL_DIRECT_NORMAL),                TS(ul_int) },
+  { RS(PGSTEAL_KSWAPD_DMA),                   TS(ul_int) },
+  { RS(PGSTEAL_KSWAPD_DMA32),                 TS(ul_int) },
+  { RS(PGSTEAL_KSWAPD_MOVABLE),               TS(ul_int) },
+  { RS(PGSTEAL_KSWAPD_NORMAL),                TS(ul_int) },
+  { RS(PSWPIN),                               TS(ul_int) },
+  { RS(PSWPOUT),                              TS(ul_int) },
+  { RS(SLABS_SCANNED),                        TS(ul_int) },
+  { RS(THP_COLLAPSE_ALLOC),                   TS(ul_int) },
+  { RS(THP_COLLAPSE_ALLOC_FAILED),            TS(ul_int) },
+  { RS(THP_FAULT_ALLOC),                      TS(ul_int) },
+  { RS(THP_FAULT_FALLBACK),                   TS(ul_int) },
+  { RS(THP_SPLIT),                            TS(ul_int) },
+  { RS(THP_ZERO_PAGE_ALLOC),                  TS(ul_int) },
+  { RS(THP_ZERO_PAGE_ALLOC_FAILED),           TS(ul_int) },
+  { RS(UNEVICTABLE_PGS_CLEARED),              TS(ul_int) },
+  { RS(UNEVICTABLE_PGS_CULLED),               TS(ul_int) },
+  { RS(UNEVICTABLE_PGS_MLOCKED),              TS(ul_int) },
+  { RS(UNEVICTABLE_PGS_MUNLOCKED),            TS(ul_int) },
+  { RS(UNEVICTABLE_PGS_RESCUED),              TS(ul_int) },
+  { RS(UNEVICTABLE_PGS_SCANNED),              TS(ul_int) },
+  { RS(UNEVICTABLE_PGS_STRANDED),             TS(ul_int) },
+  { RS(WORKINGSET_ACTIVATE),                  TS(ul_int) },
+  { RS(WORKINGSET_NODERECLAIM),               TS(ul_int) },
+  { RS(WORKINGSET_REFAULT),                   TS(ul_int) },
+  { RS(ZONE_RECLAIM_FAILED),                  TS(ul_int) },
 
-  { RS(DELTA_ALLOCSTALL)                    },
-  { RS(DELTA_BALLOON_DEFLATE)               },
-  { RS(DELTA_BALLOON_INFLATE)               },
-  { RS(DELTA_BALLOON_MIGRATE)               },
-  { RS(DELTA_COMPACT_FAIL)                  },
-  { RS(DELTA_COMPACT_FREE_SCANNED)          },
-  { RS(DELTA_COMPACT_ISOLATED)              },
-  { RS(DELTA_COMPACT_MIGRATE_SCANNED)       },
-  { RS(DELTA_COMPACT_STALL)                 },
-  { RS(DELTA_COMPACT_SUCCESS)               },
-  { RS(DELTA_DROP_PAGECACHE)                },
-  { RS(DELTA_DROP_SLAB)                     },
-  { RS(DELTA_HTLB_BUDDY_ALLOC_FAIL)         },
-  { RS(DELTA_HTLB_BUDDY_ALLOC_SUCCESS)      },
-  { RS(DELTA_KSWAPD_HIGH_WMARK_HIT_QUICKLY) },
-  { RS(DELTA_KSWAPD_INODESTEAL)             },
-  { RS(DELTA_KSWAPD_LOW_WMARK_HIT_QUICKLY)  },
-  { RS(DELTA_NR_ACTIVE_ANON)                },
-  { RS(DELTA_NR_ACTIVE_FILE)                },
-  { RS(DELTA_NR_ALLOC_BATCH)                },
-  { RS(DELTA_NR_ANON_PAGES)                 },
-  { RS(DELTA_NR_ANON_TRANSPARENT_HUGEPAGES) },
-  { RS(DELTA_NR_BOUNCE)                     },
-  { RS(DELTA_NR_DIRTIED)                    },
-  { RS(DELTA_NR_DIRTY)                      },
-  { RS(DELTA_NR_DIRTY_BACKGROUND_THRESHOLD) },
-  { RS(DELTA_NR_DIRTY_THRESHOLD)            },
-  { RS(DELTA_NR_FILE_PAGES)                 },
-  { RS(DELTA_NR_FREE_CMA)                   },
-  { RS(DELTA_NR_FREE_PAGES)                 },
-  { RS(DELTA_NR_INACTIVE_ANON)              },
-  { RS(DELTA_NR_INACTIVE_FILE)              },
-  { RS(DELTA_NR_ISOLATED_ANON)              },
-  { RS(DELTA_NR_ISOLATED_FILE)              },
-  { RS(DELTA_NR_KERNEL_STACK)               },
-  { RS(DELTA_NR_MAPPED)                     },
-  { RS(DELTA_NR_MLOCK)                      },
-  { RS(DELTA_NR_PAGES_SCANNED)              },
-  { RS(DELTA_NR_PAGE_TABLE_PAGES)           },
-  { RS(DELTA_NR_SHMEM)                      },
-  { RS(DELTA_NR_SLAB_RECLAIMABLE)           },
-  { RS(DELTA_NR_SLAB_UNRECLAIMABLE)         },
-  { RS(DELTA_NR_UNEVICTABLE)                },
-  { RS(DELTA_NR_UNSTABLE)                   },
-  { RS(DELTA_NR_VMSCAN_IMMEDIATE_RECLAIM)   },
-  { RS(DELTA_NR_VMSCAN_WRITE)               },
-  { RS(DELTA_NR_WRITEBACK)                  },
-  { RS(DELTA_NR_WRITEBACK_TEMP)             },
-  { RS(DELTA_NR_WRITTEN)                    },
-  { RS(DELTA_NUMA_FOREIGN)                  },
-  { RS(DELTA_NUMA_HINT_FAULTS)              },
-  { RS(DELTA_NUMA_HINT_FAULTS_LOCAL)        },
-  { RS(DELTA_NUMA_HIT)                      },
-  { RS(DELTA_NUMA_HUGE_PTE_UPDATES)         },
-  { RS(DELTA_NUMA_INTERLEAVE)               },
-  { RS(DELTA_NUMA_LOCAL)                    },
-  { RS(DELTA_NUMA_MISS)                     },
-  { RS(DELTA_NUMA_OTHER)                    },
-  { RS(DELTA_NUMA_PAGES_MIGRATED)           },
-  { RS(DELTA_NUMA_PTE_UPDATES)              },
-  { RS(DELTA_PAGEOUTRUN)                    },
-  { RS(DELTA_PGACTIVATE)                    },
-  { RS(DELTA_PGALLOC_DMA)                   },
-  { RS(DELTA_PGALLOC_DMA32)                 },
-  { RS(DELTA_PGALLOC_MOVABLE)               },
-  { RS(DELTA_PGALLOC_NORMAL)                },
-  { RS(DELTA_PGDEACTIVATE)                  },
-  { RS(DELTA_PGFAULT)                       },
-  { RS(DELTA_PGFREE)                        },
-  { RS(DELTA_PGINODESTEAL)                  },
-  { RS(DELTA_PGMAJFAULT)                    },
-  { RS(DELTA_PGMIGRATE_FAIL)                },
-  { RS(DELTA_PGMIGRATE_SUCCESS)             },
-  { RS(DELTA_PGPGIN)                        },
-  { RS(DELTA_PGPGOUT)                       },
-  { RS(DELTA_PGREFILL_DMA)                  },
-  { RS(DELTA_PGREFILL_DMA32)                },
-  { RS(DELTA_PGREFILL_MOVABLE)              },
-  { RS(DELTA_PGREFILL_NORMAL)               },
-  { RS(DELTA_PGROTATED)                     },
-  { RS(DELTA_PGSCAN_DIRECT_DMA)             },
-  { RS(DELTA_PGSCAN_DIRECT_DMA32)           },
-  { RS(DELTA_PGSCAN_DIRECT_MOVABLE)         },
-  { RS(DELTA_PGSCAN_DIRECT_NORMAL)          },
-  { RS(DELTA_PGSCAN_DIRECT_THROTTLE)        },
-  { RS(DELTA_PGSCAN_KSWAPD_DMA)             },
-  { RS(DELTA_PGSCAN_KSWAPD_DMA32)           },
-  { RS(DELTA_PGSCAN_KSWAPD_MOVEABLE)        },
-  { RS(DELTA_PGSCAN_KSWAPD_NORMAL)          },
-  { RS(DELTA_PGSTEAL_DIRECT_DMA)            },
-  { RS(DELTA_PGSTEAL_DIRECT_DMA32)          },
-  { RS(DELTA_PGSTEAL_DIRECT_MOVABLE)        },
-  { RS(DELTA_PGSTEAL_DIRECT_NORMAL)         },
-  { RS(DELTA_PGSTEAL_KSWAPD_DMA)            },
-  { RS(DELTA_PGSTEAL_KSWAPD_DMA32)          },
-  { RS(DELTA_PGSTEAL_KSWAPD_MOVABLE)        },
-  { RS(DELTA_PGSTEAL_KSWAPD_NORMAL)         },
-  { RS(DELTA_PSWPIN)                        },
-  { RS(DELTA_PSWPOUT)                       },
-  { RS(DELTA_SLABS_SCANNED)                 },
-  { RS(DELTA_THP_COLLAPSE_ALLOC)            },
-  { RS(DELTA_THP_COLLAPSE_ALLOC_FAILED)     },
-  { RS(DELTA_THP_FAULT_ALLOC)               },
-  { RS(DELTA_THP_FAULT_FALLBACK)            },
-  { RS(DELTA_THP_SPLIT)                     },
-  { RS(DELTA_THP_ZERO_PAGE_ALLOC)           },
-  { RS(DELTA_THP_ZERO_PAGE_ALLOC_FAILED)    },
-  { RS(DELTA_UNEVICTABLE_PGS_CLEARED)       },
-  { RS(DELTA_UNEVICTABLE_PGS_CULLED)        },
-  { RS(DELTA_UNEVICTABLE_PGS_MLOCKED)       },
-  { RS(DELTA_UNEVICTABLE_PGS_MUNLOCKED)     },
-  { RS(DELTA_UNEVICTABLE_PGS_RESCUED)       },
-  { RS(DELTA_UNEVICTABLE_PGS_SCANNED)       },
-  { RS(DELTA_UNEVICTABLE_PGS_STRANDED)      },
-  { RS(DELTA_WORKINGSET_ACTIVATE)           },
-  { RS(DELTA_WORKINGSET_NODERECLAIM)        },
-  { RS(DELTA_WORKINGSET_REFAULT)            },
-  { RS(DELTA_ZONE_RECLAIM_FAILED)           },
+  { RS(DELTA_ALLOCSTALL),                     TS(sl_int) },
+  { RS(DELTA_BALLOON_DEFLATE),                TS(sl_int) },
+  { RS(DELTA_BALLOON_INFLATE),                TS(sl_int) },
+  { RS(DELTA_BALLOON_MIGRATE),                TS(sl_int) },
+  { RS(DELTA_COMPACT_FAIL),                   TS(sl_int) },
+  { RS(DELTA_COMPACT_FREE_SCANNED),           TS(sl_int) },
+  { RS(DELTA_COMPACT_ISOLATED),               TS(sl_int) },
+  { RS(DELTA_COMPACT_MIGRATE_SCANNED),        TS(sl_int) },
+  { RS(DELTA_COMPACT_STALL),                  TS(sl_int) },
+  { RS(DELTA_COMPACT_SUCCESS),                TS(sl_int) },
+  { RS(DELTA_DROP_PAGECACHE),                 TS(sl_int) },
+  { RS(DELTA_DROP_SLAB),                      TS(sl_int) },
+  { RS(DELTA_HTLB_BUDDY_ALLOC_FAIL),          TS(sl_int) },
+  { RS(DELTA_HTLB_BUDDY_ALLOC_SUCCESS),       TS(sl_int) },
+  { RS(DELTA_KSWAPD_HIGH_WMARK_HIT_QUICKLY),  TS(sl_int) },
+  { RS(DELTA_KSWAPD_INODESTEAL),              TS(sl_int) },
+  { RS(DELTA_KSWAPD_LOW_WMARK_HIT_QUICKLY),   TS(sl_int) },
+  { RS(DELTA_NR_ACTIVE_ANON),                 TS(sl_int) },
+  { RS(DELTA_NR_ACTIVE_FILE),                 TS(sl_int) },
+  { RS(DELTA_NR_ALLOC_BATCH),                 TS(sl_int) },
+  { RS(DELTA_NR_ANON_PAGES),                  TS(sl_int) },
+  { RS(DELTA_NR_ANON_TRANSPARENT_HUGEPAGES),  TS(sl_int) },
+  { RS(DELTA_NR_BOUNCE),                      TS(sl_int) },
+  { RS(DELTA_NR_DIRTIED),                     TS(sl_int) },
+  { RS(DELTA_NR_DIRTY),                       TS(sl_int) },
+  { RS(DELTA_NR_DIRTY_BACKGROUND_THRESHOLD),  TS(sl_int) },
+  { RS(DELTA_NR_DIRTY_THRESHOLD),             TS(sl_int) },
+  { RS(DELTA_NR_FILE_PAGES),                  TS(sl_int) },
+  { RS(DELTA_NR_FREE_CMA),                    TS(sl_int) },
+  { RS(DELTA_NR_FREE_PAGES),                  TS(sl_int) },
+  { RS(DELTA_NR_INACTIVE_ANON),               TS(sl_int) },
+  { RS(DELTA_NR_INACTIVE_FILE),               TS(sl_int) },
+  { RS(DELTA_NR_ISOLATED_ANON),               TS(sl_int) },
+  { RS(DELTA_NR_ISOLATED_FILE),               TS(sl_int) },
+  { RS(DELTA_NR_KERNEL_STACK),                TS(sl_int) },
+  { RS(DELTA_NR_MAPPED),                      TS(sl_int) },
+  { RS(DELTA_NR_MLOCK),                       TS(sl_int) },
+  { RS(DELTA_NR_PAGES_SCANNED),               TS(sl_int) },
+  { RS(DELTA_NR_PAGE_TABLE_PAGES),            TS(sl_int) },
+  { RS(DELTA_NR_SHMEM),                       TS(sl_int) },
+  { RS(DELTA_NR_SLAB_RECLAIMABLE),            TS(sl_int) },
+  { RS(DELTA_NR_SLAB_UNRECLAIMABLE),          TS(sl_int) },
+  { RS(DELTA_NR_UNEVICTABLE),                 TS(sl_int) },
+  { RS(DELTA_NR_UNSTABLE),                    TS(sl_int) },
+  { RS(DELTA_NR_VMSCAN_IMMEDIATE_RECLAIM),    TS(sl_int) },
+  { RS(DELTA_NR_VMSCAN_WRITE),                TS(sl_int) },
+  { RS(DELTA_NR_WRITEBACK),                   TS(sl_int) },
+  { RS(DELTA_NR_WRITEBACK_TEMP),              TS(sl_int) },
+  { RS(DELTA_NR_WRITTEN),                     TS(sl_int) },
+  { RS(DELTA_NUMA_FOREIGN),                   TS(sl_int) },
+  { RS(DELTA_NUMA_HINT_FAULTS),               TS(sl_int) },
+  { RS(DELTA_NUMA_HINT_FAULTS_LOCAL),         TS(sl_int) },
+  { RS(DELTA_NUMA_HIT),                       TS(sl_int) },
+  { RS(DELTA_NUMA_HUGE_PTE_UPDATES),          TS(sl_int) },
+  { RS(DELTA_NUMA_INTERLEAVE),                TS(sl_int) },
+  { RS(DELTA_NUMA_LOCAL),                     TS(sl_int) },
+  { RS(DELTA_NUMA_MISS),                      TS(sl_int) },
+  { RS(DELTA_NUMA_OTHER),                     TS(sl_int) },
+  { RS(DELTA_NUMA_PAGES_MIGRATED),            TS(sl_int) },
+  { RS(DELTA_NUMA_PTE_UPDATES),               TS(sl_int) },
+  { RS(DELTA_PAGEOUTRUN),                     TS(sl_int) },
+  { RS(DELTA_PGACTIVATE),                     TS(sl_int) },
+  { RS(DELTA_PGALLOC_DMA),                    TS(sl_int) },
+  { RS(DELTA_PGALLOC_DMA32),                  TS(sl_int) },
+  { RS(DELTA_PGALLOC_MOVABLE),                TS(sl_int) },
+  { RS(DELTA_PGALLOC_NORMAL),                 TS(sl_int) },
+  { RS(DELTA_PGDEACTIVATE),                   TS(sl_int) },
+  { RS(DELTA_PGFAULT),                        TS(sl_int) },
+  { RS(DELTA_PGFREE),                         TS(sl_int) },
+  { RS(DELTA_PGINODESTEAL),                   TS(sl_int) },
+  { RS(DELTA_PGMAJFAULT),                     TS(sl_int) },
+  { RS(DELTA_PGMIGRATE_FAIL),                 TS(sl_int) },
+  { RS(DELTA_PGMIGRATE_SUCCESS),              TS(sl_int) },
+  { RS(DELTA_PGPGIN),                         TS(sl_int) },
+  { RS(DELTA_PGPGOUT),                        TS(sl_int) },
+  { RS(DELTA_PGREFILL_DMA),                   TS(sl_int) },
+  { RS(DELTA_PGREFILL_DMA32),                 TS(sl_int) },
+  { RS(DELTA_PGREFILL_MOVABLE),               TS(sl_int) },
+  { RS(DELTA_PGREFILL_NORMAL),                TS(sl_int) },
+  { RS(DELTA_PGROTATED),                      TS(sl_int) },
+  { RS(DELTA_PGSCAN_DIRECT_DMA),              TS(sl_int) },
+  { RS(DELTA_PGSCAN_DIRECT_DMA32),            TS(sl_int) },
+  { RS(DELTA_PGSCAN_DIRECT_MOVABLE),          TS(sl_int) },
+  { RS(DELTA_PGSCAN_DIRECT_NORMAL),           TS(sl_int) },
+  { RS(DELTA_PGSCAN_DIRECT_THROTTLE),         TS(sl_int) },
+  { RS(DELTA_PGSCAN_KSWAPD_DMA),              TS(sl_int) },
+  { RS(DELTA_PGSCAN_KSWAPD_DMA32),            TS(sl_int) },
+  { RS(DELTA_PGSCAN_KSWAPD_MOVEABLE),         TS(sl_int) },
+  { RS(DELTA_PGSCAN_KSWAPD_NORMAL),           TS(sl_int) },
+  { RS(DELTA_PGSTEAL_DIRECT_DMA),             TS(sl_int) },
+  { RS(DELTA_PGSTEAL_DIRECT_DMA32),           TS(sl_int) },
+  { RS(DELTA_PGSTEAL_DIRECT_MOVABLE),         TS(sl_int) },
+  { RS(DELTA_PGSTEAL_DIRECT_NORMAL),          TS(sl_int) },
+  { RS(DELTA_PGSTEAL_KSWAPD_DMA),             TS(sl_int) },
+  { RS(DELTA_PGSTEAL_KSWAPD_DMA32),           TS(sl_int) },
+  { RS(DELTA_PGSTEAL_KSWAPD_MOVABLE),         TS(sl_int) },
+  { RS(DELTA_PGSTEAL_KSWAPD_NORMAL),          TS(sl_int) },
+  { RS(DELTA_PSWPIN),                         TS(sl_int) },
+  { RS(DELTA_PSWPOUT),                        TS(sl_int) },
+  { RS(DELTA_SLABS_SCANNED),                  TS(sl_int) },
+  { RS(DELTA_THP_COLLAPSE_ALLOC),             TS(sl_int) },
+  { RS(DELTA_THP_COLLAPSE_ALLOC_FAILED),      TS(sl_int) },
+  { RS(DELTA_THP_FAULT_ALLOC),                TS(sl_int) },
+  { RS(DELTA_THP_FAULT_FALLBACK),             TS(sl_int) },
+  { RS(DELTA_THP_SPLIT),                      TS(sl_int) },
+  { RS(DELTA_THP_ZERO_PAGE_ALLOC),            TS(sl_int) },
+  { RS(DELTA_THP_ZERO_PAGE_ALLOC_FAILED),     TS(sl_int) },
+  { RS(DELTA_UNEVICTABLE_PGS_CLEARED),        TS(sl_int) },
+  { RS(DELTA_UNEVICTABLE_PGS_CULLED),         TS(sl_int) },
+  { RS(DELTA_UNEVICTABLE_PGS_MLOCKED),        TS(sl_int) },
+  { RS(DELTA_UNEVICTABLE_PGS_MUNLOCKED),      TS(sl_int) },
+  { RS(DELTA_UNEVICTABLE_PGS_RESCUED),        TS(sl_int) },
+  { RS(DELTA_UNEVICTABLE_PGS_SCANNED),        TS(sl_int) },
+  { RS(DELTA_UNEVICTABLE_PGS_STRANDED),       TS(sl_int) },
+  { RS(DELTA_WORKINGSET_ACTIVATE),            TS(sl_int) },
+  { RS(DELTA_WORKINGSET_NODERECLAIM),         TS(sl_int) },
+  { RS(DELTA_WORKINGSET_REFAULT),             TS(sl_int) },
+  { RS(DELTA_ZONE_RECLAIM_FAILED),            TS(sl_int) },
 
  // dummy entry corresponding to VMSTAT_logical_end ...
-  { NULL,                                   }
+  { NULL,                                     NULL        }
 };
 
     /* please note,
@@ -1242,3 +1247,56 @@ PROCPS_EXPORT struct vmstat_stack *procps_vmstat_select (
 
     return info->extents->stacks[0];
 } // end: procps_vmstat_select
+
+
+// --- special debugging function(s) ------------------------------------------
+/*
+ *  The following isn't part of the normal programming interface.  Rather,
+ *  it exists to validate result types referenced in application programs.
+ *
+ *  It's used only when:
+ *      1) the 'XTRA_PROCPS_DEBUG' has been defined, or
+ *      2) the '#include <proc/xtra-procps-debug.h>' used
+ */
+
+PROCPS_EXPORT struct vmstat_result *xtra_vmstat_get (
+        struct vmstat_info *info,
+        enum vmstat_item actual_enum,
+        const char *typestr,
+        const char *file,
+        int lineno)
+{
+    struct vmstat_result *r = procps_vmstat_get(info, actual_enum);
+
+    if (r) {
+        char *str = Item_table[r->item].type2str;
+        if (str[0]
+        && (strcmp(typestr, str)))
+            fprintf(stderr, "%s line %d: was %s, expected %s\n", file, lineno, typestr, str);
+    }
+    return r;
+} // end: xtra_vmstat_get_
+
+
+PROCPS_EXPORT void xtra_vmstat_val (
+        int relative_enum,
+        const char *typestr,
+        const struct vmstat_stack *stack,
+        struct vmstat_info *info,
+        const char *file,
+        int lineno)
+{
+    struct vmstat_result *r;
+    char *str;
+
+    r = &stack->head[relative_enum];
+    if (r->item < 0 || r->item >= VMSTAT_logical_end) {
+        fprintf(stderr, "%s line %d: invalid item = %d, relative_enum = %d, type = %s\n"
+            , file, lineno, r->item, relative_enum, typestr);
+        return;
+    }
+    str = Item_table[r->item].type2str;
+    if (str[0]
+    && (strcmp(typestr, str)))
+        fprintf(stderr, "%s line %d: was %s, expected %s\n", file, lineno, typestr, str);
+} // end: xtra_vmstat_val
diff --git a/proc/xtra-procps-debug.h b/proc/xtra-procps-debug.h
new file mode 100644
index 00000000..7a8eb4ac
--- /dev/null
+++ b/proc/xtra-procps-debug.h
@@ -0,0 +1,194 @@
+/*
+ * libprocps - Library to read proc filesystem
+ *
+ * Copyright (C) 2016 Jim Warner <james.warner@comcast.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef XTRA_PROCPS_DEBUG_H
+#define XTRA_PROCPS_DEBUG_H
+
+#include <proc/procps-private.h>
+
+
+// --- DISKSTATS ------------------------------------------
+#ifdef DISKSTATS_GET
+#undef DISKSTATS_GET
+struct diskstats_result *xtra_diskstats_get (
+    struct diskstats_info *info,
+    const char *name,
+    enum diskstats_item actual_enum,
+    const char *typestr,
+    const char *file,
+    int lineno);
+
+#define DISKSTATS_GET( info, name, actual_enum, type ) \
+    xtra_diskstats_get(info, name, actual_enum , STRINGIFY(type), __FILE__, __LINE__) -> result . type; } )
+#endif // . . . . . . . . . .
+
+#ifdef DISKSTATS_VAL
+#undef DISKSTATS_VAL
+void xtra_diskstats_val (
+    int relative_enum,
+    const char *typestr,
+    const struct diskstats_stack *stack,
+    struct diskstats_info *info,
+    const char *file,
+    int lineno);
+
+#define DISKSTATS_VAL( relative_enum, type, stack, info ) ( { \
+    xtra_diskstats_val(relative_enum, STRINGIFY(type), stack, info, __FILE__, __LINE__); \
+    stack -> head [ relative_enum ] . result . type; } )
+#endif // . . . . . . . . . .
+
+
+// --- MEMINFO --------------------------------------------
+#ifdef MEMINFO_GET
+#undef MEMINFO_GET
+struct meminfo_result *xtra_meminfo_get (
+    struct meminfo_info *info,
+    enum meminfo_item actual_enum,
+    const char *typestr,
+    const char *file,
+    int lineno);
+
+#define MEMINFO_GET( info, actual_enum, type ) ( { \
+    xtra_meminfo_get(info, actual_enum , STRINGIFY(type), __FILE__, __LINE__) -> result . type; } )
+#endif // . . . . . . . . . .
+
+#ifdef MEMINFO_VAL
+#undef MEMINFO_VAL
+void xtra_meminfo_val (
+    int relative_enum,
+    const char *typestr,
+    const struct meminfo_stack *stack,
+    struct meminfo_info *info,
+    const char *file,
+    int lineno);
+
+#define MEMINFO_VAL( relative_enum, type, stack, info ) ( { \
+    xtra_meminfo_val(relative_enum, STRINGIFY(type), stack, info, __FILE__, __LINE__); \
+    stack -> head [ relative_enum ] . result . type; } )
+#endif // . . . . . . . . . .
+
+
+// --- PIDS -----------------------------------------------
+#ifdef PIDS_VAL
+#undef PIDS_VAL
+void xtra_pids_val (
+    int relative_enum,
+    const char *typestr,
+    const struct pids_stack *stack,
+    struct pids_info *info,
+    const char *file,
+    int lineno);
+
+#define PIDS_VAL( relative_enum, type, stack, info ) ( { \
+    xtra_pids_val(relative_enum, STRINGIFY(type), stack, info, __FILE__, __LINE__); \
+    stack -> head [ relative_enum ] . result . type; } )
+#endif // . . . . . . . . . .
+
+
+// --- SLABINFO -------------------------------------------
+#ifdef SLABINFO_GET
+#undef SLABINFO_GET
+struct slabinfo_result *xtra_slabinfo_get (
+    struct slabinfo_info *info,
+    enum slabinfo_item actual_enum,
+    const char *typestr,
+    const char *file,
+    int lineno);
+
+#define SLABINFO_GET( info, actual_enum, type ) \
+    xtra_slabinfo_get(info, actual_enum , STRINGIFY(type), __FILE__, __LINE__) -> result . type; } )
+#endif // . . . . . . . . . .
+
+#ifdef SLABINFO_VAL
+#undef SLABINFO_VAL
+void xtra_slabinfo_val (
+    int relative_enum,
+    const char *typestr,
+    const struct slabinfo_stack *stack,
+    struct slabinfo_info *info,
+    const char *file,
+    int lineno);
+
+#define SLABINFO_VAL( relative_enum, type, stack, info ) ( { \
+    xtra_slabinfo_val(relative_enum, STRINGIFY(type), stack, info, __FILE__, __LINE__); \
+    stack -> head [ relative_enum ] . result . type; } )
+#endif // . . . . . . . . . .
+
+
+// --- STAT -----------------------------------------------
+#ifdef STAT_GET
+#undef STAT_GET
+struct stat_result *xtra_stat_get (
+    struct stat_info *info,
+    enum stat_item actual_enum,
+    const char *typestr,
+    const char *file,
+    int lineno);
+
+#define STAT_GET( info, actual_enum, type ) ( { \
+    xtra_stat_get(info, actual_enum , STRINGIFY(type), __FILE__, __LINE__) -> result . type; } )
+#endif // . . . . . . . . . .
+
+#ifdef STAT_VAL
+#undef STAT_VAL
+void xtra_stat_val (
+    int relative_enum,
+    const char *typestr,
+    const struct stat_stack *stack,
+    struct stat_info *info,
+    const char *file,
+    int lineno);
+
+#define STAT_VAL( relative_enum, type, stack, info ) ( { \
+    xtra_stat_val(relative_enum, STRINGIFY(type), stack, info, __FILE__, __LINE__); \
+    stack -> head [ relative_enum ] . result . type; } )
+#endif // . . . . . . . . . .
+
+
+// --- VMSTAT ---------------------------------------------
+#ifdef VMSTAT_GET
+#undef VMSTAT_GET
+struct vmstat_result *xtra_vmstat_get (
+    struct vmstat_info *info,
+    enum vmstat_item actual_enum,
+    const char *typestr,
+    const char *file,
+    int lineno);
+
+#define VMSTAT_GET( info, actual_enum, type ) ( { \
+    xtra_vmstat_get(info, actual_enum , STRINGIFY(type), __FILE__, __LINE__) -> result . type; } )
+#endif // . . . . . . . . . .
+
+#ifdef VMSTAT_VAL
+#undef VMSTAT_VAL
+void xtra_vmstat_val (
+    int relative_enum,
+    const char *typestr,
+    const struct vmstat_stack *stack,
+    struct vmstat_info *info,
+    const char *file,
+    int lineno);
+
+#define VMSTAT_VAL( relative_enum, type, stack, info ) ( { \
+    xtra_vmstat_val(relative_enum, STRINGIFY(type), stack, info, __FILE__, __LINE__); \
+    stack -> head [ relative_enum ] . result . type; } )
+#endif // . . . . . . . . . .
+
+#endif // end: XTRA_PROCPS_DEBUG_H