aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/libxo/doc/libxo-manual.html2
-rw-r--r--contrib/libxo/libxo/libxo.c244
-rw-r--r--contrib/libxo/tests/core/saved/test_01.E.out4
-rw-r--r--contrib/libxo/tests/core/saved/test_01.H.out4
-rw-r--r--contrib/libxo/tests/core/saved/test_01.HIPx.out9
-rw-r--r--contrib/libxo/tests/core/saved/test_01.HP.out9
-rw-r--r--contrib/libxo/tests/core/saved/test_01.J.out2
-rw-r--r--contrib/libxo/tests/core/saved/test_01.JP.out4
-rw-r--r--contrib/libxo/tests/core/saved/test_01.T.out2
-rw-r--r--contrib/libxo/tests/core/saved/test_01.X.out2
-rw-r--r--contrib/libxo/tests/core/saved/test_01.XP.out4
-rw-r--r--contrib/libxo/tests/core/saved/test_02.J.out2
-rw-r--r--contrib/libxo/tests/core/saved/test_02.JP.out2
-rw-r--r--contrib/libxo/tests/core/test_01.c4
-rw-r--r--contrib/libxo/xohtml/xohtml.css2
-rw-r--r--contrib/libxo/xohtml/xohtml.sh.in9
-rw-r--r--usr.bin/xohtml/Makefile31
-rwxr-xr-xusr.bin/xohtml/xohtml.sh79
-rw-r--r--usr.bin/xolint/Makefile13
-rw-r--r--usr.bin/xopo/Makefile21
20 files changed, 332 insertions, 117 deletions
diff --git a/contrib/libxo/doc/libxo-manual.html b/contrib/libxo/doc/libxo-manual.html
index c7577b922678..ef9def7c38f4 100644
--- a/contrib/libxo/doc/libxo-manual.html
+++ b/contrib/libxo/doc/libxo-manual.html
@@ -22011,7 +22011,7 @@ jQuery(function ($) {
</tr>
<tr>
<td class="header left"></td>
-<td class="header right">June 8, 2017</td>
+<td class="header right">June 14, 2017</td>
</tr>
</table></div>
<p id="title" class="title">libxo: The Easy Way to Generate text, XML, JSON, and HTML output<br><span class="filename">libxo-manual</span></p>
diff --git a/contrib/libxo/libxo/libxo.c b/contrib/libxo/libxo/libxo.c
index 7f015b7b2dcf..2b8ba68bd25e 100644
--- a/contrib/libxo/libxo/libxo.c
+++ b/contrib/libxo/libxo/libxo.c
@@ -95,6 +95,14 @@
#include <libintl.h>
#endif /* HAVE_GETTEXT */
+/* Rather lame that we can't count on these... */
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+
/*
* Three styles of specifying thread-local variables are supported.
* configure.ac has the brains to run each possibility through the
@@ -473,6 +481,7 @@ static void
xo_buf_append_div (xo_handle_t *xop, const char *class, xo_xff_flags_t flags,
const char *name, ssize_t nlen,
const char *value, ssize_t vlen,
+ const char *fmt, ssize_t flen,
const char *encoding, ssize_t elen);
static void
@@ -1761,7 +1770,8 @@ xo_message_hcv (xo_handle_t *xop, int code, const char *fmt, va_list vap)
rc += rc2;
}
- xo_buf_append_div(xop, "message", 0, NULL, 0, bp, rc, NULL, 0);
+ xo_buf_append_div(xop, "message", 0, NULL, 0, bp, rc,
+ NULL, 0, NULL, 0);
}
break;
@@ -2703,6 +2713,8 @@ xo_format_string_direct (xo_handle_t *xop, xo_buffer_t *xbp,
if ((flags & XFF_UNESCAPE) && (*cp == '\\' || *cp == '%')) {
cp += 1;
len -= 1;
+ if (len == 0 || *cp == '\0')
+ break;
}
}
@@ -3644,6 +3656,10 @@ xo_do_format_field (xo_handle_t *xop, xo_buffer_t *xbp,
return 0;
}
+/*
+ * Remove any numeric precision/width format from the format string by
+ * inserting the "%" after the [0-9]+, returning the substring.
+ */
static char *
xo_fix_encoding (xo_handle_t *xop UNUSED, char *encoding)
{
@@ -3657,8 +3673,7 @@ xo_fix_encoding (xo_handle_t *xop UNUSED, char *encoding)
break;
}
- cp -= 1;
- *cp = '%';
+ *--cp = '%'; /* Back off and insert the '%' */
return cp;
}
@@ -3777,10 +3792,35 @@ xo_format_humanize (xo_handle_t *xop, xo_buffer_t *xbp,
}
}
+/*
+ * Convenience function that either append a fixed value (if one is
+ * given) or formats a field using a format string. If it's
+ * encode_only, then we can't skip formatting the field, since it may
+ * be pulling arguments off the stack.
+ */
+static inline void
+xo_simple_field (xo_handle_t *xop, unsigned encode_only,
+ const char *value, ssize_t vlen,
+ const char *fmt, ssize_t flen, xo_xff_flags_t flags)
+{
+ if (encode_only)
+ flags |= XFF_NO_OUTPUT;
+
+ if (vlen == 0)
+ xo_do_format_field(xop, NULL, fmt, flen, flags);
+ else if (!encode_only)
+ xo_data_append_content(xop, value, vlen, flags);
+}
+
+/*
+ * Html mode: append a <div> to the output buffer contain a field
+ * along with all the supporting information indicated by the flags.
+ */
static void
xo_buf_append_div (xo_handle_t *xop, const char *class, xo_xff_flags_t flags,
const char *name, ssize_t nlen,
const char *value, ssize_t vlen,
+ const char *fmt, ssize_t flen,
const char *encoding, ssize_t elen)
{
static char div_start[] = "<div class=\"";
@@ -3791,10 +3831,10 @@ xo_buf_append_div (xo_handle_t *xop, const char *class, xo_xff_flags_t flags,
static char div_close[] = "</div>";
/* The encoding format defaults to the normal format */
- if (encoding == NULL) {
- char *enc = alloca(vlen + 1);
- memcpy(enc, value, vlen);
- enc[vlen] = '\0';
+ if (encoding == NULL && fmt != NULL) {
+ char *enc = alloca(flen + 1);
+ memcpy(enc, fmt, flen);
+ enc[flen] = '\0';
encoding = xo_fix_encoding(xop, enc);
elen = strlen(encoding);
}
@@ -3861,10 +3901,10 @@ xo_buf_append_div (xo_handle_t *xop, const char *class, xo_xff_flags_t flags,
/*
* Even if this is encode-only, we need to go through the
* work of formatting it to make sure the args are cleared
- * from xo_vap.
+ * from xo_vap. This is not true when vlen is zero, since
+ * that means our "value" isn't on the stack.
*/
- xo_do_format_field(xop, NULL, encoding, elen,
- flags | XFF_NO_OUTPUT);
+ xo_simple_field(xop, TRUE, NULL, 0, encoding, elen, flags);
return;
}
@@ -3972,7 +4012,7 @@ xo_buf_append_div (xo_handle_t *xop, const char *class, xo_xff_flags_t flags,
save.xhs_columns = xop->xo_columns;
save.xhs_anchor_columns = xop->xo_anchor_columns;
- xo_do_format_field(xop, NULL, value, vlen, flags);
+ xo_simple_field(xop, FALSE, value, vlen, fmt, flen, flags);
if (flags & XFF_HUMANIZE) {
/*
@@ -4023,14 +4063,14 @@ xo_format_text (xo_handle_t *xop, const char *str, ssize_t len)
break;
case XO_STYLE_HTML:
- xo_buf_append_div(xop, "text", 0, NULL, 0, str, len, NULL, 0);
+ xo_buf_append_div(xop, "text", 0, NULL, 0, str, len, NULL, 0, NULL, 0);
break;
}
}
static void
xo_format_title (xo_handle_t *xop, xo_field_info_t *xfip,
- const char *str, ssize_t len)
+ const char *value, ssize_t vlen)
{
const char *fmt = xfip->xfi_format;
ssize_t flen = xfip->xfi_flen;
@@ -4054,8 +4094,7 @@ xo_format_title (xo_handle_t *xop, xo_field_info_t *xfip,
* Even though we don't care about text, we need to do
* enough parsing work to skip over the right bits of xo_vap.
*/
- if (len == 0)
- xo_do_format_field(xop, NULL, fmt, flen, flags | XFF_NO_OUTPUT);
+ xo_simple_field(xop, TRUE, value, vlen, fmt, flen, flags);
return;
}
@@ -4074,17 +4113,17 @@ xo_format_title (xo_handle_t *xop, xo_field_info_t *xfip,
}
start = xbp->xb_curp - xbp->xb_bufp; /* Reset start */
- if (len) {
+ if (vlen) {
char *newfmt = alloca(flen + 1);
memcpy(newfmt, fmt, flen);
newfmt[flen] = '\0';
/* If len is non-zero, the format string apply to the name */
- char *newstr = alloca(len + 1);
- memcpy(newstr, str, len);
- newstr[len] = '\0';
+ char *newstr = alloca(vlen + 1);
+ memcpy(newstr, value, vlen);
+ newstr[vlen] = '\0';
- if (newstr[len - 1] == 's') {
+ if (newstr[vlen - 1] == 's') {
char *bp;
rc = snprintf(NULL, 0, newfmt, newstr);
@@ -4166,8 +4205,9 @@ xo_arg (xo_handle_t *xop)
static void
xo_format_value (xo_handle_t *xop, const char *name, ssize_t nlen,
- const char *format, ssize_t flen,
- const char *encoding, ssize_t elen, xo_xff_flags_t flags)
+ const char *value, ssize_t vlen,
+ const char *fmt, ssize_t flen,
+ const char *encoding, ssize_t elen, xo_xff_flags_t flags)
{
int pretty = XOF_ISSET(xop, XOF_PRETTY);
int quote;
@@ -4253,7 +4293,7 @@ xo_format_value (xo_handle_t *xop, const char *name, ssize_t nlen,
save.xhs_columns = xop->xo_columns;
save.xhs_anchor_columns = xop->xo_anchor_columns;
- xo_do_format_field(xop, NULL, format, flen, flags);
+ xo_simple_field(xop, FALSE, value, vlen, fmt, flen, flags);
if (flags & XFF_HUMANIZE)
xo_format_humanize(xop, xbp, &save, flags);
@@ -4263,8 +4303,8 @@ xo_format_value (xo_handle_t *xop, const char *name, ssize_t nlen,
if (flags & XFF_ENCODE_ONLY)
flags |= XFF_NO_OUTPUT;
- xo_buf_append_div(xop, "data", flags, name, nlen,
- format, flen, encoding, elen);
+ xo_buf_append_div(xop, "data", flags, name, nlen, value, vlen,
+ fmt, flen, encoding, elen);
break;
case XO_STYLE_XML:
@@ -4273,25 +4313,24 @@ xo_format_value (xo_handle_t *xop, const char *name, ssize_t nlen,
* let the formatting code handle the va_arg popping.
*/
if (flags & XFF_DISPLAY_ONLY) {
- flags |= XFF_NO_OUTPUT;
- xo_do_format_field(xop, NULL, format, flen, flags);
+ xo_simple_field(xop, TRUE, value, vlen, fmt, flen, flags);
break;
}
if (encoding) {
- format = encoding;
+ fmt = encoding;
flen = elen;
} else {
char *enc = alloca(flen + 1);
- memcpy(enc, format, flen);
+ memcpy(enc, fmt, flen);
enc[flen] = '\0';
- format = xo_fix_encoding(xop, enc);
- flen = strlen(format);
+ fmt = xo_fix_encoding(xop, enc);
+ flen = strlen(fmt);
}
if (nlen == 0) {
static char missing[] = "missing-field-name";
- xo_failure(xop, "missing field name: %s", format);
+ xo_failure(xop, "missing field name: %s", fmt);
name = missing;
nlen = sizeof(missing) - 1;
}
@@ -4327,7 +4366,9 @@ xo_format_value (xo_handle_t *xop, const char *name, ssize_t nlen,
}
xo_data_append(xop, ">", 1);
- xo_do_format_field(xop, NULL, format, flen, flags);
+
+ xo_simple_field(xop, FALSE, value, vlen, fmt, flen, flags);
+
xo_data_append(xop, "</", 2);
xo_data_escape(xop, name, nlen);
xo_data_append(xop, ">", 1);
@@ -4337,20 +4378,19 @@ xo_format_value (xo_handle_t *xop, const char *name, ssize_t nlen,
case XO_STYLE_JSON:
if (flags & XFF_DISPLAY_ONLY) {
- flags |= XFF_NO_OUTPUT;
- xo_do_format_field(xop, NULL, format, flen, flags);
+ xo_simple_field(xop, TRUE, value, vlen, fmt, flen, flags);
break;
}
if (encoding) {
- format = encoding;
+ fmt = encoding;
flen = elen;
} else {
char *enc = alloca(flen + 1);
- memcpy(enc, format, flen);
+ memcpy(enc, fmt, flen);
enc[flen] = '\0';
- format = xo_fix_encoding(xop, enc);
- flen = strlen(format);
+ fmt = xo_fix_encoding(xop, enc);
+ flen = strlen(fmt);
}
int first = (xop->xo_stack[xop->xo_depth].xs_flags & XSF_NOT_FIRST)
@@ -4362,18 +4402,20 @@ xo_format_value (xo_handle_t *xop, const char *name, ssize_t nlen,
quote = 1;
else if (flags & XFF_NOQUOTE)
quote = 0;
+ else if (vlen != 0)
+ quote = 1;
else if (flen == 0) {
quote = 0;
- format = "true"; /* JSON encodes empty tags as a boolean true */
+ fmt = "true"; /* JSON encodes empty tags as a boolean true */
flen = 4;
- } else if (strchr("diouDOUeEfFgG", format[flen - 1]) == NULL)
+ } else if (strchr("diouDOUeEfFgG", fmt[flen - 1]) == NULL)
quote = 1;
else
quote = 0;
if (nlen == 0) {
static char missing[] = "missing-field-name";
- xo_failure(xop, "missing field name: %s", format);
+ xo_failure(xop, "missing field name: %s", fmt);
name = missing;
nlen = sizeof(missing) - 1;
}
@@ -4407,7 +4449,7 @@ xo_format_value (xo_handle_t *xop, const char *name, ssize_t nlen,
if (quote)
xo_data_append(xop, "\"", 1);
- xo_do_format_field(xop, NULL, format, flen, flags);
+ xo_simple_field(xop, FALSE, value, vlen, fmt, flen, flags);
if (quote)
xo_data_append(xop, "\"", 1);
@@ -4415,39 +4457,39 @@ xo_format_value (xo_handle_t *xop, const char *name, ssize_t nlen,
case XO_STYLE_SDPARAMS:
if (flags & XFF_DISPLAY_ONLY) {
- flags |= XFF_NO_OUTPUT;
- xo_do_format_field(xop, NULL, format, flen, flags);
+ xo_simple_field(xop, TRUE, value, vlen, fmt, flen, flags);
break;
}
if (encoding) {
- format = encoding;
+ fmt = encoding;
flen = elen;
} else {
char *enc = alloca(flen + 1);
- memcpy(enc, format, flen);
+ memcpy(enc, fmt, flen);
enc[flen] = '\0';
- format = xo_fix_encoding(xop, enc);
- flen = strlen(format);
+ fmt = xo_fix_encoding(xop, enc);
+ flen = strlen(fmt);
}
if (nlen == 0) {
static char missing[] = "missing-field-name";
- xo_failure(xop, "missing field name: %s", format);
+ xo_failure(xop, "missing field name: %s", fmt);
name = missing;
nlen = sizeof(missing) - 1;
}
xo_data_escape(xop, name, nlen);
xo_data_append(xop, "=\"", 2);
- xo_do_format_field(xop, NULL, format, flen, flags);
+
+ xo_simple_field(xop, FALSE, value, vlen, fmt, flen, flags);
+
xo_data_append(xop, "\" ", 2);
break;
case XO_STYLE_ENCODER:
if (flags & XFF_DISPLAY_ONLY) {
- flags |= XFF_NO_OUTPUT;
- xo_do_format_field(xop, NULL, format, flen, flags);
+ xo_simple_field(xop, TRUE, value, vlen, fmt, flen, flags);
break;
}
@@ -4457,27 +4499,27 @@ xo_format_value (xo_handle_t *xop, const char *name, ssize_t nlen,
quote = 0;
else if (flen == 0) {
quote = 0;
- format = "true"; /* JSON encodes empty tags as a boolean true */
+ fmt = "true"; /* JSON encodes empty tags as a boolean true */
flen = 4;
- } else if (strchr("diouxXDOUeEfFgGaAcCp", format[flen - 1]) == NULL)
+ } else if (strchr("diouxXDOUeEfFgGaAcCp", fmt[flen - 1]) == NULL)
quote = 1;
else
quote = 0;
if (encoding) {
- format = encoding;
+ fmt = encoding;
flen = elen;
} else {
char *enc = alloca(flen + 1);
- memcpy(enc, format, flen);
+ memcpy(enc, fmt, flen);
enc[flen] = '\0';
- format = xo_fix_encoding(xop, enc);
- flen = strlen(format);
+ fmt = xo_fix_encoding(xop, enc);
+ flen = strlen(fmt);
}
if (nlen == 0) {
static char missing[] = "missing-field-name";
- xo_failure(xop, "missing field name: %s", format);
+ xo_failure(xop, "missing field name: %s", fmt);
name = missing;
nlen = sizeof(missing) - 1;
}
@@ -4487,7 +4529,9 @@ xo_format_value (xo_handle_t *xop, const char *name, ssize_t nlen,
xo_data_append(xop, "", 1);
ssize_t value_offset = xo_buf_offset(&xop->xo_data);
- xo_do_format_field(xop, NULL, format, flen, flags);
+
+ xo_simple_field(xop, FALSE, value, vlen, fmt, flen, flags);
+
xo_data_append(xop, "", 1);
xo_encoder_handle(xop, quote ? XO_OP_STRING : XO_OP_CONTENT,
@@ -4536,37 +4580,27 @@ xo_set_gettext_domain (xo_handle_t *xop, xo_field_info_t *xfip,
static void
xo_format_content (xo_handle_t *xop, const char *class_name,
const char *tag_name,
- const char *str, ssize_t len, const char *fmt, ssize_t flen,
+ const char *value, ssize_t vlen,
+ const char *fmt, ssize_t flen,
xo_xff_flags_t flags)
{
switch (xo_style(xop)) {
case XO_STYLE_TEXT:
- if (len)
- xo_data_append_content(xop, str, len, flags);
- else
- xo_do_format_field(xop, NULL, fmt, flen, flags);
+ xo_simple_field(xop, FALSE, value, vlen, fmt, flen, flags);
break;
case XO_STYLE_HTML:
- if (len == 0) {
- str = fmt;
- len = flen;
- }
-
- xo_buf_append_div(xop, class_name, flags, NULL, 0, str, len, NULL, 0);
+ xo_buf_append_div(xop, class_name, flags, NULL, 0,
+ value, vlen, fmt, flen, NULL, 0);
break;
case XO_STYLE_XML:
case XO_STYLE_JSON:
case XO_STYLE_SDPARAMS:
if (tag_name) {
- if (len == 0) {
- str = fmt;
- len = flen;
- }
-
xo_open_container_h(xop, tag_name);
- xo_format_value(xop, "message", 7, str, len, NULL, 0, flags);
+ xo_format_value(xop, "message", 7, value, vlen,
+ fmt, flen, NULL, 0, flags);
xo_close_container_h(xop, tag_name);
} else {
@@ -4574,16 +4608,12 @@ xo_format_content (xo_handle_t *xop, const char *class_name,
* Even though we don't care about labels, we need to do
* enough parsing work to skip over the right bits of xo_vap.
*/
- if (len == 0)
- xo_do_format_field(xop, NULL, fmt, flen,
- flags | XFF_NO_OUTPUT);
+ xo_simple_field(xop, TRUE, value, vlen, fmt, flen, flags);
}
break;
case XO_STYLE_ENCODER:
- if (len == 0)
- xo_do_format_field(xop, NULL, fmt, flen,
- flags | XFF_NO_OUTPUT);
+ xo_simple_field(xop, TRUE, value, vlen, fmt, flen, flags);
break;
}
}
@@ -4898,7 +4928,7 @@ xo_colors_handle_html (xo_handle_t *xop, xo_colors_t *newp)
static void
xo_format_colors (xo_handle_t *xop, xo_field_info_t *xfip,
- const char *str, ssize_t len)
+ const char *value, ssize_t vlen)
{
const char *fmt = xfip->xfi_format;
ssize_t flen = xfip->xfi_flen;
@@ -4906,13 +4936,13 @@ xo_format_colors (xo_handle_t *xop, xo_field_info_t *xfip,
xo_buffer_t xb;
/* If the string is static and we've in an encoding style, bail */
- if (len != 0 && xo_style_is_encoding(xop))
+ if (vlen != 0 && xo_style_is_encoding(xop))
return;
xo_buf_init(&xb);
- if (len)
- xo_buf_append(&xb, str, len);
+ if (vlen)
+ xo_buf_append(&xb, value, vlen);
else if (flen)
xo_do_format_field(xop, &xb, fmt, flen, 0);
else
@@ -4972,7 +5002,7 @@ xo_format_colors (xo_handle_t *xop, xo_field_info_t *xfip,
static void
xo_format_units (xo_handle_t *xop, xo_field_info_t *xfip,
- const char *str, ssize_t len)
+ const char *value, ssize_t vlen)
{
const char *fmt = xfip->xfi_format;
ssize_t flen = xfip->xfi_flen;
@@ -4982,7 +5012,7 @@ xo_format_units (xo_handle_t *xop, xo_field_info_t *xfip,
static char units_start_html[] = " data-units=\"";
if (!XOIF_ISSET(xop, XOIF_UNITS_PENDING)) {
- xo_format_content(xop, "units", NULL, str, len, fmt, flen, flags);
+ xo_format_content(xop, "units", NULL, value, vlen, fmt, flen, flags);
return;
}
@@ -4997,8 +5027,8 @@ xo_format_units (xo_handle_t *xop, xo_field_info_t *xfip,
else
return;
- if (len)
- xo_data_escape(xop, str, len);
+ if (vlen)
+ xo_data_escape(xop, value, vlen);
else
xo_do_format_field(xop, NULL, fmt, flen, flags);
@@ -5026,7 +5056,7 @@ xo_format_units (xo_handle_t *xop, xo_field_info_t *xfip,
static ssize_t
xo_find_width (xo_handle_t *xop, xo_field_info_t *xfip,
- const char *str, ssize_t len)
+ const char *value, ssize_t vlen)
{
const char *fmt = xfip->xfi_format;
ssize_t flen = xfip->xfi_flen;
@@ -5035,10 +5065,10 @@ xo_find_width (xo_handle_t *xop, xo_field_info_t *xfip,
char *bp;
char *cp;
- if (len) {
- bp = alloca(len + 1); /* Make local NUL-terminated copy of str */
- memcpy(bp, str, len);
- bp[len] = '\0';
+ if (vlen) {
+ bp = alloca(vlen + 1); /* Make local NUL-terminated copy of value */
+ memcpy(bp, value, vlen);
+ bp[vlen] = '\0';
width = strtol(bp, &cp, 0);
if (width == LONG_MIN || width == LONG_MAX
@@ -5075,7 +5105,7 @@ xo_anchor_clear (xo_handle_t *xop)
*/
static void
xo_anchor_start (xo_handle_t *xop, xo_field_info_t *xfip,
- const char *str, ssize_t len)
+ const char *value, ssize_t vlen)
{
if (xo_style(xop) != XO_STYLE_TEXT && xo_style(xop) != XO_STYLE_HTML)
return;
@@ -5092,12 +5122,12 @@ xo_anchor_start (xo_handle_t *xop, xo_field_info_t *xfip,
* Now we find the width, if possible. If it's not there,
* we'll get it on the end anchor.
*/
- xop->xo_anchor_min_width = xo_find_width(xop, xfip, str, len);
+ xop->xo_anchor_min_width = xo_find_width(xop, xfip, value, vlen);
}
static void
xo_anchor_stop (xo_handle_t *xop, xo_field_info_t *xfip,
- const char *str, ssize_t len)
+ const char *value, ssize_t vlen)
{
if (xo_style(xop) != XO_STYLE_TEXT && xo_style(xop) != XO_STYLE_HTML)
return;
@@ -5109,7 +5139,7 @@ xo_anchor_stop (xo_handle_t *xop, xo_field_info_t *xfip,
XOIF_CLEAR(xop, XOIF_UNITS_PENDING);
- ssize_t width = xo_find_width(xop, xfip, str, len);
+ ssize_t width = xo_find_width(xop, xfip, value, vlen);
if (width == 0)
width = xop->xo_anchor_min_width;
@@ -6213,12 +6243,12 @@ xo_do_emit_fields (xo_handle_t *xop, xo_field_info_t *fields,
if (flags & XFF_WS) {
xo_format_content(xop, "padding", NULL, " ", 1,
NULL, 0, flags);
- flags &= ~XFF_WS; /* Block later handling of this */
+ flags &= ~XFF_WS; /* Prevent later handling of this flag */
}
}
if (ftype == 'V')
- xo_format_value(xop, content, clen,
+ xo_format_value(xop, content, clen, NULL, 0,
xfip->xfi_format, xfip->xfi_flen,
xfip->xfi_encoding, xfip->xfi_elen, flags);
else if (ftype == '[')
@@ -7899,7 +7929,8 @@ xo_error_hv (xo_handle_t *xop, const char *fmt, va_list vap)
case XO_STYLE_HTML:
va_copy(xop->xo_vap, vap);
- xo_buf_append_div(xop, "error", 0, NULL, 0, fmt, strlen(fmt), NULL, 0);
+ xo_buf_append_div(xop, "error", 0, NULL, 0, NULL, 0,
+ fmt, strlen(fmt), NULL, 0);
if (XOIF_ISSET(xop, XOIF_DIV_OPEN))
xo_line_close(xop);
@@ -7915,7 +7946,8 @@ xo_error_hv (xo_handle_t *xop, const char *fmt, va_list vap)
va_copy(xop->xo_vap, vap);
xo_open_container_h(xop, "error");
- xo_format_value(xop, "message", 7, fmt, strlen(fmt), NULL, 0, 0);
+ xo_format_value(xop, "message", 7, NULL, 0,
+ fmt, strlen(fmt), NULL, 0, 0);
xo_close_container_h(xop, "error");
va_end(xop->xo_vap);
@@ -8132,7 +8164,7 @@ xo_emit_warn_hcv (xo_handle_t *xop, int as_warning, int code,
xo_buffer_t *src = &temp.xo_data;
xo_format_value(xop, "message", 7, src->xb_bufp,
- src->xb_curp - src->xb_bufp, NULL, 0, 0);
+ src->xb_curp - src->xb_bufp, NULL, 0, NULL, 0, 0);
xo_free(temp.xo_stack);
xo_buf_cleanup(src);
diff --git a/contrib/libxo/tests/core/saved/test_01.E.out b/contrib/libxo/tests/core/saved/test_01.E.out
index 407d3f4a5567..40d9ec67f5eb 100644
--- a/contrib/libxo/tests/core/saved/test_01.E.out
+++ b/contrib/libxo/tests/core/saved/test_01.E.out
@@ -1,5 +1,6 @@
op create: [] [] [0]
op open_container: [top] [] [0x810]
+op content: [used-percent] [12] [0]
op content: [kve_start] [0xdeadbeef] [0x8]
op content: [kve_end] [0xcabb1e] [0x8]
op string: [host] [my-box] [0x200000]
@@ -129,6 +130,9 @@ op string: [mode_octal] [octal] [0x8]
op string: [links] [links] [0x1000]
op string: [user] [user] [0x1000]
op string: [group] [group] [0x1000]
+op string: [pre] [that] [0x8]
+op content: [links] [3] [0x1000]
+op string: [post] [this] [0x1000]
op string: [mode] [/some/file] [0x1000]
op content: [mode_octal] [640] [0x8]
op content: [links] [1] [0x1000]
diff --git a/contrib/libxo/tests/core/saved/test_01.H.out b/contrib/libxo/tests/core/saved/test_01.H.out
index 7c0b3de061a6..7622c97a31ff 100644
--- a/contrib/libxo/tests/core/saved/test_01.H.out
+++ b/contrib/libxo/tests/core/saved/test_01.H.out
@@ -1,2 +1,2 @@
-<div class="line"><div class="text">testing argument modifier </div><div class="data" data-tag="host">my-box</div><div class="text">.</div><div class="data" data-tag="domain">example.com</div><div class="text">...</div></div><div class="line"><div class="text">testing argument modifier with encoding to </div><div class="text">.</div><div class="data" data-tag="domain">example.com</div><div class="text">...</div></div><div class="line"><div class="label">Label text</div><div class="text"> </div><div class="data" data-tag="label">value</div></div><div class="line"><div class="data" data-tag="max-chaos"> very </div><div class="data" data-tag="min-chaos">42</div><div class="data" data-tag="some-chaos">42
-</div><div class="text">Connecting to </div><div class="data" data-tag="host">my-box</div><div class="text">.</div><div class="data" data-tag="domain">example.com</div><div class="text">...</div></div><div class="line"><div class="title">Item </div><div class="title"> Total Sold</div><div class="title"> In Stock</div><div class="title"> On Order</div><div class="title"> SKU</div></div><div class="line"><div class="data" data-tag="name" data-key="key">gum </div><div class="data" data-tag="sold"> 1412</div><div class="data" data-tag="in-stock"> 54</div><div class="data" data-tag="on-order"> 10</div><div class="data" data-tag="sku" data-key="key"> GRO-000-415</div></div><div class="line"><div class="data" data-tag="name" data-key="key">rope </div><div class="data" data-tag="sold"> 85</div><div class="data" data-tag="in-stock"> 4</div><div class="data" data-tag="on-order"> 2</div><div class="data" data-tag="sku" data-key="key"> HRD-000-212</div></div><div class="line"><div class="data" data-tag="name" data-key="key">ladder </div><div class="data" data-tag="sold"> 0</div><div class="data" data-tag="in-stock"> 2</div><div class="data" data-tag="on-order"> 1</div><div class="data" data-tag="sku" data-key="key"> HRD-000-517</div></div><div class="line"><div class="data" data-tag="name" data-key="key">bolt </div><div class="data" data-tag="sold"> 4123</div><div class="data" data-tag="in-stock"> 144</div><div class="data" data-tag="on-order"> 42</div><div class="data" data-tag="sku" data-key="key"> HRD-000-632</div></div><div class="line"><div class="data" data-tag="name" data-key="key">water </div><div class="data" data-tag="sold"> 17</div><div class="data" data-tag="in-stock"> 14</div><div class="data" data-tag="on-order"> 2</div><div class="data" data-tag="sku" data-key="key"> GRO-000-2331</div></div><div class="line"></div><div class="line"></div><div class="line"><div class="label">Item</div><div class="text"> '</div><div class="data" data-tag="name" data-key="key">gum</div><div class="text">':</div></div><div class="line"><div class="padding"> </div><div class="label">Total sold</div><div class="text">: </div><div class="data" data-tag="sold">1412.0</div></div><div class="line"><div class="padding"> </div><div class="label">In stock</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="in-stock">54</div></div><div class="line"><div class="padding"> </div><div class="label">On order</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="on-order">10</div></div><div class="line"><div class="padding"> </div><div class="label">SKU</div><div class="text">: </div><div class="data" data-tag="sku" data-key="key">GRO-000-415</div></div><div class="line"><div class="label">Item</div><div class="text"> '</div><div class="data" data-tag="name" data-key="key">rope</div><div class="text">':</div></div><div class="line"><div class="padding"> </div><div class="label">Total sold</div><div class="text">: </div><div class="data" data-tag="sold">85.0</div></div><div class="line"><div class="padding"> </div><div class="label">In stock</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="in-stock">4</div></div><div class="line"><div class="padding"> </div><div class="label">On order</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="on-order">2</div></div><div class="line"><div class="padding"> </div><div class="label">SKU</div><div class="text">: </div><div class="data" data-tag="sku" data-key="key">HRD-000-212</div></div><div class="line"><div class="label">Item</div><div class="text"> '</div><div class="data" data-tag="name" data-key="key">ladder</div><div class="text">':</div></div><div class="line"><div class="padding"> </div><div class="label">Total sold</div><div class="text">: </div><div class="data" data-tag="sold">0</div></div><div class="line"><div class="padding"> </div><div class="label">In stock</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="in-stock">2</div></div><div class="line"><div class="padding"> </div><div class="label">On order</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="on-order">1</div></div><div class="line"><div class="padding"> </div><div class="label">SKU</div><div class="text">: </div><div class="data" data-tag="sku" data-key="key">HRD-000-517</div></div><div class="line"><div class="label">Item</div><div class="text"> '</div><div class="data" data-tag="name" data-key="key">bolt</div><div class="text">':</div></div><div class="line"><div class="padding"> </div><div class="label">Total sold</div><div class="text">: </div><div class="data" data-tag="sold">4123.0</div></div><div class="line"><div class="padding"> </div><div class="label">In stock</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="in-stock">144</div></div><div class="line"><div class="padding"> </div><div class="label">On order</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="on-order">42</div></div><div class="line"><div class="padding"> </div><div class="label">SKU</div><div class="text">: </div><div class="data" data-tag="sku" data-key="key">HRD-000-632</div></div><div class="line"><div class="label">Item</div><div class="text"> '</div><div class="data" data-tag="name" data-key="key">water</div><div class="text">':</div></div><div class="line"><div class="padding"> </div><div class="label">Total sold</div><div class="text">: </div><div class="data" data-tag="sold">17.0</div></div><div class="line"><div class="padding"> </div><div class="label">In stock</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="in-stock">14</div></div><div class="line"><div class="padding"> </div><div class="label">On order</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="on-order">2</div></div><div class="line"><div class="padding"> </div><div class="label">SKU</div><div class="text">: </div><div class="data" data-tag="sku" data-key="key">GRO-000-2331</div></div><div class="line"><div class="label">Item</div><div class="text"> '</div><div class="data" data-tag="name" data-key="key">fish</div><div class="text">':</div></div><div class="line"><div class="padding"> </div><div class="label">Total sold</div><div class="text">: </div><div class="data" data-tag="sold">1321.0</div></div><div class="line"><div class="padding"> </div><div class="label">In stock</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="in-stock">45</div></div><div class="line"><div class="padding"> </div><div class="label">On order</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="on-order">1</div></div><div class="line"><div class="padding"> </div><div class="label">SKU</div><div class="text">: </div><div class="data" data-tag="sku" data-key="key">GRO-000-533</div></div><div class="line"><div class="label">Item</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="item">gum</div></div><div class="line"><div class="label">Item</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="item">rope</div></div><div class="line"><div class="label">Item</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="item">ladder</div></div><div class="line"><div class="label">Item</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="item">bolt</div></div><div class="line"><div class="label">Item</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="item">water</div></div><div class="line"><div class="text">X</div><div class="text">X</div><div class="text">X</div><div class="text">X</div><div class="text">X</div><div class="text">X</div><div class="text">X</div><div class="text">X</div></div><div class="line"><div class="text">X</div><div class="padding"> </div><div class="text">X</div><div class="label">Cost</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="cost">425</div></div><div class="line"><div class="text">X</div><div class="padding"> </div><div class="text">X</div><div class="label">Cost</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="cost">455</div></div><div class="line"><div class="text"> </div><div class="data" data-tag="links">links</div><div class="text"> </div><div class="data" data-tag="user">user</div><div class="text"> </div><div class="data" data-tag="group">group</div><div class="text"> </div></div><div class="line"><div class="data" data-tag="mode">/some/file</div><div class="text"> </div><div class="data" data-tag="links"> 1</div><div class="text"> </div><div class="data" data-tag="user">user </div><div class="text"> </div><div class="data" data-tag="group">group </div><div class="text"> </div></div> \ No newline at end of file
+<div class="line"><div class="text">df </div><div class="data" data-tag="used-percent"> 12</div><div class="units">%</div></div><div class="line"><div class="text">testing argument modifier </div><div class="data" data-tag="host">my-box</div><div class="text">.</div><div class="data" data-tag="domain">example.com</div><div class="text">...</div></div><div class="line"><div class="text">testing argument modifier with encoding to </div><div class="text">.</div><div class="data" data-tag="domain">example.com</div><div class="text">...</div></div><div class="line"><div class="label">Label text</div><div class="text"> </div><div class="data" data-tag="label">value</div></div><div class="line"><div class="data" data-tag="max-chaos"> very </div><div class="data" data-tag="min-chaos">42</div><div class="data" data-tag="some-chaos">42
+</div><div class="text">Connecting to </div><div class="data" data-tag="host">my-box</div><div class="text">.</div><div class="data" data-tag="domain">example.com</div><div class="text">...</div></div><div class="line"><div class="title">Item </div><div class="title"> Total Sold</div><div class="title"> In Stock</div><div class="title"> On Order</div><div class="title"> SKU</div></div><div class="line"><div class="data" data-tag="name" data-key="key">gum </div><div class="data" data-tag="sold"> 1412</div><div class="data" data-tag="in-stock"> 54</div><div class="data" data-tag="on-order"> 10</div><div class="data" data-tag="sku" data-key="key"> GRO-000-415</div></div><div class="line"><div class="data" data-tag="name" data-key="key">rope </div><div class="data" data-tag="sold"> 85</div><div class="data" data-tag="in-stock"> 4</div><div class="data" data-tag="on-order"> 2</div><div class="data" data-tag="sku" data-key="key"> HRD-000-212</div></div><div class="line"><div class="data" data-tag="name" data-key="key">ladder </div><div class="data" data-tag="sold"> 0</div><div class="data" data-tag="in-stock"> 2</div><div class="data" data-tag="on-order"> 1</div><div class="data" data-tag="sku" data-key="key"> HRD-000-517</div></div><div class="line"><div class="data" data-tag="name" data-key="key">bolt </div><div class="data" data-tag="sold"> 4123</div><div class="data" data-tag="in-stock"> 144</div><div class="data" data-tag="on-order"> 42</div><div class="data" data-tag="sku" data-key="key"> HRD-000-632</div></div><div class="line"><div class="data" data-tag="name" data-key="key">water </div><div class="data" data-tag="sold"> 17</div><div class="data" data-tag="in-stock"> 14</div><div class="data" data-tag="on-order"> 2</div><div class="data" data-tag="sku" data-key="key"> GRO-000-2331</div></div><div class="line"></div><div class="line"></div><div class="line"><div class="label">Item</div><div class="text"> '</div><div class="data" data-tag="name" data-key="key">gum</div><div class="text">':</div></div><div class="line"><div class="padding"> </div><div class="label">Total sold</div><div class="text">: </div><div class="data" data-tag="sold">1412.0</div></div><div class="line"><div class="padding"> </div><div class="label">In stock</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="in-stock">54</div></div><div class="line"><div class="padding"> </div><div class="label">On order</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="on-order">10</div></div><div class="line"><div class="padding"> </div><div class="label">SKU</div><div class="text">: </div><div class="data" data-tag="sku" data-key="key">GRO-000-415</div></div><div class="line"><div class="label">Item</div><div class="text"> '</div><div class="data" data-tag="name" data-key="key">rope</div><div class="text">':</div></div><div class="line"><div class="padding"> </div><div class="label">Total sold</div><div class="text">: </div><div class="data" data-tag="sold">85.0</div></div><div class="line"><div class="padding"> </div><div class="label">In stock</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="in-stock">4</div></div><div class="line"><div class="padding"> </div><div class="label">On order</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="on-order">2</div></div><div class="line"><div class="padding"> </div><div class="label">SKU</div><div class="text">: </div><div class="data" data-tag="sku" data-key="key">HRD-000-212</div></div><div class="line"><div class="label">Item</div><div class="text"> '</div><div class="data" data-tag="name" data-key="key">ladder</div><div class="text">':</div></div><div class="line"><div class="padding"> </div><div class="label">Total sold</div><div class="text">: </div><div class="data" data-tag="sold">0</div></div><div class="line"><div class="padding"> </div><div class="label">In stock</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="in-stock">2</div></div><div class="line"><div class="padding"> </div><div class="label">On order</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="on-order">1</div></div><div class="line"><div class="padding"> </div><div class="label">SKU</div><div class="text">: </div><div class="data" data-tag="sku" data-key="key">HRD-000-517</div></div><div class="line"><div class="label">Item</div><div class="text"> '</div><div class="data" data-tag="name" data-key="key">bolt</div><div class="text">':</div></div><div class="line"><div class="padding"> </div><div class="label">Total sold</div><div class="text">: </div><div class="data" data-tag="sold">4123.0</div></div><div class="line"><div class="padding"> </div><div class="label">In stock</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="in-stock">144</div></div><div class="line"><div class="padding"> </div><div class="label">On order</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="on-order">42</div></div><div class="line"><div class="padding"> </div><div class="label">SKU</div><div class="text">: </div><div class="data" data-tag="sku" data-key="key">HRD-000-632</div></div><div class="line"><div class="label">Item</div><div class="text"> '</div><div class="data" data-tag="name" data-key="key">water</div><div class="text">':</div></div><div class="line"><div class="padding"> </div><div class="label">Total sold</div><div class="text">: </div><div class="data" data-tag="sold">17.0</div></div><div class="line"><div class="padding"> </div><div class="label">In stock</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="in-stock">14</div></div><div class="line"><div class="padding"> </div><div class="label">On order</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="on-order">2</div></div><div class="line"><div class="padding"> </div><div class="label">SKU</div><div class="text">: </div><div class="data" data-tag="sku" data-key="key">GRO-000-2331</div></div><div class="line"><div class="label">Item</div><div class="text"> '</div><div class="data" data-tag="name" data-key="key">fish</div><div class="text">':</div></div><div class="line"><div class="padding"> </div><div class="label">Total sold</div><div class="text">: </div><div class="data" data-tag="sold">1321.0</div></div><div class="line"><div class="padding"> </div><div class="label">In stock</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="in-stock">45</div></div><div class="line"><div class="padding"> </div><div class="label">On order</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="on-order">1</div></div><div class="line"><div class="padding"> </div><div class="label">SKU</div><div class="text">: </div><div class="data" data-tag="sku" data-key="key">GRO-000-533</div></div><div class="line"><div class="label">Item</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="item">gum</div></div><div class="line"><div class="label">Item</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="item">rope</div></div><div class="line"><div class="label">Item</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="item">ladder</div></div><div class="line"><div class="label">Item</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="item">bolt</div></div><div class="line"><div class="label">Item</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="item">water</div></div><div class="line"><div class="text">X</div><div class="text">X</div><div class="text">X</div><div class="text">X</div><div class="text">X</div><div class="text">X</div><div class="text">X</div><div class="text">X</div></div><div class="line"><div class="text">X</div><div class="padding"> </div><div class="text">X</div><div class="label">Cost</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="cost">425</div></div><div class="line"><div class="text">X</div><div class="padding"> </div><div class="text">X</div><div class="label">Cost</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="cost">455</div></div><div class="line"><div class="text"> </div><div class="data" data-tag="links">links</div><div class="text"> </div><div class="data" data-tag="user">user</div><div class="text"> </div><div class="data" data-tag="group">group</div><div class="text"> </div></div><div class="line"><div class="data" data-tag="links">3 </div><div class="data" data-tag="post">this </div></div><div class="line"><div class="data" data-tag="mode">/some/file</div><div class="text"> </div><div class="data" data-tag="links"> 1</div><div class="text"> </div><div class="data" data-tag="user">user </div><div class="text"> </div><div class="data" data-tag="group">group </div><div class="text"> </div></div> \ No newline at end of file
diff --git a/contrib/libxo/tests/core/saved/test_01.HIPx.out b/contrib/libxo/tests/core/saved/test_01.HIPx.out
index f6c7290366fb..94c387ea8d08 100644
--- a/contrib/libxo/tests/core/saved/test_01.HIPx.out
+++ b/contrib/libxo/tests/core/saved/test_01.HIPx.out
@@ -1,4 +1,9 @@
<div class="line">
+ <div class="text">df </div>
+ <div class="data" data-tag="used-percent" data-xpath="/top/used-percent"> 12</div>
+ <div class="units">%</div>
+</div>
+<div class="line">
<div class="text">testing argument modifier </div>
<div class="data" data-tag="host" data-xpath="/top/host">my-box</div>
<div class="text">.</div>
@@ -333,6 +338,10 @@
<div class="text"> </div>
</div>
<div class="line">
+ <div class="data" data-tag="links" data-xpath="/top/links">3 </div>
+ <div class="data" data-tag="post" data-xpath="/top/post">this </div>
+</div>
+<div class="line">
<div class="data" data-tag="mode" data-xpath="/top/mode">/some/file</div>
<div class="text"> </div>
<div class="data" data-tag="links" data-xpath="/top/links"> 1</div>
diff --git a/contrib/libxo/tests/core/saved/test_01.HP.out b/contrib/libxo/tests/core/saved/test_01.HP.out
index 0fdcbd18005b..044bd4430496 100644
--- a/contrib/libxo/tests/core/saved/test_01.HP.out
+++ b/contrib/libxo/tests/core/saved/test_01.HP.out
@@ -1,4 +1,9 @@
<div class="line">
+ <div class="text">df </div>
+ <div class="data" data-tag="used-percent"> 12</div>
+ <div class="units">%</div>
+</div>
+<div class="line">
<div class="text">testing argument modifier </div>
<div class="data" data-tag="host">my-box</div>
<div class="text">.</div>
@@ -333,6 +338,10 @@
<div class="text"> </div>
</div>
<div class="line">
+ <div class="data" data-tag="links">3 </div>
+ <div class="data" data-tag="post">this </div>
+</div>
+<div class="line">
<div class="data" data-tag="mode">/some/file</div>
<div class="text"> </div>
<div class="data" data-tag="links"> 1</div>
diff --git a/contrib/libxo/tests/core/saved/test_01.J.out b/contrib/libxo/tests/core/saved/test_01.J.out
index 1577ce0c0410..897a7d28958e 100644
--- a/contrib/libxo/tests/core/saved/test_01.J.out
+++ b/contrib/libxo/tests/core/saved/test_01.J.out
@@ -1,2 +1,2 @@
-{"top": {"kve_start":"0xdeadbeef","kve_end":"0xcabb1e","host":"my-box","domain":"example.com","host":"my-box","domain":"example.com","label":"value","max-chaos":"very","min-chaos":42,"some-chaos":"[42]","host":"my-box","domain":"example.com", "data": {"item": [{"sku":"GRO-000-415","name":"gum","sold":1412,"in-stock":54,"on-order":10}, {"sku":"HRD-000-212","name":"rope","sold":85,"in-stock":4,"on-order":2}, {"sku":"HRD-000-517","name":"ladder","sold":0,"in-stock":2,"on-order":1}, {"sku":"HRD-000-632","name":"bolt","sold":4123,"in-stock":144,"on-order":42}, {"sku":"GRO-000-2331","name":"water","sold":17,"in-stock":14,"on-order":2}]}, "data2": {"item": [{"sku":"GRO-000-415","name":"gum","sold":1412.0,"in-stock":54,"on-order":10}, {"sku":"HRD-000-212","name":"rope","sold":85.0,"in-stock":4,"on-order":2}, {"sku":"HRD-000-517","name":"ladder","sold":0,"in-stock":2,"on-order":1}, {"sku":"HRD-000-632","name":"bolt","sold":4123.0,"in-stock":144,"on-order":42}, {"sku":"GRO-000-2331","name":"water","sold":17.0,"in-stock":14,"on-order":2}]}, "data3": {"item": [{"sku":"GRO-000-533","name":"fish","sold":1321.0,"in-stock":45,"on-order":1}]}, "data4": {"item": ["gum","rope","ladder","bolt","water"]},"cost":425,"cost":455,"mode":"mode","mode_octal":"octal","links":"links","user":"user","group":"group","mode":"/some/file","mode_octal":640,"links":1,"user":"user","group":"group"}
+{"top": {"used-percent":12,"kve_start":"0xdeadbeef","kve_end":"0xcabb1e","host":"my-box","domain":"example.com","host":"my-box","domain":"example.com","label":"value","max-chaos":"very","min-chaos":42,"some-chaos":"[42]","host":"my-box","domain":"example.com", "data": {"item": [{"sku":"GRO-000-415","name":"gum","sold":1412,"in-stock":54,"on-order":10}, {"sku":"HRD-000-212","name":"rope","sold":85,"in-stock":4,"on-order":2}, {"sku":"HRD-000-517","name":"ladder","sold":0,"in-stock":2,"on-order":1}, {"sku":"HRD-000-632","name":"bolt","sold":4123,"in-stock":144,"on-order":42}, {"sku":"GRO-000-2331","name":"water","sold":17,"in-stock":14,"on-order":2}]}, "data2": {"item": [{"sku":"GRO-000-415","name":"gum","sold":1412.0,"in-stock":54,"on-order":10}, {"sku":"HRD-000-212","name":"rope","sold":85.0,"in-stock":4,"on-order":2}, {"sku":"HRD-000-517","name":"ladder","sold":0,"in-stock":2,"on-order":1}, {"sku":"HRD-000-632","name":"bolt","sold":4123.0,"in-stock":144,"on-order":42}, {"sku":"GRO-000-2331","name":"water","sold":17.0,"in-stock":14,"on-order":2}]}, "data3": {"item": [{"sku":"GRO-000-533","name":"fish","sold":1321.0,"in-stock":45,"on-order":1}]}, "data4": {"item": ["gum","rope","ladder","bolt","water"]},"cost":425,"cost":455,"mode":"mode","mode_octal":"octal","links":"links","user":"user","group":"group","pre":"that","links":3,"post":"this","mode":"/some/file","mode_octal":640,"links":1,"user":"user","group":"group"}
}
diff --git a/contrib/libxo/tests/core/saved/test_01.JP.out b/contrib/libxo/tests/core/saved/test_01.JP.out
index d24abbc0254f..885f30e59f99 100644
--- a/contrib/libxo/tests/core/saved/test_01.JP.out
+++ b/contrib/libxo/tests/core/saved/test_01.JP.out
@@ -1,5 +1,6 @@
{
"top": {
+ "used-percent": 12,
"kve_start": "0xdeadbeef",
"kve_end": "0xcabb1e",
"host": "my-box",
@@ -117,6 +118,9 @@
"links": "links",
"user": "user",
"group": "group",
+ "pre": "that",
+ "links": 3,
+ "post": "this",
"mode": "/some/file",
"mode_octal": 640,
"links": 1,
diff --git a/contrib/libxo/tests/core/saved/test_01.T.out b/contrib/libxo/tests/core/saved/test_01.T.out
index 71cd130ab350..5a4673f7d8bc 100644
--- a/contrib/libxo/tests/core/saved/test_01.T.out
+++ b/contrib/libxo/tests/core/saved/test_01.T.out
@@ -1,3 +1,4 @@
+df 12%
testing argument modifier my-box.example.com...
testing argument modifier with encoding to .example.com...
Label text value
@@ -50,4 +51,5 @@ XXXXXXXX
X XCost: 425
X XCost: 455
links user group
+3 this
/some/file 1 user group
diff --git a/contrib/libxo/tests/core/saved/test_01.X.out b/contrib/libxo/tests/core/saved/test_01.X.out
index a243ce7c79f1..6c5afaca81ae 100644
--- a/contrib/libxo/tests/core/saved/test_01.X.out
+++ b/contrib/libxo/tests/core/saved/test_01.X.out
@@ -1 +1 @@
-<top><kve_start>0xdeadbeef</kve_start><kve_end>0xcabb1e</kve_end><host>my-box</host><domain>example.com</domain><host>my-box</host><domain>example.com</domain><label>value</label><max-chaos>very</max-chaos><min-chaos>42</min-chaos><some-chaos>[42]</some-chaos><host>my-box</host><domain>example.com</domain><data test="value"><item test2="value2"><sku test3="value3" key="key">GRO-000-415</sku><name key="key">gum</name><sold>1412</sold><in-stock>54</in-stock><on-order>10</on-order></item><item><sku test3="value3" key="key">HRD-000-212</sku><name key="key">rope</name><sold>85</sold><in-stock>4</in-stock><on-order>2</on-order></item><item><sku test3="value3" key="key">HRD-000-517</sku><name key="key">ladder</name><sold>0</sold><in-stock>2</in-stock><on-order>1</on-order></item><item><sku test3="value3" key="key">HRD-000-632</sku><name key="key">bolt</name><sold>4123</sold><in-stock>144</in-stock><on-order>42</on-order></item><item><sku test3="value3" key="key">GRO-000-2331</sku><name key="key">water</name><sold>17</sold><in-stock>14</in-stock><on-order>2</on-order></item></data><data2><item><sku key="key">GRO-000-415</sku><name key="key">gum</name><sold>1412.0</sold><in-stock>54</in-stock><on-order>10</on-order></item><item><sku key="key">HRD-000-212</sku><name key="key">rope</name><sold>85.0</sold><in-stock>4</in-stock><on-order>2</on-order></item><item><sku key="key">HRD-000-517</sku><name key="key">ladder</name><sold>0</sold><in-stock>2</in-stock><on-order>1</on-order></item><item><sku key="key">HRD-000-632</sku><name key="key">bolt</name><sold>4123.0</sold><in-stock>144</in-stock><on-order>42</on-order></item><item><sku key="key">GRO-000-2331</sku><name key="key">water</name><sold>17.0</sold><in-stock>14</in-stock><on-order>2</on-order></item></data2><data3><item><sku key="key">GRO-000-533</sku><name key="key">fish</name><sold>1321.0</sold><in-stock>45</in-stock><on-order>1</on-order></item></data3><data4><item test4="value4">gum</item><item test4="value4">rope</item><item test4="value4">ladder</item><item test4="value4">bolt</item><item test4="value4">water</item></data4><cost>425</cost><cost>455</cost><mode>mode</mode><mode_octal>octal</mode_octal><links>links</links><user>user</user><group>group</group><mode>/some/file</mode><mode_octal>640</mode_octal><links>1</links><user>user</user><group>group</group></top> \ No newline at end of file
+<top><used-percent>12</used-percent><kve_start>0xdeadbeef</kve_start><kve_end>0xcabb1e</kve_end><host>my-box</host><domain>example.com</domain><host>my-box</host><domain>example.com</domain><label>value</label><max-chaos>very</max-chaos><min-chaos>42</min-chaos><some-chaos>[42]</some-chaos><host>my-box</host><domain>example.com</domain><data test="value"><item test2="value2"><sku test3="value3" key="key">GRO-000-415</sku><name key="key">gum</name><sold>1412</sold><in-stock>54</in-stock><on-order>10</on-order></item><item><sku test3="value3" key="key">HRD-000-212</sku><name key="key">rope</name><sold>85</sold><in-stock>4</in-stock><on-order>2</on-order></item><item><sku test3="value3" key="key">HRD-000-517</sku><name key="key">ladder</name><sold>0</sold><in-stock>2</in-stock><on-order>1</on-order></item><item><sku test3="value3" key="key">HRD-000-632</sku><name key="key">bolt</name><sold>4123</sold><in-stock>144</in-stock><on-order>42</on-order></item><item><sku test3="value3" key="key">GRO-000-2331</sku><name key="key">water</name><sold>17</sold><in-stock>14</in-stock><on-order>2</on-order></item></data><data2><item><sku key="key">GRO-000-415</sku><name key="key">gum</name><sold>1412.0</sold><in-stock>54</in-stock><on-order>10</on-order></item><item><sku key="key">HRD-000-212</sku><name key="key">rope</name><sold>85.0</sold><in-stock>4</in-stock><on-order>2</on-order></item><item><sku key="key">HRD-000-517</sku><name key="key">ladder</name><sold>0</sold><in-stock>2</in-stock><on-order>1</on-order></item><item><sku key="key">HRD-000-632</sku><name key="key">bolt</name><sold>4123.0</sold><in-stock>144</in-stock><on-order>42</on-order></item><item><sku key="key">GRO-000-2331</sku><name key="key">water</name><sold>17.0</sold><in-stock>14</in-stock><on-order>2</on-order></item></data2><data3><item><sku key="key">GRO-000-533</sku><name key="key">fish</name><sold>1321.0</sold><in-stock>45</in-stock><on-order>1</on-order></item></data3><data4><item test4="value4">gum</item><item test4="value4">rope</item><item test4="value4">ladder</item><item test4="value4">bolt</item><item test4="value4">water</item></data4><cost>425</cost><cost>455</cost><mode>mode</mode><mode_octal>octal</mode_octal><links>links</links><user>user</user><group>group</group><pre>that</pre><links>3</links><post>this</post><mode>/some/file</mode><mode_octal>640</mode_octal><links>1</links><user>user</user><group>group</group></top> \ No newline at end of file
diff --git a/contrib/libxo/tests/core/saved/test_01.XP.out b/contrib/libxo/tests/core/saved/test_01.XP.out
index 98dc13b68f29..2aa52ace6e65 100644
--- a/contrib/libxo/tests/core/saved/test_01.XP.out
+++ b/contrib/libxo/tests/core/saved/test_01.XP.out
@@ -1,4 +1,5 @@
<top>
+ <used-percent>12</used-percent>
<kve_start>0xdeadbeef</kve_start>
<kve_end>0xcabb1e</kve_end>
<host>my-box</host>
@@ -108,6 +109,9 @@
<links>links</links>
<user>user</user>
<group>group</group>
+ <pre>that</pre>
+ <links>3</links>
+ <post>this</post>
<mode>/some/file</mode>
<mode_octal>640</mode_octal>
<links>1</links>
diff --git a/contrib/libxo/tests/core/saved/test_02.J.out b/contrib/libxo/tests/core/saved/test_02.J.out
index 5578389aa479..2cb2abcb8726 100644
--- a/contrib/libxo/tests/core/saved/test_02.J.out
+++ b/contrib/libxo/tests/core/saved/test_02.J.out
@@ -1,2 +1,2 @@
-{"top": {"data": {"what":"braces","length":"abcdef","fd":-1,"error":"Bad file descriptor","test":"good","fd":-1,"error":"Bad fi","test":"good","lines":20,"words":30,"characters":40, "bytes": [0,1,2,3,4],"mbuf-current":10,"mbuf-cache":20,"mbuf-total":30,"distance":50,"location":"Boston","memory":64,"total":640,"memory":64,"total":640,"ten":10,"eleven":11,"unknown":1010,"unknown":1010,"min":15,"cur":20,"max":30,"min":15,"cur":20,"max":125,"min":15,"cur":20,"max":125,"min":15,"cur":20,"max":125,"val1":21,"val2":58368,"val3":100663296,"val4":44470272,"val5":1342172800, "flag": ["one","two","three"],"works":null,"empty-tag":true,"t1":"1000","t2":"test5000","t3":"ten-longx","t4":"xtest", "__error": {"message":"this is an error"}, "__error": {"message":"two more errors"}, "__warning": {"message":this is an warning}, "__warning": {"message":"two more warnings"},"count":10,"test":4, "error": {"message":"Shut 'er down, Clancey! She's a-pumpin' mud! <>!,\"!<>\n"}}}
+{"top": {"data": {"what":"braces","length":"abcdef","fd":-1,"error":"Bad file descriptor","test":"good","fd":-1,"error":"Bad fi","test":"good","lines":20,"words":30,"characters":40, "bytes": [0,1,2,3,4],"mbuf-current":10,"mbuf-cache":20,"mbuf-total":30,"distance":50,"location":"Boston","memory":64,"total":640,"memory":64,"total":640,"ten":10,"eleven":11,"unknown":1010,"unknown":1010,"min":15,"cur":20,"max":30,"min":15,"cur":20,"max":125,"min":15,"cur":20,"max":125,"min":15,"cur":20,"max":125,"val1":21,"val2":58368,"val3":100663296,"val4":44470272,"val5":1342172800, "flag": ["one","two","three"],"works":null,"empty-tag":true,"t1":"1000","t2":"test5000","t3":"ten-longx","t4":"xtest", "__error": {"message":"this is an error"}, "__error": {"message":"two more errors"}, "__warning": {"message":"this is an warning"}, "__warning": {"message":"two more warnings"},"count":10,"test":4, "error": {"message":"Shut 'er down, Clancey! She's a-pumpin' mud! <>!,\"!<>\n"}}}
}
diff --git a/contrib/libxo/tests/core/saved/test_02.JP.out b/contrib/libxo/tests/core/saved/test_02.JP.out
index fd910aa6e808..930d8876fba3 100644
--- a/contrib/libxo/tests/core/saved/test_02.JP.out
+++ b/contrib/libxo/tests/core/saved/test_02.JP.out
@@ -67,7 +67,7 @@
"message": "two more errors"
},
"__warning": {
- "message": this is an warning
+ "message": "this is an warning"
},
"__warning": {
"message": "two more warnings"
diff --git a/contrib/libxo/tests/core/test_01.c b/contrib/libxo/tests/core/test_01.c
index a3a6a4be3e29..26c272492ecb 100644
--- a/contrib/libxo/tests/core/test_01.c
+++ b/contrib/libxo/tests/core/test_01.c
@@ -80,6 +80,8 @@ main (int argc, char **argv)
xo_open_container_h(NULL, "top");
+ xo_emit("df {:used-percent/%5.0f}{U:%%}\n", (double) 12);
+
xo_emit("{e:kve_start/%#jx}", (uintmax_t) 0xdeadbeef);
xo_emit("{e:kve_end/%#jx}", (uintmax_t) 0xcabb1e);
@@ -190,6 +192,8 @@ main (int argc, char **argv)
"mode", "octal", "links",
"user", "group", "extra1", "extra2", "extra3");
+ xo_emit("{e:pre/%s}{t:links/%-*u}{t:post/%-*s}\n", "that", 8, 3, 8, "this");
+
xo_emit("{t:mode/%s}{e:mode_octal/%03o} {t:links/%*u} "
"{t:user/%-*s} {t:group/%-*s} \n",
"/some/file", (int) 0640, 8, 1,
diff --git a/contrib/libxo/xohtml/xohtml.css b/contrib/libxo/xohtml/xohtml.css
index fc9ea066860e..67c3bff1b18a 100644
--- a/contrib/libxo/xohtml/xohtml.css
+++ b/contrib/libxo/xohtml/xohtml.css
@@ -124,7 +124,7 @@ div.muxer-buttons {
padding: 20px;
}
-div.text, div.decoration, div.data, div.header, div.pad, div.item {
+div.text, div.decoration, div.data, div.header, div.pad, div.item, div.units {
font-family: monospace;
display: inline;
vertical-align: middle;
diff --git a/contrib/libxo/xohtml/xohtml.sh.in b/contrib/libxo/xohtml/xohtml.sh.in
index a15d82e3276a..f6c2fdbc99ff 100644
--- a/contrib/libxo/xohtml/xohtml.sh.in
+++ b/contrib/libxo/xohtml/xohtml.sh.in
@@ -57,7 +57,8 @@ if [ "$CMD" = "cat" -a -t 0 ]; then
do_help
fi
-echo "<html>\n<head>\n"
+echo '<html>'
+echo '<head>'
echo '<meta http-equiv="content-type" content="text/html; charset=utf-8"/>'
echo '<link rel="stylesheet" href="'$BASE'/xohtml.css">'
echo '<link rel="stylesheet" href="'$BASE'/external/jquery.qtip.css"/>'
@@ -66,10 +67,12 @@ echo '<script type="text/javascript" src="'$BASE'/external/jquery.qtip.js"></scr
echo '<script type="text/javascript" src="'$BASE'/xohtml.js"></script>'
echo '<script>'
echo '</script>'
-echo "</head>\n<body>\n"
+echo '</head>'
+echo '<body>'
$CMD
-echo "</body>\n</html>\n"
+echo '</body>'
+echo '</html>'
exit 0
diff --git a/usr.bin/xohtml/Makefile b/usr.bin/xohtml/Makefile
new file mode 100644
index 000000000000..0efb843f8cec
--- /dev/null
+++ b/usr.bin/xohtml/Makefile
@@ -0,0 +1,31 @@
+# $FreeBSD$
+
+.include <src.opts.mk>
+
+LIBXOSRC= ${SRCTOP}/contrib/libxo
+
+.PATH:
+.PATH: ${LIBXOSRC}/xohtml
+
+SCRIPTS= xohtml.sh
+MAN= xohtml.1
+
+EXTERNAL_FILES = \
+ external/jquery.js \
+ external/jquery.qtip.css \
+ external/jquery.qtip.js
+
+INTERNAL_FILES = \
+ xohtml.js \
+ xohtml.css
+
+FILES= ${INTERNAL_FILES} ${EXTERNAL_FILES}
+FILESDIR= /usr/share/xohtml
+FILESMODE= ${NOBINMODE}
+
+beforeinstall: mkfilesdir
+mkfilesdir:
+ test -d ${DESTDIR}${FILESDIR} \
+ || ${INSTALL} -d -o ${FILESOWN} -g ${FILESGRP} -m 755 ${DESTDIR}${FILESDIR}
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/xohtml/xohtml.sh b/usr.bin/xohtml/xohtml.sh
new file mode 100755
index 000000000000..c1e85f7e151d
--- /dev/null
+++ b/usr.bin/xohtml/xohtml.sh
@@ -0,0 +1,79 @@
+#!/bin/sh
+# $FreeBSD$
+#
+# Copyright (c) 2014, Juniper Networks, Inc.
+# All rights reserved.
+# This SOFTWARE is licensed under the LICENSE provided in the
+# ../Copyright file. By downloading, installing, copying, or otherwise
+# using the SOFTWARE, you agree to be bound by the terms of that
+# LICENSE.
+# Phil Shafer, July 2014
+#
+
+BASE=/usr/share/libxo
+CMD=cat
+DONE=
+
+do_help () {
+ echo "xohtml: wrap libxo-enabled output in HTML"
+ echo "Usage: xohtml [options] [command [arguments]]"
+ echo "Valid options are:"
+ echo " -b <basepath> | --base <basepath>"
+ echo " -c <command> | --command <command>"
+ echo " -f <output-file> | --file <output-file>"
+ exit 1
+}
+
+while [ -z "$DONE" -a ! -z "$1" ]; do
+ case "$1" in
+ -b|--base)
+ shift;
+ BASE="$1";
+ shift;
+ ;;
+ -c|--command)
+ shift;
+ CMD="$1";
+ shift;
+ ;;
+ -f|--file)
+ shift;
+ FILE="$1";
+ shift;
+ exec > "$FILE";
+ ;;
+ -*)
+ do_help
+ ;;
+ *)
+ DONE=1;
+ XX=$1;
+ shift;
+ CMD="$XX --libxo=html $@"
+ ;;
+ esac
+done
+
+if [ "$CMD" = "cat" -a -t 0 ]; then
+ do_help
+fi
+
+echo '<html>'
+echo '<head>'
+echo '<meta http-equiv="content-type" content="text/html; charset=utf-8"/>'
+echo '<link rel="stylesheet" href="'$BASE'/xohtml.css">'
+echo '<link rel="stylesheet" href="'$BASE'/external/jquery.qtip.css"/>'
+echo '<script type="text/javascript" src="'$BASE'/external/jquery.js"></script>'
+echo '<script type="text/javascript" src="'$BASE'/external/jquery.qtip.js"></script>'
+echo '<script type="text/javascript" src="'$BASE'/xohtml.js"></script>'
+echo '<script>'
+echo '</script>'
+echo '</head>'
+echo '<body>'
+
+$CMD
+
+echo '</body>'
+echo '</html>'
+
+exit 0
diff --git a/usr.bin/xolint/Makefile b/usr.bin/xolint/Makefile
new file mode 100644
index 000000000000..ea8217e66ada
--- /dev/null
+++ b/usr.bin/xolint/Makefile
@@ -0,0 +1,13 @@
+# $FreeBSD$
+
+.include <src.opts.mk>
+
+LIBXOSRC= ${SRCTOP}/contrib/libxo
+
+.PATH:
+.PATH: ${LIBXOSRC}/xolint
+
+SCRIPTS= xolint.pl
+MAN= xolint.1
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/xopo/Makefile b/usr.bin/xopo/Makefile
new file mode 100644
index 000000000000..c8cf4bde7ba8
--- /dev/null
+++ b/usr.bin/xopo/Makefile
@@ -0,0 +1,21 @@
+# $FreeBSD$
+
+.include <src.opts.mk>
+
+LIBXOSRC= ${SRCTOP}/contrib/libxo
+
+.PATH:
+.PATH: ${LIBXOSRC}/xopo
+
+PROG= xopo
+MAN= xopo.1
+
+# XXX For xoversion.h
+CFLAGS+=-I${LIBXOSRC}/libxo
+
+# XXX For xo_config.h
+CFLAGS+=-I${SRCTOP}/lib/libxo
+
+LIBADD= xo util
+
+.include <bsd.prog.mk>