Merge remote-tracking branch 'jwpi/hwclock-date7'

* jwpi/hwclock-date7:
  lib: add parse-date documentation
  hwclock: use parse_date function
  build-sys: add parse-date.y
  lib: add parse-date.y
diff --git a/Documentation/boilerplate.c b/Documentation/boilerplate.c
index b210cc3..7da9374 100644
--- a/Documentation/boilerplate.c
+++ b/Documentation/boilerplate.c
@@ -39,11 +39,11 @@
 	fputs(_(" -r, --required <arg>    option requires an argument\n"), out);
 	fputs(_(" -z                      no long option\n"), out);
 	fputs(_("     --xyzzy             a long option only\n"), out);
-	fputs(_(" -e, --extremely-long-long-option\n"), out);
-	fputs(_("                         use next line for description when needed\n"), out);
-	fputs(_(" -l, --long-explanation  an example of very verbose, and chatty option\n"), out);
-	fputs(_("                           description on two, or multiple lines, where the\n"), out);
-	fputs(_("                           consecutive lines are intended by two spaces\n"), out);
+	fputs(_(" -e, --extremely-long-long-option\n"
+		"                         use next line for description when needed\n"), out);
+	fputs(_(" -l, --long-explanation  an example of very verbose, and chatty option\n"
+		"                           description on two, or multiple lines, where the\n"
+		"                           consecutive lines are intended by two spaces\n"), out);
 	fputs(_(" -f, --foobar            next option description resets indent\n"), out);
 	fputs(USAGE_SEPARATOR, out);
 	fputs(USAGE_HELP, out);
@@ -77,11 +77,12 @@
 	textdomain(PACKAGE);
 	atexit(close_stdout);
 
-	while ((c = getopt_long(argc, argv, "nr:elfVh", longopts, NULL)) != -1)
+	while ((c = getopt_long(argc, argv, "nr:zelfVh", longopts, NULL)) != -1)
 		switch (c) {
 		case 'n':
 		case OPT_OPTIONAL:
 		case 'r':
+		case 'z':
 		case OPT_XYZZY:
 		case 'e':
 		case 'l':
diff --git a/disk-utils/cfdisk.c b/disk-utils/cfdisk.c
index f06dad1..cc4a867 100644
--- a/disk-utils/cfdisk.c
+++ b/disk-utils/cfdisk.c
@@ -1530,14 +1530,14 @@
 		return 0;
 	}
 
-	DBG(MENU, ul_debug(" no memu move key"));
+	DBG(MENU, ul_debug(" no menu move key"));
 	return 1;
 }
 
 /* but don't call me from ui_run(), this is for pop-up menus only */
 static void ui_menu_resize(struct cfdisk *cf)
 {
-	DBG(MENU, ul_debug("memu resize/refresh"));
+	DBG(MENU, ul_debug("menu resize/refresh"));
 	resize();
 	ui_clean_menu(cf);
 	menu_refresh_size(cf);
@@ -2092,6 +2092,8 @@
 
 
 	do {
+		int key;
+
 		if (refresh_menu) {
 			ui_draw_menu(cf);
 			ui_hint(_("Select a type to create a new label or press 'L' to load script file."));
@@ -2099,7 +2101,7 @@
 			refresh_menu = 0;
 		}
 
-		int key = getch();
+		key = getch();
 
 		if (ui_resize)
 			ui_menu_resize(cf);
diff --git a/disk-utils/fdisk.c b/disk-utils/fdisk.c
index 4ac58ee..f1cd3aa 100644
--- a/disk-utils/fdisk.c
+++ b/disk-utils/fdisk.c
@@ -23,6 +23,7 @@
 #include <limits.h>
 #include <libsmartcols.h>
 #ifdef HAVE_LIBREADLINE
+# define _FUNCTION_DEF
 # include <readline/readline.h>
 #endif
 
diff --git a/disk-utils/sfdisk.c b/disk-utils/sfdisk.c
index f4f9b6b..4603483 100644
--- a/disk-utils/sfdisk.c
+++ b/disk-utils/sfdisk.c
@@ -33,6 +33,7 @@
 #include <fcntl.h>
 #include <libsmartcols.h>
 #ifdef HAVE_LIBREADLINE
+# define _FUNCTION_DEF
 # include <readline/readline.h>
 #endif
 #include <libgen.h>
@@ -1495,7 +1496,7 @@
 static int wipe_partition(struct sfdisk *sf, size_t partno)
 {
 	int rc, yes = 0;
-	char *fstype = NULL;;
+	char *fstype = NULL;
 	struct fdisk_partition *tmp = NULL;
 
 	DBG(MISC, ul_debug("checking for signature"));
diff --git a/include/optutils.h b/include/optutils.h
index 99ad7e4..325cb88 100644
--- a/include/optutils.h
+++ b/include/optutils.h
@@ -1,6 +1,8 @@
 #ifndef UTIL_LINUX_OPTUTILS_H
 #define UTIL_LINUX_OPTUTILS_H
 
+#include <assert.h>
+
 #include "c.h"
 #include "nls.h"
 
@@ -8,6 +10,7 @@
 {
 	const struct option *o;
 
+	assert(!(opts == NULL));
 	for (o = opts; o->name; o++)
 		if (o->val == c)
 			return o->name;
diff --git a/include/pt-mbr.h b/include/pt-mbr.h
index 90be95b..177cc74 100644
--- a/include/pt-mbr.h
+++ b/include/pt-mbr.h
@@ -1,6 +1,8 @@
 #ifndef UTIL_LINUX_PT_MBR_H
 #define UTIL_LINUX_PT_MBR_H
 
+#include <assert.h>
+
 struct dos_partition {
 	unsigned char boot_ind;		/* 0x80 - active */
 	unsigned char bh, bs, bc;	/* begin CHS */
@@ -27,6 +29,7 @@
 
 static inline void __dos_store_4le(unsigned char *p, unsigned int val)
 {
+	assert(!(p == NULL));
 	p[0] = (val & 0xff);
 	p[1] = ((val >> 8) & 0xff);
 	p[2] = ((val >> 16) & 0xff);
diff --git a/lib/colors.c b/lib/colors.c
index 4b280fe..dda6170 100644
--- a/lib/colors.c
+++ b/lib/colors.c
@@ -342,6 +342,7 @@
 static int cn_sequence(const char *str, char **seq)
 {
 	char *in, *out;
+	int len;
 
 	if (!str)
 		return -EINVAL;
@@ -357,7 +358,7 @@
 	}
 
 	/* convert xx;yy sequences to "\033[xx;yy" */
-	if (asprintf(seq, "\033[%sm", str) < 1)
+	if ((len = asprintf(seq, "\033[%sm", str)) < 1)
 		return -ENOMEM;
 
 	for (in = *seq, out = *seq; in && *in; in++) {
@@ -409,6 +410,8 @@
 		}
 		in++;
 	}
+
+	assert ((out - *seq) <= len);
 	*out = '\0';
 
 	return 0;
diff --git a/libblkid/src/config.c b/libblkid/src/config.c
index 1822f1c..52f159d 100644
--- a/libblkid/src/config.c
+++ b/libblkid/src/config.c
@@ -88,7 +88,7 @@
 	} while (*s == '\0' || *s == '#');
 
 	if (!strncmp(s, "SEND_UEVENT=", 12)) {
-		s += 13;
+		s += 12;
 		if (*s && !strcasecmp(s, "yes"))
 			conf->uevent = TRUE;
 		else if (*s)
diff --git a/libblkid/src/superblocks/drbdmanage.c b/libblkid/src/superblocks/drbdmanage.c
index 48bf1da..b45f89b 100644
--- a/libblkid/src/superblocks/drbdmanage.c
+++ b/libblkid/src/superblocks/drbdmanage.c
@@ -35,7 +35,7 @@
 } __attribute__ ((packed));
 
 
-static const char persistence_magic[4] = "\x1a\xdb\x98\xa2";
+static const char persistence_magic[4] = { '\x1a', '\xdb', '\x98', '\xa2' };
 
 
 static int probe_drbdmanage(blkid_probe pr,
diff --git a/libblkid/src/superblocks/minix.c b/libblkid/src/superblocks/minix.c
index feebc96..c47378d 100644
--- a/libblkid/src/superblocks/minix.c
+++ b/libblkid/src/superblocks/minix.c
@@ -77,6 +77,9 @@
 	unsigned char *ext;
 	const unsigned char *data;
 	int version = 0, swabme = 0;
+	unsigned long zones, ninodes, imaps, zmaps;
+	off_t firstz;
+	size_t zone_size;
 
 	data = blkid_probe_get_buffer(pr, 1024,
 			max(sizeof(struct minix_super_block),
@@ -84,14 +87,9 @@
 	if (!data)
 		return errno ? -errno : 1;
 	version = get_minix_version(data, &swabme);
-	if (version < 1)
-		return 1;
-
-	unsigned long zones, ninodes, imaps, zmaps;
-	off_t firstz;
-	size_t zone_size;
-
-	if (version <= 2) {
+	switch (version) {
+	case 1:
+	case 2: {
 		struct minix_super_block *sb = (struct minix_super_block *) data;
 
 		uint16_t state = minix_swab16(swabme, sb->s_state);
@@ -105,7 +103,9 @@
 		zmaps   = minix_swab16(swabme, sb->s_zmap_blocks);
 		firstz  = minix_swab16(swabme, sb->s_firstdatazone);
 		zone_size = sb->s_log_zone_size;
-	} else if (version == 3) {
+		break;
+	}
+	case 3: {
 		struct minix3_super_block *sb = (struct minix3_super_block *) data;
 
 		zones = minix_swab32(swabme, sb->s_zones);
@@ -114,6 +114,10 @@
 		zmaps   = minix_swab16(swabme, sb->s_zmap_blocks);
 		firstz  = minix_swab16(swabme, sb->s_firstdatazone);
 		zone_size = sb->s_log_zone_size;
+		break;
+	}
+	default:
+		return 1;
 	}
 
 	/* sanity checks to be sure that the FS is really minix.
diff --git a/libfdisk/src/dos.c b/libfdisk/src/dos.c
index 11946b3..39e42e3 100644
--- a/libfdisk/src/dos.c
+++ b/libfdisk/src/dos.c
@@ -249,6 +249,9 @@
 	unsigned char *buf;
 	struct pte *pe = self_pte(cxt, pno);
 
+	if (!pe)
+		return -EINVAL;
+
 	buf = calloc(1, cxt->sector_size);
 	if (!buf)
 		return -ENOMEM;
@@ -311,6 +314,7 @@
 	for (i = 0; i < 4; i++) {
 		struct pte *pe = self_pte(cxt, i);
 
+		assert(pe);
 		pe->pt_entry = mbr_get_partition(cxt->firstsector, i);
 		pe->ex_entry = NULL;
 		pe->offset = 0;
@@ -502,6 +506,10 @@
 
 	l->ext_index = ext;
 	pex = self_pte(cxt, ext);
+	if (!pex) {
+		DBG(LABEL, ul_debug("DOS: uninitialized pointer to %zu pex", ext));
+		return;
+	}
 	pex->ex_entry = pex->pt_entry;
 
 	p = pex->pt_entry;
@@ -513,8 +521,6 @@
 	DBG(LABEL, ul_debug("DOS: Reading extended %zu", ext));
 
 	while (IS_EXTENDED (p->sys_ind)) {
-		pe = self_pte(cxt, cxt->label->nparts_max);
-
 		if (cxt->label->nparts_max >= MAXIMUM_PARTS) {
 			/* This is not a Linux restriction, but
 			   this program uses arrays of size MAXIMUM_PARTS.
@@ -526,12 +532,18 @@
 			  "if you save this partition table."),
 				cxt->label->nparts_max);
 
-			clear_partition(pre->ex_entry);
-			partition_set_changed(cxt,
-					cxt->label->nparts_max - 1, 1);
+			if (pre) {
+				clear_partition(pre->ex_entry);
+				partition_set_changed(cxt,
+						cxt->label->nparts_max - 1, 1);
+			}
 			return;
 		}
 
+		pe = self_pte(cxt, cxt->label->nparts_max);
+		if (!pe)
+			return;
+
 		if (read_pte(cxt, cxt->label->nparts_max, l->ext_offset +
 						dos_partition_get_start(p)))
 			return;
@@ -596,7 +608,8 @@
 
 	/* remove last empty EBR */
 	pe = self_pte(cxt, cxt->label->nparts_max - 1);
-	if (is_cleared_partition(pe->ex_entry) &&
+	if (pe &&
+	    is_cleared_partition(pe->ex_entry) &&
 	    is_cleared_partition(pe->pt_entry)) {
 		DBG(LABEL, ul_debug("DOS: EBR[offset=%ju]: empty, remove", (uintmax_t) pe->offset));
 		reset_pte(pe);
@@ -610,8 +623,8 @@
 	for (i = 4; i < cxt->label->nparts_max; i++) {
 		p = self_partition(cxt, i);
 
-		if (!dos_partition_get_size(p) &&
-		    (cxt->label->nparts_max > 5 || q->sys_ind)) {
+		if (p && !dos_partition_get_size(p) &&
+		    (cxt->label->nparts_max > 5 || (q && q->sys_ind))) {
 			fdisk_info(cxt, _("omitting empty partition (%zu)"), i+1);
 			dos_delete_partition(cxt, i);
 			goto remove; 	/* numbering changed */
@@ -798,6 +811,7 @@
 	for (i = 0; i < 4; i++) {
 		struct pte *pe = self_pte(cxt, i);
 
+		assert(pe);
 		if (is_used_partition(pe->pt_entry))
 			cxt->label->nparts_cur++;
 
@@ -815,6 +829,7 @@
 		struct pte *pe = self_pte(cxt, i);
 		struct fdisk_dos_label *l = self_label(cxt);
 
+		assert(pe);
 		if (!mbr_is_valid_magic(pe->sectorbuffer)) {
 			fdisk_info(cxt, _(
 			"Invalid flag 0x%02x%02x of EBR (for partition %zu) will "
@@ -843,6 +858,7 @@
 
 	assert(!FDISK_IS_UNDEF(start));
 	assert(!FDISK_IS_UNDEF(stop));
+	assert(pe);
 
 	if (doext) {
 		struct fdisk_dos_label *l = self_label(cxt);
@@ -884,6 +900,7 @@
 		fdisk_sector_t lastplusoff;
 		struct pte *pe = self_pte(cxt, i);
 
+		assert(pe);
 		if (start == pe->offset)
 			start += cxt->first_lba;
 		lastplusoff = last[i] + ((part_n < 4) ? 0 : cxt->first_lba);
@@ -901,6 +918,7 @@
 	struct pte *pe = self_pte(cxt, 0);
 	struct dos_partition *p;
 
+	assert(pe);
 	for (i = 0; i < cxt->label->nparts_max; pe++,i++) {
 		p = pe->pt_entry;
 		if (is_cleared_partition(p) || IS_EXTENDED (p->sys_ind)) {
@@ -1007,6 +1025,7 @@
 	for (i = 0; i < cxt->label->nparts_max; i++) {
 		struct pte *pe = self_pte(cxt, i);
 
+		assert(pe);
 		if (start < pe->offset && limit >= pe->offset)
 			limit = pe->offset - 1;
 		if (start < first[i] && limit >= first[i])
@@ -1036,7 +1055,7 @@
 
 	sys = pa && pa->type ? pa->type->code : MBR_LINUX_DATA_PARTITION;
 
-	if (is_used_partition(p)) {
+	if (p && is_used_partition(p)) {
 		fdisk_warnx(cxt, _("Partition %zu is already defined.  "
 			           "Delete it before re-adding it."),
 				n + 1);
@@ -1127,12 +1146,14 @@
 	if (n == 4) {
 		/* The first EBR is stored at begin of the extended partition */
 		struct pte *pe = self_pte(cxt, n);
-		pe->offset = l->ext_offset;
 
+		assert(pe);
+		pe->offset = l->ext_offset;
 	} else if (n > 4) {
 		/* The second (and another) EBR */
 		struct pte *pe = self_pte(cxt, n);
 
+		assert(pe);
 		pe->offset = start - cxt->first_lba;
 		if (pe->offset == l->ext_offset) { /* must be corrected */
 			pe->offset++;
@@ -1235,6 +1256,8 @@
 	set_partition(cxt, n, 0, start, stop, sys, fdisk_partition_is_bootable(pa));
 	if (n > 4) {
 		struct pte *pe = self_pte(cxt, n);
+
+		assert(pe);
 		set_partition(cxt, n - 1, 1, pe->offset, stop,
 					MBR_DOS_EXTENDED_PARTITION, 0);
 	}
@@ -1251,6 +1274,7 @@
 	if (IS_EXTENDED(sys)) {
 		struct pte *pen = self_pte(cxt, n);
 
+		assert(pen);
 		l->ext_index = n;
 		l->ext_offset = start;
 		pen->ex_entry = p;
@@ -1277,6 +1301,7 @@
 
 	DBG(LABEL, ul_debug("DOS: nparts max: %zu", cxt->label->nparts_max));
 	pe = self_pte(cxt, cxt->label->nparts_max);
+	assert(pe);
 
 	if (!pe->sectorbuffer) {
 		pe->sectorbuffer = calloc(1, cxt->sector_size);
@@ -1436,8 +1461,9 @@
 		struct pte *pe = self_pte(cxt, i);
 
 		p = self_partition(cxt, i);
-		if (is_used_partition(p) && !IS_EXTENDED(p->sys_ind)) {
+		if (p && is_used_partition(p) && !IS_EXTENDED(p->sys_ind)) {
 			check_consistency(cxt, p, i);
+			assert(pe);
 			if (get_abs_partition_start(pe) < first[i])
 				fdisk_warnx(cxt, _(
 					"Partition %zu: bad start-of-data."),
@@ -1470,11 +1496,13 @@
 		fdisk_sector_t e_last;
 		struct pte *ext_pe = self_pte(cxt, l->ext_index);
 
+		assert(ext_pe);
 		e_last = get_abs_partition_end(ext_pe);
 
 		for (i = 4; i < cxt->label->nparts_max; i++) {
 			total++;
 			p = self_partition(cxt, i);
+			assert(p);
 
 			if (!p->sys_ind) {
 				if (i != 4 || i + 1 < cxt->label->nparts_max)
@@ -1592,6 +1620,7 @@
 	for (i = 0; i < 4; i++) {
 		struct dos_partition *p = self_partition(cxt, i);
 
+		assert(p);
 		if (is_used_partition(p)) {
 			fdisk_sector_t start = dos_partition_get_start(p);
 			if (last + grain <= start)
@@ -1759,6 +1788,8 @@
 	if (!mbr_changed) {
 		for (i = 0; i < 4; i++) {
 			struct pte *pe = self_pte(cxt, i);
+
+			assert(pe);
 			if (pe->changed)
 				mbr_changed = 1;
 		}
@@ -1788,6 +1819,7 @@
 	for (i = 4; i < cxt->label->nparts_max; i++) {
 		struct pte *pe = self_pte(cxt, i);
 
+		assert(pe);
 		if (!pe->changed || !pe->offset || !pe->sectorbuffer)
 			continue;
 
@@ -1821,6 +1853,7 @@
 		if ((size_t)n - 1 + 4 < cxt->label->nparts_max) {
 			struct pte *pe = self_pte(cxt, n - 1 + 4);
 
+			assert(pe);
 			assert(pe->private_sectorbuffer);
 
 			*name = "EBR";
@@ -1847,7 +1880,10 @@
 	for (i = 0 ; i < cxt->label->nparts_max; i++) {
 
 		struct pte *pe = self_pte(cxt, i);
-		struct dos_partition *p = pe->pt_entry;
+		struct dos_partition *p;
+
+		assert(pe);
+		p = pe->pt_entry;
 
 		if (i == 4) {
 			last_i = 4;
@@ -1912,7 +1948,10 @@
 	assert(fdisk_is_label(cxt, DOS));
 
 	lb = self_label(cxt);
+
 	pe = self_pte(cxt, n);
+	assert(pe);
+
 	p = pe->pt_entry;
 	pa->used = !is_cleared_partition(p);
 	if (!pa->used)
@@ -1978,7 +2017,11 @@
 
 	l = self_label(cxt);
 	p = self_partition(cxt, n);
+
 	pe = self_pte(cxt, n);
+	if (!pe)
+		return -EINVAL;
+
 	orgtype = p->sys_ind;
 
 	if (pa->type) {
@@ -2058,6 +2101,7 @@
 	for (i = 4; i < cxt->label->nparts_max; i++) {
 		struct pte *pe = self_pte(cxt, i);
 
+		assert(pe);
 		fprintf(stderr, "#%02zu EBR [%10ju], "
 			"data[start=%10ju (%10ju), size=%10ju], "
 			"link[start=%10ju (%10ju), size=%10ju]\n",
@@ -2114,6 +2158,9 @@
 		struct pte *cur = self_pte(cxt, i),
 			   *nxt = self_pte(cxt, i + 1);
 
+		assert(cur);
+		assert(nxt);
+
 		if (get_abs_partition_start(cur) >
 		    get_abs_partition_start(nxt)) {
 
@@ -2141,8 +2188,11 @@
 		struct pte *cur = self_pte(cxt, i),
 			   *nxt = self_pte(cxt, i + 1);
 
+		assert(cur);
+		assert(nxt);
+
 		fdisk_sector_t noff = nxt->offset - l->ext_offset,
-			 ooff = dos_partition_get_start(cur->ex_entry);
+		 ooff = dos_partition_get_start(cur->ex_entry);
 
 		if (noff == ooff)
 			continue;
@@ -2183,6 +2233,9 @@
 		pei = self_pte(cxt, i);
 		pek = self_pte(cxt, k);
 
+		assert(pei);
+		assert(pek);
+
 		pe = pei->ex_entry;
 		pei->ex_entry = pek->ex_entry;
 		pek->ex_entry = pe;
@@ -2218,6 +2271,9 @@
 	assert(fdisk_is_label(cxt, DOS));
 
 	pe = self_pte(cxt, i);
+	if (!pe)
+		return -EINVAL;
+
 	p = pe->pt_entry;
 
 	if (!is_used_partition(p) || IS_EXTENDED (p->sys_ind)) {
@@ -2236,8 +2292,11 @@
 	for (x = 0; x < cxt->label->nparts_max; x++) {
 		unsigned int end;
 		struct pte *prev_pe = self_pte(cxt, x);
-		struct dos_partition *prev_p = prev_pe->pt_entry;
+		struct dos_partition *prev_p;
 
+		assert(prev_pe);
+
+		prev_p = prev_pe->pt_entry;
 		if (!prev_p)
 			continue;
 		end = get_abs_partition_start(prev_pe)
diff --git a/libfdisk/src/gpt.c b/libfdisk/src/gpt.c
index 6962e77..c99b16f 100644
--- a/libfdisk/src/gpt.c
+++ b/libfdisk/src/gpt.c
@@ -830,7 +830,7 @@
 	sz = (ssize_t) le32_to_cpu(header->npartition_entries) *
 	     le32_to_cpu(header->sizeof_partition_entry);
 
-	if (sz == 0 || sz >= UINT32_MAX ||
+	if (sz == 0 || sz >= (ssize_t) UINT32_MAX ||
 	    le32_to_cpu(header->sizeof_partition_entry) != sizeof(struct gpt_entry)) {
 		DBG(LABEL, ul_debug("GPT entreis array size check failed"));
 		return NULL;
diff --git a/libfdisk/src/partition.c b/libfdisk/src/partition.c
index 1e8c1eb..4017096 100644
--- a/libfdisk/src/partition.c
+++ b/libfdisk/src/partition.c
@@ -1243,6 +1243,10 @@
 
 	if (pa->resize || fdisk_partition_has_start(pa) || fdisk_partition_has_size(pa)) {
 		xpa = __copy_partition(pa);
+		if (!xpa) {
+			rc = -ENOMEM;
+			goto done;
+		}
 		xpa->movestart = 0;
 		xpa->resize = 0;
 		FDISK_INIT_UNDEF(xpa->size);
diff --git a/libmount/src/context_mount.c b/libmount/src/context_mount.c
index 23f0e30..6368e9b 100644
--- a/libmount/src/context_mount.c
+++ b/libmount/src/context_mount.c
@@ -987,7 +987,7 @@
 	} else
 		res = do_mount_by_pattern(cxt, cxt->fstype_pattern);
 
-#if USE_LIBMOUNT_SUPPORT_MTAB
+#ifdef USE_LIBMOUNT_SUPPORT_MTAB
 	if (mnt_context_get_status(cxt)
 	    && !mnt_context_is_fake(cxt)
 	    && !cxt->helper) {
diff --git a/login-utils/last.c b/login-utils/last.c
index 3407057..679ea6c 100644
--- a/login-utils/last.c
+++ b/login-utils/last.c
@@ -505,10 +505,12 @@
 	if (ctl->usedns || ctl->useip)
 		r = dns_lookup(domain, sizeof(domain), ctl->useip, p->ut_addr_v6);
 	if (r < 0) {
-		len = sizeof(p->ut_host);
-		if (len >= (int)sizeof(domain)) len = sizeof(domain) - 1;
-		domain[0] = 0;
-		strncat(domain, p->ut_host, len);
+		size_t sz = sizeof(p->ut_host);
+
+		if (sz > sizeof(domain))
+			sz = sizeof(domain);
+
+		xstrncpy(domain, p->ut_host, sz);
 	}
 
 
diff --git a/login-utils/logindefs.c b/login-utils/logindefs.c
index f02c475..213ff8d 100644
--- a/login-utils/logindefs.c
+++ b/login-utils/logindefs.c
@@ -344,7 +344,8 @@
 				continue;	/* ignore errors... */
 
 			while (ok == 0 && fgets(buf, sizeof(buf), f)) {
-				buf[strlen(buf) - 1] = '\0';
+				if (buf[0] != '\0')
+					buf[strlen(buf) - 1] = '\0';
 				ok = !strcmp(buf, *buf == '/' ? pwd->pw_shell :
 								pwd->pw_name);
 			}
diff --git a/misc-utils/blkid.c b/misc-utils/blkid.c
index 9278553..cc29b5c 100644
--- a/misc-utils/blkid.c
+++ b/misc-utils/blkid.c
@@ -43,6 +43,7 @@
 #define CLOSE_EXIT_CODE		BLKID_EXIT_OTHER	/* close_stdout() */
 #include "closestream.h"
 
+#include "nls.h"
 #include "ttyutils.h"
 #include "xalloc.h"
 
@@ -50,7 +51,7 @@
 
 static void print_version(FILE *out)
 {
-	fprintf(out, "%s from %s  (libblkid %s, %s)\n",
+	fprintf(out, _("%s from %s  (libblkid %s, %s)\n"),
 		program_invocation_short_name, PACKAGE_STRING,
 		LIBBLKID_VERSION, LIBBLKID_DATE);
 }
@@ -59,40 +60,39 @@
 {
 	FILE *out = error ? stderr : stdout;
 
-	print_version(out);
-	fprintf(out,
-		"Usage:\n"
-		" %1$s -L <label> | -U <uuid>\n\n"
-		" %1$s [-c <file>] [-ghlLv] [-o <format>] [-s <tag>] \n"
-		"       [-t <token>] [<dev> ...]\n\n"
-		" %1$s -p [-s <tag>] [-O <offset>] [-S <size>] \n"
-		"       [-o <format>] <dev> ...\n\n"
-		" %1$s -i [-s <tag>] [-o <format>] <dev> ...\n\n"
-		"Options:\n"
-		" -c <file>   read from <file> instead of reading from the default\n"
-		"               cache file (-c /dev/null means no cache)\n"
-		" -d          don't encode non-printing characters\n"
-		" -h          print this usage message and exit\n"
-		" -g          garbage collect the blkid cache\n"
-		" -o <format> output format; can be one of:\n"
-		"               value, device, export or full; (default: full)\n"
-		" -k          list all known filesystems/RAIDs and exit\n"
-		" -s <tag>    show specified tag(s) (default show all tags)\n"
-		" -t <token>  find device with a specific token (NAME=value pair)\n"
-		" -l          look up only first device with token specified by -t\n"
-		" -L <label>  convert LABEL to device name\n"
-		" -U <uuid>   convert UUID to device name\n"
-		" -V          print version and exit\n"
-		" <dev>       specify device(s) to probe (default: all devices)\n\n"
-		"Low-level probing options:\n"
-		" -p          low-level superblocks probing (bypass cache)\n"
-		" -i          gather information about I/O limits\n"
-		" -S <size>   overwrite device size\n"
-		" -O <offset> probe at the given offset\n"
-		" -u <list>   filter by \"usage\" (e.g. -u filesystem,raid)\n"
-		" -n <list>   filter by filesystem type (e.g. -n vfat,ext3)\n"
-		"\n", program_invocation_short_name);
+	fputs(USAGE_HEADER, out);
+	fprintf(out, _(	" %s -L <label> | -U <uuid>\n\n"), program_invocation_short_name);
+	fprintf(out, _(	" %s [-c <file>] [-ghlLv] [-o <format>] [-s <tag>] \n"
+			"       [-t <token>] [<dev> ...]\n\n"), program_invocation_short_name);
+	fprintf(out, _(	" %s -p [-s <tag>] [-O <offset>] [-S <size>] \n"
+			"       [-o <format>] <dev> ...\n\n"), program_invocation_short_name);
+	fprintf(out, _(	" %s -i [-s <tag>] [-o <format>] <dev> ...\n"), program_invocation_short_name);
+	fputs(USAGE_OPTIONS, out);
+	fputs(_(	" -c <file>   read from <file> instead of reading from the default\n"
+			"               cache file (-c /dev/null means no cache)\n"), out);
+	fputs(_(	" -d          don't encode non-printing characters\n"), out);
+	fputs(_(	" -h          print this usage message and exit\n"), out);
+	fputs(_(	" -g          garbage collect the blkid cache\n"), out);
+	fputs(_(	" -o <format> output format; can be one of:\n"
+			"               value, device, export or full; (default: full)\n"), out);
+	fputs(_(	" -k          list all known filesystems/RAIDs and exit\n"), out);
+	fputs(_(	" -s <tag>    show specified tag(s) (default show all tags)\n"), out);
+	fputs(_(	" -t <token>  find device with a specific token (NAME=value pair)\n"), out);
+	fputs(_(	" -l          look up only first device with token specified by -t\n"), out);
+	fputs(_(	" -L <label>  convert LABEL to device name\n"), out);
+	fputs(_(	" -U <uuid>   convert UUID to device name\n"), out);
+	fputs(_(	" -V          print version and exit\n"), out);
+	fputs(_(	" <dev>       specify device(s) to probe (default: all devices)\n"), out);
+	fputs(          "\n", out);
+	fputs(_(	"Low-level probing options:\n"), out);
+	fputs(_(	" -p          low-level superblocks probing (bypass cache)\n"), out);
+	fputs(_(	" -i          gather information about I/O limits\n"), out);
+	fputs(_(	" -S <size>   overwrite device size\n"), out);
+	fputs(_(	" -O <offset> probe at the given offset\n"), out);
+	fputs(_(	" -u <list>   filter by \"usage\" (e.g. -u filesystem,raid)\n"), out);
+	fputs(_(	" -n <list>   filter by filesystem type (e.g. -n vfat,ext3)\n"), out);
 
+	fprintf(out, USAGE_MAN_TAIL("blkid(8)"));
 	exit(error);
 }
 
@@ -139,9 +139,9 @@
 		len = 0;
 	} else if (len > max_len)
 		ret = len - max_len;
-	do
+	do {
 		fputc(' ', stdout);
-	while (len++ < max_len);
+	} while (len++ < max_len);
 	return ret;
 }
 
@@ -219,11 +219,11 @@
 	if (retval == 0) {
 		if (mount_flags & MF_MOUNTED) {
 			if (!mtpt[0])
-				strcpy(mtpt, "(mounted, mtpt unknown)");
+				strcpy(mtpt, _("(mounted, mtpt unknown)"));
 		} else if (mount_flags & MF_BUSY)
-			strcpy(mtpt, "(in use)");
+			strcpy(mtpt, _("(in use)"));
 		else
-			strcpy(mtpt, "(not mounted)");
+			strcpy(mtpt, _("(not mounted)"));
 	}
 
 	pretty_print_line(devname, fs_type, label, mtpt, uuid);
@@ -487,7 +487,7 @@
 
 	fd = open(devname, O_RDONLY|O_CLOEXEC);
 	if (fd < 0) {
-		fprintf(stderr, "error: %s: %m\n", devname);
+		warn(_("error: %s"), devname);
 		return BLKID_EXIT_NOTFOUND;
 	}
 	if (blkid_probe_set_device(pr, fd, offset, size))
@@ -531,10 +531,9 @@
 		if (output & OUTPUT_UDEV_LIST)
 			print_udev_ambivalent(pr);
 		else
-			fprintf(stderr,
-				"%s: ambivalent result (probably more "
+			warnx(_("%s: ambivalent result (probably more "
 				"filesystems on the device, use wipefs(8) "
-				"to see more details)\n",
+				"to see more details)"),
 				devname);
 	}
 	close(fd);
@@ -578,7 +577,7 @@
 	return mask;
 err:
 	*flag = 0;
-	fprintf(stderr, "unknown keyword in -u <list> argument: '%s'\n",
+	warnx(_("unknown keyword in -u <list> argument: '%s'"),
 			word ? word : list);
 	exit(BLKID_EXIT_OTHER);
 }
@@ -595,7 +594,7 @@
 		p += 2;
 	}
 	if (!p || !*p) {
-		fprintf(stderr, "error: -u <list> argument is empty\n");
+		warnx(_("error: -u <list> argument is empty"));
 		goto err;
 	}
 	for (i = 1; p && (p = strchr(p, ',')); i++, p++);
@@ -656,6 +655,9 @@
 	int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT;
 
 	show[0] = NULL;
+	setlocale(LC_ALL, "");
+	bindtextdomain(PACKAGE, LOCALEDIR);
+	textdomain(PACKAGE);
 	atexit(close_stdout);
 
 	while ((c = getopt (argc, argv,
@@ -720,41 +722,37 @@
 				output_format = OUTPUT_EXPORT_LIST;
 			else if (!strcmp(optarg, "full"))
 				output_format = 0;
-			else {
-				fprintf(stderr, "Invalid output format %s. "
-					"Choose from value,\n\t"
-					"device, list, udev or full\n", optarg);
-				exit(BLKID_EXIT_OTHER);
-			}
+			else
+				errx(BLKID_EXIT_OTHER, _("unsupported output format %s"), optarg);
 			break;
 		case 'O':
-			offset = strtosize_or_err(optarg, "invalid offset argument");
+			offset = strtosize_or_err(optarg, _("invalid offset argument"));
 			break;
 		case 'p':
 			lowprobe |= LOWPROBE_SUPERBLOCKS;
 			break;
 		case 's':
 			if (numtag + 1 >= sizeof(show) / sizeof(*show)) {
-				fprintf(stderr, "Too many tags specified\n");
-				usage(err);
+				warnx(_("Too many tags specified"));
+				errtryh(err);
 			}
 			show[numtag++] = optarg;
 			show[numtag] = NULL;
 			break;
 		case 'S':
-			size = strtosize_or_err(optarg, "invalid size argument");
+			size = strtosize_or_err(optarg, _("invalid size argument"));
 			break;
 		case 't':
 			if (search_type) {
-				fprintf(stderr, "Can only search for "
-						"one NAME=value pair\n");
-				usage(err);
+				warnx(_("Can only search for "
+					"one NAME=value pair"));
+				errtryh(err);
 			}
 			if (blkid_parse_tag_string(optarg,
 						   &search_type,
 						   &search_value)) {
-				fprintf(stderr, "-t needs NAME=value pair\n");
-				usage(err);
+				warnx(_("-t needs NAME=value pair"));
+				errtryh(err);
 			}
 			break;
 		case 'V':
@@ -803,11 +801,10 @@
 	err = BLKID_EXIT_NOTFOUND;
 
 	if (eval == 0 && (output_format & OUTPUT_PRETTY_LIST)) {
-		if (lowprobe) {
-			fprintf(stderr, "The low-level probing mode does not "
-					"support 'list' output format\n");
-			exit(BLKID_EXIT_OTHER);
-		}
+		if (lowprobe)
+			errx(BLKID_EXIT_OTHER,
+			     _("The low-level probing mode does not "
+			       "support 'list' output format"));
 		pretty_print_dev(NULL);
 	}
 
@@ -817,11 +814,10 @@
 		 */
 		blkid_probe pr;
 
-		if (!numdev) {
-			fprintf(stderr, "The low-level probing mode "
-					"requires a device\n");
-			exit(BLKID_EXIT_OTHER);
-		}
+		if (!numdev)
+			errx(BLKID_EXIT_OTHER,
+			     _("The low-level probing mode "
+			       "requires a device"));
 
 		/* automatically enable 'export' format for I/O Limits */
 		if (!output_format  && (lowprobe & LOWPROBE_TOPOLOGY))
@@ -870,11 +866,10 @@
 		 */
 		blkid_dev dev;
 
-		if (!search_type) {
-			fprintf(stderr, "The lookup option requires a "
-				"search type specified using -t\n");
-			exit(BLKID_EXIT_OTHER);
-		}
+		if (!search_type)
+			errx(BLKID_EXIT_OTHER,
+			     _("The lookup option requires a "
+			       "search type specified using -t"));
 		/* Load any additional devices not in the cache */
 		for (i = 0; i < numdev; i++)
 			blkid_get_dev(cache, devices[i], BLKID_DEV_NORMAL);
diff --git a/sys-utils/lscpu.1 b/sys-utils/lscpu.1
index d00de64..b70f2e1 100644
--- a/sys-utils/lscpu.1
+++ b/sys-utils/lscpu.1
@@ -3,7 +3,7 @@
 lscpu \- display information about the CPU architecture
 .SH SYNOPSIS
 .B lscpu
-.RB [ \-a | \-b | \-c "] [" \-x "] [" \-y "] [" \-s " \fIdirectory\fP] [" \-e [=\fIlist\fP]| \-p [=\fIlist\fP]]
+.RB [ \-a | \-b | \-c | \-J "] [" \-x "] [" \-y "] [" \-s " \fIdirectory\fP] [" \-e [=\fIlist\fP]| \-p [=\fIlist\fP]]
 .br
 .B lscpu
 .BR \-h | \-V
@@ -123,6 +123,10 @@
 .BR \-h , " \-\-help"
 Display help text and exit.
 .TP
+.BR \-J , " \-\-json"
+Use JSON output format for the default summary or extended output (see \fB\-\-extended\fP).
+.BR
+.TP
 .BR \-p , " \-\-parse" [=\fIlist\fP]
 Optimize the command output for easy parsing.
 
diff --git a/sys-utils/lscpu.c b/sys-utils/lscpu.c
index 683fd66..a3b4c8b 100644
--- a/sys-utils/lscpu.c
+++ b/sys-utils/lscpu.c
@@ -299,6 +299,7 @@
 			compat:1,	/* use backwardly compatible format */
 			online:1,	/* print online CPUs */
 			offline:1,	/* print offline CPUs */
+			json:1,		/* JSON output format */
 			physical:1;	/* use physical numbers */
 };
 
@@ -1711,6 +1712,10 @@
 	table = scols_new_table();
 	if (!table)
 		 err(EXIT_FAILURE, _("failed to initialize output table"));
+	if (mod->json) {
+		scols_table_enable_json(table, 1);
+		scols_table_set_name(table, "cpus");
+	}
 
 	for (i = 0; i < ncols; i++) {
 		data = get_cell_header(desc, cols[i], mod, buf, sizeof(buf));
@@ -1747,12 +1752,38 @@
 	scols_unref_table(table);
 }
 
-/* output formats "<key>  <value>"*/
-#define print_s(_key, _val)	printf("%-23s%s\n", _key, _val)
-#define print_n(_key, _val)	printf("%-23s%d\n", _key, _val)
+
+static void __attribute__ ((__format__(printf, 3, 4)))
+	add_summary_sprint(struct libscols_table *tb,
+			const char *txt,
+			const char *fmt,
+			...)
+{
+	struct libscols_line *ln = scols_table_new_line(tb, NULL);
+	char *data;
+	va_list args;
+
+	if (!ln)
+		err(EXIT_FAILURE, _("failed to initialize output line"));
+
+	/* description column */
+	scols_line_set_data(ln, 0, txt);
+
+	/* data column */
+	va_start(args, fmt);
+	xvasprintf(&data, fmt, args);
+	va_end(args);
+
+	if (data)
+		scols_line_refer_data(ln, 1, data);
+}
+
+#define add_summary_n(tb, txt, num)	add_summary_sprint(tb, txt, "%d", num)
+#define add_summary_s(tb, txt, str)	add_summary_sprint(tb, txt, "%s", str)
 
 static void
-print_cpuset(const char *key, cpu_set_t *set, int hex)
+print_cpuset(struct libscols_table *tb,
+	     const char *key, cpu_set_t *set, int hex)
 {
 	size_t setsize = CPU_ALLOC_SIZE(maxcpus);
 	size_t setbuflen = 7 * maxcpus;
@@ -1760,12 +1791,11 @@
 
 	if (hex) {
 		p = cpumask_create(setbuf, setbuflen, set, setsize);
-		printf("%-23s0x%s\n", key, p);
+		add_summary_s(tb, key, p);
 	} else {
 		p = cpulist_create(setbuf, setbuflen, set, setsize);
-		print_s(key, p);
+		add_summary_s(tb, key, p);
 	}
-
 }
 
 /*
@@ -1777,9 +1807,25 @@
 	char buf[512];
 	int i;
 	size_t setsize = CPU_ALLOC_SIZE(maxcpus);
+	struct libscols_table *tb;
 
-	print_s(_("Architecture:"), desc->arch);
+	scols_init_debug(0);
 
+	tb = scols_new_table();
+	if (!tb)
+		 err(EXIT_FAILURE, _("failed to initialize output table"));
+
+	scols_table_enable_noheadings(tb, 1);
+	if (mod->json) {
+		scols_table_enable_json(tb, 1);
+		scols_table_set_name(tb, "lscpu");
+	}
+
+	if (scols_table_new_column(tb, "field", 0, 0) == NULL ||
+	    scols_table_new_column(tb, "data", 0, SCOLS_FL_NOEXTREMES) == NULL)
+		err(EXIT_FAILURE, _("failed to initialize output column"));
+
+	add_summary_s(tb, _("Architecture:"), desc->arch);
 	if (desc->mode) {
 		char mbuf[64], *p = mbuf;
 
@@ -1792,18 +1838,18 @@
 			p += 8;
 		}
 		*(p - 2) = '\0';
-		print_s(_("CPU op-mode(s):"), mbuf);
+		add_summary_s(tb, _("CPU op-mode(s):"), mbuf);
 	}
 #if !defined(WORDS_BIGENDIAN)
-	print_s(_("Byte Order:"), "Little Endian");
+	add_summary_s(tb, _("Byte Order:"), "Little Endian");
 #else
-	print_s(_("Byte Order:"), "Big Endian");
+	add_summary_s(tb, _("Byte Order:"), "Big Endian");
 #endif
-	print_n(_("CPU(s):"), desc->ncpus);
+	add_summary_n(tb, _("CPU(s):"), desc->ncpus);
 
 	if (desc->online)
-		print_cpuset(mod->hex ? _("On-line CPU(s) mask:") :
-					_("On-line CPU(s) list:"),
+		print_cpuset(tb, mod->hex ? _("On-line CPU(s) mask:") :
+					    _("On-line CPU(s) list:"),
 				desc->online, mod->hex);
 
 	if (desc->online && CPU_COUNT_S(setsize, desc->online) != desc->ncpus) {
@@ -1822,8 +1868,8 @@
 			if (!is_cpu_online(desc, cpu) && is_cpu_present(desc, cpu))
 				CPU_SET_S(cpu, setsize, set);
 		}
-		print_cpuset(mod->hex ? _("Off-line CPU(s) mask:") :
-					_("Off-line CPU(s) list:"),
+		print_cpuset(tb, mod->hex ? _("Off-line CPU(s) mask:") :
+					    _("Off-line CPU(s) list:"),
 			     set, mod->hex);
 		cpuset_free(set);
 	}
@@ -1859,97 +1905,99 @@
 		}
 		if (desc->mtid)
 			threads_per_core = atoi(desc->mtid) + 1;
-		print_n(_("Thread(s) per core:"),
+		add_summary_n(tb, _("Thread(s) per core:"),
 			threads_per_core ?: desc->nthreads / desc->ncores);
-		print_n(_("Core(s) per socket:"),
+		add_summary_n(tb, _("Core(s) per socket:"),
 			cores_per_socket ?: desc->ncores / desc->nsockets);
 		if (desc->nbooks) {
-			print_n(_("Socket(s) per book:"),
+			add_summary_n(tb, _("Socket(s) per book:"),
 				sockets_per_book ?: desc->nsockets / desc->nbooks);
 			if (desc->ndrawers) {
-				print_n(_("Book(s) per drawer:"),
+				add_summary_n(tb, _("Book(s) per drawer:"),
 					books_per_drawer ?: desc->nbooks / desc->ndrawers);
-				print_n(_("Drawer(s):"), drawers ?: desc->ndrawers);
+				add_summary_n(tb, _("Drawer(s):"), drawers ?: desc->ndrawers);
 			} else {
-				print_n(_("Book(s):"), books_per_drawer ?: desc->nbooks);
+				add_summary_n(tb, _("Book(s):"), books_per_drawer ?: desc->nbooks);
 			}
 		} else {
-			print_n(_("Socket(s):"), sockets_per_book ?: desc->nsockets);
+			add_summary_n(tb, _("Socket(s):"), sockets_per_book ?: desc->nsockets);
 		}
 	}
 	if (desc->nnodes)
-		print_n(_("NUMA node(s):"), desc->nnodes);
+		add_summary_n(tb, _("NUMA node(s):"), desc->nnodes);
 	if (desc->vendor)
-		print_s(_("Vendor ID:"), desc->vendor);
+		add_summary_s(tb, _("Vendor ID:"), desc->vendor);
 	if (desc->machinetype)
-		print_s(_("Machine type:"), desc->machinetype);
+		add_summary_s(tb, _("Machine type:"), desc->machinetype);
 	if (desc->family)
-		print_s(_("CPU family:"), desc->family);
+		add_summary_s(tb, _("CPU family:"), desc->family);
 	if (desc->model || desc->revision)
-		print_s(_("Model:"), desc->revision ? desc->revision : desc->model);
+		add_summary_s(tb, _("Model:"), desc->revision ? desc->revision : desc->model);
 	if (desc->modelname || desc->cpu)
-		print_s(_("Model name:"), desc->cpu ? desc->cpu : desc->modelname);
+		add_summary_s(tb, _("Model name:"), desc->cpu ? desc->cpu : desc->modelname);
 	if (desc->stepping)
-		print_s(_("Stepping:"), desc->stepping);
+		add_summary_s(tb, _("Stepping:"), desc->stepping);
 	if (desc->mhz)
-		print_s(_("CPU MHz:"), desc->mhz);
+		add_summary_s(tb, _("CPU MHz:"), desc->mhz);
 	if (desc->dynamic_mhz)
-		print_s(_("CPU dynamic MHz:"), desc->dynamic_mhz);
+		add_summary_s(tb, _("CPU dynamic MHz:"), desc->dynamic_mhz);
 	if (desc->static_mhz)
-		print_s(_("CPU static MHz:"), desc->static_mhz);
+		add_summary_s(tb, _("CPU static MHz:"), desc->static_mhz);
 	if (desc->maxmhz)
-		print_s(_("CPU max MHz:"), desc->maxmhz[0]);
+		add_summary_s(tb, _("CPU max MHz:"), desc->maxmhz[0]);
 	if (desc->minmhz)
-		print_s(_("CPU min MHz:"), desc->minmhz[0]);
+		add_summary_s(tb, _("CPU min MHz:"), desc->minmhz[0]);
 	if (desc->bogomips)
-		print_s(_("BogoMIPS:"), desc->bogomips);
+		add_summary_s(tb, _("BogoMIPS:"), desc->bogomips);
 	if (desc->virtflag) {
 		if (!strcmp(desc->virtflag, "svm"))
-			print_s(_("Virtualization:"), "AMD-V");
+			add_summary_s(tb, _("Virtualization:"), "AMD-V");
 		else if (!strcmp(desc->virtflag, "vmx"))
-			print_s(_("Virtualization:"), "VT-x");
+			add_summary_s(tb, _("Virtualization:"), "VT-x");
 	}
 	if (desc->hypervisor)
-		print_s(_("Hypervisor:"), desc->hypervisor);
+		add_summary_s(tb, _("Hypervisor:"), desc->hypervisor);
 	if (desc->hyper) {
-		print_s(_("Hypervisor vendor:"), hv_vendors[desc->hyper]);
-		print_s(_("Virtualization type:"), _(virt_types[desc->virtype]));
+		add_summary_s(tb, _("Hypervisor vendor:"), hv_vendors[desc->hyper]);
+		add_summary_s(tb, _("Virtualization type:"), _(virt_types[desc->virtype]));
 	}
 	if (desc->dispatching >= 0)
-		print_s(_("Dispatching mode:"), _(disp_modes[desc->dispatching]));
+		add_summary_s(tb, _("Dispatching mode:"), _(disp_modes[desc->dispatching]));
 	if (desc->ncaches) {
 		char cbuf[512];
 
 		for (i = desc->ncaches - 1; i >= 0; i--) {
 			snprintf(cbuf, sizeof(cbuf),
 					_("%s cache:"), desc->caches[i].name);
-			print_s(cbuf, desc->caches[i].size);
+			add_summary_s(tb, cbuf, desc->caches[i].size);
 		}
 	}
-
 	if (desc->necaches) {
 		char cbuf[512];
 
 		for (i = desc->necaches - 1; i >= 0; i--) {
 			snprintf(cbuf, sizeof(cbuf),
 					_("%s cache:"), desc->ecaches[i].name);
-			print_s(cbuf, desc->ecaches[i].size);
+			add_summary_s(tb, cbuf, desc->ecaches[i].size);
 		}
 	}
 
 	for (i = 0; i < desc->nnodes; i++) {
 		snprintf(buf, sizeof(buf), _("NUMA node%d CPU(s):"), desc->idx2nodenum[i]);
-		print_cpuset(buf, desc->nodemaps[i], mod->hex);
+		print_cpuset(tb, buf, desc->nodemaps[i], mod->hex);
+	}
+
+	if (desc->physsockets) {
+		add_summary_n(tb, _("Physical sockets:"), desc->physsockets);
+		add_summary_n(tb, _("Physical chips:"), desc->physchips);
+		add_summary_n(tb, _("Physical cores/chip:"), desc->physcoresperchip);
 	}
 
 	if (desc->flags)
-		print_s(_("Flags:"), desc->flags);
+		add_summary_s(tb, _("Flags:"), desc->flags);
 
-	if (desc->physsockets) {
-		print_n(_("Physical sockets:"), desc->physsockets);
-		print_n(_("Physical chips:"), desc->physchips);
-		print_n(_("Physical cores/chip:"), desc->physcoresperchip);
-	}
+	scols_print_table(tb);
+	scols_unref_table(tb);
 }
 
 static void __attribute__((__noreturn__)) usage(FILE *out)
@@ -1966,6 +2014,7 @@
 	fputs(_(" -a, --all               print both online and offline CPUs (default for -e)\n"), out);
 	fputs(_(" -b, --online            print online CPUs only (default for -p)\n"), out);
 	fputs(_(" -c, --offline           print offline CPUs only\n"), out);
+	fputs(_(" -J, --json              use JSON for default or extended format\n"), out);
 	fputs(_(" -e, --extended[=<list>] print out an extended readable format\n"), out);
 	fputs(_(" -p, --parse[=<list>]    print out a parsable format\n"), out);
 	fputs(_(" -s, --sysroot <dir>     use specified directory as system root\n"), out);
@@ -1999,6 +2048,7 @@
 		{ "offline",    no_argument,       NULL, 'c' },
 		{ "help",	no_argument,       NULL, 'h' },
 		{ "extended",	optional_argument, NULL, 'e' },
+		{ "json",       no_argument,       NULL, 'J' },
 		{ "parse",	optional_argument, NULL, 'p' },
 		{ "sysroot",	required_argument, NULL, 's' },
 		{ "physical",	no_argument,	   NULL, 'y' },
@@ -2019,7 +2069,7 @@
 	textdomain(PACKAGE);
 	atexit(close_stdout);
 
-	while ((c = getopt_long(argc, argv, "abce::hp::s:xyV", longopts, NULL)) != -1) {
+	while ((c = getopt_long(argc, argv, "abce::hJp::s:xyV", longopts, NULL)) != -1) {
 
 		err_exclusive_options(c, longopts, excl, excl_st);
 
@@ -2038,6 +2088,9 @@
 			break;
 		case 'h':
 			usage(stdout);
+		case 'J':
+			mod->json = 1;
+			break;
 		case 'p':
 		case 'e':
 			if (optarg) {
diff --git a/tests/expected/lscpu/lscpu-armv7 b/tests/expected/lscpu/lscpu-armv7
index 6f7db2b..e67af47 100644
--- a/tests/expected/lscpu/lscpu-armv7
+++ b/tests/expected/lscpu/lscpu-armv7
@@ -1,13 +1,13 @@
-CPU(s):                2
-On-line CPU(s) list:   0,1
-Thread(s) per core:    1
-Core(s) per socket:    2
-Socket(s):             1
-Model:                 4
-CPU max MHz:           1700.0000
-CPU min MHz:           200.0000
-BogoMIPS:              1694.10
-Flags:                 swp half thumb fastmult vfp edsp thumbee neon vfpv3 tls vfpv4 idiva idivt
+CPU(s):              2
+On-line CPU(s) list: 0,1
+Thread(s) per core:  1
+Core(s) per socket:  2
+Socket(s):           1
+Model:               4
+CPU max MHz:         1700.0000
+CPU min MHz:         200.0000
+BogoMIPS:            1694.10
+Flags:               swp half thumb fastmult vfp edsp thumbee neon vfpv3 tls vfpv4 idiva idivt
 
 # The following is the parsable format, which can be fed to other
 # programs. Each different item in every column has an unique ID
diff --git a/tests/expected/lscpu/lscpu-ppc-qemu b/tests/expected/lscpu/lscpu-ppc-qemu
index e6cc68b..bf8e49e 100644
--- a/tests/expected/lscpu/lscpu-ppc-qemu
+++ b/tests/expected/lscpu/lscpu-ppc-qemu
@@ -1,13 +1,13 @@
-CPU(s):                1
-On-line CPU(s) list:   0
-Thread(s) per core:    1
-Core(s) per socket:    1
-Socket(s):             1
-Model:                 3.1 (pvr 0008 0301)
-Model name:            740/750
-BogoMIPS:              33.25
-L1d cache:             unknown size
-L1i cache:             unknown size
+CPU(s):              1
+On-line CPU(s) list: 0
+Thread(s) per core:  1
+Core(s) per socket:  1
+Socket(s):           1
+Model:               3.1 (pvr 0008 0301)
+Model name:          740/750
+BogoMIPS:            33.25
+L1d cache:           unknown size
+L1i cache:           unknown size
 
 # The following is the parsable format, which can be fed to other
 # programs. Each different item in every column has an unique ID
diff --git a/tests/expected/lscpu/lscpu-ppc64-POWER7 b/tests/expected/lscpu/lscpu-ppc64-POWER7
index 7ae7ea1..8c4dca0 100644
--- a/tests/expected/lscpu/lscpu-ppc64-POWER7
+++ b/tests/expected/lscpu/lscpu-ppc64-POWER7
@@ -1,14 +1,14 @@
-CPU(s):                16
-On-line CPU(s) list:   0-15
-Thread(s) per core:    4
-Core(s) per socket:    1
-Socket(s):             4
-NUMA node(s):          1
-Model:                 2.1 (pvr 003f 0201)
-Model name:            POWER7 (architected), altivec supported
-L1d cache:             32K
-L1i cache:             32K
-NUMA node0 CPU(s):     0-15
+CPU(s):              16
+On-line CPU(s) list: 0-15
+Thread(s) per core:  4
+Core(s) per socket:  1
+Socket(s):           4
+NUMA node(s):        1
+Model:               2.1 (pvr 003f 0201)
+Model name:          POWER7 (architected), altivec supported
+L1d cache:           32K
+L1i cache:           32K
+NUMA node0 CPU(s):   0-15
 
 # The following is the parsable format, which can be fed to other
 # programs. Each different item in every column has an unique ID
diff --git a/tests/expected/lscpu/lscpu-ppc64-POWER7-64cpu b/tests/expected/lscpu/lscpu-ppc64-POWER7-64cpu
index 1a9b910..2157b17 100644
--- a/tests/expected/lscpu/lscpu-ppc64-POWER7-64cpu
+++ b/tests/expected/lscpu/lscpu-ppc64-POWER7-64cpu
@@ -1,17 +1,17 @@
-CPU(s):                64
-On-line CPU(s) list:   0-63
-Thread(s) per core:    4
-Core(s) per socket:    1
-Socket(s):             16
-NUMA node(s):          2
-Model:                 2.1 (pvr 003f 0201)
-Model name:            POWER7 (architected), altivec supported
-Hypervisor vendor:     pHyp
-Virtualization type:   para
-L1d cache:             32K
-L1i cache:             32K
-NUMA node0 CPU(s):     0-63
-NUMA node1 CPU(s):     
+CPU(s):              64
+On-line CPU(s) list: 0-63
+Thread(s) per core:  4
+Core(s) per socket:  1
+Socket(s):           16
+NUMA node(s):        2
+Model:               2.1 (pvr 003f 0201)
+Model name:          POWER7 (architected), altivec supported
+Hypervisor vendor:   pHyp
+Virtualization type: para
+L1d cache:           32K
+L1i cache:           32K
+NUMA node0 CPU(s):   0-63
+NUMA node1 CPU(s):   
 
 # The following is the parsable format, which can be fed to other
 # programs. Each different item in every column has an unique ID
diff --git a/tests/expected/lscpu/lscpu-s390-kvm b/tests/expected/lscpu/lscpu-s390-kvm
index 77c06f5..661d84d 100644
--- a/tests/expected/lscpu/lscpu-s390-kvm
+++ b/tests/expected/lscpu/lscpu-s390-kvm
@@ -1,18 +1,18 @@
-CPU op-mode(s):        32-bit, 64-bit
-CPU(s):                3
-On-line CPU(s) list:   0-2
-Thread(s) per core:    1
-Core(s) per socket:    1
-Socket(s) per book:    1
-Book(s):               3
-Vendor ID:             IBM/S390
-Machine type:          2817
-BogoMIPS:              14367.00
-Hypervisor:            KVM/Linux
-Hypervisor vendor:     KVM
-Virtualization type:   full
-Dispatching mode:      horizontal
-Flags:                 esan3 zarch stfle msa ldisp eimm dfp edat etf3eh highgprs
+CPU op-mode(s):      32-bit, 64-bit
+CPU(s):              3
+On-line CPU(s) list: 0-2
+Thread(s) per core:  1
+Core(s) per socket:  1
+Socket(s) per book:  1
+Book(s):             3
+Vendor ID:           IBM/S390
+Machine type:        2817
+BogoMIPS:            14367.00
+Hypervisor:          KVM/Linux
+Hypervisor vendor:   KVM
+Virtualization type: full
+Dispatching mode:    horizontal
+Flags:               esan3 zarch stfle msa ldisp eimm dfp edat etf3eh highgprs
 
 # The following is the parsable format, which can be fed to other
 # programs. Each different item in every column has an unique ID
diff --git a/tests/expected/lscpu/lscpu-s390-lpar b/tests/expected/lscpu/lscpu-s390-lpar
index b9daf07..af02cf5 100644
--- a/tests/expected/lscpu/lscpu-s390-lpar
+++ b/tests/expected/lscpu/lscpu-s390-lpar
@@ -1,19 +1,19 @@
-CPU op-mode(s):        32-bit, 64-bit
-CPU(s):                20
-On-line CPU(s) list:   1-5,8-19
-Off-line CPU(s) list:  0,6,7
-Thread(s) per core:    1
-Core(s) per socket:    4
-Socket(s) per book:    6
-Book(s):               4
-Vendor ID:             IBM/S390
-Machine type:          2817
-BogoMIPS:              14367.00
-Hypervisor:            PR/SM
-Hypervisor vendor:     IBM
-Virtualization type:   full
-Dispatching mode:      vertical
-Flags:                 esan3 zarch stfle msa ldisp eimm dfp etf3eh highgprs
+CPU op-mode(s):       32-bit, 64-bit
+CPU(s):               20
+On-line CPU(s) list:  1-5,8-19
+Off-line CPU(s) list: 0,6,7
+Thread(s) per core:   1
+Core(s) per socket:   4
+Socket(s) per book:   6
+Book(s):              4
+Vendor ID:            IBM/S390
+Machine type:         2817
+BogoMIPS:             14367.00
+Hypervisor:           PR/SM
+Hypervisor vendor:    IBM
+Virtualization type:  full
+Dispatching mode:     vertical
+Flags:                esan3 zarch stfle msa ldisp eimm dfp etf3eh highgprs
 
 # The following is the parsable format, which can be fed to other
 # programs. Each different item in every column has an unique ID
diff --git a/tests/expected/lscpu/lscpu-s390-lpar-drawer b/tests/expected/lscpu/lscpu-s390-lpar-drawer
index e5f3af9..d223009 100644
--- a/tests/expected/lscpu/lscpu-s390-lpar-drawer
+++ b/tests/expected/lscpu/lscpu-s390-lpar-drawer
@@ -1,29 +1,29 @@
-CPU op-mode(s):        32-bit, 64-bit
-CPU(s):                8
-On-line CPU(s) list:   0-7
-Thread(s) per core:    1
-Core(s) per socket:    8
-Socket(s) per book:    3
-Book(s) per drawer:    2
-Drawer(s):             4
-NUMA node(s):          1
-Vendor ID:             IBM/S390
-Machine type:          2964
-CPU dynamic MHz:       5000
-CPU static MHz:        5000
-BogoMIPS:              20325.00
-Hypervisor:            PR/SM
-Hypervisor vendor:     IBM
-Virtualization type:   full
-Dispatching mode:      horizontal
-L1d cache:             128K
-L1i cache:             96K
-L2d cache:             2048K
-L2i cache:             2048K
-L3 cache:              65536K
-L4 cache:              491520K
-NUMA node0 CPU(s):     0-140
-Flags:                 esan3 zarch stfle msa ldisp eimm dfp edat etf3eh highgprs te vx sie
+CPU op-mode(s):      32-bit, 64-bit
+CPU(s):              8
+On-line CPU(s) list: 0-7
+Thread(s) per core:  1
+Core(s) per socket:  8
+Socket(s) per book:  3
+Book(s) per drawer:  2
+Drawer(s):           4
+NUMA node(s):        1
+Vendor ID:           IBM/S390
+Machine type:        2964
+CPU dynamic MHz:     5000
+CPU static MHz:      5000
+BogoMIPS:            20325.00
+Hypervisor:          PR/SM
+Hypervisor vendor:   IBM
+Virtualization type: full
+Dispatching mode:    horizontal
+L1d cache:           128K
+L1i cache:           96K
+L2d cache:           2048K
+L2i cache:           2048K
+L3 cache:            65536K
+L4 cache:            491520K
+NUMA node0 CPU(s):   0-140
+Flags:               esan3 zarch stfle msa ldisp eimm dfp edat etf3eh highgprs te vx sie
 
 # The following is the parsable format, which can be fed to other
 # programs. Each different item in every column has an unique ID
diff --git a/tests/expected/lscpu/lscpu-s390-zvm b/tests/expected/lscpu/lscpu-s390-zvm
index 4c02b03..5242b30 100644
--- a/tests/expected/lscpu/lscpu-s390-zvm
+++ b/tests/expected/lscpu/lscpu-s390-zvm
@@ -1,18 +1,18 @@
-CPU op-mode(s):        32-bit, 64-bit
-CPU(s):                4
-On-line CPU(s) list:   0-3
-Thread(s) per core:    1
-Core(s) per socket:    1
-Socket(s) per book:    1
-Book(s):               4
-Vendor ID:             IBM/S390
-Machine type:          2817
-BogoMIPS:              14367.00
-Hypervisor:            z/VM 6.1.0
-Hypervisor vendor:     IBM
-Virtualization type:   full
-Dispatching mode:      horizontal
-Flags:                 esan3 zarch stfle msa ldisp eimm dfp etf3eh highgprs
+CPU op-mode(s):      32-bit, 64-bit
+CPU(s):              4
+On-line CPU(s) list: 0-3
+Thread(s) per core:  1
+Core(s) per socket:  1
+Socket(s) per book:  1
+Book(s):             4
+Vendor ID:           IBM/S390
+Machine type:        2817
+BogoMIPS:            14367.00
+Hypervisor:          z/VM 6.1.0
+Hypervisor vendor:   IBM
+Virtualization type: full
+Dispatching mode:    horizontal
+Flags:               esan3 zarch stfle msa ldisp eimm dfp etf3eh highgprs
 
 # The following is the parsable format, which can be fed to other
 # programs. Each different item in every column has an unique ID
diff --git a/tests/expected/lscpu/lscpu-sparc64 b/tests/expected/lscpu/lscpu-sparc64
index fdc5e8b..a12c136 100644
--- a/tests/expected/lscpu/lscpu-sparc64
+++ b/tests/expected/lscpu/lscpu-sparc64
@@ -1,11 +1,11 @@
-CPU op-mode(s):        32-bit, 64-bit
-CPU(s):                6
-On-line CPU(s) list:   6,7,10,11,14,15
-Thread(s) per core:    1
-Core(s) per socket:    1
-Socket(s):             6
-Model name:            TI UltraSparc II  (BlackBird)
-Flags:                 sun4u
+CPU op-mode(s):      32-bit, 64-bit
+CPU(s):              6
+On-line CPU(s) list: 6,7,10,11,14,15
+Thread(s) per core:  1
+Core(s) per socket:  1
+Socket(s):           6
+Model name:          TI UltraSparc II  (BlackBird)
+Flags:               sun4u
 
 # The following is the parsable format, which can be fed to other
 # programs. Each different item in every column has an unique ID
diff --git a/tests/expected/lscpu/lscpu-vbox-win b/tests/expected/lscpu/lscpu-vbox-win
index 595824b..34f6130 100644
--- a/tests/expected/lscpu/lscpu-vbox-win
+++ b/tests/expected/lscpu/lscpu-vbox-win
@@ -1,26 +1,26 @@
-CPU op-mode(s):        32-bit, 64-bit
-CPU(s):                2
-On-line CPU(s) list:   0,1
-Thread(s) per core:    1
-Core(s) per socket:    2
-Socket(s):             1
-NUMA node(s):          1
-Vendor ID:             GenuineIntel
-CPU family:            6
-Model:                 58
-Model name:            Intel(R) Core(TM) i5-3317U CPU @ 1.70GHz
-Stepping:              9
-CPU MHz:               1600.000
-CPU max MHz:           3800.0000
-CPU min MHz:           1600.0000
-BogoMIPS:              3355.62
-Hypervisor vendor:     Oracle
-Virtualization type:   full
-L1d cache:             32K
-L1d cache:             32K
-L2d cache:             6144K
-NUMA node0 CPU(s):     0,1
-Flags:                 fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx rdtscp lm constant_tsc rep_good nopl pni ssse3 lahf_lm
+CPU op-mode(s):      32-bit, 64-bit
+CPU(s):              2
+On-line CPU(s) list: 0,1
+Thread(s) per core:  1
+Core(s) per socket:  2
+Socket(s):           1
+NUMA node(s):        1
+Vendor ID:           GenuineIntel
+CPU family:          6
+Model:               58
+Model name:          Intel(R) Core(TM) i5-3317U CPU @ 1.70GHz
+Stepping:            9
+CPU MHz:             1600.000
+CPU max MHz:         3800.0000
+CPU min MHz:         1600.0000
+BogoMIPS:            3355.62
+Hypervisor vendor:   Oracle
+Virtualization type: full
+L1d cache:           32K
+L1d cache:           32K
+L2d cache:           6144K
+NUMA node0 CPU(s):   0,1
+Flags:               fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx rdtscp lm constant_tsc rep_good nopl pni ssse3 lahf_lm
 
 # The following is the parsable format, which can be fed to other
 # programs. Each different item in every column has an unique ID
diff --git a/tests/expected/lscpu/lscpu-x86_64-64cpu b/tests/expected/lscpu/lscpu-x86_64-64cpu
index cf5c57a..432ecaf 100644
--- a/tests/expected/lscpu/lscpu-x86_64-64cpu
+++ b/tests/expected/lscpu/lscpu-x86_64-64cpu
@@ -1,28 +1,28 @@
-CPU op-mode(s):        32-bit, 64-bit
-CPU(s):                64
-On-line CPU(s) list:   0-63
-Thread(s) per core:    2
-Core(s) per socket:    8
-Socket(s):             4
-NUMA node(s):          3
-Vendor ID:             GenuineIntel
-CPU family:            6
-Model:                 46
-Model name:            Intel(R) Xeon(R) CPU           X7550  @ 2.00GHz
-Stepping:              6
-CPU MHz:               1064.000
-CPU max MHz:           1996.0000
-CPU min MHz:           1064.0000
-BogoMIPS:              3990.31
-Virtualization:        VT-x
-L1d cache:             32K
-L1i cache:             32K
-L2 cache:              256K
-L3 cache:              18432K
-NUMA node0 CPU(s):     0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62
-NUMA node2 CPU(s):     1,5,9,13,17,21,25,29,33,37,41,45,49,53,57,61
-NUMA node3 CPU(s):     3,7,11,15,19,23,27,31,35,39,43,47,51,55,59,63
-Flags:                 fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good xtopology nonstop_tsc aperfmperf pni dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm dca sse4_1 sse4_2 x2apic popcnt lahf_lm ida epb dts tpr_shadow vnmi flexpriority ept vpid
+CPU op-mode(s):      32-bit, 64-bit
+CPU(s):              64
+On-line CPU(s) list: 0-63
+Thread(s) per core:  2
+Core(s) per socket:  8
+Socket(s):           4
+NUMA node(s):        3
+Vendor ID:           GenuineIntel
+CPU family:          6
+Model:               46
+Model name:          Intel(R) Xeon(R) CPU           X7550  @ 2.00GHz
+Stepping:            6
+CPU MHz:             1064.000
+CPU max MHz:         1996.0000
+CPU min MHz:         1064.0000
+BogoMIPS:            3990.31
+Virtualization:      VT-x
+L1d cache:           32K
+L1i cache:           32K
+L2 cache:            256K
+L3 cache:            18432K
+NUMA node0 CPU(s):   0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62
+NUMA node2 CPU(s):   1,5,9,13,17,21,25,29,33,37,41,45,49,53,57,61
+NUMA node3 CPU(s):   3,7,11,15,19,23,27,31,35,39,43,47,51,55,59,63
+Flags:               fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good xtopology nonstop_tsc aperfmperf pni dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm dca sse4_1 sse4_2 x2apic popcnt lahf_lm ida epb dts tpr_shadow vnmi flexpriority ept vpid
 
 # The following is the parsable format, which can be fed to other
 # programs. Each different item in every column has an unique ID
diff --git a/tests/expected/lscpu/lscpu-x86_64-dell_e4310 b/tests/expected/lscpu/lscpu-x86_64-dell_e4310
index 7e3ea6e..631887e 100644
--- a/tests/expected/lscpu/lscpu-x86_64-dell_e4310
+++ b/tests/expected/lscpu/lscpu-x86_64-dell_e4310
@@ -1,26 +1,26 @@
-CPU op-mode(s):        32-bit, 64-bit
-CPU(s):                4
-On-line CPU(s) list:   0-3
-Thread(s) per core:    2
-Core(s) per socket:    2
-Socket(s):             1
-NUMA node(s):          1
-Vendor ID:             GenuineIntel
-CPU family:            6
-Model:                 37
-Model name:            Intel(R) Core(TM) i5 CPU       M 560  @ 2.67GHz
-Stepping:              5
-CPU MHz:               1199.000
-CPU max MHz:           2667.0000
-CPU min MHz:           1199.0000
-BogoMIPS:              5319.92
-Virtualization:        VT-x
-L1d cache:             32K
-L1i cache:             32K
-L2 cache:              256K
-L3 cache:              3072K
-NUMA node0 CPU(s):     0-3
-Flags:                 fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm sse4_1 sse4_2 popcnt aes lahf_lm ida arat dts tpr_shadow vnmi flexpriority ept vpid
+CPU op-mode(s):      32-bit, 64-bit
+CPU(s):              4
+On-line CPU(s) list: 0-3
+Thread(s) per core:  2
+Core(s) per socket:  2
+Socket(s):           1
+NUMA node(s):        1
+Vendor ID:           GenuineIntel
+CPU family:          6
+Model:               37
+Model name:          Intel(R) Core(TM) i5 CPU       M 560  @ 2.67GHz
+Stepping:            5
+CPU MHz:             1199.000
+CPU max MHz:         2667.0000
+CPU min MHz:         1199.0000
+BogoMIPS:            5319.92
+Virtualization:      VT-x
+L1d cache:           32K
+L1i cache:           32K
+L2 cache:            256K
+L3 cache:            3072K
+NUMA node0 CPU(s):   0-3
+Flags:               fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm sse4_1 sse4_2 popcnt aes lahf_lm ida arat dts tpr_shadow vnmi flexpriority ept vpid
 
 # The following is the parsable format, which can be fed to other
 # programs. Each different item in every column has an unique ID
diff --git a/text-utils/hexdump-display.c b/text-utils/hexdump-display.c
index ce714f6..3e01763 100644
--- a/text-utils/hexdump-display.c
+++ b/text-utils/hexdump-display.c
@@ -299,9 +299,9 @@
 			eaddress = address;
 		}
 		list_for_each (p, &endfu->prlist) {
-			pr = list_entry(p, struct hexdump_pr, prlist);
-
 			const char *color = NULL;
+
+			pr = list_entry(p, struct hexdump_pr, prlist);
 			if (colors_wanted() && pr->colorlist
 			    && (color = color_cond(pr, bp, pr->bcnt))) {
 				color_enable(color);