Index: head/usr.bin/procstat/Makefile
===================================================================
--- head/usr.bin/procstat/Makefile
+++ head/usr.bin/procstat/Makefile
@@ -17,6 +17,6 @@
 	procstat_threads.c	\
 	procstat_vm.c
 
-LIBADD+=	util procstat
+LIBADD+=	procstat xo util sbuf
 
 .include <bsd.prog.mk>
Index: head/usr.bin/procstat/procstat.h
===================================================================
--- head/usr.bin/procstat/procstat.h
+++ head/usr.bin/procstat/procstat.h
@@ -1,5 +1,6 @@
 /*-
  * Copyright (c) 2007 Robert N. M. Watson
+ * Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,9 +27,13 @@
  * $FreeBSD$
  */
 
+#include <libxo/xo.h>
+
 #ifndef PROCSTAT_H
 #define	PROCSTAT_H
 
+#define PROCSTAT_XO_VERSION "1"
+
 extern int	hflag, nflag, Cflag, Hflag;
 
 struct kinfo_proc;
Index: head/usr.bin/procstat/procstat.1
===================================================================
--- head/usr.bin/procstat/procstat.1
+++ head/usr.bin/procstat/procstat.1
@@ -25,7 +25,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd May 18, 2015
+.Dd September 5, 2015
 .Dt PROCSTAT 1
 .Os
 .Sh NAME
@@ -33,6 +33,7 @@
 .Nd get detailed process information
 .Sh SYNOPSIS
 .Nm
+.Op Fl -libxo
 .Op Fl CHhn
 .Op Fl w Ar interval
 .Op Fl b | c | e | f | i | j | k | l | r | s | S | t | v | x
@@ -52,6 +53,13 @@
 options may be specified in order to select more detailed process information
 for printing:
 .Bl -tag -width indent
+.It Fl -libxo
+Generate output via
+.Xr libxo 3
+in a selection of different human and machine readable formats.
+See
+.Xr xo_parse_args 3
+for details on command line arguments.
 .It Fl b
 Display binary information for the process.
 .It Fl c
@@ -531,16 +539,19 @@
 .Xr cap_enter 2 ,
 .Xr cap_rights_limit 2 ,
 .Xr libprocstat 3 ,
+.Xr libxo 3 ,
+.Xr xo_parse_args 3 ,
 .Xr ddb 4 ,
 .Xr stack 9
 .Sh AUTHORS
-.An Robert N M Watson
+.An Robert N M Watson Aq Mt rwatson@FreeBSD.org .
+.br
+.Xr libxo 3
+support was added by
+.An -nosplit
+Allan Jude
+.Aq Mt allanjude@FreeBSD.org .
 .Sh BUGS
-Some field values may include spaces, which limits the extent to which the
-output of
-.Nm
-may be mechanically parsed.
-.Pp
 The display of open file or memory mapping pathnames is implemented using the
 kernel's name cache.
 If a file system does not use the name cache, or the path to a file is not in
Index: head/usr.bin/procstat/procstat.c
===================================================================
--- head/usr.bin/procstat/procstat.c
+++ head/usr.bin/procstat/procstat.c
@@ -1,5 +1,6 @@
 /*-
  * Copyright (c) 2007, 2011 Robert N. M. Watson
+ * Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -47,17 +48,24 @@
 usage(void)
 {
 
-	fprintf(stderr, "usage: procstat [-CHhn] [-M core] [-N system] "
-	    "[-w interval] \n");
-	fprintf(stderr, "                [-b | -c | -e | -f | -i | -j | -k | "
-	    "-l | -r | -s | -S | -t | -v | -x]\n");
-	fprintf(stderr, "                [-a | pid | core ...]\n");
+	xo_error("usage: procstat [-CHhn] [-M core] [-N system] "
+	    "[-w interval]\n"
+	    "                [-b | -c | -e | -f | -i | -j | -k | "
+	    "-l | -r | -s | -S | -t | -v | -x]\n"
+	    "                [-a | pid | core ...]\n");
+	xo_finish();
 	exit(EX_USAGE);
 }
 
 static void
 procstat(struct procstat *prstat, struct kinfo_proc *kipp)
 {
+	char *pidstr = NULL;
+
+	asprintf(&pidstr, "%d", kipp->ki_pid);
+	if (pidstr == NULL)
+		xo_errc(1, ENOMEM, "Failed to allocate memory in procstat()");
+	xo_open_container(pidstr);
 
 	if (bflag)
 		procstat_bin(prstat, kipp);
@@ -89,6 +97,9 @@
 		procstat_cs(prstat, kipp);
 	else
 		procstat_basic(kipp);
+
+	xo_close_container(pidstr);
+	free(pidstr);
 }
 
 /*
@@ -126,10 +137,14 @@
 	pid_t pid;
 	char *dummy;
 	char *nlistf, *memf;
+	const char *xocontainer;
 	int cnt;
 
 	interval = 0;
 	memf = nlistf = NULL;
+	argc = xo_parse_args(argc, argv);
+	xocontainer = "basic";
+
 	while ((ch = getopt(argc, argv, "CHN:M:abcefijklhrsStvw:x")) != -1) {
 		switch (ch) {
 		case 'C':
@@ -148,6 +163,7 @@
 			break;
 		case 'S':
 			Sflag++;
+			xocontainer = "cs";
 			break;
 		case 'a':
 			aflag++;
@@ -155,34 +171,42 @@
 
 		case 'b':
 			bflag++;
+			xocontainer = "binary";
 			break;
 
 		case 'c':
 			cflag++;
+			xocontainer = "arguments";
 			break;
 
 		case 'e':
 			eflag++;
+			xocontainer = "environment";
 			break;
 
 		case 'f':
 			fflag++;
+			xocontainer = "files";
 			break;
 
 		case 'i':
 			iflag++;
+			xocontainer = "signals";
 			break;
 
 		case 'j':
 			jflag++;
+			xocontainer = "thread_signals";
 			break;
 
 		case 'k':
 			kflag++;
+			xocontainer = "kstack";
 			break;
 
 		case 'l':
 			lflag++;
+			xocontainer = "rlimit";
 			break;
 
 		case 'n':
@@ -195,18 +219,22 @@
 
 		case 'r':
 			rflag++;
+			xocontainer = "rusage";
 			break;
 
 		case 's':
 			sflag++;
+			xocontainer = "credentials";
 			break;
 
 		case 't':
 			tflag++;
+			xocontainer = "threads";
 			break;
 
 		case 'v':
 			vflag++;
+			xocontainer = "vm";
 			break;
 
 		case 'w':
@@ -220,6 +248,7 @@
 
 		case 'x':
 			xflag++;
+			xocontainer = "auxv";
 			break;
 
 		case '?':
@@ -254,18 +283,23 @@
 	else
 		prstat = procstat_open_sysctl();
 	if (prstat == NULL)
-		errx(1, "procstat_open()");
+		xo_errx(1, "procstat_open()");
 	do {
+		xo_set_version(PROCSTAT_XO_VERSION);
+		xo_open_container("procstat");
+		xo_open_container(xocontainer);
+
 		if (aflag) {
 			p = procstat_getprocs(prstat, KERN_PROC_PROC, 0, &cnt);
 			if (p == NULL)
-				errx(1, "procstat_getprocs()");
+				xo_errx(1, "procstat_getprocs()");
 			kinfo_proc_sort(p, cnt);
 			for (i = 0; i < cnt; i++) {
 				procstat(prstat, &p[i]);
 
 				/* Suppress header after first process. */
 				hflag = 1;
+				xo_flush();
 			}
 			procstat_freeprocs(prstat, p);
 		}
@@ -276,9 +310,10 @@
 					usage();
 				pid = l;
 
-				p = procstat_getprocs(prstat, KERN_PROC_PID, pid, &cnt);
+				p = procstat_getprocs(prstat, KERN_PROC_PID,
+				    pid, &cnt);
 				if (p == NULL)
-					errx(1, "procstat_getprocs()");
+					xo_errx(1, "procstat_getprocs()");
 				if (cnt != 0)
 					procstat(prstat, p);
 				procstat_freeprocs(prstat, p);
@@ -291,7 +326,7 @@
 				p = procstat_getprocs(cprstat, KERN_PROC_PID,
 				    -1, &cnt);
 				if (p == NULL)
-					errx(1, "procstat_getprocs()");
+					xo_errx(1, "procstat_getprocs()");
 				if (cnt != 0)
 					procstat(cprstat, p);
 				procstat_freeprocs(cprstat, p);
@@ -300,9 +335,15 @@
 			/* Suppress header after first process. */
 			hflag = 1;
 		}
+
+		xo_close_container(xocontainer);
+		xo_close_container("procstat");
+		xo_finish();
 		if (interval)
 			sleep(interval);
 	} while (interval);
+
 	procstat_close(prstat);
+
 	exit(0);
 }
Index: head/usr.bin/procstat/procstat_args.c
===================================================================
--- head/usr.bin/procstat/procstat_args.c
+++ head/usr.bin/procstat/procstat_args.c
@@ -1,5 +1,6 @@
 /*-
  * Copyright (c) 2007 Robert N. M. Watson
+ * Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -40,40 +41,56 @@
 
 #include "procstat.h"
 
-static void
-do_args(struct procstat *procstat, struct kinfo_proc *kipp, int env)
+void
+procstat_args(struct procstat *procstat, struct kinfo_proc *kipp)
 {
 	int i;
 	char **args;
 
 	if (!hflag) {
-		printf("%5s %-16s %-53s\n", "PID", "COMM",
-		    env ? "ENVIRONMENT" : "ARGS");
+		xo_emit("{T:/%5s %-16s %-53s}\n", "PID", "COMM", "ARGS");
 	}
 
-	args = env ? procstat_getenvv(procstat, kipp, 0) :
-	    procstat_getargv(procstat, kipp, 0);
+	args = procstat_getargv(procstat, kipp, 0);
 
-	printf("%5d %-16s", kipp->ki_pid, kipp->ki_comm);
+	xo_emit("{k:process_id/%5d/%d} {:command/%-16s/%s}", kipp->ki_pid,
+	    kipp->ki_comm);
 
 	if (args == NULL) {
-		printf(" -\n");
+		xo_emit(" {d:args/-}\n");
 		return;
 	}
 
+	xo_open_list("arguments");
 	for (i = 0; args[i] != NULL; i++)
-		printf(" %s", args[i]);
-	printf("\n");
-}
-
-void
-procstat_args(struct procstat *procstat, struct kinfo_proc *kipp)
-{
-	do_args(procstat, kipp, 0);
+		xo_emit(" {l:args/%s}", args[i]);
+	xo_close_list("arguments");
+	xo_emit("\n");
 }
 
 void
 procstat_env(struct procstat *procstat, struct kinfo_proc *kipp)
 {
-	do_args(procstat, kipp, 1);
+	int i;
+	char **envs;
+
+	if (!hflag) {
+		xo_emit("{T:/%5s %-16s %-53s}\n", "PID", "COMM", "ENVIRONMENT");
+	}
+
+	envs = procstat_getenvv(procstat, kipp, 0);
+
+	xo_emit("{k:process_id/%5d/%d} {:command/%-16s/%s}", kipp->ki_pid,
+	    kipp->ki_comm);
+
+	if (envs == NULL) {
+		xo_emit(" {d:env/-}\n");
+		return;
+	}
+
+	xo_open_list("environment");
+	for (i = 0; envs[i] != NULL; i++)
+		xo_emit(" {l:env/%s}", envs[i]);
+	xo_close_list("environment");
+	xo_emit("\n");
 }
Index: head/usr.bin/procstat/procstat_auxv.c
===================================================================
--- head/usr.bin/procstat/procstat_auxv.c
+++ head/usr.bin/procstat/procstat_auxv.c
@@ -1,5 +1,6 @@
 /*-
  * Copyright (c) 2011 Mikolaj Golub
+ * Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -43,11 +44,6 @@
 
 #include "procstat.h"
 
-#define	PRINT(name, spec, val)		\
-	printf("%s %-16s " #spec "\n", prefix, #name, (val))
-#define	PRINT_UNKNOWN(type, val)	\
-	printf("%s %16ld %#lx\n", prefix, (long)type, (u_long)(val))
-
 void
 procstat_auxv(struct procstat *procstat, struct kinfo_proc *kipp)
 {
@@ -56,12 +52,18 @@
 	static char prefix[256];
 
 	if (!hflag)
-		printf("%5s %-16s %-16s %-16s\n", "PID", "COMM", "AUXV", "VALUE");
+		xo_emit("{T:/%5s %-16s %-16s %-16s}\n", "PID", "COMM", "AUXV",
+		    "VALUE");
+
 	auxv = procstat_getauxv(procstat, kipp, &count);
 	if (auxv == NULL)
 		return;
-	snprintf(prefix, sizeof(prefix), "%5d %-16s", kipp->ki_pid,
+        snprintf(prefix, sizeof(prefix), "%5d %-16s", kipp->ki_pid,
+            kipp->ki_comm);
+
+	xo_emit("{e:process_id/%5d/%d}{e:command/%-16s/%s}", kipp->ki_pid,
 	    kipp->ki_comm);
+
 	for (i = 0; i < count; i++) {
 		switch(auxv[i].a_type) {
 		case AT_NULL:
@@ -69,92 +71,119 @@
 		case AT_IGNORE:
 			break;
 		case AT_EXECFD:
-			PRINT(AT_EXECFD, %ld, (long)auxv[i].a_un.a_val);
+			xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_EXECFD/%ld}\n",
+			    prefix, "AT_EXECFD", (long)auxv[i].a_un.a_val);
 			break;
 		case AT_PHDR:
-			PRINT(AT_PHDR, %p, auxv[i].a_un.a_ptr);
+			xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_PHDR/%p}\n",
+			    prefix, "AT_PHDR", auxv[i].a_un.a_ptr);
 			break;
 		case AT_PHENT:
-			PRINT(AT_PHENT, %ld, (long)auxv[i].a_un.a_val);
+			xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_PHENT/%ld}\n",
+			    prefix, "AT_PHENT", (long)auxv[i].a_un.a_val);
 			break;
 		case AT_PHNUM:
-			PRINT(AT_PHNUM, %ld, (long)auxv[i].a_un.a_val);
+			xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_PHNUM/%ld}\n",
+			    prefix, "AT_PHNUM", (long)auxv[i].a_un.a_val);
 			break;
 		case AT_PAGESZ:
-			PRINT(AT_PAGESZ, %ld, (long)auxv[i].a_un.a_val);
+			xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_PAGESZ/%ld}\n",
+			    prefix, "AT_PAGESZ", (long)auxv[i].a_un.a_val);
 			break;
 		case AT_BASE:
-			PRINT(AT_BASE, %p, auxv[i].a_un.a_ptr);
+			xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_BASE/%p}\n",
+			    prefix, "AT_BASE", auxv[i].a_un.a_ptr);
 			break;
 		case AT_FLAGS:
-			PRINT(AT_FLAGS, %#lx, (u_long)auxv[i].a_un.a_val);
+			xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_FLAGS/%#lx}\n",
+			    prefix, "AT_FLAGS", (u_long)auxv[i].a_un.a_val);
 			break;
 		case AT_ENTRY:
-			PRINT(AT_ENTRY, %p, auxv[i].a_un.a_ptr);
+			xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_ENTRY/%p}\n",
+			    prefix, "AT_ENTRY", auxv[i].a_un.a_ptr);
 			break;
 #ifdef AT_NOTELF
 		case AT_NOTELF:
-			PRINT(AT_NOTELF, %ld, (long)auxv[i].a_un.a_val);
+			xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_NOTELF/%ld}\n",
+			    prefix, "AT_NOTELF", (long)auxv[i].a_un.a_val);
 			break;
 #endif
 #ifdef AT_UID
 		case AT_UID:
-			PRINT(AT_UID, %ld, (long)auxv[i].a_un.a_val);
+			xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_UID/%ld}\n",
+			    prefix, "AT_UID", (long)auxv[i].a_un.a_val);
 			break;
 #endif
 #ifdef AT_EUID
 		case AT_EUID:
-			PRINT(AT_EUID, %ld, (long)auxv[i].a_un.a_val);
+			xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_EUID/%ld}\n",
+			    prefix, "AT_EUID", (long)auxv[i].a_un.a_val);
 			break;
 #endif
 #ifdef AT_GID
 		case AT_GID:
-			PRINT(AT_GID, %ld, (long)auxv[i].a_un.a_val);
+			xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_GID/%ld}\n",
+			    prefix, "AT_GID", (long)auxv[i].a_un.a_val);
 			break;
 #endif
 #ifdef AT_EGID
 		case AT_EGID:
-			PRINT(AT_EGID, %ld, (long)auxv[i].a_un.a_val);
+			xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_EGID/%ld}\n",
+			    prefix, "AT_EGID", (long)auxv[i].a_un.a_val);
 			break;
 #endif
 		case AT_EXECPATH:
-			PRINT(AT_EXECPATH, %p, auxv[i].a_un.a_ptr);
+			xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_EXECPATH/%p}\n",
+			    prefix, "AT_EXECPATH", auxv[i].a_un.a_ptr);
 			break;
 		case AT_CANARY:
-			PRINT(AT_CANARY, %p, auxv[i].a_un.a_ptr);
+			xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_CANARY/%p}\n",
+			    prefix, "AT_CANARY", auxv[i].a_un.a_ptr);
 			break;
 		case AT_CANARYLEN:
-			PRINT(AT_CANARYLEN, %ld, (long)auxv[i].a_un.a_val);
+			xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_CANARYLEN/%ld}\n",
+			    prefix, "AT_CANARYLEN", (long)auxv[i].a_un.a_val);
 			break;
 		case AT_OSRELDATE:
-			PRINT(AT_OSRELDATE, %ld, (long)auxv[i].a_un.a_val);
+			xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_OSRELDATE/%ld}\n",
+			    prefix, "AT_OSRELDATE", (long)auxv[i].a_un.a_val);
 			break;
 		case AT_NCPUS:
-			PRINT(AT_NCPUS, %ld, (long)auxv[i].a_un.a_val);
+			xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_NCPUS/%ld}\n",
+			    prefix, "AT_NCPUS", (long)auxv[i].a_un.a_val);
 			break;
 		case AT_PAGESIZES:
-			PRINT(AT_PAGESIZES, %p, auxv[i].a_un.a_ptr);
+			xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_PAGESIZES/%p}\n",
+			    prefix, "AT_PAGESIZES", auxv[i].a_un.a_ptr);
 			break;
 		case AT_PAGESIZESLEN:
-			PRINT(AT_PAGESIZESLEN, %ld, (long)auxv[i].a_un.a_val);
+			xo_emit("{dw:/%s}{Lw:/%-16s/%s}"
+			    "{:AT_PAGESIZESLEN/%ld}\n", prefix,
+			    "AT_PAGESIZESLEN", (long)auxv[i].a_un.a_val);
 			break;
 		case AT_STACKPROT:
 			if ((auxv[i].a_un.a_val & VM_PROT_EXECUTE) != 0)
-				PRINT(AT_STACKPROT, %s, "NONEXECUTABLE");
+				xo_emit("{dw:/%s}{Lw:/%-16s/%s}"
+				    "{:AT_STACKPROT/%s}\n", prefix,
+				    "AT_STACKPROT", "NONEXECUTABLE");
 			else
-				PRINT(AT_STACKPROT, %s, "EXECUTABLE");
+				xo_emit("{dw:/%s}{Lw:/%-16s/%s}"
+				    "{:AT_STACKPROT/%s}\n", prefix,
+				    "AT_STACKPROT", "EXECUTABLE");
 			break;
 #ifdef AT_TIMEKEEP
 		case AT_TIMEKEEP:
-			PRINT(AT_TIMEKEEP, %p, auxv[i].a_un.a_ptr);
+			xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_TIMEKEEP/%p}\n",
+			    prefix, "AT_TIMEKEEP", auxv[i].a_un.a_ptr);
 			break;
 #endif
 		default:
-			PRINT_UNKNOWN(auxv[i].a_type, auxv[i].a_un.a_val);
+			xo_emit("{dw:/%s}{Lw:/%16ld/%ld}{:UNKNOWN/%#lx}\n",
+			    prefix, auxv[i].a_type, auxv[i].a_un.a_val);
 			break;
 		}
 	}
-	printf("\n");
+	xo_emit("\n");
 	procstat_freeauxv(procstat, auxv);
 }
 
Index: head/usr.bin/procstat/procstat_basic.c
===================================================================
--- head/usr.bin/procstat/procstat_basic.c
+++ head/usr.bin/procstat/procstat_basic.c
@@ -1,5 +1,6 @@
 /*-
  * Copyright (c) 2007 Robert N. M. Watson
+ * Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -42,24 +43,26 @@
 {
 
 	if (!hflag)
-		printf("%5s %5s %5s %5s %5s %3s %-8s %-9s %-13s %-12s\n",
+		xo_emit("{T:/%5s %5s %5s %5s %5s %3s %-8s %-9s %-13s %-12s}\n",
 		    "PID", "PPID", "PGID", "SID", "TSID", "THR", "LOGIN",
 		    "WCHAN", "EMUL", "COMM");
 
-	printf("%5d ", kipp->ki_pid);
-	printf("%5d ", kipp->ki_ppid);
-	printf("%5d ", kipp->ki_pgid);
-	printf("%5d ", kipp->ki_sid);
-	printf("%5d ", kipp->ki_tsid);
-	printf("%3d ", kipp->ki_numthreads);
-	printf("%-8s ", strlen(kipp->ki_login) ? kipp->ki_login : "-");
+	xo_emit("{k:process_id/%5d/%d} ", kipp->ki_pid);
+	xo_emit("{:parent_process_id/%5d/%d} ", kipp->ki_ppid);
+	xo_emit("{:process_group_id/%5d/%d} ", kipp->ki_pgid);
+	xo_emit("{:session_id/%5d/%d} ", kipp->ki_sid);
+	xo_emit("{:terminal_session_id/%5d/%d} ", kipp->ki_tsid);
+	xo_emit("{:threads/%3d/%d} ", kipp->ki_numthreads);
+	xo_emit("{:login/%-8s/%s} ", strlen(kipp->ki_login) ?
+	    kipp->ki_login : "-");
 	if (kipp->ki_kiflag & KI_LOCKBLOCK) {
-		printf("*%-8s ", strlen(kipp->ki_lockname) ?
+		xo_emit("{:lockname/*%-8s/%s} ", strlen(kipp->ki_lockname) ?
 		    kipp->ki_lockname : "-");
 	} else {
-		printf("%-9s ", strlen(kipp->ki_wmesg) ?
+		xo_emit("{:wait_channel/%-9s/%s} ", strlen(kipp->ki_wmesg) ?
 		    kipp->ki_wmesg : "-");
 	}
-	printf("%-13s ", strcmp(kipp->ki_emul, "null") ? kipp->ki_emul : "-");
-	printf("%-12s\n", kipp->ki_comm);
+	xo_emit("{:emulation/%-13s/%s} ", strcmp(kipp->ki_emul, "null") ?
+	    kipp->ki_emul : "-");
+	xo_emit("{:command/%-12s/%s}\n", kipp->ki_comm);
 }
Index: head/usr.bin/procstat/procstat_bin.c
===================================================================
--- head/usr.bin/procstat/procstat_bin.c
+++ head/usr.bin/procstat/procstat_bin.c
@@ -1,5 +1,6 @@
 /*-
  * Copyright (c) 2007 Robert N. M. Watson
+ * Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -46,7 +47,8 @@
 	static char pathname[PATH_MAX];
 
 	if (!hflag)
-		printf("%5s %-16s %8s %s\n", "PID", "COMM", "OSREL", "PATH");
+		xo_emit("{T:/%5s %-16s %8s %s}\n", "PID", "COMM", "OSREL",
+		    "PATH");
 
 	if (procstat_getpathname(prstat, kipp, pathname, sizeof(pathname)) != 0)
 		return;
@@ -55,8 +57,8 @@
 	if (procstat_getosrel(prstat, kipp, &osrel) != 0)
 		return;
 
-	printf("%5d ", kipp->ki_pid);
-	printf("%-16s ", kipp->ki_comm);
-	printf("%8d ", osrel);
-	printf("%s\n", pathname);
+	xo_emit("{k:process_id/%5d/%d} ", kipp->ki_pid);
+	xo_emit("{:command/%-16s/%s} ", kipp->ki_comm);
+	xo_emit("{:osrel/%8d/%d} ", osrel);
+	xo_emit("{:pathname/%s}\n", pathname);
 }
Index: head/usr.bin/procstat/procstat_cred.c
===================================================================
--- head/usr.bin/procstat/procstat_cred.c
+++ head/usr.bin/procstat/procstat_cred.c
@@ -1,5 +1,6 @@
 /*-
  * Copyright (c) 2007-2008 Robert N. M. Watson
+ * Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -48,21 +49,22 @@
 	gid_t *groups;
 
 	if (!hflag)
-		printf("%5s %-16s %5s %5s %5s %5s %5s %5s %5s %5s %-15s\n",
+		xo_emit("{T:/%5s %-16s %5s %5s %5s %5s %5s %5s %5s %5s %-15s}\n",
 		    "PID", "COMM", "EUID", "RUID", "SVUID", "EGID", "RGID",
 		    "SVGID", "UMASK", "FLAGS", "GROUPS");
 
-	printf("%5d ", kipp->ki_pid);
-	printf("%-16s ", kipp->ki_comm);
-	printf("%5d ", kipp->ki_uid);
-	printf("%5d ", kipp->ki_ruid);
-	printf("%5d ", kipp->ki_svuid);
-	printf("%5d ", kipp->ki_groups[0]);
-	printf("%5d ", kipp->ki_rgid);
-	printf("%5d ", kipp->ki_svgid);
-	printf("%5s ", get_umask(procstat, kipp));
-	printf("%s", kipp->ki_cr_flags & CRED_FLAG_CAPMODE ? "C" : "-");
-	printf("     ");
+	xo_emit("{k:process_id/%5d/%d} ", kipp->ki_pid);
+	xo_emit("{:command/%-16s/%s} ", kipp->ki_comm);
+	xo_emit("{:uid/%5d} ", kipp->ki_uid);
+	xo_emit("{:ruid/%5d} ", kipp->ki_ruid);
+	xo_emit("{:svuid/%5d} ", kipp->ki_svuid);
+	xo_emit("{:group/%5d} ", kipp->ki_groups[0]);
+	xo_emit("{:rgid/%5d} ", kipp->ki_rgid);
+	xo_emit("{:svgid/%5d} ", kipp->ki_svgid);
+	xo_emit("{:umask/%5s} ", get_umask(procstat, kipp));
+	xo_emit("{:cr_flags/%s}", kipp->ki_cr_flags & CRED_FLAG_CAPMODE ?
+	    "C" : "-");
+	xo_emit("{P:     }");
 
 	groups = NULL;
 	/*
@@ -76,12 +78,14 @@
 		ngroups = kipp->ki_ngroups;
 		groups = kipp->ki_groups;
 	}
+	xo_open_list("groups");
 	for (i = 0; i < ngroups; i++)
-		printf("%s%d", (i > 0) ? "," : "", groups[i]);
+		xo_emit("{D:/%s}{l:groups/%d}", (i > 0) ? "," : "", groups[i]);
 	if (groups != kipp->ki_groups)
 		procstat_freegroups(procstat, groups);
 
-	printf("\n");
+	xo_close_list("groups");
+	xo_emit("\n");
 }
 
 static const char *
Index: head/usr.bin/procstat/procstat_cs.c
===================================================================
--- head/usr.bin/procstat/procstat_cs.c
+++ head/usr.bin/procstat/procstat_cs.c
@@ -1,5 +1,6 @@
 /*-
  * Copyright (c) 2007 Robert N. M. Watson
+ * Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -28,6 +29,7 @@
 
 #include <sys/param.h>
 #include <sys/cpuset.h>
+#include <sys/sbuf.h>
 #include <sys/sysctl.h>
 #include <sys/user.h>
 
@@ -46,11 +48,12 @@
 	cpusetid_t cs;
 	cpuset_t mask;
 	struct kinfo_proc *kip;
+	struct sbuf *cpusetbuf;
 	unsigned int count, i;
 	int once, twice, lastcpu, cpu;
 
 	if (!hflag)
-		printf("%5s %6s %-16s %-16s %2s %4s %-7s\n", "PID",
+		xo_emit("{T:/%5s %6s %-16s %-16s %2s %4s %-7s}\n", "PID",
 		    "TID", "COMM", "TDNAME", "CPU", "CSID", "CPU MASK");
 
 	kip = procstat_getprocs(procstat, KERN_PROC_PID | KERN_PROC_INC_THREAD,
@@ -60,49 +63,57 @@
 	kinfo_proc_sort(kip, count);
 	for (i = 0; i < count; i++) {
 		kipp = &kip[i];
-		printf("%5d ", kipp->ki_pid);
-		printf("%6d ", kipp->ki_tid);
-		printf("%-16s ", strlen(kipp->ki_comm) ?
+		xo_emit("{k:process_id/%5d/%d} ", kipp->ki_pid);
+		xo_emit("{:thread_id/%6d/%d} ", kipp->ki_tid);
+		xo_emit("{:command/%-16s/%s} ", strlen(kipp->ki_comm) ?
 		    kipp->ki_comm : "-");
-		printf("%-16s ", (strlen(kipp->ki_tdname) &&
+		xo_emit("{:thread_name/%-16s/%s} ", (strlen(kipp->ki_tdname) &&
 		    (strcmp(kipp->ki_comm, kipp->ki_tdname) != 0)) ?
 		    kipp->ki_tdname : "-");
 		if (kipp->ki_oncpu != 255)
-			printf("%3d ", kipp->ki_oncpu);
+			xo_emit("{:cpu/%3d/%d} ", kipp->ki_oncpu);
 		else if (kipp->ki_lastcpu != 255)
-			printf("%3d ", kipp->ki_lastcpu);
+			xo_emit("{:cpu/%3d/%d} ", kipp->ki_lastcpu);
 		else
-			printf("%3s ", "-");
+			xo_emit("{:cpu/%3s/%s} ", "-");
 		if (cpuset_getid(CPU_LEVEL_CPUSET, CPU_WHICH_TID,
 		    kipp->ki_tid, &cs) != 0) {
 			cs = CPUSET_INVALID;
 		}
-		printf("%4d ", cs);
+		xo_emit("{:cpu_set_id/%4d/%d} ", cs);
 		if ((cs != CPUSET_INVALID) && 
 		    (cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID,
 		    kipp->ki_tid, sizeof(mask), &mask) == 0)) {
 			lastcpu = -1;
 			once = 0;
 			twice = 0;
+			cpusetbuf = sbuf_new_auto();
 			for (cpu = 0; cpu < CPU_SETSIZE; cpu++) {
 				if (CPU_ISSET(cpu, &mask)) {
 					if (once == 0) {
-						printf("%d", cpu);
+						sbuf_printf(cpusetbuf, "%d",
+						    cpu);
 						once = 1;
 					} else if (cpu == lastcpu + 1) {
 						twice = 1;
 					} else if (twice == 1) {
-						printf("-%d,%d", lastcpu, cpu);
+						sbuf_printf(cpusetbuf, "-%d,%d",
+						    lastcpu, cpu);
 						twice = 0;
 					} else
-						printf(",%d", cpu);
+						sbuf_printf(cpusetbuf, ",%d",
+						    cpu);
 					lastcpu = cpu;
 				}
 			}
 			if (once && twice)
-				printf("-%d", lastcpu);
+				sbuf_printf(cpusetbuf, "-%d", lastcpu);
+			if (sbuf_finish(cpusetbuf) != 0)
+				xo_err(1, "Could not generate output");
+			xo_emit("{:cpu_set/%s}", sbuf_data(cpusetbuf));
+			sbuf_delete(cpusetbuf);
 		}
-		printf("\n");
+		xo_emit("\n");
 	}
 	procstat_freeprocs(procstat, kip);
 }
Index: head/usr.bin/procstat/procstat_files.c
===================================================================
--- head/usr.bin/procstat/procstat_files.c
+++ head/usr.bin/procstat/procstat_files.c
@@ -1,5 +1,6 @@
 /*-
  * Copyright (c) 2007-2011 Robert N. M. Watson
+ * Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -123,15 +124,6 @@
 	}
 }
 
-static void
-print_address(struct sockaddr_storage *ss)
-{
-	char addr[PATH_MAX];
-
-	addr_to_string(ss, addr, sizeof(addr));
-	printf("%s", addr);
-}
-
 static struct cap_desc {
 	uint64_t	 cd_right;
 	const char	*cd_desc;
@@ -273,19 +265,22 @@
 	width = 0;
 	for (i = width_capability(rightsp); i < capwidth; i++) {
 		if (i != 0)
-			printf(" ");
+			xo_emit(" ");
 		else
-			printf("-");
+			xo_emit("-");
 	}
+	xo_open_list("capabilities");
 	for (i = 0; i < cap_desc_count; i++) {
 		if (cap_rights_is_set(rightsp, cap_desc[i].cd_right)) {
-			printf("%s%s", count ? "," : "", cap_desc[i].cd_desc);
+			xo_emit("{D:/%s}{l:capabilities/%s}", count ? "," : "",
+			    cap_desc[i].cd_desc);
 			width += strlen(cap_desc[i].cd_desc);
 			if (count)
 				width++;
 			count++;
 		}
 	}
+	xo_close_list("capabilities");
 }
 
 void
@@ -298,6 +293,8 @@
 	struct vnstat vn;
 	u_int capwidth, width;
 	int error;
+	char src_addr[PATH_MAX];
+	char dst_addr[PATH_MAX];
 
 	/*
 	 * To print the header in capability mode, we need to know the width
@@ -319,84 +316,103 @@
 
 	if (!hflag) {
 		if (Cflag)
-			printf("%5s %-16s %5s %1s %-8s %-*s "
-			    "%-3s %-12s\n", "PID", "COMM", "FD", "T",
+			xo_emit("{T:/%5s %-16s %5s %1s %-8s %-*s "
+			    "%-3s %-12s}\n", "PID", "COMM", "FD", "T",
 			    "FLAGS", capwidth, "CAPABILITIES", "PRO",
 			    "NAME");
 		else
-			printf("%5s %-16s %5s %1s %1s %-8s "
-			    "%3s %7s %-3s %-12s\n", "PID", "COMM", "FD", "T",
+			xo_emit("{T:/%5s %-16s %5s %1s %1s %-8s "
+			    "%3s %7s %-3s %-12s}\n", "PID", "COMM", "FD", "T",
 			    "V", "FLAGS", "REF", "OFFSET", "PRO", "NAME");
 	}
 
 	if (head == NULL)
 		return;
+	xo_emit("{ek:process_id/%5d/%d}", kipp->ki_pid);
+	xo_emit("{e:command/%-16s/%s}", kipp->ki_comm);
+	xo_open_list("files");
 	STAILQ_FOREACH(fst, head, next) {
-		printf("%5d ", kipp->ki_pid);
-		printf("%-16s ", kipp->ki_comm);
+		xo_open_instance("files");
+		xo_emit("{dk:process_id/%5d/%d} ", kipp->ki_pid);
+		xo_emit("{d:command/%-16s/%s} ", kipp->ki_comm);
 		if (fst->fs_uflags & PS_FST_UFLAG_CTTY)
-			printf(" ctty ");
+			xo_emit("{P: }{:fd/%s} ", "ctty");
 		else if (fst->fs_uflags & PS_FST_UFLAG_CDIR)
-			printf("  cwd ");
+			xo_emit("{P:  }{:fd/%s} ", "cwd");
 		else if (fst->fs_uflags & PS_FST_UFLAG_JAIL)
-			printf(" jail ");
+			xo_emit("{P: }{:fd/%s} ", "jail");
 		else if (fst->fs_uflags & PS_FST_UFLAG_RDIR)
-			printf(" root ");
+			xo_emit("{P: }{:fd/%s} ", "root");
 		else if (fst->fs_uflags & PS_FST_UFLAG_TEXT)
-			printf(" text ");
+			xo_emit("{P: }{:fd/%s} ", "text");
 		else if (fst->fs_uflags & PS_FST_UFLAG_TRACE)
-			printf("trace ");
+			xo_emit("{:fd/%s} ", "trace");
 		else
-			printf("%5d ", fst->fs_fd);
+			xo_emit("{:fd/%5d} ", fst->fs_fd);
 
 		switch (fst->fs_type) {
 		case PS_FST_TYPE_VNODE:
 			str = "v";
+			xo_emit("{eq:fd_type/vnode}");
 			break;
 
 		case PS_FST_TYPE_SOCKET:
 			str = "s";
+			xo_emit("{eq:fd_type/socket}");
 			break;
 
 		case PS_FST_TYPE_PIPE:
 			str = "p";
+			xo_emit("{eq:fd_type/pipe}");
 			break;
 
 		case PS_FST_TYPE_FIFO:
 			str = "f";
+			xo_emit("{eq:fd_type/fifo}");
 			break;
 
 		case PS_FST_TYPE_KQUEUE:
 			str = "k";
+			xo_emit("{eq:fd_type/kqueue}");
 			break;
 
 		case PS_FST_TYPE_CRYPTO:
 			str = "c";
+			xo_emit("{eq:fd_type/crypto}");
 			break;
 
 		case PS_FST_TYPE_MQUEUE:
 			str = "m";
+			xo_emit("{eq:fd_type/mqueue}");
 			break;
 
 		case PS_FST_TYPE_SHM:
 			str = "h";
+			xo_emit("{eq:fd_type/shm}");
 			break;
 
 		case PS_FST_TYPE_PTS:
 			str = "t";
+			xo_emit("{eq:fd_type/pts}");
 			break;
 
 		case PS_FST_TYPE_SEM:
 			str = "e";
+			xo_emit("{eq:fd_type/sem}");
 			break;
 
 		case PS_FST_TYPE_NONE:
+			str = "?";
+			xo_emit("{eq:fd_type/none}");
+			break;
+
 		case PS_FST_TYPE_UNKNOWN:
 		default:
 			str = "?";
+			xo_emit("{eq:fd_type/unknown}");
 			break;
 		}
-		printf("%1s ", str);
+		xo_emit("{d:fd_type/%1s/%s} ", str);
 		if (!Cflag) {
 			str = "-";
 			if (fst->fs_type == PS_FST_TYPE_VNODE) {
@@ -405,74 +421,118 @@
 				switch (vn.vn_type) {
 				case PS_FST_VTYPE_VREG:
 					str = "r";
+					xo_emit("{eq:vode_type/regular}");
 					break;
 
 				case PS_FST_VTYPE_VDIR:
 					str = "d";
+					xo_emit("{eq:vode_type/directory}");
 					break;
 
 				case PS_FST_VTYPE_VBLK:
 					str = "b";
+					xo_emit("{eq:vode_type/block}");
 					break;
 
 				case PS_FST_VTYPE_VCHR:
 					str = "c";
+					xo_emit("{eq:vode_type/character}");
 					break;
 
 				case PS_FST_VTYPE_VLNK:
 					str = "l";
+					xo_emit("{eq:vode_type/link}");
 					break;
 
 				case PS_FST_VTYPE_VSOCK:
 					str = "s";
+					xo_emit("{eq:vode_type/socket}");
 					break;
 
 				case PS_FST_VTYPE_VFIFO:
 					str = "f";
+					xo_emit("{eq:vode_type/fifo}");
 					break;
 
 				case PS_FST_VTYPE_VBAD:
 					str = "x";
+					xo_emit("{eq:vode_type/revoked_device}");
 					break;
 
 				case PS_FST_VTYPE_VNON:
+					str = "?";
+					xo_emit("{eq:vode_type/non}");
+					break;
+
 				case PS_FST_VTYPE_UNKNOWN:
 				default:
 					str = "?";
+					xo_emit("{eq:vode_type/unknown}");
 					break;
 				}
 			}
-			printf("%1s ", str);
+			xo_emit("{d:vnode_type/%1s/%s} ", str);
 		}
-		printf("%s", fst->fs_fflags & PS_FST_FFLAG_READ ? "r" : "-");
-		printf("%s", fst->fs_fflags & PS_FST_FFLAG_WRITE ? "w" : "-");
-		printf("%s", fst->fs_fflags & PS_FST_FFLAG_APPEND ? "a" : "-");
-		printf("%s", fst->fs_fflags & PS_FST_FFLAG_ASYNC ? "s" : "-");
-		printf("%s", fst->fs_fflags & PS_FST_FFLAG_SYNC ? "f" : "-");
-		printf("%s", fst->fs_fflags & PS_FST_FFLAG_NONBLOCK ? "n" : "-");
-		printf("%s", fst->fs_fflags & PS_FST_FFLAG_DIRECT ? "d" : "-");
-		printf("%s", fst->fs_fflags & PS_FST_FFLAG_HASLOCK ? "l" : "-");
-		printf(" ");
+		
+		xo_emit("{d:/%s}", fst->fs_fflags & PS_FST_FFLAG_READ ?
+		    "r" : "-");
+		xo_emit("{d:/%s}", fst->fs_fflags & PS_FST_FFLAG_WRITE ?
+		    "w" : "-");
+		xo_emit("{d:/%s}", fst->fs_fflags & PS_FST_FFLAG_APPEND ?
+		    "a" : "-");
+		xo_emit("{d:/%s}", fst->fs_fflags & PS_FST_FFLAG_ASYNC ?
+		    "s" : "-");
+		xo_emit("{d:/%s}", fst->fs_fflags & PS_FST_FFLAG_SYNC ?
+		    "f" : "-");
+		xo_emit("{d:/%s}", fst->fs_fflags & PS_FST_FFLAG_NONBLOCK ?
+		    "n" : "-");
+		xo_emit("{d:/%s}", fst->fs_fflags & PS_FST_FFLAG_DIRECT ?
+		    "d" : "-");
+		xo_emit("{d:/%s}", fst->fs_fflags & PS_FST_FFLAG_HASLOCK ?
+		    "l" : "-");
+		xo_emit(" ");
+		xo_open_list("fd_flags");
+		if (fst->fs_fflags & PS_FST_FFLAG_READ)
+			xo_emit("{elq:fd_flags/read}");
+		if (fst->fs_fflags & PS_FST_FFLAG_WRITE)
+			xo_emit("{elq:fd_flags/write}");
+		if (fst->fs_fflags & PS_FST_FFLAG_APPEND)
+			xo_emit("{elq:fd_flags/append}");
+		if (fst->fs_fflags & PS_FST_FFLAG_ASYNC)
+			xo_emit("{elq:fd_flags/async}");
+		if (fst->fs_fflags & PS_FST_FFLAG_SYNC)
+			xo_emit("{elq:fd_flags/fsync}");
+		if (fst->fs_fflags & PS_FST_FFLAG_NONBLOCK)
+			xo_emit("{elq:fd_flags/nonblocking}");
+		if (fst->fs_fflags & PS_FST_FFLAG_DIRECT)
+			xo_emit("{elq:fd_flags/direct_io}");
+		if (fst->fs_fflags & PS_FST_FFLAG_HASLOCK)
+			xo_emit("{elq:fd_flags/lock_held}");
+		xo_close_list("fd_flags");
+
 		if (!Cflag) {
 			if (fst->fs_ref_count > -1)
-				printf("%3d ", fst->fs_ref_count);
+				xo_emit("{:ref_count/%3d/%d} ",
+				    fst->fs_ref_count);
 			else
-				printf("%3c ", '-');
+				xo_emit("{q:ref_count/%3c/%c} ", '-');
 			if (fst->fs_offset > -1)
-				printf("%7jd ", (intmax_t)fst->fs_offset);
+				xo_emit("{:offset/%7jd/%jd} ",
+				    (intmax_t)fst->fs_offset);
 			else
-				printf("%7c ", '-');
+				xo_emit("{q:offset/%7c/%c} ", '-');
 		}
 		if (Cflag) {
 			print_capability(&fst->fs_cap_rights, capwidth);
-			printf(" ");
+			xo_emit(" ");
 		}
 		switch (fst->fs_type) {
 		case PS_FST_TYPE_SOCKET:
-			error = procstat_get_socket_info(procstat, fst, &sock, NULL);
+			error = procstat_get_socket_info(procstat, fst, &sock,
+			    NULL);
 			if (error != 0)
 				break;
-			printf("%-3s ",
+			xo_emit("{:protocol/%-3s/%s} ",
 			    protocol_to_string(sock.dom_family,
 			    sock.type, sock.proto));
 			/*
@@ -487,22 +547,30 @@
 				    (struct sockaddr_un *)&sock.sa_local;
 
 				if (sun->sun_path[0] != 0)
-					print_address(&sock.sa_local);
+					addr_to_string(&sock.sa_local,
+					    src_addr, sizeof(src_addr));
 				else
-					print_address(&sock.sa_peer);
+					addr_to_string(&sock.sa_peer,
+					    src_addr, sizeof(src_addr));
+				xo_emit("{:path/%s}", src_addr);
 			} else {
-				print_address(&sock.sa_local);
-				printf(" ");
-				print_address(&sock.sa_peer);
+				addr_to_string(&sock.sa_local, src_addr,
+				    sizeof(src_addr));
+				addr_to_string(&sock.sa_peer, dst_addr,
+				    sizeof(dst_addr));
+				xo_emit("{:path/%s %s}", src_addr, dst_addr);
 			}
 			break;
 
 		default:
-			printf("%-3s ", "-");
-			printf("%-18s", fst->fs_path != NULL ? fst->fs_path : "-");
+			xo_emit("{:protocol/%-3s/%s} ", "-");
+			xo_emit("{:path/%-18s/%s}", fst->fs_path != NULL ?
+			    fst->fs_path : "-");
 		}
 
-		printf("\n");
+		xo_emit("\n");
+		xo_close_instance("files");
 	}
+	xo_close_list("files");
 	procstat_freefiles(procstat, head);
 }
Index: head/usr.bin/procstat/procstat_kstack.c
===================================================================
--- head/usr.bin/procstat/procstat_kstack.c
+++ head/usr.bin/procstat/procstat_kstack.c
@@ -1,5 +1,6 @@
 /*-
  * Copyright (c) 2007 Robert N. M. Watson
+ * Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -105,6 +106,42 @@
 	*cp_new = '\0';
 }
 
+static void
+kstack_cleanup_encoded(const char *old, char *new, int kflag)
+{
+	enum trace_state old_ts, ts;
+	const char *cp_old;
+	char *cp_new, *cp_loop, *cp_tofree, *cp_line;
+
+	ts = TS_FRAMENUM;
+	if (kflag == 1) {
+		for (cp_old = old, cp_new = new; *cp_old != '\0'; cp_old++) {
+			switch (*cp_old) {
+			case '\n':
+				*cp_new = *cp_old;
+				cp_new++;
+			case ' ':
+			case '+':
+				old_ts = ts;
+				ts = kstack_nextstate(old_ts);
+				continue;
+			}
+			if (ts == TS_FUNC) {
+				*cp_new = *cp_old;
+				cp_new++;
+			}
+		}
+		cp_tofree = cp_loop = strdup(new);
+	} else
+		cp_tofree = cp_loop = strdup(old);
+        while ((cp_line = strsep(&cp_loop, "\n")) != NULL) {
+		if (strlen(cp_line) != 0 && *cp_line != 127)
+			xo_emit("{le:token/%s}", cp_line);
+	}
+	*cp_new = '\0';
+	free(cp_tofree);
+}
+
 /*
  * Sort threads by tid.
  */
@@ -129,12 +166,12 @@
 {
 	struct kinfo_kstack *kkstp, *kkstp_free;
 	struct kinfo_proc *kip, *kip_free;
-	char trace[KKST_MAXLEN];
+	char trace[KKST_MAXLEN], encoded_trace[KKST_MAXLEN];
 	unsigned int i, j;
 	unsigned int kip_count, kstk_count;
 
 	if (!hflag)
-		printf("%5s %6s %-16s %-16s %-29s\n", "PID", "TID", "COMM",
+		xo_emit("{T:/%5s %6s %-16s %-16s %-29s}\n", "PID", "TID", "COMM",
 		    "TDNAME", "KSTACK");
 
 	kkstp = kkstp_free = procstat_getkstack(procstat, kipp, &kstk_count);
@@ -169,27 +206,27 @@
 		if (kipp == NULL)
 			continue;
 
-		printf("%5d ", kipp->ki_pid);
-		printf("%6d ", kkstp->kkst_tid);
-		printf("%-16s ", kipp->ki_comm);
-		printf("%-16s ", (strlen(kipp->ki_tdname) &&
+		xo_emit("{k:process_id/%5d/%d} ", kipp->ki_pid);
+		xo_emit("{:thread_id/%6d/%d} ", kkstp->kkst_tid);
+		xo_emit("{:command/%-16s/%s} ", kipp->ki_comm);
+		xo_emit("{:thread_name/%-16s/%s} ", (strlen(kipp->ki_tdname) &&
 		    (strcmp(kipp->ki_comm, kipp->ki_tdname) != 0)) ?
 		    kipp->ki_tdname : "-");
 
 		switch (kkstp->kkst_state) {
 		case KKST_STATE_RUNNING:
-			printf("%-29s\n", "<running>");
+			xo_emit("{:state/%-29s/%s}\n", "<running>");
 			continue;
 
 		case KKST_STATE_SWAPPED:
-			printf("%-29s\n", "<swapped>");
+			xo_emit("{:state/%-29s/%s}\n", "<swapped>");
 			continue;
 
 		case KKST_STATE_STACKOK:
 			break;
 
 		default:
-			printf("%-29s\n", "<unknown>");
+			xo_emit("{:state/%-29s/%s}\n", "<unknown>");
 			continue;
 		}
 
@@ -199,7 +236,10 @@
 		 * returns to spaces.
 		 */
 		kstack_cleanup(kkstp->kkst_trace, trace, kflag);
-		printf("%-29s\n", trace);
+		xo_open_list("trace");
+		kstack_cleanup_encoded(kkstp->kkst_trace, encoded_trace, kflag);
+		xo_close_list("trace");
+		xo_emit("{d:trace/%-29s}\n", trace);
 	}
 	procstat_freekstack(procstat, kkstp_free);
 	procstat_freeprocs(procstat, kip_free);
Index: head/usr.bin/procstat/procstat_rlimit.c
===================================================================
--- head/usr.bin/procstat/procstat_rlimit.c
+++ head/usr.bin/procstat/procstat_rlimit.c
@@ -1,5 +1,6 @@
 /*-
  * Copyright (c) 2011 Mikolaj Golub
+ * Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -93,15 +94,33 @@
 	int i;
 
 	if (!hflag) {
-		printf("%5s %-16s %-16s %16s %16s\n",
+		xo_emit("{T:/%5s %-16s %-16s %16s %16s}\n",
 		    "PID", "COMM", "RLIMIT", "SOFT     ", "HARD     ");
 	}
+	xo_emit("{ek:process_id/%5d}{e:command/%-16s/%s}", kipp->ki_pid,
+	    kipp->ki_comm);
 	for (i = 0; i < RLIM_NLIMITS; i++) {
 		if (procstat_getrlimit(prstat, kipp, i, &rlimit) == -1)
 			return;
-		printf("%5d %-16s %-16s ", kipp->ki_pid, kipp->ki_comm,
+		xo_emit("{dk:process_id/%5d} {d:command/%-16s} "
+		    "{d:rlimit_param/%-16s} ", kipp->ki_pid, kipp->ki_comm,
 		    rlimit_param[i].name);
-		printf("%16s ", humanize_rlimit(i, rlimit.rlim_cur));
-		printf("%16s\n", humanize_rlimit(i, rlimit.rlim_max));
+
+		xo_open_container(rlimit_param[i].name);
+		if (rlimit.rlim_cur == RLIM_INFINITY)
+			xo_emit("{e:soft_limit/infinity}");
+		else
+			xo_emit("{e:soft_limit/%U}", rlimit.rlim_cur);
+
+		if (rlimit.rlim_max == RLIM_INFINITY)
+			xo_emit("{e:hard_limit/infinity}");
+		else
+			xo_emit("{e:hard_limit/%U}", rlimit.rlim_max);
+		xo_close_container(rlimit_param[i].name);
+
+		xo_emit("{d:rlim_cur/%16s} ",
+		    humanize_rlimit(i, rlimit.rlim_cur));
+		xo_emit("{d:rlim_max/%16s}\n",
+		    humanize_rlimit(i, rlimit.rlim_max));
 	}
 }
Index: head/usr.bin/procstat/procstat_rusage.c
===================================================================
--- head/usr.bin/procstat/procstat_rusage.c
+++ head/usr.bin/procstat/procstat_rusage.c
@@ -1,6 +1,7 @@
 /*-
  * Copyright (c) 2012 Hudson River Trading LLC
  * Written by: John H. Baldwin <jhb@FreeBSD.org>
+ * Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -35,6 +36,7 @@
 #include <libprocstat.h>
 #include <stdbool.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <libutil.h>
 
 #include "procstat.h"
@@ -79,7 +81,7 @@
 	else if (days > 0)
 		used += snprintf(buffer, sizeof(buffer), "%u days ", days);
 	
-	snprintf(buffer + used, sizeof(buffer) - used, "%02u:%02u:%02u.%06u   ",
+	snprintf(buffer + used, sizeof(buffer) - used, "%02u:%02u:%02u.%06u",
 	    hours, minutes, seconds, (unsigned int)tv->tv_usec);
 	return (buffer);
 }
@@ -103,10 +105,10 @@
 print_prefix(struct kinfo_proc *kipp)
 {
 
-	printf("%5d ", kipp->ki_pid);
+	xo_emit("{d:process_id/%5d/%d} ", kipp->ki_pid);
 	if (Hflag)
-		printf("%6d ", kipp->ki_tid);
-	printf("%-16s ", kipp->ki_comm);
+		xo_emit("{d:thread_id/%6d/%d} ", kipp->ki_tid);
+	xo_emit("{d:command/%-16s/%s} ", kipp->ki_comm);
 }
 
 static void
@@ -114,21 +116,48 @@
 {
 	long *lp;
 	unsigned int i;
+	char *field, *threadid;
 
 	print_prefix(kipp);
-	printf("%-14s %32s\n", "user time",
+	xo_emit("{d:resource/%-14s} {d:usage/%29s}{P:   }\n", "user time",
 	    format_time(&kipp->ki_rusage.ru_utime));
 	print_prefix(kipp);
-	printf("%-14s %32s\n", "system time",
+	xo_emit("{d:resource/%-14s} {d:usage/%29s}{P:   }\n", "system time",
 	    format_time(&kipp->ki_rusage.ru_stime));
+
+	if (Hflag) {
+		asprintf(&threadid, "%d", kipp->ki_tid);
+		if (threadid == NULL)
+			xo_errc(1, ENOMEM,
+			    "Failed to allocate memory in print_rusage()");
+		xo_open_container(threadid);
+		xo_emit("{e:thread_id/%d}", kipp->ki_tid);
+	} else {
+		xo_emit("{e:process_id/%d}", kipp->ki_pid);
+		xo_emit("{e:command/%s}", kipp->ki_comm);
+	}
+	xo_emit("{e:user time/%s}", format_time(&kipp->ki_rusage.ru_utime));
+	xo_emit("{e:system time/%s}", format_time(&kipp->ki_rusage.ru_stime));
+
 	lp = &kipp->ki_rusage.ru_maxrss;
 	for (i = 0; i < nitems(rusage_info); i++) {
 		print_prefix(kipp);
-		printf("%-32s %14s\n", rusage_info[i].ri_name,
+		asprintf(&field, "{e:%s/%%D}", rusage_info[i].ri_name);
+		if (field == NULL)
+			xo_errc(1, ENOMEM,
+			    "Failed to allocate memory in print_rusage()");
+		xo_emit(field, *lp);
+		free(field);
+		xo_emit("{d:resource/%-32s} {d:usage/%14s}\n",
+		    rusage_info[i].ri_name,
 		    format_value(*lp, rusage_info[i].ri_humanize,
-			rusage_info[i].ri_scale));
+		    rusage_info[i].ri_scale));
 		lp++;
 	}
+	if (Hflag) {
+		xo_close_container(threadid);
+		free(threadid);
+	}
 }
 
 void
@@ -138,10 +167,10 @@
 	unsigned int count, i;
 
 	if (!hflag) {
-		printf("%5s ", "PID");
+		xo_emit("{d:ta/%5s} ", "PID");
 		if (Hflag)
-			printf("%6s ", "TID");
-		printf("%-16s %-32s %14s\n", "COMM", "RESOURCE",
+			xo_emit("{d:tb/%6s} ", "TID");
+		xo_emit("{d:tc/%-16s %-32s %14s}\n", "COMM", "RESOURCE",
 		    "VALUE        ");
 	}
 
@@ -150,12 +179,19 @@
 		return;
 	}
 
+	xo_emit("{e:process_id/%d}", kipp->ki_pid);
+	xo_emit("{e:command/%s}", kipp->ki_comm);
+	xo_open_container("threads");
+
 	kip = procstat_getprocs(procstat, KERN_PROC_PID | KERN_PROC_INC_THREAD,
 	    kipp->ki_pid, &count);
 	if (kip == NULL)
 		return;
 	kinfo_proc_sort(kip, count);
-	for (i = 0; i < count; i++)
+	for (i = 0; i < count; i++) {
 		print_rusage(&kip[i]);
+	}
+
+	xo_close_container("threads");
 	procstat_freeprocs(procstat, kip);
 }
Index: head/usr.bin/procstat/procstat_sigs.c
===================================================================
--- head/usr.bin/procstat/procstat_sigs.c
+++ head/usr.bin/procstat/procstat_sigs.c
@@ -1,5 +1,6 @@
 /*-
  * Copyright (c) 2010 Konstantin Belousov
+ * Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -51,70 +52,129 @@
 		strlcpy(name, sys_signame[sig], sizeof(name));
 		for (i = 0; name[i] != 0; i++)
 			name[i] = toupper(name[i]);
-		printf("%-7s ", name);
+		xo_emit("{d:signal/%-7s/%s} ", name);
+		xo_open_container(name);
+	} else {
+		xo_emit("{d:signal/%-7d/%d} ", sig);
+		snprintf(name, 12, "%d", sig);
+		xo_open_container(name);
+	}
+}
+
+static void
+procstat_close_signame(int sig)
+{
+	char name[12];
+	int i;
+
+	if (!nflag && sig < sys_nsig) {
+		strlcpy(name, sys_signame[sig], sizeof(name));
+		for (i = 0; name[i] != 0; i++)
+			name[i] = toupper(name[i]);
+		xo_close_container(name);
 	} else
-		printf("%-7d ", sig);
+		snprintf(name, 12, "%d", sig);
+		xo_close_container(name);
 }
 
 static void
 procstat_print_sig(const sigset_t *set, int sig, char flag)
 {
-
-	printf("%c", sigismember(set, sig) ? flag : '-');
+	xo_emit("{d:sigmember/%c}", sigismember(set, sig) ? flag : '-');
+	switch (flag) {
+		case 'B':
+			xo_emit("{en:mask/%s}", sigismember(set, sig) ?
+			    "true" : "false");
+			break;
+		case 'C':
+			xo_emit("{en:catch/%s}", sigismember(set, sig) ?
+			    "true" : "false");
+			break;
+		case 'P':
+			xo_emit("{en:list/%s}", sigismember(set, sig) ?
+			    "true" : "false");
+			break;
+		case 'I':
+			xo_emit("{en:ignore/%s}", sigismember(set, sig) ?
+			    "true" : "false");
+			break;
+		default:
+			xo_emit("{en:unknown/%s}", sigismember(set, sig) ?
+			    "true" : "false");
+			break;
+	}
 }
 
 void
 procstat_sigs(struct procstat *prstat __unused, struct kinfo_proc *kipp)
 {
 	int j;
-	pid_t pid;
 
-	pid = kipp->ki_pid;
 	if (!hflag)
-		printf("%5s %-16s %-7s %4s\n", "PID", "COMM", "SIG", "FLAGS");
+		xo_emit("{T:/%5s %-16s %-7s %4s}\n", "PID", "COMM", "SIG",
+		    "FLAGS");
 
+	xo_emit("{ek:process_id/%5d/%d}", kipp->ki_pid);
+	xo_emit("{e:command/%-16s/%s}", kipp->ki_comm);
+	xo_open_container("signals");
 	for (j = 1; j <= _SIG_MAXSIG; j++) {
-		printf("%5d ", pid);
-		printf("%-16s ", kipp->ki_comm);
+		xo_emit("{dk:process_id/%5d/%d} ", kipp->ki_pid);
+		xo_emit("{d:command/%-16s/%s} ", kipp->ki_comm);
 		procstat_print_signame(j);
-		printf(" ");
+		xo_emit(" ");
 		procstat_print_sig(&kipp->ki_siglist, j, 'P');
 		procstat_print_sig(&kipp->ki_sigignore, j, 'I');
 		procstat_print_sig(&kipp->ki_sigcatch, j, 'C');
-		printf("\n");
+		procstat_close_signame(j);
+		xo_emit("\n");
 	}
+	xo_close_container("signals");
 }
 
 void
 procstat_threads_sigs(struct procstat *procstat, struct kinfo_proc *kipp)
 {
 	struct kinfo_proc *kip;
-	pid_t pid;
 	int j;
 	unsigned int count, i;
+	char *threadid;
 
-	pid = kipp->ki_pid;
 	if (!hflag)
-		printf("%5s %6s %-16s %-7s %4s\n", "PID", "TID", "COMM",
+		xo_emit("{T:/%5s %6s %-16s %-7s %4s}\n", "PID", "TID", "COMM",
 		     "SIG", "FLAGS");
 
 	kip = procstat_getprocs(procstat, KERN_PROC_PID | KERN_PROC_INC_THREAD,
-	    pid, &count);
+	    kipp->ki_pid, &count);
 	if (kip == NULL)
 		return;
+	xo_emit("{ek:process_id/%5d/%d}", kipp->ki_pid);
+	xo_emit("{e:command/%-16s/%s}", kipp->ki_comm);
+	xo_open_container("threads");
 	kinfo_proc_sort(kip, count);
 	for (i = 0; i < count; i++) {
 		kipp = &kip[i];
+		asprintf(&threadid, "%d", kipp->ki_tid);
+		if (threadid == NULL)
+			xo_errc(1, ENOMEM, "Failed to allocate memory in "
+			    "procstat_threads_sigs()");
+		xo_open_container(threadid);
+		xo_emit("{e:thread_id/%6d/%d}", kipp->ki_tid);
+		xo_open_container("signals");
 		for (j = 1; j <= _SIG_MAXSIG; j++) {
-			printf("%5d ", pid);
-			printf("%6d ", kipp->ki_tid);
-			printf("%-16s ", kipp->ki_comm);
+			xo_emit("{dk:process_id/%5d/%d} ", kipp->ki_pid);
+			xo_emit("{d:thread_id/%6d/%d} ", kipp->ki_tid);
+			xo_emit("{d:command/%-16s/%s} ", kipp->ki_comm);
 			procstat_print_signame(j);
-			printf(" ");
+			xo_emit(" ");
 			procstat_print_sig(&kipp->ki_siglist, j, 'P');
 			procstat_print_sig(&kipp->ki_sigmask, j, 'B');
-			printf("\n");
+			procstat_close_signame(j);
+			xo_emit("\n");
 		}
+		xo_close_container("signals");
+		xo_close_container(threadid);
+		free(threadid);
 	}
+	xo_close_container("threads");
 	procstat_freeprocs(procstat, kip);
 }
Index: head/usr.bin/procstat/procstat_threads.c
===================================================================
--- head/usr.bin/procstat/procstat_threads.c
+++ head/usr.bin/procstat/procstat_threads.c
@@ -1,5 +1,6 @@
 /*-
  * Copyright (c) 2007 Robert N. M. Watson
+ * Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -45,11 +46,17 @@
 	struct kinfo_proc *kip;
 	unsigned int count, i;
 	const char *str;
+	char *threadid;
 
 	if (!hflag)
-		printf("%5s %6s %-16s %-16s %2s %4s %-7s %-9s\n", "PID",
+		xo_emit("{T:/%5s %6s %-16s %-16s %2s %4s %-7s %-9s}\n", "PID",
 		    "TID", "COMM", "TDNAME", "CPU", "PRI", "STATE", "WCHAN");
 
+	xo_emit("{ek:process_id/%d}", kipp->ki_pid);
+	xo_emit("{e:command/%s}", strlen(kipp->ki_comm) ?
+		    kipp->ki_comm : "-");
+	xo_open_container("threads");
+
 	kip = procstat_getprocs(procstat, KERN_PROC_PID | KERN_PROC_INC_THREAD,
 	    kipp->ki_pid, &count);
 	if (kip == NULL)
@@ -57,20 +64,25 @@
 	kinfo_proc_sort(kip, count);
 	for (i = 0; i < count; i++) {
 		kipp = &kip[i];
-		printf("%5d ", kipp->ki_pid);
-		printf("%6d ", kipp->ki_tid);
-		printf("%-16s ", strlen(kipp->ki_comm) ?
+		asprintf(&threadid, "%d", kipp->ki_tid);
+		if (threadid == NULL)
+			xo_errc(1, ENOMEM, "Failed to allocate memory in "
+			    "procstat_threads()");
+		xo_open_container(threadid);
+		xo_emit("{dk:process_id/%5d/%d} ", kipp->ki_pid);
+		xo_emit("{:thread_id/%6d/%d} ", kipp->ki_tid);
+		xo_emit("{d:command/%-16s/%s} ", strlen(kipp->ki_comm) ?
 		    kipp->ki_comm : "-");
-		printf("%-16s ", (strlen(kipp->ki_tdname) &&
+		xo_emit("{:thread_name/%-16s/%s} ", (strlen(kipp->ki_tdname) &&
 		    (strcmp(kipp->ki_comm, kipp->ki_tdname) != 0)) ?
 		    kipp->ki_tdname : "-");
 		if (kipp->ki_oncpu != 255)
-			printf("%3d ", kipp->ki_oncpu);
+			xo_emit("{:cpu/%3d/%d} ", kipp->ki_oncpu);
 		else if (kipp->ki_lastcpu != 255)
-			printf("%3d ", kipp->ki_lastcpu);
+			xo_emit("{:cpu/%3d/%d} ", kipp->ki_lastcpu);
 		else
-			printf("%3s ", "-");
-		printf("%4d ", kipp->ki_pri.pri_level);
+			xo_emit("{:cpu/%3s/%s} ", "-");
+		xo_emit("{:priority/%4d/%d} ", kipp->ki_pri.pri_level);
 		switch (kipp->ki_stat) {
 		case SRUN:
 			str = "run";
@@ -104,15 +116,19 @@
 			str = "??";
 			break;
 		}
-		printf("%-7s ", str);
+		xo_emit("{:run_state/%-7s/%s} ", str);
 		if (kipp->ki_kiflag & KI_LOCKBLOCK) {
-			printf("*%-8s ", strlen(kipp->ki_lockname) ?
+			xo_emit("{:lock_name/*%-8s/%s} ",
+			    strlen(kipp->ki_lockname) ?
 			    kipp->ki_lockname : "-");
 		} else {
-			printf("%-9s ", strlen(kipp->ki_wmesg) ?
-			    kipp->ki_wmesg : "-");
+			xo_emit("{:wait_channel/%-9s/%s} ",
+			    strlen(kipp->ki_wmesg) ? kipp->ki_wmesg : "-");
 		}
-		printf("\n");
+		xo_close_container(threadid);
+		free(threadid);
+		xo_emit("\n");
 	}
+	xo_close_container("threads");
 	procstat_freeprocs(procstat, kip);
 }
Index: head/usr.bin/procstat/procstat_vm.c
===================================================================
--- head/usr.bin/procstat/procstat_vm.c
+++ head/usr.bin/procstat/procstat_vm.c
@@ -1,5 +1,6 @@
 /*-
  * Copyright (c) 2007 Robert N. M. Watson
+ * Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -46,70 +47,118 @@
 	struct kinfo_vmentry *freep, *kve;
 	int ptrwidth;
 	int i, cnt;
-	const char *str;
+	const char *str, *lstr;
 
 	ptrwidth = 2*sizeof(void *) + 2;
 	if (!hflag)
-		printf("%5s %*s %*s %3s %4s %4s %3s %3s %-4s %-2s %-s\n",
+		xo_emit("{T:/%5s %*s %*s %3s %4s %4s %3s %3s %-4s %-2s %-s}\n",
 		    "PID", ptrwidth, "START", ptrwidth, "END", "PRT", "RES",
 		    "PRES", "REF", "SHD", "FLAG", "TP", "PATH");
 
+	xo_emit("{ek:process_id/%d}", kipp->ki_pid);
+
 	freep = procstat_getvmmap(procstat, kipp, &cnt);
 	if (freep == NULL)
 		return;
+	xo_open_list("vm");
 	for (i = 0; i < cnt; i++) {
+		xo_open_instance("vm");
 		kve = &freep[i];
-		printf("%5d ", kipp->ki_pid);
-		printf("%#*jx ", ptrwidth, (uintmax_t)kve->kve_start);
-		printf("%#*jx ", ptrwidth, (uintmax_t)kve->kve_end);
-		printf("%s", kve->kve_protection & KVME_PROT_READ ? "r" : "-");
-		printf("%s", kve->kve_protection & KVME_PROT_WRITE ? "w" : "-");
-		printf("%s ", kve->kve_protection & KVME_PROT_EXEC ? "x" : "-");
-		printf("%4d ", kve->kve_resident);
-		printf("%4d ", kve->kve_private_resident);
-		printf("%3d ", kve->kve_ref_count);
-		printf("%3d ", kve->kve_shadow_count);
-		printf("%-1s", kve->kve_flags & KVME_FLAG_COW ? "C" : "-");
-		printf("%-1s", kve->kve_flags & KVME_FLAG_NEEDS_COPY ? "N" :
-		    "-");
-		printf("%-1s", kve->kve_flags & KVME_FLAG_SUPER ? "S" : "-");
-		printf("%-1s ", kve->kve_flags & KVME_FLAG_GROWS_UP ? "U" :
-		    kve->kve_flags & KVME_FLAG_GROWS_DOWN ? "D" : "-");
+		xo_emit("{dk:process_id/%5d} ", kipp->ki_pid);
+		xo_emit("{d:kve_start/%#*jx} ", ptrwidth,
+		    (uintmax_t)kve->kve_start);
+		xo_emit("{d:kve_end/%#*jx} ", ptrwidth,
+		    (uintmax_t)kve->kve_end);
+		xo_emit("{e:kve_start/%#jx}", (uintmax_t)kve->kve_start);
+		xo_emit("{e:kve_end/%#jx}", (uintmax_t)kve->kve_end);
+		xo_emit("{d:read/%s}", kve->kve_protection & KVME_PROT_READ ?
+		    "r" : "-");
+		xo_emit("{d:write/%s}", kve->kve_protection & KVME_PROT_WRITE ?
+		    "w" : "-");
+		xo_emit("{d:exec/%s} ", kve->kve_protection & KVME_PROT_EXEC ?
+		    "x" : "-");
+		xo_open_container("kve_protection");
+		xo_emit("{en:read/%s}", kve->kve_protection & KVME_PROT_READ ?
+		    "true" : "false");
+		xo_emit("{en:write/%s}", kve->kve_protection & KVME_PROT_WRITE ?
+		    "true" : "false");
+		xo_emit("{en:exec/%s}", kve->kve_protection & KVME_PROT_EXEC ?
+		    "true" : "false");
+		xo_close_container("kve_protection");
+		xo_emit("{:kve_resident/%4d/%d} ", kve->kve_resident);
+		xo_emit("{:kve_private_resident/%4d/%d} ",
+		    kve->kve_private_resident);
+		xo_emit("{:kve_ref_count/%3d/%d} ", kve->kve_ref_count);
+		xo_emit("{:kve_shadow_count/%3d/%d} ", kve->kve_shadow_count);
+		xo_emit("{d:copy_on_write/%-1s}", kve->kve_flags &
+		    KVME_FLAG_COW ? "C" : "-");
+		xo_emit("{d:need_copy/%-1s}", kve->kve_flags &
+		    KVME_FLAG_NEEDS_COPY ? "N" : "-");
+		xo_emit("{d:super_pages/%-1s}", kve->kve_flags &
+		    KVME_FLAG_SUPER ? "S" : "-");
+		xo_emit("{d:grows_down/%-1s} ", kve->kve_flags &
+		    KVME_FLAG_GROWS_UP ? "U" : kve->kve_flags &
+		    KVME_FLAG_GROWS_DOWN ? "D" : "-");
+		xo_open_container("kve_flags");
+		xo_emit("{en:copy_on_write/%s}", kve->kve_flags &
+		    KVME_FLAG_COW ? "true" : "false");
+		xo_emit("{en:needs_copy/%s}", kve->kve_flags &
+		    KVME_FLAG_NEEDS_COPY ? "true" : "false");
+		xo_emit("{en:super_pages/%s}", kve->kve_flags &
+		    KVME_FLAG_SUPER ? "true" : "false");
+		xo_emit("{en:grows_up/%s}", kve->kve_flags &
+		    KVME_FLAG_GROWS_UP ? "true" : "false");
+		xo_emit("{en:grows_down/%s}", kve->kve_flags &
+		    KVME_FLAG_GROWS_DOWN ? "true" : "false");
+		xo_close_container("kve_flags");
 		switch (kve->kve_type) {
 		case KVME_TYPE_NONE:
 			str = "--";
+			lstr = "none";
 			break;
 		case KVME_TYPE_DEFAULT:
 			str = "df";
+			lstr = "default";
 			break;
 		case KVME_TYPE_VNODE:
 			str = "vn";
+			lstr = "vnode";
 			break;
 		case KVME_TYPE_SWAP:
 			str = "sw";
+			lstr = "swap";
 			break;
 		case KVME_TYPE_DEVICE:
 			str = "dv";
+			lstr = "device";
 			break;
 		case KVME_TYPE_PHYS:
 			str = "ph";
+			lstr = "physical";
 			break;
 		case KVME_TYPE_DEAD:
 			str = "dd";
+			lstr = "dead";
 			break;
 		case KVME_TYPE_SG:
 			str = "sg";
+			lstr = "scatter/gather";
 			break;
 		case KVME_TYPE_MGTDEVICE:
 			str = "md";
+			lstr = "managed_device";
 			break;
 		case KVME_TYPE_UNKNOWN:
 		default:
 			str = "??";
+			lstr = "unknown";
 			break;
 		}
-		printf("%-2s ", str);
-		printf("%-s\n", kve->kve_path);
+		xo_emit("{d:kve_type/%-2s} ", str);
+		xo_emit("{e:kve_type/%s}", lstr);
+		xo_emit("{:kve_path/%-s/%s}\n", kve->kve_path);
+		xo_close_instance("vm");
 	}
+	xo_close_list("vm");
 	free(freep);
 }