aboutsummaryrefslogtreecommitdiff
path: root/contrib/libxo/libxo
diff options
context:
space:
mode:
authorMarcel Moolenaar <marcel@FreeBSD.org>2015-01-19 02:22:03 +0000
committerMarcel Moolenaar <marcel@FreeBSD.org>2015-01-19 02:22:03 +0000
commit545ddfbe7d4fe8adfb862903b24eac1d5896c1ef (patch)
tree8db7c468a655beb61f455f2901342b8b7884e50d /contrib/libxo/libxo
parent9745de4c2c78da747da5ddcb58b941cef9599132 (diff)
downloadsrc-545ddfbe7d4fe8adfb862903b24eac1d5896c1ef.tar.gz
src-545ddfbe7d4fe8adfb862903b24eac1d5896c1ef.zip
Upgrade libxo to 0.2.0.
Obtained from: https://github.com/Juniper/libxo Requested by: Phil Shafer <phil@juniper.net> Revisions 276253 & 276273 were incorporated into 0.2.0. Revision 276260 has been merged-in.
Notes
Notes: svn path=/head/; revision=277353
Diffstat (limited to 'contrib/libxo/libxo')
-rw-r--r--contrib/libxo/libxo/libxo.3257
-rw-r--r--contrib/libxo/libxo/libxo.c1123
-rw-r--r--contrib/libxo/libxo/xo.h91
-rw-r--r--contrib/libxo/libxo/xo_attr.34
-rw-r--r--contrib/libxo/libxo/xo_create.342
-rw-r--r--contrib/libxo/libxo/xo_emit.315
-rw-r--r--contrib/libxo/libxo/xo_err.323
-rw-r--r--contrib/libxo/libxo/xo_error.364
-rw-r--r--contrib/libxo/libxo/xo_finish.320
-rw-r--r--contrib/libxo/libxo/xo_flush.323
-rw-r--r--contrib/libxo/libxo/xo_format.5335
-rw-r--r--contrib/libxo/libxo/xo_no_setlocale.337
-rw-r--r--contrib/libxo/libxo/xo_open_container.358
-rw-r--r--contrib/libxo/libxo/xo_open_list.355
-rw-r--r--contrib/libxo/libxo/xo_parse_args.388
-rw-r--r--contrib/libxo/libxo/xo_set_allocator.321
-rw-r--r--contrib/libxo/libxo/xo_set_flags.3106
-rw-r--r--contrib/libxo/libxo/xo_set_info.351
-rw-r--r--contrib/libxo/libxo/xo_set_options.319
-rw-r--r--contrib/libxo/libxo/xo_set_style.321
-rw-r--r--contrib/libxo/libxo/xo_set_writer.330
-rw-r--r--contrib/libxo/libxo/xoconfig.h12
-rw-r--r--contrib/libxo/libxo/xoconfig.h.in6
-rw-r--r--contrib/libxo/libxo/xoversion.h6
24 files changed, 1923 insertions, 584 deletions
diff --git a/contrib/libxo/libxo/libxo.3 b/contrib/libxo/libxo/libxo.3
index fca0774eb134..f9b0e6f8b2a9 100644
--- a/contrib/libxo/libxo/libxo.3
+++ b/contrib/libxo/libxo/libxo.3
@@ -7,7 +7,7 @@
.\" # LICENSE.
.\" # Phil Shafer, July 2014
.\"
-.Dd July, 2014
+.Dd December 8, 2014
.Dt LIBXO 3
.Os
.Sh NAME
@@ -19,58 +19,82 @@
.In libxo/xo.h
.Sh DESCRIPTION
The functions defined in
-.Lb libxo
+.Nm
are used to generate a choice of
.Em TEXT ,
.Em XML ,
.Em JSON ,
or
.Em HTML
-output. A common set of functions are used, with
+output.
+A common set of functions are used, with
command line switches passed to the library to control the details of
the output.
.Pp
-Most commands emit text output aimed at humans. It is designed
-to be parsed and understood by a user. Humans are gifted at extracted
-details and pattern matching. Often programmers need to extract
-information from this human-oriented output. Programmers use tools
-like grep, awk, and regular expressions to ferret out the pieces of
-information they need. Such solutions are fragile and require
+Most commands emit text output aimed at humans.
+It is designed
+to be parsed and understood by a user.
+Humans are gifted at extracting
+details and pattern matching.
+Often programmers need to extract
+information from this human-oriented output.
+Programmers use tools
+like
+.Xr grep 1 ,
+.Xr awk 1 ,
+and regular expressions to ferret out the pieces of
+information they need.
+Such solutions are fragile and require
updates when output contents change or evolve, requiring testing and
validation.
.Pp
-Modern tool developers favors encoding schemes like XML and JSON,
-which allow trivial parsing and extraction of data. Such formats are
+Modern tool developers favor encoding schemes like XML and JSON,
+which allow trivial parsing and extraction of data.
+Such formats are
simple, well understood, hierarchical, easily parsed, and often
integrate easier with common tools and environments.
.Pp
In addition, modern reality means that more output ends up in web
browsers than in terminals, making HTML output valuable.
.Pp
-.Em libxo
+.Nm
allows a single set of function calls in source code to generate
-traditional text output, as well as XML and JSON formatted data. HTML
+traditional text output, as well as XML and JSON formatted data.
+HTML
can also be generated; "<div>" elements surround the traditional text
output, with attributes that detail how to render the data.
.Pp
-There are four encoding styles supported by libxo: TEXT, HTML, JSON,
-and XML. JSON and XML are suitable for encoding data, while TEXT and
-HTML are suited for display to the user. TEXT output can be display
+There are four encoding styles supported by
+.Nm :
+TEXT, HTML, JSON,
+and XML.
+JSON and XML are suitable for encoding data, while TEXT and
+HTML are suited for display to the user.
+TEXT output can be display
on a terminal session, allowing compatibility with traditional usage.
HTML can be matched with a small CSS file to permit rendering in any
-HTML5 browser. XML output is suitable for tools like XPath and
-protocols like NETCONF. JSON output can be used for RESTful APIs.
+HTML5 browser.
+XML output is suitable for tools like XPath and
+protocols like NETCONF.
+JSON output can be used for RESTful APIs.
.Pp
The
-.Em libxo
+.Nm
library allows an application to generate text, XML, JSON,
-and HTML output using a common set of function calls. The application
-decides at run time which output style should be produced. The
+and HTML output using a common set of function calls.
+The application
+decides at run time which output style should be produced.
+The
application calls a function
-.Fn xo_emit
+.Xr xo_emit 3
to product output that is
-described in a format string. A "field descriptor" tells libxo what
-the field is and what it means. Each field descriptor is placed in
+described in a format string.
+A
+.Dq field descriptor
+tells
+.Nm
+what the field is and what it means.
+Each field descriptor is placed in
braces with a printf-like format string:
.Bd -literal -offset indent
xo_emit(" {:lines/%7ju} {:words/%7ju} "
@@ -79,55 +103,199 @@ braces with a printf-like format string:
.Ed
.Pp
Each field can have a role, with the 'value' role being the default,
-and the role tells libxo how and when to render that field, as well as
+and the role tells
+.Nm
+how and when to render that field, as well as
a
-.Xr printf 3 -like
+.Xr printf 3 Ns -like
format string.
.Pp
Output
can then be generated in various style, using the "--libxo" option.
.Sh DEFAULT HANDLE
-Handles give an abstraction for libxo that encapsulates the state of a
-stream of output. Handles have the data type "xo_handle_t" and are
+Handles give an abstraction for
+.Nm
+that encapsulates the state of a
+stream of output.
+Handles have the data type "xo_handle_t" and are
opaque to the caller.
-
+.Pp
The library has a default handle that is automatically initialized.
By default, this handle will send text style output to standard output.
-The xo_set_style and xo_set_flags functions can be used to change this
+The
+.Xr xo_set_style 3
+and
+.Xr xo_set_flags 3
+functions can be used to change this
behavior.
-
-Many libxo functions take a handle as their first parameter; most that
-do not use the default handle. Any function taking a handle can
-be passed NULL to access the default handle.
-
+.Pp
+Many
+.Nm
+functions take a handle as their first parameter; most that
+do not use the default handle.
+Any function taking a handle can
+be passed
+.Dv NULL
+to access the default handle.
+.Pp
For the typical command that is generating output on standard output,
there is no need to create an explicit handle, but they are available
-when needed, e.g. for daemons that generate multiple streams of
+when needed, e.g., for daemons that generate multiple streams of
output.
+.Sh FUNCTION OVERVIEW
+The
+.Nm
+library includes the following functions:
+.Bl -tag -width "xo_close_container_hd"
+.It Sy "Function Description"
+.It Fn xo_attr
+.It Fn xo_attr_h
+.It Fn xo_attr_hv
+Allows the caller to emit XML attributes with the next open element.
+.It Fn xo_create
+.It Fn xo_create_to_file
+Allow the caller to create a new handle.
+Note that
+.Nm
+has a default handle that allows the caller to avoid use of an
+explicitly created handle.
+Only callers writing to files other than
+.Dv stdout
+would need to call
+.Fn xo_create .
+.It Fn xo_destroy
+Frees any resources associated with the handle, including the handle
+itself.
+.It Fn xo_emit
+.It Fn xo_emit_h
+.It Fn xo_emit_hv
+Emit formatted output.
+The
+.Fa fmt
+string controls the conversion of the remaining arguments into
+formatted output.
+See
+.Xr xo_format 5
+for details.
+.It Fn xo_warn
+.It Fn xo_warnx
+.It Fn xo_warn_c
+.It Fn xo_warn_hc
+.It Fn xo_err
+.It Fn xo_errc
+.It Fn xo_errx
+.It Fn xo_message
+.It Fn xo_message_c
+.It Fn xo_message_hc
+.It Fn xo_message_hcv
+These functions are meant to be compatible with their standard libc namesakes.
+.It Fn xo_finish
+.It Fn xo_finish_h
+Flush output, close open construct, and complete any pending
+operations.
+.It Fn xo_flush
+.It Fn xo_flush_h
+Allow the caller to flush any pending output for a handle.
+.It Fn xo_no_setlocale
+Direct
+.Nm
+to avoid initializing the locale.
+This function should be called before any other
+.Nm
+function is called.
+.It Fn xo_open_container
+.It Fn xo_open_container_h
+.It Fn xo_open_container_hd
+.It Fn xo_open_container_d
+.It Fn xo_close_container
+.It Fn xo_close_container_h
+.It Fn xo_close_container_hd
+.It Fn xo_close_container_d
+Containers a singleton levels of hierarchy, typically used to organize
+related content.
+.It Fn xo_open_list_h
+.It Fn xo_open_list
+.It Fn xo_open_list_hd
+.It Fn xo_open_list_d
+.It Fn xo_open_instance_h
+.It Fn xo_open_instance
+.It Fn xo_open_instance_hd
+.It Fn xo_open_instance_d
+.It Fn xo_close_instance_h
+.It Fn xo_close_instance
+.It Fn xo_close_instance_hd
+.It Fn xo_close_instance_d
+.It Fn xo_close_list_h
+.It Fn xo_close_list
+.It Fn xo_close_list_hd
+.It Fn xo_close_list_d
+Lists are levels of hierarchy that can appear multiple times within
+the same parent.
+Two calls are needed to encapsulate them, one for
+the list and one for each instance of that list.
+Typically
+.Fn xo_open_list
+and
+.Fn xo_close_list
+are called outside a
+for-loop, where
+.Fn xo_open_instance
+it called at the top of the loop, and
+.Fn xo_close_instance
+is called at the bottom of the loop.
+.It Fn xo_parse_args
+Inspects command line arguments for directions to
+.Nm .
+This function should be called before
+.Va argv
+is inspected by the application.
+.It Fn xo_set_allocator
+Instructs
+.Nm
+to use an alternative memory allocator and deallocator.
+.It Fn xo_set_flags
+.It Fn xo_clear_flags
+Change the flags set for a handle.
+.It Fn xo_set_info
+Provides additional information about elements for use with HTML
+rendering.
+.It Fn xo_set_options
+Changes formatting options used by handle.
+.It Fn xo_set_style
+.It Fn xo_set_style_name
+Changes the output style used by a handle.
+.It Fn xo_set_writer
+Instructs
+.Nm
+to use an alternative set of low-level output functions.
+.El
.Sh ADDITIONAL DOCUMENTATION
-.Pp
Complete documentation can be found on github:
.Bd -literal -offset indent
http://juniper.github.io/libxo/libxo-manual.html
.Ed
.Pp
-libxo lives on github as:
+.Nm
+lives on github as:
.Bd -literal -offset indent
https://github.com/Juniper/libxo
.Ed
.Pp
-The latest release of libxo is available at:
+The latest release of
+.Nm
+is available at:
.Bd -literal -offset indent
https://github.com/Juniper/libxo/releases
.Ed
.Sh SEE ALSO
+.Xr xo 1 ,
+.Xr xolint 1 ,
.Xr xo_attr 3 ,
.Xr xo_create 3 ,
.Xr xo_emit 3 ,
.Xr xo_err 3 ,
.Xr xo_finish 3 ,
.Xr xo_flush 3 ,
-.Xr xo_format 5 ,
.Xr xo_no_setlocale 3 ,
.Xr xo_open_container 3 ,
.Xr xo_open_list 3 ,
@@ -138,12 +306,11 @@ https://github.com/Juniper/libxo/releases
.Xr xo_set_options 3 ,
.Xr xo_set_style 3 ,
.Xr xo_set_writer 3 ,
-.Xr xo 1 ,
-and
-.Xr xolint 1 .
+.Xr xo_format 5
.Sh HISTORY
The
-.Fa libxo
-library was added in FreeBSD 11.0.
+.Nm
+library was added in
+.Fx 11.0 .
.Sh AUTHOR
Phil Shafer
diff --git a/contrib/libxo/libxo/libxo.c b/contrib/libxo/libxo/libxo.c
index 2c9733773378..e9d05ce0ceb3 100644
--- a/contrib/libxo/libxo/libxo.c
+++ b/contrib/libxo/libxo/libxo.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Juniper Networks, Inc.
+ * Copyright (c) 2014-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
@@ -11,6 +11,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
+#include <unistd.h>
#include <stddef.h>
#include <wchar.h>
#include <locale.h>
@@ -27,6 +28,10 @@
#include "xo.h"
#include "xoversion.h"
+#ifdef HAVE_STDIO_EXT_H
+#include <stdio_ext.h>
+#endif /* HAVE_STDIO_EXT_H */
+
const char xo_version[] = LIBXO_VERSION;
const char xo_version_extra[] = LIBXO_VERSION_EXTRA;
@@ -58,6 +63,52 @@ typedef unsigned xo_xsf_flags_t; /* XSF_* flags */
#define XSF_INSTANCE (1<<2) /* Frame is an instance */
#define XSF_DTRT (1<<3) /* Save the name for DTRT mode */
+#define XSF_CONTENT (1<<4) /* Some content has been emitted */
+#define XSF_EMIT (1<<5) /* Some field has been emitted */
+#define XSF_EMIT_KEY (1<<6) /* A key has been emitted */
+#define XSF_EMIT_LEAF_LIST (1<<7) /* A leaf-list field has been emitted */
+
+/* These are the flags we propagate between markers and their parents */
+#define XSF_MARKER_FLAGS \
+ (XSF_NOT_FIRST | XSF_CONTENT | XSF_EMIT | XSF_EMIT_KEY | XSF_EMIT_LEAF_LIST )
+
+/*
+ * A word about states: We're moving to 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 event, since they
+ * function rather like both. None of the XO_CLOSE_* events will
+ * persist as states, since their 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;
+#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))
+
/*
* xo_stack_t: As we open and close containers and levels, we
* create a stack of frames to track them. This is needed for
@@ -65,6 +116,7 @@ typedef unsigned xo_xsf_flags_t; /* XSF_* flags */
*/
typedef struct xo_stack_s {
xo_xsf_flags_t xs_flags; /* Flags for this frame */
+ xo_state_t xs_state; /* State for this stack frame */
char *xs_name; /* Name (for XPath value) */
char *xs_keys; /* XPath predicate for any key fields */
} xo_stack_t;
@@ -74,12 +126,13 @@ typedef struct xo_stack_s {
* It's used as a store for state, options, and content.
*/
struct xo_handle_s {
- unsigned long xo_flags; /* Flags */
+ xo_xof_flags_t xo_flags; /* Flags */
unsigned short xo_style; /* XO_STYLE_* value */
unsigned short xo_indent; /* Indent level (if pretty) */
unsigned short xo_indent_by; /* Indent amount (tab stop) */
xo_write_func_t xo_write; /* Write callback */
xo_close_func_t xo_close; /* Close callback */
+ xo_flush_func_t xo_flush; /* Flush callback */
xo_formatter_t xo_formatter; /* Custom formating function */
xo_checkpointer_t xo_checkpointer; /* Custom formating support function */
void *xo_opaque; /* Opaque data for write function */
@@ -197,7 +250,7 @@ typedef struct xo_format_s {
static xo_handle_t xo_default_handle;
static int xo_default_inited;
static int xo_locale_inited;
-static char *xo_program;
+static const char *xo_program;
/*
* To allow libxo to be used in diverse environment, we allow the
@@ -210,6 +263,10 @@ static xo_free_func_t xo_free = free;
static void
xo_failure (xo_handle_t *xop, const char *fmt, ...);
+static int
+xo_transition (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name,
+ xo_state_t new_state);
+
static void
xo_buf_append_div (xo_handle_t *xop, const char *class, xo_xff_flags_t flags,
const char *name, int nlen,
@@ -226,6 +283,7 @@ static int
xo_write_to_file (void *opaque, const char *data)
{
FILE *fp = (FILE *) opaque;
+
return fprintf(fp, "%s", data);
}
@@ -236,10 +294,22 @@ static void
xo_close_file (void *opaque)
{
FILE *fp = (FILE *) opaque;
+
fclose(fp);
}
/*
+ * Callback to flush a FILE pointer
+ */
+static int
+xo_flush_file (void *opaque)
+{
+ FILE *fp = (FILE *) opaque;
+
+ return fflush(fp);
+}
+
+/*
* Initialize the contents of an xo_buffer_t.
*/
static void
@@ -291,6 +361,29 @@ xo_no_setlocale (void)
}
/*
+ * We need to decide if stdout is line buffered (_IOLBF). Lacking a
+ * standard way to decide this (e.g. getlinebuf()), we have configure
+ * look to find __flbf, which glibc supported. If not, we'll rely
+ * on isatty, with the assumption that terminals are the only thing
+ * that's line buffered. We _could_ test for "steam._flags & _IOLBF",
+ * which is all __flbf does, but that's even tackier. Like a
+ * bedazzled Elvis outfit on an ugly lap dog sort of tacky. Not
+ * something we're willing to do.
+ */
+static int
+xo_is_line_buffered (FILE *stream)
+{
+#if HAVE___FLBF
+ if (__flbf(stream))
+ return 1;
+#else /* HAVE___FLBF */
+ if (isatty(fileno(stream)))
+ return 1;
+#endif /* HAVE___FLBF */
+ return 0;
+}
+
+/*
* Initialize an xo_handle_t, using both static defaults and
* the global settings from the LIBXO_OPTIONS environment
* variable.
@@ -300,6 +393,10 @@ xo_init_handle (xo_handle_t *xop)
{
xop->xo_opaque = stdout;
xop->xo_write = xo_write_to_file;
+ xop->xo_flush = xo_flush_file;
+
+ if (xo_is_line_buffered(stdout))
+ xop->xo_flags |= XOF_FLUSH_LINE;
/*
* We need to initialize the locale, which isn't really pretty.
@@ -415,7 +512,7 @@ xo_indent (xo_handle_t *xop)
rc += xop->xo_indent_by;
}
- return rc;
+ return (rc > 0) ? rc : 0;
}
static void
@@ -500,9 +597,9 @@ xo_escape_json (xo_buffer_t *xbp, int len)
char *cp, *ep, *ip;
for (cp = xbp->xb_curp, ep = cp + len; cp < ep; cp++) {
- if (*cp == '\\')
+ if (*cp == '\\' || *cp == '"')
delta += 1;
- else if (*cp == '"')
+ else if (*cp == '\n' || *cp == '\r')
delta += 1;
}
@@ -519,13 +616,18 @@ xo_escape_json (xo_buffer_t *xbp, int len)
cp -= 1;
ip -= 1;
- if (*cp != '\\' && *cp != '"') {
+ if (*cp == '\\' || *cp == '"') {
+ *ip-- = *cp;
+ *ip = '\\';
+ } else if (*cp == '\n') {
+ *ip-- = 'n';
+ *ip = '\\';
+ } else if (*cp == '\r') {
+ *ip-- = 'r';
+ *ip = '\\';
+ } else {
*ip = *cp;
- continue;
}
-
- *ip-- = *cp;
- *ip = '\\';
} while (cp > ep && cp != ip);
@@ -572,20 +674,23 @@ xo_buf_escape (xo_handle_t *xop, xo_buffer_t *xbp,
* Write the current contents of the data buffer using the handle's
* xo_write function.
*/
-static void
+static int
xo_write (xo_handle_t *xop)
{
+ int rc = 0;
xo_buffer_t *xbp = &xop->xo_data;
if (xbp->xb_curp != xbp->xb_bufp) {
xo_buf_append(xbp, "", 1); /* Append ending NUL */
xo_anchor_clear(xop);
- xop->xo_write(xop->xo_opaque, xbp->xb_bufp);
+ rc = xop->xo_write(xop->xo_opaque, xbp->xb_bufp);
xbp->xb_curp = xbp->xb_bufp;
}
/* Turn off the flags that don't survive across writes */
xop->xo_flags &= ~(XOF_UNITS_PENDING);
+
+ return rc;
}
/*
@@ -947,7 +1052,7 @@ xo_warn_hcv (xo_handle_t *xop, int code, int check_warn,
int len = strlen(fmt);
int plen = xo_program ? strlen(xo_program) : 0;
- char *newfmt = alloca(len + 2 + plen + 2); /* newline, NUL, and ": " */
+ char *newfmt = alloca(len + 1 + plen + 2); /* NUL, and ": " */
if (plen) {
memcpy(newfmt, xo_program, plen);
@@ -955,7 +1060,6 @@ xo_warn_hcv (xo_handle_t *xop, int code, int check_warn,
newfmt[plen++] = ' ';
}
memcpy(newfmt + plen, fmt, len);
-
newfmt[len + plen] = '\0';
if (xop->xo_flags & XOF_WARN_XML) {
@@ -994,7 +1098,7 @@ xo_warn_hcv (xo_handle_t *xop, int code, int check_warn,
xo_buf_append(xbp, msg_close, sizeof(msg_close) - 1);
xo_buf_append(xbp, err_close, sizeof(err_close) - 1);
- if (code > 0) {
+ if (code >= 0) {
const char *msg = strerror(code);
if (msg) {
xo_buf_append(xbp, ": ", 2);
@@ -1003,11 +1107,16 @@ xo_warn_hcv (xo_handle_t *xop, int code, int check_warn,
}
xo_buf_append(xbp, "\n", 2); /* Append newline and NUL to string */
- xo_write(xop);
+ (void) xo_write(xop);
} else {
vfprintf(stderr, newfmt, vap);
- fprintf(stderr, ": %s\n", strerror(code));
+ if (code >= 0) {
+ const char *msg = strerror(code);
+ if (msg)
+ fprintf(stderr, ": %s", msg);
+ }
+ fprintf(stderr, "\n");
}
}
@@ -1027,7 +1136,7 @@ xo_warn_c (int code, const char *fmt, ...)
va_list vap;
va_start(vap, fmt);
- xo_warn_hcv(NULL, 0, code, fmt, vap);
+ xo_warn_hcv(NULL, code, 0, fmt, vap);
va_end(vap);
}
@@ -1149,7 +1258,7 @@ xo_message_hcv (xo_handle_t *xop, int code, const char *fmt, va_list vap)
xo_buf_append(xbp, msg_close, sizeof(msg_close) - 1);
if (need_nl)
xo_buf_append(xbp, "\n", 2); /* Append newline and NUL to string */
- xo_write(xop);
+ (void) xo_write(xop);
break;
case XO_STYLE_HTML:
@@ -1211,7 +1320,7 @@ xo_message_hcv (xo_handle_t *xop, int code, const char *fmt, va_list vap)
break;
}
- xo_flush_h(xop);
+ (void) xo_flush_h(xop);
}
void
@@ -1299,6 +1408,7 @@ xo_create_to_file (FILE *fp, xo_style_t style, xo_xof_flags_t flags)
xop->xo_opaque = fp;
xop->xo_write = xo_write_to_file;
xop->xo_close = xo_close_file;
+ xop->xo_flush = xo_flush_file;
}
return xop;
@@ -1323,7 +1433,7 @@ xo_destroy (xo_handle_t *xop_arg)
xo_buf_cleanup(&xop->xo_attrs);
if (xop_arg == NULL) {
- bzero(&xo_default_handle, sizeof(&xo_default_handle));
+ bzero(&xo_default_handle, sizeof(xo_default_handle));
xo_default_inited = 0;
} else
xo_free(xop);
@@ -1451,6 +1561,10 @@ xo_set_options (xo_handle_t *xop, const char *input)
xop->xo_flags |= XOF_FLUSH;
break;
+ case 'F':
+ xop->xo_flags |= XOF_FLUSH_LINE;
+ break;
+
case 'H':
xop->xo_style = XO_STYLE_HTML;
break;
@@ -1651,6 +1765,33 @@ xo_clear_flags (xo_handle_t *xop, xo_xof_flags_t flags)
xop->xo_flags &= ~flags;
}
+static const char *
+xo_state_name (xo_state_t state)
+{
+ static const char *names[] = {
+ "init",
+ "open_container",
+ "close_container",
+ "open_list",
+ "close_list",
+ "open_instance",
+ "close_instance",
+ "open_leaf_list",
+ "close_leaf_list",
+ "discarding",
+ "marker",
+ "emit",
+ "emit_leaf_list",
+ "finish",
+ NULL
+ };
+
+ if (state < (sizeof(names) / sizeof(names[0])))
+ return names[state];
+
+ return "unknown";
+}
+
static void
xo_line_ensure_open (xo_handle_t *xop, xo_xff_flags_t flags UNUSED)
{
@@ -1867,14 +2008,20 @@ xo_format_string_direct (xo_handle_t *xop, xo_buffer_t *xbp,
goto done_with_encoding; /* Need multi-level 'break' */
case XO_STYLE_JSON:
- if (wc != '\\' && wc != '"')
+ if (wc != '\\' && wc != '"' && wc != '\n' && wc != '\r')
break;
if (!xo_buf_has_room(xbp, 2))
return -1;
*xbp->xb_curp++ = '\\';
- *xbp->xb_curp++ = wc & 0x7f;
+ if (wc == '\n')
+ wc = 'n';
+ else if (wc == '\r')
+ wc = 'r';
+ else wc = wc & 0x7f;
+
+ *xbp->xb_curp++ = wc;
goto done_with_encoding;
}
@@ -2550,6 +2697,15 @@ xo_buf_append_div (xo_handle_t *xop, const char *class, xo_xff_flags_t flags,
if (xsp->xs_name == NULL)
continue;
+ /*
+ * XSS_OPEN_LIST and XSS_OPEN_LEAF_LIST stack frames
+ * are directly under XSS_OPEN_INSTANCE frames so we
+ * don't need to put these in our XPath expressions.
+ */
+ if (xsp->xs_state == XSS_OPEN_LIST
+ || xsp->xs_state == XSS_OPEN_LEAF_LIST)
+ continue;
+
xo_data_append(xop, "/", 1);
xo_data_escape(xop, xsp->xs_name, strlen(xsp->xs_name));
if (xsp->xs_keys) {
@@ -2615,6 +2771,11 @@ xo_format_title (xo_handle_t *xop, const char *str, int len,
static char div_open[] = "<div class=\"title\">";
static char div_close[] = "</div>";
+ if (flen == 0) {
+ fmt = "%s";
+ flen = 2;
+ }
+
switch (xop->xo_style) {
case XO_STYLE_XML:
case XO_STYLE_JSON:
@@ -2748,6 +2909,75 @@ xo_format_value (xo_handle_t *xop, const char *name, int nlen,
int quote;
xo_buffer_t *xbp;
+ /*
+ * Before we emit a value, we need to know that the frame is ready.
+ */
+ xo_stack_t *xsp = &xop->xo_stack[xop->xo_depth];
+
+ if (flags & XFF_LEAF_LIST) {
+ /*
+ * Check if we've already started to emit normal leafs
+ * or if we're not in a leaf list.
+ */
+ if ((xsp->xs_flags & (XSF_EMIT | XSF_EMIT_KEY))
+ || !(xsp->xs_flags & XSF_EMIT_LEAF_LIST)) {
+ char nbuf[nlen + 1];
+ memcpy(nbuf, name, nlen);
+ nbuf[nlen] = '\0';
+
+ int rc = xo_transition(xop, 0, nbuf, XSS_EMIT_LEAF_LIST);
+ if (rc < 0)
+ flags |= XFF_DISPLAY_ONLY | XFF_ENCODE_ONLY;
+ else
+ xop->xo_stack[xop->xo_depth].xs_flags |= XSF_EMIT_LEAF_LIST;
+ }
+
+ xsp = &xop->xo_stack[xop->xo_depth];
+ if (xsp->xs_name) {
+ name = xsp->xs_name;
+ nlen = strlen(name);
+ }
+
+ } else if (flags & XFF_KEY) {
+ /* Emitting a 'k' (key) field */
+ if ((xsp->xs_flags & XSF_EMIT) && !(flags & XFF_DISPLAY_ONLY)) {
+ xo_failure(xop, "key field emitted after normal value field: '%.*s'",
+ nlen, name);
+
+ } else if (!(xsp->xs_flags & XSF_EMIT_KEY)) {
+ char nbuf[nlen + 1];
+ memcpy(nbuf, name, nlen);
+ nbuf[nlen] = '\0';
+
+ int rc = xo_transition(xop, 0, nbuf, XSS_EMIT);
+ if (rc < 0)
+ flags |= XFF_DISPLAY_ONLY | XFF_ENCODE_ONLY;
+ else
+ xop->xo_stack[xop->xo_depth].xs_flags |= XSF_EMIT_KEY;
+
+ xsp = &xop->xo_stack[xop->xo_depth];
+ xsp->xs_flags |= XSF_EMIT_KEY;
+ }
+
+ } else {
+ /* Emitting a normal value field */
+ if ((xsp->xs_flags & XSF_EMIT_LEAF_LIST)
+ || !(xsp->xs_flags & XSF_EMIT)) {
+ char nbuf[nlen + 1];
+ memcpy(nbuf, name, nlen);
+ nbuf[nlen] = '\0';
+
+ int rc = xo_transition(xop, 0, nbuf, XSS_EMIT);
+ if (rc < 0)
+ flags |= XFF_DISPLAY_ONLY | XFF_ENCODE_ONLY;
+ else
+ xop->xo_stack[xop->xo_depth].xs_flags |= XSF_EMIT;
+
+ xsp = &xop->xo_stack[xop->xo_depth];
+ xsp->xs_flags |= XSF_EMIT;
+ }
+ }
+
switch (xop->xo_style) {
case XO_STYLE_TEXT:
if (flags & XFF_ENCODE_ONLY)
@@ -3157,13 +3387,15 @@ xo_do_emit (xo_handle_t *xop, const char *fmt)
const char *cp, *sp, *ep, *basep;
char *newp = NULL;
int flush = (xop->xo_flags & XOF_FLUSH) ? 1 : 0;
+ int flush_line = (xop->xo_flags & XOF_FLUSH_LINE) ? 1 : 0;
xop->xo_columns = 0; /* Always reset it */
for (cp = fmt; *cp; ) {
if (*cp == '\n') {
xo_line_close(xop);
- xo_flush_h(xop);
+ if (flush_line && xo_flush_h(xop) < 0)
+ return -1;
cp += 1;
continue;
@@ -3375,42 +3607,53 @@ xo_do_emit (xo_handle_t *xop, const char *fmt)
return -1;
}
- if (format == NULL && ftype != '[' && ftype != ']' ) {
- format = "%s";
- flen = 2;
- }
+ if (ftype == 0 || ftype == 'V') {
+ if (format == NULL) {
+ /* Default format for value fields is '%s' */
+ format = "%s";
+ flen = 2;
+ }
- if (ftype == 0 || ftype == 'V')
xo_format_value(xop, content, clen, format, flen,
encoding, elen, flags);
- else if (ftype == 'D')
- xo_format_content(xop, "decoration", NULL, 1,
- content, clen, format, flen);
- else if (ftype == 'E')
- xo_format_content(xop, "error", "error", 0,
- content, clen, format, flen);
- else if (ftype == 'L')
- xo_format_content(xop, "label", NULL, 1,
- content, clen, format, flen);
- else if (ftype == 'N')
- xo_format_content(xop, "note", NULL, 1,
- content, clen, format, flen);
- else if (ftype == 'P')
- xo_format_content(xop, "padding", NULL, 1,
- content, clen, format, flen);
- else if (ftype == 'T')
- xo_format_title(xop, content, clen, format, flen);
- else if (ftype == 'U') {
- if (flags & XFF_WS)
- xo_format_content(xop, "padding", NULL, 1, " ", 1, NULL, 0);
- xo_format_units(xop, content, clen, format, flen);
- } else if (ftype == 'W')
- xo_format_content(xop, "warning", "warning", 0,
- content, clen, format, flen);
- else if (ftype == '[')
- xo_anchor_start(xop, content, clen, format, flen);
+
+ } else if (ftype == '[')
+ xo_anchor_start(xop, content, clen, format, flen);
else if (ftype == ']')
- xo_anchor_stop(xop, content, clen, format, flen);
+ xo_anchor_stop(xop, content, clen, format, flen);
+
+ else if (clen || format) { /* Need either content or format */
+ if (format == NULL) {
+ /* Default format for value fields is '%s' */
+ format = "%s";
+ flen = 2;
+ }
+
+ if (ftype == 'D')
+ xo_format_content(xop, "decoration", NULL, 1,
+ content, clen, format, flen);
+ else if (ftype == 'E')
+ xo_format_content(xop, "error", "error", 0,
+ content, clen, format, flen);
+ else if (ftype == 'L')
+ xo_format_content(xop, "label", NULL, 1,
+ content, clen, format, flen);
+ else if (ftype == 'N')
+ xo_format_content(xop, "note", NULL, 1,
+ content, clen, format, flen);
+ else if (ftype == 'P')
+ xo_format_content(xop, "padding", NULL, 1,
+ content, clen, format, flen);
+ else if (ftype == 'T')
+ xo_format_title(xop, content, clen, format, flen);
+ else if (ftype == 'U') {
+ if (flags & XFF_WS)
+ xo_format_content(xop, "padding", NULL, 1, " ", 1, NULL, 0);
+ xo_format_units(xop, content, clen, format, flen);
+ } else if (ftype == 'W')
+ xo_format_content(xop, "warning", "warning", 0,
+ content, clen, format, flen);
+ }
if (flags & XFF_COLON)
xo_format_content(xop, "decoration", NULL, 1, ":", 1, NULL, 0);
@@ -3425,8 +3668,12 @@ xo_do_emit (xo_handle_t *xop, const char *fmt)
}
/* If we don't have an anchor, write the text out */
- if (flush && !(xop->xo_flags & XOF_ANCHOR))
- xo_write(xop);
+ if (flush && !(xop->xo_flags & XOF_ANCHOR)) {
+ if (xo_write(xop) < 0)
+ rc = -1; /* Report failure */
+ else if (xop->xo_flush && xop->xo_flush(xop->xo_opaque) < 0)
+ rc = -1;
+ }
return (rc < 0) ? rc : (int) xop->xo_columns;
}
@@ -3549,8 +3796,11 @@ xo_stack_set_flags (xo_handle_t *xop)
static void
xo_depth_change (xo_handle_t *xop, const char *name,
- int delta, int indent, xo_xsf_flags_t flags)
+ int delta, int indent, xo_state_t state, xo_xsf_flags_t flags)
{
+ if (xop->xo_style == XO_STYLE_HTML || xop->xo_style == XO_STYLE_TEXT)
+ indent = 0;
+
if (xop->xo_flags & XOF_DTRT)
flags |= XSF_DTRT;
@@ -3560,18 +3810,17 @@ xo_depth_change (xo_handle_t *xop, const char *name,
xo_stack_t *xsp = &xop->xo_stack[xop->xo_depth + delta];
xsp->xs_flags = flags;
+ xsp->xs_state = state;
xo_stack_set_flags(xop);
- unsigned save = (xop->xo_flags & (XOF_XPATH | XOF_WARN | XOF_DTRT));
- save |= (flags & XSF_DTRT);
+ if (name == NULL)
+ name = XO_FAILURE_NAME;
- if (name && save) {
- int len = strlen(name) + 1;
- char *cp = xo_realloc(NULL, len);
- if (cp) {
- memcpy(cp, name, len);
- xsp->xs_name = cp;
- }
+ int len = strlen(name) + 1;
+ char *cp = xo_realloc(NULL, len);
+ if (cp) {
+ memcpy(cp, name, len);
+ xsp->xs_name = cp;
}
} else { /* Pop operation */
@@ -3636,10 +3885,8 @@ xo_stack_flags (unsigned xflags)
}
static int
-xo_open_container_hf (xo_handle_t *xop, xo_xof_flags_t flags, const char *name)
+xo_do_open_container (xo_handle_t *xop, xo_xof_flags_t flags, const char *name)
{
- xop = xo_default(xop);
-
int rc = 0;
const char *ppn = (xop->xo_flags & XOF_PRETTY) ? "\n" : "";
const char *pre_nl = "";
@@ -3653,9 +3900,16 @@ xo_open_container_hf (xo_handle_t *xop, xo_xof_flags_t flags, const char *name)
switch (xop->xo_style) {
case XO_STYLE_XML:
- rc = xo_printf(xop, "%*s<%s>%s", xo_indent(xop), "",
- name, ppn);
- xo_depth_change(xop, name, 1, 1, xo_stack_flags(flags));
+ rc = xo_printf(xop, "%*s<%s", xo_indent(xop), "", name);
+
+ if (xop->xo_attrs.xb_curp != xop->xo_attrs.xb_bufp) {
+ rc += xop->xo_attrs.xb_curp - xop->xo_attrs.xb_bufp;
+ xo_data_append(xop, xop->xo_attrs.xb_bufp,
+ xop->xo_attrs.xb_curp - xop->xo_attrs.xb_bufp);
+ xop->xo_attrs.xb_curp = xop->xo_attrs.xb_bufp;
+ }
+
+ rc += xo_printf(xop, ">%s", ppn);
break;
case XO_STYLE_JSON:
@@ -3674,18 +3928,21 @@ xo_open_container_hf (xo_handle_t *xop, xo_xof_flags_t flags, const char *name)
rc = xo_printf(xop, "%s%*s\"%s\": {%s",
pre_nl, xo_indent(xop), "", name, ppn);
- xo_depth_change(xop, name, 1, 1, xo_stack_flags(flags));
- break;
-
- case XO_STYLE_HTML:
- case XO_STYLE_TEXT:
- xo_depth_change(xop, name, 1, 0, xo_stack_flags(flags));
break;
}
+ xo_depth_change(xop, name, 1, 1, XSS_OPEN_CONTAINER,
+ xo_stack_flags(flags));
+
return rc;
}
+static int
+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);
+}
+
int
xo_open_container_h (xo_handle_t *xop, const char *name)
{
@@ -3710,8 +3967,8 @@ xo_open_container_d (const char *name)
return xo_open_container_hf(NULL, XOF_DTRT, name);
}
-int
-xo_close_container_h (xo_handle_t *xop, const char *name)
+static int
+xo_do_close_container (xo_handle_t *xop, const char *name)
{
xop = xo_default(xop);
@@ -3721,8 +3978,6 @@ xo_close_container_h (xo_handle_t *xop, const char *name)
if (name == NULL) {
xo_stack_t *xsp = &xop->xo_stack[xop->xo_depth];
- if (!(xsp->xs_flags & XSF_DTRT))
- xo_failure(xop, "missing name without 'dtrt' mode");
name = xsp->xs_name;
if (name) {
@@ -3731,13 +3986,15 @@ xo_close_container_h (xo_handle_t *xop, const char *name)
char *cp = alloca(len);
memcpy(cp, name, len);
name = cp;
- } else
+ } else if (!(xsp->xs_flags & XSF_DTRT)) {
+ xo_failure(xop, "missing name without 'dtrt' mode");
name = XO_FAILURE_NAME;
+ }
}
switch (xop->xo_style) {
case XO_STYLE_XML:
- xo_depth_change(xop, name, -1, -1, 0);
+ xo_depth_change(xop, name, -1, -1, XSS_CLOSE_CONTAINER, 0);
rc = xo_printf(xop, "%*s</%s>%s", xo_indent(xop), "", name, ppn);
break;
@@ -3745,14 +4002,14 @@ xo_close_container_h (xo_handle_t *xop, const char *name)
pre_nl = (xop->xo_flags & XOF_PRETTY) ? "\n" : "";
ppn = (xop->xo_depth <= 1) ? "\n" : "";
- xo_depth_change(xop, name, -1, -1, 0);
+ xo_depth_change(xop, name, -1, -1, XSS_CLOSE_CONTAINER, 0);
rc = xo_printf(xop, "%s%*s}%s", pre_nl, xo_indent(xop), "", ppn);
xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST;
break;
case XO_STYLE_HTML:
case XO_STYLE_TEXT:
- xo_depth_change(xop, name, -1, 0, 0);
+ xo_depth_change(xop, name, -1, 0, XSS_CLOSE_CONTAINER, 0);
break;
}
@@ -3760,6 +4017,12 @@ xo_close_container_h (xo_handle_t *xop, const char *name)
}
int
+xo_close_container_h (xo_handle_t *xop, const char *name)
+{
+ return xo_transition(xop, 0, name, XSS_CLOSE_CONTAINER);
+}
+
+int
xo_close_container (const char *name)
{
return xo_close_container_h(NULL, name);
@@ -3778,42 +4041,52 @@ xo_close_container_d (void)
}
static int
-xo_open_list_hf (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name)
+xo_do_open_list (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name)
{
+ int rc = 0;
+ int indent = 0;
+
xop = xo_default(xop);
- if (xop->xo_style != XO_STYLE_JSON)
- return 0;
+ if (xop->xo_style == XO_STYLE_JSON) {
+ const char *ppn = (xop->xo_flags & XOF_PRETTY) ? "\n" : "";
+ const char *pre_nl = "";
- int rc = 0;
- const char *ppn = (xop->xo_flags & XOF_PRETTY) ? "\n" : "";
- const char *pre_nl = "";
+ indent = 1;
+ if (!(xop->xo_flags & XOF_NO_TOP)) {
+ if (!(xop->xo_flags & XOF_TOP_EMITTED)) {
+ xo_printf(xop, "%*s{%s", xo_indent(xop), "", ppn);
+ xop->xo_flags |= XOF_TOP_EMITTED;
+ }
+ }
- if (!(xop->xo_flags & XOF_NO_TOP)) {
- if (!(xop->xo_flags & XOF_TOP_EMITTED)) {
- xo_printf(xop, "%*s{%s", xo_indent(xop), "", ppn);
- xop->xo_flags |= XOF_TOP_EMITTED;
+ if (name == NULL) {
+ xo_failure(xop, "NULL passed for list name");
+ name = XO_FAILURE_NAME;
}
- }
- if (name == NULL) {
- xo_failure(xop, "NULL passed for list name");
- name = XO_FAILURE_NAME;
- }
+ xo_stack_set_flags(xop);
- xo_stack_set_flags(xop);
+ if (xop->xo_stack[xop->xo_depth].xs_flags & XSF_NOT_FIRST)
+ pre_nl = (xop->xo_flags & XOF_PRETTY) ? ",\n" : ", ";
+ xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST;
- if (xop->xo_stack[xop->xo_depth].xs_flags & XSF_NOT_FIRST)
- pre_nl = (xop->xo_flags & XOF_PRETTY) ? ",\n" : ", ";
- xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST;
+ rc = xo_printf(xop, "%s%*s\"%s\": [%s",
+ pre_nl, xo_indent(xop), "", name, ppn);
+ }
- rc = xo_printf(xop, "%s%*s\"%s\": [%s",
- pre_nl, xo_indent(xop), "", name, ppn);
- xo_depth_change(xop, name, 1, 1, XSF_LIST | xo_stack_flags(flags));
+ xo_depth_change(xop, name, 1, indent, XSS_OPEN_LIST,
+ XSF_LIST | xo_stack_flags(flags));
return rc;
}
+static int
+xo_open_list_hf (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name)
+{
+ return xo_transition(xop, flags, name, XSS_OPEN_LIST);
+}
+
int
xo_open_list_h (xo_handle_t *xop, const char *name UNUSED)
{
@@ -3838,21 +4111,14 @@ xo_open_list_d (const char *name)
return xo_open_list_hf(NULL, XOF_DTRT, name);
}
-int
-xo_close_list_h (xo_handle_t *xop, const char *name)
+static int
+xo_do_close_list (xo_handle_t *xop, const char *name)
{
int rc = 0;
const char *pre_nl = "";
- xop = xo_default(xop);
-
- if (xop->xo_style != XO_STYLE_JSON)
- return 0;
-
if (name == NULL) {
xo_stack_t *xsp = &xop->xo_stack[xop->xo_depth];
- if (!(xsp->xs_flags & XSF_DTRT))
- xo_failure(xop, "missing name without 'dtrt' mode");
name = xsp->xs_name;
if (name) {
@@ -3861,22 +4127,36 @@ xo_close_list_h (xo_handle_t *xop, const char *name)
char *cp = alloca(len);
memcpy(cp, name, len);
name = cp;
- } else
+ } else if (!(xsp->xs_flags & XSF_DTRT)) {
+ xo_failure(xop, "missing name without 'dtrt' mode");
name = XO_FAILURE_NAME;
+ }
}
- if (xop->xo_stack[xop->xo_depth].xs_flags & XSF_NOT_FIRST)
- pre_nl = (xop->xo_flags & XOF_PRETTY) ? "\n" : "";
- xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST;
+ if (xop->xo_style == XO_STYLE_JSON) {
+ if (xop->xo_stack[xop->xo_depth].xs_flags & XSF_NOT_FIRST)
+ pre_nl = (xop->xo_flags & XOF_PRETTY) ? "\n" : "";
+ xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST;
- xo_depth_change(xop, name, -1, -1, XSF_LIST);
- rc = xo_printf(xop, "%s%*s]", pre_nl, xo_indent(xop), "");
- xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST;
+ xo_depth_change(xop, name, -1, -1, XSS_CLOSE_LIST, XSF_LIST);
+ rc = xo_printf(xop, "%s%*s]", pre_nl, xo_indent(xop), "");
+ xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST;
+
+ } else {
+ xo_depth_change(xop, name, -1, 0, XSS_CLOSE_LIST, XSF_LIST);
+ xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST;
+ }
return rc;
}
int
+xo_close_list_h (xo_handle_t *xop, const char *name)
+{
+ return xo_transition(xop, 0, name, XSS_CLOSE_LIST);
+}
+
+int
xo_close_list (const char *name)
{
return xo_close_list_h(NULL, name);
@@ -3895,7 +4175,88 @@ xo_close_list_d (void)
}
static int
-xo_open_instance_hf (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name)
+xo_do_open_leaf_list (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name)
+{
+ int rc = 0;
+ int indent = 0;
+
+ xop = xo_default(xop);
+
+ if (xop->xo_style == XO_STYLE_JSON) {
+ const char *ppn = (xop->xo_flags & XOF_PRETTY) ? "\n" : "";
+ const char *pre_nl = "";
+
+ indent = 1;
+
+ if (!(xop->xo_flags & XOF_NO_TOP)) {
+ if (!(xop->xo_flags & XOF_TOP_EMITTED)) {
+ xo_printf(xop, "%*s{%s", xo_indent(xop), "", ppn);
+ xop->xo_flags |= XOF_TOP_EMITTED;
+ }
+ }
+
+ if (name == NULL) {
+ xo_failure(xop, "NULL passed for list name");
+ name = XO_FAILURE_NAME;
+ }
+
+ xo_stack_set_flags(xop);
+
+ if (xop->xo_stack[xop->xo_depth].xs_flags & XSF_NOT_FIRST)
+ pre_nl = (xop->xo_flags & XOF_PRETTY) ? ",\n" : ", ";
+ xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST;
+
+ rc = xo_printf(xop, "%s%*s\"%s\": [%s",
+ pre_nl, xo_indent(xop), "", name, ppn);
+ }
+
+ xo_depth_change(xop, name, 1, indent, XSS_OPEN_LEAF_LIST,
+ XSF_LIST | xo_stack_flags(flags));
+
+ return rc;
+}
+
+static int
+xo_do_close_leaf_list (xo_handle_t *xop, const char *name)
+{
+ int rc = 0;
+ const char *pre_nl = "";
+
+ if (name == NULL) {
+ xo_stack_t *xsp = &xop->xo_stack[xop->xo_depth];
+
+ name = xsp->xs_name;
+ if (name) {
+ int len = strlen(name) + 1;
+ /* We need to make a local copy; xo_depth_change will free it */
+ char *cp = alloca(len);
+ memcpy(cp, name, len);
+ name = cp;
+ } else if (!(xsp->xs_flags & XSF_DTRT)) {
+ xo_failure(xop, "missing name without 'dtrt' mode");
+ name = XO_FAILURE_NAME;
+ }
+ }
+
+ if (xop->xo_style == XO_STYLE_JSON) {
+ if (xop->xo_stack[xop->xo_depth].xs_flags & XSF_NOT_FIRST)
+ pre_nl = (xop->xo_flags & XOF_PRETTY) ? "\n" : "";
+ xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST;
+
+ xo_depth_change(xop, name, -1, -1, XSS_CLOSE_LEAF_LIST, XSF_LIST);
+ rc = xo_printf(xop, "%s%*s]", pre_nl, xo_indent(xop), "");
+ xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST;
+
+ } else {
+ xo_depth_change(xop, name, -1, 0, XSS_CLOSE_LEAF_LIST, XSF_LIST);
+ xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST;
+ }
+
+ return rc;
+}
+
+static int
+xo_do_open_instance (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name)
{
xop = xo_default(xop);
@@ -3912,8 +4273,16 @@ xo_open_instance_hf (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name)
switch (xop->xo_style) {
case XO_STYLE_XML:
- rc = xo_printf(xop, "%*s<%s>%s", xo_indent(xop), "", name, ppn);
- xo_depth_change(xop, name, 1, 1, xo_stack_flags(flags));
+ rc = xo_printf(xop, "%*s<%s", xo_indent(xop), "", name);
+
+ if (xop->xo_attrs.xb_curp != xop->xo_attrs.xb_bufp) {
+ rc += xop->xo_attrs.xb_curp - xop->xo_attrs.xb_bufp;
+ xo_data_append(xop, xop->xo_attrs.xb_bufp,
+ xop->xo_attrs.xb_curp - xop->xo_attrs.xb_bufp);
+ xop->xo_attrs.xb_curp = xop->xo_attrs.xb_bufp;
+ }
+
+ rc += xo_printf(xop, ">%s", ppn);
break;
case XO_STYLE_JSON:
@@ -3925,18 +4294,20 @@ xo_open_instance_hf (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name)
rc = xo_printf(xop, "%s%*s{%s",
pre_nl, xo_indent(xop), "", ppn);
- xo_depth_change(xop, name, 1, 1, xo_stack_flags(flags));
- break;
-
- case XO_STYLE_HTML:
- case XO_STYLE_TEXT:
- xo_depth_change(xop, name, 1, 0, xo_stack_flags(flags));
break;
}
+ xo_depth_change(xop, name, 1, 1, XSS_OPEN_INSTANCE, xo_stack_flags(flags));
+
return rc;
}
+static int
+xo_open_instance_hf (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name)
+{
+ return xo_transition(xop, flags, name, XSS_OPEN_INSTANCE);
+}
+
int
xo_open_instance_h (xo_handle_t *xop, const char *name)
{
@@ -3961,8 +4332,8 @@ xo_open_instance_d (const char *name)
return xo_open_instance_hf(NULL, XOF_DTRT, name);
}
-int
-xo_close_instance_h (xo_handle_t *xop, const char *name)
+static int
+xo_do_close_instance (xo_handle_t *xop, const char *name)
{
xop = xo_default(xop);
@@ -3972,8 +4343,6 @@ xo_close_instance_h (xo_handle_t *xop, const char *name)
if (name == NULL) {
xo_stack_t *xsp = &xop->xo_stack[xop->xo_depth];
- if (!(xsp->xs_flags & XSF_DTRT))
- xo_failure(xop, "missing name without 'dtrt' mode");
name = xsp->xs_name;
if (name) {
@@ -3982,27 +4351,29 @@ xo_close_instance_h (xo_handle_t *xop, const char *name)
char *cp = alloca(len);
memcpy(cp, name, len);
name = cp;
- } else
+ } else if (!(xsp->xs_flags & XSF_DTRT)) {
+ xo_failure(xop, "missing name without 'dtrt' mode");
name = XO_FAILURE_NAME;
+ }
}
switch (xop->xo_style) {
case XO_STYLE_XML:
- xo_depth_change(xop, name, -1, -1, 0);
+ xo_depth_change(xop, name, -1, -1, XSS_CLOSE_INSTANCE, 0);
rc = xo_printf(xop, "%*s</%s>%s", xo_indent(xop), "", name, ppn);
break;
case XO_STYLE_JSON:
pre_nl = (xop->xo_flags & XOF_PRETTY) ? "\n" : "";
- xo_depth_change(xop, name, -1, -1, 0);
+ xo_depth_change(xop, name, -1, -1, XSS_CLOSE_INSTANCE, 0);
rc = xo_printf(xop, "%s%*s}", pre_nl, xo_indent(xop), "");
xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST;
break;
case XO_STYLE_HTML:
case XO_STYLE_TEXT:
- xo_depth_change(xop, name, -1, 0, 0);
+ xo_depth_change(xop, name, -1, 0, XSS_CLOSE_INSTANCE, 0);
break;
}
@@ -4010,6 +4381,12 @@ xo_close_instance_h (xo_handle_t *xop, const char *name)
}
int
+xo_close_instance_h (xo_handle_t *xop, const char *name)
+{
+ return xo_transition(xop, 0, name, XSS_CLOSE_INSTANCE);
+}
+
+int
xo_close_instance (const char *name)
{
return xo_close_instance_h(NULL, name);
@@ -4027,15 +4404,421 @@ xo_close_instance_d (void)
return xo_close_instance_h(NULL, NULL);
}
+static int
+xo_do_close_all (xo_handle_t *xop, xo_stack_t *limit)
+{
+ xo_stack_t *xsp;
+ int rc = 0;
+ xo_xsf_flags_t flags;
+
+ for (xsp = &xop->xo_stack[xop->xo_depth]; xsp >= limit; xsp--) {
+ switch (xsp->xs_state) {
+ case XSS_INIT:
+ /* Nothing */
+ rc = 0;
+ break;
+
+ case XSS_OPEN_CONTAINER:
+ rc = xo_do_close_container(xop, NULL);
+ break;
+
+ case XSS_OPEN_LIST:
+ rc = xo_do_close_list(xop, NULL);
+ break;
+
+ case XSS_OPEN_INSTANCE:
+ rc = xo_do_close_instance(xop, NULL);
+ break;
+
+ case XSS_OPEN_LEAF_LIST:
+ rc = xo_do_close_leaf_list(xop, NULL);
+ break;
+
+ case XSS_MARKER:
+ flags = xsp->xs_flags & XSF_MARKER_FLAGS;
+ xo_depth_change(xop, xsp->xs_name, -1, 0, XSS_MARKER, 0);
+ xop->xo_stack[xop->xo_depth].xs_flags |= flags;
+ rc = 0;
+ break;
+ }
+
+ if (rc < 0)
+ xo_failure(xop, "close %d failed: %d", xsp->xs_state, rc);
+ }
+
+ return 0;
+}
+
+/*
+ * This function is responsible for clearing out whatever is needed
+ * to get to the desired state, if possible.
+ */
+static int
+xo_do_close (xo_handle_t *xop, const char *name, xo_state_t new_state)
+{
+ xo_stack_t *xsp, *limit = NULL;
+ int rc;
+ xo_state_t need_state = new_state;
+
+ if (new_state == XSS_CLOSE_CONTAINER)
+ need_state = XSS_OPEN_CONTAINER;
+ else if (new_state == XSS_CLOSE_LIST)
+ need_state = XSS_OPEN_LIST;
+ else if (new_state == XSS_CLOSE_INSTANCE)
+ need_state = XSS_OPEN_INSTANCE;
+ else if (new_state == XSS_CLOSE_LEAF_LIST)
+ need_state = XSS_OPEN_LEAF_LIST;
+ else if (new_state == XSS_MARKER)
+ need_state = XSS_MARKER;
+ else
+ return 0; /* Unknown or useless new states are ignored */
+
+ for (xsp = &xop->xo_stack[xop->xo_depth]; xsp > xop->xo_stack; xsp--) {
+ /*
+ * Marker's normally stop us from going any further, unless
+ * we are popping a marker (new_state == XSS_MARKER).
+ */
+ if (xsp->xs_state == XSS_MARKER && need_state != XSS_MARKER) {
+ if (name) {
+ xo_failure(xop, "close (xo_%s) fails at marker '%s'; "
+ "not found '%s'",
+ xo_state_name(new_state),
+ xsp->xs_name, name);
+ return 0;
+
+ } else {
+ limit = xsp;
+ xo_failure(xop, "close stops at marker '%s'", xsp->xs_name);
+ }
+ break;
+ }
+
+ if (xsp->xs_state != need_state)
+ continue;
+
+ if (name && xsp->xs_name && strcmp(name, xsp->xs_name) != 0)
+ continue;
+
+ limit = xsp;
+ break;
+ }
+
+ if (limit == NULL) {
+ xo_failure(xop, "xo_%s can't find match for '%s'",
+ xo_state_name(new_state), name);
+ return 0;
+ }
+
+ rc = xo_do_close_all(xop, limit);
+
+ return rc;
+}
+
+/*
+ * We are in a given state and need to transition to the new state.
+ */
+static int
+xo_transition (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name,
+ xo_state_t new_state)
+{
+ xo_stack_t *xsp;
+ int rc;
+ int old_state, on_marker;
+
+ xop = xo_default(xop);
+
+ rc = 0;
+ xsp = &xop->xo_stack[xop->xo_depth];
+ old_state = xsp->xs_state;
+ on_marker = (old_state == XSS_MARKER);
+
+ /* If there's a marker on top of the stack, we need to find a real state */
+ while (old_state == XSS_MARKER) {
+ if (xsp == xop->xo_stack)
+ break;
+ xsp -= 1;
+ old_state = xsp->xs_state;
+ }
+
+ /*
+ * At this point, the list of possible states are:
+ * XSS_INIT, XSS_OPEN_CONTAINER, XSS_OPEN_LIST,
+ * XSS_OPEN_INSTANCE, XSS_OPEN_LEAF_LIST, XSS_DISCARDING
+ */
+ switch (XSS_TRANSITION(old_state, new_state)) {
+
+ open_container:
+ case XSS_TRANSITION(XSS_INIT, XSS_OPEN_CONTAINER):
+ case XSS_TRANSITION(XSS_OPEN_INSTANCE, XSS_OPEN_CONTAINER):
+ case XSS_TRANSITION(XSS_OPEN_CONTAINER, XSS_OPEN_CONTAINER):
+ rc = xo_do_open_container(xop, flags, name);
+ break;
+
+ case XSS_TRANSITION(XSS_OPEN_LIST, XSS_OPEN_CONTAINER):
+ if (on_marker)
+ goto marker_prevents_close;
+ rc = xo_do_close_list(xop, NULL);
+ if (rc >= 0)
+ goto open_container;
+ break;
+
+ case XSS_TRANSITION(XSS_OPEN_LEAF_LIST, XSS_OPEN_CONTAINER):
+ if (on_marker)
+ goto marker_prevents_close;
+ rc = xo_do_close_leaf_list(xop, NULL);
+ if (rc >= 0)
+ goto open_container;
+ break;
+
+ /*close_container:*/
+ case XSS_TRANSITION(XSS_OPEN_CONTAINER, XSS_CLOSE_CONTAINER):
+ if (on_marker)
+ goto marker_prevents_close;
+ rc = xo_do_close(xop, name, new_state);
+ break;
+
+ case XSS_TRANSITION(XSS_INIT, XSS_CLOSE_CONTAINER):
+ /* This is an exception for "xo --close" */
+ rc = xo_do_close_container(xop, name);
+ break;
+
+ case XSS_TRANSITION(XSS_OPEN_LIST, XSS_CLOSE_CONTAINER):
+ case XSS_TRANSITION(XSS_OPEN_INSTANCE, XSS_CLOSE_CONTAINER):
+ if (on_marker)
+ goto marker_prevents_close;
+ rc = xo_do_close(xop, name, new_state);
+ break;
+
+ case XSS_TRANSITION(XSS_OPEN_LEAF_LIST, XSS_CLOSE_CONTAINER):
+ if (on_marker)
+ goto marker_prevents_close;
+ rc = xo_do_close_leaf_list(xop, NULL);
+ if (rc >= 0)
+ rc = xo_do_close(xop, name, new_state);
+ break;
+
+ open_list:
+ case XSS_TRANSITION(XSS_INIT, XSS_OPEN_LIST):
+ case XSS_TRANSITION(XSS_OPEN_CONTAINER, XSS_OPEN_LIST):
+ case XSS_TRANSITION(XSS_OPEN_INSTANCE, XSS_OPEN_LIST):
+ rc = xo_do_open_list(xop, flags, name);
+ break;
+
+ case XSS_TRANSITION(XSS_OPEN_LIST, XSS_OPEN_LIST):
+ if (on_marker)
+ goto marker_prevents_close;
+ rc = xo_do_close_list(xop, NULL);
+ if (rc >= 0)
+ goto open_list;
+ break;
+
+ case XSS_TRANSITION(XSS_OPEN_LEAF_LIST, XSS_OPEN_LIST):
+ if (on_marker)
+ goto marker_prevents_close;
+ rc = xo_do_close_leaf_list(xop, NULL);
+ if (rc >= 0)
+ goto open_list;
+ break;
+
+ /*close_list:*/
+ case XSS_TRANSITION(XSS_OPEN_LIST, XSS_CLOSE_LIST):
+ if (on_marker)
+ goto marker_prevents_close;
+ rc = xo_do_close(xop, name, new_state);
+ break;
+
+ case XSS_TRANSITION(XSS_INIT, XSS_CLOSE_LIST):
+ case XSS_TRANSITION(XSS_OPEN_CONTAINER, XSS_CLOSE_LIST):
+ case XSS_TRANSITION(XSS_OPEN_INSTANCE, XSS_CLOSE_LIST):
+ case XSS_TRANSITION(XSS_OPEN_LEAF_LIST, XSS_CLOSE_LIST):
+ rc = xo_do_close(xop, name, new_state);
+ break;
+
+ open_instance:
+ case XSS_TRANSITION(XSS_OPEN_LIST, XSS_OPEN_INSTANCE):
+ rc = xo_do_open_instance(xop, flags, name);
+ break;
+
+ case XSS_TRANSITION(XSS_OPEN_CONTAINER, XSS_OPEN_INSTANCE):
+ case XSS_TRANSITION(XSS_INIT, XSS_OPEN_INSTANCE):
+ rc = xo_do_open_list(xop, flags, name);
+ if (rc >= 0)
+ goto open_instance;
+ break;
+
+ case XSS_TRANSITION(XSS_OPEN_INSTANCE, XSS_OPEN_INSTANCE):
+ if (on_marker) {
+ rc = xo_do_open_list(xop, flags, name);
+ } else {
+ rc = xo_do_close_instance(xop, NULL);
+ }
+ if (rc >= 0)
+ goto open_instance;
+ break;
+
+ case XSS_TRANSITION(XSS_OPEN_LEAF_LIST, XSS_OPEN_INSTANCE):
+ if (on_marker)
+ goto marker_prevents_close;
+ rc = xo_do_close_leaf_list(xop, NULL);
+ if (rc >= 0)
+ goto open_instance;
+ break;
+
+ /*close_instance:*/
+ case XSS_TRANSITION(XSS_OPEN_INSTANCE, XSS_CLOSE_INSTANCE):
+ if (on_marker)
+ goto marker_prevents_close;
+ rc = xo_do_close_instance(xop, name);
+ break;
+
+ case XSS_TRANSITION(XSS_INIT, XSS_CLOSE_INSTANCE):
+ /* This one makes no sense; ignore it */
+ break;
+
+ case XSS_TRANSITION(XSS_OPEN_CONTAINER, XSS_CLOSE_INSTANCE):
+ case XSS_TRANSITION(XSS_OPEN_LIST, XSS_CLOSE_INSTANCE):
+ if (on_marker)
+ goto marker_prevents_close;
+ rc = xo_do_close(xop, name, new_state);
+ break;
+
+ case XSS_TRANSITION(XSS_OPEN_LEAF_LIST, XSS_CLOSE_INSTANCE):
+ if (on_marker)
+ goto marker_prevents_close;
+ rc = xo_do_close_leaf_list(xop, NULL);
+ if (rc >= 0)
+ rc = xo_do_close(xop, name, new_state);
+ break;
+
+ open_leaf_list:
+ case XSS_TRANSITION(XSS_OPEN_CONTAINER, XSS_OPEN_LEAF_LIST):
+ case XSS_TRANSITION(XSS_OPEN_INSTANCE, XSS_OPEN_LEAF_LIST):
+ case XSS_TRANSITION(XSS_INIT, XSS_OPEN_LEAF_LIST):
+ rc = xo_do_open_leaf_list(xop, flags, name);
+ break;
+
+ case XSS_TRANSITION(XSS_OPEN_LIST, XSS_OPEN_LEAF_LIST):
+ case XSS_TRANSITION(XSS_OPEN_LEAF_LIST, XSS_OPEN_LEAF_LIST):
+ if (on_marker)
+ goto marker_prevents_close;
+ rc = xo_do_close_list(xop, NULL);
+ if (rc >= 0)
+ goto open_leaf_list;
+ break;
+
+ /*close_leaf_list:*/
+ case XSS_TRANSITION(XSS_OPEN_LEAF_LIST, XSS_CLOSE_LEAF_LIST):
+ if (on_marker)
+ goto marker_prevents_close;
+ rc = xo_do_close_leaf_list(xop, name);
+ break;
+
+ case XSS_TRANSITION(XSS_INIT, XSS_CLOSE_LEAF_LIST):
+ /* Makes no sense; ignore */
+ break;
+
+ case XSS_TRANSITION(XSS_OPEN_CONTAINER, XSS_CLOSE_LEAF_LIST):
+ case XSS_TRANSITION(XSS_OPEN_LIST, XSS_CLOSE_LEAF_LIST):
+ case XSS_TRANSITION(XSS_OPEN_INSTANCE, XSS_CLOSE_LEAF_LIST):
+ if (on_marker)
+ goto marker_prevents_close;
+ rc = xo_do_close(xop, name, new_state);
+ break;
+
+ /*emit:*/
+ case XSS_TRANSITION(XSS_OPEN_CONTAINER, XSS_EMIT):
+ case XSS_TRANSITION(XSS_OPEN_INSTANCE, XSS_EMIT):
+ break;
+
+ case XSS_TRANSITION(XSS_OPEN_LIST, XSS_EMIT):
+ if (on_marker)
+ goto marker_prevents_close;
+ rc = xo_do_close(xop, NULL, XSS_CLOSE_LIST);
+ break;
+
+ case XSS_TRANSITION(XSS_INIT, XSS_EMIT):
+ break;
+
+ case XSS_TRANSITION(XSS_OPEN_LEAF_LIST, XSS_EMIT):
+ if (on_marker)
+ goto marker_prevents_close;
+ rc = xo_do_close_leaf_list(xop, NULL);
+ break;
+
+ /*emit_leaf_list:*/
+ case XSS_TRANSITION(XSS_INIT, XSS_EMIT_LEAF_LIST):
+ case XSS_TRANSITION(XSS_OPEN_CONTAINER, XSS_EMIT_LEAF_LIST):
+ case XSS_TRANSITION(XSS_OPEN_INSTANCE, XSS_EMIT_LEAF_LIST):
+ rc = xo_do_open_leaf_list(xop, flags, name);
+ break;
+
+ case XSS_TRANSITION(XSS_OPEN_LEAF_LIST, XSS_EMIT_LEAF_LIST):
+ break;
+
+ case XSS_TRANSITION(XSS_OPEN_LIST, XSS_EMIT_LEAF_LIST):
+ /*
+ * We need to be backward compatible with the pre-xo_open_leaf_list
+ * API, where both lists and leaf-lists were opened as lists. So
+ * if we find an open list that hasn't had anything written to it,
+ * we'll accept it.
+ */
+ break;
+
+ default:
+ xo_failure(xop, "unknown transition: (%u -> %u)",
+ xsp->xs_state, new_state);
+ }
+
+ return rc;
+
+ marker_prevents_close:
+ xo_failure(xop, "marker '%s' prevents transition from %s to %s",
+ xop->xo_stack[xop->xo_depth].xs_name,
+ xo_state_name(old_state), xo_state_name(new_state));
+ return -1;
+}
+
+int
+xo_open_marker_h (xo_handle_t *xop, const char *name)
+{
+ xop = xo_default(xop);
+
+ xo_depth_change(xop, name, 1, 0, XSS_MARKER,
+ xop->xo_stack[xop->xo_depth].xs_flags & XSF_MARKER_FLAGS);
+
+ return 0;
+}
+
+int
+xo_open_marker (const char *name)
+{
+ return xo_open_marker_h(NULL, name);
+}
+
+int
+xo_close_marker_h (xo_handle_t *xop, const char *name)
+{
+ xop = xo_default(xop);
+
+ return xo_do_close(xop, name, XSS_MARKER);
+}
+
+int
+xo_close_marker (const char *name)
+{
+ return xo_close_marker_h(NULL, name);
+}
+
void
xo_set_writer (xo_handle_t *xop, void *opaque, xo_write_func_t write_func,
- xo_close_func_t close_func)
+ xo_close_func_t close_func, xo_flush_func_t flush_func)
{
xop = xo_default(xop);
xop->xo_opaque = opaque;
xop->xo_write = write_func;
xop->xo_close = close_func;
+ xop->xo_flush = flush_func;
}
void
@@ -4045,10 +4828,11 @@ xo_set_allocator (xo_realloc_func_t realloc_func, xo_free_func_t free_func)
xo_free = free_func;
}
-void
+int
xo_flush_h (xo_handle_t *xop)
{
static char div_close[] = "</div>";
+ int rc;
xop = xo_default(xop);
@@ -4064,21 +4848,29 @@ xo_flush_h (xo_handle_t *xop)
break;
}
- xo_write(xop);
+ rc = xo_write(xop);
+ if (rc >= 0 && xop->xo_flush)
+ if (xop->xo_flush(xop->xo_opaque) < 0)
+ return -1;
+
+ return rc;
}
-void
+int
xo_flush (void)
{
- xo_flush_h(NULL);
+ return xo_flush_h(NULL);
}
-void
+int
xo_finish_h (xo_handle_t *xop)
{
const char *cp = "";
xop = xo_default(xop);
+ if (!(xop->xo_flags & XOF_NO_CLOSE))
+ xo_do_close_all(xop, xop->xo_stack);
+
switch (xop->xo_style) {
case XO_STYLE_JSON:
if (!(xop->xo_flags & XOF_NO_TOP)) {
@@ -4091,13 +4883,13 @@ xo_finish_h (xo_handle_t *xop)
break;
}
- xo_flush_h(xop);
+ return xo_flush_h(xop);
}
-void
+int
xo_finish (void)
{
- xo_finish_h(NULL);
+ return xo_finish_h(NULL);
}
/*
@@ -4141,6 +4933,7 @@ xo_error_hv (xo_handle_t *xop, const char *fmt, va_list vap)
break;
case XO_STYLE_XML:
+ case XO_STYLE_JSON:
va_copy(xop->xo_vap, vap);
xo_open_container_h(xop, "error");
@@ -4235,6 +5028,30 @@ xo_parse_args (int argc, char **argv)
return save;
}
+void
+xo_dump_stack (xo_handle_t *xop)
+{
+ int i;
+ xo_stack_t *xsp;
+
+ xop = xo_default(xop);
+
+ fprintf(stderr, "Stack dump:\n");
+
+ xsp = xop->xo_stack;
+ for (i = 1, xsp++; i <= xop->xo_depth; i++, xsp++) {
+ fprintf(stderr, " [%d] %s '%s' [%x]\n",
+ i, xo_state_name(xsp->xs_state),
+ xsp->xs_name ?: "--", xsp->xs_flags);
+ }
+}
+
+void
+xo_set_program (const char *name)
+{
+ xo_program = name;
+}
+
#ifdef UNIT_TEST
int
main (int argc, char **argv)
diff --git a/contrib/libxo/libxo/xo.h b/contrib/libxo/libxo/xo.h
index 3a59e4c81efc..82b965a29202 100644
--- a/contrib/libxo/libxo/xo.h
+++ b/contrib/libxo/libxo/xo.h
@@ -25,35 +25,39 @@ typedef unsigned xo_style_t;
#define XO_STYLE_HTML 3 /** Generate HTML output */
/** Flags for libxo */
-typedef unsigned long xo_xof_flags_t;
-#define XOF_CLOSE_FP (1<<0) /** Close file pointer on xo_close() */
-#define XOF_PRETTY (1<<1) /** Make 'pretty printed' output */
-#define XOF_DIV_OPEN (1<<2) /** Internal use only: a <div> is open */
-#define XOF_LINE_OPEN (1<<3) /** Internal use only: a <div class="line"> */
-
-#define XOF_WARN (1<<4) /** Generate warnings for broken calls */
-#define XOF_XPATH (1<<5) /** Emit XPath attributes in HTML */
-#define XOF_INFO (1<<6) /** Emit additional info fields (HTML) */
-#define XOF_WARN_XML (1<<7) /** Emit warnings in XML (on stdout) */
-
-#define XOF_NO_ENV (1<<8) /** Don't look at the LIBXO_OPTIONS env var */
-#define XOF_NO_VA_ARG (1<<9) /** Don't advance va_list w/ va_arg() */
-#define XOF_DTRT (1<<10) /** Enable "do the right thing" mode */
-#define XOF_KEYS (1<<11) /** Flag 'key' fields for xml and json */
-
-#define XOF_IGNORE_CLOSE (1<<12) /** Ignore errors on close tags */
-#define XOF_NOT_FIRST (1<<13) /* Not the first item (JSON) */
-#define XOF_NO_LOCALE (1<<14) /** Don't bother with locale */
-#define XOF_TOP_EMITTED (1<<15) /* The top JSON braces have been emitted */
-
-#define XOF_NO_TOP (1<<16) /** Don't emit the top braces in JSON */
-#define XOF_ANCHOR (1<<17) /** An anchor is in place */
-#define XOF_UNITS (1<<18) /** Encode units in XML */
-#define XOF_UNITS_PENDING (1<<19) /** We have a units-insertion pending */
-
-#define XOF_UNDERSCORES (1<<20) /** Replace dashes with underscores (JSON) */
-#define XOF_COLUMNS (1<<21) /** xo_emit should return a column count */
-#define XOF_FLUSH (1<<22) /** Flush after each xo_emit call */
+typedef unsigned long long xo_xof_flags_t;
+#define XOF_BIT(_n) ((xo_xof_flags_t) 1 << (_n))
+#define XOF_CLOSE_FP XOF_BIT(0) /** Close file pointer on xo_close() */
+#define XOF_PRETTY XOF_BIT(1) /** Make 'pretty printed' output */
+#define XOF_DIV_OPEN XOF_BIT(2) /** Internal use only: a <div> is open */
+#define XOF_LINE_OPEN XOF_BIT(3) /** Internal use only: <div class="line"> */
+
+#define XOF_WARN XOF_BIT(4) /** Generate warnings for broken calls */
+#define XOF_XPATH XOF_BIT(5) /** Emit XPath attributes in HTML */
+#define XOF_INFO XOF_BIT(6) /** Emit additional info fields (HTML) */
+#define XOF_WARN_XML XOF_BIT(7) /** Emit warnings in XML (on stdout) */
+
+#define XOF_NO_ENV XOF_BIT(8) /** Don't look at LIBXO_OPTIONS env var */
+#define XOF_NO_VA_ARG XOF_BIT(9) /** Don't advance va_list w/ va_arg() */
+#define XOF_DTRT XOF_BIT(10) /** Enable "do the right thing" mode */
+#define XOF_KEYS XOF_BIT(11) /** Flag 'key' fields for xml and json */
+
+#define XOF_IGNORE_CLOSE XOF_BIT(12) /** Ignore errors on close tags */
+#define XOF_NOT_FIRST XOF_BIT(13) /* Not the first item (JSON) */
+#define XOF_NO_LOCALE XOF_BIT(14) /** Don't bother with locale */
+#define XOF_TOP_EMITTED XOF_BIT(15) /* The top JSON braces have been emitted */
+
+#define XOF_NO_TOP XOF_BIT(16) /** Don't emit the top braces in JSON */
+#define XOF_ANCHOR XOF_BIT(17) /** An anchor is in place */
+#define XOF_UNITS XOF_BIT(18) /** Encode units in XML */
+#define XOF_UNITS_PENDING XOF_BIT(19) /** We have a units-insertion pending */
+
+#define XOF_UNDERSCORES XOF_BIT(20) /** Replace dashes with underscores (JSON)*/
+#define XOF_COLUMNS XOF_BIT(21) /** xo_emit should return a column count */
+#define XOF_FLUSH XOF_BIT(22) /** Flush after each xo_emit call */
+#define XOF_FLUSH_LINE XOF_BIT(23) /** Flush after each newline */
+
+#define XOF_NO_CLOSE XOF_BIT(24) /** xo_finish won't close open elements */
/*
* The xo_info_t structure provides a mapping between names and
@@ -70,6 +74,7 @@ typedef struct xo_handle_s xo_handle_t; /* Handle for XO output */
typedef int (*xo_write_func_t)(void *, const char *);
typedef void (*xo_close_func_t)(void *);
+typedef int (*xo_flush_func_t)(void *);
typedef void *(*xo_realloc_func_t)(void *, size_t);
typedef void (*xo_free_func_t)(void *);
@@ -93,7 +98,7 @@ xo_destroy (xo_handle_t *xop);
void
xo_set_writer (xo_handle_t *xop, void *opaque, xo_write_func_t write_func,
- xo_close_func_t close_func);
+ xo_close_func_t close_func, xo_flush_func_t flush_func);
void
xo_set_allocator (xo_realloc_func_t realloc_func, xo_free_func_t free_func);
@@ -210,6 +215,18 @@ int
xo_close_instance_d (void);
int
+xo_open_marker_h (xo_handle_t *xop, const char *name);
+
+int
+xo_open_marker (const char *name);
+
+int
+xo_close_marker_h (xo_handle_t *xop, const char *name);
+
+int
+xo_close_marker (const char *name);
+
+int
xo_attr_h (xo_handle_t *xop, const char *name, const char *fmt, ...);
int
@@ -227,16 +244,16 @@ xo_error_h (xo_handle_t *xop, const char *fmt, ...);
void
xo_error (const char *fmt, ...);
-void
+int
xo_flush_h (xo_handle_t *xop);
-void
+int
xo_flush (void);
-void
+int
xo_finish_h (xo_handle_t *xop);
-void
+int
xo_finish (void);
void
@@ -297,4 +314,10 @@ xo_parse_args (int argc, char **argv);
extern const char xo_version[];
extern const char xo_version_extra[];
+void
+xo_dump_stack (xo_handle_t *xop);
+
+void
+xo_set_program (const char *name);
+
#endif /* INCLUDE_XO_H */
diff --git a/contrib/libxo/libxo/xo_attr.3 b/contrib/libxo/libxo/xo_attr.3
index afd805f54f01..1c183605975b 100644
--- a/contrib/libxo/libxo/xo_attr.3
+++ b/contrib/libxo/libxo/xo_attr.3
@@ -51,6 +51,10 @@ parameter as passed to
XML:
<login-time seconds="1408336270">00:14</login-time>
.Ed
+.Pp
+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.
.Sh ADDITIONAL DOCUMENTATION
.Pp
Complete documentation can be found on github:
diff --git a/contrib/libxo/libxo/xo_create.3 b/contrib/libxo/libxo/xo_create.3
index ec241ee1e0e1..b0e896522707 100644
--- a/contrib/libxo/libxo/xo_create.3
+++ b/contrib/libxo/libxo/xo_create.3
@@ -7,7 +7,7 @@
.\" # LICENSE.
.\" # Phil Shafer, July 2014
.\"
-.Dd July, 2014
+.Dd December 4, 2014
.Dt LIBXO 3
.Os
.Sh NAME
@@ -25,7 +25,7 @@
.Fn xo_destroy "xo_handle_t *handle"
.Sh DESCRIPTION
A
-.Em libxo
+.Nm libxo
handle can be allocated using the
.Fn xo_create
function.
@@ -37,49 +37,55 @@ function.
.Ed
.Pp
By default,
-.Em libxo
-writes output to standard output. A convenience
-function is provided for situations when output should be written to
+.Nm libxo
+writes output to standard output.
+A convenience
+function is provided for situations when output should be written to a
different file.
.Pp
Use the
-.Em XOF_CLOSE_FP
+.Dv XOF_CLOSE_FP
flag to trigger a call to
-.Em fclose 3
-for the FILE pointer when the handle is destroyed.
+.Xr fclose 3
+for the
+.Dv FILE
+pointer when the handle is destroyed.
.Pp
The
.Fn xo_destroy
function releases a handle and any resources it is
-using. Calling
+using.
+Calling
.Fn xo_destroy
with a
-.Em NULL
+.Dv NULL
handle will release any
resources associated with the default handle.
.Sh ADDITIONAL DOCUMENTATION
-.Pp
Complete documentation can be found on github:
.Bd -literal -offset indent
http://juniper.github.io/libxo/libxo-manual.html
.Ed
.Pp
-libxo lives on github as:
+.Nm libxo
+lives on github as:
.Bd -literal -offset indent
https://github.com/Juniper/libxo
.Ed
.Pp
-The latest release of libxo is available at:
+The latest release of
+.Nm libxo
+is available at:
.Bd -literal -offset indent
https://github.com/Juniper/libxo/releases
.Ed
.Sh SEE ALSO
-.Xr xo_emit 3
-and
-.Xr xo_set_options 3 .
+.Xr xo_emit 3 ,
+.Xr xo_set_options 3
.Sh HISTORY
The
-.Fa libxo
-library was added in FreeBSD 11.0.
+.Nm libxo
+library was added in
+.Fx 11.0 .
.Sh AUTHOR
Phil Shafer
diff --git a/contrib/libxo/libxo/xo_emit.3 b/contrib/libxo/libxo/xo_emit.3
index 9f76e13c6329..706082450986 100644
--- a/contrib/libxo/libxo/xo_emit.3
+++ b/contrib/libxo/libxo/xo_emit.3
@@ -7,7 +7,7 @@
.\" # LICENSE.
.\" # Phil Shafer, July 2014
.\"
-.Dd July, 2014
+.Dd December 4, 2014
.Dt LIBXO 3
.Os
.Sh NAME
@@ -44,13 +44,13 @@ accepts a
.Fa va_list
for additional flexibility.
.Sh ADDITIONAL DOCUMENTATION
-.Pp
Complete documentation can be found on github:
.Bd -literal -offset indent
http://juniper.github.io/libxo/libxo-manual.html
.Ed
.Pp
-libxo lives on github as:
+.Nm libxo
+lives on github as:
.Bd -literal -offset indent
https://github.com/Juniper/libxo
.Ed
@@ -61,11 +61,12 @@ https://github.com/Juniper/libxo/releases
.Ed
.Sh SEE ALSO
.Xr xo_open_container 3 ,
-.Xr xo_open_list 3 , and
-.Xr xo_format 5 .
+.Xr xo_open_list 3 ,
+.Xr xo_format 5
.Sh HISTORY
The
-.Fa libxo
-library was added in FreeBSD 11.0.
+.Nm libxo
+library was added in
+.Fx 11.0 .
.Sh AUTHOR
Phil Shafer
diff --git a/contrib/libxo/libxo/xo_err.3 b/contrib/libxo/libxo/xo_err.3
index 2445aa70f652..5584309f3bf0 100644
--- a/contrib/libxo/libxo/xo_err.3
+++ b/contrib/libxo/libxo/xo_err.3
@@ -7,7 +7,7 @@
.\" # LICENSE.
.\" # Phil Shafer, July 2014
.\"
-.Dd July, 2014
+.Dd December 4, 2014
.Dt LIBXO 3
.Os
.Sh NAME
@@ -45,32 +45,38 @@ Many programs make use of the standard library functions
and
.Xr warn 3
to generate errors and warnings for the user.
-.Em libxo
+.Nm libxo
wants to
pass that information via the current output style, and provides
compatible functions to allow this.
.Pp
These functions display the program name, a colon, a formatted message
based on the arguments, and then optionally a colon and an error
-message associated with either "errno" or the "code" parameter.
+message associated with either
+.Fa errno
+or the
+.Fa code
+parameter.
.Bd -literal -offset indent
EXAMPLE:
if (open(filename, O_RDONLY) < 0)
xo_err(1, "cannot open file '%s'", filename);
.Ed
.Sh ADDITIONAL DOCUMENTATION
-.Pp
Complete documentation can be found on github:
.Bd -literal -offset indent
http://juniper.github.io/libxo/libxo-manual.html
.Ed
.Pp
-libxo lives on github as:
+.Nm libxo
+lives on github as:
.Bd -literal -offset indent
https://github.com/Juniper/libxo
.Ed
.Pp
-The latest release of libxo is available at:
+The latest release of
+.Nm libxo
+is available at:
.Bd -literal -offset indent
https://github.com/Juniper/libxo/releases
.Ed
@@ -78,7 +84,8 @@ https://github.com/Juniper/libxo/releases
.Xr xo_emit 3
.Sh HISTORY
The
-.Fa libxo
-library was added in FreeBSD 11.0.
+.Nm libxo
+library was added in
+.Fx 11.0 .
.Sh AUTHOR
Phil Shafer
diff --git a/contrib/libxo/libxo/xo_error.3 b/contrib/libxo/libxo/xo_error.3
new file mode 100644
index 000000000000..da91785928d5
--- /dev/null
+++ b/contrib/libxo/libxo/xo_error.3
@@ -0,0 +1,64 @@
+.\" #
+.\" # Copyright (c) 2014, Juniper Networks, Inc.
+.\" # All rights reserved.
+.\" # This SOFTWARE is licensed under the LICENSE provided in the
+.\" # ../Copyright file. By downloading, installing, copying, or
+.\" # using the SOFTWARE, you agree to be bound by the terms of that
+.\" # LICENSE.
+.\" # Phil Shafer, July 2014
+.\"
+.Dd December 4, 2014
+.Dt LIBXO 3
+.Os
+.Sh NAME
+.Nm xo_error
+.Nd generate error messages
+.Sh LIBRARY
+.Lb libxo
+.Sh SYNOPSIS
+.In libxo/xo.h
+.Ft void
+.Fn xo_error "const char *fmt" "..."
+.Sh DESCRIPTION
+Use the
+.Fn xo_error
+function to generate error messages to standard error.
+The
+.Fa fmt
+argument is a string containing printf-style formatting
+instructions that describe the remaining arguments.
+.Pp
+When converting an application to libxo, one can replace
+.Em "fprintf(stderr,...)"
+calls with
+.Fn xo_error
+calls.
+.Pp
+.Sh ADDITIONAL DOCUMENTATION
+Complete documentation can be found on github:
+.Bd -literal -offset indent
+http://juniper.github.io/libxo/libxo-manual.html
+.Ed
+.Pp
+.Nm libxo
+lives on github as:
+.Bd -literal -offset indent
+https://github.com/Juniper/libxo
+.Ed
+.Pp
+The latest release of
+.Nm libxo
+is available at:
+.Bd -literal -offset indent
+https://github.com/Juniper/libxo/releases
+.Ed
+.Sh SEE ALSO
+.Xr printf 3
+.Xr xo_emit 3
+.Sh HISTORY
+The
+.Nm libxo
+library was added in
+.Fx 11.0 .
+.Sh AUTHOR
+Phil Shafer
diff --git a/contrib/libxo/libxo/xo_finish.3 b/contrib/libxo/libxo/xo_finish.3
index 3b25dc34cbfc..421e94557bf9 100644
--- a/contrib/libxo/libxo/xo_finish.3
+++ b/contrib/libxo/libxo/xo_finish.3
@@ -7,7 +7,7 @@
.\" # LICENSE.
.\" # Phil Shafer, July 2014
.\"
-.Dd July, 2014
+.Dd December 4, 2014
.Dt LIBXO 3
.Os
.Sh NAME
@@ -24,9 +24,10 @@
.Sh DESCRIPTION
When the program is ready to exit or close a handle, a call to
.Fn xo_finish
-is required. This flushes any buffered data, closes
+is required.
+This flushes any buffered data, closes
open
-.Em libxo
+.Nm libxo
constructs, and completes any pending operations.
.Pp
Calling this function is
@@ -34,18 +35,20 @@ Calling this function is
to the proper operation of libxo,
especially for the non-TEXT output styles.
.Sh ADDITIONAL DOCUMENTATION
-.Pp
Complete documentation can be found on github:
.Bd -literal -offset indent
http://juniper.github.io/libxo/libxo-manual.html
.Ed
.Pp
-libxo lives on github as:
+.Nm libxo
+lives on github as:
.Bd -literal -offset indent
https://github.com/Juniper/libxo
.Ed
.Pp
-The latest release of libxo is available at:
+The latest release of
+.Nm libxo
+is available at:
.Bd -literal -offset indent
https://github.com/Juniper/libxo/releases
.Ed
@@ -53,7 +56,8 @@ https://github.com/Juniper/libxo/releases
.Xr xo_emit 3
.Sh HISTORY
The
-.Fa libxo
-library was added in FreeBSD 11.0.
+.Nm libxo
+library was added in
+.Fx 11.0 .
.Sh AUTHOR
Phil Shafer
diff --git a/contrib/libxo/libxo/xo_flush.3 b/contrib/libxo/libxo/xo_flush.3
index 160f634773de..b85e9f786d0c 100644
--- a/contrib/libxo/libxo/xo_flush.3
+++ b/contrib/libxo/libxo/xo_flush.3
@@ -7,7 +7,7 @@
.\" # LICENSE.
.\" # Phil Shafer, July 2014
.\"
-.Dd July, 2014
+.Dd December 4, 2014
.Dt LIBXO 3
.Os
.Sh NAME
@@ -22,25 +22,29 @@
.Ft void
.Fn xo_flush_h "xo_handle_t *handle"
.Sh DESCRIPTION
-.Em libxo
+.Nm libxo
buffers data, both for performance and consistency, but also to
-allow some advanced features to work properly. At various times, the
-caller may wish to flush any data buffered within the library. The
+allow some advanced features to work properly.
+At various times, the
+caller may wish to flush any data buffered within the library.
+The
.Fn xo_flush
function is used for this.
.Sh ADDITIONAL DOCUMENTATION
-.Pp
Complete documentation can be found on github:
.Bd -literal -offset indent
http://juniper.github.io/libxo/libxo-manual.html
.Ed
.Pp
-libxo lives on github as:
+.Nm libxo
+lives on github as:
.Bd -literal -offset indent
https://github.com/Juniper/libxo
.Ed
.Pp
-The latest release of libxo is available at:
+The latest release of
+.Nm libxo
+is available at:
.Bd -literal -offset indent
https://github.com/Juniper/libxo/releases
.Ed
@@ -48,7 +52,8 @@ https://github.com/Juniper/libxo/releases
.Xr xo_emit 3
.Sh HISTORY
The
-.Fa libxo
-library was added in FreeBSD 11.0.
+.Nm libxo
+library was added in
+.Fx 11.0 .
.Sh AUTHOR
Phil Shafer
diff --git a/contrib/libxo/libxo/xo_format.5 b/contrib/libxo/libxo/xo_format.5
index 62cfeb6b92f8..b021b98fd559 100644
--- a/contrib/libxo/libxo/xo_format.5
+++ b/contrib/libxo/libxo/xo_format.5
@@ -7,7 +7,7 @@
.\" # LICENSE.
.\" # Phil Shafer, July 2014
.\"
-.Dd July, 2014
+.Dd December 4, 2014
.Dt LIBXO 3
.Os
.Sh NAME
@@ -15,7 +15,7 @@
.Nd content of format descriptors for xo_emit
.Sh DESCRIPTION
.Pp
-.Em libxo
+.Nm libxo
uses format strings to control the rendering of data into
various output styles, including
.Em text ,
@@ -25,25 +25,28 @@ and
.Em HTML .
Each format string contains a set of zero or more
.Dq field descriptions ,
-which describe independent data fields. Each
-field description contains a set of
+which describe independent data fields.
+Each field description contains a set of
.Dq modifiers ,
a
.Dq content string ,
and zero, one, or two
.Dq format descriptors .
The modifiers tell
-.Em libxo
+.Nm libxo
what the field is and how to treat it, while the format descriptors are
formatting instructions using
-.Xr printf 3 -style
+.Xr printf 3 Ns -style
format strings, telling
-libxo how to format the field. The field description is placed inside
+.Nm libxo
+how to format the field.
+The field description is placed inside
a set of braces, with a colon
.Ql ( \&: )
after the modifiers and a slash
.Ql ( \&/ )
-before each format descriptors. Text may be intermixed with
+before each format descriptors.
+Text may be intermixed with
field descriptions within the format string.
.Pp
The field description is given as follows:
@@ -53,15 +56,19 @@ The field description is given as follows:
.Ed
.Pp
The role describes the function of the field, while the modifiers
-enable optional behaviors. The contents, field-format, and
-encoding-format are used in varying ways, based on the role. These
-are described in the following sections.
+enable optional behaviors.
+The contents, field-format, and
+encoding-format are used in varying ways, based on the role.
+These are described in the following sections.
.Pp
-In the following example, three field descriptors appear. The first
+In the following example, three field descriptors appear.
+The first
is a padding field containing three spaces of padding, the second is a
-label ("In stock"), and the third is a value field ("in-stock"). The
-in-stock field has a "%u" format that will parse the next argument
-passed to the xo_emit function as an unsigned integer.
+label ("In stock"), and the third is a value field ("in-stock").
+The in-stock field has a "%u" format that will parse the next argument
+passed to the
+.Xr xo_emit 3 ,
+function as an unsigned integer.
.Bd -literal -offset indent
xo_emit("{P: }{Lwc:In stock}{:in-stock/%u}\\n", 65);
.Ed
@@ -71,7 +78,8 @@ This single line of code can generate text ("In stock: 65\\n"), XML
lengthy to be listed here).
.Ss Modifier Roles
Modifiers are optional, and indicate the role and formatting of the
-content. The roles are listed below; only one role is permitted:
+content.
+The roles are listed below; only one role is permitted:
.Pp
.Bl -column "M" "Name12341234"
.It Sy "M Name Description"
@@ -91,7 +99,8 @@ content. The roles are listed below; only one role is permitted:
.Ss The Decoration Role ({D:})
Decorations are typically punctuation marks such as colons,
semi-colons, and commas used to decorate the text and make it simpler
-for human readers. By marking these distinctly, HTML usage scenarios
+for human readers.
+By marking these distinctly, HTML usage scenarios
can use CSS to direct their display parameters.
.Bd -literal -offset indent
xo_emit("{D:((}{:name}{D:))}\\n", name);
@@ -116,8 +125,9 @@ if preceded by a slash ("/"):
xo_emit("{P:/30s}{Lwc:Cost}{:cost/%u}\\n", "", cost);
.Ed
.Ss The Title Role ({T:})
-Title are heading or column headers that are meant to be displayed to
-the user. The title can be either static, when placed directly within
+Titles are heading or column headers that are meant to be displayed to
+the user.
+The title can be either static, when placed directly within
the field descriptor, or a printf-style format descriptor can be used,
if preceded by a slash ("/"):
.Bd -literal -offset indent
@@ -126,7 +136,8 @@ if preceded by a slash ("/"):
.Ed
.Ss The Units Role ({U:})
Units are the dimension by which values are measured, such as degrees,
-miles, bytes, and decibels. The units field carries this information
+miles, bytes, and decibels.
+The units field carries this information
for the previous value field.
.Bd -literal -offset indent
xo_emit("{Lwc:Distance}{:distance/%u}{Uw:miles}\\n", miles);
@@ -136,7 +147,7 @@ Note that the sense of the 'w' modifier is reversed for units;
a blank is added before the contents, rather than after it.
.Pp
When the
-.Em XOF_UNITS
+.Dv XOF_UNITS
flag is set, units are rendered in XML as the
.Dq units
attribute:
@@ -151,14 +162,19 @@ Units can also be rendered in HTML as the "data-units" attribute:
.Ed
.Ss The Value Role ({V:} and {:})
The value role is used to represent the a data value that is
-interesting for the non-display output styles (XML and JSON). Value
+interesting for the non-display output styles (XML and JSON).
+Value
is the default role; if no other role designation is given, the field
-is a value. The field name must appear within the field descriptor,
-followed by one or two format descriptors. The first format
+is a value.
+The field name must appear within the field descriptor,
+followed by one or two format descriptors.
+The first format
descriptor is used for display styles (TEXT and HTML), while the
-second one is used for encoding styles (XML and JSON). If no second
+second one is used for encoding styles (XML and JSON).
+If no second
format is given, the encoding format defaults to the first format,
-with any minimum width removed. If no first format is given, both
+with any minimum width removed.
+If no first format is given, both
format descriptors default to "%s".
.Bd -literal -offset indent
xo_emit("{:length/%02u}x{:width/%02u}x{:height/%02u}\\n",
@@ -168,9 +184,13 @@ format descriptors default to "%s".
.Ed
.Ss The Anchor Modifiers ({[:} and {]:})
The anchor roles allow a set of strings by be padded as a group,
-but still be visible to xo_emit as distinct fields. Either the start
+but still be visible to
+.Xr xo_emit 3
+as distinct fields.
+Either the start
or stop anchor can give a field width and it can be either directly in
-the descriptor or passed as an argument. Any fields between the start
+the descriptor or passed as an argument.
+Any fields between the start
and stop anchor are padded to meet the minimum width given.
.Pp
To give a width directly, encode it as the content of the anchor tag:
@@ -179,21 +199,26 @@ To give a width directly, encode it as the content of the anchor tag:
.Ed
.Pp
To pass a width as an argument, use "%d" as the format, which must
-appear after the "/". Note that only "%d" is supported for widths.
+appear after the "/".
+Note that only "%d" is supported for widths.
Using any other value could ruin your day.
.Bd -literal -offset indent
xo_emit("({[:/%d}{:min/%d}/{:max/%d}{]:})\\n", width, min, max);
.Ed
.Pp
If the width is negative, padding will be added on the right, suitable
-for left justification. Otherwise the padding will be added to the
+for left justification.
+Otherwise the padding will be added to the
left of the fields between the start and stop anchors, suitable for
-right justification. If the width is zero, nothing happens. If the
+right justification.
+If the width is zero, nothing happens.
+If the
number of columns of output between the start and stop anchors is less
than the absolute value of the given width, nothing happens.
.Pp
-Widths over 8k are considered probable errors and not supported. If
-.Em XOF_WARN
+Widths over 8k are considered probable errors and not supported.
+If
+.Dv XOF_WARN
is set, a warning will be generated.
.Ss Modifier Flags
The modifiers can also include the following flags, which modify the
@@ -201,19 +226,20 @@ content emitted for some output styles:
.Pp
.Bl -column M "Name12341234"
.It Sy M "Name Description"
-.It c "colon " "A colon (":") is appended after the label"
+.It c "colon " "A colon ("":"") is appended after the label"
.It d "display " "Only emit field for display styles (text/HTML)"
.It e "encoding " "Only emit for encoding styles (XML/JSON)"
.It k "key " "Field is a key, suitable for XPath predicates"
.It n "no-quotes " "Do not quote the field when using JSON style"
.It q "quotes " "Quote the field when using JSON style"
-.It w "white space " "A blank (" ") is appended after the label"
+.It w "white space " "A blank ("" "") is appended after the label"
.El
.Pp
For example, the modifier string "Lwc" means the field has a label
role (text that describes the next field) and should be followed by a
-colon ('c') and a space ('w'). The modifier string "Vkq" means the
-field is has value role, that it is a key for the current instance, and
+colon ('c') and a space ('w').
+The modifier string "Vkq" means the
+field has a value role, that it is a key for the current instance, and
that the value should be quoted when encoded for JSON.
.Ss The Colon Modifier ({c:})
The colon modifier appends a single colon to the data value:
@@ -225,7 +251,8 @@ The colon modifier appends a single colon to the data value:
.Ed
.Pp
The colon modifier is only used for the TEXT and HTML output
-styles. It is commonly combined with the space modifier ('{w:').
+styles.
+It is commonly combined with the space modifier ('{w:}').
It is purely a convenience feature.
.Ss The Display Modifier ({d:})
The display modifier indicated the field should only be generated for
@@ -270,15 +297,34 @@ uniquely identify an instance of list data.
xo_close_list("user");
.Ed
.Pp
-Currently the key modifier is only used when generating XPath value
+Currently the key modifier is only used when generating XPath values
for the HTML output style when
-.Em XOF_XPATH
+.Dv XOF_XPATH
is set, but other uses are likely in the near future.
+.Ss The Leaf-List Modifier ({l:})
+The leaf-list modifier is used to distinguish lists where each
+instance consists of only a single value. In XML, these are
+rendered as single elements, where JSON renders them as arrays.
+.Bd -literal -offset indent
+ EXAMPLE:
+ xo_open_list("user");
+ for (i = 0; i < num_users; i++) {
+ xo_emit("Member {l:name}\n", user[i].u_name);
+ }
+ xo_close_list("user");
+ XML:
+ <user>phil</user>
+ <user>pallavi</user>
+ JSON:
+ "user": [ "phil", "pallavi" ]
+.Ed
.Ss The No-Quotes Modifier ({n:})
The no-quotes modifier (and its twin, the 'quotes' modifier) affect
-the quoting of values in the JSON output style. JSON uses quotes for
-string value, but no quotes for numeric, boolean, and null data.
-xo_emit applies a simple heuristic to determine whether quotes are
+the quoting of values in the JSON output style.
+JSON uses quotes for
+string values, but no quotes for numeric, boolean, and null data.
+.Xr xo_emit 3
+applies a simple heuristic to determine whether quotes are
needed, but often this needs to be controlled by the caller.
.Bd -literal -offset indent
EXAMPLE:
@@ -289,9 +335,11 @@ needed, but often this needs to be controlled by the caller.
.Ed
.Ss The Quotes Modifier ({q:})
The quotes modifier (and its twin, the 'no-quotes' modifier) affect
-the quoting of values in the JSON output style. JSON uses quotes for
-string value, but no quotes for numeric, boolean, and null data.
-xo_emit applies a simple heuristic to determine whether quotes are
+the quoting of values in the JSON output style.
+JSON uses quotes for
+string values, but no quotes for numeric, boolean, and null data.
+.Xr xo_emit 3
+applies a simple heuristic to determine whether quotes are
needed, but often this needs to be controlled by the caller.
.Bd -literal -offset indent
EXAMPLE:
@@ -309,7 +357,8 @@ The white space modifier appends a single space to the data value:
.Ed
.Pp
The white space modifier is only used for the TEXT and HTML output
-styles. It is commonly combined with the colon modifier ('{c:').
+styles.
+It is commonly combined with the colon modifier ('{c:}').
It is purely a convenience feature.
.Pp
Note that the sense of the 'w' modifier is reversed for the units role
@@ -317,16 +366,20 @@ Note that the sense of the 'w' modifier is reversed for the units role
.Ss Field Formatting
The field format is similar to the format string for
.Xr printf 3 .
-It's used varies based on the role of the field, but generally is used to
+Its use varies based on the role of the field, but generally is used to
format the field's contents.
.Pp
-If not provided, the format string defaults to "%s".
+If the format string is not provided for a value field, it defaults
+to "%s".
.Pp
Note a field definition can contain zero or more printf-style
.Dq directives ,
-which are sequences that start with a '%' and end with a
-one of following characters: "diouxXDOUeEfFgGaAcCsSp". Each directive
-is matched by one of more arguments to the xo_emit function.
+which are sequences that start with a '%' and end with
+one of following characters: "diouxXDOUeEfFgGaAcCsSp".
+Each directive
+is matched by one of more arguments to the
+.Xr xo_emit 3
+function.
.Pp
The format string has the form:
.Bd -literal -offset indent
@@ -346,19 +399,22 @@ a leading zero ('0') indicating the output value should be padded on the
left with zeroes instead of spaces (' ').
.It
one or more digits ('0' - '9') indicating the minimum width of the
-argument. If the width in columns of the output value is less that
-the minumum width, the value will be padded to reach the minimum.
+argument.
+If the width in columns of the output value is less than
+the minimum width, the value will be padded to reach the minimum.
.It
a period followed by one or more digits indicating the maximum
number of bytes which will be examined for a string argument, or the maximum
-width for a non-string argument. When handling ASCII strings this is
+width for a non-string argument.
+When handling ASCII strings this
functions as the field width but for multi-byte characters, a single
character may be composed of multiple bytes.
-xo_emit will never dereference memory beyond the given number of bytes.
+.Xr xo_emit 3
+will never dereference memory beyond the given number of bytes.
.It
a second period followed by one or more digits indicating the maximum
-width for a string argument. This modifier cannot be given for non-string
-arguments.
+width for a string argument.
+This modifier cannot be given for non-string arguments.
.It
one or more 'h' characters, indicating shorter input data.
.It
@@ -420,39 +476,50 @@ argument:
.El
.Pp
.Ss UTF-8 and Locale Strings
-All strings for libxo must be UTF-8. libxo will handle turning them
+All strings for
+.Nm libxo
+must be UTF-8.
+.Nm libxo
+will handle turning them
into locale-based strings for display to the user.
.Pp
For strings, the 'h' and 'l' modifiers affect the interpretation of
-the bytes pointed to argument. The default '%s' string is a 'char *'
-pointer to a string encoded as UTF-8. Since UTF-8 is compatible with
+the bytes pointed to argument.
+The default '%s' string is a 'char *'
+pointer to a string encoded as UTF-8.
+Since UTF-8 is compatible with
.Em ASCII
data, a normal 7-bit
.Em ASCII
- string can be used. '%ls' expects a
-'wchar_t *' pointer to a wide-character string, encoded as a 32-bit
-Unicode values. '%hs' expects a 'char *' pointer to a multi-byte
+string can be used.
+'%ls' expects a
+'wchar_t *' pointer to a wide-character string, encoded as 32-bit
+Unicode values.
+'%hs' expects a 'char *' pointer to a multi-byte
string encoded with the current locale, as given by the
-.Em LC_CTYPE ,
-.Em LANG ,
+.Ev LC_CTYPE ,
+.Ev LANG ,
or
-.Em LC_ALL
-environment varibles. The first of this list of
-variables is used and if none of the variables, the locale defaults to
-.Em UTF-8.
-.Pp
-libxo will
+.Ev LC_ALL
+environment variables.
+The first of this list of
+variables is used and if none of the variables are set, the locale defaults to
+.Em UTF-8 .
+.Pp
+.Nm libxo
+will
convert these arguments as needed to either UTF-8 (for XML, JSON, and
HTML styles) or locale-based strings for display in text style.
.Bd -literal -offset indent
- xo_emit("Alll strings are utf-8 content {:tag/%ls}",
+ xo_emit("All strings are utf-8 content {:tag/%ls}",
L"except for wide strings");
.Ed
.Pp
"%S" is equivalent to "%ls".
.Pp
For example, a function is passed a locale-base name, a hat size,
-and a time value. The hat size is formatted in a UTF-8 (ASCII)
+and a time value.
+The hat size is formatted in a UTF-8 (ASCII)
string, and the time value is formatted into a wchar_t string.
.Bd -literal -offset indent
void print_order (const char *name, int size,
@@ -475,29 +542,35 @@ string, and the time value is formatted into a wchar_t string.
}
.Ed
.Pp
-It is important to note that xo_emit will perform the conversion
-required to make appropriate output. Text style output uses the
+It is important to note that
+.Xr xo_emit 3
+will perform the conversion
+required to make appropriate output.
+Text style output uses the
current locale (as described above), while XML, JSON, and HTML use
UTF-8.
.Pp
UTF-8 and locale-encoded strings can use multiple bytes to encode one
-column of data. The traditional "precision'" (aka "max-width") value
+column of data.
+The traditional "precision'" (aka "max-width") value
for "%s" printf formatting becomes overloaded since it specifies both
the number of bytes that can be safely referenced and the maximum
-number of columns to emit. xo_emit uses the precision as the former,
+number of columns to emit.
+.Xr xo_emit 3
+uses the precision as the former,
and adds a third value for specifying the maximum number of columns.
.Pp
In this example, the name field is printed with a minimum of 3 columns
-and a maximum of 6. Up to ten bytes are in used in filling those
-columns.
+and a maximum of 6.
+Up to ten bytes are in used in filling those columns.
.Bd -literal -offset indent
xo_emit("{:name/%3.10.6s}", name);
.Ed
.Ss Characters Outside of Field Definitions
-Characters in the format string are not part of a field definition are
+Characters in the format string that are not part of a field definition are
copied to the output for the TEXT style, and are ignored for the JSON
-and XML styles. For HTML, these characters are placed in a <div> with
-class "text".
+and XML styles.
+For HTML, these characters are placed in a <div> with class "text".
.Bd -literal -offset indent
EXAMPLE:
xo_emit("The hat is {:size/%s}.\\n", size_val);
@@ -513,13 +586,16 @@ class "text".
<div class="text">.</div>
.Ed
.Ss "%n" is Not Supported
-libxo does not support the '%n' directive. It's a bad idea and we
-just don't do it.
+.Nm libxo
+does not support the '%n' directive.
+It is a bad idea and we
+just do not do it.
.Ss The Encoding Format (eformat)
The "eformat" string is the format string used when encoding the field
-for JSON and XML. If not provided, it defaults to the primary format
-with any minimum width removed. If the primary is not given, both
-default to "%s".
+for JSON and XML.
+If not provided, it defaults to the primary format
+with any minimum width removed.
+If the primary is not given, both default to "%s".
.Sh EXAMPLE
In this example, the value for the number of items in stock is emitted:
.Bd -literal -offset indent
@@ -547,9 +623,9 @@ This call will generate the following output:
.Pp
Clearly HTML wins the verbosity award, and this output does
not include
-.Em XOF_XPATH
+.Dv XOF_XPATH
or
-.Em XOF_INFO
+.Dv XOF_INFO
data, which would expand the penultimate line to:
.Bd -literal -offset indent
<div class="data" data-tag="in-stock"
@@ -561,28 +637,33 @@ data, which would expand the penultimate line to:
To make useful, consistent field names, follow these guidelines:
.Pp
.Ss Use lower case, even for TLAs
-Lower case is more civilized. Even TLAs should be lower case
+Lower case is more civilized.
+Even TLAs should be lower case
to avoid scenarios where the differences between "XPath" and
-"Xpath" drive your users crazy. Using "xpath" is simpler and better.
+"Xpath" drive your users crazy.
+Using "xpath" is simpler and better.
.Ss Use hyphens, not underscores
Use of hyphens is traditional in XML, and the
-.Em XOF_UNDERSCORES
+.Dv XOF_UNDERSCORES
flag can be used to generate underscores in JSON, if desired.
But the raw field name should use hyphens.
-.Se Use full words
-Don't abbreviate especially when the abbreviation is not obvious or
-not widely used. Use "data-size", not "dsz" or "dsize". Use
+.Ss Use full words
+Do not abbreviate especially when the abbreviation is not obvious or
+not widely used.
+Use "data-size", not "dsz" or "dsize".
+Use
"interface" instead of "ifname", "if-name", "iface", "if", or "intf".
-.Se Use <verb>-<units>
+.Ss Use <verb>-<units>
Using the form <verb>-<units> or <verb>-<classifier>-<units> helps in
making consistent, useful names, avoiding the situation where one app
uses "sent-packet" and another "packets-sent" and another
-"packets-we-have-sent". The <units> can be dropped when it is
+"packets-we-have-sent".
+The <units> can be dropped when it is
obvious, as can obvious words in the classification.
Use "receive-after-window-packets" instead of
"received-packets-of-data-after-window".
-.Se Reuse existing field names
-Nothing's worse than writing expressions like:
+.Ss Reuse existing field names
+Nothing is worse than writing expressions like:
.Bd -literal -offset indent
if ($src1/process[pid == $pid]/name ==
$src2/proc-table/proc/p[process-id == $pid]/proc-name) {
@@ -591,32 +672,38 @@ Nothing's worse than writing expressions like:
.Ed
.Pp
Find someone else who is expressing similar data and follow their
-field's and hierarchy. Remember the quote is not
+fields and hierarchy.
+Remember the quote is not
.Dq Consistency is the hobgoblin of little minds
but
-.Dq A foolish consistency is the hobgoblin of little minds.
+.Dq A foolish consistency is the hobgoblin of little minds .
.Ss Think about your users
Have empathy for your users, choosing clear and useful fields that
-contain clear and useful data. You may need to augment the display
-content with
+contain clear and useful data.
+You may need to augment the display content with
.Xr xo_attr 3
calls or "{e:}" fields to make the data useful.
-.Ss Don't use an arbitrary number postfix
-What does "errors2" mean? No one will know. "errors-after-restart"
-would be a better choice. Think of you users, and think of the
-future. If you make "errors2", the next guy will happily make
-"errors3" and before you know it, someone will be asking what's the
+.Ss Do not use an arbitrary number postfix
+What does "errors2" mean?
+No one will know.
+"errors-after-restart" would be a better choice.
+Think of your users, and think of the future.
+If you make "errors2", the next guy will happily make
+"errors3" and before you know it, someone will be asking what is the
difference between errors37 and errors63.
.Ss Be consistent, uniform, unsurprising, and predictable
-Think of your field vocabulary as an API. You want it useful,
-expressive, meaningful, direct, and obvious. You want the client
+Think of your field vocabulary as an API.
+You want it useful,
+expressive, meaningful, direct, and obvious.
+You want the client
application's programmer to move between without the need to
-understand a variety of opinions on how fields are named. They should
+understand a variety of opinions on how fields are named.
+They should
see the system as a single cohesive whole, not a sack of cats.
.Pp
Field names constitute the means by which client programmers interact
-with our system. By choosing wise names now, you are making their
-lives better.
+with our system.
+By choosing wise names now, you are making their lives better.
.Pp
After using
.Xr xolint 1
@@ -628,30 +715,36 @@ names for the same data.
and
.Dq dropped-too-short
are both reasonable names, but using them both will lead users to ask the
-difference between the two fields. If there isn't a difference,
-use only one of the field names. If there is a difference, change the
+difference between the two fields.
+If there is no difference,
+use only one of the field names.
+If there is a difference, change the
names to make that difference more obvious.
.Sh ADDITIONAL DOCUMENTATION
-.Pp
Complete documentation can be found on github:
.Bd -literal -offset indent
http://juniper.github.io/libxo/libxo-manual.html
.Ed
.Pp
-libxo lives on github as:
+.Nm libxo
+lives on github as:
.Bd -literal -offset indent
https://github.com/Juniper/libxo
.Ed
.Pp
-The latest release of libxo is available at:
+The latest release of
+.Nm libxo
+is available at:
.Bd -literal -offset indent
https://github.com/Juniper/libxo/releases
.Ed
.Sh SEE ALSO
+.Xr xolint 1 ,
.Xr xo_emit 3
.Sh HISTORY
The
-.Fa libxo
-library was added in FreeBSD 11.0.
+.Nm libxo
+library was added in
+.Fx 11.0 .
.Sh AUTHOR
Phil Shafer
diff --git a/contrib/libxo/libxo/xo_no_setlocale.3 b/contrib/libxo/libxo/xo_no_setlocale.3
index 94a126440f83..c3f32a403d03 100644
--- a/contrib/libxo/libxo/xo_no_setlocale.3
+++ b/contrib/libxo/libxo/xo_no_setlocale.3
@@ -7,12 +7,13 @@
.\" # LICENSE.
.\" # Phil Shafer, July 2014
.\"
-.Dd July, 2014
+.Dd December 4, 2014
.Dt LIBXO 3
.Os
.Sh NAME
.Nm xo_no_setlocale
-.Nd prevent implicit call to setlocale()
+.Nd prevent implicit call to
+.Fn setlocale
.Sh LIBRARY
.Lb libxo
.Sh SYNOPSIS
@@ -20,44 +21,48 @@
.Ft void
.Fn xo_no_setlocale "void"
.Sh DESCRIPTION
-.Em libxo
-automatically initializes the locale based on setting of the
+.Nm libxo
+automatically initializes the locale based on the setting of the
environment variables
-.Em LC_CTYPE ,
-.Em LANG ,
+.Ev LC_CTYPE ,
+.Ev LANG ,
and
-.Em LC_ALL .
+.Ev LC_ALL .
The first of this
-list of variables is used and if none of the variables, the locale
+list of variables is used and if none of the variables are set, the locale
defaults to
-.Em UTF-8. The caller may wish to avoid this behavior, and
+.Em UTF-8 .
+The caller may wish to avoid this behavior, and
can do so by calling the
.Fn xo_no_setlocale
function.
.Sh ADDITIONAL DOCUMENTATION
-.Pp
Complete documentation can be found on github:
.Bd -literal -offset indent
http://juniper.github.io/libxo/libxo-manual.html
.Ed
.Pp
-libxo lives on github as:
+.Nm libxo
+lives on github as:
.Bd -literal -offset indent
https://github.com/Juniper/libxo
.Ed
.Pp
-The latest release of libxo is available at:
+The latest release of
+.Nm libxo
+is available at:
.Bd -literal -offset indent
https://github.com/Juniper/libxo/releases
.Ed
.Sh SEE ALSO
.Xr xo_emit 3 ,
.Xr xo_open_container 3 ,
-.Xr xo_open_list 3 , and
-.Xr xo_format 5 .
+.Xr xo_open_list 3 ,
+.Xr xo_format 5
.Sh HISTORY
The
-.Fa libxo
-library was added in FreeBSD 11.0.
+.Nm libxo
+library was added in
+.Fx 11.0 .
.Sh AUTHOR
Phil Shafer
diff --git a/contrib/libxo/libxo/xo_open_container.3 b/contrib/libxo/libxo/xo_open_container.3
index 9ba32c98f6f4..86412ca91da7 100644
--- a/contrib/libxo/libxo/xo_open_container.3
+++ b/contrib/libxo/libxo/xo_open_container.3
@@ -7,7 +7,7 @@
.\" # LICENSE.
.\" # Phil Shafer, July 2014
.\"
-.Dd July, 2014
+.Dd December 4, 2014
.Dt LIBXO 3
.Os
.Sh NAME
@@ -47,13 +47,14 @@
.Ft int
.Fn xo_close_container_d "void"
.Sh DESCRIPTION
-.Fa libxo
+.Nm libxo
represents to types of hierarchy:
.Dq containers
and
.Dq lists .
A container appears once under a given parent where a list contains
-instances that can appear multiple times. A container is used to hold
+instances that can appear multiple times.
+A container is used to hold
related fields and to give the data organization and scope.
The container has no value, but serves to
contain other nodes.
@@ -71,8 +72,9 @@ or
.Fn xo_close_container_h
functions.
.Pp
-Each open call must have a matching close call. If the
-.Fa XOF_WARN
+Each open call must have a matching close call.
+If the
+.Dv XOF_WARN
flag is set and the name given does not match the name of
the currently open
container, a warning will be generated.
@@ -115,8 +117,8 @@ The
.Fa handle
parameter contains a handle such as returned by
.Xr xo_create 3
-or a
-.Em NULL
+or
+.Dv NULL
to use the default handle.
The
.Fa name
@@ -134,18 +136,18 @@ suffix are used in
.Dq \&Do The Right Thing
mode, where the name of the open containers, lists, and
instances are maintained internally by
-.Em libxo
+.Nm libxo
to allow the caller to
avoid keeping track of the open container name.
.Pp
Use the
-.Em XOF_WARN
+.Dv XOF_WARN
flag to generate a warning if the name given on the
close does not match the current open container.
.Pp
For TEXT and HTML output, containers are not rendered into output
text, though for HTML they are used when the
-.Em XOF_XPATH
+.Dv XOF_XPATH
flag is set.
.Pp
.Bd -literal -offset indent -compact
@@ -157,21 +159,22 @@ flag is set.
<system><host-name>foo</host-name></system>
.Ed
.Sh DTRT MODE
-Some user may find tracking the names of open containers, lists, and
+Some users may find tracking the names of open containers, lists, and
instances inconvenient.
-.Em libxo
-offers
+.Nm libxo
+offers a
.Dq \&Do The Right Thing
mode, where
-.Em libxo
+.Nm libxo
will track the names of open containers, lists, and instances so
-the close function can be called without a name. To enable
+the close function can be called without a name.
+To enable
.Em DTRT
mode,
turn on the
-.Em XOF_DTRT
+.Dv XOF_DTRT
flag prior to making any other
-.Em libxo
+.Nm libxo
output.
.Bd -literal -offset indent -compact
xo_set_flags(NULL, XOF_DTRT);
@@ -185,24 +188,28 @@ which will close the open container, list, or instance:
xo_close_container_d();
.Ed
Note that the
-.Em XOF_WARN
-flag will also cause libxo to track open
+.Dv XOF_WARN
+flag will also cause
+.Nm libxo
+to track open
containers, lists, and instances.
-A warning is generated with the name given to the close function
+A warning is generated when the name given to the close function
and the name recorded do not match.
.Sh ADDITIONAL DOCUMENTATION
-.Pp
Complete documentation can be found on github:
.Bd -literal -offset indent
http://juniper.github.io/libxo/libxo-manual.html
.Ed
.Pp
-libxo lives on github as:
+.Nm libxo
+lives on github as:
.Bd -literal -offset indent
https://github.com/Juniper/libxo
.Ed
.Pp
-The latest release of libxo is available at:
+The latest release of
+.Nm libxo
+is available at:
.Bd -literal -offset indent
https://github.com/Juniper/libxo/releases
.Ed
@@ -210,7 +217,8 @@ https://github.com/Juniper/libxo/releases
.Xr xo_emit 3
.Sh HISTORY
The
-.Fa libxo
-library was added in FreeBSD 11.0.
+.Nm libxo
+library was added in
+.Fx 11.0 .
.Sh AUTHOR
Phil Shafer
diff --git a/contrib/libxo/libxo/xo_open_list.3 b/contrib/libxo/libxo/xo_open_list.3
index 9a6a21504c7c..047af87596fa 100644
--- a/contrib/libxo/libxo/xo_open_list.3
+++ b/contrib/libxo/libxo/xo_open_list.3
@@ -7,7 +7,7 @@
.\" # LICENSE.
.\" # Phil Shafer, July 2014
.\"
-.Dd July, 2014
+.Dd December 4, 2014
.Dt LIBXO 3
.Os
.Sh NAME
@@ -71,19 +71,23 @@
.Ft int
.Fn xo_close_list_d "void"
.Sh DESCRIPTION
-Lists are sequences of instances of homogeneous data objects. Two
+Lists are sequences of instances of homogeneous data objects.
+Two
distinct levels of calls are needed to represent them in our output
-styles. Calls must be made to open and close a list, and for each
+styles.
+Calls must be made to open and close a list, and for each
instance of data in that list, calls must be make to open and close
that instance.
.Pp
-The name given to all calls must be identical, and it is strong
+The name given to all calls must be identical, and it is strongly
suggested that the name be singular, not plural, as a matter of
style and usage expectations.
.Pp
-A list is set of one or more instances that appear under the same
-parent. The instances contains details about a specific object. One
-can think of instances as objects or records. A call is needed to
+A list is a 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:
.Bd -literal -offset indent -compact
@@ -143,19 +147,45 @@ generation of XML and JSON data.
}
]
.Ed
-.Sh ADDITIONAL DOCUMENTATION
.Pp
+.Sh LEAF LISTS
+In contrast to a list of instances, a "leaf list" is list of simple
+values.
+To emit a leaf list, call the
+.Fn xo_emit
+function using the ""l"" modifier:
+.Bd -literal -offset indent -compact
+ for (ip = list; ip->i_title; ip++) {
+ xo_emit("{Lwc:Item}{l:item}\n", ip->i_title);
+ }
+.Ed
+.Pp
+The name of the field must match the name of the leaf list.
+.Pp
+In JSON, leaf lists are rendered as arrays of values. In XML, they
+are rendered as multiple leaf elements.
+.Bd -literal -offset indent -compact
+ JSON:
+ "item": "hammer", "nail"
+ XML:
+ <item>hammer</item>
+ <item>nail</item>
+.Ed
+.Sh ADDITIONAL DOCUMENTATION
Complete documentation can be found on github:
.Bd -literal -offset indent
http://juniper.github.io/libxo/libxo-manual.html
.Ed
.Pp
-libxo lives on github as:
+.Nm libxo
+lives on github as:
.Bd -literal -offset indent
https://github.com/Juniper/libxo
.Ed
.Pp
-The latest release of libxo is available at:
+The latest release of
+.Nm libxo
+is available at:
.Bd -literal -offset indent
https://github.com/Juniper/libxo/releases
.Ed
@@ -163,7 +193,8 @@ https://github.com/Juniper/libxo/releases
.Xr xo_emit 3
.Sh HISTORY
The
-.Fa libxo
-library was added in FreeBSD 11.0.
+.Nm libxo
+library was added in
+.Fx 11.0 .
.Sh AUTHOR
Phil Shafer
diff --git a/contrib/libxo/libxo/xo_parse_args.3 b/contrib/libxo/libxo/xo_parse_args.3
index a9b4cec29b30..f66546bd3c9e 100644
--- a/contrib/libxo/libxo/xo_parse_args.3
+++ b/contrib/libxo/libxo/xo_parse_args.3
@@ -7,27 +7,31 @@
.\" # LICENSE.
.\" # Phil Shafer, July 2014
.\"
-.Dd July, 2014
+.Dd December 4, 2014
.Dt LIBXO 3
.Os
.Sh NAME
.Nm xo_parse_args
.Nd detect, parse, and remove arguments for libxo
.Sh LIBRARY
-.Nm libxo
+.Lb libxo
.Sh SYNOPSIS
.In libxo/xo.h
.Ft int
.Fn xo_parse_args "int argc" "char **argv"
+.Ft int
+.Fn xo_set_program "const char *name"
.Sh DESCRIPTION
The
.Fn xo_parse_args
function is used to process command-line arguments.
-.Em libxo -specific
+.Nm libxo
+specific
options are processed and removed
from the argument list so the calling application does not
-need to process them. If successful, a new value for argc
-is returned. On failure, a message it emitted and -1 is returned.
+need to process them.
+If successful, a new value for argc is returned.
+On failure, a message it emitted and -1 is returned.
.Bd -literal -offset indent
argc = xo_parse_args(argc, argv);
if (argc < 0)
@@ -38,9 +42,9 @@ Following the call to
.Fn xo_parse_args ,
the application can process the remaining arguments in a normal manner.
.Pp
-.Em libxo
-uses command line options to trigger rendering behavior. The
-following options are recognised:
+.Nm libxo
+uses command line options to trigger rendering behavior.
+The following options are recognised:
.Pp
.Bl -tag -width "--libxo"
.It
@@ -56,44 +60,45 @@ styles, flags, or features:
.Pp
.Bl -tag -width "12345678"
.It Sy "Token Action"
-.It dtrt
+.It Dv dtrt
Enable "Do The Right Thing" mode
-.It html
+.It Dv html
Emit HTML output
-.It indent=xx
+.It Dv indent=xx
Set the indentation level
-.It info
+.It Dv info
Add info attributes (HTML)
-.It json
+.It Dv json
Emit JSON output
-.It keys
+.It Dv keys
Emit the key attribute for keys (XML)
-.It no-locale
+.It Dv no-locale
Do not initialize the locale setting
-.It no-top
+.It Dv no-top
Do not emit a top set of braces (JSON)
-.It not-first
+.It Dv not-first
Pretend the 1st output item was not 1st (JSON)
-.It pretty
+.It Dv pretty
Emit pretty-printed output
-.It text
+.It Dv text
Emit TEXT output
-.It units
+.It Dv units
Add the 'units' (XML) or 'data-units (HTML) attribute
-.It warn
+.It Dv warn
Emit warnings when libxo detects bad calls
-.It warn-xml
+.It Dv warn-xml
Emit warnings in XML
-.It xml
+.It Dv xml
Emit XML output
-.It xpath
+.It Dv xpath
Add XPath expressions (HTML)
.El
.Pp
The
.Dq brief-options
are single letter commands, designed for those with
-too little patience to use real tokens. No comma separator is used.
+too little patience to use real tokens.
+No comma separator is used.
.Bl -column "i<num>"
.It Sy "Token Action"
.It "H " "Enable HTML output (XO_STYLE_HTML)"
@@ -107,19 +112,41 @@ too little patience to use real tokens. No comma separator is used.
.It "x " "Enable XPath data (XOF_XPATH)"
.El
.Pp
-.Sh ADDITIONAL DOCUMENTATION
+The
+.Fn xo_set_program
+function sets name of the program as reported by
+functions like
+.Fn xo_failure ,
+.Fn xo_warn ,
+.Fn xo_err ,
+etc.
+The program name is initialized by
+.Fn xo_parse_args ,
+but subsequent calls to
+.Fn xo_set_program
+can override this value.
+.Pp
+Note that the value is not copied, so the memory passed to
+.Fn xo_set_program
+(and
+.Fn xo_parse_args )
+must be maintained by the caller.
.Pp
+.Sh ADDITIONAL DOCUMENTATION
Complete documentation can be found on github:
.Bd -literal -offset indent
http://juniper.github.io/libxo/libxo-manual.html
.Ed
.Pp
-libxo lives on github as:
+.Nm libxo
+lives on github as:
.Bd -literal -offset indent
https://github.com/Juniper/libxo
.Ed
.Pp
-The latest release of libxo is available at:
+The latest release of
+.Nm libxo
+is available at:
.Bd -literal -offset indent
https://github.com/Juniper/libxo/releases
.Ed
@@ -127,7 +154,8 @@ https://github.com/Juniper/libxo/releases
.Xr xo_emit 3
.Sh HISTORY
The
-.Fa libxo
-library was added in FreeBSD 11.0.
+.Nm libxo
+library was added in
+.Fx 11.0 .
.Sh AUTHOR
Phil Shafer
diff --git a/contrib/libxo/libxo/xo_set_allocator.3 b/contrib/libxo/libxo/xo_set_allocator.3
index 508cc8e9af53..70bfdd59a45d 100644
--- a/contrib/libxo/libxo/xo_set_allocator.3
+++ b/contrib/libxo/libxo/xo_set_allocator.3
@@ -7,7 +7,7 @@
.\" # LICENSE.
.\" # Phil Shafer, July 2014
.\"
-.Dd July, 2014
+.Dd December 4, 2014
.Dt LIBXO 3
.Os
.Sh NAME
@@ -25,7 +25,9 @@
.Sh DESCRIPTION
The
.Fn xo_set_allocator
-function allows libxo to be used in environments
+function allows
+.Nm libxo
+to be used in environments
where the standard
.Xr realloc 3
and
@@ -40,7 +42,7 @@ a pointer to memory following the same convention.
.Fa free_func
will receive the same argument as
.Xr free 3
-and should release it, asappropriate for the environment.
+and should release it, as appropriate for the environment.
.Pp
By default, the standard
.Xr realloc 3
@@ -48,18 +50,20 @@ and
.Xr free 3
functions are used.
.Sh ADDITIONAL DOCUMENTATION
-.Pp
Complete documentation can be found on github:
.Bd -literal -offset indent
http://juniper.github.io/libxo/libxo-manual.html
.Ed
.Pp
-libxo lives on github as:
+.Nm libxo
+lives on github as:
.Bd -literal -offset indent
https://github.com/Juniper/libxo
.Ed
.Pp
-The latest release of libxo is available at:
+The latest release of
+.Nm libxo
+is available at:
.Bd -literal -offset indent
https://github.com/Juniper/libxo/releases
.Ed
@@ -67,7 +71,8 @@ https://github.com/Juniper/libxo/releases
.Xr xo_emit 3
.Sh HISTORY
The
-.Fa libxo
-library was added in FreeBSD 11.0.
+.Nm libxo
+library was added in
+.Fx 11.0 .
.Sh AUTHOR
Phil Shafer
diff --git a/contrib/libxo/libxo/xo_set_flags.3 b/contrib/libxo/libxo/xo_set_flags.3
index a23de7bfdd7b..ca6655360d21 100644
--- a/contrib/libxo/libxo/xo_set_flags.3
+++ b/contrib/libxo/libxo/xo_set_flags.3
@@ -7,7 +7,7 @@
.\" # LICENSE.
.\" # Phil Shafer, July 2014
.\"
-.Dd July, 2014
+.Dd December 4, 2014
.Dt LIBXO 3
.Os
.Sh NAME
@@ -25,96 +25,121 @@
Use the
.Fn xo_set_flags
function to set the flags for a
-.Em libxo
-handle. To use the default handle, pass a NULL handle.
+.Nm libxo
+handle.
+To use the default handle, pass a
+.Dv NULL
+handle.
.Pp
The set of valid flags include:
.Bl -tag -width "XOF_UNDERSCORES"
.It Sy "Flag Description"
-.It XOF_CLOSE_FP
-Close file pointer on xo_destroy(). This
-flag will trigger the call of the close_func
+.It Dv XOF_CLOSE_FP
+Close file pointer on
+.Xr xo_destroy 3 .
+This flag will trigger the call of the
+.Fn close_func
(provided via
-.Fn xo_set_writer 3 )
+.Xr xo_set_writer 3 )
when the handle is destroyed.
-.It XOF_DTRT
+.It Dv XOF_DTRT
Enable "do the right thing" mode
-.It XOF_INFO
+.It Dv XOF_INFO
Display info data attributes (HTML)
-.It XOF_KEYS
+.It Dv XOF_KEYS
Emit the key attribute (XML)
-.It XOF_NO_ENV
-Do not use the LIBXO_OPTIONS env var
-.It XOF_PRETTY
+.It Dv XOF_NO_ENV
+Do not use the
+.Ev LIBXO_OPTIONS
+environment variable.
+.It Dv XOF_PRETTY
Make 'pretty printed' output, with the
addition of indentation and newlines to enhance the readability of
-XML, JSON, and HTML output. Text output is not affected.
-.It XOF_UNDERSCORES
+XML, JSON, and HTML output.
+Text output is not affected.
+.It Dv XOF_UNDERSCORES
Replaces hyphens with underscores
-.It XOF_UNITS
+.It Dv XOF_UNITS
Display units (XML and HMTL)
-.It XOF_WARN
+.It Dv XOF_WARN
Generate warnings for broken calls, triggering diagnostic
output (on standard error) when the library notices errors during
-operations, or with arguments to functions. Without warning enabled,
-such conditions are ignored.
-Warnings allow developers to debug their interaction with libxo.
-The function "xo_failure" can used as a breakpoint for a debugger,
+operations, or with arguments to functions.
+Without warnings enabled, such conditions are ignored.
+Warnings allow developers to debug their interaction with
+.Nm libxo .
+The function
+.Fn xo_failure
+can be used as a breakpoint for a debugger,
regardless of whether warnings are enabled.
-.It XOF_WARN_XML
+.It Dv XOF_WARN_XML
Generate warnings in XML on stdout
-.It XOF_XPATH
+.It Dv XOF_XPATH
Emit XPath expressions (HTML)
-.It XOF_COLUMNS
-Force xo_emit to return columns used
-.It XOF_FLUSH
-Flush output after each xo_emit call
+.It Dv XOF_COLUMNS
+Force
+.Xr xo_emit 3
+to return columns used
+.It Dv XOF_FLUSH
+Flush output after each
+.Xr xo_emit 3
+call
.El
.Pp
-If the style is XO_STYLE_HTML, the following additional flags can be
+If the style is
+.Dv XO_STYLE_HTML ,
+the following additional flags can be
used:
.Bl -tag -width "XOF_UNDERSCORES"
.It Sy "Flag Description"
-.It XOF_XPATH
+.It Dv XOF_XPATH
Emit "data-xpath" attributes
-.It XOF_INFO
+.It Dv XOF_INFO
Emit additional informational fields for HTML
-output. See
+output.
+See
.Xr xo_set_info 3
for details.
.El
.Pp
The
-.Em XOF_XPATH
+.Dv XOF_XPATH
flag enables the emission of XPath expressions detailing
the hierarchy of XML elements used to encode the data field, if the
XPATH style of output were requested.
.Pp
-If the style is XO_STYLE_XML, the following additional flags can be
+If the style is
+.Dv XO_STYLE_XML ,
+the following additional flags can be
used:
.Bl -tag -width "XOF_UNDERSCORES"
.It Sy "Flag Description"
.It XOF_KEYS
Add 'key' attribute to the XML encoding for
-field definitions that use the 'k' modifier. The key attribute has
+field definitions that use the 'k' modifier.
+The key attribute has
the value "key".
.El
.Pp
-The xo_clear_flags() function turns off the given flags in a specific
+The
+.Fn xo_clear_flags
+function turns off the given flags in a specific
handle.
.Sh ADDITIONAL DOCUMENTATION
-.Pp
Complete documentation can be found on github:
.Bd -literal -offset indent
http://juniper.github.io/libxo/libxo-manual.html
.Ed
.Pp
-libxo lives on github as:
+.Nm libxo
+lives on github as:
.Bd -literal -offset indent
https://github.com/Juniper/libxo
.Ed
.Pp
-The latest release of libxo is available at:
+The latest release of
+.Nm libxo
+is available at:
.Bd -literal -offset indent
https://github.com/Juniper/libxo/releases
.Ed
@@ -122,7 +147,8 @@ https://github.com/Juniper/libxo/releases
.Xr xo_emit 3
.Sh HISTORY
The
-.Fa libxo
-library was added in FreeBSD 11.0.
+.Nm libxo
+library was added in
+.Fx 11.0 .
.Sh AUTHOR
Phil Shafer
diff --git a/contrib/libxo/libxo/xo_set_info.3 b/contrib/libxo/libxo/xo_set_info.3
index dbb3c9c88c93..4f8c5877c72a 100644
--- a/contrib/libxo/libxo/xo_set_info.3
+++ b/contrib/libxo/libxo/xo_set_info.3
@@ -7,7 +7,7 @@
.\" # LICENSE.
.\" # Phil Shafer, July 2014
.\"
-.Dd July, 2014
+.Dd December 4, 2014
.Dt LIBXO 3
.Os
.Sh NAME
@@ -21,19 +21,23 @@
.Fn xo_set_info "xo_handle_t *handle" "xo_info_t *info" "int count"
.Sh DESCRIPTION
HTML data can include additional information in attributes that
-begin with "data-". To enable this, three things must occur:
+begin with "data-".
+To enable this, three things must occur:
.Pp
-First the application must build an array of xo_info_t structures,
-one per tag. The array must be sorted by name, since
-.Em libxo
+First the application must build an array of
+.Dv xo_info_t
+structures,
+one per tag.
+The array must be sorted by name, since
+.Nm libxo
uses a
binary search to find the entry that matches names from format
instructions.
.Pp
The
-.Em xo_info_t
+.Dv xo_info_t
structure is defined in
-.Em <libxo/xo.h> :
+.In libxo/xo.h :
.Bd -literal -offset indent
typedef struct xo_info_s {
const char *xi_name; /* Name of the element */
@@ -43,21 +47,27 @@ structure is defined in
.Ed
.Pp
Second, the application must inform
-.Em libxo
+.Nm libxo
about this information using the
.Fn xo_set_info
-call. Like other libxo calls, passing NULL for the handle tells
-.Em libxo
+call.
+Like other
+.Nm libxo
+calls, passing
+.Dv NULL
+for the handle tells
+.Nm libxo
to use the default handle.
.Pp
If the
.Fa count
is -1,
-.Em libxo
+.Nm libxo
will count the elements of
.Fa info ,
but there
-must be an empty element at the end. More typically, the number is
+must be an empty element at the end.
+More typically, the number is
known to the application:
.Bd -literal -offset indent
xo_info_t info[] = {
@@ -72,8 +82,8 @@ known to the application:
xo_set_info(NULL, info, info_count);
.Ed
.Pp
-Third, the emitting of info must be triggered with the
-.Em XOF_INFO
+Third, the emission of info must be triggered with the
+.Dv XOF_INFO
flag
using either the
.Fn xo_set_flags
@@ -88,18 +98,20 @@ and "data-help" attributes:
data-help="Stock Keeping Unit">GRO-000-533</div>
.Ed
.Sh ADDITIONAL DOCUMENTATION
-.Pp
Complete documentation can be found on github:
.Bd -literal -offset indent
http://juniper.github.io/libxo/libxo-manual.html
.Ed
.Pp
-libxo lives on github as:
+.Nm libxo
+lives on github as:
.Bd -literal -offset indent
https://github.com/Juniper/libxo
.Ed
.Pp
-The latest release of libxo is available at:
+The latest release of
+.Nm libxo
+is available at:
.Bd -literal -offset indent
https://github.com/Juniper/libxo/releases
.Ed
@@ -107,7 +119,8 @@ https://github.com/Juniper/libxo/releases
.Xr xo_emit 3
.Sh HISTORY
The
-.Fa libxo
-library was added in FreeBSD 11.0.
+.Nm libxo
+library was added in
+.Fx 11.0 .
.Sh AUTHOR
Phil Shafer
diff --git a/contrib/libxo/libxo/xo_set_options.3 b/contrib/libxo/libxo/xo_set_options.3
index af7e95cdcce1..bedbf912da15 100644
--- a/contrib/libxo/libxo/xo_set_options.3
+++ b/contrib/libxo/libxo/xo_set_options.3
@@ -7,12 +7,12 @@
.\" # LICENSE.
.\" # Phil Shafer, July 2014
.\"
-.Dd July, 2014
+.Dd December 4, 2014
.Dt LIBXO 3
.Os
.Sh NAME
-.Nm xo_emit
-.Nd emit formatted output based on format string and arguments
+.Nm xo_set_options
+.Nd change options used by a handle
.Sh LIBRARY
.Lb libxo
.Sh SYNOPSIS
@@ -27,18 +27,20 @@ and flags and enables them for a specific handle.
The options are identical to those listed in
.Xr xo_parse_args 3 .
.Sh ADDITIONAL DOCUMENTATION
-.Pp
Complete documentation can be found on github:
.Bd -literal -offset indent
http://juniper.github.io/libxo/libxo-manual.html
.Ed
.Pp
-libxo lives on github as:
+.Nm libxo
+lives on github as:
.Bd -literal -offset indent
https://github.com/Juniper/libxo
.Ed
.Pp
-The latest release of libxo is available at:
+The latest release of
+.Nm libxo
+is available at:
.Bd -literal -offset indent
https://github.com/Juniper/libxo/releases
.Ed
@@ -46,7 +48,8 @@ https://github.com/Juniper/libxo/releases
.Xr xo_emit 3
.Sh HISTORY
The
-.Fa libxo
-library was added in FreeBSD 11.0.
+.Nm libxo
+library was added in
+.Fx 11.0 .
.Sh AUTHOR
Phil Shafer
diff --git a/contrib/libxo/libxo/xo_set_style.3 b/contrib/libxo/libxo/xo_set_style.3
index 83371ac71b15..f11f190bf13f 100644
--- a/contrib/libxo/libxo/xo_set_style.3
+++ b/contrib/libxo/libxo/xo_set_style.3
@@ -7,7 +7,7 @@
.\" # LICENSE.
.\" # Phil Shafer, July 2014
.\"
-.Dd July, 2014
+.Dd December 4, 2014
.Dt LIBXO 3
.Os
.Sh NAME
@@ -25,9 +25,11 @@
Use the
.Fn xo_set_style
function to set the output style for a handle.
-To use the default handle, pass a NULL handle.
+To use the default handle, pass a
+.Dv NULL
+handle.
The set of output styles used by
-.Em libxo
+.Nm libxo
is:
.Bl -column "XO_STYLE_TEXT12"
.It Sy "Flag Description"
@@ -47,18 +49,20 @@ The name can be any of the styles: "text", "xml", "json", or "html".
xo_set_style_name(NULL, "html");
.Ed
.Sh ADDITIONAL DOCUMENTATION
-.Pp
Complete documentation can be found on github:
.Bd -literal -offset indent
http://juniper.github.io/libxo/libxo-manual.html
.Ed
.Pp
-libxo lives on github as:
+.Nm libxo
+lives on github as:
.Bd -literal -offset indent
https://github.com/Juniper/libxo
.Ed
.Pp
-The latest release of libxo is available at:
+The latest release of
+.Nm libxo
+is available at:
.Bd -literal -offset indent
https://github.com/Juniper/libxo/releases
.Ed
@@ -66,7 +70,8 @@ https://github.com/Juniper/libxo/releases
.Xr xo_emit 3
.Sh HISTORY
The
-.Fa libxo
-library was added in FreeBSD 11.0.
+.Nm libxo
+library was added in
+.Fx 11.0 .
.Sh AUTHOR
Phil Shafer
diff --git a/contrib/libxo/libxo/xo_set_writer.3 b/contrib/libxo/libxo/xo_set_writer.3
index 9185f10dd601..942bcc2866b6 100644
--- a/contrib/libxo/libxo/xo_set_writer.3
+++ b/contrib/libxo/libxo/xo_set_writer.3
@@ -7,7 +7,7 @@
.\" # LICENSE.
.\" # Phil Shafer, July 2014
.\"
-.Dd July, 2014
+.Dd December 4, 2014
.Dt LIBXO 3
.Os
.Sh NAME
@@ -21,9 +21,12 @@
.Sy typedef int (*xo_write_func_t)(void *, const char *);
.Pp
.Sy typedef void (*xo_close_func_t)(void *);
+.Pp
+.Sy typedef int (*xo_flush_func_t)(void *);
.Fn xo_set_writer "xo_handle_t *handle" "void *opaque"
"xo_write_func_t write_func"
"xo_close_func_t close_func"
+ "xo_flush_func_t flush_func"
.Sh DESCRIPTION
The
.Fn xo_set_writer
@@ -31,30 +34,38 @@ function allows custom
.Dq write
functions
which can tailor how
-.Em libxo
-writes data. An
+.Nm libxo
+writes data.
+An
.Fa opaque
argument is
recorded and passed back to the
.Fa write_func
function, allowing the function
-to acquire context information. The
+to acquire context information.
+The
.Fa close_func
function can
release this opaque data and any other resources as needed.
+The
+.Fa flush_func
+function should
+flush any pending data associated with the opaque pointer.
.Sh ADDITIONAL DOCUMENTATION
-.Pp
Complete documentation can be found on github:
.Bd -literal -offset indent
http://juniper.github.io/libxo/libxo-manual.html
.Ed
.Pp
-libxo lives on github as:
+.Nm libxo
+lives on github as:
.Bd -literal -offset indent
https://github.com/Juniper/libxo
.Ed
.Pp
-The latest release of libxo is available at:
+The latest release of
+.Nm libxo
+is available at:
.Bd -literal -offset indent
https://github.com/Juniper/libxo/releases
.Ed
@@ -62,7 +73,8 @@ https://github.com/Juniper/libxo/releases
.Xr xo_emit 3
.Sh HISTORY
The
-.Fa libxo
-library was added in FreeBSD 11.0.
+.Nm libxo
+library was added in
+.Fx 11.0 .
.Sh AUTHOR
Phil Shafer
diff --git a/contrib/libxo/libxo/xoconfig.h b/contrib/libxo/libxo/xoconfig.h
index 0870e3587209..4c596b4adf6e 100644
--- a/contrib/libxo/libxo/xoconfig.h
+++ b/contrib/libxo/libxo/xoconfig.h
@@ -87,6 +87,9 @@
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
+/* Define to 1 if you have the <stdio_ext.h> header file. */
+/* #undef HAVE_STDIO_EXT_H */
+
/* Define to 1 if you have the <stdio.h> header file. */
#define HAVE_STDIO_H 1
@@ -141,6 +144,9 @@
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
+/* Define to 1 if you have the `__flbf' function. */
+/* #undef HAVE___FLBF */
+
/* Enable debugging */
/* #undef LIBXO_DEBUG */
@@ -158,7 +164,7 @@
#define PACKAGE_NAME "libxo"
/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "libxo 0.1.6"
+#define PACKAGE_STRING "libxo 0.2.0"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "libxo"
@@ -167,7 +173,7 @@
#define PACKAGE_URL ""
/* Define to the version of this package. */
-#define PACKAGE_VERSION "0.1.6"
+#define PACKAGE_VERSION "0.2.0"
/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
@@ -181,7 +187,7 @@
#define STDC_HEADERS 1
/* Version number of package */
-#define VERSION "0.1.6"
+#define VERSION "0.2.0"
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
diff --git a/contrib/libxo/libxo/xoconfig.h.in b/contrib/libxo/libxo/xoconfig.h.in
index 3fe736571d07..467f5644d6b7 100644
--- a/contrib/libxo/libxo/xoconfig.h.in
+++ b/contrib/libxo/libxo/xoconfig.h.in
@@ -86,6 +86,9 @@
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
+/* Define to 1 if you have the <stdio_ext.h> header file. */
+#undef HAVE_STDIO_EXT_H
+
/* Define to 1 if you have the <stdio.h> header file. */
#undef HAVE_STDIO_H
@@ -140,6 +143,9 @@
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
+/* Define to 1 if you have the `__flbf' function. */
+#undef HAVE___FLBF
+
/* Enable debugging */
#undef LIBXO_DEBUG
diff --git a/contrib/libxo/libxo/xoversion.h b/contrib/libxo/libxo/xoversion.h
index 60c6118be935..4c29e82963eb 100644
--- a/contrib/libxo/libxo/xoversion.h
+++ b/contrib/libxo/libxo/xoversion.h
@@ -18,17 +18,17 @@
/**
* The version string
*/
-#define LIBXO_VERSION "0.1.6"
+#define LIBXO_VERSION "0.2.0"
/**
* The version number
*/
-#define LIBXO_VERSION_NUMBER 1006
+#define LIBXO_VERSION_NUMBER 2000
/**
* The version number as a string
*/
-#define LIBXO_VERSION_STRING "1006"
+#define LIBXO_VERSION_STRING "2000"
/**
* The version number extra info as a string