Import libxo-1.0.2

from 1.0.0:
    Add "continuation" flag, to allow multiple "xo" invocations in a single line of output (#58)
    Add --top-wrap to make top-level JSON wrappers
    Add --{open,close}-{list,instace} options
    Add xo_xml_leader(), to detect use of some bogus XML tags. It's still bad form, but it's a little safer now
    Avoid call to xo_write before xo_flush, since the latter calls the former
    Check return code from xo_flush_h properly (<0) (FreeBSD Bug 236935)
    For JSON output, avoid newline before a container's close brace (#62)
    Merge branch 'text_only' of https://github.com/zvr/libxo into zvr-text_only
    Use XO_USE_INT_RETURN_CODES, not USE_INT_RETURN_CODES
    add docs for --continuation
    add docs for --not-first
    call xo_state_set_flags before values and close containers; add XOIF_MADE_OUTPUT flag to track state; make proper empty JSON objects in xo_finish
    color_map code has to be #ifdef'd out, since the struct definition
    correct xo_flush_func_t (doesn't use xo_ssize_t)
    make depth change for --top-wrap only for JSON
    fix to handle --top-wrap in "xo" by being more consistent with handling trailing newlines
    fix to handle text-only version #64 (from zvr)
    fix xo_buf_has_room for round up to the next XO_BUFSIZ, not just add XO_BUFSIZ to the size (FreeBSD Bug 236937)
    update docs for new "xo" options
    update functions to use xo_ssize_t
    update test cases
from 1.0.1:
    Add EINTEGRITY to .pot files under test/gettext/ (fix from FreeBSD)
from 1.0.2:
    handle failure from xo_vnsprintf; don't add -1 to "rc"

PR:		236937, 236935
Submitted by:	phil
Reported by:	Alfonso S. Siciliano <alfix86@gmail.com>
MFC after:	2 weeks
This commit is contained in:
Phil Shafer 2019-04-03 21:55:39 +00:00
commit 406a584d7e
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=345859
80 changed files with 1293 additions and 259 deletions

View File

@ -12,7 +12,7 @@
#
AC_PREREQ(2.2)
AC_INIT([libxo], [0.9.0], [phil@juniper.net])
AC_INIT([libxo], [1.0.2], [phil@juniper.net])
AM_INIT_AUTOMAKE([-Wall -Werror foreign -Wno-portability])
# Support silent build rules. Requires at least automake-1.11.

View File

@ -400,28 +400,28 @@ string, since an inappropriate cast can ruin your day. The vap
argument to `xo_emit_hv` points to a variable argument list that can
be used to retrieve arguments via `va_arg`.
.. c:function:: int xo_emit (const char *fmt, ...)
.. c:function:: xo_ssize_t xo_emit (const char *fmt, ...)
:param fmt: The format string, followed by zero or more arguments
:returns: If XOF_COLUMNS is set, the number of columns used; otherwise the number of bytes emitted
:rtype: int
:rtype: xo_ssize_t
.. c:function:: int xo_emit_h (xo_handle_t *xop, const char *fmt, ...)
.. c:function:: xo_ssize_t xo_emit_h (xo_handle_t *xop, const char *fmt, ...)
:param xop: Handle for modify (or NULL for default handle)
:type xop: xo_handle_t \*
:param fmt: The format string, followed by zero or more arguments
:returns: If XOF_COLUMNS is set, the number of columns used; otherwise the number of bytes emitted
:rtype: int
:rtype: xo_ssize_t
.. c:function:: int xo_emit_hv (xo_handle_t *xop, const char *fmt, va_list vap)
.. c:function:: xo_ssize_t xo_emit_hv (xo_handle_t *xop, const char *fmt, va_list vap)
:param xop: Handle for modify (or NULL for default handle)
:type xop: xo_handle_t \*
:param fmt: The format string
:param va_list vap: A set of variadic arguments
:returns: If XOF_COLUMNS is set, the number of columns used; otherwise the number of bytes emitted
:rtype: int
:rtype: xo_ssize_t
.. index:: xo_emit_field
@ -434,7 +434,7 @@ scenario where one would otherwise need to compose a format
descriptors using `snprintf`. The individual parts of the format
descriptor are passed in distinctly.
.. c:function:: int xo_emit_field (const char *rolmod, const char *contents, const char *fmt, const char *efmt, ...)
.. c:function:: xo_ssize_t xo_emit_field (const char *rolmod, const char *contents, const char *fmt, const char *efmt, ...)
:param rolmod: A comma-separated list of field roles and field modifiers
:type rolmod: const char *
@ -445,7 +445,7 @@ descriptor are passed in distinctly.
:param efmt: Encoding format string, followed by additional arguments
:type efmt: const char *
:returns: If XOF_COLUMNS is set, the number of columns used; otherwise the number of bytes emitted
:rtype: int
:rtype: xo_ssize_t
::
@ -453,7 +453,7 @@ descriptor are passed in distinctly.
xo_emit_field("T", "Host name is ", NULL, NULL);
xo_emit_field("V", "host-name", NULL, NULL, host-name);
.. c:function:: int xo_emit_field_h (xo_handle_t *xop, const char *rolmod, const char *contents, const char *fmt, const char *efmt, ...)
.. c:function:: xo_ssize_t xo_emit_field_h (xo_handle_t *xop, const char *rolmod, const char *contents, const char *fmt, const char *efmt, ...)
:param xop: Handle for modify (or NULL for default handle)
:type xop: xo_handle_t \*
@ -466,9 +466,9 @@ descriptor are passed in distinctly.
:param efmt: Encoding format string, followed by additional arguments
:type efmt: const char *
:returns: If XOF_COLUMNS is set, the number of columns used; otherwise the number of bytes emitted
:rtype: int
:rtype: xo_ssize_t
.. c:function:: int xo_emit_field_hv (xo_handle_t *xop, const char *rolmod, const char *contents, const char *fmt, const char *efmt, va_list vap)
.. c:function:: xo_ssize_t xo_emit_field_hv (xo_handle_t *xop, const char *rolmod, const char *contents, const char *fmt, const char *efmt, va_list vap)
:param xop: Handle for modify (or NULL for default handle)
:type xop: xo_handle_t \*
@ -482,7 +482,7 @@ descriptor are passed in distinctly.
:type efmt: const char *
:param va_list vap: A set of variadic arguments
:returns: If XOF_COLUMNS is set, the number of columns used; otherwise the number of bytes emitted
:rtype: int
:rtype: xo_ssize_t
.. index:: xo_attr
.. _xo_attr:
@ -505,14 +505,14 @@ Since attributes are only emitted in XML, their use should be limited
to meta-data and additional or redundant representations of data
already emitted in other form.
.. c:function:: int xo_attr (const char *name, const char *fmt, ...)
.. c:function:: xo_ssize_t xo_attr (const char *name, const char *fmt, ...)
:param name: Attribute name
:type name: const char *
:param fmt: Attribute value, as variadic arguments
:type fmt: const char *
:returns: -1 for error, or the number of bytes in the formatted attribute value
:rtype: int
:rtype: xo_ssize_t
::
@ -525,7 +525,7 @@ already emitted in other form.
<login-time seconds="1408336270">00:14</login-time>
.. c:function:: int xo_attr_h (xo_handle_t *xop, const char *name, const char *fmt, ...)
.. c:function:: xo_ssize_t xo_attr_h (xo_handle_t *xop, const char *name, const char *fmt, ...)
:param xop: Handle for modify (or NULL for default handle)
:type xop: xo_handle_t \*
@ -533,7 +533,7 @@ already emitted in other form.
The `xo_attr_h` function follows the conventions of `xo_attr` but
adds an explicit libxo handle.
.. c:function:: int xo_attr_hv (xo_handle_t *xop, const char *name, const char *fmt, va_list vap)
.. c:function:: xo_ssize_t xo_attr_hv (xo_handle_t *xop, const char *name, const char *fmt, va_list vap)
The `xo_attr_h` function follows the conventions of `xo_attr_h`
but replaced the variadic list with a variadic pointer.

View File

@ -515,7 +515,7 @@ li.indline1 {
}
@top-right {
content: "May 2018";
content: "April 2019";
}
@top-center {
@ -22011,7 +22011,7 @@ jQuery(function ($) {
</tr>
<tr>
<td class="header left"></td>
<td class="header right">May 21, 2018</td>
<td class="header right">April 2, 2019</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>

View File

@ -75,7 +75,7 @@ prepend data to the XPath values used for HTML output style::
EXAMPLE;
#!/bin/sh
xo --open top/data
xo --depth 2 '{tag}' value
xo --depth 2 '{:tag}' value
xo --close top/data
XML:
<top>
@ -90,6 +90,84 @@ prepend data to the XPath values used for HTML output style::
}
}
When making partial lines of output (where the format string does not
include a newline), use the `--continuation` option to let secondary
invocations know they are adding data to an existing line.
When emitting a series of objects, use the `--not-first` option to
ensure that any details from the previous object (e.g. commas in JSON)
are handled correctly.
Use the `--top-wrap` option to ensure any top-level object details are
handled correctly, e.g. wrap the entire output in a top-level set of
braces for JSON output.
EXAMPLE;
#!/bin/sh
xo --top-wrap --open top/data
xo --depth 2 'First {:tag} ' value1
xo --depth 2 --continuation 'and then {:tag}\n' value2
xo --top-wrap --close top/data
TEXT:
First value1 and then value2
HTML:
<div class="line">
<div class="text">First </div>
<div class="data" data-tag="tag">value1</div>
<div class="text"> </div>
<div class="text">and then </div>
<div class="data" data-tag="tag">value2</div>
</div>
XML:
<top>
<data>
<tag>value1</tag>
<tag>value2</tag>
</data>
</top>
JSON:
{
"top": {
"data": {
"tag": "value1",
"tag": "value2"
}
}
}
Lists and Instances
-------------------
A "*list*" is set of one or more instances that appear under the same
parent. The instances contain details about a specific object. One
can think of instances as objects or records. A call is needed to
open and close the list, while a distinct call is needed to open and
close each instance of the list.
Use the `--open-list` and `--open-instances` to open lists and
instances. Use the `--close-list` and `--close-instances` to close
them. Each of these options take a `name` parameter, providing the
name of the list and instance.
In the following example, a list named "machine" is created with three
instances:
opts="--json"
xo $opts --open-list machine
NF=
for name in red green blue; do
xo $opts --depth 1 $NF --open-instance machine
xo $opts --depth 2 "Machine {k:name} has {:memory}\n" $name 55
xo $opts --depth 1 --close-instance machine
NF=--not-first
done
xo $opts $NF --close-list machine
The normal `libxo` functions use a state machine to help these
transitions, but since each `xo` command is invoked independent of the
previous calls, the state must be passed in explicitly via these
command line options.
Command Line Options
--------------------
@ -97,15 +175,23 @@ Command Line Options
Usage: xo [options] format [fields]
--close <path> Close tags for the given path
--close-instance <name> Close an open instance name
--close-list <name> Close an open list name
--continuation OR -C Output belongs on same line as previous output
--depth <num> Set the depth for pretty printing
--help Display this help text
--html OR -H Generate HTML output
--json OR -J Generate JSON output
--leading-xpath <path> Add a prefix to generated XPaths (HTML)
--not-first Indicate this object is not the first (JSON)
--open <path> Open tags for the given path
--open-instance <name> Open an instance given by name
--open-list <name> Open a list given by name
--option <opts> -or -O <opts> Give formatting options
--pretty OR -p Make 'pretty' output (add indent, newlines)
--style <style> Generate given style (xml, json, text, html)
--text OR -T Generate text output (the default style)
--top-wrap Generate a top-level object wrapper (JSON)
--version Display version information
--warn OR -W Display warnings in text on stderr
--warn-xml Display warnings in xml on stdout

View File

@ -35,6 +35,7 @@ libxoinc_HEADERS = \
noinst_HEADERS = \
xo_buf.h \
xo_explicit.h \
xo_humanize.h \
xo_wcwidth.h

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2015, Juniper Networks, Inc.
* Copyright (c) 2014-2018, Juniper Networks, Inc.
* All rights reserved.
* This SOFTWARE is licensed under the LICENSE provided in the
* ../Copyright file. By downloading, installing, copying, or otherwise
@ -47,6 +47,7 @@
#include "xo.h"
#include "xo_encoder.h"
#include "xo_buf.h"
#include "xo_explicit.h"
/*
* We ask wcwidth() to do an impossible job, really. It's supposed to
@ -158,40 +159,9 @@ typedef unsigned xo_xsf_flags_t; /* XSF_* flags */
(XSF_NOT_FIRST | XSF_CONTENT | XSF_EMIT | XSF_EMIT_KEY | XSF_EMIT_LEAF_LIST )
/*
* A word about states: We use a finite state machine (FMS) approach
* to help remove fragility from the caller's code. Instead of
* requiring a specific order of calls, we'll allow the caller more
* flexibility and make the library responsible for recovering from
* missed steps. The goal is that the library should not be capable
* of emitting invalid xml or json, but the developer shouldn't need
* to know or understand all the details about these encodings.
*
* You can think of states as either states or events, since they
* function rather like both. None of the XO_CLOSE_* events will
* persist as states, since the matching stack frame will be popped.
* Same is true of XSS_EMIT, which is an event that asks us to
* prep for emitting output fields.
* Turn the transition between two states into a number suitable for
* a "switch" statement.
*/
/* Stack frame states */
typedef unsigned xo_state_t;
#define XSS_INIT 0 /* Initial stack state */
#define XSS_OPEN_CONTAINER 1
#define XSS_CLOSE_CONTAINER 2
#define XSS_OPEN_LIST 3
#define XSS_CLOSE_LIST 4
#define XSS_OPEN_INSTANCE 5
#define XSS_CLOSE_INSTANCE 6
#define XSS_OPEN_LEAF_LIST 7
#define XSS_CLOSE_LEAF_LIST 8
#define XSS_DISCARDING 9 /* Discarding data until recovered */
#define XSS_MARKER 10 /* xo_open_marker's marker */
#define XSS_EMIT 11 /* xo_emit has a leaf field */
#define XSS_EMIT_LEAF_LIST 12 /* xo_emit has a leaf-list ({l:}) */
#define XSS_FINISH 13 /* xo_finish was called */
#define XSS_MAX 13
#define XSS_TRANSITION(_old, _new) ((_old) << 8 | (_new))
/*
@ -288,8 +258,8 @@ struct xo_handle_s {
ssize_t xo_units_offset; /* Start of units insertion point */
ssize_t xo_columns; /* Columns emitted during this xo_emit call */
#ifndef LIBXO_TEXT_ONLY
uint8_t xo_color_map_fg[XO_NUM_COLORS]; /* Foreground color mappings */
uint8_t xo_color_map_bg[XO_NUM_COLORS]; /* Background color mappings */
xo_color_t xo_color_map_fg[XO_NUM_COLORS]; /* Foreground color mappings */
xo_color_t xo_color_map_bg[XO_NUM_COLORS]; /* Background color mappings */
#endif /* LIBXO_TEXT_ONLY */
xo_colors_t xo_colors; /* Current color and effect values */
xo_buffer_t xo_color_buf; /* HTML: buffer of colors and effects */
@ -321,6 +291,7 @@ struct xo_handle_s {
#define XOIF_UNITS_PENDING XOF_BIT(4) /* We have a units-insertion pending */
#define XOIF_INIT_IN_PROGRESS XOF_BIT(5) /* Init of handle is in progress */
#define XOIF_MADE_OUTPUT XOF_BIT(6) /* Have already made output */
/* Flags for formatting functions */
typedef unsigned long xo_xff_flags_t;
@ -468,7 +439,7 @@ static void
xo_failure (xo_handle_t *xop, const char *fmt, ...);
static ssize_t
xo_transition (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name,
xo_transition (xo_handle_t *xop, xo_xof_flags_t flags, const char *name,
xo_state_t new_state);
static int
@ -505,6 +476,20 @@ xo_style (xo_handle_t *xop UNUSED)
#endif /* LIBXO_TEXT_ONLY */
}
/*
* Allow the compiler to optimize out non-text-only code while
* still compiling it.
*/
static inline int
xo_text_only (void)
{
#ifdef LIBXO_TEXT_ONLY
return TRUE;
#else /* LIBXO_TEXT_ONLY */
return FALSE;
#endif /* LIBXO_TEXT_ONLY */
}
/*
* Callback to write data to a FILE pointer
*/
@ -606,6 +591,28 @@ xo_no_setlocale (void)
xo_locale_inited = 1; /* Skip initialization */
}
/*
* For XML, the first character of a tag cannot be numeric, but people
* will likely not notice. So we people-proof them by forcing a leading
* underscore if they use invalid tags. Note that this doesn't cover
* all broken tags, just this fairly specific case.
*/
static const char *
xo_xml_leader_len (xo_handle_t *xop, const char *name, xo_ssize_t nlen)
{
if (isalpha(name[0]) || name[0] == '_')
return "";
xo_failure(xop, "invalid XML tag name: '%.*s'", nlen, name);
return "_";
}
static const char *
xo_xml_leader (xo_handle_t *xop, const char *name)
{
return xo_xml_leader_len(xop, name, strlen(name));
}
/*
* We need to decide if stdout is line buffered (_IOLBF). Lacking a
* standard way to decide this (e.g. getlinebuf()), we have configure
@ -2194,9 +2201,8 @@ xo_set_style_name (xo_handle_t *xop, const char *name)
static void
xo_set_color_map (xo_handle_t *xop, char *value)
{
#ifdef LIBXO_TEXT_ONLY
return;
#endif /* LIBXO_TEXT_ONLY */
if (xo_text_only())
return;
char *cp, *ep, *vp, *np;
ssize_t len = value ? strlen(value) + 1 : 0;
@ -2214,8 +2220,11 @@ xo_set_color_map (xo_handle_t *xop, char *value)
fg = *cp ? xo_color_find(cp) : -1;
bg = (vp && *vp) ? xo_color_find(vp) : -1;
#ifndef LIBXO_TEXT_ONLY
xop->xo_color_map_fg[num] = (fg < 0) ? num : fg;
xop->xo_color_map_bg[num] = (bg < 0) ? num : bg;
#endif /* LIBXO_TEXT_ONLY */
if (++num > XO_NUM_COLORS)
break;
}
@ -2226,9 +2235,11 @@ xo_set_color_map (xo_handle_t *xop, char *value)
else
XOF_CLEAR(xop, XOF_COLOR_MAP);
#ifndef LIBXO_TEXT_ONLY
/* Fill in the rest of the colors with the defaults */
for ( ; num < XO_NUM_COLORS; num++)
xop->xo_color_map_fg[num] = xop->xo_color_map_bg[num] = num;
#endif /* LIBXO_TEXT_ONLY */
}
static int
@ -2600,6 +2611,12 @@ xo_line_ensure_open (xo_handle_t *xop, xo_xff_flags_t flags UNUSED)
static char div_open[] = "<div class=\"line\">";
static char div_open_blank[] = "<div class=\"blank-line\">";
if (XOF_ISSET(xop, XOF_CONTINUATION)) {
XOF_CLEAR(xop, XOF_CONTINUATION);
XOIF_SET(xop, XOIF_DIV_OPEN);
return;
}
if (XOIF_ISSET(xop, XOIF_DIV_OPEN))
return;
@ -3505,51 +3522,54 @@ xo_do_format_field (xo_handle_t *xop, xo_buffer_t *xbp,
ssize_t columns = rc = xo_vsnprintf(xop, xbp, newfmt,
xop->xo_vap);
/*
* For XML and HTML, we need "&<>" processing; for JSON,
* it's quotes. Text gets nothing.
*/
switch (style) {
case XO_STYLE_XML:
if (flags & XFF_TRIM_WS)
columns = rc = xo_trim_ws(xbp, rc);
/* FALLTHRU */
case XO_STYLE_HTML:
rc = xo_escape_xml(xbp, rc, (flags & XFF_ATTR));
break;
if (rc > 0) {
/*
* For XML and HTML, we need "&<>" processing; for JSON,
* it's quotes. Text gets nothing.
*/
switch (style) {
case XO_STYLE_XML:
if (flags & XFF_TRIM_WS)
columns = rc = xo_trim_ws(xbp, rc);
/* FALLTHRU */
case XO_STYLE_HTML:
rc = xo_escape_xml(xbp, rc, (flags & XFF_ATTR));
break;
case XO_STYLE_JSON:
if (flags & XFF_TRIM_WS)
columns = rc = xo_trim_ws(xbp, rc);
rc = xo_escape_json(xbp, rc, 0);
break;
case XO_STYLE_JSON:
if (flags & XFF_TRIM_WS)
columns = rc = xo_trim_ws(xbp, rc);
rc = xo_escape_json(xbp, rc, 0);
break;
case XO_STYLE_SDPARAMS:
if (flags & XFF_TRIM_WS)
columns = rc = xo_trim_ws(xbp, rc);
rc = xo_escape_sdparams(xbp, rc, 0);
break;
case XO_STYLE_SDPARAMS:
if (flags & XFF_TRIM_WS)
columns = rc = xo_trim_ws(xbp, rc);
rc = xo_escape_sdparams(xbp, rc, 0);
break;
case XO_STYLE_ENCODER:
if (flags & XFF_TRIM_WS)
columns = rc = xo_trim_ws(xbp, rc);
break;
case XO_STYLE_ENCODER:
if (flags & XFF_TRIM_WS)
columns = rc = xo_trim_ws(xbp, rc);
break;
}
/*
* We can assume all the non-%s data we've
* added is ASCII, so the columns and bytes are the
* same. xo_format_string handles all the fancy
* string conversions and updates xo_anchor_columns
* accordingly.
*/
if (XOF_ISSET(xop, XOF_COLUMNS))
xop->xo_columns += columns;
if (XOIF_ISSET(xop, XOIF_ANCHOR))
xop->xo_anchor_columns += columns;
}
/*
* We can assume all the non-%s data we've
* added is ASCII, so the columns and bytes are the
* same. xo_format_string handles all the fancy
* string conversions and updates xo_anchor_columns
* accordingly.
*/
if (XOF_ISSET(xop, XOF_COLUMNS))
xop->xo_columns += columns;
if (XOIF_ISSET(xop, XOIF_ANCHOR))
xop->xo_anchor_columns += columns;
}
xbp->xb_curp += rc;
if (rc > 0)
xbp->xb_curp += rc;
}
/*
@ -4233,6 +4253,21 @@ xo_format_is_numeric (const char *fmt, ssize_t flen)
return (strchr("diouDOUeEfFgG", *fmt) == NULL) ? FALSE : TRUE;
}
/*
* Update the stack flags using the object flags, allowing callers
* to monkey with the stack flags without even knowing they exist.
*/
static void
xo_stack_set_flags (xo_handle_t *xop)
{
if (XOF_ISSET(xop, XOF_NOT_FIRST)) {
xo_stack_t *xsp = &xop->xo_stack[xop->xo_depth];
xsp->xs_flags |= XSF_NOT_FIRST;
XOF_CLEAR(xop, XOF_NOT_FIRST);
}
}
static void
xo_format_prep (xo_handle_t *xop, xo_xff_flags_t flags)
{
@ -4337,6 +4372,8 @@ xo_format_value (xo_handle_t *xop, const char *name, ssize_t nlen,
xo_buffer_t *xbp = &xop->xo_data;
xo_humanize_save_t save; /* Save values for humanizing logic */
const char *leader = xo_xml_leader_len(xop, name, nlen);
switch (xo_style(xop)) {
case XO_STYLE_TEXT:
if (flags & XFF_ENCODE_ONLY)
@ -4391,6 +4428,8 @@ xo_format_value (xo_handle_t *xop, const char *name, ssize_t nlen,
if (pretty)
xo_buf_indent(xop, -1);
xo_data_append(xop, "<", 1);
if (*leader)
xo_data_append(xop, leader, 1);
xo_data_escape(xop, name, nlen);
if (xop->xo_attrs.xb_curp != xop->xo_attrs.xb_bufp) {
@ -4423,6 +4462,8 @@ xo_format_value (xo_handle_t *xop, const char *name, ssize_t nlen,
xo_simple_field(xop, FALSE, value, vlen, fmt, flen, flags);
xo_data_append(xop, "</", 2);
if (*leader)
xo_data_append(xop, leader, 1);
xo_data_escape(xop, name, nlen);
xo_data_append(xop, ">", 1);
if (pretty)
@ -4446,6 +4487,8 @@ xo_format_value (xo_handle_t *xop, const char *name, ssize_t nlen,
flen = strlen(fmt);
}
xo_stack_set_flags(xop);
int first = (xop->xo_stack[xop->xo_depth].xs_flags & XSF_NOT_FIRST)
? 0 : 1;
@ -4751,9 +4794,8 @@ xo_effect_find (const char *str)
static void
xo_colors_parse (xo_handle_t *xop, xo_colors_t *xocp, char *str)
{
#ifdef LIBXO_TEXT_ONLY
return;
#endif /* LIBXO_TEXT_ONLY */
if (xo_text_only())
return;
char *cp, *ep, *np, *xp;
ssize_t len = strlen(str);
@ -4837,12 +4879,9 @@ xo_colors_enabled (xo_handle_t *xop UNUSED)
* the incoming foreground and background colors from the map.
*/
static void
xo_colors_update (xo_handle_t *xop, xo_colors_t *newp)
xo_colors_update (xo_handle_t *xop UNUSED, xo_colors_t *newp UNUSED)
{
#ifdef LIBXO_TEXT_ONLY
return;
#endif /* LIBXO_TEXT_ONLY */
#ifndef LIBXO_TEXT_ONLY
xo_color_t fg = newp->xoc_col_fg;
if (XOF_ISSET(xop, XOF_COLOR_MAP) && fg < XO_NUM_COLORS)
fg = xop->xo_color_map_fg[fg]; /* Fetch from color map */
@ -4852,6 +4891,7 @@ xo_colors_update (xo_handle_t *xop, xo_colors_t *newp)
if (XOF_ISSET(xop, XOF_COLOR_MAP) && bg < XO_NUM_COLORS)
bg = xop->xo_color_map_bg[bg]; /* Fetch from color map */
newp->xoc_col_bg = bg;
#endif /* LIBXO_TEXT_ONLY */
}
static void
@ -6454,9 +6494,7 @@ xo_do_emit_fields (xo_handle_t *xop, xo_field_info_t *fields,
/* If we don't have an anchor, write the text out */
if (flush && !XOIF_ISSET(xop, XOIF_ANCHOR)) {
if (xo_write(xop) < 0)
rc = -1; /* Report failure */
else if (xo_flush_h(xop) < 0)
if (xo_flush_h(xop) < 0)
rc = -1;
}
@ -6803,17 +6841,6 @@ xo_attr (const char *name, const char *fmt, ...)
return rc;
}
static void
xo_stack_set_flags (xo_handle_t *xop)
{
if (XOF_ISSET(xop, XOF_NOT_FIRST)) {
xo_stack_t *xsp = &xop->xo_stack[xop->xo_depth];
xsp->xs_flags |= XSF_NOT_FIRST;
XOF_CLEAR(xop, XOF_NOT_FIRST);
}
}
static void
xo_depth_change (xo_handle_t *xop, const char *name,
int delta, int indent, xo_state_t state, xo_xsf_flags_t flags)
@ -6889,6 +6916,15 @@ xo_set_depth (xo_handle_t *xop, int depth)
xop->xo_depth += depth;
xop->xo_indent += depth;
/*
* Handling the "top wrapper" for JSON is a bit of a pain. Here
* we need to detect that the depth has been changed to set the
* "XOIF_TOP_EMITTED" flag correctly.
*/
if (xop->xo_style == XO_STYLE_JSON
&& !XOF_ISSET(xop, XOF_NO_TOP) && xop->xo_depth > 0)
XOIF_SET(xop, XOIF_TOP_EMITTED);
}
static xo_xsf_flags_t
@ -6925,11 +6961,12 @@ xo_do_open_container (xo_handle_t *xop, xo_xof_flags_t flags, const char *name)
name = XO_FAILURE_NAME;
}
const char *leader = xo_xml_leader(xop, name);
flags |= xop->xo_flags; /* Pick up handle flags */
switch (xo_style(xop)) {
case XO_STYLE_XML:
rc = xo_printf(xop, "%*s<%s", xo_indent(xop), "", name);
rc = xo_printf(xop, "%*s<%s%s", xo_indent(xop), "", leader, name);
if (xop->xo_attrs.xb_curp != xop->xo_attrs.xb_bufp) {
rc += xop->xo_attrs.xb_curp - xop->xo_attrs.xb_bufp;
@ -6970,7 +7007,7 @@ xo_do_open_container (xo_handle_t *xop, xo_xof_flags_t flags, const char *name)
return rc;
}
static int
xo_ssize_t
xo_open_container_hf (xo_handle_t *xop, xo_xof_flags_t flags, const char *name)
{
return xo_transition(xop, flags, name, XSS_OPEN_CONTAINER);
@ -7025,15 +7062,20 @@ xo_do_close_container (xo_handle_t *xop, const char *name)
}
}
const char *leader = xo_xml_leader(xop, name);
switch (xo_style(xop)) {
case XO_STYLE_XML:
xo_depth_change(xop, name, -1, -1, XSS_CLOSE_CONTAINER, 0);
rc = xo_printf(xop, "%*s</%s>%s", xo_indent(xop), "", name, ppn);
rc = xo_printf(xop, "%*s</%s%s>%s", xo_indent(xop), "", leader, name, ppn);
break;
case XO_STYLE_JSON:
xo_stack_set_flags(xop);
pre_nl = XOF_ISSET(xop, XOF_PRETTY) ? "\n" : "";
ppn = (xop->xo_depth <= 1) ? "\n" : "";
ppn = (xop->xo_depth <= 1) ? pre_nl : "";
ppn = "";
xo_depth_change(xop, name, -1, -1, XSS_CLOSE_CONTAINER, 0);
rc = xo_printf(xop, "%s%*s}%s", pre_nl, xo_indent(xop), "", ppn);
@ -7082,7 +7124,7 @@ xo_close_container_d (void)
}
static int
xo_do_open_list (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name)
xo_do_open_list (xo_handle_t *xop, xo_xof_flags_t flags, const char *name)
{
ssize_t rc = 0;
int indent = 0;
@ -7126,8 +7168,8 @@ xo_do_open_list (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name)
return rc;
}
static int
xo_open_list_hf (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name)
xo_ssize_t
xo_open_list_hf (xo_handle_t *xop, xo_xof_flags_t flags, const char *name)
{
return xo_transition(xop, flags, name, XSS_OPEN_LIST);
}
@ -7228,7 +7270,7 @@ xo_close_list_d (void)
}
static int
xo_do_open_leaf_list (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name)
xo_do_open_leaf_list (xo_handle_t *xop, xo_xof_flags_t flags, const char *name)
{
ssize_t rc = 0;
int indent = 0;
@ -7322,7 +7364,7 @@ xo_do_close_leaf_list (xo_handle_t *xop, const char *name)
}
static int
xo_do_open_instance (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name)
xo_do_open_instance (xo_handle_t *xop, xo_xof_flags_t flags, const char *name)
{
xop = xo_default(xop);
@ -7330,16 +7372,17 @@ xo_do_open_instance (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name)
const char *ppn = XOF_ISSET(xop, XOF_PRETTY) ? "\n" : "";
const char *pre_nl = "";
flags |= xop->xo_flags;
if (name == NULL) {
xo_failure(xop, "NULL passed for instance name");
name = XO_FAILURE_NAME;
}
const char *leader = xo_xml_leader(xop, name);
flags |= xop->xo_flags;
switch (xo_style(xop)) {
case XO_STYLE_XML:
rc = xo_printf(xop, "%*s<%s", xo_indent(xop), "", name);
rc = xo_printf(xop, "%*s<%s%s", xo_indent(xop), "", leader, name);
if (xop->xo_attrs.xb_curp != xop->xo_attrs.xb_bufp) {
rc += xop->xo_attrs.xb_curp - xop->xo_attrs.xb_bufp;
@ -7375,8 +7418,8 @@ xo_do_open_instance (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name)
return rc;
}
static int
xo_open_instance_hf (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name)
xo_ssize_t
xo_open_instance_hf (xo_handle_t *xop, xo_xof_flags_t flags, const char *name)
{
return xo_transition(xop, flags, name, XSS_OPEN_INSTANCE);
}
@ -7430,10 +7473,12 @@ xo_do_close_instance (xo_handle_t *xop, const char *name)
}
}
const char *leader = xo_xml_leader(xop, name);
switch (xo_style(xop)) {
case XO_STYLE_XML:
xo_depth_change(xop, name, -1, -1, XSS_CLOSE_INSTANCE, 0);
rc = xo_printf(xop, "%*s</%s>%s", xo_indent(xop), "", name, ppn);
rc = xo_printf(xop, "%*s</%s%s>%s", xo_indent(xop), "", leader, name, ppn);
break;
case XO_STYLE_JSON:
@ -7599,7 +7644,7 @@ xo_do_close (xo_handle_t *xop, const char *name, xo_state_t new_state)
* We are in a given state and need to transition to the new state.
*/
static ssize_t
xo_transition (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name,
xo_transition (xo_handle_t *xop, xo_xof_flags_t flags, const char *name,
xo_state_t new_state)
{
xo_stack_t *xsp;
@ -7855,9 +7900,12 @@ xo_transition (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name,
/* Handle the flush flag */
if (rc >= 0 && XOF_ISSET(xop, XOF_FLUSH))
if (xo_flush_h(xop))
if (xo_flush_h(xop) < 0)
rc = -1;
/* We have now official made output */
XOIF_SET(xop, XOIF_MADE_OUTPUT);
return rc;
marker_prevents_close:
@ -7950,7 +7998,7 @@ xo_flush (void)
xo_ssize_t
xo_finish_h (xo_handle_t *xop)
{
const char *cp = "";
const char *open_if_empty = "";
xop = xo_default(xop);
if (!XOF_ISSET(xop, XOF_NO_CLOSE))
@ -7959,11 +8007,17 @@ xo_finish_h (xo_handle_t *xop)
switch (xo_style(xop)) {
case XO_STYLE_JSON:
if (!XOF_ISSET(xop, XOF_NO_TOP)) {
const char *pre_nl = XOF_ISSET(xop, XOF_PRETTY) ? "\n" : "";
if (XOIF_ISSET(xop, XOIF_TOP_EMITTED))
XOIF_CLEAR(xop, XOIF_TOP_EMITTED); /* Turn off before output */
else
cp = "{ ";
xo_printf(xop, "%*s%s}\n",xo_indent(xop), "", cp);
else if (!XOIF_ISSET(xop, XOIF_MADE_OUTPUT)) {
open_if_empty = "{ ";
pre_nl = "";
}
xo_printf(xop, "%s%*s%s}\n",
pre_nl, xo_indent(xop), "", open_if_empty);
}
break;
@ -8402,3 +8456,46 @@ xo_set_encoder (xo_handle_t *xop, xo_encoder_func_t encoder)
xop->xo_style = XO_STYLE_ENCODER;
xop->xo_encoder = encoder;
}
/*
* The xo(1) utility needs to be able to open and close lists and
* instances, but since it's called without "state", we cannot
* rely on the state transitions (in xo_transition) to DTRT, so
* we have a mechanism for external parties to "force" transitions
* that would otherwise be impossible. This is not a general
* mechanism, and is really tailored only for xo(1).
*/
void
xo_explicit_transition (xo_handle_t *xop, xo_state_t new_state,
const char *name, xo_xof_flags_t flags)
{
xo_xsf_flags_t xsf_flags;
xop = xo_default(xop);
switch (new_state) {
case XSS_OPEN_LIST:
xo_do_open_list(xop, flags, name);
break;
case XSS_OPEN_INSTANCE:
xo_do_open_instance(xop, flags, name);
break;
case XSS_CLOSE_INSTANCE:
xo_depth_change(xop, name, 1, 1, XSS_OPEN_INSTANCE,
xo_stack_flags(flags));
xo_stack_set_flags(xop);
xo_do_close_instance(xop, name);
break;
case XSS_CLOSE_LIST:
xsf_flags = XOF_ISSET(xop, XOF_NOT_FIRST) ? XSF_NOT_FIRST : 0;
xo_depth_change(xop, name, 1, 1, XSS_OPEN_LIST,
XSF_LIST | xsf_flags | xo_stack_flags(flags));
xo_do_close_list(xop, name);
break;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2015, Juniper Networks, Inc.
* Copyright (c) 2014-2018, Juniper Networks, Inc.
* All rights reserved.
* This SOFTWARE is licensed under the LICENSE provided in the
* ../Copyright file. By downloading, installing, copying, or otherwise
@ -102,6 +102,7 @@ typedef unsigned long long xo_xof_flags_t;
#define XOF_RETAIN_NONE XOF_BIT(31) /** Prevent use of XOEF_RETAIN */
#define XOF_COLOR_MAP XOF_BIT(32) /** Color map has been initialized */
#define XOF_CONTINUATION XOF_BIT(33) /** Continuation of previous line */
typedef unsigned xo_emit_flags_t; /* Flags to xo_emit() and friends */
#define XOEF_RETAIN (1<<0) /* Retain parsed formatting information */
@ -126,11 +127,11 @@ typedef struct xo_handle_s xo_handle_t; /* Handle for XO output */
* sizes. We want to fix this but allow for backwards compatibility
* where needed.
*/
#ifdef USE_INT_RETURN_CODES
#ifdef XO_USE_INT_RETURN_CODES
typedef int xo_ssize_t; /* Buffer size */
#else /* USE_INT_RETURN_CODES */
#else /* XO_USE_INT_RETURN_CODES */
typedef ssize_t xo_ssize_t; /* Buffer size */
#endif /* USE_INT_RETURN_CODES */
#endif /* XO_USE_INT_RETURN_CODES */
typedef xo_ssize_t (*xo_write_func_t)(void *, const char *);
typedef void (*xo_close_func_t)(void *);
@ -219,36 +220,36 @@ xo_ssize_t
xo_emit_f (xo_emit_flags_t flags, const char *fmt, ...);
PRINTFLIKE(2, 0)
static inline int
static inline xo_ssize_t
xo_emit_hvp (xo_handle_t *xop, const char *fmt, va_list vap)
{
return xo_emit_hv(xop, fmt, vap);
}
PRINTFLIKE(2, 3)
static inline int
static inline xo_ssize_t
xo_emit_hp (xo_handle_t *xop, const char *fmt, ...)
{
va_list vap;
va_start(vap, fmt);
int rc = xo_emit_hv(xop, fmt, vap);
xo_ssize_t rc = xo_emit_hv(xop, fmt, vap);
va_end(vap);
return rc;
}
PRINTFLIKE(1, 2)
static inline int
static inline xo_ssize_t
xo_emit_p (const char *fmt, ...)
{
va_list vap;
va_start(vap, fmt);
int rc = xo_emit_hv(NULL, fmt, vap);
xo_ssize_t rc = xo_emit_hv(NULL, fmt, vap);
va_end(vap);
return rc;
}
PRINTFLIKE(3, 0)
static inline int
static inline xo_ssize_t
xo_emit_hvfp (xo_handle_t *xop, xo_emit_flags_t flags,
const char *fmt, va_list vap)
{
@ -256,27 +257,30 @@ xo_emit_hvfp (xo_handle_t *xop, xo_emit_flags_t flags,
}
PRINTFLIKE(3, 4)
static inline int
static inline xo_ssize_t
xo_emit_hfp (xo_handle_t *xop, xo_emit_flags_t flags, const char *fmt, ...)
{
va_list vap;
va_start(vap, fmt);
int rc = xo_emit_hvf(xop, flags, fmt, vap);
xo_ssize_t rc = xo_emit_hvf(xop, flags, fmt, vap);
va_end(vap);
return rc;
}
PRINTFLIKE(2, 3)
static inline int
static inline xo_ssize_t
xo_emit_fp (xo_emit_flags_t flags, const char *fmt, ...)
{
va_list vap;
va_start(vap, fmt);
int rc = xo_emit_hvf(NULL, flags, fmt, vap);
xo_ssize_t rc = xo_emit_hvf(NULL, flags, fmt, vap);
va_end(vap);
return rc;
}
xo_ssize_t
xo_open_container_hf (xo_handle_t *xop, xo_xof_flags_t flags, const char *name);
xo_ssize_t
xo_open_container_h (xo_handle_t *xop, const char *name);
@ -301,6 +305,9 @@ xo_close_container_hd (xo_handle_t *xop);
xo_ssize_t
xo_close_container_d (void);
xo_ssize_t
xo_open_list_hf (xo_handle_t *xop, xo_xof_flags_t flags, const char *name);
xo_ssize_t
xo_open_list_h (xo_handle_t *xop, const char *name);
@ -325,6 +332,9 @@ xo_close_list_hd (xo_handle_t *xop);
xo_ssize_t
xo_close_list_d (void);
xo_ssize_t
xo_open_instance_hf (xo_handle_t *xop, xo_xof_flags_t flags, const char *name);
xo_ssize_t
xo_open_instance_h (xo_handle_t *xop, const char *name);

View File

@ -17,11 +17,11 @@
.Lb libxo
.Sh SYNOPSIS
.In libxo/xo.h
.Ft int
.Ft xo_ssize_t
.Fn xo_attr "const char *name" "const char *fmt" "..."
.Ft int
.Ft xo_ssize_t
.Fn xo_attr_h "xo_handle_t *handle" "const char *name, const char *fmt" "..."
.Ft int
.Ft xo_ssize_t
.Fn xo_attr_hv "xo_handle_t *handle" "const char *name" "const char *fmt" "va_list vap"
.Sh DESCRIPTION
The

View File

@ -114,7 +114,12 @@ static inline int
xo_buf_has_room (xo_buffer_t *xbp, ssize_t len)
{
if (xbp->xb_curp + len >= xbp->xb_bufp + xbp->xb_size) {
ssize_t sz = xbp->xb_size + XO_BUFSIZ;
/*
* Find out how much new space we need, round it up to XO_BUFSIZ
*/
ssize_t sz = (xbp->xb_curp + len) - xbp->xb_bufp;
sz = (sz + XO_BUFSIZ - 1) & ~(XO_BUFSIZ - 1);
char *bp = xo_realloc(xbp->xb_bufp, sz);
if (bp == NULL)
return 0;

View File

@ -17,11 +17,11 @@
.Lb libxo
.Sh SYNOPSIS
.In libxo/xo.h
.Ft int
.Ft xo_ssize_t
.Fn xo_emit "const char *fmt" "..."
.Ft int
.Ft xo_ssize_t
.Fn xo_emit_h "xo_handle_t *xop" "const char *fmt" "..."
.Ft int
.Ft xo_ssize_t
.Fn xo_emit_hv "xo_handle_t *xop" "const char *fmt" "va_list vap"
.Sh DESCRIPTION
The

View File

@ -17,11 +17,11 @@
.Lb libxo
.Sh SYNOPSIS
.In libxo/xo.h
.Ft int
.Ft xo_ssize_t
.Fn xo_emit_f "xo_emit_flags_t flags" "const char *fmt" "..."
.Ft int
.Ft xo_ssize_t
.Fn xo_emit_hf "xo_handle_t *xop" "xo_emit_flags_t flags" "const char *fmt" "..."
.Ft int
.Ft xo_ssize_t
.Fn xo_emit_hvf "xo_handle_t *xop" "xo_emit_flags_t flags" "const char *fmt" "va_list vap"
.Ft void
.Fn xo_retain_clear_all "void"

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2015, 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, March 2019
*/
#ifndef XO_EXPLICIT_H
#define XO_EXPLICIT_H
/*
* NOTE WELL: This file is needed to software that implements an
* explicit transition between libxo states on its internal stack.
* General libxo code should _never_ include this header file.
*/
/*
* A word about states: We use a finite state machine (FMS) approach
* to help remove fragility from the caller's code. Instead of
* requiring a specific order of calls, we'll allow the caller more
* flexibility and make the library responsible for recovering from
* missed steps. The goal is that the library should not be capable
* of emitting invalid xml or json, but the developer shouldn't need
* to know or understand all the details about these encodings.
*
* You can think of states as either states or events, since they
* function rather like both. None of the XO_CLOSE_* events will
* persist as states, since the matching stack frame will be popped.
* Same is true of XSS_EMIT, which is an event that asks us to
* prep for emitting output fields.
*/
/* Stack frame states */
typedef unsigned xo_state_t; /* XSS_* values */
#define XSS_INIT 0 /* Initial stack state */
#define XSS_OPEN_CONTAINER 1
#define XSS_CLOSE_CONTAINER 2
#define XSS_OPEN_LIST 3
#define XSS_CLOSE_LIST 4
#define XSS_OPEN_INSTANCE 5
#define XSS_CLOSE_INSTANCE 6
#define XSS_OPEN_LEAF_LIST 7
#define XSS_CLOSE_LEAF_LIST 8
#define XSS_DISCARDING 9 /* Discarding data until recovered */
#define XSS_MARKER 10 /* xo_open_marker's marker */
#define XSS_EMIT 11 /* xo_emit has a leaf field */
#define XSS_EMIT_LEAF_LIST 12 /* xo_emit has a leaf-list ({l:}) */
#define XSS_FINISH 13 /* xo_finish was called */
#define XSS_MAX 13
void
xo_explicit_transition (xo_handle_t *xop, xo_state_t new_state,
const char *tag, xo_xof_flags_t flags);
#endif /* XO_EXPLICIT_H */

View File

@ -17,9 +17,9 @@
.Lb libxo
.Sh SYNOPSIS
.In libxo/xo.h
.Ft void
.Ft xo_ssize_t
.Fn xo_finish "void"
.Ft void
.Ft xo_ssize_t
.Fn xo_finish_h "xo_handle_t *xop"
.Sh DESCRIPTION
When the program is ready to exit or close a handle, a call to

View File

@ -17,9 +17,9 @@
.Lb libxo
.Sh SYNOPSIS
.In libxo/xo.h
.Ft void
.Ft xo_ssize_t
.Fn xo_flush "void"
.Ft void
.Ft xo_ssize_t
.Fn xo_flush_h "xo_handle_t *handle"
.Sh DESCRIPTION
.Nm libxo

View File

@ -18,21 +18,21 @@
.Lb libxo
.Sh SYNOPSIS
.In libxo/xo.h
.Ft int
.Ft xo_ssize_t
.Fn xo_open_container "const char *name"
.Ft int
.Ft xo_ssize_t
.Fn xo_open_container_h "xo_handle_t *handle" "const char *name"
.Ft int
.Ft xo_ssize_t
.Fn xo_open_container_hd "xo_handle_t *handle" "const char *name"
.Ft int
.Ft xo_ssize_t
.Fn xo_open_container_d "const char *name"
.Ft int
.Ft xo_ssize_t
.Fn xo_close_container "const char *name"
.Ft int
.Ft xo_ssize_t
.Fn xo_close_container_h "xo_handle_t *handle" "const char *name"
.Ft int
.Ft xo_ssize_t
.Fn xo_close_container_hd "xo_handle_t *handle"
.Ft int
.Ft xo_ssize_t
.Fn xo_close_container_d "void"
.Sh DESCRIPTION
.Nm libxo

View File

@ -20,37 +20,37 @@
.Lb libxo
.Sh SYNOPSIS
.In libxo/xo.h
.Ft int
.Ft xo_ssize_t
.Fn xo_open_list_h "xo_handle_t *xop" "const char *name"
.Ft int
.Ft xo_ssize_t
.Fn xo_open_list "const char *name"
.Ft int
.Ft xo_ssize_t
.Fn xo_open_list_hd "xo_handle_t *xop" "const char *name"
.Ft int
.Ft xo_ssize_t
.Fn xo_open_list_d "const char *name"
.Ft int
.Ft xo_ssize_t
.Fn xo_open_instance_h "xo_handle_t *xop" "const char *name"
.Ft int
.Ft xo_ssize_t
.Fn xo_open_instance "const char *name"
.Ft int
.Ft xo_ssize_t
.Fn xo_open_instance_hd "xo_handle_t *xop" "const char *name"
.Ft int
.Ft xo_ssize_t
.Fn xo_open_instance_d "const char *name"
.Ft int
.Ft xo_ssize_t
.Fn xo_close_instance_h "xo_handle_t *xop" "const char *name"
.Ft int
.Ft xo_ssize_t
.Fn xo_close_instance "const char *name"
.Ft int
.Ft xo_ssize_t
.Fn xo_close_instance_hd "xo_handle_t *xop"
.Ft int
.Ft xo_ssize_t
.Fn xo_close_instance_d "void"
.Ft int
.Ft xo_ssize_t
.Fn xo_close_list_h "xo_handle_t *xop" "const char *name"
.Ft int
.Ft xo_ssize_t
.Fn xo_close_list "const char *name"
.Ft int
.Ft xo_ssize_t
.Fn xo_close_list_hd "xo_handle_t *xop"
.Ft int
.Ft xo_ssize_t
.Fn xo_close_list_d "void"
.Sh DESCRIPTION
Lists are sequences of instances of homogeneous data objects.

View File

@ -17,13 +17,13 @@
.Lb libxo
.Sh SYNOPSIS
.In libxo/xo.h
.Ft int
.Ft xo_ssize_t
.Fn xo_open_marker "const char *name"
.Ft int
.Ft xo_ssize_t
.Fn xo_open_marker_h "xo_handle_t *handle" "const char *name"
.Ft int
.Ft xo_ssize_t
.Fn xo_close_marker "const char *name"
.Ft int
.Ft xo_ssize_t
.Fn xo_close_marker_h "xo_handle_t *handle" "const char *name"
.Sh DESCRIPTION
.Nm libxo

View File

@ -18,7 +18,7 @@
.Sh SYNOPSIS
.In libxo/xo.h
.Ft void
.Sy typedef int (*xo_write_func_t)(void *, const char *);
.Sy typedef xo_ssize_t (*xo_write_func_t)(void *, const char *);
.Pp
.Sy typedef void (*xo_close_func_t)(void *);
.Pp

View File

@ -1,2 +1 @@
{"top": {"type":"ethernet","type":"bridge","type":"18u","type":24,"address":"0x0","port":1,"address":"0x0","port":1,"address":"0x0","port":1,"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"}
}
{"top": {"type":"ethernet","type":"bridge","type":"18u","type":24,"address":"0x0","port":1,"address":"0x0","port":1,"address":"0x0","port":1,"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"}}

View File

@ -1,2 +1 @@
{"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":125,"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":125,"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"}}}}

View File

@ -1,2 +1 @@
{"employees": {"employee": [],"extra":"", "memory": [{"type":"name","in-use":12345,"memory-use":54321,"high-use":"-","requests":32145}], "employee": [{"first-name":"Terry","last-name":"Jones","department":660}, {"first-name":"Leslie","last-name":"Patterson","department":341}, {"first-name":"Ashley","last-name":"Smith","department":1440}]}
}
{"employees": {"employee": [],"extra":"", "memory": [{"type":"name","in-use":12345,"memory-use":54321,"high-use":"-","requests":32145}], "employee": [{"first-name":"Terry","last-name":"Jones","department":660}, {"first-name":"Leslie","last-name":"Patterson","department":341}, {"first-name":"Ashley","last-name":"Smith","department":1440}]}}

View File

@ -1,2 +1 @@
{"employees": {"employee": [{"first-name":"Terry","last-name":"Jones","department":660}, {"first-name":"Leslie","last-name":"Patterson","department":341}, {"first-name":"Ashley","last-name":"Smith","department":1440}]}
}
{"employees": {"employee": [{"first-name":"Terry","last-name":"Jones","department":660}, {"first-name":"Leslie","last-name":"Patterson","department":341}, {"first-name":"Ashley","last-name":"Smith","department":1440}]}}

View File

@ -1,3 +1 @@
{"indian-languages": {"gurmukhi":"ਲਹੌਰ ਪਾਕਿਸਤਾਨੀ ਪੰਜਾਬ ਦੀ ਰਾਜਧਾਨੀ ਹੈ । ਲੋਕ ਗਿਣਤੀ ਦੇ ਨਾਲ ਕਰਾਚੀ ਤੋਂ ਬਾਅਦ ਲਹੌਰ ਦੂਜਾ ਸਭ ਤੋਂ ਵੱਡਾ ਸ਼ਹਿਰ ਹੈ । ਲਹੌਰ ਪਾਕਿਸਤਾਨ ਦਾ ਸਿਆਸੀ, ਰਹਤਲੀ ਤੇ ਪੜ੍ਹਾਈ ਦਾ ਗੜ੍ਹ ਹੈ ਅਤੇ ਇਸ ਲਈ ਇਹਨੂੰ ਪਾਕਿਸਤਾਨ ਦਾ ਦਿਲ ਵੀ ਕਿਹਾ ਜਾਂਦਾ ਹੈ । ਲਹੌਰ ਦਰਿਆ-ਏ-ਰਾਵੀ ਦੇ ਕੰਢੇ ਤੇ ਵਸਦਾ ਹੈ ਤੇ ਇਸਦੀ ਲੋਕ ਗਿਣਤੀ ਇੱਕ ਕਰੋੜ ਦੇ ਨੇੜੇ ਹੈ ।","shahmukhi":"لہور پاکستانی پنجاب دا دارالحکومت اے۔ لوک گنتی دے نال کراچی توں بعد لہور دوجا سبھ توں وڈا شہر اے۔ لہور پاکستان دا سیاسی، رہتلی تے پڑھائی دا گڑھ اے تے اس لئی ایھنوں پاکستان دا دل وی کیھا جاندا اے۔ لہور دریاۓ راوی دے کنڈھے تے وسدا اے اسدی لوک گنتی اک کروڑ دے نیڑے اے ۔","tranliteration":"lahor pākistān panjāb dā dārul hakūmat ē. lōk giṇtī dē nāḷ karācī tō᷈ bāad lahor dūjā sab tō᷈ vaḍḍā shahr ē. lahor pākistān dā siāsī, rahtalī tē paṛā̀ī dā gā́ṛ ē tē is laī ihnū᷈ pākistān dā dil vī kehā jāndā ē. lahor dariāē rāvī dē kanḍē tē vasdā ē. isdī lōk giṇtī ikk karōṛ dē nēṛē ē."}
, "employees": {"wc": ["෴ - 0xdf4 - 1","ණ - 0xdab - 1","් - 0xdca - 0","ණ - 0xdab - 1","្ - 0x17d2 - 0","෴ - 0xdf4 - 1","1 - 0x31 - 1","͏ - 0x34f - 0","2 - 0x32 - 1","⃝ - 0x20dd - 0"],"fancy":"1͏2⃝","v1":"γιγνώσκειν","v2":"ὦ ἄνδρες ᾿Αθηναῖοι","v1":"ახლავე გაიაროთ რეგისტრაცია","v2":"Unicode-ის მეათე საერთაშორისო","width":55,"sinhala":"෴ණ්ණ෴","width":4,"sinhala":"෴","width":1,"sinhala":"෴ණ්ණ෴෴ණ්ණ෴","width":8,"not-sinhala":"123456","tag":"ර්‍ඝ","width":2, "employee": [{"first-name":"Jim","nic-name":"\"რეგტ\"","last-name":"გთხოვთ ახ","department":431,"percent-time":90,"benefits":"full"}, {"first-name":"Terry","nic-name":"\"<one\"","last-name":"Οὐχὶ ταὐτὰ παρίσταταί μοι Jones","department":660,"percent-time":90,"benefits":"full"}, {"first-name":"Leslie","nic-name":"\"Les\"","last-name":"Patterson","department":341,"percent-time":60,"benefits":"full"}, {"first-name":"Ashley","nic-name":"\"Ash\"","last-name":"Meter & Smith","department":1440,"percent-time":40}, {"first-name":"0123456789","nic-name":"\"0123456789\"","last-name":"012345678901234567890","department":1440,"percent-time":40}, {"first-name":"ახლა","nic-name":"\"გაიარო\"","last-name":"საერთაშორისო","department":123,"percent-time":90,"benefits":"full"}, {"first-name":"෴ණ්ණ෴෴ණ්ණ෴","nic-name":"\"Mick\"","last-name":"෴ණ්ණ෴෴ණ්ණ෴෴ණ්ණ෴෴෴","department":110,"percent-time":20}]}
}
{"indian-languages": {"gurmukhi":"ਲਹੌਰ ਪਾਕਿਸਤਾਨੀ ਪੰਜਾਬ ਦੀ ਰਾਜਧਾਨੀ ਹੈ । ਲੋਕ ਗਿਣਤੀ ਦੇ ਨਾਲ ਕਰਾਚੀ ਤੋਂ ਬਾਅਦ ਲਹੌਰ ਦੂਜਾ ਸਭ ਤੋਂ ਵੱਡਾ ਸ਼ਹਿਰ ਹੈ । ਲਹੌਰ ਪਾਕਿਸਤਾਨ ਦਾ ਸਿਆਸੀ, ਰਹਤਲੀ ਤੇ ਪੜ੍ਹਾਈ ਦਾ ਗੜ੍ਹ ਹੈ ਅਤੇ ਇਸ ਲਈ ਇਹਨੂੰ ਪਾਕਿਸਤਾਨ ਦਾ ਦਿਲ ਵੀ ਕਿਹਾ ਜਾਂਦਾ ਹੈ । ਲਹੌਰ ਦਰਿਆ-ਏ-ਰਾਵੀ ਦੇ ਕੰਢੇ ਤੇ ਵਸਦਾ ਹੈ ਤੇ ਇਸਦੀ ਲੋਕ ਗਿਣਤੀ ਇੱਕ ਕਰੋੜ ਦੇ ਨੇੜੇ ਹੈ ।","shahmukhi":"لہور پاکستانی پنجاب دا دارالحکومت اے۔ لوک گنتی دے نال کراچی توں بعد لہور دوجا سبھ توں وڈا شہر اے۔ لہور پاکستان دا سیاسی، رہتلی تے پڑھائی دا گڑھ اے تے اس لئی ایھنوں پاکستان دا دل وی کیھا جاندا اے۔ لہور دریاۓ راوی دے کنڈھے تے وسدا اے اسدی لوک گنتی اک کروڑ دے نیڑے اے ۔","tranliteration":"lahor pākistān panjāb dā dārul hakūmat ē. lōk giṇtī dē nāḷ karācī tō᷈ bāad lahor dūjā sab tō᷈ vaḍḍā shahr ē. lahor pākistān dā siāsī, rahtalī tē paṛā̀ī dā gā́ṛ ē tē is laī ihnū᷈ pākistān dā dil vī kehā jāndā ē. lahor dariāē rāvī dē kanḍē tē vasdā ē. isdī lōk giṇtī ikk karōṛ dē nēṛē ē."}, "employees": {"wc": ["෴ - 0xdf4 - 1","ණ - 0xdab - 1","් - 0xdca - 0","ණ - 0xdab - 1","្ - 0x17d2 - 0","෴ - 0xdf4 - 1","1 - 0x31 - 1","͏ - 0x34f - 0","2 - 0x32 - 1","⃝ - 0x20dd - 0"],"fancy":"1͏2⃝","v1":"γιγνώσκειν","v2":"ὦ ἄνδρες ᾿Αθηναῖοι","v1":"ახლავე გაიაროთ რეგისტრაცია","v2":"Unicode-ის მეათე საერთაშორისო","width":55,"sinhala":"෴ණ්ණ෴","width":4,"sinhala":"෴","width":1,"sinhala":"෴ණ්ණ෴෴ණ්ණ෴","width":8,"not-sinhala":"123456","tag":"ර්‍ඝ","width":2, "employee": [{"first-name":"Jim","nic-name":"\"რეგტ\"","last-name":"გთხოვთ ახ","department":431,"percent-time":90,"benefits":"full"}, {"first-name":"Terry","nic-name":"\"<one\"","last-name":"Οὐχὶ ταὐτὰ παρίσταταί μοι Jones","department":660,"percent-time":90,"benefits":"full"}, {"first-name":"Leslie","nic-name":"\"Les\"","last-name":"Patterson","department":341,"percent-time":60,"benefits":"full"}, {"first-name":"Ashley","nic-name":"\"Ash\"","last-name":"Meter & Smith","department":1440,"percent-time":40}, {"first-name":"0123456789","nic-name":"\"0123456789\"","last-name":"012345678901234567890","department":1440,"percent-time":40}, {"first-name":"ახლა","nic-name":"\"გაიარო\"","last-name":"საერთაშორისო","department":123,"percent-time":90,"benefits":"full"}, {"first-name":"෴ණ්ණ෴෴ණ්ණ෴","nic-name":"\"Mick\"","last-name":"෴ණ්ණ෴෴ණ්ණ෴෴ණ්ණ෴෴෴","department":110,"percent-time":20}]}}

View File

@ -3,8 +3,7 @@
"gurmukhi": "ਲਹੌਰ ਪਾਕਿਸਤਾਨੀ ਪੰਜਾਬ ਦੀ ਰਾਜਧਾਨੀ ਹੈ । ਲੋਕ ਗਿਣਤੀ ਦੇ ਨਾਲ ਕਰਾਚੀ ਤੋਂ ਬਾਅਦ ਲਹੌਰ ਦੂਜਾ ਸਭ ਤੋਂ ਵੱਡਾ ਸ਼ਹਿਰ ਹੈ । ਲਹੌਰ ਪਾਕਿਸਤਾਨ ਦਾ ਸਿਆਸੀ, ਰਹਤਲੀ ਤੇ ਪੜ੍ਹਾਈ ਦਾ ਗੜ੍ਹ ਹੈ ਅਤੇ ਇਸ ਲਈ ਇਹਨੂੰ ਪਾਕਿਸਤਾਨ ਦਾ ਦਿਲ ਵੀ ਕਿਹਾ ਜਾਂਦਾ ਹੈ । ਲਹੌਰ ਦਰਿਆ-ਏ-ਰਾਵੀ ਦੇ ਕੰਢੇ ਤੇ ਵਸਦਾ ਹੈ ਤੇ ਇਸਦੀ ਲੋਕ ਗਿਣਤੀ ਇੱਕ ਕਰੋੜ ਦੇ ਨੇੜੇ ਹੈ ।",
"shahmukhi": "لہور پاکستانی پنجاب دا دارالحکومت اے۔ لوک گنتی دے نال کراچی توں بعد لہور دوجا سبھ توں وڈا شہر اے۔ لہور پاکستان دا سیاسی، رہتلی تے پڑھائی دا گڑھ اے تے اس لئی ایھنوں پاکستان دا دل وی کیھا جاندا اے۔ لہور دریاۓ راوی دے کنڈھے تے وسدا اے اسدی لوک گنتی اک کروڑ دے نیڑے اے ۔",
"tranliteration": "lahor pākistān panjāb dā dārul hakūmat ē. lōk giṇtī dē nāḷ karācī tō᷈ bāad lahor dūjā sab tō᷈ vaḍḍā shahr ē. lahor pākistān dā siāsī, rahtalī tē paṛā̀ī dā gā́ṛ ē tē is laī ihnū᷈ pākistān dā dil vī kehā jāndā ē. lahor dariāē rāvī dē kanḍē tē vasdā ē. isdī lōk giṇtī ikk karōṛ dē nēṛē ē."
}
,
},
"employees": {
"wc": [
"෴ - 0xdf4 - 1",

View File

@ -1,2 +1 @@
{"employees": {"employee": [{"first-name":"Terry","last-name":"Jones","department":660}, {"first-name":"Leslie","last-name":"Patterson","department":341}, {"first-name":"Ashley","last-name":"Smith","department":1440}]}
}
{"employees": {"employee": [{"first-name":"Terry","last-name":"Jones","department":660}, {"first-name":"Leslie","last-name":"Patterson","department":341}, {"first-name":"Ashley","last-name":"Smith","department":1440}]}}

View File

@ -1,2 +1 @@
{"employees": {"test": [{"filename":"(null)"}],"v1":"γιγνώσκειν","v2":"ὦ ἄνδρες ᾿Αθηναῖοι","columns":28,"columns":2,"v1":"ახლავე გაიაროთ რეგისტრაცია","v2":"Unicode-ის მეათე საერთაშორისო","columns":55,"columns":0, "employee": [{"first-name":"Jim","nic-name":"\"რეგტ\"","last-name":"გთხოვთ ახ","department":431,"percent-time":90,"columns":23,"benefits":"full"}, {"first-name":"Terry","nic-name":"\"<one\"","last-name":"Οὐχὶ ταὐτὰ παρίσταταί μοι Jones","department":660,"percent-time":90,"columns":47,"benefits":"full"}, {"first-name":"Leslie","nic-name":"\"Les\"","last-name":"Patterson","department":341,"percent-time":60,"columns":25,"benefits":"full"}, {"first-name":"Ashley","nic-name":"\"Ash\"","last-name":"Meter & Smith","department":1440,"percent-time":40,"columns":30}, {"first-name":"0123456789","nic-name":"\"0123456789\"","last-name":"012345678901234567890","department":1440,"percent-time":40,"columns":49}, {"first-name":"ახლა","nic-name":"\"გაიარო\"","last-name":"საერთაშორისო","department":123,"percent-time":90,"columns":29,"benefits":"full"}]}
}
{"employees": {"test": [{"filename":"(null)"}],"v1":"γιγνώσκειν","v2":"ὦ ἄνδρες ᾿Αθηναῖοι","columns":28,"columns":2,"v1":"ახლავე გაიაროთ რეგისტრაცია","v2":"Unicode-ის მეათე საერთაშორისო","columns":55,"columns":0, "employee": [{"first-name":"Jim","nic-name":"\"რეგტ\"","last-name":"გთხოვთ ახ","department":431,"percent-time":90,"columns":23,"benefits":"full"}, {"first-name":"Terry","nic-name":"\"<one\"","last-name":"Οὐχὶ ταὐτὰ παρίσταταί μοι Jones","department":660,"percent-time":90,"columns":47,"benefits":"full"}, {"first-name":"Leslie","nic-name":"\"Les\"","last-name":"Patterson","department":341,"percent-time":60,"columns":25,"benefits":"full"}, {"first-name":"Ashley","nic-name":"\"Ash\"","last-name":"Meter & Smith","department":1440,"percent-time":40,"columns":30}, {"first-name":"0123456789","nic-name":"\"0123456789\"","last-name":"012345678901234567890","department":1440,"percent-time":40,"columns":49}, {"first-name":"ახლა","nic-name":"\"გაიარო\"","last-name":"საერთაშორისო","department":123,"percent-time":90,"columns":29,"benefits":"full"}]}}

View File

@ -1,2 +1 @@
{"top": {"data": {"contents": {"item": [{"name":"gum","count":1412}, {"name":"rope","count":85}, {"name":"ladder","count":0}, {"name":"bolt","count":4123}, {"name":"water","count":17}]}}, "data2": {"contents": {"item": [{"name":"gum","count":1412}, {"name":"rope","count":85}, {"name":"ladder","count":0}, {"name":"bolt","count":4123}, {"name":"water","count":17}]}}, "data3": {"contents": {"item": [{"name":"gum","count":1412}, {"name":"rope","count":85}, {"name":"ladder","count":0}, {"name":"bolt","count":4123}, {"name":"water","count":17,"test":"one"}]}}, "data4": {"contents": {"item": [{"name":"gum","count":1412, "sub": [{"name":0,"next":1}, {"name":1,"next":2}, {"name":2,"next":3}],"last":3}, {"name":"rope","count":85, "sub": [{"name":0,"next":1}, {"name":1,"next":2}, {"name":2,"next":3}],"last":3}, {"name":"ladder","count":0, "sub": [{"name":0,"next":1}, {"name":1,"next":2}, {"name":2,"next":3}],"last":3}, {"name":"bolt","count":4123, "sub": [{"name":0,"next":1}, {"name":1,"next":2}, {"name":2,"next":3}],"last":3}, {"name":"water","count":17, "sub": [{"name":0,"next":1}, {"name":1,"next":2}, {"name":2,"next":3}],"last":3,"test":"one"}]}}}
}
{"top": {"data": {"contents": {"item": [{"name":"gum","count":1412}, {"name":"rope","count":85}, {"name":"ladder","count":0}, {"name":"bolt","count":4123}, {"name":"water","count":17}]}}, "data2": {"contents": {"item": [{"name":"gum","count":1412}, {"name":"rope","count":85}, {"name":"ladder","count":0}, {"name":"bolt","count":4123}, {"name":"water","count":17}]}}, "data3": {"contents": {"item": [{"name":"gum","count":1412}, {"name":"rope","count":85}, {"name":"ladder","count":0}, {"name":"bolt","count":4123}, {"name":"water","count":17,"test":"one"}]}}, "data4": {"contents": {"item": [{"name":"gum","count":1412, "sub": [{"name":0,"next":1}, {"name":1,"next":2}, {"name":2,"next":3}],"last":3}, {"name":"rope","count":85, "sub": [{"name":0,"next":1}, {"name":1,"next":2}, {"name":2,"next":3}],"last":3}, {"name":"ladder","count":0, "sub": [{"name":0,"next":1}, {"name":1,"next":2}, {"name":2,"next":3}],"last":3}, {"name":"bolt","count":4123, "sub": [{"name":0,"next":1}, {"name":1,"next":2}, {"name":2,"next":3}],"last":3}, {"name":"water","count":17, "sub": [{"name":0,"next":1}, {"name":1,"next":2}, {"name":2,"next":3}],"last":3,"test":"one"}]}}}}

View File

@ -1,2 +1 @@
{"top": {"data": {"contents": {"name": ["gum","rope","ladder","bolt","water"]}, "contents": {"item": ["gum","rope","ladder","bolt","water"]}, "contents": {"item": ["gum","rope","ladder","bolt","water"],"total":"six","one":"one", "two": ["two"],"three":"three"}}}
}
{"top": {"data": {"contents": {"name": ["gum","rope","ladder","bolt","water"]}, "contents": {"item": ["gum","rope","ladder","bolt","water"]}, "contents": {"item": ["gum","rope","ladder","bolt","water"],"total":"six","one":"one", "two": ["two"],"three":"three"}}}}

View File

@ -1,2 +1 @@
{"__version": "3.1.4", "top": {"data": {"item": [],"data":"bold","data":"bold-ul","data":"triple","data":"inv-ul","data":"underline","data":"plain", "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}]}, "data": {"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}]}, "data": {"item": [{"sku":"GRO-000-533","name":"fish","sold":1321.0,"in-stock":45,"on-order":1}]}, "data": {"item": ["gum","rope","ladder","bolt","water"]},"cost":425,"cost":455}
}
{"__version": "3.1.4", "top": {"data": {"item": [],"data":"bold","data":"bold-ul","data":"triple","data":"inv-ul","data":"underline","data":"plain", "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}]}, "data": {"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}]}, "data": {"item": [{"sku":"GRO-000-533","name":"fish","sold":1321.0,"in-stock":45,"on-order":1}]}, "data": {"item": ["gum","rope","ladder","bolt","water"]},"cost":425,"cost":455}}

View File

@ -14,5 +14,4 @@
{{test-program: }}
{{An application 1011 log entry}}
{"__version": "3.1.4", "top": {}
}
{"__version": "3.1.4", "top": {}}

View File

@ -0,0 +1,4 @@
test_12.test: invalid XML tag name: '2by4'
test_12.test: invalid XML tag name: '4x4'
test_12.test: invalid XML tag name: '2morrow'
test_12.test: invalid XML tag name: '2by4'

View File

@ -83,6 +83,10 @@ op content: [time] [2:15] [0]
op string: [hand] [left] [0]
op string: [color] [blue] [0]
op content: [time] [3:45] [0]
op open_container: [2by4] [] [0x4040010]
op string: [4x4] [truck] [0]
op string: [2morrow] [tomorrow] [0]
op close_container: [2by4] [] [0]
op close_instance: [thing] [] [0]
op close_list: [thing] [] [0]
op close_container: [data] [] [0]

View File

@ -0,0 +1,4 @@
test_12.test: invalid XML tag name: '2by4'
test_12.test: invalid XML tag name: '4x4'
test_12.test: invalid XML tag name: '2morrow'
test_12.test: invalid XML tag name: '2by4'

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,4 @@
test_12.test: invalid XML tag name: '2by4'
test_12.test: invalid XML tag name: '4x4'
test_12.test: invalid XML tag name: '2morrow'
test_12.test: invalid XML tag name: '2by4'

View File

@ -167,3 +167,9 @@
<div class="text"> til </div>
<div class="data" data-tag="time" data-xpath="/top/data/thing[name = 'thing']/time">03:45</div>
</div>
<div class="line">
<div class="text">There is </div>
<div class="data" data-tag="4x4" data-xpath="/top/data/thing[name = 'thing']/2by4/4x4">truck</div>
<div class="text"> in </div>
<div class="data" data-tag="2morrow" data-xpath="/top/data/thing[name = 'thing']/2by4/2morrow">tomorrow</div>
</div>

View File

@ -0,0 +1,4 @@
test_12.test: invalid XML tag name: '2by4'
test_12.test: invalid XML tag name: '4x4'
test_12.test: invalid XML tag name: '2morrow'
test_12.test: invalid XML tag name: '2by4'

View File

@ -167,3 +167,9 @@
<div class="text"> til </div>
<div class="data" data-tag="time">03:45</div>
</div>
<div class="line">
<div class="text">There is </div>
<div class="data" data-tag="4x4">truck</div>
<div class="text"> in </div>
<div class="data" data-tag="2morrow">tomorrow</div>
</div>

View File

@ -0,0 +1,4 @@
test_12.test: invalid XML tag name: '2by4'
test_12.test: invalid XML tag name: '4x4'
test_12.test: invalid XML tag name: '2morrow'
test_12.test: invalid XML tag name: '2by4'

View File

@ -1,2 +1 @@
{"top": {"data": {"animal":"fish","animal":"fish", "thing": [{"name":"thing","color":"green","time":"2:15","hand":"left","color":"blue","time":"3:45"}, {"name":"thing","color":"green","time":"2:15","hand":"left","color":"blue","time":"3:45"}, {"name":"thing","color":"green","time":"2:15","hand":"left","color":"blue","time":"3:45"}, {"name":"thing","color":"green","time":"2:15","hand":"left","color":"blue","time":"3:45"}, {"name":"thing","color":"green","time":"2:15","hand":"left","color":"blue","time":"3:45"}, {"name":"thing","color":"green","time":"2:15","hand":"left","color":"blue","time":"3:45"}, {"name":"thing","color":"green","time":"2:15","hand":"left","color":"blue","time":"3:45"}, {"name":"thing","color":"green","time":"2:15","hand":"left","color":"blue","time":"3:45"}, {"name":"thing","color":"green","time":"2:15","hand":"left","color":"blue","time":"3:45"}, {"name":"thing","color":"green","time":"2:15","hand":"left","color":"blue","time":"3:45"}]}}
}
{"top": {"data": {"animal":"fish","animal":"fish", "thing": [{"name":"thing","color":"green","time":"2:15","hand":"left","color":"blue","time":"3:45"}, {"name":"thing","color":"green","time":"2:15","hand":"left","color":"blue","time":"3:45"}, {"name":"thing","color":"green","time":"2:15","hand":"left","color":"blue","time":"3:45"}, {"name":"thing","color":"green","time":"2:15","hand":"left","color":"blue","time":"3:45"}, {"name":"thing","color":"green","time":"2:15","hand":"left","color":"blue","time":"3:45"}, {"name":"thing","color":"green","time":"2:15","hand":"left","color":"blue","time":"3:45"}, {"name":"thing","color":"green","time":"2:15","hand":"left","color":"blue","time":"3:45"}, {"name":"thing","color":"green","time":"2:15","hand":"left","color":"blue","time":"3:45"}, {"name":"thing","color":"green","time":"2:15","hand":"left","color":"blue","time":"3:45"}, {"name":"thing","color":"green","time":"2:15","hand":"left","color":"blue","time":"3:45", "2by4": {"4x4":"truck","2morrow":"tomorrow"}}]}}}

View File

@ -0,0 +1,4 @@
test_12.test: invalid XML tag name: '2by4'
test_12.test: invalid XML tag name: '4x4'
test_12.test: invalid XML tag name: '2morrow'
test_12.test: invalid XML tag name: '2by4'

View File

@ -82,7 +82,11 @@
"time": "2:15",
"hand": "left",
"color": "blue",
"time": "3:45"
"time": "3:45",
"2by4": {
"4x4": "truck",
"2morrow": "tomorrow"
}
}
]
}

View File

@ -0,0 +1,4 @@
test_12.test: invalid XML tag name: '2by4'
test_12.test: invalid XML tag name: '4x4'
test_12.test: invalid XML tag name: '2morrow'
test_12.test: invalid XML tag name: '2by4'

View File

@ -20,3 +20,4 @@ The thing is green til 02:15
My left hand is blue til 03:45
The thing is green til 02:15
My left hand is blue til 03:45
There is truck in tomorrow

View File

@ -0,0 +1,4 @@
test_12.test: invalid XML tag name: '2by4'
test_12.test: invalid XML tag name: '4x4'
test_12.test: invalid XML tag name: '2morrow'
test_12.test: invalid XML tag name: '2by4'

View File

@ -1 +1 @@
<top><data><animal>fish</animal><animal>fish</animal><thing><name>thing</name><color>green</color><time>2:15</time><hand>left</hand><color>blue</color><time>3:45</time></thing><thing><name>thing</name><color>green</color><time>2:15</time><hand>left</hand><color>blue</color><time>3:45</time></thing><thing><name>thing</name><color>green</color><time>2:15</time><hand>left</hand><color>blue</color><time>3:45</time></thing><thing><name>thing</name><color>green</color><time>2:15</time><hand>left</hand><color>blue</color><time>3:45</time></thing><thing><name>thing</name><color>green</color><time>2:15</time><hand>left</hand><color>blue</color><time>3:45</time></thing><thing><name>thing</name><color>green</color><time>2:15</time><hand>left</hand><color>blue</color><time>3:45</time></thing><thing><name>thing</name><color>green</color><time>2:15</time><hand>left</hand><color>blue</color><time>3:45</time></thing><thing><name>thing</name><color>green</color><time>2:15</time><hand>left</hand><color>blue</color><time>3:45</time></thing><thing><name>thing</name><color>green</color><time>2:15</time><hand>left</hand><color>blue</color><time>3:45</time></thing><thing><name>thing</name><color>green</color><time>2:15</time><hand>left</hand><color>blue</color><time>3:45</time></thing></data></top>
<top><data><animal>fish</animal><animal>fish</animal><thing><name>thing</name><color>green</color><time>2:15</time><hand>left</hand><color>blue</color><time>3:45</time></thing><thing><name>thing</name><color>green</color><time>2:15</time><hand>left</hand><color>blue</color><time>3:45</time></thing><thing><name>thing</name><color>green</color><time>2:15</time><hand>left</hand><color>blue</color><time>3:45</time></thing><thing><name>thing</name><color>green</color><time>2:15</time><hand>left</hand><color>blue</color><time>3:45</time></thing><thing><name>thing</name><color>green</color><time>2:15</time><hand>left</hand><color>blue</color><time>3:45</time></thing><thing><name>thing</name><color>green</color><time>2:15</time><hand>left</hand><color>blue</color><time>3:45</time></thing><thing><name>thing</name><color>green</color><time>2:15</time><hand>left</hand><color>blue</color><time>3:45</time></thing><thing><name>thing</name><color>green</color><time>2:15</time><hand>left</hand><color>blue</color><time>3:45</time></thing><thing><name>thing</name><color>green</color><time>2:15</time><hand>left</hand><color>blue</color><time>3:45</time></thing><thing><name>thing</name><color>green</color><time>2:15</time><hand>left</hand><color>blue</color><time>3:45</time><_2by4><_4x4>truck</_4x4><_2morrow>tomorrow</_2morrow></_2by4></thing></data></top>

View File

@ -0,0 +1,4 @@
test_12.test: invalid XML tag name: '2by4'
test_12.test: invalid XML tag name: '4x4'
test_12.test: invalid XML tag name: '2morrow'
test_12.test: invalid XML tag name: '2by4'

View File

@ -81,6 +81,10 @@
<hand>left</hand>
<color>blue</color>
<time>3:45</time>
<_2by4>
<_4x4>truck</_4x4>
<_2morrow>tomorrow</_2morrow>
</_2by4>
</thing>
</data>
</top>

View File

@ -78,6 +78,11 @@ main (int argc, char **argv)
xo_emit_f(flags, fmt2, "left", "blue", "blue", 3, 45);
}
xo_open_container("2by4");
xo_emit("There is {:4x4} in {:2morrow}\n", "truck", "tomorrow");
xo_close_container("2by4");
xo_close_container("data");
xo_close_container_h(NULL, "top");

View File

@ -460,4 +460,4 @@ msgstr "Eviouspray ownerway iedday"
# 97 - EINTEGRITY
msgid "Integrity check failed"
msgstr "integrityyay eckchay ailedfay"
msgstr "Integrityway eckchey ailedfey"

View File

@ -1,2 +1 @@
{"top": {"adjective":"amingflay","noun":"ordsway","verb":"urningbay","owner":"ymay","target":"ouchcay","adjective":"amingflay","noun":"ordsway","verb":"urningbay","owner":"ymay","target":"ouchcay", "bytes": [0,1,2,3,4],"total":1234,"received":1234,"from":"foop","port":4321,"time":32,"received":1234,"from":"foop","port":4321,"time":32,"received":1234,"from":"foop","port":4321,"time":32,"marzlevanes":3,"version":"1.2.3","date":"Tue Jun 23 18:47:09 UTC 2015", "__warning": {"program":"gt_01.test","message":"Nableuay otay ectulatobjay orwardfay elocipingvay","verb":"ectulatobjay","error":"Ermissionpay eniedday"}, "__warning": {"program":"gt_01.test","message":"automaticyay ynchronizationsay ofyay ardinalyay ammetersgray ailedfay","style":"automaticyay","type":"ardinalyay","target":"ammetersgray","error":"Ermissionpay eniedday"},"marzlevanes":6,"windings":"otuslay-oyay-eltayay"}
}
{"top": {"adjective":"amingflay","noun":"ordsway","verb":"urningbay","owner":"ymay","target":"ouchcay","adjective":"amingflay","noun":"ordsway","verb":"urningbay","owner":"ymay","target":"ouchcay", "bytes": [0,1,2,3,4],"total":1234,"received":1234,"from":"foop","port":4321,"time":32,"received":1234,"from":"foop","port":4321,"time":32,"received":1234,"from":"foop","port":4321,"time":32,"marzlevanes":3,"version":"1.2.3","date":"Tue Jun 23 18:47:09 UTC 2015", "__warning": {"program":"gt_01.test","message":"Nableuay otay ectulatobjay orwardfay elocipingvay","verb":"ectulatobjay","error":"Ermissionpay eniedday"}, "__warning": {"program":"gt_01.test","message":"automaticyay ynchronizationsay ofyay ardinalyay ammetersgray ailedfay","style":"automaticyay","type":"ardinalyay","target":"ammetersgray","error":"Ermissionpay eniedday"},"marzlevanes":6,"windings":"otuslay-oyay-eltayay"}}

View File

@ -12,14 +12,8 @@ AM_CFLAGS = -I${top_srcdir} -I${top_srcdir}/libxo
# Ick: maintained by hand!
TEST_CASES = \
xo_01.sh
X=\
xo_02.sh \
xo_03.sh \
xo_04.sh \
xo_05.sh \
xo_06.sh
xo_01.sh \
xo_02.sh
# TEST_CASES := $(shell cd ${srcdir} ; echo *.c )

View File

@ -1 +1 @@
<div class="line"><div class="text">Item </div><div class="data" data-tag="name">one</div><div class="text"> is </div><div class="label">number</div><div class="padding"> </div><div class="data" data-tag="value">001</div><div class="text">, </div><div class="label">color</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="color">red</div></div><div class="line"><div class="text">Item </div><div class="data" data-tag="name">two</div><div class="text"> is </div><div class="label">number</div><div class="padding"> </div><div class="data" data-tag="value">002</div><div class="text">, </div><div class="label">color</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="color">blue</div></div><div class="line"><div class="text">Item </div><div class="data" data-tag="name">three</div><div class="text"> is </div><div class="label">number</div><div class="padding"> </div><div class="data" data-tag="value">003</div><div class="text">, </div><div class="label">color</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="color">green</div></div><div class="line"><div class="text">Item </div><div class="data" data-tag="name">four</div><div class="text"> is </div><div class="label">number</div><div class="padding"> </div><div class="data" data-tag="value">004</div><div class="text">, </div><div class="label">color</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="color">yellow</div></div><div class="padding"> </div><div class="line"><div class="data" data-tag="address">0xdeadbeef</div><div class="text">..</div><div class="data" data-tag="foo">1</div></div><div class="padding"> </div><div class="line"><div class="data" data-tag="address">0xdeadbeef</div><div class="text">..</div><div class="data" data-tag="foo">1</div></div><div class="padding"> </div><div class="line"><div class="data" data-tag="address">0xdeadbeef</div><div class="text">..</div><div class="data" data-tag="foo">1</div></div><div class="padding"> </div><div class="line"><div class="data" data-tag="address">0xdeadbeef</div><div class="text">..</div><div class="data" data-tag="foo">1</div></div>
<div class="line"><div class="text">Item </div><div class="data" data-tag="name">one</div><div class="text"> is </div><div class="label">number</div><div class="padding"> </div><div class="data" data-tag="value">001</div><div class="text">, </div><div class="label">color</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="color">red</div></div><div class="line"><div class="text">Item </div><div class="data" data-tag="name">two</div><div class="text"> is </div><div class="label">number</div><div class="padding"> </div><div class="data" data-tag="value">002</div><div class="text">, </div><div class="label">color</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="color">blue</div></div><div class="line"><div class="text">Item </div><div class="data" data-tag="name">three</div><div class="text"> is </div><div class="label">number</div><div class="padding"> </div><div class="data" data-tag="value">003</div><div class="text">, </div><div class="label">color</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="color">green</div></div><div class="line"><div class="text">Item </div><div class="data" data-tag="name">four</div><div class="text"> is </div><div class="label">number</div><div class="padding"> </div><div class="data" data-tag="value">004</div><div class="text">, </div><div class="label">color</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="color">yellow</div></div><div class="padding"> </div><div class="line"><div class="data" data-tag="address">0xdeadbeef</div><div class="text">..</div><div class="data" data-tag="foo">1</div></div><div class="padding"> </div><div class="line"><div class="data" data-tag="address">0xdeadbeef</div><div class="text">..</div><div class="data" data-tag="foo">1</div></div><div class="padding"> </div><div class="line"><div class="data" data-tag="address">0xdeadbeef</div><div class="text">..</div><div class="data" data-tag="foo">1</div></div><div class="padding"> </div><div class="line"><div class="data" data-tag="address">0xdeadbeef</div><div class="text">..</div><div class="data" data-tag="foo">1</div></div><div class="line"><div class="text">partial line</div><div class="text"> -- rest of line</div></div>

View File

@ -74,3 +74,7 @@
<div class="text">..</div>
<div class="data" data-tag="foo" data-xpath="/anchor/foo">1</div>
</div>
<div class="line">
<div class="text">partial line</div>
<div class="text"> -- rest of line</div>
</div>

View File

@ -74,3 +74,7 @@
<div class="text">..</div>
<div class="data" data-tag="foo">1</div>
</div>
<div class="line">
<div class="text">partial line</div>
<div class="text"> -- rest of line</div>
</div>

View File

@ -1 +1 @@
"top": {"item": {"name":"one","value":1,"color":"red"}, "item": {"name":"two","value":2,"color":"blue"}, "item": {"name":"three","value":3,"color":"green"}, "item": {"name":"four","value":4,"color":"yellow"}, "anchor": {"address":"0xdeadbeef","foo":1}, "anchor": {"address":"0xdeadbeef","foo":1}, "anchor": {"address":"0xdeadbeef","foo":1}, "anchor": {"address":"0xdeadbeef","foo":1}}
"top": {"item": {"name":"one","value":1,"color":"red"}, "item": {"name":"two","value":2,"color":"blue"}, "item": {"name":"three","value":3,"color":"green"}, "item": {"name":"four","value":4,"color":"yellow"}, "anchor": {"address":"0xdeadbeef","foo":1}, "anchor": {"address":"0xdeadbeef","foo":1}, "anchor": {"address":"0xdeadbeef","foo":1}, "anchor": {"address":"0xdeadbeef","foo":1}}

View File

@ -35,4 +35,4 @@
"address": "0xdeadbeef",
"foo": 1
}
}
}

View File

@ -6,3 +6,4 @@ Item four is number 004, color: yellow
0xdeadbeef..1
0xdeadbeef..1
0xdeadbeef..1
partial line -- rest of line

View File

@ -0,0 +1,25 @@
Usage: xo [options] format [fields]
--close <path> Close tags for the given path
--close-instance <name> Close an open instance name
--close-list <name> Close an open list name
--continuation OR -C Output belongs on same line as previous output
--depth <num> Set the depth for pretty printing
--help Display this help text
--html OR -H Generate HTML output
--json OR -J Generate JSON output
--leading-xpath <path> OR -l <path> Add a prefix to generated XPaths (HTML)
--not-first Indicate this object is not the first (JSON)
--open <path> Open tags for the given path
--open-instance <name> Open an instance given by name
--open-list <name> Open a list given by name
--option <opts> -or -O <opts> Give formatting options
--pretty OR -p Make 'pretty' output (add indent, newlines)
--style <style> OR -s <style> Generate given style (xml, json, text, html)
--text OR -T Generate text output (the default style)
--top-wrap Generate a top-level object wrapper (JSON)
--version Display version information
--warn OR -W Display warnings in text on stderr
--warn-xml Display warnings in xml on stdout
--wrap <path> Wrap output in a set of containers
--xml OR -X Generate XML output
--xpath Add XPath data to HTML output

View File

@ -0,0 +1 @@
<div class="line"><div class="text">The capital of </div><div class="data" data-tag="state">North Carolina</div><div class="text"> is </div><div class="data" data-tag="city">Raleigh</div></div><div class="line"><div class="text">The capital of </div><div class="data" data-tag="state">North Carolina</div><div class="text"> is </div><div class="data" data-tag="city">Raleigh</div></div><div class="line"><div class="text">The capital of </div><div class="data" data-tag="state">North Carolina</div><div class="text"> is </div><div class="data" data-tag="city">Raleigh</div></div><div class="line"><div class="text">The capital of </div><div class="data" data-tag="state">North Carolina</div><div class="text"> is </div><div class="data" data-tag="city">Raleigh</div></div><div class="line"><div class="text">The capital of </div><div class="data" data-tag="state">North Carolina</div><div class="text"> is </div><div class="data" data-tag="city">Raleigh</div></div><div class="line"><div class="text">The capital of </div><div class="data" data-tag="state">North Carolina</div><div class="text"> is </div><div class="data" data-tag="city">Raleigh</div></div><div class="line"><div class="text">The capital of </div><div class="data" data-tag="state">North Carolina</div><div class="text"> is </div><div class="data" data-tag="city">Raleigh</div></div><div class="line"><div class="text">The capital of </div><div class="data" data-tag="state">North Carolina</div><div class="text"> is </div><div class="data" data-tag="city">Raleigh</div></div><div class="line"><div class="text">test</div></div><div class="line"><div class="text">Answer:</div><div class="text">The capital of </div><div class="data" data-tag="state">North Carolina</div><div class="text"> is </div><div class="data" data-tag="city">Raleigh</div></div><div class="line"><div class="text">First </div><div class="data" data-tag="tag">value1</div><div class="text"> </div><div class="text">and then </div><div class="data" data-tag="tag">value2</div></div><div class="line"><div class="text">Machine </div><div class="data" data-tag="name">red</div><div class="text"> has </div><div class="data" data-tag="memory">55</div></div><div class="line"><div class="text">Machine </div><div class="data" data-tag="name">green</div><div class="text"> has </div><div class="data" data-tag="memory">55</div></div><div class="line"><div class="text">Machine </div><div class="data" data-tag="name">blue</div><div class="text"> has </div><div class="data" data-tag="memory">55</div></div>

View File

@ -0,0 +1,25 @@
Usage: xo [options] format [fields]
--close <path> Close tags for the given path
--close-instance <name> Close an open instance name
--close-list <name> Close an open list name
--continuation OR -C Output belongs on same line as previous output
--depth <num> Set the depth for pretty printing
--help Display this help text
--html OR -H Generate HTML output
--json OR -J Generate JSON output
--leading-xpath <path> OR -l <path> Add a prefix to generated XPaths (HTML)
--not-first Indicate this object is not the first (JSON)
--open <path> Open tags for the given path
--open-instance <name> Open an instance given by name
--open-list <name> Open a list given by name
--option <opts> -or -O <opts> Give formatting options
--pretty OR -p Make 'pretty' output (add indent, newlines)
--style <style> OR -s <style> Generate given style (xml, json, text, html)
--text OR -T Generate text output (the default style)
--top-wrap Generate a top-level object wrapper (JSON)
--version Display version information
--warn OR -W Display warnings in text on stderr
--warn-xml Display warnings in xml on stdout
--wrap <path> Wrap output in a set of containers
--xml OR -X Generate XML output
--xpath Add XPath data to HTML output

View File

@ -0,0 +1,83 @@
<div class="line">
<div class="text">The capital of </div>
<div class="data" data-tag="state" data-xpath="/a/b/c/state">North Carolina</div>
<div class="text"> is </div>
<div class="data" data-tag="city" data-xpath="/a/b/c/city">Raleigh</div>
</div>
<div class="line">
<div class="text">The capital of </div>
<div class="data" data-tag="state" data-xpath="/state">North Carolina</div>
<div class="text"> is </div>
<div class="data" data-tag="city" data-xpath="/city">Raleigh</div>
</div>
<div class="line">
<div class="text">The capital of </div>
<div class="data" data-tag="state" data-xpath="/a/b/c/state">North Carolina</div>
<div class="text"> is </div>
<div class="data" data-tag="city" data-xpath="/a/b/c/city">Raleigh</div>
</div>
<div class="line">
<div class="text">The capital of </div>
<div class="data" data-tag="state" data-xpath="/a/b/c/state">North Carolina</div>
<div class="text"> is </div>
<div class="data" data-tag="city" data-xpath="/a/b/c/city">Raleigh</div>
</div>
<div class="line">
<div class="text">The capital of </div>
<div class="data" data-tag="state" data-xpath="/d/e/f/state">North Carolina</div>
<div class="text"> is </div>
<div class="data" data-tag="city" data-xpath="/d/e/f/city">Raleigh</div>
</div>
<div class="line">
<div class="text">The capital of </div>
<div class="data" data-tag="state" data-xpath="/state">North Carolina</div>
<div class="text"> is </div>
<div class="data" data-tag="city" data-xpath="/city">Raleigh</div>
</div>
<div class="line">
<div class="text">The capital of </div>
<div class="data" data-tag="state" data-xpath="/a/b/c/state">North Carolina</div>
<div class="text"> is </div>
<div class="data" data-tag="city" data-xpath="/a/b/c/city">Raleigh</div>
</div>
<div class="line">
<div class="text">The capital of </div>
<div class="data" data-tag="state" data-xpath="/a/b/c/state">North Carolina</div>
<div class="text"> is </div>
<div class="data" data-tag="city" data-xpath="/a/b/c/city">Raleigh</div>
</div>
<div class="line">
<div class="text">test</div>
</div>
<div class="line">
<div class="text">Answer:</div>
<div class="text">The capital of </div>
<div class="data" data-tag="state" data-xpath="/state">North Carolina</div>
<div class="text"> is </div>
<div class="data" data-tag="city" data-xpath="/city">Raleigh</div>
</div>
<div class="line">
<div class="text">First </div>
<div class="data" data-tag="tag" data-xpath="/tag">value1</div>
<div class="text"> </div>
<div class="text">and then </div>
<div class="data" data-tag="tag" data-xpath="/tag">value2</div>
</div>
<div class="line">
<div class="text">Machine </div>
<div class="data" data-tag="name" data-xpath="/name">red</div>
<div class="text"> has </div>
<div class="data" data-tag="memory" data-xpath="/memory">55</div>
</div>
<div class="line">
<div class="text">Machine </div>
<div class="data" data-tag="name" data-xpath="/name">green</div>
<div class="text"> has </div>
<div class="data" data-tag="memory" data-xpath="/memory">55</div>
</div>
<div class="line">
<div class="text">Machine </div>
<div class="data" data-tag="name" data-xpath="/name">blue</div>
<div class="text"> has </div>
<div class="data" data-tag="memory" data-xpath="/memory">55</div>
</div>

View File

@ -0,0 +1,25 @@
Usage: xo [options] format [fields]
--close <path> Close tags for the given path
--close-instance <name> Close an open instance name
--close-list <name> Close an open list name
--continuation OR -C Output belongs on same line as previous output
--depth <num> Set the depth for pretty printing
--help Display this help text
--html OR -H Generate HTML output
--json OR -J Generate JSON output
--leading-xpath <path> OR -l <path> Add a prefix to generated XPaths (HTML)
--not-first Indicate this object is not the first (JSON)
--open <path> Open tags for the given path
--open-instance <name> Open an instance given by name
--open-list <name> Open a list given by name
--option <opts> -or -O <opts> Give formatting options
--pretty OR -p Make 'pretty' output (add indent, newlines)
--style <style> OR -s <style> Generate given style (xml, json, text, html)
--text OR -T Generate text output (the default style)
--top-wrap Generate a top-level object wrapper (JSON)
--version Display version information
--warn OR -W Display warnings in text on stderr
--warn-xml Display warnings in xml on stdout
--wrap <path> Wrap output in a set of containers
--xml OR -X Generate XML output
--xpath Add XPath data to HTML output

View File

@ -0,0 +1,83 @@
<div class="line">
<div class="text">The capital of </div>
<div class="data" data-tag="state">North Carolina</div>
<div class="text"> is </div>
<div class="data" data-tag="city">Raleigh</div>
</div>
<div class="line">
<div class="text">The capital of </div>
<div class="data" data-tag="state">North Carolina</div>
<div class="text"> is </div>
<div class="data" data-tag="city">Raleigh</div>
</div>
<div class="line">
<div class="text">The capital of </div>
<div class="data" data-tag="state">North Carolina</div>
<div class="text"> is </div>
<div class="data" data-tag="city">Raleigh</div>
</div>
<div class="line">
<div class="text">The capital of </div>
<div class="data" data-tag="state">North Carolina</div>
<div class="text"> is </div>
<div class="data" data-tag="city">Raleigh</div>
</div>
<div class="line">
<div class="text">The capital of </div>
<div class="data" data-tag="state">North Carolina</div>
<div class="text"> is </div>
<div class="data" data-tag="city">Raleigh</div>
</div>
<div class="line">
<div class="text">The capital of </div>
<div class="data" data-tag="state">North Carolina</div>
<div class="text"> is </div>
<div class="data" data-tag="city">Raleigh</div>
</div>
<div class="line">
<div class="text">The capital of </div>
<div class="data" data-tag="state">North Carolina</div>
<div class="text"> is </div>
<div class="data" data-tag="city">Raleigh</div>
</div>
<div class="line">
<div class="text">The capital of </div>
<div class="data" data-tag="state">North Carolina</div>
<div class="text"> is </div>
<div class="data" data-tag="city">Raleigh</div>
</div>
<div class="line">
<div class="text">test</div>
</div>
<div class="line">
<div class="text">Answer:</div>
<div class="text">The capital of </div>
<div class="data" data-tag="state">North Carolina</div>
<div class="text"> is </div>
<div class="data" data-tag="city">Raleigh</div>
</div>
<div class="line">
<div class="text">First </div>
<div class="data" data-tag="tag">value1</div>
<div class="text"> </div>
<div class="text">and then </div>
<div class="data" data-tag="tag">value2</div>
</div>
<div class="line">
<div class="text">Machine </div>
<div class="data" data-tag="name">red</div>
<div class="text"> has </div>
<div class="data" data-tag="memory">55</div>
</div>
<div class="line">
<div class="text">Machine </div>
<div class="data" data-tag="name">green</div>
<div class="text"> has </div>
<div class="data" data-tag="memory">55</div>
</div>
<div class="line">
<div class="text">Machine </div>
<div class="data" data-tag="name">blue</div>
<div class="text"> has </div>
<div class="data" data-tag="memory">55</div>
</div>

View File

@ -0,0 +1,25 @@
Usage: xo [options] format [fields]
--close <path> Close tags for the given path
--close-instance <name> Close an open instance name
--close-list <name> Close an open list name
--continuation OR -C Output belongs on same line as previous output
--depth <num> Set the depth for pretty printing
--help Display this help text
--html OR -H Generate HTML output
--json OR -J Generate JSON output
--leading-xpath <path> OR -l <path> Add a prefix to generated XPaths (HTML)
--not-first Indicate this object is not the first (JSON)
--open <path> Open tags for the given path
--open-instance <name> Open an instance given by name
--open-list <name> Open a list given by name
--option <opts> -or -O <opts> Give formatting options
--pretty OR -p Make 'pretty' output (add indent, newlines)
--style <style> OR -s <style> Generate given style (xml, json, text, html)
--text OR -T Generate text output (the default style)
--top-wrap Generate a top-level object wrapper (JSON)
--version Display version information
--warn OR -W Display warnings in text on stderr
--warn-xml Display warnings in xml on stdout
--wrap <path> Wrap output in a set of containers
--xml OR -X Generate XML output
--xpath Add XPath data to HTML output

View File

@ -0,0 +1,7 @@
{"a": {"b": {"c": {"state":"North Carolina","city":"Raleigh","state":"North Carolina","city":"Raleigh"}}}}
{"a": {"b": {"c": {"state":"North Carolina","city":"Raleigh"}}}}
{"a": {"b": {"c": {"state":"North Carolina","city":"Raleigh", "d": {"e": {"f": {"state":"North Carolina","city":"Raleigh"}}},"state":"North Carolina","city":"Raleigh"}}}}
"a": {"b": {"c": {"state":"North Carolina","city":"Raleigh"}}}{"a": {"b": {"c": {"state":"North Carolina","city":"Raleigh"}}}}
{ }
"answer": {"state":"North Carolina","city":"Raleigh"}{"top": {"data": {"tag":"value1""tag":"value2"}}}
"machine": [{"name":"red","memory":"55"}, {"name":"green","memory":"55"}, {"name":"blue","memory":"55"}]

View File

@ -0,0 +1,25 @@
Usage: xo [options] format [fields]
--close <path> Close tags for the given path
--close-instance <name> Close an open instance name
--close-list <name> Close an open list name
--continuation OR -C Output belongs on same line as previous output
--depth <num> Set the depth for pretty printing
--help Display this help text
--html OR -H Generate HTML output
--json OR -J Generate JSON output
--leading-xpath <path> OR -l <path> Add a prefix to generated XPaths (HTML)
--not-first Indicate this object is not the first (JSON)
--open <path> Open tags for the given path
--open-instance <name> Open an instance given by name
--open-list <name> Open a list given by name
--option <opts> -or -O <opts> Give formatting options
--pretty OR -p Make 'pretty' output (add indent, newlines)
--style <style> OR -s <style> Generate given style (xml, json, text, html)
--text OR -T Generate text output (the default style)
--top-wrap Generate a top-level object wrapper (JSON)
--version Display version information
--warn OR -W Display warnings in text on stderr
--warn-xml Display warnings in xml on stdout
--wrap <path> Wrap output in a set of containers
--xml OR -X Generate XML output
--xpath Add XPath data to HTML output

View File

@ -0,0 +1,84 @@
{
"a": {
"b": {
"c": {
"state": "North Carolina",
"city": "Raleigh",
"state": "North Carolina",
"city": "Raleigh"
}
}
}
}
{
"a": {
"b": {
"c": {
"state": "North Carolina",
"city": "Raleigh"
}
}
}
}
{
"a": {
"b": {
"c": {
"state": "North Carolina",
"city": "Raleigh",
"d": {
"e": {
"f": {
"state": "North Carolina",
"city": "Raleigh"
}
}
},
"state": "North Carolina",
"city": "Raleigh"
}
}
}
}
"a": {
"b": {
"c": {
"state": "North Carolina",
"city": "Raleigh"
}
}
}{
"a": {
"b": {
"c": {
"state": "North Carolina",
"city": "Raleigh"
}
}
}
}
{ }
"answer": {
"state": "North Carolina",
"city": "Raleigh"
}{
"top": {
"data": {
"tag": "value1" "tag": "value2"
}
}
}
"machine": [
{
"name": "red",
"memory": "55"
},
{
"name": "green",
"memory": "55"
},
{
"name": "blue",
"memory": "55"
}
]

View File

@ -0,0 +1,25 @@
Usage: xo [options] format [fields]
--close <path> Close tags for the given path
--close-instance <name> Close an open instance name
--close-list <name> Close an open list name
--continuation OR -C Output belongs on same line as previous output
--depth <num> Set the depth for pretty printing
--help Display this help text
--html OR -H Generate HTML output
--json OR -J Generate JSON output
--leading-xpath <path> OR -l <path> Add a prefix to generated XPaths (HTML)
--not-first Indicate this object is not the first (JSON)
--open <path> Open tags for the given path
--open-instance <name> Open an instance given by name
--open-list <name> Open a list given by name
--option <opts> -or -O <opts> Give formatting options
--pretty OR -p Make 'pretty' output (add indent, newlines)
--style <style> OR -s <style> Generate given style (xml, json, text, html)
--text OR -T Generate text output (the default style)
--top-wrap Generate a top-level object wrapper (JSON)
--version Display version information
--warn OR -W Display warnings in text on stderr
--warn-xml Display warnings in xml on stdout
--wrap <path> Wrap output in a set of containers
--xml OR -X Generate XML output
--xpath Add XPath data to HTML output

View File

@ -0,0 +1,14 @@
The capital of North Carolina is Raleigh
The capital of North Carolina is Raleigh
The capital of North Carolina is Raleigh
The capital of North Carolina is Raleigh
The capital of North Carolina is Raleigh
The capital of North Carolina is Raleigh
The capital of North Carolina is Raleigh
The capital of North Carolina is Raleigh
test
Answer:The capital of North Carolina is Raleigh
First value1 and then value2
Machine red has 55
Machine green has 55
Machine blue has 55

View File

@ -0,0 +1,25 @@
Usage: xo [options] format [fields]
--close <path> Close tags for the given path
--close-instance <name> Close an open instance name
--close-list <name> Close an open list name
--continuation OR -C Output belongs on same line as previous output
--depth <num> Set the depth for pretty printing
--help Display this help text
--html OR -H Generate HTML output
--json OR -J Generate JSON output
--leading-xpath <path> OR -l <path> Add a prefix to generated XPaths (HTML)
--not-first Indicate this object is not the first (JSON)
--open <path> Open tags for the given path
--open-instance <name> Open an instance given by name
--open-list <name> Open a list given by name
--option <opts> -or -O <opts> Give formatting options
--pretty OR -p Make 'pretty' output (add indent, newlines)
--style <style> OR -s <style> Generate given style (xml, json, text, html)
--text OR -T Generate text output (the default style)
--top-wrap Generate a top-level object wrapper (JSON)
--version Display version information
--warn OR -W Display warnings in text on stderr
--warn-xml Display warnings in xml on stdout
--wrap <path> Wrap output in a set of containers
--xml OR -X Generate XML output
--xpath Add XPath data to HTML output

View File

@ -0,0 +1 @@
<a><b><c><state>North Carolina</state><city>Raleigh</city><state>North Carolina</state><city>Raleigh</city></c></b></a><a><b><c><state>North Carolina</state><city>Raleigh</city></c></b></a><a><b><c><state>North Carolina</state><city>Raleigh</city><d><e><f><state>North Carolina</state><city>Raleigh</city></f></e></d><state>North Carolina</state><city>Raleigh</city></c></b></a><a><b><c><state>North Carolina</state><city>Raleigh</city></c></b></a><a><b><c><state>North Carolina</state><city>Raleigh</city></c></b></a><answer><state>North Carolina</state><city>Raleigh</city></answer><top><data><tag>value1</tag><tag>value2</tag></data></top><machine><name>red</name><memory>55</memory></machine><machine><name>green</name><memory>55</memory></machine><machine><name>blue</name><memory>55</memory></machine>

View File

@ -0,0 +1,25 @@
Usage: xo [options] format [fields]
--close <path> Close tags for the given path
--close-instance <name> Close an open instance name
--close-list <name> Close an open list name
--continuation OR -C Output belongs on same line as previous output
--depth <num> Set the depth for pretty printing
--help Display this help text
--html OR -H Generate HTML output
--json OR -J Generate JSON output
--leading-xpath <path> OR -l <path> Add a prefix to generated XPaths (HTML)
--not-first Indicate this object is not the first (JSON)
--open <path> Open tags for the given path
--open-instance <name> Open an instance given by name
--open-list <name> Open a list given by name
--option <opts> -or -O <opts> Give formatting options
--pretty OR -p Make 'pretty' output (add indent, newlines)
--style <style> OR -s <style> Generate given style (xml, json, text, html)
--text OR -T Generate text output (the default style)
--top-wrap Generate a top-level object wrapper (JSON)
--version Display version information
--warn OR -W Display warnings in text on stderr
--warn-xml Display warnings in xml on stdout
--wrap <path> Wrap output in a set of containers
--xml OR -X Generate XML output
--xpath Add XPath data to HTML output

View File

@ -0,0 +1,74 @@
<a>
<b>
<c>
<state>North Carolina</state>
<city>Raleigh</city>
<state>North Carolina</state>
<city>Raleigh</city>
</c>
</b>
</a>
<a>
<b>
<c>
<state>North Carolina</state>
<city>Raleigh</city>
</c>
</b>
</a>
<a>
<b>
<c>
<state>North Carolina</state>
<city>Raleigh</city>
<d>
<e>
<f>
<state>North Carolina</state>
<city>Raleigh</city>
</f>
</e>
</d>
<state>North Carolina</state>
<city>Raleigh</city>
</c>
</b>
</a>
<a>
<b>
<c>
<state>North Carolina</state>
<city>Raleigh</city>
</c>
</b>
</a>
<a>
<b>
<c>
<state>North Carolina</state>
<city>Raleigh</city>
</c>
</b>
</a>
<answer>
<state>North Carolina</state>
<city>Raleigh</city>
</answer>
<top>
<data>
<tag>value1</tag>
<tag>value2</tag>
</data>
</top>
<machine>
<name>red</name>
<memory>55</memory>
</machine>
<machine>
<name>green</name>
<memory>55</memory>
</machine>
<machine>
<name>blue</name>
<memory>55</memory>
</machine>

View File

@ -30,4 +30,7 @@ ${XOAN} "{[:/18}{:address/%p}..{:foo/%u}{]:}\n" 0xdeadbeef 1
${XOAN} "{[:/%d}{:address/%p}..{:foo/%u}{]:}\n" 18 0xdeadbeef 1
${XOAN} "{[:/%s}{:address/%p}..{:foo/%u}{]:}\n" 18 0xdeadbeef 1
${XO} "partial line"
${XO} -C " -- rest of line\n"
${XO} --close top

57
contrib/libxo/tests/xo/xo_02.sh Executable file
View File

@ -0,0 +1,57 @@
#
# $Id$
#
# Copyright 2019, 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.
XO=$1
shift
XOP="${XO} --warn"
# This is testing --wrap, --open, --close, --top-wrap, etc, so
# the output is not a single valid document
set -- 'The capital of {:state} is {:city}\n' 'North Carolina' Raleigh
${XOP} --top-wrap --open a/b/c "$@"
${XOP} --top-wrap --close a/b/c --not-first "$@"
${XOP} --top-wrap --wrap a/b/c "$@"
${XOP} --top-wrap --open a/b/c "$@"
${XOP} --depth 4 --not-first --wrap d/e/f "$@"
${XOP} --top-wrap --close a/b/c --not-first "$@"
${XOP} --wrap a/b/c "$@"
${XOP} --top-wrap --wrap a/b/c "$@"
${XOP} --top-wrap "test\n"
${XOP} --open answer
${XOP} "Answer:"
${XOP} --continuation "$@"
${XOP} --close answer
${XOP} --top-wrap --open top/data
${XOP} --depth 2 'First {:tag} ' value1
${XOP} --depth 2 --continuation 'and then {:tag}\n' value2
${XOP} --top-wrap --close top/data
${XOP} --help
${XOP} --open-list machine
NF=
for name in red green blue; do
${XOP} --depth 1 $NF --open-instance machine
${XOP} --depth 2 "Machine {k:name} has {:memory}\n" $name 55
${XOP} --depth 1 --close-instance machine
NF=--not-first
done
${XOP} $NF --close-list machine

View File

@ -36,6 +36,10 @@ using the same commands that emit text output.
.Bl -tag -width indent
.It Ic --close Ar path
Close tags for the given path
.It Ic -C | Ic --continuation
Indicates this output is a continuation of the previous output data
and should appear on the same line.
This is allows HTML output to be constructed correctly.
.It Ic --depth Ar num
Set the depth for pretty printing
.It Ic --help
@ -46,6 +50,10 @@ Generate HTML output
Generate JSON output
.It Ic --leading-xpath Ar path
Add a prefix to generated XPaths (HTML)
.It Ic --not-first
Indicate that this content is not the first in a series of sibling
objects, which is vital information for "JSON" output, which requires
a comma between such objects.
.It Ic --open Ar path
Open tags for the given path
.It Ic -p | Ic --pretty
@ -54,6 +62,9 @@ Make 'pretty' output (add indent, newlines)
Generate given style (xml, json, text, html)
.It Ic -T | Ic --text
Generate text output (the default style)
.It Ic --top-warp
Indicates the entire object should be placed inside a top-level
object wrapper, specifically when generating JSON output.
.It Ic --version
Display version information
.It Ic -W | Ic --warn

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Juniper Networks, Inc.
* Copyright (c) 2014-2018, Juniper Networks, Inc.
* All rights reserved.
* This SOFTWARE is licensed under the LICENSE provided in the
* ../Copyright file. By downloading, installing, copying, or otherwise
@ -15,6 +15,7 @@
#include "xo_config.h"
#include "xo.h"
#include "xo_explicit.h"
#include <getopt.h> /* Include after xo.h for testing */
@ -194,18 +195,25 @@ print_help (void)
fprintf(stderr,
"Usage: xo [options] format [fields]\n"
" --close <path> Close tags for the given path\n"
" --close-instance <name> Close an open instance name\n"
" --close-list <name> Close an open list name\n"
" --continuation OR -C Output belongs on same line as previous output\n"
" --depth <num> Set the depth for pretty printing\n"
" --help Display this help text\n"
" --html OR -H Generate HTML output\n"
" --json OR -J Generate JSON output\n"
" --leading-xpath <path> OR -l <path> "
"Add a prefix to generated XPaths (HTML)\n"
" --not-first Indicate this object is not the first (JSON)\n"
" --open <path> Open tags for the given path\n"
" --open-instance <name> Open an instance given by name\n"
" --open-list <name> Open a list given by name\n"
" --option <opts> -or -O <opts> Give formatting options\n"
" --pretty OR -p Make 'pretty' output (add indent, newlines)\n"
" --style <style> OR -s <style> "
"Generate given style (xml, json, text, html)\n"
" --text OR -T Generate text output (the default style)\n"
" --top-wrap Generate a top-level object wrapper (JSON)\n"
" --version Display version information\n"
" --warn OR -W Display warnings in text on stderr\n"
" --warn-xml Display warnings in xml on stdout\n"
@ -215,17 +223,25 @@ print_help (void)
}
static struct opts {
int o_close_instance;
int o_close_list;
int o_depth;
int o_help;
int o_not_first;
int o_xpath;
int o_open_instance;
int o_open_list;
int o_top_wrap;
int o_version;
int o_warn_xml;
int o_wrap;
int o_xpath;
} opts;
static struct option long_opts[] = {
{ "close", required_argument, NULL, 'c' },
{ "close-instance", required_argument, &opts.o_close_instance, 1 },
{ "close-list", required_argument, &opts.o_close_list, 1 },
{ "continuation", no_argument, NULL, 'C' },
{ "depth", required_argument, &opts.o_depth, 1 },
{ "help", no_argument, &opts.o_help, 1 },
{ "html", no_argument, NULL, 'H' },
@ -233,10 +249,13 @@ static struct option long_opts[] = {
{ "leading-xpath", required_argument, NULL, 'l' },
{ "not-first", no_argument, &opts.o_not_first, 1 },
{ "open", required_argument, NULL, 'o' },
{ "open-instance", required_argument, &opts.o_open_instance, 1 },
{ "open-list", required_argument, &opts.o_open_list, 1 },
{ "option", required_argument, NULL, 'O' },
{ "pretty", no_argument, NULL, 'p' },
{ "style", required_argument, NULL, 's' },
{ "text", no_argument, NULL, 'T' },
{ "top-wrap", no_argument, &opts.o_top_wrap, 1 },
{ "xml", no_argument, NULL, 'X' },
{ "xpath", no_argument, &opts.o_xpath, 1 },
{ "version", no_argument, &opts.o_version, 1 },
@ -252,17 +271,24 @@ main (int argc UNUSED, char **argv)
char *fmt = NULL, *cp, *np;
char *opt_opener = NULL, *opt_closer = NULL, *opt_wrapper = NULL;
char *opt_options = NULL;
char *opt_name = NULL;
xo_state_t new_state = 0;
int opt_depth = 0;
int opt_not_first = 0;
int opt_top_wrap = 0;
int rc;
argc = xo_parse_args(argc, argv);
if (argc < 0)
return 1;
while ((rc = getopt_long(argc, argv, "c:HJl:O:o:ps:TXW",
while ((rc = getopt_long(argc, argv, "Cc:HJl:O:o:ps:TXW",
long_opts, NULL)) != -1) {
switch (rc) {
case 'C':
xo_set_flags(NULL, XOF_CONTINUATION);
break;
case 'c':
opt_closer = optarg;
xo_set_flags(NULL, XOF_IGNORE_CLOSE);
@ -339,6 +365,41 @@ main (int argc UNUSED, char **argv)
} else if (opts.o_wrap) {
opt_wrapper = optarg;
} else if (opts.o_top_wrap) {
opt_top_wrap = 1;
} else if (opts.o_open_list) {
if (opt_name)
xo_errx(1, "only one open/close list/instance allowed: %s",
optarg);
opt_name = optarg;
new_state = XSS_OPEN_LIST;
} else if (opts.o_open_instance) {
if (opt_name)
xo_errx(1, "only one open/close list/instance allowed: %s",
optarg);
opt_name = optarg;
new_state = XSS_OPEN_INSTANCE;
} else if (opts.o_close_list) {
if (opt_name)
xo_errx(1, "only one open/close list/instance allowed: %s",
optarg);
opt_name = optarg;
new_state = XSS_CLOSE_LIST;
} else if (opts.o_close_instance) {
if (opt_name)
xo_errx(1, "only one open/close list/instance allowed: %s",
optarg);
opt_name = optarg;
new_state = XSS_CLOSE_INSTANCE;
} else {
print_help();
return 1;
@ -365,14 +426,34 @@ main (int argc UNUSED, char **argv)
xo_set_formatter(NULL, formatter, checkpoint);
xo_set_flags(NULL, XOF_NO_VA_ARG | XOF_NO_TOP | XOF_NO_CLOSE);
/*
* If we have some explicit state change, handle it
*/
if (new_state) {
if (opt_depth > 0)
xo_set_depth(NULL, opt_depth);
if (opt_not_first)
xo_set_flags(NULL, XOF_NOT_FIRST);
xo_explicit_transition(NULL, new_state, opt_name, 0);
xo_finish();
exit(0);
}
fmt = *argv++;
if (opt_opener == NULL && opt_closer == NULL && fmt == NULL) {
print_help();
return 1;
}
if (opt_not_first)
xo_set_flags(NULL, XOF_NOT_FIRST);
if (opt_top_wrap) {
/* If we have a closing path, we'll be one extra level deeper */
if (opt_closer && xo_get_style(NULL) == XO_STYLE_JSON)
opt_depth += 1;
else
xo_clear_flags(NULL, XOF_NO_TOP);
}
if (opt_closer) {
opt_depth += 1;
@ -388,6 +469,10 @@ main (int argc UNUSED, char **argv)
if (opt_depth > 0)
xo_set_depth(NULL, opt_depth);
if (opt_not_first)
xo_set_flags(NULL, XOF_NOT_FIRST);
/* If there's an opening hierarchy, open each element as a container */
if (opt_opener) {
for (cp = opt_opener; cp && *cp; cp = np) {
np = strchr(cp, '/');
@ -395,10 +480,11 @@ main (int argc UNUSED, char **argv)
*np = '\0';
xo_open_container(cp);
if (np)
*np++ = '/';
np += 1;
}
}
/* If there's an wrapper hierarchy, open each element as a container */
if (opt_wrapper) {
for (cp = opt_wrapper; cp && *cp; cp = np) {
np = strchr(cp, '/');
@ -406,16 +492,18 @@ main (int argc UNUSED, char **argv)
*np = '\0';
xo_open_container(cp);
if (np)
*np++ = '/';
*np++ = '/'; /* Put it back */
}
}
/* If there's a format string, call xo_emit to emit the contents */
if (fmt && *fmt) {
save_argv = argv;
prep_arg(fmt);
xo_emit(fmt);
xo_emit(fmt); /* This call does the real formatting */
}
/* If there's an wrapper hierarchy, close each element's container */
while (opt_wrapper) {
np = strrchr(opt_wrapper, '/');
xo_close_container(np ? np + 1 : opt_wrapper);
@ -425,6 +513,10 @@ main (int argc UNUSED, char **argv)
opt_wrapper = NULL;
}
/* Remember to undo the depth before calling xo_finish() */
opt_depth = (opt_closer && opt_top_wrap) ? -1 : 0;
/* If there's an closing hierarchy, close each element's container */
while (opt_closer) {
np = strrchr(opt_closer, '/');
xo_close_container(np ? np + 1 : opt_closer);
@ -434,6 +526,16 @@ main (int argc UNUSED, char **argv)
opt_closer = NULL;
}
/* If there's a closer and a wrapper, we need to clean it up */
if (opt_depth) {
xo_set_depth(NULL, opt_depth);
xo_clear_flags(NULL, XOF_NO_TOP);
}
/* If we're wrapping the entire content, skip the closer */
if (opt_top_wrap && opt_opener)
xo_set_flags(NULL, XOF_NO_TOP);
xo_finish();
return 0;

View File

@ -183,16 +183,16 @@
/* #undef LIBXO_TEXT_ONLY */
/* Version number as dotted value */
#define LIBXO_VERSION "0.9.0"
#define LIBXO_VERSION "1.0.2"
/* Version number extra information */
#define LIBXO_VERSION_EXTRA ""
/* Version number as a number */
#define LIBXO_VERSION_NUMBER 9000
#define LIBXO_VERSION_NUMBER 1000002
/* Version number as string */
#define LIBXO_VERSION_STRING "9000"
#define LIBXO_VERSION_STRING "1000002"
/* Enable local wcwidth implementation */
#define LIBXO_WCWIDTH 1
@ -210,7 +210,7 @@
#define PACKAGE_NAME "libxo"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "libxo 0.9.0"
#define PACKAGE_STRING "libxo 1.0.2"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "libxo"
@ -219,7 +219,7 @@
#define PACKAGE_URL ""
/* Define to the version of this package. */
#define PACKAGE_VERSION "0.9.0"
#define PACKAGE_VERSION "1.0.2"
/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
@ -236,7 +236,7 @@
/* #undef USE_INT_RETURN_CODES */
/* Version number of package */
#define VERSION "0.9.0"
#define VERSION "1.0.2"
/* Retain hash bucket size */
/* #undef XO_RETAIN_SIZE */

View File

@ -12,7 +12,7 @@
#
BASE=/usr/share/libxo
VERSION=0.9.0
VERSION=1.0.2
CMD=cat
DONE=
WEB=http://juniper.github.io/libxo/${VERSION}/xohtml