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.
This commit is contained in:
Marcel Moolenaar 2015-01-19 02:22:03 +00:00
parent 9745de4c2c
commit 545ddfbe7d
83 changed files with 4077 additions and 710 deletions

View File

@ -35,6 +35,7 @@ docs:
DIST_FILES_DIR = ~/Dropbox/dist-files/
GH_PAGES_DIR = gh-pages/
GH_PAGES_DIR_VER = gh-pages/${PACKAGE_VERSION}
PACKAGE_FILE = ${PACKAGE_TARNAME}-${PACKAGE_VERSION}.tar.gz
upload: dist upload-docs
@ -45,10 +46,14 @@ upload-docs: docs
@echo "Uploading libxo-manual.html ... "
@-[ -d ${GH_PAGES_DIR} ] \
&& echo "Updating manual on gh-pages ..." \
&& mkdir -p ${GH_PAGES_DIR_VER} \
&& cp doc/libxo-manual.html ${GH_PAGES_DIR} \
&& cp doc/libxo-manual.html ${GH_PAGES_DIR_VER} \
&& (cd ${GH_PAGES_DIR} \
&& git add ${PACKAGE_VERSION} \
&& git add libxo-manual.html \
&& git commit -m 'new docs' \
libxo-manual.html \
libxo-manual.html ${PACKAGE_VERSION} \
&& git push origin gh-pages ) ; true
pkgconfigdir=$(libdir)/pkgconfig
@ -66,7 +71,7 @@ UPDATE_PACKAGE_FILE = \
-e "s;__SHA256__;SHA256 (textproc/${PACKAGE_FILE}) = $$SHA256;" \
-e "s;__SIZE__;SIZE (textproc/${PACKAGE_FILE}) = $$SIZE;"
GH_PACKAGING_DIR = packaging/${PACKAGE_VERSION}
GH_PACKAGING_DIR = ${PACKAGE_VERSION}/packaging
GH_PAGES_PACKAGE_DIR = ${GH_PAGES_DIR}/${GH_PACKAGING_DIR}
packages:
@ -75,7 +80,6 @@ packages:
&& SHA1="`openssl sha1 ${PACKAGE_FILE} | awk '{print $$2}'`" \
&& SHA256="`openssl sha256 ${PACKAGE_FILE} | awk '{print $$2}'`" \
&& SIZE="`ls -l ${PACKAGE_FILE} | awk '{print $$5}'`" \
&& mkdir -p ${GH_PAGES_PACKAGE_DIR}/freebsd \
&& echo "... ${GH_PAGES_PACKAGE_DIR}/${PACKAGE_NAME}.rb ..." \
&& sed ${UPDATE_PACKAGE_FILE} \
packaging/${PACKAGE_NAME}.rb.base \
@ -83,20 +87,10 @@ packages:
&& echo "... ${GH_PAGES_PACKAGE_DIR}/${PACKAGE_NAME}.spec ..." \
&& cp packaging/${PACKAGE_NAME}.spec \
${GH_PAGES_PACKAGE_DIR}/${PACKAGE_NAME}.spec \
&& echo "... ${GH_PAGES_PACKAGE_DIR}/freebsd ..." \
&& sed ${UPDATE_PACKAGE_FILE} \
${srcdir}/packaging/freebsd/distinfo.base \
> ${GH_PAGES_PACKAGE_DIR}/freebsd/distinfo \
&& cp ${srcdir}/packaging/freebsd/pkg-descr \
${GH_PAGES_PACKAGE_DIR}/freebsd/pkg-descr \
&& cp ${srcdir}/packaging/freebsd/pkg-plist \
${GH_PAGES_PACKAGE_DIR}/freebsd/pkg-plist \
&& cp ${srcdir}/packaging/freebsd/pkg-plist \
${GH_PAGES_PACKAGE_DIR}/freebsd/pkg-plist \
&& cp packaging/freebsd/port-Makefile \
${GH_PAGES_PACKAGE_DIR}/freebsd/Makefile \
&& (cd ${GH_PAGES_DIR} \
&& git add ${GH_PACKAGING_DIR} \
&& git add ${GH_PACKAGING_DIR}/libxo.rb \
${GH_PACKAGING_DIR}/libxo.spec \
&& git commit -m 'new packaging data' \
${GH_PACKAGING_DIR} \
&& git push origin gh-pages ) ; true

View File

@ -1,5 +1,5 @@
set top_src=`pwd`
alias Zautoreconf "(cd $top_src ; autoreconf --install)"
alias Zautoreconf "(cd $top_src ; autoreconf)"
set opts=' \
--with-libslax-prefix=/Users/phil/work/root \

View File

@ -12,7 +12,7 @@
#
AC_PREREQ(2.2)
AC_INIT([libxo], [0.1.6], [phil@juniper.net])
AC_INIT([libxo], [0.2.0], [phil@juniper.net])
AM_INIT_AUTOMAKE([-Wall -Werror foreign -Wno-portability])
# Support silent build rules. Requires at least automake-1.11.
@ -57,8 +57,10 @@ AC_CHECK_FUNCS([getpass])
AC_CHECK_FUNCS([sysctlbyname])
AC_CHECK_FUNCS([flock])
AC_CHECK_FUNCS([asprintf])
AC_CHECK_FUNCS([__flbf])
AC_CHECK_HEADERS([dlfcn.h])
AC_CHECK_HEADERS([stdio_ext.h])
AC_CHECK_HEADERS([tzfile.h])
AC_CHECK_HEADERS([stdtime/tzfile.h])
AC_CHECK_FUNCS([dlfunc])
@ -164,7 +166,6 @@ AC_ARG_ENABLE([libxo-options],
AC_MSG_RESULT([$LIBXO_OPTS])
AM_CONDITIONAL([NO_LIBXO_OPTIONS], [test "$LIBXO_OPTS" != "yes"])
case $host_os in
darwin*)
LIBTOOL=glibtool
@ -238,6 +239,7 @@ AC_CONFIG_FILES([
tests/core/Makefile
tests/xo/Makefile
packaging/libxo.spec
packaging/libxo.rb.base
])
AC_OUTPUT

View File

@ -12,14 +12,15 @@
libxo - A Library for Generating Text, XML, JSON, and HTML Output
You live in the present, but you want to live in the future. You'd
love a flying car, but need to get to work today. You want to support
features like XML, JSON, and HTML rendering to allow integration with
NETCONF, REST, and web browsers, but you need to make text output for
command line users. And you don't want multiple code paths that can't
help but get out of sync. None of this "if (xml) {... } else {...}"
logic. And ifdefs are right out. But you'd really, really like all
the fancy features that modern encoding formats can provide.
You want to prepare for the future, but you need to live in the
present. You'd love a flying car, but need to get to work today. You
want to support features like XML, JSON, and HTML rendering to allow
integration with NETCONF, REST, and web browsers, but you need to make
text output for command line users. And you don't want multiple code
paths that can't help but get out of sync. None of this "if (xml)
{... } else {...}" logic. And ifdefs are right out. But you'd
really, really like all the fancy features that modern encoding
formats can provide. libxo can help.
The libxo library allows an application to generate text, XML, JSON,
and HTML output using a common set of function calls. The application
@ -83,31 +84,37 @@ The latest release of libxo is available at:
https://github.com/Juniper/libxo/releases
We are following the branching scheme from
^http://nvie.com/posts/a-successful-git-branching-model/^
which means we will do development under the "develop" branch, and
release from the master. To clone a developer tree, run the following
We are following the branching scheme from
^http://nvie.com/posts/a-successful-git-branching-model/^ which means
we will do development under the "develop" branch, and release from
the "master" branch. To clone a developer tree, run the following
command:
git clone https://github.com/Juniper/libxo.git -b develop
We're using semantic release numbering.
We're using semantic release numbering, as defined in
^http://semver.org/spec/v2.0.0.html^.
libxo is open source, distributed under the BSD license. It
is shipped as part of FreeBSD 11.0.
* Overview
Most unix 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
updates when output contents change or evolve, requiring testing and
validation.
to be parsed and understood by a user. Humans are gifted at
extracting details and pattern matching in such output. 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 maintenance when output contents change or evolve,
along with testing and validation.
Modern tool developers favors encoding schemes like XML and JSON,
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.
integrate easier with common tools and environments. Changes to
content can be done in ways that do not break existing users of the
data, which can reduce maintenance costs and increase feature velocity.
In addition, modern reality means that more output ends up in web
browsers than in terminals, making HTML output valuable.
@ -278,7 +285,7 @@ content. The roles are listed below; only one role is permitted:
|---+--------------+-------------------------------------------------|
| M | Name | Description |
|---+--------------+-------------------------------------------------|
| D | decoration | Field is non-text (e.g. colon, comma) |
| D | decoration | Field is non-text (e.g., colon, comma) |
| E | error | Field is an error message |
| L | label | Field is text that prefixes a value |
| N | note | Field is text that follows a value |
@ -321,7 +328,7 @@ the field descriptor, or a printf-style format descriptor can be used,
if preceded by a slash ("/"):
xo_emit("{P: }{Lwc:Cost}{:cost/%u}\n", cost);
xo_emit("{P:/30s}{Lwc:Cost}{:cost/%u}\n", "", cost);
xo_emit("{P:/%30s}{Lwc:Cost}{:cost/%u}\n", "", cost);
**** The Title Role ({T:})
@ -333,6 +340,16 @@ if preceded by a slash ("/"):
xo_emit("{T:Interface Statistics}\n");
xo_emit("{T:/%20.20s}{T:/%6.6s}\n", "Item Name", "Cost");
Title fields have an extra convenience feature; if both content and
format are specified, instead of looking to the argument list for a
value, the content is used, allowing a mixture of format and content
within the field descriptor:
xo_emit("{T:Name/%20s}{T:Count/%6s}\n");
Since the incoming argument is a string, the format must be "%s" or
something suitable.
**** The Units Role ({U:})
Units are the dimension by which values are measured, such as degrees,
@ -412,6 +429,7 @@ content emitted for some output styles:
| d | display | Only emit field for display styles (text/HTML) |
| e | encoding | Only emit for encoding styles (XML/JSON) |
| k | key | Field is a key, suitable for XPath predicates |
| l | leaf-list | Field is a leaf-list
| n | no-quotes | Do not quote the field when using JSON style |
| q | quotes | Quote the field when using JSON style |
| w | white space | A blank (" ") is appended after the label |
@ -433,7 +451,7 @@ The colon modifier appends a single colon to the data value:
Name:phil
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.
**** The Display Modifier ({d:})
@ -485,6 +503,24 @@ Currently the key modifier is only used when generating XPath value
for the HTML output style when XOF_XPATH is set, but other uses are
likely in the near future.
**** 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.
EXAMPLE:
for (i = 0; i < num_users; i++) {
xo_emit("Member {l:user}\n", user[i].u_name);
}
XML:
<user>phil</user>
<user>pallavi</user>
JSON:
"user": [ "phil", "pallavi" ]
The name of the field must match the name of the leaf list.
**** The No-Quotes Modifier ({n:})
The no-quotes modifier (and its twin, the 'quotes' modifier) affect
@ -522,7 +558,7 @@ The white space modifier appends a single space to the data value:
Name phil
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.
Note that the sense of the 'w' modifier is reversed for the units role
@ -530,14 +566,15 @@ Note that the sense of the 'w' modifier is reversed for the units role
*** Field Formatting
The field format is similar to the format string for printf(3). It's
used varies based on the role of the field, but generally is used to
The field format is similar to the format string for printf(3). Its
use varies based on the role of the field, but generally is used to
format the field's contents.
If not provided, the format string defaults to "%s".
If the format string is not provided for a value field, it defaults to
"%s".
Note a field definition can contain zero or more printf-style
'directives', which are sequences that start with a '%' and end with a
'directives', 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 xo_emit function.
@ -557,7 +594,7 @@ 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.
- 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.
@ -630,8 +667,8 @@ ASCII data, a normal 7-bit ASCII string can be used. '%ls' expects a
Unicode values. '%hs' expects a 'char *' pointer to a multi-byte
string encoded with the current locale, as given by the LC_CTYPE,
LANG, or LC_ALL environment varibles. The first of this list of
variables is used and if none of the variables, the locale defaults to
"UTF-8".
variables is used and if none of the variables are set, the locale
defaults to "UTF-8".
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)
@ -676,10 +713,10 @@ columns.
*** Characters Outside of Field Definitions
Characters in the format string 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".
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".
EXAMPLE:
xo_emit("The hat is {:size/%s}.\n", size_val);
@ -854,7 +891,7 @@ container, a warning will be generated.
*** Lists and Instances
A list is set of one or more instances that appear under the same
parent. The instances contains details about a specific object. One
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:
@ -874,8 +911,8 @@ generation of XML and JSON data.
*** DTRT Mode
Some user may find tracking the names of open containers, lists, and
instances inconvenient. libxo offers "Do The Right Thing" mode, where
Some users may find tracking the names of open containers, lists, and
instances inconvenient. libxo offers a "Do The Right Thing" mode, where
libxo will track the names of open containers, lists, and instances so
the close function can be called without a name. To enable DTRT mode,
turn on the XOF_DTRT flag prior to making any other libxo output.
@ -889,10 +926,42 @@ will close the open container, list, or instance:
...
xo_close_container_d();
This also works for lists and instances:
xo_open_list("item");
for (...) {
xo_open_instance("item");
xo_emit(...);
xo_close_instance_d();
}
xo_close_list_d();
Note that the XOF_WARN flag will also cause libxo to track open
containers, lists, and instances. A warning is generated with the
containers, lists, and instances. A warning is generated when the
name given to the close function and the name recorded do not match.
*** Markers
Markers are used to protect and restore the state of open constructs.
While a marker is open, no other open constructs can be closed. When
a marker is closed, all constructs open since the marker was opened
will be closed.
Markers use names which are not user-visible, allowing the caller to
choose appropriate internal names.
In this example, the code whiffles through a list of fish, calling a
function to emit details about each fish. The marker "fish-guts" is
used to ensure that any constructs opened by the function are closed
properly.
for (i = 0; fish[i]; i++) {
xo_open_instance("fish");
xo_open_marker("fish-guts");
dump_fish_details(i);
xo_close_marker("fish-guts");
}
** Handles
libxo uses "handles" to control its rendering functionality. The
@ -952,7 +1021,7 @@ be passed NULL to access the default handle.
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.
*** xo_create
@ -972,7 +1041,7 @@ See also ^styles^ and ^flags^.
By default, libxo writes output to standard output. A convenience
function is provided for situations when output should be written to
different file:
a different file:
xo_handle_t *xo_create_to_file (FILE *fp, unsigned style,
unsigned flags);
@ -987,10 +1056,13 @@ which can tailor how libxo writes data. An opaque argument is
recorded and passed back to the write function, allowing the function
to acquire context information. The 'close' function can
release this opaque data and any other resources as needed.
The flush function can flush buffered data associated with the opaque
object.
void xo_set_writer (xo_handle_t *xop, void *opaque,
xo_write_func_t write_func,
xo_close_func_t close_func);
xo_flush_func_t flush_func);
*** xo_set_style
@ -1068,7 +1140,7 @@ XML, JSON, and HTML output. Text output is not affected.
The XOF_WARN flag requests that warnings will trigger diagnostic
output (on standard error) when the library notices errors during
operations, or with arguments to functions. Without warning enabled,
operations, or with arguments to functions. Without warnings enabled,
such conditions are ignored.
Warnings allow developers to debug their interaction with libxo.
@ -1178,6 +1250,13 @@ parameter passed to xo_attr_hv().
XML:
<login-time seconds="1408336270">00:14</login-time>
xo_attr is placed on the next container, instance, leaf, or leaf list
that is emitted.
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.
*** Flushing Output (xo_flush)
libxo buffers data, both for performance and consistency, but also to
@ -1188,6 +1267,10 @@ xo_flush() call is used for this:
void xo_flush (void);
void xo_flush_h (xo_handle_t *xop);
Calling xo_flush also triggers the flush function associated with the
handle. For the default handle, this is equivalent to
"fflush(stdio);".
*** Finishing Output (xo_finish)
When the program is ready to exit or close a handle, a call to
@ -1250,7 +1333,7 @@ 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.
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.
@ -1314,6 +1397,16 @@ Following the call to xo_parse_args, the application can process the
remaining arguments in a normal manner. See ^command-line-arguments^
for a description of valid arguments.
*** xo_set_program
The xo_set_program function sets name of the program as reported by
functions like xo_failure, xo_warn, xo_err, etc. The program name is
initialized by xo_parse_args, but subsequent calls to xo_set_program
can override this value.
Note that the value is not copied, so the memory passed to
xo_set_program (and xo_parse_args) must be maintained by the caller.
*** Field Information (xo_info_t) @info@
HTML data can include additional information in attributes that
@ -1353,7 +1446,7 @@ known to the application:
...
xo_set_info(NULL, info, info_count);
Third, the emitting of info must be triggered with the XOF_INFO flag
Third, the emission of info must be triggered with the XOF_INFO flag
using either the xo_set_flags() function or the "--libxo=info" command
line argument.
@ -1405,6 +1498,10 @@ Complete HTML output can be generated with:
% env LIBXO_OPTIONS=HXI my-app
Since environment variables are inherited, child processes will have
the same options, which may be undesirable, making the use of the
"--libxo" option is preferable in most situations.
*** Errors, Warnings, and Messages
Many programs make use of the standard library functions err() and
@ -1435,6 +1532,20 @@ message associated with either "errno" or the "code" parameter.
if (open(filename, O_RDONLY) < 0)
xo_err(1, "cannot open file '%s'", filename);
*** xo_error
The xo_error function can be used for generic errors that should be
reported over the handle, rather than to stderr. The xo_error
function behaves like xo_err for TEXT and HTML output styles, but puts
the error into XML or JSON elements:
EXAMPLE::
xo_error("Does not %s", "compute");
XML::
<error><message>Does not compute</message></error>
JSON::
"error": { "message": "Does not compute" }
*** xo_no_setlocale
libxo automatically initializes the locale based on setting of the
@ -1580,7 +1691,7 @@ and errors, warning, or informational messages as needed.
| -X | Extract samples from xolint, suitable for testing |
|------------+---------------------------------------------------|
Output message contain the source filename and line number, the
The output message will contain the source filename and line number, the
class of the message, the message, and, if -p is given, the
line that contains the error:
@ -1627,6 +1738,88 @@ libxo is an effort to mix the best aspects of the JUNOS strategy into
FreeBSD in a seemless way, allowing commands to make printf-like
output calls without needing to care how the output is rendered.
*** Did the complex semantics of format strings evolve over time?
The history is both long and short: libxo's functionality is based
on what JUNOS does in a data modeling language called ODL (output
definition language). In JUNOS, all subcomponents generate XML,
which is feed to the CLI, where data from the ODL files tell is
how to render that XML into text. ODL might had a set of tags
like:
tag docsis-state {
help "State of the DOCSIS interface";
type string;
}
tag docsis-mode {
help "DOCSIS mode (2.0/3.0) of the DOCSIS interface";
type string;
}
tag docsis-upstream-speed {
help "Operational upstream speed of the interface";
type string;
}
tag downstream-scanning {
help "Result of scanning in downstream direction";
type string;
}
tag ranging {
help "Result of ranging action";
type string;
}
tag signal-to-noise-ratio {
help "Signal to noise ratio for all channels";
type string;
}
tag power {
help "Operational power of the signal on all channels";
type string;
}
format docsis-status-format {
picture "
State : @, Mode: @, Upstream speed: @
Downstream scanning: @, Ranging: @
Signal to noise ratio: @
Power: @
";
line {
field docsis-state;
field docsis-mode;
field docsis-upstream-speed;
field downstream-scanning;
field ranging;
field signal-to-noise-ratio;
field power;
}
}
These tag definitions are compiled into field definitions
that are triggered when matching XML elements are seen. ODL
also supports other means of defining output.
The roles and modifiers describe these details.
In moving these ideas to bsd, two things had to happen: the
formatting had to happen at the source since BSD won't have
a JUNOS-like CLI to do the rendering, and we can't depend on
external data models like ODL, which was seen as too hard a
sell to the BSD community.
The results were that the xo_emit strings are used to encode the
roles, modifiers, names, and formats. They are dense and a bit
cryptic, but not so unlike printf format strings that developers will
be lost.
libxo is a new implementation of these ideas and is distinct from
the previous implementation in JUNOS.
*** What makes a good field name?
To make useful, consistent field names, follow these guidelines:
@ -1660,7 +1853,7 @@ Nothing's worse than writing expressions like:
}
Find someone else who is expressing similar data and follow their
field's and hierarchy. Remember the quote is not "Consistency is the
fields and hierarchy. Remember the quote is not "Consistency is the
hobgoblin of little minds", but "A foolish consistency is the
hobgoblin of little minds".
= Think about your users
@ -1670,7 +1863,7 @@ content with xo_attr() calls (^xo_attr^) or "{e:}" fields
(^e-modifier^) to make the data useful.
= 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
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's the
difference between errors37 and errors63.
@ -1689,7 +1882,7 @@ After using "xolint" to find errors in your field descriptors, use
"xolint -V" to spell check your field names and to detect different
names for the same data. "dropped-short" and "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,
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.

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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"> */
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 (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_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 (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_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 (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_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 (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_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 (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 */
#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);
@ -209,6 +214,18 @@ xo_close_instance_hd (xo_handle_t *xop);
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, ...);
@ -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 */

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.
.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
libxo will
.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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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. */

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,20 @@
#
# Homebrew formula file for libxo
# https://github.com/mxcl/homebrew
#
require 'formula'
class Libxo < Formula
homepage 'https://github.com/Juniper/@PACKAGE-NAME@'
url 'https://github.com/Juniper/@PACKAGE_NAME@/releases/@PACKAGE_VERSION@/@PACKAGE_NAME@-@PACKAGE_VERSION@.tar.gz'
sha1 '__SHA1__'
depends_on 'libtool' => :build
def install
system "./configure", "--disable-dependency-tracking",
"--prefix=#{prefix}"
system "make install"
end
end

View File

@ -18,7 +18,9 @@ test_03.c \
test_04.c \
test_05.c \
test_06.c \
test_07.c
test_07.c \
test_08.c \
test_09.c
test_01_test_SOURCES = test_01.c
test_02_test_SOURCES = test_02.c
@ -27,6 +29,8 @@ test_04_test_SOURCES = test_04.c
test_05_test_SOURCES = test_05.c
test_06_test_SOURCES = test_06.c
test_07_test_SOURCES = test_07.c
test_08_test_SOURCES = test_08.c
test_09_test_SOURCES = test_09.c
# TEST_CASES := $(shell cd ${srcdir} ; echo *.c )

File diff suppressed because one or more lines are too long

View File

@ -236,3 +236,61 @@
<div class="text">: </div>
<div class="data" data-tag="sku" data-xpath="/top/data/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key">GRO-000-533</div>
</div>
<div class="line">
<div class="label">Item</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="item" data-xpath="/top/data/item">gum</div>
</div>
<div class="line">
<div class="label">Item</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="item" data-xpath="/top/data/item">rope</div>
</div>
<div class="line">
<div class="label">Item</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="item" data-xpath="/top/data/item">ladder</div>
</div>
<div class="line">
<div class="label">Item</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="item" data-xpath="/top/data/item">bolt</div>
</div>
<div class="line">
<div class="label">Item</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="item" data-xpath="/top/data/item">water</div>
</div>
<div class="line">
<div class="text">X</div>
<div class="text">X</div>
<div class="text">X</div>
<div class="text">X</div>
<div class="text">X</div>
<div class="text">X</div>
<div class="text">X</div>
<div class="text">X</div>
</div>
<div class="line">
<div class="text">X</div>
<div class="padding"> </div>
<div class="text">X</div>
<div class="label">Cost</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="cost" data-xpath="/top/cost">425</div>
</div>
<div class="line">
<div class="text">X</div>
<div class="padding"> </div>
<div class="text">X</div>
<div class="label">Cost</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="cost" data-xpath="/top/cost">455</div>
</div>

View File

@ -236,3 +236,61 @@
<div class="text">: </div>
<div class="data" data-tag="sku" data-key="key">GRO-000-533</div>
</div>
<div class="line">
<div class="label">Item</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="item">gum</div>
</div>
<div class="line">
<div class="label">Item</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="item">rope</div>
</div>
<div class="line">
<div class="label">Item</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="item">ladder</div>
</div>
<div class="line">
<div class="label">Item</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="item">bolt</div>
</div>
<div class="line">
<div class="label">Item</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="item">water</div>
</div>
<div class="line">
<div class="text">X</div>
<div class="text">X</div>
<div class="text">X</div>
<div class="text">X</div>
<div class="text">X</div>
<div class="text">X</div>
<div class="text">X</div>
<div class="text">X</div>
</div>
<div class="line">
<div class="text">X</div>
<div class="padding"> </div>
<div class="text">X</div>
<div class="label">Cost</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="cost">425</div>
</div>
<div class="line">
<div class="text">X</div>
<div class="padding"> </div>
<div class="text">X</div>
<div class="label">Cost</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="cost">455</div>
</div>

View File

@ -1,2 +1,2 @@
{"top": {"data": {"item": [{"sku":"GRO-000-415","name":"gum","sold":1412,"in-stock":54,"on-order":10}, {"sku":"HRD-000-212","name":"rope","sold":85,"in-stock":4,"on-order":2}, {"sku":"HRD-000-517","name":"ladder","sold":0,"in-stock":2,"on-order":1}, {"sku":"HRD-000-632","name":"bolt","sold":4123,"in-stock":144,"on-order":42}, {"sku":"GRO-000-2331","name":"water","sold":17,"in-stock":14,"on-order":2}]}, "data": {"item": [{"sku":"GRO-000-415","name":"gum","sold":1412.0,"in-stock":54,"on-order":10}, {"sku":"HRD-000-212","name":"rope","sold":85.0,"in-stock":4,"on-order":2}, {"sku":"HRD-000-517","name":"ladder","sold":0,"in-stock":2,"on-order":1}, {"sku":"HRD-000-632","name":"bolt","sold":4123.0,"in-stock":144,"on-order":42}, {"sku":"GRO-000-2331","name":"water","sold":17.0,"in-stock":14,"on-order":2}]}, "data": {"item": [{"sku":"GRO-000-533","name":"fish","sold":1321.0,"in-stock":45,"on-order":1}]}}
{"top": {"data": {"item": [{"sku":"GRO-000-415","name":"gum","sold":1412,"in-stock":54,"on-order":10}, {"sku":"HRD-000-212","name":"rope","sold":85,"in-stock":4,"on-order":2}, {"sku":"HRD-000-517","name":"ladder","sold":0,"in-stock":2,"on-order":1}, {"sku":"HRD-000-632","name":"bolt","sold":4123,"in-stock":144,"on-order":42}, {"sku":"GRO-000-2331","name":"water","sold":17,"in-stock":14,"on-order":2}]}, "data": {"item": [{"sku":"GRO-000-415","name":"gum","sold":1412.0,"in-stock":54,"on-order":10}, {"sku":"HRD-000-212","name":"rope","sold":85.0,"in-stock":4,"on-order":2}, {"sku":"HRD-000-517","name":"ladder","sold":0,"in-stock":2,"on-order":1}, {"sku":"HRD-000-632","name":"bolt","sold":4123.0,"in-stock":144,"on-order":42}, {"sku":"GRO-000-2331","name":"water","sold":17.0,"in-stock":14,"on-order":2}]}, "data": {"item": [{"sku":"GRO-000-533","name":"fish","sold":1321.0,"in-stock":45,"on-order":1}]}, "data": {"item": ["gum","rope","ladder","bolt","water"]},"cost":425,"cost":455}
}

View File

@ -88,6 +88,13 @@
"on-order": 1
}
]
}
},
"data": {
"item": [
"gum", "rope", "ladder", "bolt", "water"
]
},
"cost": 425,
"cost": 455
}
}

View File

@ -36,3 +36,11 @@ Item 'fish':
In stock: 45
On order: 1
SKU: GRO-000-533
Item: gum
Item: rope
Item: ladder
Item: bolt
Item: water
XXXXXXXX
X XCost: 425
X XCost: 455

View File

@ -1 +1 @@
<top><data><item><sku key="key">GRO-000-415</sku><name key="key">gum</name><sold>1412</sold><in-stock>54</in-stock><on-order>10</on-order></item><item><sku key="key">HRD-000-212</sku><name key="key">rope</name><sold>85</sold><in-stock>4</in-stock><on-order>2</on-order></item><item><sku key="key">HRD-000-517</sku><name key="key">ladder</name><sold>0</sold><in-stock>2</in-stock><on-order>1</on-order></item><item><sku key="key">HRD-000-632</sku><name key="key">bolt</name><sold>4123</sold><in-stock>144</in-stock><on-order>42</on-order></item><item><sku key="key">GRO-000-2331</sku><name key="key">water</name><sold>17</sold><in-stock>14</in-stock><on-order>2</on-order></item></data><data><item><sku key="key">GRO-000-415</sku><name key="key">gum</name><sold>1412.0</sold><in-stock>54</in-stock><on-order>10</on-order></item><item><sku key="key">HRD-000-212</sku><name key="key">rope</name><sold>85.0</sold><in-stock>4</in-stock><on-order>2</on-order></item><item><sku key="key">HRD-000-517</sku><name key="key">ladder</name><sold>0</sold><in-stock>2</in-stock><on-order>1</on-order></item><item><sku key="key">HRD-000-632</sku><name key="key">bolt</name><sold>4123.0</sold><in-stock>144</in-stock><on-order>42</on-order></item><item><sku key="key">GRO-000-2331</sku><name key="key">water</name><sold>17.0</sold><in-stock>14</in-stock><on-order>2</on-order></item></data><data><item><sku key="key">GRO-000-533</sku><name key="key">fish</name><sold>1321.0</sold><in-stock>45</in-stock><on-order>1</on-order></item></data></top>
<top><data test="value"><item test2="value2"><sku test3="value3" key="key">GRO-000-415</sku><name key="key">gum</name><sold>1412</sold><in-stock>54</in-stock><on-order>10</on-order></item><item><sku test3="value3" key="key">HRD-000-212</sku><name key="key">rope</name><sold>85</sold><in-stock>4</in-stock><on-order>2</on-order></item><item><sku test3="value3" key="key">HRD-000-517</sku><name key="key">ladder</name><sold>0</sold><in-stock>2</in-stock><on-order>1</on-order></item><item><sku test3="value3" key="key">HRD-000-632</sku><name key="key">bolt</name><sold>4123</sold><in-stock>144</in-stock><on-order>42</on-order></item><item><sku test3="value3" key="key">GRO-000-2331</sku><name key="key">water</name><sold>17</sold><in-stock>14</in-stock><on-order>2</on-order></item></data><data><item><sku key="key">GRO-000-415</sku><name key="key">gum</name><sold>1412.0</sold><in-stock>54</in-stock><on-order>10</on-order></item><item><sku key="key">HRD-000-212</sku><name key="key">rope</name><sold>85.0</sold><in-stock>4</in-stock><on-order>2</on-order></item><item><sku key="key">HRD-000-517</sku><name key="key">ladder</name><sold>0</sold><in-stock>2</in-stock><on-order>1</on-order></item><item><sku key="key">HRD-000-632</sku><name key="key">bolt</name><sold>4123.0</sold><in-stock>144</in-stock><on-order>42</on-order></item><item><sku key="key">GRO-000-2331</sku><name key="key">water</name><sold>17.0</sold><in-stock>14</in-stock><on-order>2</on-order></item></data><data><item><sku key="key">GRO-000-533</sku><name key="key">fish</name><sold>1321.0</sold><in-stock>45</in-stock><on-order>1</on-order></item></data><data><item test4="value4">gum</item><item test4="value4">rope</item><item test4="value4">ladder</item><item test4="value4">bolt</item><item test4="value4">water</item></data><cost>425</cost><cost>455</cost></top>

View File

@ -1,35 +1,35 @@
<top>
<data>
<item>
<sku key="key">GRO-000-415</sku>
<data test="value">
<item test2="value2">
<sku test3="value3" key="key">GRO-000-415</sku>
<name key="key">gum</name>
<sold>1412</sold>
<in-stock>54</in-stock>
<on-order>10</on-order>
</item>
<item>
<sku key="key">HRD-000-212</sku>
<sku test3="value3" key="key">HRD-000-212</sku>
<name key="key">rope</name>
<sold>85</sold>
<in-stock>4</in-stock>
<on-order>2</on-order>
</item>
<item>
<sku key="key">HRD-000-517</sku>
<sku test3="value3" key="key">HRD-000-517</sku>
<name key="key">ladder</name>
<sold>0</sold>
<in-stock>2</in-stock>
<on-order>1</on-order>
</item>
<item>
<sku key="key">HRD-000-632</sku>
<sku test3="value3" key="key">HRD-000-632</sku>
<name key="key">bolt</name>
<sold>4123</sold>
<in-stock>144</in-stock>
<on-order>42</on-order>
</item>
<item>
<sku key="key">GRO-000-2331</sku>
<sku test3="value3" key="key">GRO-000-2331</sku>
<name key="key">water</name>
<sold>17</sold>
<in-stock>14</in-stock>
@ -82,4 +82,13 @@
<on-order>1</on-order>
</item>
</data>
<data>
<item test4="value4">gum</item>
<item test4="value4">rope</item>
<item test4="value4">ladder</item>
<item test4="value4">bolt</item>
<item test4="value4">water</item>
</data>
<cost>425</cost>
<cost>455</cost>
</top>

View File

@ -1,2 +1,2 @@
{"top": {"data": {"mbuf-current":10,"mbuf-cache":20,"mbuf-total":30,"distance":50,"location":"Boston","memory":64,"total":640,"memory":64,"total":640,"ten":10,"eleven":11,"unknown":1010,"min":15,"cur":20,"max":30,"min":15,"cur":20,"max":125,"min":15,"cur":20,"max":125,"min":15,"cur":20,"max":125, "flag": ["one","two","three"],"empty-tag":true,"t1":"1000","t2":"test5000","t3":"ten-longx","t4":"xtest","count":10,"test":4}}
{"top": {"data": {"mbuf-current":10,"mbuf-cache":20,"mbuf-total":30,"distance":50,"location":"Boston","memory":64,"total":640,"memory":64,"total":640,"ten":10,"eleven":11,"unknown":1010,"min":15,"cur":20,"max":30,"min":15,"cur":20,"max":125,"min":15,"cur":20,"max":125,"min":15,"cur":20,"max":125, "flag": ["one","two","three"],"empty-tag":true,"t1":"1000","t2":"test5000","t3":"ten-longx","t4":"xtest","count":10,"test":4, "error": {"message":"Shut 'er down, Clancey! She's a-pumpin' mud! <>!,\"!<>\n"}}}
}

View File

@ -34,7 +34,10 @@
"t3": "ten-longx",
"t4": "xtest",
"count": 10,
"test": 4
"test": 4,
"error": {
"message": "Shut 'er down, Clancey! She's a-pumpin' mud! <>!,\"!<>\n"
}
}
}
}

View File

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

View File

@ -12,8 +12,8 @@
"v1": "ახლავე გაიაროთ რეგისტრაცია",
"v2": "Unicode-ის მეათე საერთაშორისო",
"columns": 55,
"columns": 0,
"employee": [
"columns": 0,
{
"first-name": "Jim",
"nic-name": "\"რეგტ\"",

View File

@ -0,0 +1,18 @@
test: close (xo_close_container) fails at marker 'm1'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm1'; not found 'data'
test: close (xo_close_container) fails at marker 'm1'; not found 'top'

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,18 @@
test: close (xo_close_container) fails at marker 'm1'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm1'; not found 'data'
test: close (xo_close_container) fails at marker 'm1'; not found 'top'

View File

@ -0,0 +1,264 @@
<div class="line">
<div class="title">Item </div>
<div class="title"> Count</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-xpath="/top/data/contents/item/name" data-key="key">gum </div>
<div class="data" data-tag="count" data-xpath="/top/data/contents/item[name = 'gum']/count"> 1412</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-xpath="/top/data/contents/item/name" data-key="key">rope </div>
<div class="data" data-tag="count" data-xpath="/top/data/contents/item[name = 'rope']/count"> 85</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-xpath="/top/data/contents/item/name" data-key="key">ladder </div>
<div class="data" data-tag="count" data-xpath="/top/data/contents/item[name = 'ladder']/count"> 0</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-xpath="/top/data/contents/item/name" data-key="key">bolt </div>
<div class="data" data-tag="count" data-xpath="/top/data/contents/item[name = 'bolt']/count"> 4123</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-xpath="/top/data/contents/item/name" data-key="key">water </div>
<div class="data" data-tag="count" data-xpath="/top/data/contents/item[name = 'water']/count"> 17</div>
</div>
<div class="line">
</div>
<div class="line">
</div>
<div class="line">
<div class="title">Item </div>
<div class="title"> Count</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-xpath="/top/data/contents/item/name" data-key="key">gum </div>
<div class="data" data-tag="count" data-xpath="/top/data/contents/item[name = 'gum']/count"> 1412</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-xpath="/top/data/contents/item/name" data-key="key">rope </div>
<div class="data" data-tag="count" data-xpath="/top/data/contents/item[name = 'rope']/count"> 85</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-xpath="/top/data/contents/item/name" data-key="key">ladder </div>
<div class="data" data-tag="count" data-xpath="/top/data/contents/item[name = 'ladder']/count"> 0</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-xpath="/top/data/contents/item/name" data-key="key">bolt </div>
<div class="data" data-tag="count" data-xpath="/top/data/contents/item[name = 'bolt']/count"> 4123</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-xpath="/top/data/contents/item/name" data-key="key">water </div>
<div class="data" data-tag="count" data-xpath="/top/data/contents/item[name = 'water']/count"> 17</div>
</div>
<div class="line">
</div>
<div class="line">
</div>
<div class="line">
<div class="title">Item </div>
<div class="title"> Count</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item/name" data-key="key">gum </div>
<div class="data" data-tag="count" data-xpath="/top/data/m1/contents/item[name = 'gum']/count"> 1412</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item/name" data-key="key">rope </div>
<div class="data" data-tag="count" data-xpath="/top/data/m1/contents/item[name = 'rope']/count"> 85</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item/name" data-key="key">ladder </div>
<div class="data" data-tag="count" data-xpath="/top/data/m1/contents/item[name = 'ladder']/count"> 0</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item/name" data-key="key">bolt </div>
<div class="data" data-tag="count" data-xpath="/top/data/m1/contents/item[name = 'bolt']/count"> 4123</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item/name" data-key="key">water </div>
<div class="data" data-tag="count" data-xpath="/top/data/m1/contents/item[name = 'water']/count"> 17</div>
</div>
<div class="line">
<div class="data" data-tag="test" data-xpath="/top/data/m1/contents/item[name = 'water']/test">one</div>
</div>
<div class="line">
</div>
<div class="line">
<div class="title">Item </div>
<div class="title"> Count</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item/name" data-key="key">gum </div>
<div class="data" data-tag="count" data-xpath="/top/data/m1/contents/item[name = 'gum']/count"> 1412</div>
</div>
<div class="line">
<div class="label">Name</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item[name = 'gum']/m2/sub/name">0</div>
<div class="text"> + 1 = </div>
<div class="data" data-tag="next" data-xpath="/top/data/m1/contents/item[name = 'gum']/m2/sub/next">1</div>
</div>
<div class="line">
<div class="label">Name</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item[name = 'gum']/m2/sub/name">1</div>
<div class="text"> + 1 = </div>
<div class="data" data-tag="next" data-xpath="/top/data/m1/contents/item[name = 'gum']/m2/sub/next">2</div>
</div>
<div class="line">
<div class="label">Name</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item[name = 'gum']/m2/sub/name">2</div>
<div class="text"> + 1 = </div>
<div class="data" data-tag="next" data-xpath="/top/data/m1/contents/item[name = 'gum']/m2/sub/next">3</div>
</div>
<div class="line">
<div class="label">Last</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="last" data-xpath="/top/data/m1/contents/item[name = 'gum']/last">3</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item/name" data-key="key">rope </div>
<div class="data" data-tag="count" data-xpath="/top/data/m1/contents/item[name = 'rope']/count"> 85</div>
</div>
<div class="line">
<div class="label">Name</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item[name = 'rope']/m2/sub/name">0</div>
<div class="text"> + 1 = </div>
<div class="data" data-tag="next" data-xpath="/top/data/m1/contents/item[name = 'rope']/m2/sub/next">1</div>
</div>
<div class="line">
<div class="label">Name</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item[name = 'rope']/m2/sub/name">1</div>
<div class="text"> + 1 = </div>
<div class="data" data-tag="next" data-xpath="/top/data/m1/contents/item[name = 'rope']/m2/sub/next">2</div>
</div>
<div class="line">
<div class="label">Name</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item[name = 'rope']/m2/sub/name">2</div>
<div class="text"> + 1 = </div>
<div class="data" data-tag="next" data-xpath="/top/data/m1/contents/item[name = 'rope']/m2/sub/next">3</div>
</div>
<div class="line">
<div class="label">Last</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="last" data-xpath="/top/data/m1/contents/item[name = 'rope']/last">3</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item/name" data-key="key">ladder </div>
<div class="data" data-tag="count" data-xpath="/top/data/m1/contents/item[name = 'ladder']/count"> 0</div>
</div>
<div class="line">
<div class="label">Name</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item[name = 'ladder']/m2/sub/name">0</div>
<div class="text"> + 1 = </div>
<div class="data" data-tag="next" data-xpath="/top/data/m1/contents/item[name = 'ladder']/m2/sub/next">1</div>
</div>
<div class="line">
<div class="label">Name</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item[name = 'ladder']/m2/sub/name">1</div>
<div class="text"> + 1 = </div>
<div class="data" data-tag="next" data-xpath="/top/data/m1/contents/item[name = 'ladder']/m2/sub/next">2</div>
</div>
<div class="line">
<div class="label">Name</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item[name = 'ladder']/m2/sub/name">2</div>
<div class="text"> + 1 = </div>
<div class="data" data-tag="next" data-xpath="/top/data/m1/contents/item[name = 'ladder']/m2/sub/next">3</div>
</div>
<div class="line">
<div class="label">Last</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="last" data-xpath="/top/data/m1/contents/item[name = 'ladder']/last">3</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item/name" data-key="key">bolt </div>
<div class="data" data-tag="count" data-xpath="/top/data/m1/contents/item[name = 'bolt']/count"> 4123</div>
</div>
<div class="line">
<div class="label">Name</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item[name = 'bolt']/m2/sub/name">0</div>
<div class="text"> + 1 = </div>
<div class="data" data-tag="next" data-xpath="/top/data/m1/contents/item[name = 'bolt']/m2/sub/next">1</div>
</div>
<div class="line">
<div class="label">Name</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item[name = 'bolt']/m2/sub/name">1</div>
<div class="text"> + 1 = </div>
<div class="data" data-tag="next" data-xpath="/top/data/m1/contents/item[name = 'bolt']/m2/sub/next">2</div>
</div>
<div class="line">
<div class="label">Name</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item[name = 'bolt']/m2/sub/name">2</div>
<div class="text"> + 1 = </div>
<div class="data" data-tag="next" data-xpath="/top/data/m1/contents/item[name = 'bolt']/m2/sub/next">3</div>
</div>
<div class="line">
<div class="label">Last</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="last" data-xpath="/top/data/m1/contents/item[name = 'bolt']/last">3</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item/name" data-key="key">water </div>
<div class="data" data-tag="count" data-xpath="/top/data/m1/contents/item[name = 'water']/count"> 17</div>
</div>
<div class="line">
<div class="label">Name</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item[name = 'water']/m2/sub/name">0</div>
<div class="text"> + 1 = </div>
<div class="data" data-tag="next" data-xpath="/top/data/m1/contents/item[name = 'water']/m2/sub/next">1</div>
</div>
<div class="line">
<div class="label">Name</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item[name = 'water']/m2/sub/name">1</div>
<div class="text"> + 1 = </div>
<div class="data" data-tag="next" data-xpath="/top/data/m1/contents/item[name = 'water']/m2/sub/next">2</div>
</div>
<div class="line">
<div class="label">Name</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item[name = 'water']/m2/sub/name">2</div>
<div class="text"> + 1 = </div>
<div class="data" data-tag="next" data-xpath="/top/data/m1/contents/item[name = 'water']/m2/sub/next">3</div>
</div>
<div class="line">
<div class="label">Last</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="last" data-xpath="/top/data/m1/contents/item[name = 'water']/last">3</div>
</div>
<div class="line">
<div class="data" data-tag="test" data-xpath="/top/data/m1/contents/item[name = 'water']/test">one</div>
</div>
<div class="line">
</div>

View File

@ -0,0 +1,18 @@
test: close (xo_close_container) fails at marker 'm1'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm1'; not found 'data'
test: close (xo_close_container) fails at marker 'm1'; not found 'top'

View File

@ -0,0 +1,264 @@
<div class="line">
<div class="title">Item </div>
<div class="title"> Count</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-key="key">gum </div>
<div class="data" data-tag="count"> 1412</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-key="key">rope </div>
<div class="data" data-tag="count"> 85</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-key="key">ladder </div>
<div class="data" data-tag="count"> 0</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-key="key">bolt </div>
<div class="data" data-tag="count"> 4123</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-key="key">water </div>
<div class="data" data-tag="count"> 17</div>
</div>
<div class="line">
</div>
<div class="line">
</div>
<div class="line">
<div class="title">Item </div>
<div class="title"> Count</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-key="key">gum </div>
<div class="data" data-tag="count"> 1412</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-key="key">rope </div>
<div class="data" data-tag="count"> 85</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-key="key">ladder </div>
<div class="data" data-tag="count"> 0</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-key="key">bolt </div>
<div class="data" data-tag="count"> 4123</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-key="key">water </div>
<div class="data" data-tag="count"> 17</div>
</div>
<div class="line">
</div>
<div class="line">
</div>
<div class="line">
<div class="title">Item </div>
<div class="title"> Count</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-key="key">gum </div>
<div class="data" data-tag="count"> 1412</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-key="key">rope </div>
<div class="data" data-tag="count"> 85</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-key="key">ladder </div>
<div class="data" data-tag="count"> 0</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-key="key">bolt </div>
<div class="data" data-tag="count"> 4123</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-key="key">water </div>
<div class="data" data-tag="count"> 17</div>
</div>
<div class="line">
<div class="data" data-tag="test">one</div>
</div>
<div class="line">
</div>
<div class="line">
<div class="title">Item </div>
<div class="title"> Count</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-key="key">gum </div>
<div class="data" data-tag="count"> 1412</div>
</div>
<div class="line">
<div class="label">Name</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="name">0</div>
<div class="text"> + 1 = </div>
<div class="data" data-tag="next">1</div>
</div>
<div class="line">
<div class="label">Name</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="name">1</div>
<div class="text"> + 1 = </div>
<div class="data" data-tag="next">2</div>
</div>
<div class="line">
<div class="label">Name</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="name">2</div>
<div class="text"> + 1 = </div>
<div class="data" data-tag="next">3</div>
</div>
<div class="line">
<div class="label">Last</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="last">3</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-key="key">rope </div>
<div class="data" data-tag="count"> 85</div>
</div>
<div class="line">
<div class="label">Name</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="name">0</div>
<div class="text"> + 1 = </div>
<div class="data" data-tag="next">1</div>
</div>
<div class="line">
<div class="label">Name</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="name">1</div>
<div class="text"> + 1 = </div>
<div class="data" data-tag="next">2</div>
</div>
<div class="line">
<div class="label">Name</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="name">2</div>
<div class="text"> + 1 = </div>
<div class="data" data-tag="next">3</div>
</div>
<div class="line">
<div class="label">Last</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="last">3</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-key="key">ladder </div>
<div class="data" data-tag="count"> 0</div>
</div>
<div class="line">
<div class="label">Name</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="name">0</div>
<div class="text"> + 1 = </div>
<div class="data" data-tag="next">1</div>
</div>
<div class="line">
<div class="label">Name</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="name">1</div>
<div class="text"> + 1 = </div>
<div class="data" data-tag="next">2</div>
</div>
<div class="line">
<div class="label">Name</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="name">2</div>
<div class="text"> + 1 = </div>
<div class="data" data-tag="next">3</div>
</div>
<div class="line">
<div class="label">Last</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="last">3</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-key="key">bolt </div>
<div class="data" data-tag="count"> 4123</div>
</div>
<div class="line">
<div class="label">Name</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="name">0</div>
<div class="text"> + 1 = </div>
<div class="data" data-tag="next">1</div>
</div>
<div class="line">
<div class="label">Name</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="name">1</div>
<div class="text"> + 1 = </div>
<div class="data" data-tag="next">2</div>
</div>
<div class="line">
<div class="label">Name</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="name">2</div>
<div class="text"> + 1 = </div>
<div class="data" data-tag="next">3</div>
</div>
<div class="line">
<div class="label">Last</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="last">3</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-key="key">water </div>
<div class="data" data-tag="count"> 17</div>
</div>
<div class="line">
<div class="label">Name</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="name">0</div>
<div class="text"> + 1 = </div>
<div class="data" data-tag="next">1</div>
</div>
<div class="line">
<div class="label">Name</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="name">1</div>
<div class="text"> + 1 = </div>
<div class="data" data-tag="next">2</div>
</div>
<div class="line">
<div class="label">Name</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="name">2</div>
<div class="text"> + 1 = </div>
<div class="data" data-tag="next">3</div>
</div>
<div class="line">
<div class="label">Last</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="last">3</div>
</div>
<div class="line">
<div class="data" data-tag="test">one</div>
</div>
<div class="line">
</div>

View File

@ -0,0 +1,18 @@
test: close (xo_close_container) fails at marker 'm1'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm1'; not found 'data'
test: close (xo_close_container) fails at marker 'm1'; not found 'top'

View File

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

View File

@ -0,0 +1,18 @@
test: close (xo_close_container) fails at marker 'm1'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm1'; not found 'data'
test: close (xo_close_container) fails at marker 'm1'; not found 'top'

View File

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

View File

@ -0,0 +1,18 @@
test: close (xo_close_container) fails at marker 'm1'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm1'; not found 'data'
test: close (xo_close_container) fails at marker 'm1'; not found 'top'

View File

@ -0,0 +1,52 @@
Item Count
gum 1412
rope 85
ladder 0
bolt 4123
water 17
Item Count
gum 1412
rope 85
ladder 0
bolt 4123
water 17
Item Count
gum 1412
rope 85
ladder 0
bolt 4123
water 17
one
Item Count
gum 1412
Name: 0 + 1 = 1
Name: 1 + 1 = 2
Name: 2 + 1 = 3
Last: 3
rope 85
Name: 0 + 1 = 1
Name: 1 + 1 = 2
Name: 2 + 1 = 3
Last: 3
ladder 0
Name: 0 + 1 = 1
Name: 1 + 1 = 2
Name: 2 + 1 = 3
Last: 3
bolt 4123
Name: 0 + 1 = 1
Name: 1 + 1 = 2
Name: 2 + 1 = 3
Last: 3
water 17
Name: 0 + 1 = 1
Name: 1 + 1 = 2
Name: 2 + 1 = 3
Last: 3
one

View File

@ -0,0 +1,18 @@
test: close (xo_close_container) fails at marker 'm1'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm1'; not found 'data'
test: close (xo_close_container) fails at marker 'm1'; not found 'top'

View File

@ -0,0 +1 @@
<top><data><contents><item><name key="key">gum</name><count>1412</count></item><item><name key="key">rope</name><count>85</count></item><item><name key="key">ladder</name><count>0</count></item><item><name key="key">bolt</name><count>4123</count></item><item><name key="key">water</name><count>17</count></item></contents></data><data><contents><item><name key="key">gum</name><count>1412</count></item><item><name key="key">rope</name><count>85</count></item><item><name key="key">ladder</name><count>0</count></item><item><name key="key">bolt</name><count>4123</count></item><item><name key="key">water</name><count>17</count></item></contents></data><data><contents><item><name key="key">gum</name><count>1412</count></item><item><name key="key">rope</name><count>85</count></item><item><name key="key">ladder</name><count>0</count></item><item><name key="key">bolt</name><count>4123</count></item><item><name key="key">water</name><count>17</count><test>one</test></item></contents></data><data><contents><item><name key="key">gum</name><count>1412</count><sub><name>0</name><next>1</next></sub><sub><name>1</name><next>2</next></sub><sub><name>2</name><next>3</next></sub><last>3</last></item><item><name key="key">rope</name><count>85</count><sub><name>0</name><next>1</next></sub><sub><name>1</name><next>2</next></sub><sub><name>2</name><next>3</next></sub><last>3</last></item><item><name key="key">ladder</name><count>0</count><sub><name>0</name><next>1</next></sub><sub><name>1</name><next>2</next></sub><sub><name>2</name><next>3</next></sub><last>3</last></item><item><name key="key">bolt</name><count>4123</count><sub><name>0</name><next>1</next></sub><sub><name>1</name><next>2</next></sub><sub><name>2</name><next>3</next></sub><last>3</last></item><item><name key="key">water</name><count>17</count><sub><name>0</name><next>1</next></sub><sub><name>1</name><next>2</next></sub><sub><name>2</name><next>3</next></sub><last>3</last><test>one</test></item></contents></data></top>

View File

@ -0,0 +1,18 @@
test: close (xo_close_container) fails at marker 'm1'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm2'; not found 'data'
test: close (xo_close_container) fails at marker 'm1'; not found 'data'
test: close (xo_close_container) fails at marker 'm1'; not found 'top'

View File

@ -0,0 +1,165 @@
<top>
<data>
<contents>
<item>
<name key="key">gum</name>
<count>1412</count>
</item>
<item>
<name key="key">rope</name>
<count>85</count>
</item>
<item>
<name key="key">ladder</name>
<count>0</count>
</item>
<item>
<name key="key">bolt</name>
<count>4123</count>
</item>
<item>
<name key="key">water</name>
<count>17</count>
</item>
</contents>
</data>
<data>
<contents>
<item>
<name key="key">gum</name>
<count>1412</count>
</item>
<item>
<name key="key">rope</name>
<count>85</count>
</item>
<item>
<name key="key">ladder</name>
<count>0</count>
</item>
<item>
<name key="key">bolt</name>
<count>4123</count>
</item>
<item>
<name key="key">water</name>
<count>17</count>
</item>
</contents>
</data>
<data>
<contents>
<item>
<name key="key">gum</name>
<count>1412</count>
</item>
<item>
<name key="key">rope</name>
<count>85</count>
</item>
<item>
<name key="key">ladder</name>
<count>0</count>
</item>
<item>
<name key="key">bolt</name>
<count>4123</count>
</item>
<item>
<name key="key">water</name>
<count>17</count>
<test>one</test>
</item>
</contents>
</data>
<data>
<contents>
<item>
<name key="key">gum</name>
<count>1412</count>
<sub>
<name>0</name>
<next>1</next>
</sub>
<sub>
<name>1</name>
<next>2</next>
</sub>
<sub>
<name>2</name>
<next>3</next>
</sub>
<last>3</last>
</item>
<item>
<name key="key">rope</name>
<count>85</count>
<sub>
<name>0</name>
<next>1</next>
</sub>
<sub>
<name>1</name>
<next>2</next>
</sub>
<sub>
<name>2</name>
<next>3</next>
</sub>
<last>3</last>
</item>
<item>
<name key="key">ladder</name>
<count>0</count>
<sub>
<name>0</name>
<next>1</next>
</sub>
<sub>
<name>1</name>
<next>2</next>
</sub>
<sub>
<name>2</name>
<next>3</next>
</sub>
<last>3</last>
</item>
<item>
<name key="key">bolt</name>
<count>4123</count>
<sub>
<name>0</name>
<next>1</next>
</sub>
<sub>
<name>1</name>
<next>2</next>
</sub>
<sub>
<name>2</name>
<next>3</next>
</sub>
<last>3</last>
</item>
<item>
<name key="key">water</name>
<count>17</count>
<sub>
<name>0</name>
<next>1</next>
</sub>
<sub>
<name>1</name>
<next>2</next>
</sub>
<sub>
<name>2</name>
<next>3</next>
</sub>
<last>3</last>
<test>one</test>
</item>
</contents>
</data>
</top>

View File

@ -0,0 +1 @@
<div class="line"><div class="title">Item </div><div class="title"> Count</div></div><div class="line"><div class="text">Name: </div><div class="data" data-tag="name">gum </div></div><div class="line"><div class="text">Name: </div><div class="data" data-tag="name">rope </div></div><div class="line"><div class="text">Name: </div><div class="data" data-tag="name">ladder </div></div><div class="line"><div class="text">Name: </div><div class="data" data-tag="name">bolt </div></div><div class="line"><div class="text">Name: </div><div class="data" data-tag="name">water </div></div><div class="line"></div><div class="line"></div><div class="line"><div class="title">Item </div><div class="title"> Count</div></div><div class="line"><div class="text">Name: </div><div class="data" data-tag="item">gum </div></div><div class="line"><div class="text">Name: </div><div class="data" data-tag="item">rope </div></div><div class="line"><div class="text">Name: </div><div class="data" data-tag="item">ladder </div></div><div class="line"><div class="text">Name: </div><div class="data" data-tag="item">bolt </div></div><div class="line"><div class="text">Name: </div><div class="data" data-tag="item">water </div></div><div class="line"></div><div class="line"></div><div class="line"><div class="title">Test </div><div class="title"> Three</div></div><div class="line"><div class="text">Name: </div><div class="data" data-tag="item">gum </div></div><div class="line"><div class="text">Name: </div><div class="data" data-tag="item">rope </div></div><div class="line"><div class="text">Name: </div><div class="data" data-tag="item">ladder </div></div><div class="line"><div class="text">Name: </div><div class="data" data-tag="item">bolt </div></div><div class="line"><div class="text">Name: </div><div class="data" data-tag="item">water </div></div><div class="line"><div class="label">Total:</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="total">six</div></div><div class="line"><div class="data" data-tag="one">one</div><div class="data" data-tag="two">two</div><div class="data" data-tag="three">three</div></div><div class="line"></div>

View File

@ -0,0 +1,93 @@
<div class="line">
<div class="title">Item </div>
<div class="title"> Count</div>
</div>
<div class="line">
<div class="text">Name: </div>
<div class="data" data-tag="name" data-xpath="/top/data/contents/name">gum </div>
</div>
<div class="line">
<div class="text">Name: </div>
<div class="data" data-tag="name" data-xpath="/top/data/contents/name">rope </div>
</div>
<div class="line">
<div class="text">Name: </div>
<div class="data" data-tag="name" data-xpath="/top/data/contents/name">ladder </div>
</div>
<div class="line">
<div class="text">Name: </div>
<div class="data" data-tag="name" data-xpath="/top/data/contents/name">bolt </div>
</div>
<div class="line">
<div class="text">Name: </div>
<div class="data" data-tag="name" data-xpath="/top/data/contents/name">water </div>
</div>
<div class="line">
</div>
<div class="line">
</div>
<div class="line">
<div class="title">Item </div>
<div class="title"> Count</div>
</div>
<div class="line">
<div class="text">Name: </div>
<div class="data" data-tag="item" data-xpath="/top/data/contents/item">gum </div>
</div>
<div class="line">
<div class="text">Name: </div>
<div class="data" data-tag="item" data-xpath="/top/data/contents/item">rope </div>
</div>
<div class="line">
<div class="text">Name: </div>
<div class="data" data-tag="item" data-xpath="/top/data/contents/item">ladder </div>
</div>
<div class="line">
<div class="text">Name: </div>
<div class="data" data-tag="item" data-xpath="/top/data/contents/item">bolt </div>
</div>
<div class="line">
<div class="text">Name: </div>
<div class="data" data-tag="item" data-xpath="/top/data/contents/item">water </div>
</div>
<div class="line">
</div>
<div class="line">
</div>
<div class="line">
<div class="title">Test </div>
<div class="title"> Three</div>
</div>
<div class="line">
<div class="text">Name: </div>
<div class="data" data-tag="item" data-xpath="/top/data/contents/item">gum </div>
</div>
<div class="line">
<div class="text">Name: </div>
<div class="data" data-tag="item" data-xpath="/top/data/contents/item">rope </div>
</div>
<div class="line">
<div class="text">Name: </div>
<div class="data" data-tag="item" data-xpath="/top/data/contents/item">ladder </div>
</div>
<div class="line">
<div class="text">Name: </div>
<div class="data" data-tag="item" data-xpath="/top/data/contents/item">bolt </div>
</div>
<div class="line">
<div class="text">Name: </div>
<div class="data" data-tag="item" data-xpath="/top/data/contents/item">water </div>
</div>
<div class="line">
<div class="label">Total:</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="total" data-xpath="/top/data/contents/total">six</div>
</div>
<div class="line">
<div class="data" data-tag="one" data-xpath="/top/data/contents/one">one</div>
<div class="data" data-tag="two" data-xpath="/top/data/contents/two">two</div>
<div class="data" data-tag="three" data-xpath="/top/data/contents/three">three</div>
</div>
<div class="line">
</div>

View File

@ -0,0 +1,93 @@
<div class="line">
<div class="title">Item </div>
<div class="title"> Count</div>
</div>
<div class="line">
<div class="text">Name: </div>
<div class="data" data-tag="name">gum </div>
</div>
<div class="line">
<div class="text">Name: </div>
<div class="data" data-tag="name">rope </div>
</div>
<div class="line">
<div class="text">Name: </div>
<div class="data" data-tag="name">ladder </div>
</div>
<div class="line">
<div class="text">Name: </div>
<div class="data" data-tag="name">bolt </div>
</div>
<div class="line">
<div class="text">Name: </div>
<div class="data" data-tag="name">water </div>
</div>
<div class="line">
</div>
<div class="line">
</div>
<div class="line">
<div class="title">Item </div>
<div class="title"> Count</div>
</div>
<div class="line">
<div class="text">Name: </div>
<div class="data" data-tag="item">gum </div>
</div>
<div class="line">
<div class="text">Name: </div>
<div class="data" data-tag="item">rope </div>
</div>
<div class="line">
<div class="text">Name: </div>
<div class="data" data-tag="item">ladder </div>
</div>
<div class="line">
<div class="text">Name: </div>
<div class="data" data-tag="item">bolt </div>
</div>
<div class="line">
<div class="text">Name: </div>
<div class="data" data-tag="item">water </div>
</div>
<div class="line">
</div>
<div class="line">
</div>
<div class="line">
<div class="title">Test </div>
<div class="title"> Three</div>
</div>
<div class="line">
<div class="text">Name: </div>
<div class="data" data-tag="item">gum </div>
</div>
<div class="line">
<div class="text">Name: </div>
<div class="data" data-tag="item">rope </div>
</div>
<div class="line">
<div class="text">Name: </div>
<div class="data" data-tag="item">ladder </div>
</div>
<div class="line">
<div class="text">Name: </div>
<div class="data" data-tag="item">bolt </div>
</div>
<div class="line">
<div class="text">Name: </div>
<div class="data" data-tag="item">water </div>
</div>
<div class="line">
<div class="label">Total:</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="total">six</div>
</div>
<div class="line">
<div class="data" data-tag="one">one</div>
<div class="data" data-tag="two">two</div>
<div class="data" data-tag="three">three</div>
</div>
<div class="line">
</div>

View File

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

View File

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

View File

@ -0,0 +1,25 @@
Item Count
Name: gum
Name: rope
Name: ladder
Name: bolt
Name: water
Item Count
Name: gum
Name: rope
Name: ladder
Name: bolt
Name: water
Test Three
Name: gum
Name: rope
Name: ladder
Name: bolt
Name: water
Total:: six
onetwothree

View File

@ -0,0 +1 @@
<top><data><contents><name>gum</name><name>rope</name><name>ladder</name><name>bolt</name><name>water</name></contents><contents><item>gum</item><item>rope</item><item>ladder</item><item>bolt</item><item>water</item></contents><contents><item>gum</item><item>rope</item><item>ladder</item><item>bolt</item><item>water</item><total>six</total><one>one</one><two>two</two><three>three</three></contents></data></top>

View File

@ -0,0 +1,29 @@
<top>
<data>
<contents>
<name>gum</name>
<name>rope</name>
<name>ladder</name>
<name>bolt</name>
<name>water</name>
</contents>
<contents>
<item>gum</item>
<item>rope</item>
<item>ladder</item>
<item>bolt</item>
<item>water</item>
</contents>
<contents>
<item>gum</item>
<item>rope</item>
<item>ladder</item>
<item>bolt</item>
<item>water</item>
<total>six</total>
<one>one</one>
<two>two</two>
<three>three</three>
</contents>
</data>
</top>

View File

@ -11,6 +11,8 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include "xo.h"
@ -69,6 +71,10 @@ main (int argc, char **argv)
xo_set_flags(NULL, XOF_XPATH);
else if (strcmp(argv[argc], "info") == 0)
xo_set_flags(NULL, XOF_INFO);
else if (strcmp(argv[argc], "error") == 0) {
close(-1);
xo_err(1, "error detected");
}
}
xo_set_info(NULL, info, info_count);
@ -76,14 +82,17 @@ main (int argc, char **argv)
xo_open_container_h(NULL, "top");
xo_attr("test", "value");
xo_open_container("data");
xo_open_list("item");
xo_attr("test2", "value2");
xo_emit("{T:Item/%-10s}{T:Total Sold/%12s}{T:In Stock/%12s}"
"{T:On Order/%12s}{T:SKU/%5s}\n");
for (ip = list; ip->i_title; ip++) {
xo_open_instance("item");
xo_attr("test3", "value3");
xo_emit("{keq:sku/%s-%u/%s-000-%u}"
"{k:name/%-10s/%s}{n:sold/%12u/%u}{:in-stock/%12u/%u}"
@ -142,6 +151,25 @@ main (int argc, char **argv)
xo_close_list("item");
xo_close_container("data");
xo_open_container("data");
xo_open_list("item");
for (ip = list; ip->i_title; ip++) {
xo_attr("test4", "value4");
xo_emit("{Lwc:Item}{l:item}\n", ip->i_title);
}
xo_close_list("item");
xo_close_container("data");
xo_emit("X{P:}X", "epic fail");
xo_emit("X{T:}X", "epic fail");
xo_emit("X{N:}X", "epic fail");
xo_emit("X{L:}X\n", "epic fail");
xo_emit("X{P: }X{Lwc:Cost}{:cost/%u}\n", 425);
xo_emit("X{P:/%30s}X{Lwc:Cost}{:cost/%u}\n", "", 455);
xo_close_container_h(NULL, "top");
xo_finish();

View File

@ -68,11 +68,12 @@ main (int argc, char **argv)
"Unicode-ის მეათე საერთაშორისო");
xo_emit("{:columns/%d}\n", rc);
xo_open_list("employee");
rc = xo_emit("{T:First Name/%-25s}{T:Last Name/%-14s}"
"{T:/%-12s}{T:Time (%)}\n", "Department");
xo_emit("{:columns/%d}\n", rc);
xo_open_list("employee");
for ( ; ep->e_first; ep++) {
xo_open_instance("employee");
rc = xo_emit("{[:-25}{:first-name/%s} ({:nic-name/\"%s\"}){]:}"

View File

@ -0,0 +1,157 @@
/*
* Copyright (c) 2015, Juniper Networks, Inc.
* All rights reserved.
* This SOFTWARE is licensed under the LICENSE provided in the
* ../Copyright file. By downloading, installing, copying, or otherwise
* using the SOFTWARE, you agree to be bound by the terms of that
* LICENSE.
* Phil Shafer, July 2015
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include "xo.h"
int
main (int argc, char **argv)
{
struct item {
const char *i_title;
int i_count;
};
struct item list[] = {
{ "gum", 1412 },
{ "rope", 85 },
{ "ladder", 0 },
{ "bolt", 4123 },
{ "water", 17 },
{ NULL, 0 }
};
struct item *ip;
int i;
argc = xo_parse_args(argc, argv);
if (argc < 0)
return 1;
for (argc = 1; argv[argc]; argc++) {
if (strcmp(argv[argc], "xml") == 0)
xo_set_style(NULL, XO_STYLE_XML);
else if (strcmp(argv[argc], "json") == 0)
xo_set_style(NULL, XO_STYLE_JSON);
else if (strcmp(argv[argc], "text") == 0)
xo_set_style(NULL, XO_STYLE_TEXT);
else if (strcmp(argv[argc], "html") == 0)
xo_set_style(NULL, XO_STYLE_HTML);
else if (strcmp(argv[argc], "pretty") == 0)
xo_set_flags(NULL, XOF_PRETTY);
else if (strcmp(argv[argc], "xpath") == 0)
xo_set_flags(NULL, XOF_XPATH);
else if (strcmp(argv[argc], "info") == 0)
xo_set_flags(NULL, XOF_INFO);
else if (strcmp(argv[argc], "error") == 0) {
close(-1);
xo_err(1, "error detected");
}
}
xo_set_flags(NULL, XOF_KEYS);
xo_set_program("test");
xo_open_container_h(NULL, "top");
xo_open_container("data");
xo_open_container("contents");
xo_open_list("item");
xo_emit("{T:Item/%-10s}{T:Count/%12s}\n");
for (ip = list; ip->i_title; ip++) {
xo_open_instance("item");
xo_emit("{k:name/%-10s/%s}{n:count/%12u/%u}\n",
ip->i_title, ip->i_count);
xo_close_instance("item");
}
xo_close_list("item");
xo_close_container("contents");
xo_close_container("data");
xo_emit("\n\n");
xo_open_container("data");
xo_open_container("contents");
xo_emit("{T:Item/%-10s}{T:Count/%12s}\n");
for (ip = list; ip->i_title; ip++) {
xo_open_instance("item");
xo_emit("{k:name/%-10s/%s}{n:count/%12u/%u}\n",
ip->i_title, ip->i_count);
}
xo_close_container("data");
xo_emit("\n\n");
xo_open_container("data");
xo_open_marker("m1");
xo_open_container("contents");
xo_emit("{T:Item/%-10s}{T:Count/%12s}\n");
for (ip = list; ip->i_title; ip++) {
xo_open_instance("item");
xo_emit("{k:name/%-10s/%s}{n:count/%12u/%u}\n",
ip->i_title, ip->i_count);
}
xo_close_container("data"); /* Should be a noop */
xo_emit("{:test}", "one");
xo_close_marker("m1");
xo_close_container("data"); /* Should be a noop */
xo_emit("\n\n");
xo_open_container("data");
xo_open_marker("m1");
xo_open_container("contents");
xo_emit("{T:Item/%-10s}{T:Count/%12s}\n");
for (ip = list; ip->i_title; ip++) {
xo_open_instance("item");
xo_emit("{k:name/%-10s/%s}{n:count/%12u/%u}\n",
ip->i_title, ip->i_count);
xo_open_marker("m2");
for (i = 0; i < 3; i++) {
xo_open_instance("sub");
xo_emit("{Lwc:/Name}{:name/%d} + 1 = {:next/%d}\n", i, i + 1);
xo_close_container("data");
}
xo_close_marker("m2");
xo_emit("{Lwc:/Last}{:last/%d}\n", i);
}
xo_close_container("data"); /* Should be a noop */
xo_emit("{:test}", "one");
xo_emit("\n\n");
xo_close_container_h(NULL, "top");
xo_finish();
return 0;
}

View File

@ -0,0 +1,114 @@
/*
* Copyright (c) 2015, Juniper Networks, Inc.
* All rights reserved.
* This SOFTWARE is licensed under the LICENSE provided in the
* ../Copyright file. By downloading, installing, copying, or otherwise
* using the SOFTWARE, you agree to be bound by the terms of that
* LICENSE.
* Phil Shafer, July 2015
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include "xo.h"
int
main (int argc, char **argv)
{
struct item {
const char *i_title;
int i_count;
};
struct item list[] = {
{ "gum", 1412 },
{ "rope", 85 },
{ "ladder", 0 },
{ "bolt", 4123 },
{ "water", 17 },
{ NULL, 0 }
};
struct item *ip;
int i;
argc = xo_parse_args(argc, argv);
if (argc < 0)
return 1;
for (argc = 1; argv[argc]; argc++) {
if (strcmp(argv[argc], "xml") == 0)
xo_set_style(NULL, XO_STYLE_XML);
else if (strcmp(argv[argc], "json") == 0)
xo_set_style(NULL, XO_STYLE_JSON);
else if (strcmp(argv[argc], "text") == 0)
xo_set_style(NULL, XO_STYLE_TEXT);
else if (strcmp(argv[argc], "html") == 0)
xo_set_style(NULL, XO_STYLE_HTML);
else if (strcmp(argv[argc], "pretty") == 0)
xo_set_flags(NULL, XOF_PRETTY);
else if (strcmp(argv[argc], "xpath") == 0)
xo_set_flags(NULL, XOF_XPATH);
else if (strcmp(argv[argc], "info") == 0)
xo_set_flags(NULL, XOF_INFO);
else if (strcmp(argv[argc], "error") == 0) {
close(-1);
xo_err(1, "error detected");
}
}
xo_set_flags(NULL, XOF_KEYS);
xo_set_program("test");
xo_open_container_h(NULL, "top");
xo_open_container("data");
xo_open_container("contents");
xo_emit("{T:Item/%-10s}{T:Count/%12s}\n");
for (ip = list; ip->i_title; ip++) {
xo_emit("Name: {l:name/%-10s/%s}\n", ip->i_title);
}
xo_close_container("contents");
xo_emit("\n\n");
xo_open_container("contents");
xo_emit("{T:Item/%-10s}{T:Count/%12s}\n");
for (ip = list; ip->i_title; ip++) {
xo_emit("Name: {l:item/%-10s/%s}\n", ip->i_title);
}
xo_close_container("contents");
xo_emit("\n\n");
xo_open_container("contents");
xo_emit("{T:Test/%-10s}{T:Three/%12s}\n");
xo_open_list("item");
for (ip = list; ip->i_title; ip++) {
xo_emit("Name: {l:item/%-10s/%s}\n", ip->i_title);
}
xo_emit("{Lwc:/Total:}{:total}\n", "six");
xo_emit("{:one}", "one");
xo_emit("{l:two}", "two");
xo_emit("{:three}", "three");
xo_close_container("contents");
xo_emit("\n\n");
xo_close_container_h(NULL, "top");
xo_finish();
return 0;
}

View File

@ -7,27 +7,29 @@
.\" # LICENSE.
.\" # Phil Shafer, July 2014
.\"
.Dd July, 2014
.Dt LIBXO 3
.Dd December 4, 2014
.Dt XO 1
.Os
.Sh NAME
.Nm xo
.Nd emit formatted output based on format string and arguments
.Sh SYNOPSIS
.Nm xo
.Nm
.Op Fl options
.Op Ar argument...
.Sh DESCRIPTION
The
.Nm xo
.Nm
utility allows command line access to the functionality of
the
.Em libxo
library. Using
.Nm xo ,
.Nm libxo
library.
Using
.Nm ,
shell scripts can emit
.Em XML ,
.Em JSON , or
.Em JSON ,
or
.Em HTML
using the same commands that emit text output.
.Pp
@ -63,11 +65,11 @@ Wrap output in a set of containers
.It Fl "-xml OR -X"
Generate XML output
.It Fl "-xpath"
Add XPath data to HTML output);
Add XPath data to HTML output
.El
.Pp
The
.Nm xo
.Nm
utility accepts a format string suitable for
.Xr xo_emit 3
and a set of zero or more arguments used to supply data for that string.
@ -95,7 +97,8 @@ and a set of zero or more arguments used to supply data for that string.
The
.Fl "-wrap <path>"
option can be used to wrap emitted content in a
specific hierarchy. The path is a set of hierarchical names separated
specific hierarchy.
The path is a set of hierarchical names separated
by the '/' character.
.Bd -literal -offset indent
xo --wrap top/a/b/c '{:tag}' value
@ -128,11 +131,14 @@ and
.Fl "\-close <path>"
can be used to emit
hierarchical information without the matching close and open
tag. This allows a shell script to emit open tags, data, and
then close tags. The
tag.
This allows a shell script to emit open tags, data, and
then close tags.
The
.Fl \-depth
option may be used to set the
depth for indentation. The
depth for indentation.
The
.Fl "\-leading-xpath"
may be used to
prepend data to the XPath values used for HTML output style.
@ -154,37 +160,39 @@ prepend data to the XPath values used for HTML output style.
}
}
.Ed
.Pp
.Sh EXAMPLE
.Bd -literal -offset indent
.Bd -literal
% xo 'The {:product} is {:status}\n' stereo "in route"
The stereo is in route
% xo -p -X 'The {:product} is {:status}\n' stereo "in route"
<product>stereo</product>
<status>in route</status>
.Ed
.Pp
.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 libxo 3 ,
.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

View File

@ -362,8 +362,7 @@ main (int argc UNUSED, char **argv)
}
xo_set_formatter(NULL, formatter, checkpoint);
xo_set_flags(NULL, XOF_NO_VA_ARG);
xo_set_flags(NULL, XOF_NO_TOP);
xo_set_flags(NULL, XOF_NO_VA_ARG | XOF_NO_TOP | XOF_NO_CLOSE);
fmt = *argv++;
if (opt_opener == NULL && opt_closer == NULL && fmt == NULL) {

View File

@ -11,4 +11,4 @@ man_MANS = xolint.1
EXTRA_DIST = xolint.1 xolint.pl
install-exec-hook:
install ${srcdir}/xolint.pl ${bindir}/xolint
install ${srcdir}/xolint.pl ${DESTDIR}${bindir}/xolint

View File

@ -7,12 +7,13 @@
.\" # LICENSE.
.\" # Phil Shafer, July 2014
.\"
.Dd July, 2014
.Dt LIBXO 3
.Dd December 4, 2014
.Dt XOLINT 1
.Os
.Sh NAME
.Nm xolint
.Nd detect errors in programs using xo_emit
.Nd detect errors in programs using
.Xr xo_emit 3
.Sh SYNOPSIS
.Nm xolint
.Op Fl c
@ -25,34 +26,45 @@
.Op Fl "X"
.Op Ar files...
.Sh DESCRIPTION
xolint is a tool for reporting common mistakes in format strings
in source code that invokes xo_emit(). It allows these errors
.Nm
is a tool for reporting common mistakes in format strings
in source code that invokes
.Xr xo_emit 3 .
It allows these errors
to be diagnosed at build time, rather than waiting until runtime.
.Pp
xolint takes the one or more C files as arguments, and reports
and errors, warning, or informational messages as needed.
.Nm
takes one or more C files as arguments, and reports
error, warning, or informational messages as needed.
.Bl -tag -width "C <flags>"
.It Fl c
Invoke 'cpp' against the input file
.It Fl "C <flags>"
Flags that are passed to 'cpp
Flags that are passed to 'cpp'
.It Fl "d"
Enable debug output
.It Fl "D"
Generate documentation for all xolint messages
Generate documentation for all
.Nm
messages
.It Fl "I"
Generate a table of xo_info_t structures.
Generate a table of
.Dv xo_info_t
structures.
.It Fl "p"
Print the offending lines after the error message is displayed
.It Fl "V"
Do not report errors, but instead print a complete list of
all field names, sorted alphabetically. The output can help spot
all field names, sorted alphabetically.
The output can help spot
inconsistencies and spelling errors.
.It Fl "X"
Extract samples from xolint, suitable for internal testing.
Extract samples from
.Nm ,
suitable for internal testing.
.El
.Pp
Output message contain the source filename and line number, the
The output message contains the source filename and line number, the
class of the message, the message, and, if
.Fl p
is given, the
@ -62,28 +74,31 @@ line that contains the error:
xolint.c: 16: error: anchor format should be "%d"
16 xo_emit("{[:/%s}");
.Ed
.Pp
.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 libxo 3 ,
.Xr xo_emit 3
.Sh HISTORY
The
.Fa libxo
library was added in FreeBSD 10.1.
.Nm libxo
library was added in
.Fx 10.1 .
.Sh AUTHOR
Phil Shafer

View File

@ -21,6 +21,7 @@ MAN+= xo_attr.3 \
xo_create.3 \
xo_emit.3 \
xo_err.3 \
xo_error.3 \
xo_finish.3 \
xo_flush.3 \
xo_no_setlocale.3 \