mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-22 11:17:19 +00:00
Import to 0.6.1
0.5.0: document "trim" modifier add xo_emit_field functions Add xo_set_file{,_h} functions Fix LIBXO_* variables; add -L and -I as needed add --disable-silent-rules and an explicit make; s/PACKAGE-NAME/PACKAGE_NAME/; add /download/ to 'url' fix silliness where xo_flush_h emitted closing tag (html); make the caller (xo_message) do it flush after transitions; fix flush call in xo_do_emit mkdir the version-specific packaging dir use "XO_" instead of LIBXO_ 0.6.0: Add --with-retain-size to set the size (in bits) of the retain hash buckets Add The Argument Modifier ({a:}) Add retain and no-retain to --libxo autoconf: Add test for monitor.h Document quote heuristic go deep with nroff backslashes Use "ULL" for 32 bit check add xo_retain_clear and xo_retain_clear_all docs: combine two 'handles' section; move command line argument section handle GETTEXT when msgfmt isn't where it's supposed to be (FreeBSD) make 'retain' a flag (XOEF_RETAIN) instead of a role; it's simpler, and doesn't feel as tacky. "{R:}" was painful to document, which means it's painful to use. new xo_emit_f functions nuke some unused UNUSEDs test code: path must be static update test cases 0.6.1: fix version number (missed a commit during new-release) Reviewed by: sjg Approved by: sjg (mentor)
This commit is contained in:
commit
42ff34c310
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=298083
@ -77,6 +77,7 @@ GH_PAGES_PACKAGE_DIR = ${GH_PAGES_DIR}/${GH_PACKAGING_DIR}
|
||||
packages:
|
||||
@-[ -d ${GH_PAGES_DIR} ] && set -x \
|
||||
&& echo "Updating packages on gh-pages ..." \
|
||||
&& mkdir -p ${GH_PAGES_DIR}/${GH_PACKAGING_DIR} \
|
||||
&& SHA1="`openssl sha1 ${PACKAGE_FILE} | awk '{print $$2}'`" \
|
||||
&& SHA256="`openssl sha256 ${PACKAGE_FILE} | awk '{print $$2}'`" \
|
||||
&& SIZE="`ls -l ${PACKAGE_FILE} | awk '{print $$5}'`" \
|
||||
|
@ -12,7 +12,7 @@
|
||||
#
|
||||
|
||||
AC_PREREQ(2.2)
|
||||
AC_INIT([libxo], [0.4.7], [phil@juniper.net])
|
||||
AC_INIT([libxo], [0.6.1], [phil@juniper.net])
|
||||
AM_INIT_AUTOMAKE([-Wall -Werror foreign -Wno-portability])
|
||||
|
||||
# Support silent build rules. Requires at least automake-1.11.
|
||||
@ -74,6 +74,7 @@ AC_CHECK_HEADERS([ctype.h errno.h stdio.h stdlib.h])
|
||||
AC_CHECK_HEADERS([string.h sys/param.h unistd.h ])
|
||||
AC_CHECK_HEADERS([sys/sysctl.h])
|
||||
AC_CHECK_HEADERS([threads.h])
|
||||
AC_CHECK_HEADERS([monitor.h])
|
||||
|
||||
dnl humanize_number(3) is a great function, but it's not standard.
|
||||
dnl Note Macosx has the function in libutil.a but doesn't ship the
|
||||
@ -148,10 +149,18 @@ fi
|
||||
AC_SUBST(GETTEXT_CFLAGS)
|
||||
AC_SUBST(GETTEXT_LIBS)
|
||||
|
||||
GETTEXT_BINDIR=${GETTEXT_PREFIX}/bin
|
||||
AC_SUBST(GETTEXT_BINDIR)
|
||||
GETTEXT_LIBDIR=${GETTEXT_PREFIX}/lib
|
||||
AC_SUBST(GETTEXT_LIBDIR)
|
||||
if test -x ${GETTEXT_PREFIX}/bin/msgfmt ; then
|
||||
GETTEXT_BINDIR=${GETTEXT_PREFIX}/bin
|
||||
elif test -x ${GETTEXT_PREFIX}/local/bin/msgfmt ; then
|
||||
GETTEXT_BINDIR=${GETTEXT_PREFIX}/local/bin
|
||||
else
|
||||
AC_MSG_NOTICE("could not find msgfmt tool")
|
||||
# Use a (bad) fall back value
|
||||
GETTEXT_BINDIR=${GETTEXT_PREFIX}/bin
|
||||
fi
|
||||
AC_SUBST(GETTEXT_BINDIR)
|
||||
|
||||
AM_CONDITIONAL([HAVE_GETTEXT], [test "$HAVE_GETTEXT" = "yes"])
|
||||
|
||||
@ -287,6 +296,18 @@ if test "${LIBXO_WCWIDTH}" != "no"; then
|
||||
AC_DEFINE([LIBXO_WCWIDTH], [1], [Enable local wcwidth implementation])
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([retain hash bucket size])
|
||||
AC_ARG_WITH(retain-size,
|
||||
[ --with-retain-size=[DIR] Specify retain hash bucket size (in bits)],
|
||||
[XO_RETAIN_SIZE=$withval],
|
||||
[XO_RETAIN_SIZE=default]
|
||||
)
|
||||
|
||||
AC_MSG_RESULT([$XO_RETAIN_SIZE])
|
||||
if test "${XO_RETAIN_SIZE}" != "default"; then
|
||||
AC_DEFINE_UNQUOTED([XO_RETAIN_SIZE], ${XO_RETAIN_SIZE}, [Retain hash bucket size])
|
||||
fi
|
||||
|
||||
AC_CHECK_LIB([m], [lrint])
|
||||
AM_CONDITIONAL([HAVE_LIBM], [test "$HAVE_LIBM" != "no"])
|
||||
|
||||
@ -347,12 +368,15 @@ XO_SRCDIR=${srcdir}
|
||||
XO_LIBDIR=${libdir}
|
||||
XO_BINDIR=${bindir}
|
||||
XO_INCLUDEDIR=${includedir}
|
||||
XO_CFLAGS="${CFLAGS}"
|
||||
|
||||
AC_SUBST(XO_LIBS)
|
||||
AC_SUBST(XO_SRCDIR)
|
||||
AC_SUBST(XO_LIBDIR)
|
||||
AC_SUBST(XO_BINDIR)
|
||||
AC_SUBST(XO_INCLUDEDIR)
|
||||
AC_SUBST(XO_LIBEXT)
|
||||
AC_SUBST(XO_CFLAGS)
|
||||
|
||||
AC_ARG_WITH(encoder-dir,
|
||||
[ --with-encoder-dir=[DIR] Specify location of encoder libraries],
|
||||
@ -449,4 +473,5 @@ AC_MSG_NOTICE([summary of build options:
|
||||
isthreaded: ${HAVE_ISTHREADED:-no}
|
||||
thread-local: ${THREAD_LOCAL:-no}
|
||||
local wcwidth: ${LIBXO_WCWIDTH:-no}
|
||||
retain size: ${XO_RETAIN_SIZE:-no}
|
||||
])
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -699,25 +699,26 @@ XOF_WARN is set, a warning will be generated.
|
||||
Field modifiers are flags which modify the way content emitted for
|
||||
particular output styles:
|
||||
|
||||
|---+---------------+-------------------------------------------------|
|
||||
| M | Name | Description |
|
||||
|---+---------------+-------------------------------------------------|
|
||||
| c | colon | A colon (":") is appended after the label |
|
||||
| d | display | Only emit field for display styles (text/HTML) |
|
||||
| e | encoding | Only emit for encoding styles (XML/JSON) |
|
||||
| g | gettext | Call gettext on field's render content |
|
||||
| h | humanize (hn) | Format large numbers in human-readable style |
|
||||
| | hn-space | Humanize: Place space between numeric and unit |
|
||||
| | hn-decimal | Humanize: Add a decimal digit, if number < 10 |
|
||||
| | hn-1000 | Humanize: Use 1000 as divisor instead of 1024 |
|
||||
| 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 |
|
||||
| p | plural | Gettext: Use comma-separated plural form |
|
||||
| q | quotes | Quote the field when using JSON style |
|
||||
| t | trim | Trim leading and trailing whitespace |
|
||||
| w | white | A blank (" ") is appended after the label |
|
||||
|---+---------------+-------------------------------------------------|
|
||||
|---+---------------+--------------------------------------------------|
|
||||
| M | Name | Description |
|
||||
|---+---------------+--------------------------------------------------|
|
||||
| a | argument | The content appears as a 'const char *' argument |
|
||||
| c | colon | A colon (":") is appended after the label |
|
||||
| d | display | Only emit field for display styles (text/HTML) |
|
||||
| e | encoding | Only emit for encoding styles (XML/JSON) |
|
||||
| g | gettext | Call gettext on field's render content |
|
||||
| h | humanize (hn) | Format large numbers in human-readable style |
|
||||
| | hn-space | Humanize: Place space between numeric and unit |
|
||||
| | hn-decimal | Humanize: Add a decimal digit, if number < 10 |
|
||||
| | hn-1000 | Humanize: Use 1000 as divisor instead of 1024 |
|
||||
| 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 |
|
||||
| p | plural | Gettext: Use comma-separated plural form |
|
||||
| q | quotes | Quote the field when using JSON style |
|
||||
| t | trim | Trim leading and trailing whitespace |
|
||||
| w | white | A blank (" ") is appended after the label |
|
||||
|---+---------------+--------------------------------------------------|
|
||||
|
||||
Roles and modifiers can also use more verbose names, when preceeded by
|
||||
a comma. For example, the modifier string "Lwc" (or "L,white,colon")
|
||||
@ -727,6 +728,27 @@ modifier string "Vkq" (or ":key,quote") means the field has a value
|
||||
role (the default role), that it is a key for the current instance,
|
||||
and that the value should be quoted when encoded for JSON.
|
||||
|
||||
**** The Argument Modifier ({a:})
|
||||
|
||||
The argument modifier indicates that the content of the field
|
||||
descriptor will be placed as a UTF-8 string (const char *) argument
|
||||
within the xo_emit parameters.
|
||||
|
||||
EXAMPLE:
|
||||
xo_emit("{La:} {a:}\n", "Label text", "label", "value");
|
||||
TEXT:
|
||||
Label text value
|
||||
JSON:
|
||||
"label": "value"
|
||||
XML:
|
||||
<label>value</label>
|
||||
|
||||
The argument modifier allows field names for value fields to be passed
|
||||
on the stack, avoiding the need to build a field descriptor using
|
||||
snprintf. For many field roles, the argument modifier is not needed,
|
||||
since those roles have specific mechanisms for arguments, such as
|
||||
"{C:fg-%s}".
|
||||
|
||||
**** The Colon Modifier ({c:})
|
||||
|
||||
The colon modifier appends a single colon to the data value:
|
||||
@ -907,6 +929,21 @@ needed, but often this needs to be controlled by the caller.
|
||||
JSON:
|
||||
"year": "2014"
|
||||
|
||||
The heuristic is based on the format; if the format uses any of the
|
||||
following conversion specifiers, then no quotes are used:
|
||||
|
||||
d i o u x X D O U e E f F g G a A c C p
|
||||
|
||||
**** The Trim Modifier ({t:})
|
||||
|
||||
The trim modifier removes any leading or trailing whitespace from
|
||||
the value.
|
||||
|
||||
EXAMPLE:
|
||||
xo_emit("{t:description}", " some input ");
|
||||
JSON:
|
||||
"description": "some input"
|
||||
|
||||
**** The White Space Modifier ({w:})
|
||||
|
||||
The white space modifier appends a single space to the data value:
|
||||
@ -1029,6 +1066,24 @@ LANG, or LC_ALL environment varibles. The first of this list of
|
||||
variables is used and if none of the variables are set, the locale
|
||||
defaults to "UTF-8".
|
||||
|
||||
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.
|
||||
|
||||
xo_emit("Alll strings are utf-8 content {:tag/%ls}",
|
||||
L"except for wide strings");
|
||||
|
||||
"%S" is equivalent to "%ls".
|
||||
|
||||
|--------+-----------------+-------------------------------|
|
||||
| Format | Argument Type | Argument Contents |
|
||||
|--------+-----------------+-------------------------------|
|
||||
| %s | const char * | UTF-8 string |
|
||||
| %S | const char * | UTF-8 string (alias for '%s') |
|
||||
| %ls | const wchar_t * | Wide character UNICODE string |
|
||||
| %hs | const char * | locale-based string |
|
||||
|--------+-----------------+-------------------------------|
|
||||
|
||||
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)
|
||||
string, and the time value is formatted into a wchar_t string.
|
||||
@ -1163,6 +1218,53 @@ variants might be wise.
|
||||
| xo_emit_errc | xo_emit_errc_p |
|
||||
|------------------+------------------------|
|
||||
|
||||
*** Retaining Parsed Format Information @retain@
|
||||
|
||||
libxo can retain the parsed internal information related to the given
|
||||
format string, allowing subsequent xo_emit calls, the retained
|
||||
information is used, avoiding repetitive parsing of the format string.
|
||||
|
||||
SYNTAX:
|
||||
int xo_emit_f(xo_emit_flags_t flags, const char fmt, ...);
|
||||
EXAMPLE:
|
||||
xo_emit_f(XOEF_RETAIN, "{:some/%02d}{:thing/%-6s}{:fancy}\n",
|
||||
some, thing, fancy);
|
||||
|
||||
To retain parsed format information, use the XOEF_RETAIN flag to the
|
||||
xo_emit_f() function. A complete set of xo_emit_f functions exist to
|
||||
match all the xo_emit function signatures (with handles, varadic
|
||||
argument, and printf-like flags):
|
||||
|
||||
|------------------+------------------------|
|
||||
| Function | Flags Equivalent |
|
||||
|------------------+------------------------|
|
||||
| xo_emit_hv | xo_emit_hvf |
|
||||
| xo_emit_h | xo_emit_hf |
|
||||
| xo_emit | xo_emit_f |
|
||||
| xo_emit_hvp | xo_emit_hvfp |
|
||||
| xo_emit_hp | xo_emit_hfp |
|
||||
| xo_emit_p | xo_emit_fp |
|
||||
|------------------+------------------------|
|
||||
|
||||
The format string must be immutable across multiple calls to xo_emit_f(),
|
||||
since the library retains the string. Typically this is done by using
|
||||
static constant strings, such as string literals. If the string is not
|
||||
immutable, the XOEF_RETAIN flag must not be used.
|
||||
|
||||
The functions xo_retain_clear() and xo_retain_clear_all() release
|
||||
internal information on either a single format string or all format
|
||||
strings, respectively. Neither is required, but the library will
|
||||
retain this information until it is cleared or the process exits.
|
||||
|
||||
const char *fmt = "{:name} {:count/%d}\n";
|
||||
for (i = 0; i < 1000; i++) {
|
||||
xo_open_instance("item");
|
||||
xo_emit_f(XOEF_RETAIN, fmt, name[i], count[i]);
|
||||
}
|
||||
xo_retain_clear(fmt);
|
||||
|
||||
The retained information is kept as thread-specific data.
|
||||
|
||||
*** Example
|
||||
|
||||
In this example, the value for the number of items in stock is emitted:
|
||||
@ -1196,46 +1298,6 @@ penultimate line to:
|
||||
data-type="number"
|
||||
data-help="Number of items in stock">144</div>
|
||||
|
||||
** Command-line Arguments
|
||||
|
||||
libxo uses command line options to trigger rendering behavior. The
|
||||
following options are recognised:
|
||||
|
||||
- --libxo <options>
|
||||
- --libxo=<options>
|
||||
- --libxo:<brief-options>
|
||||
|
||||
Options is a comma-separated list of tokens that correspond to output
|
||||
styles, flags, or features:
|
||||
|
||||
|-------------+-------------------------------------------------------|
|
||||
| Token | Action |
|
||||
|-------------+-------------------------------------------------------|
|
||||
| color | Enable colors/effects for display styles (TEXT, HTML) |
|
||||
| dtrt | Enable "Do The Right Thing" mode |
|
||||
| html | Emit HTML output |
|
||||
| indent=xx | Set the indentation level |
|
||||
| info | Add info attributes (HTML) |
|
||||
| json | Emit JSON output |
|
||||
| keys | Emit the key attribute for keys (XML) |
|
||||
| log-gettext | Log (via stderr) each gettext(3) string lookup |
|
||||
| log-syslog | Log (via stderr) each syslog message (via xo_syslog) |
|
||||
| no-humanize | Ignore the {h:} modifier (TEXT, HTML) |
|
||||
| no-locale | Do not initialize the locale setting |
|
||||
| no-top | Do not emit a top set of braces (JSON) |
|
||||
| not-first | Pretend the 1st output item was not 1st (JSON) |
|
||||
| pretty | Emit pretty-printed output |
|
||||
| text | Emit TEXT output |
|
||||
| underscores | Replace XML-friendly "-"s with JSON friendly "_"s e |
|
||||
| units | Add the 'units' (XML) or 'data-units (HTML) attribute |
|
||||
| warn | Emit warnings when libxo detects bad calls |
|
||||
| warn-xml | Emit warnings in XML |
|
||||
| xml | Emit XML output |
|
||||
| xpath | Add XPath expressions (HTML) |
|
||||
|-------------+-------------------------------------------------------|
|
||||
|
||||
The brief options are detailed in ^LIBXO_OPTIONS^.
|
||||
|
||||
** Representing Hierarchy
|
||||
|
||||
For XML and JSON, individual fields appear inside hierarchies which
|
||||
@ -1382,20 +1444,81 @@ properly.
|
||||
xo_close_marker("fish-guts");
|
||||
}
|
||||
|
||||
** Command-line Arguments
|
||||
|
||||
libxo uses command line options to trigger rendering behavior. The
|
||||
following options are recognised:
|
||||
|
||||
- --libxo <options>
|
||||
- --libxo=<options>
|
||||
- --libxo:<brief-options>
|
||||
|
||||
Programs using libxo are expecting to call the xo_parse_args function
|
||||
to parse these arguments. See ^xo_parse_args^ for details.
|
||||
|
||||
Options is a comma-separated list of tokens that correspond to output
|
||||
styles, flags, or features:
|
||||
|
||||
|-------------+-------------------------------------------------------|
|
||||
| Token | Action |
|
||||
|-------------+-------------------------------------------------------|
|
||||
| color | Enable colors/effects for display styles (TEXT, HTML) |
|
||||
| dtrt | Enable "Do The Right Thing" mode |
|
||||
| html | Emit HTML output |
|
||||
| indent=xx | Set the indentation level |
|
||||
| info | Add info attributes (HTML) |
|
||||
| json | Emit JSON output |
|
||||
| keys | Emit the key attribute for keys (XML) |
|
||||
| log-gettext | Log (via stderr) each gettext(3) string lookup |
|
||||
| log-syslog | Log (via stderr) each syslog message (via xo_syslog) |
|
||||
| no-humanize | Ignore the {h:} modifier (TEXT, HTML) |
|
||||
| no-locale | Do not initialize the locale setting |
|
||||
| no-retain | Prevent retaining formatting information |
|
||||
| no-top | Do not emit a top set of braces (JSON) |
|
||||
| not-first | Pretend the 1st output item was not 1st (JSON) |
|
||||
| pretty | Emit pretty-printed output |
|
||||
| retain | Force retaining formatting information |
|
||||
| text | Emit TEXT output |
|
||||
| underscores | Replace XML-friendly "-"s with JSON friendly "_"s e |
|
||||
| units | Add the 'units' (XML) or 'data-units (HTML) attribute |
|
||||
| warn | Emit warnings when libxo detects bad calls |
|
||||
| warn-xml | Emit warnings in XML |
|
||||
| xml | Emit XML output |
|
||||
| xpath | Add XPath expressions (HTML) |
|
||||
|-------------+-------------------------------------------------------|
|
||||
|
||||
The brief options are detailed in ^LIBXO_OPTIONS^.
|
||||
|
||||
* The libxo API
|
||||
|
||||
This section gives details about the functions in libxo, how to call
|
||||
them, and the actions they perform.
|
||||
|
||||
** Handles @handles@
|
||||
|
||||
libxo uses "handles" to control its rendering functionality. The
|
||||
handle contains state and buffered data, as well as callback functions
|
||||
to process data.
|
||||
|
||||
A default handle is used when a NULL is passed to functions accepting
|
||||
a handle. This handle is initialized to write its data to stdout
|
||||
using the default style of text (XO_STYLE_TEXT).
|
||||
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
|
||||
opaque to the caller.
|
||||
|
||||
For the convenience of callers, the libxo library includes handle-less
|
||||
functions that implicitly use the default handle. Any function that
|
||||
takes a handle will use the default handle is a value of NULL is
|
||||
passed in place of a valid handle.
|
||||
The library has a default handle that is automatically initialized.
|
||||
By default, this handle will send text style output (XO_STYLE_TEXT) to
|
||||
standard output. The xo_set_style and xo_set_flags functions can be
|
||||
used to change this behavior.
|
||||
|
||||
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
|
||||
output.
|
||||
|
||||
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. For the convenience of
|
||||
callers, the libxo library includes handle-less functions that
|
||||
implicitly use the default handle.
|
||||
|
||||
For example, the following are equivalent:
|
||||
|
||||
@ -1404,46 +1527,6 @@ For example, the following are equivalent:
|
||||
|
||||
Handles are created using xo_create() and destroy using xo_destroy().
|
||||
|
||||
** UTF-8
|
||||
|
||||
All strings for libxo must be UTF-8. libxo will handle turning them
|
||||
into locale-based strings for display to the user.
|
||||
|
||||
The only exception is argument formatted using the "%ls" format, which
|
||||
require a wide character string (wchar_t *) as input. 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.
|
||||
|
||||
xo_emit("Alll strings are utf-8 content {:tag/%ls}",
|
||||
L"except for wide strings");
|
||||
|
||||
"%S" is equivalent to "%ls".
|
||||
|
||||
* The libxo API
|
||||
|
||||
This section gives details about the functions in libxo, how to call
|
||||
them, and the actions they perform.
|
||||
|
||||
** Handles
|
||||
|
||||
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
|
||||
opaque to the caller.
|
||||
|
||||
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
|
||||
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.
|
||||
|
||||
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
|
||||
output.
|
||||
|
||||
*** xo_create
|
||||
|
||||
A handle can be allocated using the xo_create() function:
|
||||
@ -1653,11 +1736,34 @@ string, since an inappropriate cast can ruin your day. The vap
|
||||
argument to xo_emit_hv() points to a variable argument list that can
|
||||
be used to retrieve arguments via va_arg().
|
||||
|
||||
*** Single Field Emitting Functions (xo_emit_field) @xo_emit_field@
|
||||
|
||||
The following functions can also make output, but only make a single
|
||||
field at a time:
|
||||
|
||||
int xo_emit_field_hv (xo_handle_t *xop, const char *rolmod,
|
||||
const char *contents, const char *fmt,
|
||||
const char *efmt, va_list vap);
|
||||
|
||||
int xo_emit_field_h (xo_handle_t *xop, const char *rolmod,
|
||||
const char *contents, const char *fmt,
|
||||
const char *efmt, ...);
|
||||
|
||||
int xo_emit_field (const char *rolmod, const char *contents,
|
||||
const char *fmt, const char *efmt, ...);
|
||||
|
||||
These functions are intended to avoid the scenario where one
|
||||
would otherwise need to compose a format descriptors using
|
||||
snprintf(). The individual parts of the format descriptor are
|
||||
passed in distinctly.
|
||||
|
||||
xo_emit("T", "Host name is ", NULL, NULL);
|
||||
xo_emit("V", "host-name", NULL, NULL, host-name);
|
||||
|
||||
*** Attributes (xo_attr) @xo_attr@
|
||||
|
||||
The xo_attr() function emits attributes for the XML output style.
|
||||
|
||||
|
||||
int xo_attr (const char *name, const char *fmt, ...);
|
||||
int xo_attr_h (xo_handle_t *xop, const char *name,
|
||||
const char *fmt, ...);
|
||||
@ -2555,23 +2661,23 @@ In 2001, we added an XML API to the JUNOS operating system, which is
|
||||
built on top of FreeBSD. Eventually this API became standardized as
|
||||
the NETCONF API (RFC 6241). As part of this effort, we modified many
|
||||
FreeBSD utilities to emit XML, typically via a "-X" switch. The
|
||||
results were mixed. The cost of maintaining this code, updating it
|
||||
results were mixed. The cost of maintaining this code, updating it,
|
||||
and carrying it were non-trivial, and contributed to our expense (and
|
||||
the associated delay) with upgrading the version of FreeBSD on which
|
||||
each release of JUNOS is based.
|
||||
|
||||
A recent (2014) effort within JUNOS aims at removing our modifications
|
||||
to the underlying FreeBSD code as a means of reducing the expense and
|
||||
delay. JUNOS is structured to have system components generate XML
|
||||
that is rendered by the CLI (think: login shell) into human-readable
|
||||
text. This allows the API to use the same plumbing as the CLI, and
|
||||
ensures that all components emit XML, and that it is emitted with
|
||||
knowledge of the consumer of that XML, yielding an API that have no
|
||||
incremental cost or feature delay.
|
||||
delay in tracking HEAD. JUNOS is structured to have system components
|
||||
generate XML that is rendered by the CLI (think: login shell) into
|
||||
human-readable text. This allows the API to use the same plumbing as
|
||||
the CLI, and ensures that all components emit XML, and that it is
|
||||
emitted with knowledge of the consumer of that XML, yielding an API
|
||||
that have no incremental cost or feature delay.
|
||||
|
||||
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.
|
||||
output calls with a single code path.
|
||||
|
||||
*** Did the complex semantics of format strings evolve over time?
|
||||
|
||||
|
@ -135,7 +135,7 @@ cbor_encode_uint (xo_buffer_t *xbp, uint64_t minor, unsigned limit)
|
||||
char *bp = xbp->xb_curp;
|
||||
int i, m;
|
||||
|
||||
if (minor > (1UL<<32)) {
|
||||
if (minor > (1ULL << 32)) {
|
||||
*bp++ |= CBOR_LEN64;
|
||||
m = 64;
|
||||
|
||||
|
@ -77,34 +77,34 @@ while test $# -gt 0; do
|
||||
;;
|
||||
|
||||
--cflags)
|
||||
echo -I@LIBXO_INCLUDEDIR@ @LIBXO_CFLAGS@
|
||||
echo -I@XO_INCLUDEDIR@ @XO_CFLAGS@
|
||||
;;
|
||||
|
||||
|
||||
--share)
|
||||
echo @LIBXO_SHAREDIR@
|
||||
echo @XO_SHAREDIR@
|
||||
;;
|
||||
|
||||
--bindir)
|
||||
echo @LIBXO_BINDIR@
|
||||
echo @XO_BINDIR@
|
||||
;;
|
||||
|
||||
--libdir)
|
||||
echo @LIBXO_LIBDIR@
|
||||
echo @XO_LIBDIR@
|
||||
;;
|
||||
|
||||
|
||||
--libs)
|
||||
if [ "`uname`" = "Linux" ]
|
||||
then
|
||||
if [ "@LIBXO_LIBDIR@" = "-L/usr/lib" -o "@LIBXO_LIBDIR@" = "-L/usr/lib64" ]
|
||||
if [ "@XO_LIBDIR@" = "-L/usr/lib" -o "@XO_LIBDIR@" = "-L/usr/lib64" ]
|
||||
then
|
||||
echo @LIBXO_LIBS@
|
||||
echo @XO_LIBS@
|
||||
else
|
||||
echo -L@LIBXO_LIBDIR@ @LIBXO_LIBS@
|
||||
echo -L@XO_LIBDIR@ @XO_LIBS@
|
||||
fi
|
||||
else
|
||||
echo -L@LIBXO_LIBDIR@ @LIBXO_LIBS@ @WIN32_EXTRA_LIBADD@
|
||||
echo -L@XO_LIBDIR@ @XO_LIBS@
|
||||
fi
|
||||
;;
|
||||
|
||||
|
@ -19,7 +19,8 @@
|
||||
* http://juniper.github.io/libxo/libxo-manual.html
|
||||
*
|
||||
* For first time readers, the core bits of code to start looking at are:
|
||||
* - xo_do_emit() -- the central function of the library
|
||||
* - xo_do_emit() -- parse and emit a set of fields
|
||||
* - xo_do_emit_fields -- the central function of the library
|
||||
* - xo_do_format_field() -- handles formatting a single field
|
||||
* - xo_transiton() -- the state machine that keeps things sane
|
||||
* and of course the "xo_handle_t" data structure, which carries all
|
||||
@ -120,6 +121,7 @@
|
||||
|
||||
const char xo_version[] = LIBXO_VERSION;
|
||||
const char xo_version_extra[] = LIBXO_VERSION_EXTRA;
|
||||
static const char xo_default_format[] = "%s";
|
||||
|
||||
#ifndef UNUSED
|
||||
#define UNUSED __attribute__ ((__unused__))
|
||||
@ -338,6 +340,7 @@ typedef unsigned long xo_xff_flags_t;
|
||||
#define XFF_GT_FIELD (1<<19) /* Call gettext() on a field */
|
||||
|
||||
#define XFF_GT_PLURAL (1<<20) /* Call dngettext to find plural form */
|
||||
#define XFF_ARGUMENT (1<<21) /* Content provided via argument */
|
||||
|
||||
/* Flags to turn off when we don't want i18n processing */
|
||||
#define XFF_GT_FLAGS (XFF_GT_FIELD | XFF_GT_PLURAL)
|
||||
@ -1046,7 +1049,7 @@ xo_is_utf8 (char ch)
|
||||
return (ch & 0x80);
|
||||
}
|
||||
|
||||
static int
|
||||
static inline int
|
||||
xo_utf8_to_wc_len (const char *buf)
|
||||
{
|
||||
unsigned b = (unsigned char) *buf;
|
||||
@ -1105,9 +1108,13 @@ xo_buf_utf8_len (xo_handle_t *xop, const char *buf, int bufsiz)
|
||||
* bits we pull off the first character is dependent on the length,
|
||||
* but we put 6 bits off all other bytes.
|
||||
*/
|
||||
static wchar_t
|
||||
static inline wchar_t
|
||||
xo_utf8_char (const char *buf, int len)
|
||||
{
|
||||
/* Most common case: singleton byte */
|
||||
if (len == 1)
|
||||
return (unsigned char) buf[0];
|
||||
|
||||
int i;
|
||||
wchar_t wc;
|
||||
const unsigned char *cp = (const unsigned char *) buf;
|
||||
@ -1281,6 +1288,195 @@ xo_data_escape (xo_handle_t *xop, const char *str, int len)
|
||||
xo_buf_escape(xop, &xop->xo_data, str, len, 0);
|
||||
}
|
||||
|
||||
#ifdef LIBXO_NO_RETAIN
|
||||
/*
|
||||
* Empty implementations of the retain logic
|
||||
*/
|
||||
|
||||
void
|
||||
xo_retain_clear_all (void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
xo_retain_clear (const char *fmt UNUSED)
|
||||
{
|
||||
return;
|
||||
}
|
||||
static void
|
||||
xo_retain_add (const char *fmt UNUSED, xo_field_info_t *fields UNUSED,
|
||||
unsigned num_fields UNUSED)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
xo_retain_find (const char *fmt UNUSED, xo_field_info_t **valp UNUSED,
|
||||
unsigned *nump UNUSED)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
#else /* !LIBXO_NO_RETAIN */
|
||||
/*
|
||||
* Retain: We retain parsed field definitions to enhance performance,
|
||||
* especially inside loops. We depend on the caller treating the format
|
||||
* strings as immutable, so that we can retain pointers into them. We
|
||||
* hold the pointers in a hash table, so allow quick access. Retained
|
||||
* information is retained until xo_retain_clear is called.
|
||||
*/
|
||||
|
||||
/*
|
||||
* xo_retain_entry_t holds information about one retained set of
|
||||
* parsed fields.
|
||||
*/
|
||||
typedef struct xo_retain_entry_s {
|
||||
struct xo_retain_entry_s *xre_next; /* Pointer to next (older) entry */
|
||||
unsigned long xre_hits; /* Number of times we've hit */
|
||||
const char *xre_format; /* Pointer to format string */
|
||||
unsigned xre_num_fields; /* Number of fields saved */
|
||||
xo_field_info_t *xre_fields; /* Pointer to fields */
|
||||
} xo_retain_entry_t;
|
||||
|
||||
/*
|
||||
* xo_retain_t holds a complete set of parsed fields as a hash table.
|
||||
*/
|
||||
#ifndef XO_RETAIN_SIZE
|
||||
#define XO_RETAIN_SIZE 6
|
||||
#endif /* XO_RETAIN_SIZE */
|
||||
#define RETAIN_HASH_SIZE (1<<XO_RETAIN_SIZE)
|
||||
|
||||
typedef struct xo_retain_s {
|
||||
xo_retain_entry_t *xr_bucket[RETAIN_HASH_SIZE];
|
||||
} xo_retain_t;
|
||||
|
||||
static THREAD_LOCAL(xo_retain_t) xo_retain;
|
||||
static THREAD_LOCAL(unsigned) xo_retain_count;
|
||||
|
||||
/*
|
||||
* Simple hash function based on Thomas Wang's paper. The original is
|
||||
* gone, but an archive is available on the Way Back Machine:
|
||||
*
|
||||
* http://web.archive.org/web/20071223173210/\
|
||||
* http://www.concentric.net/~Ttwang/tech/inthash.htm
|
||||
*
|
||||
* For our purposes, we can assume the low four bits are uninteresting
|
||||
* since any string less that 16 bytes wouldn't be worthy of
|
||||
* retaining. We toss the high bits also, since these bits are likely
|
||||
* to be common among constant format strings. We then run Wang's
|
||||
* algorithm, and cap the result at RETAIN_HASH_SIZE.
|
||||
*/
|
||||
static unsigned
|
||||
xo_retain_hash (const char *fmt)
|
||||
{
|
||||
volatile uintptr_t iptr = (uintptr_t) (const void *) fmt;
|
||||
|
||||
/* Discard low four bits and high bits; they aren't interesting */
|
||||
uint32_t val = (uint32_t) ((iptr >> 4) & (((1 << 24) - 1)));
|
||||
|
||||
val = (val ^ 61) ^ (val >> 16);
|
||||
val = val + (val << 3);
|
||||
val = val ^ (val >> 4);
|
||||
val = val * 0x3a8f05c5; /* My large prime number */
|
||||
val = val ^ (val >> 15);
|
||||
val &= RETAIN_HASH_SIZE - 1;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Walk all buckets, clearing all retained entries
|
||||
*/
|
||||
void
|
||||
xo_retain_clear_all (void)
|
||||
{
|
||||
int i;
|
||||
xo_retain_entry_t *xrep, *next;
|
||||
|
||||
for (i = 0; i < RETAIN_HASH_SIZE; i++) {
|
||||
for (xrep = xo_retain.xr_bucket[i]; xrep; xrep = next) {
|
||||
next = xrep->xre_next;
|
||||
xo_free(xrep);
|
||||
}
|
||||
xo_retain.xr_bucket[i] = NULL;
|
||||
}
|
||||
xo_retain_count = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Walk all buckets, clearing all retained entries
|
||||
*/
|
||||
void
|
||||
xo_retain_clear (const char *fmt)
|
||||
{
|
||||
xo_retain_entry_t **xrepp;
|
||||
unsigned hash = xo_retain_hash(fmt);
|
||||
|
||||
for (xrepp = &xo_retain.xr_bucket[hash]; *xrepp;
|
||||
xrepp = &(*xrepp)->xre_next) {
|
||||
if ((*xrepp)->xre_format == fmt) {
|
||||
*xrepp = (*xrepp)->xre_next;
|
||||
xo_retain_count -= 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Search the hash for an entry matching 'fmt'; return it's fields.
|
||||
*/
|
||||
static int
|
||||
xo_retain_find (const char *fmt, xo_field_info_t **valp, unsigned *nump)
|
||||
{
|
||||
if (xo_retain_count == 0)
|
||||
return -1;
|
||||
|
||||
unsigned hash = xo_retain_hash(fmt);
|
||||
xo_retain_entry_t *xrep;
|
||||
|
||||
for (xrep = xo_retain.xr_bucket[hash]; xrep != NULL;
|
||||
xrep = xrep->xre_next) {
|
||||
if (xrep->xre_format == fmt) {
|
||||
*valp = xrep->xre_fields;
|
||||
*nump = xrep->xre_num_fields;
|
||||
xrep->xre_hits += 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
xo_retain_add (const char *fmt, xo_field_info_t *fields, unsigned num_fields)
|
||||
{
|
||||
unsigned hash = xo_retain_hash(fmt);
|
||||
xo_retain_entry_t *xrep;
|
||||
unsigned sz = sizeof(*xrep) + (num_fields + 1) * sizeof(*fields);
|
||||
xo_field_info_t *xfip;
|
||||
|
||||
xrep = xo_realloc(NULL, sz);
|
||||
if (xrep == NULL)
|
||||
return;
|
||||
|
||||
xfip = (xo_field_info_t *) &xrep[1];
|
||||
memcpy(xfip, fields, num_fields * sizeof(*fields));
|
||||
|
||||
bzero(xrep, sizeof(*xrep));
|
||||
|
||||
xrep->xre_format = fmt;
|
||||
xrep->xre_fields = xfip;
|
||||
xrep->xre_num_fields = num_fields;
|
||||
|
||||
/* Record the field info in the retain bucket */
|
||||
xrep->xre_next = xo_retain.xr_bucket[hash];
|
||||
xo_retain.xr_bucket[hash] = xrep;
|
||||
xo_retain_count += 1;
|
||||
}
|
||||
|
||||
#endif /* !LIBXO_NO_RETAIN */
|
||||
|
||||
/*
|
||||
* Generate a warning. Normally, this is a text message written to
|
||||
* standard error. If the XOF_WARN_XML flag is set, then we generate
|
||||
@ -1574,6 +1770,19 @@ xo_message_hcv (xo_handle_t *xop, int code, const char *fmt, va_list vap)
|
||||
break;
|
||||
}
|
||||
|
||||
switch (xo_style(xop)) {
|
||||
case XO_STYLE_HTML:
|
||||
if (XOIF_ISSET(xop, XOIF_DIV_OPEN)) {
|
||||
static char div_close[] = "</div>";
|
||||
XOIF_CLEAR(xop, XOIF_DIV_OPEN);
|
||||
xo_data_append(xop, div_close, sizeof(div_close) - 1);
|
||||
|
||||
if (XOF_ISSET(xop, XOF_PRETTY))
|
||||
xo_data_append(xop, "\n", 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
(void) xo_flush_h(xop);
|
||||
}
|
||||
|
||||
@ -1679,6 +1888,39 @@ xo_create_to_file (FILE *fp, xo_style_t style, xo_xof_flags_t flags)
|
||||
return xop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default handler to output to a file.
|
||||
* @xop libxo handle
|
||||
* @fp FILE pointer to use
|
||||
*/
|
||||
int
|
||||
xo_set_file_h (xo_handle_t *xop, FILE *fp)
|
||||
{
|
||||
xop = xo_default(xop);
|
||||
|
||||
if (fp == NULL) {
|
||||
xo_failure(xop, "xo_set_file: NULL fp");
|
||||
return -1;
|
||||
}
|
||||
|
||||
xop->xo_opaque = fp;
|
||||
xop->xo_write = xo_write_to_file;
|
||||
xop->xo_close = xo_close_file;
|
||||
xop->xo_flush = xo_flush_file;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default handler to output to a file.
|
||||
* @fp FILE pointer to use
|
||||
*/
|
||||
int
|
||||
xo_set_file (FILE *fp)
|
||||
{
|
||||
return xo_set_file_h(NULL, fp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Release any resources held by the handle.
|
||||
* @xop XO handle to alter (or NULL for default handle)
|
||||
@ -1824,9 +2066,11 @@ static xo_mapping_t xo_xof_names[] = {
|
||||
{ XOF_LOG_SYSLOG, "log-syslog" },
|
||||
{ XOF_NO_HUMANIZE, "no-humanize" },
|
||||
{ XOF_NO_LOCALE, "no-locale" },
|
||||
{ XOF_RETAIN_NONE, "no-retain" },
|
||||
{ XOF_NO_TOP, "no-top" },
|
||||
{ XOF_NOT_FIRST, "not-first" },
|
||||
{ XOF_PRETTY, "pretty" },
|
||||
{ XOF_RETAIN_ALL, "retain" },
|
||||
{ XOF_UNDERSCORES, "underscores" },
|
||||
{ XOF_UNITS, "units" },
|
||||
{ XOF_WARN, "warn" },
|
||||
@ -3613,10 +3857,9 @@ xo_format_text (xo_handle_t *xop, const char *str, int len)
|
||||
}
|
||||
|
||||
static void
|
||||
xo_format_title (xo_handle_t *xop, xo_field_info_t *xfip)
|
||||
xo_format_title (xo_handle_t *xop, xo_field_info_t *xfip,
|
||||
const char *str, unsigned len)
|
||||
{
|
||||
const char *str = xfip->xfi_content;
|
||||
unsigned len = xfip->xfi_clen;
|
||||
const char *fmt = xfip->xfi_format;
|
||||
unsigned flen = xfip->xfi_flen;
|
||||
xo_xff_flags_t flags = xfip->xfi_flags;
|
||||
@ -4083,10 +4326,9 @@ xo_format_value (xo_handle_t *xop, const char *name, int nlen,
|
||||
}
|
||||
|
||||
static void
|
||||
xo_set_gettext_domain (xo_handle_t *xop, xo_field_info_t *xfip)
|
||||
xo_set_gettext_domain (xo_handle_t *xop, xo_field_info_t *xfip,
|
||||
const char *str, unsigned len)
|
||||
{
|
||||
const char *str = xfip->xfi_content;
|
||||
unsigned len = xfip->xfi_clen;
|
||||
const char *fmt = xfip->xfi_format;
|
||||
unsigned flen = xfip->xfi_flen;
|
||||
|
||||
@ -4335,13 +4577,13 @@ xo_colors_enabled (xo_handle_t *xop UNUSED)
|
||||
}
|
||||
|
||||
static void
|
||||
xo_colors_handle_text (xo_handle_t *xop UNUSED, xo_colors_t *newp)
|
||||
xo_colors_handle_text (xo_handle_t *xop, xo_colors_t *newp)
|
||||
{
|
||||
char buf[BUFSIZ];
|
||||
char *cp = buf, *ep = buf + sizeof(buf);
|
||||
unsigned i, bit;
|
||||
xo_colors_t *oldp = &xop->xo_colors;
|
||||
const char *code;
|
||||
const char *code = NULL;
|
||||
|
||||
/*
|
||||
* Start the buffer with an escape. We don't want to add the '['
|
||||
@ -4460,10 +4702,9 @@ xo_colors_handle_html (xo_handle_t *xop, xo_colors_t *newp)
|
||||
}
|
||||
|
||||
static void
|
||||
xo_format_colors (xo_handle_t *xop, xo_field_info_t *xfip)
|
||||
xo_format_colors (xo_handle_t *xop, xo_field_info_t *xfip,
|
||||
const char *str, unsigned len)
|
||||
{
|
||||
const char *str = xfip->xfi_content;
|
||||
unsigned len = xfip->xfi_clen;
|
||||
const char *fmt = xfip->xfi_format;
|
||||
unsigned flen = xfip->xfi_flen;
|
||||
|
||||
@ -4534,10 +4775,9 @@ xo_format_colors (xo_handle_t *xop, xo_field_info_t *xfip)
|
||||
}
|
||||
|
||||
static void
|
||||
xo_format_units (xo_handle_t *xop, xo_field_info_t *xfip)
|
||||
xo_format_units (xo_handle_t *xop, xo_field_info_t *xfip,
|
||||
const char *str, unsigned len)
|
||||
{
|
||||
const char *str = xfip->xfi_content;
|
||||
unsigned len = xfip->xfi_clen;
|
||||
const char *fmt = xfip->xfi_format;
|
||||
unsigned flen = xfip->xfi_flen;
|
||||
xo_xff_flags_t flags = xfip->xfi_flags;
|
||||
@ -4589,10 +4829,9 @@ xo_format_units (xo_handle_t *xop, xo_field_info_t *xfip)
|
||||
}
|
||||
|
||||
static int
|
||||
xo_find_width (xo_handle_t *xop, xo_field_info_t *xfip)
|
||||
xo_find_width (xo_handle_t *xop, xo_field_info_t *xfip,
|
||||
const char *str, unsigned len)
|
||||
{
|
||||
const char *str = xfip->xfi_content;
|
||||
unsigned len = xfip->xfi_clen;
|
||||
const char *fmt = xfip->xfi_format;
|
||||
unsigned flen = xfip->xfi_flen;
|
||||
|
||||
@ -4639,7 +4878,8 @@ xo_anchor_clear (xo_handle_t *xop)
|
||||
* format it when the end anchor tag is seen.
|
||||
*/
|
||||
static void
|
||||
xo_anchor_start (xo_handle_t *xop, xo_field_info_t *xfip)
|
||||
xo_anchor_start (xo_handle_t *xop, xo_field_info_t *xfip,
|
||||
const char *str, unsigned len)
|
||||
{
|
||||
if (xo_style(xop) != XO_STYLE_TEXT && xo_style(xop) != XO_STYLE_HTML)
|
||||
return;
|
||||
@ -4656,11 +4896,12 @@ xo_anchor_start (xo_handle_t *xop, xo_field_info_t *xfip)
|
||||
* Now we find the width, if possible. If it's not there,
|
||||
* we'll get it on the end anchor.
|
||||
*/
|
||||
xop->xo_anchor_min_width = xo_find_width(xop, xfip);
|
||||
xop->xo_anchor_min_width = xo_find_width(xop, xfip, str, len);
|
||||
}
|
||||
|
||||
static void
|
||||
xo_anchor_stop (xo_handle_t *xop, xo_field_info_t *xfip)
|
||||
xo_anchor_stop (xo_handle_t *xop, xo_field_info_t *xfip,
|
||||
const char *str, unsigned len)
|
||||
{
|
||||
if (xo_style(xop) != XO_STYLE_TEXT && xo_style(xop) != XO_STYLE_HTML)
|
||||
return;
|
||||
@ -4672,7 +4913,7 @@ xo_anchor_stop (xo_handle_t *xop, xo_field_info_t *xfip)
|
||||
|
||||
XOIF_CLEAR(xop, XOIF_UNITS_PENDING);
|
||||
|
||||
int width = xo_find_width(xop, xfip);
|
||||
int width = xo_find_width(xop, xfip, str, len);
|
||||
if (width == 0)
|
||||
width = xop->xo_anchor_min_width;
|
||||
|
||||
@ -4787,6 +5028,7 @@ static xo_mapping_t xo_role_names[] = {
|
||||
#define XO_ROLE_NEWLINE '\n'
|
||||
|
||||
static xo_mapping_t xo_modifier_names[] = {
|
||||
{ XFF_ARGUMENT, "argument" },
|
||||
{ XFF_COLON, "colon" },
|
||||
{ XFF_COMMA, "comma" },
|
||||
{ XFF_DISPLAY_ONLY, "display" },
|
||||
@ -4858,6 +5100,7 @@ xo_count_fields (xo_handle_t *xop UNUSED, const char *fmt)
|
||||
* '[': start a section of anchored text
|
||||
* ']': end a section of anchored text
|
||||
* The following modifiers are also supported:
|
||||
* 'a': content is provided via argument (const char *), not descriptor
|
||||
* 'c': flag: emit a colon after the label
|
||||
* 'd': field is only emitted for display styles (text and html)
|
||||
* 'e': field is only emitted for encoding styles (xml and json)
|
||||
@ -4884,7 +5127,7 @@ xo_parse_roles (xo_handle_t *xop, const char *fmt,
|
||||
xo_xff_flags_t flags = 0;
|
||||
uint8_t fnum = 0;
|
||||
|
||||
for (sp = basep; sp; sp++) {
|
||||
for (sp = basep; sp && *sp; sp++) {
|
||||
if (*sp == ':' || *sp == '/' || *sp == '}')
|
||||
break;
|
||||
|
||||
@ -4961,6 +5204,10 @@ xo_parse_roles (xo_handle_t *xop, const char *fmt,
|
||||
fnum = (fnum * 10) + (*sp - '0');
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
flags |= XFF_ARGUMENT;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
flags |= XFF_COLON;
|
||||
break;
|
||||
@ -5133,7 +5380,6 @@ static int
|
||||
xo_parse_fields (xo_handle_t *xop, xo_field_info_t *fields,
|
||||
unsigned num_fields, const char *fmt)
|
||||
{
|
||||
static const char default_format[] = "%s";
|
||||
const char *cp, *sp, *ep, *basep;
|
||||
unsigned field = 0;
|
||||
xo_field_info_t *xfip = fields;
|
||||
@ -5267,12 +5513,12 @@ xo_parse_fields (xo_handle_t *xop, xo_field_info_t *fields,
|
||||
xfip->xfi_next = ++sp;
|
||||
|
||||
/* If we have content, then we have a default format */
|
||||
if (xfip->xfi_clen || format) {
|
||||
if (xfip->xfi_clen || format || (xfip->xfi_flags & XFF_ARGUMENT)) {
|
||||
if (format) {
|
||||
xfip->xfi_format = format;
|
||||
xfip->xfi_flen = flen;
|
||||
} else if (xo_role_wants_default_format(xfip->xfi_ftype)) {
|
||||
xfip->xfi_format = default_format;
|
||||
xfip->xfi_format = xo_default_format;
|
||||
xfip->xfi_flen = 2;
|
||||
}
|
||||
}
|
||||
@ -5568,9 +5814,8 @@ xo_gettext_combine_formats (xo_handle_t *xop, const char *fmt UNUSED,
|
||||
* Summary: i18n aighn't cheap.
|
||||
*/
|
||||
static const char *
|
||||
xo_gettext_build_format (xo_handle_t *xop UNUSED,
|
||||
xo_field_info_t *fields UNUSED,
|
||||
int this_field UNUSED,
|
||||
xo_gettext_build_format (xo_handle_t *xop,
|
||||
xo_field_info_t *fields, int this_field,
|
||||
const char *fmt, char **new_fmtp)
|
||||
{
|
||||
if (xo_style_is_encoding(xop))
|
||||
@ -5686,17 +5931,22 @@ xo_gettext_rebuild_content (xo_handle_t *xop UNUSED,
|
||||
#endif /* HAVE_GETTEXT */
|
||||
|
||||
/*
|
||||
* The central function for emitting libxo output.
|
||||
* Emit a set of fields. This is really the core of libxo.
|
||||
*/
|
||||
static int
|
||||
xo_do_emit (xo_handle_t *xop, const char *fmt)
|
||||
xo_do_emit_fields (xo_handle_t *xop, xo_field_info_t *fields,
|
||||
unsigned max_fields, const char *fmt)
|
||||
{
|
||||
int gettext_inuse = 0;
|
||||
int gettext_changed = 0;
|
||||
int gettext_reordered = 0;
|
||||
unsigned ftype;
|
||||
xo_xff_flags_t flags;
|
||||
xo_field_info_t *new_fields = NULL;
|
||||
|
||||
xo_field_info_t *xfip;
|
||||
unsigned field;
|
||||
int rc = 0;
|
||||
|
||||
int flush = XOF_ISSET(xop, XOF_FLUSH);
|
||||
int flush_line = XOF_ISSET(xop, XOF_FLUSH_LINE);
|
||||
char *new_fmt = NULL;
|
||||
@ -5704,20 +5954,6 @@ xo_do_emit (xo_handle_t *xop, const char *fmt)
|
||||
if (XOIF_ISSET(xop, XOIF_REORDER) || xo_style(xop) == XO_STYLE_ENCODER)
|
||||
flush_line = 0;
|
||||
|
||||
xop->xo_columns = 0; /* Always reset it */
|
||||
xop->xo_errno = errno; /* Save for "%m" */
|
||||
|
||||
unsigned max_fields = xo_count_fields(xop, fmt), field;
|
||||
xo_field_info_t fields[max_fields], *xfip;
|
||||
|
||||
bzero(fields, max_fields * sizeof(fields[0]));
|
||||
|
||||
if (xo_parse_fields(xop, fields, max_fields, fmt))
|
||||
return -1; /* Warning already displayed */
|
||||
|
||||
unsigned ftype;
|
||||
xo_xff_flags_t flags;
|
||||
|
||||
/*
|
||||
* Some overhead for gettext; if the fields in the msgstr returned
|
||||
* by gettext are reordered, then we need to record start and end
|
||||
@ -5745,6 +5981,18 @@ xo_do_emit (xo_handle_t *xop, const char *fmt)
|
||||
min_fstart = field;
|
||||
}
|
||||
|
||||
const char *content = xfip->xfi_content;
|
||||
int clen = xfip->xfi_clen;
|
||||
|
||||
if (flags & XFF_ARGUMENT) {
|
||||
/*
|
||||
* Argument flag means the content isn't given in the descriptor,
|
||||
* but as a UTF-8 string ('const char *') argument in xo_vap.
|
||||
*/
|
||||
content = va_arg(xop->xo_vap, char *);
|
||||
clen = content ? strlen(content) : 0;
|
||||
}
|
||||
|
||||
if (ftype == XO_ROLE_NEWLINE) {
|
||||
xo_line_close(xop);
|
||||
if (flush_line && xo_flush_h(xop) < 0)
|
||||
@ -5773,15 +6021,15 @@ xo_do_emit (xo_handle_t *xop, const char *fmt)
|
||||
}
|
||||
|
||||
if (ftype == 'V')
|
||||
xo_format_value(xop, xfip->xfi_content, xfip->xfi_clen,
|
||||
xo_format_value(xop, content, clen,
|
||||
xfip->xfi_format, xfip->xfi_flen,
|
||||
xfip->xfi_encoding, xfip->xfi_elen, flags);
|
||||
else if (ftype == '[')
|
||||
xo_anchor_start(xop, xfip);
|
||||
xo_anchor_start(xop, xfip, content, clen);
|
||||
else if (ftype == ']')
|
||||
xo_anchor_stop(xop, xfip);
|
||||
xo_anchor_stop(xop, xfip, content, clen);
|
||||
else if (ftype == 'C')
|
||||
xo_format_colors(xop, xfip);
|
||||
xo_format_colors(xop, xfip, content, clen);
|
||||
|
||||
else if (ftype == 'G') {
|
||||
/*
|
||||
@ -5792,7 +6040,7 @@ xo_do_emit (xo_handle_t *xop, const char *fmt)
|
||||
* Since gettext returns strings in a static buffer, we make
|
||||
* a copy in new_fmt.
|
||||
*/
|
||||
xo_set_gettext_domain(xop, xfip);
|
||||
xo_set_gettext_domain(xop, xfip, content, clen);
|
||||
|
||||
if (!gettext_inuse) { /* Only translate once */
|
||||
gettext_inuse = 1;
|
||||
@ -5843,17 +6091,17 @@ xo_do_emit (xo_handle_t *xop, const char *fmt)
|
||||
}
|
||||
continue;
|
||||
|
||||
} else if (xfip->xfi_clen || xfip->xfi_format) {
|
||||
} else if (clen || xfip->xfi_format) {
|
||||
|
||||
const char *class_name = xo_class_name(ftype);
|
||||
if (class_name)
|
||||
xo_format_content(xop, class_name, xo_tag_name(ftype),
|
||||
xfip->xfi_content, xfip->xfi_clen,
|
||||
content, clen,
|
||||
xfip->xfi_format, xfip->xfi_flen, flags);
|
||||
else if (ftype == 'T')
|
||||
xo_format_title(xop, xfip);
|
||||
xo_format_title(xop, xfip, content, clen);
|
||||
else if (ftype == 'U')
|
||||
xo_format_units(xop, xfip);
|
||||
xo_format_units(xop, xfip, content, clen);
|
||||
else
|
||||
xo_failure(xop, "unknown field type: '%c'", ftype);
|
||||
}
|
||||
@ -5884,7 +6132,7 @@ xo_do_emit (xo_handle_t *xop, const char *fmt)
|
||||
if (flush && !XOIF_ISSET(xop, XOIF_ANCHOR)) {
|
||||
if (xo_write(xop) < 0)
|
||||
rc = -1; /* Report failure */
|
||||
else if (xop->xo_flush && xop->xo_flush(xop->xo_opaque) < 0)
|
||||
else if (xo_flush_h(xop) < 0)
|
||||
rc = -1;
|
||||
}
|
||||
|
||||
@ -5904,6 +6152,53 @@ xo_do_emit (xo_handle_t *xop, const char *fmt)
|
||||
return (rc < 0) ? rc : (int) xop->xo_columns;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse and emit a set of fields
|
||||
*/
|
||||
static int
|
||||
xo_do_emit (xo_handle_t *xop, xo_emit_flags_t flags, const char *fmt)
|
||||
{
|
||||
xop->xo_columns = 0; /* Always reset it */
|
||||
xop->xo_errno = errno; /* Save for "%m" */
|
||||
|
||||
if (fmt == NULL)
|
||||
return 0;
|
||||
|
||||
unsigned max_fields;
|
||||
xo_field_info_t *fields = NULL;
|
||||
|
||||
/* Adjust XOEF_RETAIN based on global flags */
|
||||
if (XOF_ISSET(xop, XOF_RETAIN_ALL))
|
||||
flags |= XOEF_RETAIN;
|
||||
if (XOF_ISSET(xop, XOF_RETAIN_NONE))
|
||||
flags &= ~XOEF_RETAIN;
|
||||
|
||||
/*
|
||||
* Check for 'retain' flag, telling us to retain the field
|
||||
* information. If we've already saved it, then we can avoid
|
||||
* re-parsing the format string.
|
||||
*/
|
||||
if (!(flags & XOEF_RETAIN)
|
||||
|| xo_retain_find(fmt, &fields, &max_fields) != 0
|
||||
|| fields == NULL) {
|
||||
|
||||
/* Nothing retained; parse the format string */
|
||||
max_fields = xo_count_fields(xop, fmt);
|
||||
fields = alloca(max_fields * sizeof(fields[0]));
|
||||
bzero(fields, max_fields * sizeof(fields[0]));
|
||||
|
||||
if (xo_parse_fields(xop, fields, max_fields, fmt))
|
||||
return -1; /* Warning already displayed */
|
||||
|
||||
if (flags & XOEF_RETAIN) {
|
||||
/* Retain the info */
|
||||
xo_retain_add(fmt, fields, max_fields);
|
||||
}
|
||||
}
|
||||
|
||||
return xo_do_emit_fields(xop, fields, max_fields, fmt);
|
||||
}
|
||||
|
||||
/*
|
||||
* Rebuild a format string in a gettext-friendly format. This function
|
||||
* is exposed to tools can perform this function. See xo(1).
|
||||
@ -5944,7 +6239,7 @@ xo_emit_hv (xo_handle_t *xop, const char *fmt, va_list vap)
|
||||
|
||||
xop = xo_default(xop);
|
||||
va_copy(xop->xo_vap, vap);
|
||||
rc = xo_do_emit(xop, fmt);
|
||||
rc = xo_do_emit(xop, 0, fmt);
|
||||
va_end(xop->xo_vap);
|
||||
bzero(&xop->xo_vap, sizeof(xop->xo_vap));
|
||||
|
||||
@ -5958,7 +6253,7 @@ xo_emit_h (xo_handle_t *xop, const char *fmt, ...)
|
||||
|
||||
xop = xo_default(xop);
|
||||
va_start(xop->xo_vap, fmt);
|
||||
rc = xo_do_emit(xop, fmt);
|
||||
rc = xo_do_emit(xop, 0, fmt);
|
||||
va_end(xop->xo_vap);
|
||||
bzero(&xop->xo_vap, sizeof(xop->xo_vap));
|
||||
|
||||
@ -5972,13 +6267,137 @@ xo_emit (const char *fmt, ...)
|
||||
int rc;
|
||||
|
||||
va_start(xop->xo_vap, fmt);
|
||||
rc = xo_do_emit(xop, fmt);
|
||||
rc = xo_do_emit(xop, 0, fmt);
|
||||
va_end(xop->xo_vap);
|
||||
bzero(&xop->xo_vap, sizeof(xop->xo_vap));
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
xo_emit_hvf (xo_handle_t *xop, xo_emit_flags_t flags,
|
||||
const char *fmt, va_list vap)
|
||||
{
|
||||
int rc;
|
||||
|
||||
xop = xo_default(xop);
|
||||
va_copy(xop->xo_vap, vap);
|
||||
rc = xo_do_emit(xop, flags, fmt);
|
||||
va_end(xop->xo_vap);
|
||||
bzero(&xop->xo_vap, sizeof(xop->xo_vap));
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
xo_emit_hf (xo_handle_t *xop, xo_emit_flags_t flags, const char *fmt, ...)
|
||||
{
|
||||
int rc;
|
||||
|
||||
xop = xo_default(xop);
|
||||
va_start(xop->xo_vap, fmt);
|
||||
rc = xo_do_emit(xop, flags, fmt);
|
||||
va_end(xop->xo_vap);
|
||||
bzero(&xop->xo_vap, sizeof(xop->xo_vap));
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
xo_emit_f (xo_emit_flags_t flags, const char *fmt, ...)
|
||||
{
|
||||
xo_handle_t *xop = xo_default(NULL);
|
||||
int rc;
|
||||
|
||||
va_start(xop->xo_vap, fmt);
|
||||
rc = xo_do_emit(xop, flags, fmt);
|
||||
va_end(xop->xo_vap);
|
||||
bzero(&xop->xo_vap, sizeof(xop->xo_vap));
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Emit a single field by providing the info information typically provided
|
||||
* inside the field description (role, modifiers, and formats). This is
|
||||
* a convenience function to avoid callers using snprintf to build field
|
||||
* descriptions.
|
||||
*/
|
||||
int
|
||||
xo_emit_field_hv (xo_handle_t *xop, const char *rolmod, const char *contents,
|
||||
const char *fmt, const char *efmt,
|
||||
va_list vap)
|
||||
{
|
||||
int rc;
|
||||
|
||||
xop = xo_default(xop);
|
||||
|
||||
if (rolmod == NULL)
|
||||
rolmod = "V";
|
||||
|
||||
xo_field_info_t xfi;
|
||||
|
||||
bzero(&xfi, sizeof(xfi));
|
||||
|
||||
const char *cp;
|
||||
cp = xo_parse_roles(xop, rolmod, rolmod, &xfi);
|
||||
if (cp == NULL)
|
||||
return -1;
|
||||
|
||||
xfi.xfi_start = fmt;
|
||||
xfi.xfi_content = contents;
|
||||
xfi.xfi_format = fmt;
|
||||
xfi.xfi_encoding = efmt;
|
||||
xfi.xfi_clen = contents ? strlen(contents) : 0;
|
||||
xfi.xfi_flen = fmt ? strlen(fmt) : 0;
|
||||
xfi.xfi_elen = efmt ? strlen(efmt) : 0;
|
||||
|
||||
/* If we have content, then we have a default format */
|
||||
if (contents && fmt == NULL
|
||||
&& xo_role_wants_default_format(xfi.xfi_ftype)) {
|
||||
xfi.xfi_format = xo_default_format;
|
||||
xfi.xfi_flen = 2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
va_copy(xop->xo_vap, vap);
|
||||
|
||||
rc = xo_do_emit_fields(xop, &xfi, 1, fmt ?: contents ?: "field");
|
||||
|
||||
va_end(xop->xo_vap);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
xo_emit_field_h (xo_handle_t *xop, const char *rolmod, const char *contents,
|
||||
const char *fmt, const char *efmt, ...)
|
||||
{
|
||||
int rc;
|
||||
va_list vap;
|
||||
|
||||
va_start(vap, efmt);
|
||||
rc = xo_emit_field_hv(xop, rolmod, contents, fmt, efmt, vap);
|
||||
va_end(vap);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
xo_emit_field (const char *rolmod, const char *contents,
|
||||
const char *fmt, const char *efmt, ...)
|
||||
{
|
||||
int rc;
|
||||
va_list vap;
|
||||
|
||||
va_start(vap, efmt);
|
||||
rc = xo_emit_field_hv(NULL, rolmod, contents, fmt, efmt, vap);
|
||||
va_end(vap);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
xo_attr_hv (xo_handle_t *xop, const char *name, const char *fmt, va_list vap)
|
||||
{
|
||||
@ -6392,7 +6811,7 @@ xo_open_list_hf (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name)
|
||||
}
|
||||
|
||||
int
|
||||
xo_open_list_h (xo_handle_t *xop, const char *name UNUSED)
|
||||
xo_open_list_h (xo_handle_t *xop, const char *name)
|
||||
{
|
||||
return xo_open_list_hf(xop, 0, name);
|
||||
}
|
||||
@ -6404,7 +6823,7 @@ xo_open_list (const char *name)
|
||||
}
|
||||
|
||||
int
|
||||
xo_open_list_hd (xo_handle_t *xop, const char *name UNUSED)
|
||||
xo_open_list_hd (xo_handle_t *xop, const char *name)
|
||||
{
|
||||
return xo_open_list_hf(xop, XOF_DTRT, name);
|
||||
}
|
||||
@ -7113,6 +7532,11 @@ xo_transition (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name,
|
||||
xsp->xs_state, new_state);
|
||||
}
|
||||
|
||||
/* Handle the flush flag */
|
||||
if (rc >= 0 && XOF_ISSET(xop, XOF_FLUSH))
|
||||
if (xo_flush_h(xop))
|
||||
rc = -1;
|
||||
|
||||
return rc;
|
||||
|
||||
marker_prevents_close:
|
||||
@ -7179,22 +7603,11 @@ xo_set_allocator (xo_realloc_func_t realloc_func, xo_free_func_t free_func)
|
||||
int
|
||||
xo_flush_h (xo_handle_t *xop)
|
||||
{
|
||||
static char div_close[] = "</div>";
|
||||
int rc;
|
||||
|
||||
xop = xo_default(xop);
|
||||
|
||||
switch (xo_style(xop)) {
|
||||
case XO_STYLE_HTML:
|
||||
if (XOIF_ISSET(xop, XOIF_DIV_OPEN)) {
|
||||
XOIF_CLEAR(xop, XOIF_DIV_OPEN);
|
||||
xo_data_append(xop, div_close, sizeof(div_close) - 1);
|
||||
|
||||
if (XOF_ISSET(xop, XOF_PRETTY))
|
||||
xo_data_append(xop, "\n", 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case XO_STYLE_ENCODER:
|
||||
xo_encoder_handle(xop, XO_OP_FLUSH, NULL, NULL);
|
||||
}
|
||||
@ -7435,7 +7848,7 @@ xo_set_program (const char *name)
|
||||
}
|
||||
|
||||
void
|
||||
xo_set_version_h (xo_handle_t *xop, const char *version UNUSED)
|
||||
xo_set_version_h (xo_handle_t *xop, const char *version)
|
||||
{
|
||||
xop = xo_default(xop);
|
||||
|
||||
|
@ -94,6 +94,11 @@ typedef unsigned long long xo_xof_flags_t;
|
||||
|
||||
#define XOF_LOG_GETTEXT XOF_BIT(28) /** Log (stderr) gettext lookup strings */
|
||||
#define XOF_UTF8 XOF_BIT(29) /** Force text output to be UTF8 */
|
||||
#define XOF_RETAIN_ALL XOF_BIT(30) /** Force use of XOEF_RETAIN */
|
||||
#define XOF_RETAIN_NONE XOF_BIT(31) /** Prevent use of XOEF_RETAIN */
|
||||
|
||||
typedef unsigned xo_emit_flags_t; /* Flags to xo_emit() and friends */
|
||||
#define XOEF_RETAIN (1<<0) /* Retain parsed formatting information */
|
||||
|
||||
/*
|
||||
* The xo_info_t structure provides a mapping between names and
|
||||
@ -162,6 +167,12 @@ xo_set_flags (xo_handle_t *xop, xo_xof_flags_t flags);
|
||||
void
|
||||
xo_clear_flags (xo_handle_t *xop, xo_xof_flags_t flags);
|
||||
|
||||
int
|
||||
xo_set_file_h (xo_handle_t *xop, FILE *fp);
|
||||
|
||||
int
|
||||
xo_set_file (FILE *fp);
|
||||
|
||||
void
|
||||
xo_set_info (xo_handle_t *xop, xo_info_t *infop, int count);
|
||||
|
||||
@ -180,6 +191,16 @@ xo_emit_h (xo_handle_t *xop, const char *fmt, ...);
|
||||
int
|
||||
xo_emit (const char *fmt, ...);
|
||||
|
||||
int
|
||||
xo_emit_hvf (xo_handle_t *xop, xo_emit_flags_t flags,
|
||||
const char *fmt, va_list vap);
|
||||
|
||||
int
|
||||
xo_emit_hf (xo_handle_t *xop, xo_emit_flags_t flags, const char *fmt, ...);
|
||||
|
||||
int
|
||||
xo_emit_f (xo_emit_flags_t flags, const char *fmt, ...);
|
||||
|
||||
PRINTFLIKE(2, 0)
|
||||
static inline int
|
||||
xo_emit_hvp (xo_handle_t *xop, const char *fmt, va_list vap)
|
||||
@ -209,6 +230,36 @@ xo_emit_p (const char *fmt, ...)
|
||||
return rc;
|
||||
}
|
||||
|
||||
PRINTFLIKE(3, 0)
|
||||
static inline int
|
||||
xo_emit_hvfp (xo_handle_t *xop, xo_emit_flags_t flags,
|
||||
const char *fmt, va_list vap)
|
||||
{
|
||||
return xo_emit_hvf(xop, flags, fmt, vap);
|
||||
}
|
||||
|
||||
PRINTFLIKE(3, 4)
|
||||
static inline int
|
||||
xo_emit_hfp (xo_handle_t *xop, xo_emit_flags_t flags, const char *fmt, ...)
|
||||
{
|
||||
va_list vap;
|
||||
va_start(vap, fmt);
|
||||
int rc = xo_emit_hvf(xop, flags, fmt, vap);
|
||||
va_end(vap);
|
||||
return rc;
|
||||
}
|
||||
|
||||
PRINTFLIKE(2, 3)
|
||||
static inline int
|
||||
xo_emit_fp (xo_emit_flags_t flags, const char *fmt, ...)
|
||||
{
|
||||
va_list vap;
|
||||
va_start(vap, fmt);
|
||||
int rc = xo_emit_hvf(NULL, flags, fmt, vap);
|
||||
va_end(vap);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
xo_open_container_h (xo_handle_t *xop, const char *name);
|
||||
|
||||
@ -593,4 +644,23 @@ char *
|
||||
xo_simplify_format (xo_handle_t *xop, const char *fmt, int with_numbers,
|
||||
xo_simplify_field_func_t field_cb);
|
||||
|
||||
int
|
||||
xo_emit_field_hv (xo_handle_t *xop, const char *rolmod, const char *contents,
|
||||
const char *fmt, const char *efmt,
|
||||
va_list vap);
|
||||
|
||||
int
|
||||
xo_emit_field_h (xo_handle_t *xop, const char *rolmod, const char *contents,
|
||||
const char *fmt, const char *efmt, ...);
|
||||
|
||||
int
|
||||
xo_emit_field (const char *rolmod, const char *contents,
|
||||
const char *fmt, const char *efmt, ...);
|
||||
|
||||
void
|
||||
xo_retain_clear_all (void);
|
||||
|
||||
void
|
||||
xo_retain_clear (const char *fmt);
|
||||
|
||||
#endif /* INCLUDE_XO_H */
|
||||
|
111
contrib/libxo/libxo/xo_emit_f.3
Normal file
111
contrib/libxo/libxo/xo_emit_f.3
Normal file
@ -0,0 +1,111 @@
|
||||
.\" #
|
||||
.\" # Copyright (c) 2016, 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, April 2016
|
||||
.\"
|
||||
.Dd April 15, 2016
|
||||
.Dt LIBXO 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm xo_emit_f , xo_emit_hf , xo_emit_hvf
|
||||
.Nd emit formatted output based on format string and arguments
|
||||
.Sh LIBRARY
|
||||
.Lb libxo
|
||||
.Sh SYNOPSIS
|
||||
.In libxo/xo.h
|
||||
.Ft int
|
||||
.Fn xo_emit_f "xo_emit_flags_t flags" "const char *fmt" "..."
|
||||
.Ft int
|
||||
.Fn xo_emit_hf "xo_handle_t *xop" "xo_emit_flags_t flags" "const char *fmt" "..."
|
||||
.Ft int
|
||||
.Fn xo_emit_hvf "xo_handle_t *xop" "xo_emit_flags_t flags" "const char *fmt" "va_list vap"
|
||||
.Ft void
|
||||
.Fn xo_retain_clear_all "void"
|
||||
.Ft void
|
||||
.Fn xo_retain_clear "const char *fmt"
|
||||
.Sh DESCRIPTION
|
||||
These functions allow callers to pass a set of flags to
|
||||
.Nm
|
||||
emitting functions. These processing of arguments, except for
|
||||
.Fa flags ,
|
||||
is identical to the base functions.
|
||||
See
|
||||
.Xr xo_emit 3
|
||||
for additional information.
|
||||
.Pp
|
||||
The only currently defined flag is
|
||||
.Dv XOEF_RETAIN .
|
||||
.Nm
|
||||
can retain the parsed internal information related to the given
|
||||
format string, allowing subsequent
|
||||
.Xr xo_emit 3
|
||||
calls, the retained
|
||||
information is used, avoiding repetitive parsing of the format string.
|
||||
To retain parsed format information, use the
|
||||
.Dv XOEF_RETAIN
|
||||
flag to the
|
||||
.Fn xo_emit_f
|
||||
function.
|
||||
.Pp
|
||||
The format string must be immutable across multiple calls to
|
||||
.Xn xo_emit_f ,
|
||||
since the library retains the string.
|
||||
Typically this is done by using
|
||||
static constant strings, such as string literals. If the string is not
|
||||
immutable, the
|
||||
.Dv XOEF_RETAIN
|
||||
flag must not be used.
|
||||
.Pp
|
||||
The functions
|
||||
.Fn xo_retain_clear
|
||||
and
|
||||
.Fn xo_retain_clear_all
|
||||
release internal information on either a single format string or all
|
||||
format strings, respectively.
|
||||
Neither is required, but the library will
|
||||
retain this information until it is cleared or the process exits.
|
||||
.Pp
|
||||
The retained information is kept as thread-specific data.
|
||||
.Pp
|
||||
Use
|
||||
.Fn xo_retain_clear
|
||||
and
|
||||
.Fn xo_retain_clear_all
|
||||
to clear the retained information, clearing the retained information
|
||||
for either a specific format string or all format strings, respectively.
|
||||
These functions are only needed when the calling application wants to
|
||||
clear this information; they are not generally needed.
|
||||
.Sh EXAMPLES
|
||||
.Pp
|
||||
.Bd -literal -offset indent
|
||||
for (i = 0; i < 1000; i++) {
|
||||
xo_open_instance("item");
|
||||
xo_emit_f(XOEF_RETAIN, "{:name} {:count/%d}\n",
|
||||
name[i], count[i]);
|
||||
}
|
||||
.Ed
|
||||
.Pp
|
||||
In this example, the caller desires to clear the retained information.
|
||||
.Bd -literal -offset indent
|
||||
const char *fmt = "{:name} {:count/%d}\n";
|
||||
for (i = 0; i < 1000; i++) {
|
||||
xo_open_instance("item");
|
||||
xo_emit_f(XOEF_RETAIN, fmt, name[i], count[i]);
|
||||
}
|
||||
xo_retain_clear(fmt);
|
||||
.Ed
|
||||
.Sh RETURN CODE
|
||||
The return values for these functions is identical to those of their
|
||||
traditional counterparts. See
|
||||
.Xr xo_emit 3
|
||||
for details.
|
||||
.Sh SEE ALSO
|
||||
.Xr xo_emit 3 ,
|
||||
.Xr xo_open_container 3 ,
|
||||
.Xr xo_open_list 3 ,
|
||||
.Xr xo_format 5 ,
|
||||
.Xr libxo 3
|
@ -51,14 +51,14 @@ field descriptions within the format string.
|
||||
.Pp
|
||||
The field description is given as follows:
|
||||
.Bd -literal -offset indent
|
||||
'{' [ role | modifier ]* [',' long-names ]* ':' [ content ]
|
||||
[ '/' field-format [ '/' encoding-format ]] '}'
|
||||
\(aq{\(aq [ role | modifier ]* [\(aq,\(aq long\-names ]* \(aq:\(aq [ content ]
|
||||
[ \(aq/\(aq field\-format [ \(aq/\(aq encoding\-format ]] \(aq}\(aq
|
||||
.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.
|
||||
The contents, field\-format, and
|
||||
encoding\-format are used in varying ways, based on the role.
|
||||
These are described in the following sections.
|
||||
.Pp
|
||||
Braces can be escaped by using double braces, similar to "%%" in
|
||||
@ -68,26 +68,26 @@ The format string "{{braces}}" would emit "{braces}".
|
||||
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
|
||||
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);
|
||||
xo_emit("{P: }{Lwc:In stock}{:in\-stock/%u}\\n", 65);
|
||||
.Ed
|
||||
.Pp
|
||||
This single line of code can generate text ("In stock: 65\\n"), XML
|
||||
("<in-stock>65</in-stock>"), JSON ('"in-stock": 65'), or HTML (too
|
||||
("<in\-stock>65</in\-stock>"), JSON (\(aq"in\-stock": 65\(aq), or HTML (too
|
||||
lengthy to be listed here).
|
||||
.Pp
|
||||
While roles and modifiers typically use single character for brevity,
|
||||
there are alternative names for each which allow more verbose
|
||||
formatting strings.
|
||||
These names must be preceded by a comma, and may follow any
|
||||
single-character values:
|
||||
single\-character values:
|
||||
.Bd -literal -offset indent
|
||||
xo_emit("{L,white,colon:In stock}{,key:in-stock/%u}\n", 65);
|
||||
xo_emit("{L,white,colon:In stock}{,key:in\-stock/%u}\\n", 65);
|
||||
.Ed
|
||||
.Ss "Field Roles"
|
||||
Field roles are optional, and indicate the role and formatting of the
|
||||
@ -96,7 +96,7 @@ The roles are listed below; only one role is permitted:
|
||||
.Bl -column "M" "Name12341234"
|
||||
.It Sy "M" "Name " "Description"
|
||||
.It C "color " "Field is a color or effect"
|
||||
.It D "decoration " "Field is non-text (e.g. colon, comma)"
|
||||
.It D "decoration " "Field is non\-text (e.g. colon, comma)"
|
||||
.It E "error " "Field is an error message"
|
||||
.It L "label " "Field is text that prefixes a value"
|
||||
.It N "note " "Field is text that follows a value"
|
||||
@ -105,12 +105,12 @@ The roles are listed below; only one role is permitted:
|
||||
.It U "units " "Field is the units for the previous value field"
|
||||
.It V "value " "Field is the name of field (the default)"
|
||||
.It W "warning " "Field is a warning message"
|
||||
.It \&[ "start-anchor" "Begin a section of anchored variable-width text"
|
||||
.It \&] "stop-anchor " "End a section of anchored variable-width text"
|
||||
.It \&[ "start\-anchor" "Begin a section of anchored variable\-width text"
|
||||
.It \&] "stop\-anchor " "End a section of anchored variable\-width text"
|
||||
.El
|
||||
.Bd -literal -offset indent
|
||||
EXAMPLE:
|
||||
xo_emit("{L:Free}{D::}{P: }{:free/%u} {U:Blocks}\n",
|
||||
xo_emit("{L:Free}{D::}{P: }{:free/%u} {U:Blocks}\\n",
|
||||
free_blocks);
|
||||
.Ed
|
||||
.Pp
|
||||
@ -121,50 +121,50 @@ a comma:
|
||||
.Bd -literal -offset indent
|
||||
EXAMPLE:
|
||||
xo_emit("{,label:Free}{,decoration::}{,padding: }"
|
||||
"{,value:free/%u} {,units:Blocks}\n",
|
||||
"{,value:free/%u} {,units:Blocks}\\n",
|
||||
free_blocks);
|
||||
.Ed
|
||||
.Ss "The Color Role ({C:})"
|
||||
Colors and effects control how text values are displayed; they are
|
||||
used for display styles (TEXT and HTML).
|
||||
.Bd -literal -offset indent
|
||||
xo_emit("{C:bold}{:value}{C:no-bold}\n", value);
|
||||
xo_emit("{C:bold}{:value}{C:no\-bold}\\n", value);
|
||||
.Ed
|
||||
.Pp
|
||||
Colors and effects remain in effect until modified by other "C"-role
|
||||
Colors and effects remain in effect until modified by other "C"\-role
|
||||
fields.
|
||||
.Bd -literal -offset indent
|
||||
xo_emit("{C:bold}{C:inverse}both{C:no-bold}only inverse\n");
|
||||
xo_emit("{C:bold}{C:inverse}both{C:no\-bold}only inverse\\n");
|
||||
.Ed
|
||||
.Pp
|
||||
If the content is empty, the "reset" action is performed.
|
||||
.Bd -literal -offset indent
|
||||
xo_emit("{C:both,underline}{:value}{C:}\n", value);
|
||||
xo_emit("{C:both,underline}{:value}{C:}\\n", value);
|
||||
.Ed
|
||||
.Pp
|
||||
The content should be a comma-separated list of zero or more colors or
|
||||
The content should be a comma\-separated list of zero or more colors or
|
||||
display effects.
|
||||
.Bd -literal -offset indent
|
||||
xo_emit("{C:bold,underline,inverse}All three{C:no-bold,no-inverse}\n");
|
||||
xo_emit("{C:bold,underline,inverse}All three{C:no\-bold,no\-inverse}\\n");
|
||||
.Ed
|
||||
.Pp
|
||||
The color content can be either static, when placed directly within
|
||||
the field descriptor, or a printf-style format descriptor can be used,
|
||||
the field descriptor, or a printf\-style format descriptor can be used,
|
||||
if preceded by a slash ("/"):
|
||||
.Bd -literal -offset indent
|
||||
xo_emit("{C:/%s%s}{:value}{C:}", need_bold ? "bold" : "",
|
||||
need_underline ? "underline" : "", value);
|
||||
.Ed
|
||||
.Pp
|
||||
Color names are prefixed with either "fg-" or "bg-" to change the
|
||||
Color names are prefixed with either "fg\-" or "bg\-" to change the
|
||||
foreground and background colors, respectively.
|
||||
.Bd -literal -offset indent
|
||||
xo_emit("{C:/fg-%s,bg-%s}{Lwc:Cost}{:cost/%u}{C:reset}\n",
|
||||
xo_emit("{C:/fg\-%s,bg\-%s}{Lwc:Cost}{:cost/%u}{C:reset}\\n",
|
||||
fg_color, bg_color, cost);
|
||||
.Ed
|
||||
.Pp
|
||||
The following table lists the supported effects:
|
||||
.Bl -column "no-underline"
|
||||
.Bl -column "no\-underline"
|
||||
.It Sy "Name " "Description"
|
||||
.It "bg\-xxxxx " "Change background color"
|
||||
.It "bold " "Start bold text effect"
|
||||
@ -179,7 +179,7 @@ The following table lists the supported effects:
|
||||
.El
|
||||
.Pp
|
||||
The following color names are supported:
|
||||
.Bl -column "no-underline"
|
||||
.Bl -column "no\-underline"
|
||||
.It Sy "Name"
|
||||
.It black
|
||||
.It blue
|
||||
@ -193,7 +193,7 @@ The following color names are supported:
|
||||
.El
|
||||
.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
|
||||
semi\-colons, and commas used to decorate the text and make it simpler
|
||||
for human readers.
|
||||
By marking these distinctly, HTML usage scenarios
|
||||
can use CSS to direct their display parameters.
|
||||
@ -219,22 +219,23 @@ change such as changing "/%06d" to "/%08d" should not force hand
|
||||
inspection of all .po files.
|
||||
.Pp
|
||||
The simplified version can be generated for a single message using the
|
||||
"xopo -s <text>" command, or an entire .pot can be translated using
|
||||
the "xopo -f <input> -o <output>" command.
|
||||
"xopo \-s <text>" command, or an entire .pot can be translated using
|
||||
the "xopo \-f <input> \-o <output>" command.
|
||||
.Bd -literal -offset indent
|
||||
xo_emit("{G:}Invalid token\n");
|
||||
xo_emit("{G:}Invalid token\\n");
|
||||
.Ed
|
||||
.Pp
|
||||
The {G:} role allows a domain name to be set.
|
||||
.Fn gettext
|
||||
calls will
|
||||
continue to use that domain name until the current format string
|
||||
processing is complete, enabling a library function to emit strings
|
||||
using it's own catalog.
|
||||
using it\(aqs own catalog.
|
||||
The domain name can be either static as the
|
||||
content of the field, or a format can be used to get the domain name
|
||||
from the arguments.
|
||||
.Bd -literal -offset indent
|
||||
xo_emit("{G:libc}Service unavailable in restricted mode\n");
|
||||
xo_emit("{G:libc}Service unavailable in restricted mode\\n");
|
||||
.Ed
|
||||
.Ss "The Label Role ({L:})"
|
||||
Labels are text that appears before a value.
|
||||
@ -249,7 +250,7 @@ Notes are text that appears after a value.
|
||||
.Ss "The Padding Role ({P:})"
|
||||
Padding represents whitespace used before and between fields.
|
||||
The padding content can be either static, when placed directly within
|
||||
the field descriptor, or a printf-style format descriptor can be used,
|
||||
the field descriptor, or a printf\-style format descriptor can be used,
|
||||
if preceded by a slash ("/"):
|
||||
.Bd -literal -offset indent
|
||||
xo_emit("{P: }{Lwc:Cost}{:cost/%u}\\n", cost);
|
||||
@ -259,7 +260,7 @@ if preceded by a slash ("/"):
|
||||
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,
|
||||
the field descriptor, or a printf\-style format descriptor can be used,
|
||||
if preceded by a slash ("/"):
|
||||
.Bd -literal -offset indent
|
||||
xo_emit("{T:Interface Statistics}\\n");
|
||||
@ -274,7 +275,7 @@ for the previous value field.
|
||||
xo_emit("{Lwc:Distance}{:distance/%u}{Uw:miles}\\n", miles);
|
||||
.Ed
|
||||
.Pp
|
||||
Note that the sense of the 'w' modifier is reversed for units;
|
||||
Note that the sense of the \(aqw\(aq modifier is reversed for units;
|
||||
a blank is added before the contents, rather than after it.
|
||||
.Pp
|
||||
When the
|
||||
@ -286,14 +287,14 @@ attribute:
|
||||
<distance units="miles">50</distance>
|
||||
.Ed
|
||||
.Pp
|
||||
Units can also be rendered in HTML as the "data-units" attribute:
|
||||
Units can also be rendered in HTML as the "data\-units" attribute:
|
||||
.Bd -literal -offset indent
|
||||
<div class="data" data-tag="distance" data-units="miles"
|
||||
data-xpath="/top/data/distance">50</div>
|
||||
<div class="data" data\-tag="distance" data\-units="miles"
|
||||
data\-xpath="/top/data/distance">50</div>
|
||||
.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).
|
||||
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.
|
||||
@ -356,16 +357,17 @@ Field modifiers are flags which modify the way content emitted for
|
||||
particular output styles:
|
||||
.Bl -column M "Name123456789"
|
||||
.It Sy M "Name " "Description"
|
||||
.It a "argument " "The content appears as a ""const char *"" argument"
|
||||
.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 h "humanize (hn) " "Format large numbers in human-readable style"
|
||||
.It " " "hn-space " "Humanize: Place space between numeric and unit"
|
||||
.It " " "hn-decimal " "Humanize: Add a decimal digit, if number < 10"
|
||||
.It " " "hn-1000 " "Humanize: Use 1000 as divisor instead of 1024"
|
||||
.It h "humanize (hn) " "Format large numbers in human\-readable style"
|
||||
.It " " "hn\-space " "Humanize: Place space between numeric and unit"
|
||||
.It " " "hn\-decimal " "Humanize: Add a decimal digit, if number < 10"
|
||||
.It " " "hn\-1000 " "Humanize: Use 1000 as divisor instead of 1024"
|
||||
.It k "key " "Field is a key, suitable for XPath predicates"
|
||||
.It l "leaf-list " "Field is a leaf-list, a list of leaf values"
|
||||
.It n "no-quotes " "Do not quote the field when using JSON style"
|
||||
.It l "leaf\-list " "Field is a leaf\-list, a list of leaf values"
|
||||
.It n "no\-quotes " "Do not quote the field when using JSON style"
|
||||
.It q "quotes " "Quote the field when using JSON style"
|
||||
.It t "trim " "Trim leading and trailing whitespace"
|
||||
.It w "white space " "A blank ("" "") is appended after the label"
|
||||
@ -373,7 +375,7 @@ particular output styles:
|
||||
.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').
|
||||
colon (\(aqc\(aq) and a space (\(aqw\(aq).
|
||||
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.
|
||||
@ -382,10 +384,31 @@ Roles and modifiers can also use more verbose names, when preceeded by
|
||||
a comma.
|
||||
For example, the modifier string "Lwc" (or "L,white,colon")
|
||||
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').
|
||||
and should be followed by a colon (\(aqc\(aq) and a space (\(aqw\(aq).
|
||||
The modifier string "Vkq" (or ":key,quote") means the field has a value
|
||||
role (the default role), that it is a key for the current instance,
|
||||
and that the value should be quoted when encoded for JSON.
|
||||
.Ss "The Argument Modifier ({a:})"
|
||||
The argument modifier indicates that the content of the field
|
||||
descriptor will be placed as a UTF\-8 string (const char *) argument
|
||||
within the xo_emit parameters.
|
||||
.Bd -literal -offset indent
|
||||
EXAMPLE:
|
||||
xo_emit("{La:} {a:}\\n", "Label text", "label", "value");
|
||||
TEXT:
|
||||
Label text value
|
||||
JSON:
|
||||
"label": "value"
|
||||
XML:
|
||||
<label>value</label>
|
||||
.Ed
|
||||
.Pp
|
||||
The argument modifier allows field names for value fields to be passed
|
||||
on the stack, avoiding the need to build a field descriptor using
|
||||
.Xr snprintf 1 .
|
||||
For many field roles, the argument modifier is not needed,
|
||||
since those roles have specific mechanisms for arguments,
|
||||
such as "{C:fg\-%s}".
|
||||
.Ss "The Colon Modifier ({c:})"
|
||||
The colon modifier appends a single colon to the data value:
|
||||
.Bd -literal -offset indent
|
||||
@ -397,7 +420,7 @@ The colon modifier appends a single colon to the data value:
|
||||
.Pp
|
||||
The colon modifier is only used for the TEXT and HTML output
|
||||
styles.
|
||||
It is commonly combined with the space modifier ('{w:}').
|
||||
It is commonly combined with the space modifier (\(aq{w:}\(aq).
|
||||
It is purely a convenience feature.
|
||||
.Ss "The Display Modifier ({d:})"
|
||||
The display modifier indicated the field should only be generated for
|
||||
@ -429,39 +452,39 @@ The encoding modifier is the opposite of the display modifier, and
|
||||
they are often used to give to distinct views of the underlying data.
|
||||
.Ss "The Humanize Modifier ({h:})"
|
||||
The humanize modifier is used to render large numbers as in a
|
||||
human-readable format.
|
||||
human\-readable format.
|
||||
While numbers like "44470272" are completely readable to computers and
|
||||
savants, humans will generally find "44M" more meaningful.
|
||||
.Pp
|
||||
"hn" can be used as an alias for "humanize".
|
||||
.Pp
|
||||
The humanize modifier only affects display styles (TEXT and HMTL).
|
||||
The "no-humanize" option will block the function of the humanize modifier.
|
||||
The "no\-humanize" option will block the function of the humanize modifier.
|
||||
.Pp
|
||||
There are a number of modifiers that affect details of humanization.
|
||||
These are only available in as full names, not single characters.
|
||||
The "hn-space" modifier places a space between the number and any
|
||||
The "hn\-space" modifier places a space between the number and any
|
||||
multiplier symbol, such as "M" or "K" (ex: "44 K").
|
||||
The "hn-decimal" modifier will add a decimal point and a single tenths digit
|
||||
The "hn\-decimal" modifier will add a decimal point and a single tenths digit
|
||||
when the number is less than 10 (ex: "4.4K").
|
||||
The "hn-1000" modifier will use 1000 as divisor instead of 1024, following the
|
||||
JEDEC-standard instead of the more natural binary powers-of-two
|
||||
The "hn\-1000" modifier will use 1000 as divisor instead of 1024, following the
|
||||
JEDEC\-standard instead of the more natural binary powers\-of\-two
|
||||
tradition.
|
||||
.Bd -literal -offset indent
|
||||
EXAMPLE:
|
||||
xo_emit("{h:input/%u}, {h,hn-space:output/%u}, "
|
||||
"{h,hn-decimal:errors/%u}, {h,hn-1000:capacity/%u}, "
|
||||
"{h,hn-decimal:remaining/%u}\n",
|
||||
xo_emit("{h:input/%u}, {h,hn\-space:output/%u}, "
|
||||
"{h,hn\-decimal:errors/%u}, {h,hn\-1000:capacity/%u}, "
|
||||
"{h,hn\-decimal:remaining/%u}\\n",
|
||||
input, output, errors, capacity, remaining);
|
||||
TEXT:
|
||||
21, 57 K, 96M, 44M, 1.2G
|
||||
.Ed
|
||||
.Pp
|
||||
In the HTML style, the original numeric value is rendered in the
|
||||
"data-number" attribute on the <div> element:
|
||||
"data\-number" attribute on the <div> element:
|
||||
.Bd -literal -offset indent
|
||||
<div class="data" data-tag="errors"
|
||||
data-number="100663296">96M</div>
|
||||
<div class="data" data\-tag="errors"
|
||||
data\-number="100663296">96M</div>
|
||||
.Ed
|
||||
.Ss "The Gettext Modifier ({g:})"
|
||||
The gettext modifier is used to translate individual fields using the
|
||||
@ -476,9 +499,9 @@ translation.
|
||||
In the following example, the strings "State" and "full" are passed
|
||||
to
|
||||
.Fn gettext
|
||||
to find locale-based translated strings.
|
||||
to find locale\-based translated strings.
|
||||
.Bd -literal -offset indent
|
||||
xo_emit("{Lgwc:State}{g:state}\n", "full");
|
||||
xo_emit("{Lgwc:State}{g:state}\\n", "full");
|
||||
.Ed
|
||||
.Ss "The Key Modifier ({k:})"
|
||||
The key modifier is used to indicate that a particular field helps
|
||||
@ -499,15 +522,15 @@ Currently the key modifier is only used when generating XPath values
|
||||
for the HTML output style when
|
||||
.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
|
||||
.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_emit("Member {l:name}\\n", user[i].u_name);
|
||||
}
|
||||
xo_close_list("user");
|
||||
XML:
|
||||
@ -516,8 +539,8 @@ rendered as single elements, where JSON renders them as arrays.
|
||||
JSON:
|
||||
"user": [ "phil", "pallavi" ]
|
||||
.Ed
|
||||
.Ss "The No-Quotes Modifier ({n:})"
|
||||
The no-quotes modifier (and its twin, the 'quotes' modifier) affect
|
||||
.Ss "The No\-Quotes Modifier ({n:})"
|
||||
The no\-quotes modifier (and its twin, the \(aqquotes\(aq modifier) affect
|
||||
the quoting of values in the JSON output style.
|
||||
JSON uses quotes for
|
||||
string values, but no quotes for numeric, boolean, and null data.
|
||||
@ -538,8 +561,9 @@ language settings.
|
||||
The contents of the field should be the singular
|
||||
and plural English values, separated by a comma:
|
||||
.Bd -literal -offset indent
|
||||
xo_emit("{:bytes} {Ngp:byte,bytes}\n", bytes);
|
||||
xo_emit("{:bytes} {Ngp:byte,bytes}\\n", bytes);
|
||||
.Ed
|
||||
.Pp
|
||||
The plural modifier is meant to work with the gettext modifier ({g:})
|
||||
but can work independently.
|
||||
.Pp
|
||||
@ -554,7 +578,7 @@ function is
|
||||
called to handle the heavy lifting, using the message catalog to
|
||||
convert the singular and plural forms into the native language.
|
||||
.Ss "The Quotes Modifier ({q:})"
|
||||
The quotes modifier (and its twin, the 'no-quotes' modifier) affect
|
||||
The quotes modifier (and its twin, the \(aqno-quotes\(aq modifier) affect
|
||||
the quoting of values in the JSON output style.
|
||||
JSON uses quotes for
|
||||
string values, but no quotes for numeric, boolean, and null data.
|
||||
@ -578,23 +602,23 @@ The white space modifier appends a single space to the data value:
|
||||
.Pp
|
||||
The white space modifier is only used for the TEXT and HTML output
|
||||
styles.
|
||||
It is commonly combined with the colon modifier ('{c:}').
|
||||
It is commonly combined with the colon modifier (\(aq{c:}\(aq).
|
||||
It is purely a convenience feature.
|
||||
.Pp
|
||||
Note that the sense of the 'w' modifier is reversed for the units role
|
||||
Note that the sense of the \(aqw\(aq modifier is reversed for the units role
|
||||
({Uw:}); a blank is added before the contents, rather than after it.
|
||||
.Ss "Field Formatting"
|
||||
The field format is similar to the format string for
|
||||
.Xr printf 3 .
|
||||
Its use varies based on the role of the field, but generally is used to
|
||||
format the field's contents.
|
||||
format the field\(aqs contents.
|
||||
.Pp
|
||||
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
|
||||
Note a field definition can contain zero or more printf\-style
|
||||
.Dq directives ,
|
||||
which are sequences that start with a '%' and end with
|
||||
which are sequences that start with a \(aq%\(aq and end with
|
||||
one of following characters: "diouxXDOUeEfFgGaAcCsSp".
|
||||
Each directive
|
||||
is matched by one of more arguments to the
|
||||
@ -603,54 +627,54 @@ function.
|
||||
.Pp
|
||||
The format string has the form:
|
||||
.Bd -literal -offset indent
|
||||
'%' format-modifier * format-character
|
||||
\(aq%\(aq format\-modifier * format\-character
|
||||
.Ed
|
||||
.Pp
|
||||
The format- modifier can be:
|
||||
The format\- modifier can be:
|
||||
.Bl -bullet
|
||||
.It
|
||||
a '#' character, indicating the output value should be prefixed with
|
||||
a \(aq#\(aq character, indicating the output value should be prefixed with
|
||||
"0x", typically to indicate a base 16 (hex) value.
|
||||
.It
|
||||
a minus sign ('-'), indicating the output value should be padded on
|
||||
a minus sign (\(aq\-\(aq), indicating the output value should be padded on
|
||||
the right instead of the left.
|
||||
.It
|
||||
a leading zero ('0') indicating the output value should be padded on the
|
||||
left with zeroes instead of spaces (' ').
|
||||
a leading zero (\(aq0\(aq) indicating the output value should be padded on the
|
||||
left with zeroes instead of spaces (\(aq \(aq).
|
||||
.It
|
||||
one or more digits ('0' - '9') indicating the minimum width of the
|
||||
one or more digits (\(aq0\(aq \- \(aq9\(aq) indicating the minimum width of the
|
||||
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.
|
||||
width for a non\-string argument.
|
||||
When handling ASCII strings this
|
||||
functions as the field width but for multi-byte characters, a single
|
||||
functions as the field width but for multi\-byte characters, a single
|
||||
character may be composed of multiple 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.
|
||||
This modifier cannot be given for non\-string arguments.
|
||||
.It
|
||||
one or more 'h' characters, indicating shorter input data.
|
||||
one or more \(aqh\(aq characters, indicating shorter input data.
|
||||
.It
|
||||
one or more 'l' characters, indicating longer input data.
|
||||
one or more \(aql\(aq characters, indicating longer input data.
|
||||
.It
|
||||
a 'z' character, indicating a 'size_t' argument.
|
||||
a \(aqz\(aq character, indicating a \(aqsize_t\(aq argument.
|
||||
.It
|
||||
a 't' character, indicating a 'ptrdiff_t' argument.
|
||||
a \(aqt\(aq character, indicating a \(aqptrdiff_t\(aq argument.
|
||||
.It
|
||||
a ' ' character, indicating a space should be emitted before
|
||||
a \(aq \(aq character, indicating a space should be emitted before
|
||||
positive numbers.
|
||||
.It
|
||||
a '+' character, indicating sign should emitted before any number.
|
||||
a \(aq+\(aq character, indicating sign should emitted before any number.
|
||||
.El
|
||||
.Pp
|
||||
Note that 'q', 'D', 'O', and 'U' are considered deprecated and will be
|
||||
Note that \(aqq\(aq, \(aqD\(aq, \(aqO\(aq, and \(aqU\(aq are considered deprecated and will be
|
||||
removed eventually.
|
||||
.Pp
|
||||
The format character is described in the following table:
|
||||
@ -665,22 +689,22 @@ The format character is described in the following table:
|
||||
.It D "long " "base 10 (decimal)"
|
||||
.It O "unsigned long " "base 8 (octal)"
|
||||
.It U "unsigned long " "base 10 (decimal)"
|
||||
.It e "double " "[-]d.ddde+-dd"
|
||||
.It E "double " "[-]d.dddE+-dd"
|
||||
.It f "double " "[-]ddd.ddd"
|
||||
.It F "double " "[-]ddd.ddd"
|
||||
.It g "double " "as 'e' or 'f'"
|
||||
.It G "double " "as 'E' or 'F'"
|
||||
.It a "double " "[-]0xh.hhhp[+-]d"
|
||||
.It A "double " "[-]0Xh.hhhp[+-]d"
|
||||
.It e "double " "[\-]d.ddde+\-dd"
|
||||
.It E "double " "[\-]d.dddE+\-dd"
|
||||
.It f "double " "[\-]ddd.ddd"
|
||||
.It F "double " "[\-]ddd.ddd"
|
||||
.It g "double " "as \(aqe\(aq or \(aqf\(aq"
|
||||
.It G "double " "as \(aqE\(aq or \(aqF\(aq"
|
||||
.It a "double " "[\-]0xh.hhhp[+\-]d"
|
||||
.It A "double " "[\-]0Xh.hhhp[+\-]d"
|
||||
.It c "unsigned char " "a character"
|
||||
.It C "wint_t " "a character"
|
||||
.It s "char * " "a UTF-8 string"
|
||||
.It s "char * " "a UTF\-8 string"
|
||||
.It S "wchar_t * " "a unicode/WCS string"
|
||||
.It p "void * " "'%#lx'"
|
||||
.It p "void * " "\(aq%#lx\(aq"
|
||||
.El
|
||||
.Pp
|
||||
The 'h' and 'l' modifiers affect the size and treatment of the
|
||||
The \(aqh\(aq and \(aql\(aq modifiers affect the size and treatment of the
|
||||
argument:
|
||||
.Bl -column "Mod" "d, i " "o, u, x, X "
|
||||
.It Sy "Mod" "d, i " "o, u, x, X"
|
||||
@ -693,27 +717,27 @@ argument:
|
||||
.It "z " "size_t " "size_t"
|
||||
.It "q " "quad_t " "u_quad_t"
|
||||
.El
|
||||
.Ss "UTF-8 and Locale Strings"
|
||||
.Ss "UTF\-8 and Locale Strings"
|
||||
All strings for
|
||||
.Nm libxo
|
||||
must be UTF-8.
|
||||
must be UTF\-8.
|
||||
.Nm libxo
|
||||
will handle turning them
|
||||
into locale-based strings for display to the user.
|
||||
into locale\-based strings for display to the user.
|
||||
.Pp
|
||||
For strings, the 'h' and 'l' modifiers affect the interpretation of
|
||||
For strings, the \(aqh\(aq and \(aql\(aq 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 default \(aq%s\(aq string is a \(aqchar *\(aq
|
||||
pointer to a string encoded as UTF\-8.
|
||||
Since UTF\-8 is compatible with
|
||||
.Em ASCII
|
||||
data, a normal 7-bit
|
||||
data, a normal 7\-bit
|
||||
.Em ASCII
|
||||
string can be used.
|
||||
"%ls" expects a
|
||||
"wchar_t *" pointer to a wide-character string, encoded as 32-bit
|
||||
"wchar_t *" pointer to a wide\-character string, encoded as 32\-bit
|
||||
Unicode values.
|
||||
"%hs" expects a "char *" pointer to a multi-byte
|
||||
"%hs" expects a "char *" pointer to a multi\-byte
|
||||
string encoded with the current locale, as given by the
|
||||
.Ev LC_CTYPE ,
|
||||
.Ev LANG ,
|
||||
@ -722,22 +746,22 @@ or
|
||||
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 .
|
||||
.Em UTF\-8 .
|
||||
.Pp
|
||||
.Nm libxo
|
||||
will
|
||||
convert these arguments as needed to either UTF-8 (for XML, JSON, and
|
||||
HTML styles) or locale-based strings for display in text style.
|
||||
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("All 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,
|
||||
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)
|
||||
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,
|
||||
@ -755,7 +779,7 @@ string, and the time value is formatted into a wchar_t string.
|
||||
|
||||
xo_emit("The hat for {:name/%hs} is {:size/%s}.\\n",
|
||||
name, size_val);
|
||||
xo_emit("It was ordered on {:order-time/%ls}.\\n",
|
||||
xo_emit("It was ordered on {:order\-time/%ls}.\\n",
|
||||
when);
|
||||
}
|
||||
.Ed
|
||||
@ -766,11 +790,11 @@ 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.
|
||||
UTF\-8.
|
||||
.Pp
|
||||
UTF-8 and locale-encoded strings can use multiple bytes to encode one
|
||||
UTF\-8 and locale\-encoded strings can use multiple bytes to encode one
|
||||
column of data.
|
||||
The traditional "precision'" (aka "max-width") value
|
||||
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.
|
||||
@ -800,12 +824,12 @@ For HTML, these characters are placed in a <div> with class "text".
|
||||
"size": "extra small"
|
||||
HTML:
|
||||
<div class="text">The hat is </div>
|
||||
<div class="data" data-tag="size">extra small</div>
|
||||
<div class="data" data\-tag="size">extra small</div>
|
||||
<div class="text">.</div>
|
||||
.Ed
|
||||
.Ss "'%n' is Not Supported"
|
||||
.Ss "\(aq%n\(aq is Not Supported"
|
||||
.Nm libxo
|
||||
does not support the '%n' directive.
|
||||
does not support the \(aq%n\(aq directive.
|
||||
It is a bad idea and we
|
||||
just do not do it.
|
||||
.Ss "The Encoding Format (eformat)"
|
||||
@ -817,7 +841,7 @@ 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
|
||||
xo_emit("{P: }{Lwc:In stock}{:in-stock/%u}\\n",
|
||||
xo_emit("{P: }{Lwc:In stock}{:in\-stock/%u}\\n",
|
||||
instock);
|
||||
.Ed
|
||||
.Pp
|
||||
@ -826,16 +850,16 @@ This call will generate the following output:
|
||||
TEXT:
|
||||
In stock: 144
|
||||
XML:
|
||||
<in-stock>144</in-stock>
|
||||
<in\-stock>144</in\-stock>
|
||||
JSON:
|
||||
"in-stock": 144,
|
||||
"in\-stock": 144,
|
||||
HTML:
|
||||
<div class="line">
|
||||
<div class="padding"> </div>
|
||||
<div class="label">In stock</div>
|
||||
<div class="decoration">:</div>
|
||||
<div class="padding"> </div>
|
||||
<div class="data" data-tag="in-stock">144</div>
|
||||
<div class="data" data\-tag="in\-stock">144</div>
|
||||
</div>
|
||||
.Ed
|
||||
.Pp
|
||||
@ -846,10 +870,10 @@ or
|
||||
.Dv XOF_INFO
|
||||
data, which would expand the penultimate line to:
|
||||
.Bd -literal -offset indent
|
||||
<div class="data" data-tag="in-stock"
|
||||
data-xpath="/top/data/item/in-stock"
|
||||
data-type="number"
|
||||
data-help="Number of items in stock">144</div>
|
||||
<div class="data" data\-tag="in\-stock"
|
||||
data\-xpath="/top/data/item/in\-stock"
|
||||
data\-type="number"
|
||||
data\-help="Number of items in stock">144</div>
|
||||
.Ed
|
||||
.Sh WHAT MAKES A GOOD FIELD NAME?
|
||||
To make useful, consistent field names, follow these guidelines:
|
||||
@ -867,23 +891,23 @@ But the raw field name should use hyphens.
|
||||
.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 "data\-size", not "dsz" or "dsize".
|
||||
Use
|
||||
"interface" instead of "ifname", "if-name", "iface", "if", or "intf".
|
||||
.Ss "Use <verb>-<units>"
|
||||
Using the form <verb>-<units> or <verb>-<classifier>-<units> helps in
|
||||
"interface" instead of "ifname", "if\-name", "iface", "if", or "intf".
|
||||
.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".
|
||||
uses "sent\-packet" and another "packets\-sent" and another
|
||||
"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".
|
||||
Use "receive\-after\-window\-packets" instead of
|
||||
"received\-packets\-of\-data\-after\-window".
|
||||
.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) {
|
||||
$src2/proc\-table/proc/p[process\-id == $pid]/proc\-name) {
|
||||
...
|
||||
}
|
||||
.Ed
|
||||
@ -903,7 +927,7 @@ calls or "{e:}" fields to make the data useful.
|
||||
.Ss "Do not use an arbitrary number postfix"
|
||||
What does "errors2" mean?
|
||||
No one will know.
|
||||
"errors-after-restart" would be a better choice.
|
||||
"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
|
||||
@ -913,7 +937,7 @@ 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
|
||||
application\(aqs programmer to move between without the need to
|
||||
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.
|
||||
@ -925,12 +949,12 @@ By choosing wise names now, you are making their lives better.
|
||||
After using
|
||||
.Xr xolint 1
|
||||
to find errors in your field descriptors, use
|
||||
.Dq "xolint -V"
|
||||
.Dq "xolint \-V"
|
||||
to spell check your field names and to detect different
|
||||
names for the same data.
|
||||
.Dq dropped-short
|
||||
.Dq dropped\-short
|
||||
and
|
||||
.Dq dropped-too-short
|
||||
.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 is no difference,
|
||||
|
@ -83,12 +83,16 @@ Log (via stderr) each syslog message (via
|
||||
Ignore the {h:} modifier (TEXT, HTML)
|
||||
.It Dv no-locale
|
||||
Do not initialize the locale setting
|
||||
.It Dv no-retain
|
||||
Prevent retaining formatting information
|
||||
.It Dv no-top
|
||||
Do not emit a top set of braces (JSON)
|
||||
.It Dv not-first
|
||||
Pretend the 1st output item was not 1st (JSON)
|
||||
.It Dv pretty
|
||||
Emit pretty-printed output
|
||||
.It Dv retain
|
||||
Force retaining formatting information
|
||||
.It Dv text
|
||||
Emit TEXT output
|
||||
.If Dv underscores
|
||||
|
@ -5,7 +5,7 @@ includedir=@includedir@
|
||||
|
||||
|
||||
Name: libxo
|
||||
Version: @VERSION@
|
||||
Version: @LIBXO_VERSION@
|
||||
Description: The XML Output Library
|
||||
Libs: @LIBXO_LIBDIR@ @LIBXO_LIBS@
|
||||
Cflags: @LIBXO_INCLUDEDIR@
|
||||
Libs: -L@XO_LIBDIR@ @XO_LIBS@
|
||||
Cflags: -I@XO_INCLUDEDIR@
|
||||
|
@ -6,15 +6,15 @@
|
||||
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'
|
||||
homepage 'https://github.com/Juniper/@PACKAGE_NAME@'
|
||||
url 'https://github.com/Juniper/@PACKAGE_NAME@/releases/download/@PACKAGE_VERSION@/@PACKAGE_NAME@-@PACKAGE_VERSION@.tar.gz'
|
||||
sha1 '__SHA1__'
|
||||
|
||||
depends_on 'libtool' => :build
|
||||
|
||||
def install
|
||||
system "./configure", "--disable-dependency-tracking",
|
||||
system "./configure", "--disable-dependency-tracking", "--disable-silent-rules",
|
||||
"--prefix=#{prefix}"
|
||||
system "make install"
|
||||
system "make", "install"
|
||||
end
|
||||
end
|
||||
|
@ -22,7 +22,8 @@ test_07.c \
|
||||
test_08.c \
|
||||
test_09.c \
|
||||
test_10.c \
|
||||
test_11.c
|
||||
test_11.c \
|
||||
test_12.c
|
||||
|
||||
test_01_test_SOURCES = test_01.c
|
||||
test_02_test_SOURCES = test_02.c
|
||||
@ -35,6 +36,7 @@ test_08_test_SOURCES = test_08.c
|
||||
test_09_test_SOURCES = test_09.c
|
||||
test_10_test_SOURCES = test_10.c
|
||||
test_11_test_SOURCES = test_11.c
|
||||
test_12_test_SOURCES = test_12.c
|
||||
|
||||
# TEST_CASES := $(shell cd ${srcdir} ; echo *.c )
|
||||
|
||||
|
@ -2,6 +2,14 @@ op create: [] []
|
||||
op open_container: [top] []
|
||||
op string: [host] [my-box]
|
||||
op string: [domain] [example.com]
|
||||
op string: [host] [my-box]
|
||||
op string: [domain] [example.com]
|
||||
op string: [label] [value]
|
||||
op string: [max-chaos] [very]
|
||||
op content: [min-chaos] [42]
|
||||
op string: [some-chaos] [[42]]
|
||||
op string: [host] [my-box]
|
||||
op string: [domain] [example.com]
|
||||
op attr: [test] [value]
|
||||
op open_container: [data] []
|
||||
op open_list: [item] []
|
||||
|
File diff suppressed because one or more lines are too long
@ -1,4 +1,26 @@
|
||||
<div class="line">
|
||||
<div class="text">testing argument modifier </div>
|
||||
<div class="data" data-tag="host" data-xpath="/top/host">my-box</div>
|
||||
<div class="text">.</div>
|
||||
<div class="data" data-tag="domain" data-xpath="/top/domain">example.com</div>
|
||||
<div class="text">...</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="text">testing argument modifier with encoding to </div>
|
||||
<div class="text">.</div>
|
||||
<div class="data" data-tag="domain" data-xpath="/top/domain">example.com</div>
|
||||
<div class="text">...</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="label">Label text</div>
|
||||
<div class="text"> </div>
|
||||
<div class="data" data-tag="label" data-xpath="/top/label">value</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="data" data-tag="max-chaos" data-xpath="/top/max-chaos"> very </div>
|
||||
<div class="data" data-tag="min-chaos" data-xpath="/top/min-chaos">42</div>
|
||||
<div class="data" data-tag="some-chaos" data-xpath="/top/some-chaos">42
|
||||
</div>
|
||||
<div class="text">Connecting to </div>
|
||||
<div class="data" data-tag="host" data-xpath="/top/host">my-box</div>
|
||||
<div class="text">.</div>
|
||||
|
@ -1,4 +1,26 @@
|
||||
<div class="line">
|
||||
<div class="text">testing argument modifier </div>
|
||||
<div class="data" data-tag="host">my-box</div>
|
||||
<div class="text">.</div>
|
||||
<div class="data" data-tag="domain">example.com</div>
|
||||
<div class="text">...</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="text">testing argument modifier with encoding to </div>
|
||||
<div class="text">.</div>
|
||||
<div class="data" data-tag="domain">example.com</div>
|
||||
<div class="text">...</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="label">Label text</div>
|
||||
<div class="text"> </div>
|
||||
<div class="data" data-tag="label">value</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="data" data-tag="max-chaos"> very </div>
|
||||
<div class="data" data-tag="min-chaos">42</div>
|
||||
<div class="data" data-tag="some-chaos">42
|
||||
</div>
|
||||
<div class="text">Connecting to </div>
|
||||
<div class="data" data-tag="host">my-box</div>
|
||||
<div class="text">.</div>
|
||||
|
@ -1,2 +1,2 @@
|
||||
{"top": {"host":"my-box","domain":"example.com", "data": {"item": [{"sku":"GRO-000-415","name":"gum","sold":1412,"in-stock":54,"on-order":10}, {"sku":"HRD-000-212","name":"rope","sold":85,"in-stock":4,"on-order":2}, {"sku":"HRD-000-517","name":"ladder","sold":0,"in-stock":2,"on-order":1}, {"sku":"HRD-000-632","name":"bolt","sold":4123,"in-stock":144,"on-order":42}, {"sku":"GRO-000-2331","name":"water","sold":17,"in-stock":14,"on-order":2}]}, "data2": {"item": [{"sku":"GRO-000-415","name":"gum","sold":1412.0,"in-stock":54,"on-order":10}, {"sku":"HRD-000-212","name":"rope","sold":85.0,"in-stock":4,"on-order":2}, {"sku":"HRD-000-517","name":"ladder","sold":0,"in-stock":2,"on-order":1}, {"sku":"HRD-000-632","name":"bolt","sold":4123.0,"in-stock":144,"on-order":42}, {"sku":"GRO-000-2331","name":"water","sold":17.0,"in-stock":14,"on-order":2}]}, "data3": {"item": [{"sku":"GRO-000-533","name":"fish","sold":1321.0,"in-stock":45,"on-order":1}]}, "data4": {"item": ["gum","rope","ladder","bolt","water"]},"cost":425,"cost":455,"mode":"mode","mode_octal":"octal","links":"links","user":"user","group":"group","mode":"/some/file","mode_octal":640,"links":1,"user":"user","group":"group"}
|
||||
{"top": {"host":"my-box","domain":"example.com","host":"my-box","domain":"example.com","label":"value","max-chaos":"very","min-chaos":42,"some-chaos":"[42]","host":"my-box","domain":"example.com", "data": {"item": [{"sku":"GRO-000-415","name":"gum","sold":1412,"in-stock":54,"on-order":10}, {"sku":"HRD-000-212","name":"rope","sold":85,"in-stock":4,"on-order":2}, {"sku":"HRD-000-517","name":"ladder","sold":0,"in-stock":2,"on-order":1}, {"sku":"HRD-000-632","name":"bolt","sold":4123,"in-stock":144,"on-order":42}, {"sku":"GRO-000-2331","name":"water","sold":17,"in-stock":14,"on-order":2}]}, "data2": {"item": [{"sku":"GRO-000-415","name":"gum","sold":1412.0,"in-stock":54,"on-order":10}, {"sku":"HRD-000-212","name":"rope","sold":85.0,"in-stock":4,"on-order":2}, {"sku":"HRD-000-517","name":"ladder","sold":0,"in-stock":2,"on-order":1}, {"sku":"HRD-000-632","name":"bolt","sold":4123.0,"in-stock":144,"on-order":42}, {"sku":"GRO-000-2331","name":"water","sold":17.0,"in-stock":14,"on-order":2}]}, "data3": {"item": [{"sku":"GRO-000-533","name":"fish","sold":1321.0,"in-stock":45,"on-order":1}]}, "data4": {"item": ["gum","rope","ladder","bolt","water"]},"cost":425,"cost":455,"mode":"mode","mode_octal":"octal","links":"links","user":"user","group":"group","mode":"/some/file","mode_octal":640,"links":1,"user":"user","group":"group"}
|
||||
}
|
||||
|
@ -1,5 +1,13 @@
|
||||
{
|
||||
"top": {
|
||||
"host": "my-box",
|
||||
"domain": "example.com",
|
||||
"host": "my-box",
|
||||
"domain": "example.com",
|
||||
"label": "value",
|
||||
"max-chaos": "very",
|
||||
"min-chaos": 42,
|
||||
"some-chaos": "[42]",
|
||||
"host": "my-box",
|
||||
"domain": "example.com",
|
||||
"data": {
|
||||
|
@ -1,3 +1,7 @@
|
||||
testing argument modifier my-box.example.com...
|
||||
testing argument modifier with encoding to .example.com...
|
||||
Label text value
|
||||
very 4242
|
||||
Connecting to my-box.example.com...
|
||||
Item Total Sold In Stock On Order SKU
|
||||
gum 1412 54 10 GRO-000-415
|
||||
|
@ -1 +1 @@
|
||||
<top><host>my-box</host><domain>example.com</domain><data test="value"><item test2="value2"><sku test3="value3" key="key">GRO-000-415</sku><name key="key">gum</name><sold>1412</sold><in-stock>54</in-stock><on-order>10</on-order></item><item><sku test3="value3" key="key">HRD-000-212</sku><name key="key">rope</name><sold>85</sold><in-stock>4</in-stock><on-order>2</on-order></item><item><sku test3="value3" key="key">HRD-000-517</sku><name key="key">ladder</name><sold>0</sold><in-stock>2</in-stock><on-order>1</on-order></item><item><sku test3="value3" key="key">HRD-000-632</sku><name key="key">bolt</name><sold>4123</sold><in-stock>144</in-stock><on-order>42</on-order></item><item><sku test3="value3" key="key">GRO-000-2331</sku><name key="key">water</name><sold>17</sold><in-stock>14</in-stock><on-order>2</on-order></item></data><data2><item><sku key="key">GRO-000-415</sku><name key="key">gum</name><sold>1412.0</sold><in-stock>54</in-stock><on-order>10</on-order></item><item><sku key="key">HRD-000-212</sku><name key="key">rope</name><sold>85.0</sold><in-stock>4</in-stock><on-order>2</on-order></item><item><sku key="key">HRD-000-517</sku><name key="key">ladder</name><sold>0</sold><in-stock>2</in-stock><on-order>1</on-order></item><item><sku key="key">HRD-000-632</sku><name key="key">bolt</name><sold>4123.0</sold><in-stock>144</in-stock><on-order>42</on-order></item><item><sku key="key">GRO-000-2331</sku><name key="key">water</name><sold>17.0</sold><in-stock>14</in-stock><on-order>2</on-order></item></data2><data3><item><sku key="key">GRO-000-533</sku><name key="key">fish</name><sold>1321.0</sold><in-stock>45</in-stock><on-order>1</on-order></item></data3><data4><item test4="value4">gum</item><item test4="value4">rope</item><item test4="value4">ladder</item><item test4="value4">bolt</item><item test4="value4">water</item></data4><cost>425</cost><cost>455</cost><mode>mode</mode><mode_octal>octal</mode_octal><links>links</links><user>user</user><group>group</group><mode>/some/file</mode><mode_octal>640</mode_octal><links>1</links><user>user</user><group>group</group></top>
|
||||
<top><host>my-box</host><domain>example.com</domain><host>my-box</host><domain>example.com</domain><label>value</label><max-chaos>very</max-chaos><min-chaos>42</min-chaos><some-chaos>[42]</some-chaos><host>my-box</host><domain>example.com</domain><data test="value"><item test2="value2"><sku test3="value3" key="key">GRO-000-415</sku><name key="key">gum</name><sold>1412</sold><in-stock>54</in-stock><on-order>10</on-order></item><item><sku test3="value3" key="key">HRD-000-212</sku><name key="key">rope</name><sold>85</sold><in-stock>4</in-stock><on-order>2</on-order></item><item><sku test3="value3" key="key">HRD-000-517</sku><name key="key">ladder</name><sold>0</sold><in-stock>2</in-stock><on-order>1</on-order></item><item><sku test3="value3" key="key">HRD-000-632</sku><name key="key">bolt</name><sold>4123</sold><in-stock>144</in-stock><on-order>42</on-order></item><item><sku test3="value3" key="key">GRO-000-2331</sku><name key="key">water</name><sold>17</sold><in-stock>14</in-stock><on-order>2</on-order></item></data><data2><item><sku key="key">GRO-000-415</sku><name key="key">gum</name><sold>1412.0</sold><in-stock>54</in-stock><on-order>10</on-order></item><item><sku key="key">HRD-000-212</sku><name key="key">rope</name><sold>85.0</sold><in-stock>4</in-stock><on-order>2</on-order></item><item><sku key="key">HRD-000-517</sku><name key="key">ladder</name><sold>0</sold><in-stock>2</in-stock><on-order>1</on-order></item><item><sku key="key">HRD-000-632</sku><name key="key">bolt</name><sold>4123.0</sold><in-stock>144</in-stock><on-order>42</on-order></item><item><sku key="key">GRO-000-2331</sku><name key="key">water</name><sold>17.0</sold><in-stock>14</in-stock><on-order>2</on-order></item></data2><data3><item><sku key="key">GRO-000-533</sku><name key="key">fish</name><sold>1321.0</sold><in-stock>45</in-stock><on-order>1</on-order></item></data3><data4><item test4="value4">gum</item><item test4="value4">rope</item><item test4="value4">ladder</item><item test4="value4">bolt</item><item test4="value4">water</item></data4><cost>425</cost><cost>455</cost><mode>mode</mode><mode_octal>octal</mode_octal><links>links</links><user>user</user><group>group</group><mode>/some/file</mode><mode_octal>640</mode_octal><links>1</links><user>user</user><group>group</group></top>
|
@ -1,4 +1,12 @@
|
||||
<top>
|
||||
<host>my-box</host>
|
||||
<domain>example.com</domain>
|
||||
<host>my-box</host>
|
||||
<domain>example.com</domain>
|
||||
<label>value</label>
|
||||
<max-chaos>very</max-chaos>
|
||||
<min-chaos>42</min-chaos>
|
||||
<some-chaos>[42]</some-chaos>
|
||||
<host>my-box</host>
|
||||
<domain>example.com</domain>
|
||||
<data test="value">
|
||||
|
0
contrib/libxo/tests/core/saved/test_12.E.err
Normal file
0
contrib/libxo/tests/core/saved/test_12.E.err
Normal file
89
contrib/libxo/tests/core/saved/test_12.E.out
Normal file
89
contrib/libxo/tests/core/saved/test_12.E.out
Normal file
@ -0,0 +1,89 @@
|
||||
op create: [] []
|
||||
op open_container: [top] []
|
||||
op open_container: [data] []
|
||||
op open_list: [thing] []
|
||||
op open_instance: [thing] []
|
||||
op string: [name] [thing]
|
||||
op string: [color] [green]
|
||||
op content: [time] [2:15]
|
||||
op string: [hand] [left]
|
||||
op string: [color] [blue]
|
||||
op content: [time] [3:45]
|
||||
op close_instance: [thing] []
|
||||
op open_instance: [thing] []
|
||||
op string: [name] [thing]
|
||||
op string: [color] [green]
|
||||
op content: [time] [2:15]
|
||||
op string: [hand] [left]
|
||||
op string: [color] [blue]
|
||||
op content: [time] [3:45]
|
||||
op close_instance: [thing] []
|
||||
op open_instance: [thing] []
|
||||
op string: [name] [thing]
|
||||
op string: [color] [green]
|
||||
op content: [time] [2:15]
|
||||
op string: [hand] [left]
|
||||
op string: [color] [blue]
|
||||
op content: [time] [3:45]
|
||||
op close_instance: [thing] []
|
||||
op open_instance: [thing] []
|
||||
op string: [name] [thing]
|
||||
op string: [color] [green]
|
||||
op content: [time] [2:15]
|
||||
op string: [hand] [left]
|
||||
op string: [color] [blue]
|
||||
op content: [time] [3:45]
|
||||
op close_instance: [thing] []
|
||||
op open_instance: [thing] []
|
||||
op string: [name] [thing]
|
||||
op string: [color] [green]
|
||||
op content: [time] [2:15]
|
||||
op string: [hand] [left]
|
||||
op string: [color] [blue]
|
||||
op content: [time] [3:45]
|
||||
op close_instance: [thing] []
|
||||
op open_instance: [thing] []
|
||||
op string: [name] [thing]
|
||||
op string: [color] [green]
|
||||
op content: [time] [2:15]
|
||||
op string: [hand] [left]
|
||||
op string: [color] [blue]
|
||||
op content: [time] [3:45]
|
||||
op close_instance: [thing] []
|
||||
op open_instance: [thing] []
|
||||
op string: [name] [thing]
|
||||
op string: [color] [green]
|
||||
op content: [time] [2:15]
|
||||
op string: [hand] [left]
|
||||
op string: [color] [blue]
|
||||
op content: [time] [3:45]
|
||||
op close_instance: [thing] []
|
||||
op open_instance: [thing] []
|
||||
op string: [name] [thing]
|
||||
op string: [color] [green]
|
||||
op content: [time] [2:15]
|
||||
op string: [hand] [left]
|
||||
op string: [color] [blue]
|
||||
op content: [time] [3:45]
|
||||
op close_instance: [thing] []
|
||||
op open_instance: [thing] []
|
||||
op string: [name] [thing]
|
||||
op string: [color] [green]
|
||||
op content: [time] [2:15]
|
||||
op string: [hand] [left]
|
||||
op string: [color] [blue]
|
||||
op content: [time] [3:45]
|
||||
op close_instance: [thing] []
|
||||
op open_instance: [thing] []
|
||||
op string: [name] [thing]
|
||||
op string: [color] [green]
|
||||
op content: [time] [2:15]
|
||||
op string: [hand] [left]
|
||||
op string: [color] [blue]
|
||||
op content: [time] [3:45]
|
||||
op close_instance: [thing] []
|
||||
op close_list: [thing] []
|
||||
op close_container: [data] []
|
||||
op close_container: [top] []
|
||||
op finish: [] []
|
||||
op flush: [] []
|
0
contrib/libxo/tests/core/saved/test_12.H.err
Normal file
0
contrib/libxo/tests/core/saved/test_12.H.err
Normal file
1
contrib/libxo/tests/core/saved/test_12.H.out
Normal file
1
contrib/libxo/tests/core/saved/test_12.H.out
Normal file
@ -0,0 +1 @@
|
||||
<div class="line"><div class="text">The </div><div class="data" data-tag="name">thing</div><div class="text"> is </div><div class="data" data-tag="color">green</div><div class="text"> til </div><div class="data" data-tag="time">02:15</div></div><div class="line"><div class="text">My </div><div class="data" data-tag="hand">left</div><div class="text"> hand is </div><div class="data" data-tag="color">blue</div><div class="text"> til </div><div class="data" data-tag="time">03:45</div></div><div class="line"><div class="text">The </div><div class="data" data-tag="name">thing</div><div class="text"> is </div><div class="data" data-tag="color">green</div><div class="text"> til </div><div class="data" data-tag="time">02:15</div></div><div class="line"><div class="text">My </div><div class="data" data-tag="hand">left</div><div class="text"> hand is </div><div class="data" data-tag="color">blue</div><div class="text"> til </div><div class="data" data-tag="time">03:45</div></div><div class="line"><div class="text">The </div><div class="data" data-tag="name">thing</div><div class="text"> is </div><div class="data" data-tag="color">green</div><div class="text"> til </div><div class="data" data-tag="time">02:15</div></div><div class="line"><div class="text">My </div><div class="data" data-tag="hand">left</div><div class="text"> hand is </div><div class="data" data-tag="color">blue</div><div class="text"> til </div><div class="data" data-tag="time">03:45</div></div><div class="line"><div class="text">The </div><div class="data" data-tag="name">thing</div><div class="text"> is </div><div class="data" data-tag="color">green</div><div class="text"> til </div><div class="data" data-tag="time">02:15</div></div><div class="line"><div class="text">My </div><div class="data" data-tag="hand">left</div><div class="text"> hand is </div><div class="data" data-tag="color">blue</div><div class="text"> til </div><div class="data" data-tag="time">03:45</div></div><div class="line"><div class="text">The </div><div class="data" data-tag="name">thing</div><div class="text"> is </div><div class="data" data-tag="color">green</div><div class="text"> til </div><div class="data" data-tag="time">02:15</div></div><div class="line"><div class="text">My </div><div class="data" data-tag="hand">left</div><div class="text"> hand is </div><div class="data" data-tag="color">blue</div><div class="text"> til </div><div class="data" data-tag="time">03:45</div></div><div class="line"><div class="text">The </div><div class="data" data-tag="name">thing</div><div class="text"> is </div><div class="data" data-tag="color">green</div><div class="text"> til </div><div class="data" data-tag="time">02:15</div></div><div class="line"><div class="text">My </div><div class="data" data-tag="hand">left</div><div class="text"> hand is </div><div class="data" data-tag="color">blue</div><div class="text"> til </div><div class="data" data-tag="time">03:45</div></div><div class="line"><div class="text">The </div><div class="data" data-tag="name">thing</div><div class="text"> is </div><div class="data" data-tag="color">green</div><div class="text"> til </div><div class="data" data-tag="time">02:15</div></div><div class="line"><div class="text">My </div><div class="data" data-tag="hand">left</div><div class="text"> hand is </div><div class="data" data-tag="color">blue</div><div class="text"> til </div><div class="data" data-tag="time">03:45</div></div><div class="line"><div class="text">The </div><div class="data" data-tag="name">thing</div><div class="text"> is </div><div class="data" data-tag="color">green</div><div class="text"> til </div><div class="data" data-tag="time">02:15</div></div><div class="line"><div class="text">My </div><div class="data" data-tag="hand">left</div><div class="text"> hand is </div><div class="data" data-tag="color">blue</div><div class="text"> til </div><div class="data" data-tag="time">03:45</div></div><div class="line"><div class="text">The </div><div class="data" data-tag="name">thing</div><div class="text"> is </div><div class="data" data-tag="color">green</div><div class="text"> til </div><div class="data" data-tag="time">02:15</div></div><div class="line"><div class="text">My </div><div class="data" data-tag="hand">left</div><div class="text"> hand is </div><div class="data" data-tag="color">blue</div><div class="text"> til </div><div class="data" data-tag="time">03:45</div></div><div class="line"><div class="text">The </div><div class="data" data-tag="name">thing</div><div class="text"> is </div><div class="data" data-tag="color">green</div><div class="text"> til </div><div class="data" data-tag="time">02:15</div></div><div class="line"><div class="text">My </div><div class="data" data-tag="hand">left</div><div class="text"> hand is </div><div class="data" data-tag="color">blue</div><div class="text"> til </div><div class="data" data-tag="time">03:45</div></div>
|
0
contrib/libxo/tests/core/saved/test_12.HIPx.err
Normal file
0
contrib/libxo/tests/core/saved/test_12.HIPx.err
Normal file
160
contrib/libxo/tests/core/saved/test_12.HIPx.out
Normal file
160
contrib/libxo/tests/core/saved/test_12.HIPx.out
Normal file
@ -0,0 +1,160 @@
|
||||
<div class="line">
|
||||
<div class="text">The </div>
|
||||
<div class="data" data-tag="name" data-xpath="/top/data/thing/name">thing</div>
|
||||
<div class="text"> is </div>
|
||||
<div class="data" data-tag="color" data-xpath="/top/data/thing[name = 'thing']/color">green</div>
|
||||
<div class="text"> til </div>
|
||||
<div class="data" data-tag="time" data-xpath="/top/data/thing[name = 'thing']/time">02:15</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="text">My </div>
|
||||
<div class="data" data-tag="hand" data-xpath="/top/data/thing[name = 'thing']/hand">left</div>
|
||||
<div class="text"> hand is </div>
|
||||
<div class="data" data-tag="color" data-xpath="/top/data/thing[name = 'thing']/color">blue</div>
|
||||
<div class="text"> til </div>
|
||||
<div class="data" data-tag="time" data-xpath="/top/data/thing[name = 'thing']/time">03:45</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="text">The </div>
|
||||
<div class="data" data-tag="name" data-xpath="/top/data/thing/name">thing</div>
|
||||
<div class="text"> is </div>
|
||||
<div class="data" data-tag="color" data-xpath="/top/data/thing[name = 'thing']/color">green</div>
|
||||
<div class="text"> til </div>
|
||||
<div class="data" data-tag="time" data-xpath="/top/data/thing[name = 'thing']/time">02:15</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="text">My </div>
|
||||
<div class="data" data-tag="hand" data-xpath="/top/data/thing[name = 'thing']/hand">left</div>
|
||||
<div class="text"> hand is </div>
|
||||
<div class="data" data-tag="color" data-xpath="/top/data/thing[name = 'thing']/color">blue</div>
|
||||
<div class="text"> til </div>
|
||||
<div class="data" data-tag="time" data-xpath="/top/data/thing[name = 'thing']/time">03:45</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="text">The </div>
|
||||
<div class="data" data-tag="name" data-xpath="/top/data/thing/name">thing</div>
|
||||
<div class="text"> is </div>
|
||||
<div class="data" data-tag="color" data-xpath="/top/data/thing[name = 'thing']/color">green</div>
|
||||
<div class="text"> til </div>
|
||||
<div class="data" data-tag="time" data-xpath="/top/data/thing[name = 'thing']/time">02:15</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="text">My </div>
|
||||
<div class="data" data-tag="hand" data-xpath="/top/data/thing[name = 'thing']/hand">left</div>
|
||||
<div class="text"> hand is </div>
|
||||
<div class="data" data-tag="color" data-xpath="/top/data/thing[name = 'thing']/color">blue</div>
|
||||
<div class="text"> til </div>
|
||||
<div class="data" data-tag="time" data-xpath="/top/data/thing[name = 'thing']/time">03:45</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="text">The </div>
|
||||
<div class="data" data-tag="name" data-xpath="/top/data/thing/name">thing</div>
|
||||
<div class="text"> is </div>
|
||||
<div class="data" data-tag="color" data-xpath="/top/data/thing[name = 'thing']/color">green</div>
|
||||
<div class="text"> til </div>
|
||||
<div class="data" data-tag="time" data-xpath="/top/data/thing[name = 'thing']/time">02:15</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="text">My </div>
|
||||
<div class="data" data-tag="hand" data-xpath="/top/data/thing[name = 'thing']/hand">left</div>
|
||||
<div class="text"> hand is </div>
|
||||
<div class="data" data-tag="color" data-xpath="/top/data/thing[name = 'thing']/color">blue</div>
|
||||
<div class="text"> til </div>
|
||||
<div class="data" data-tag="time" data-xpath="/top/data/thing[name = 'thing']/time">03:45</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="text">The </div>
|
||||
<div class="data" data-tag="name" data-xpath="/top/data/thing/name">thing</div>
|
||||
<div class="text"> is </div>
|
||||
<div class="data" data-tag="color" data-xpath="/top/data/thing[name = 'thing']/color">green</div>
|
||||
<div class="text"> til </div>
|
||||
<div class="data" data-tag="time" data-xpath="/top/data/thing[name = 'thing']/time">02:15</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="text">My </div>
|
||||
<div class="data" data-tag="hand" data-xpath="/top/data/thing[name = 'thing']/hand">left</div>
|
||||
<div class="text"> hand is </div>
|
||||
<div class="data" data-tag="color" data-xpath="/top/data/thing[name = 'thing']/color">blue</div>
|
||||
<div class="text"> til </div>
|
||||
<div class="data" data-tag="time" data-xpath="/top/data/thing[name = 'thing']/time">03:45</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="text">The </div>
|
||||
<div class="data" data-tag="name" data-xpath="/top/data/thing/name">thing</div>
|
||||
<div class="text"> is </div>
|
||||
<div class="data" data-tag="color" data-xpath="/top/data/thing[name = 'thing']/color">green</div>
|
||||
<div class="text"> til </div>
|
||||
<div class="data" data-tag="time" data-xpath="/top/data/thing[name = 'thing']/time">02:15</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="text">My </div>
|
||||
<div class="data" data-tag="hand" data-xpath="/top/data/thing[name = 'thing']/hand">left</div>
|
||||
<div class="text"> hand is </div>
|
||||
<div class="data" data-tag="color" data-xpath="/top/data/thing[name = 'thing']/color">blue</div>
|
||||
<div class="text"> til </div>
|
||||
<div class="data" data-tag="time" data-xpath="/top/data/thing[name = 'thing']/time">03:45</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="text">The </div>
|
||||
<div class="data" data-tag="name" data-xpath="/top/data/thing/name">thing</div>
|
||||
<div class="text"> is </div>
|
||||
<div class="data" data-tag="color" data-xpath="/top/data/thing[name = 'thing']/color">green</div>
|
||||
<div class="text"> til </div>
|
||||
<div class="data" data-tag="time" data-xpath="/top/data/thing[name = 'thing']/time">02:15</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="text">My </div>
|
||||
<div class="data" data-tag="hand" data-xpath="/top/data/thing[name = 'thing']/hand">left</div>
|
||||
<div class="text"> hand is </div>
|
||||
<div class="data" data-tag="color" data-xpath="/top/data/thing[name = 'thing']/color">blue</div>
|
||||
<div class="text"> til </div>
|
||||
<div class="data" data-tag="time" data-xpath="/top/data/thing[name = 'thing']/time">03:45</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="text">The </div>
|
||||
<div class="data" data-tag="name" data-xpath="/top/data/thing/name">thing</div>
|
||||
<div class="text"> is </div>
|
||||
<div class="data" data-tag="color" data-xpath="/top/data/thing[name = 'thing']/color">green</div>
|
||||
<div class="text"> til </div>
|
||||
<div class="data" data-tag="time" data-xpath="/top/data/thing[name = 'thing']/time">02:15</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="text">My </div>
|
||||
<div class="data" data-tag="hand" data-xpath="/top/data/thing[name = 'thing']/hand">left</div>
|
||||
<div class="text"> hand is </div>
|
||||
<div class="data" data-tag="color" data-xpath="/top/data/thing[name = 'thing']/color">blue</div>
|
||||
<div class="text"> til </div>
|
||||
<div class="data" data-tag="time" data-xpath="/top/data/thing[name = 'thing']/time">03:45</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="text">The </div>
|
||||
<div class="data" data-tag="name" data-xpath="/top/data/thing/name">thing</div>
|
||||
<div class="text"> is </div>
|
||||
<div class="data" data-tag="color" data-xpath="/top/data/thing[name = 'thing']/color">green</div>
|
||||
<div class="text"> til </div>
|
||||
<div class="data" data-tag="time" data-xpath="/top/data/thing[name = 'thing']/time">02:15</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="text">My </div>
|
||||
<div class="data" data-tag="hand" data-xpath="/top/data/thing[name = 'thing']/hand">left</div>
|
||||
<div class="text"> hand is </div>
|
||||
<div class="data" data-tag="color" data-xpath="/top/data/thing[name = 'thing']/color">blue</div>
|
||||
<div class="text"> til </div>
|
||||
<div class="data" data-tag="time" data-xpath="/top/data/thing[name = 'thing']/time">03:45</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="text">The </div>
|
||||
<div class="data" data-tag="name" data-xpath="/top/data/thing/name">thing</div>
|
||||
<div class="text"> is </div>
|
||||
<div class="data" data-tag="color" data-xpath="/top/data/thing[name = 'thing']/color">green</div>
|
||||
<div class="text"> til </div>
|
||||
<div class="data" data-tag="time" data-xpath="/top/data/thing[name = 'thing']/time">02:15</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="text">My </div>
|
||||
<div class="data" data-tag="hand" data-xpath="/top/data/thing[name = 'thing']/hand">left</div>
|
||||
<div class="text"> hand is </div>
|
||||
<div class="data" data-tag="color" data-xpath="/top/data/thing[name = 'thing']/color">blue</div>
|
||||
<div class="text"> til </div>
|
||||
<div class="data" data-tag="time" data-xpath="/top/data/thing[name = 'thing']/time">03:45</div>
|
||||
</div>
|
0
contrib/libxo/tests/core/saved/test_12.HP.err
Normal file
0
contrib/libxo/tests/core/saved/test_12.HP.err
Normal file
160
contrib/libxo/tests/core/saved/test_12.HP.out
Normal file
160
contrib/libxo/tests/core/saved/test_12.HP.out
Normal file
@ -0,0 +1,160 @@
|
||||
<div class="line">
|
||||
<div class="text">The </div>
|
||||
<div class="data" data-tag="name">thing</div>
|
||||
<div class="text"> is </div>
|
||||
<div class="data" data-tag="color">green</div>
|
||||
<div class="text"> til </div>
|
||||
<div class="data" data-tag="time">02:15</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="text">My </div>
|
||||
<div class="data" data-tag="hand">left</div>
|
||||
<div class="text"> hand is </div>
|
||||
<div class="data" data-tag="color">blue</div>
|
||||
<div class="text"> til </div>
|
||||
<div class="data" data-tag="time">03:45</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="text">The </div>
|
||||
<div class="data" data-tag="name">thing</div>
|
||||
<div class="text"> is </div>
|
||||
<div class="data" data-tag="color">green</div>
|
||||
<div class="text"> til </div>
|
||||
<div class="data" data-tag="time">02:15</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="text">My </div>
|
||||
<div class="data" data-tag="hand">left</div>
|
||||
<div class="text"> hand is </div>
|
||||
<div class="data" data-tag="color">blue</div>
|
||||
<div class="text"> til </div>
|
||||
<div class="data" data-tag="time">03:45</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="text">The </div>
|
||||
<div class="data" data-tag="name">thing</div>
|
||||
<div class="text"> is </div>
|
||||
<div class="data" data-tag="color">green</div>
|
||||
<div class="text"> til </div>
|
||||
<div class="data" data-tag="time">02:15</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="text">My </div>
|
||||
<div class="data" data-tag="hand">left</div>
|
||||
<div class="text"> hand is </div>
|
||||
<div class="data" data-tag="color">blue</div>
|
||||
<div class="text"> til </div>
|
||||
<div class="data" data-tag="time">03:45</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="text">The </div>
|
||||
<div class="data" data-tag="name">thing</div>
|
||||
<div class="text"> is </div>
|
||||
<div class="data" data-tag="color">green</div>
|
||||
<div class="text"> til </div>
|
||||
<div class="data" data-tag="time">02:15</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="text">My </div>
|
||||
<div class="data" data-tag="hand">left</div>
|
||||
<div class="text"> hand is </div>
|
||||
<div class="data" data-tag="color">blue</div>
|
||||
<div class="text"> til </div>
|
||||
<div class="data" data-tag="time">03:45</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="text">The </div>
|
||||
<div class="data" data-tag="name">thing</div>
|
||||
<div class="text"> is </div>
|
||||
<div class="data" data-tag="color">green</div>
|
||||
<div class="text"> til </div>
|
||||
<div class="data" data-tag="time">02:15</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="text">My </div>
|
||||
<div class="data" data-tag="hand">left</div>
|
||||
<div class="text"> hand is </div>
|
||||
<div class="data" data-tag="color">blue</div>
|
||||
<div class="text"> til </div>
|
||||
<div class="data" data-tag="time">03:45</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="text">The </div>
|
||||
<div class="data" data-tag="name">thing</div>
|
||||
<div class="text"> is </div>
|
||||
<div class="data" data-tag="color">green</div>
|
||||
<div class="text"> til </div>
|
||||
<div class="data" data-tag="time">02:15</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="text">My </div>
|
||||
<div class="data" data-tag="hand">left</div>
|
||||
<div class="text"> hand is </div>
|
||||
<div class="data" data-tag="color">blue</div>
|
||||
<div class="text"> til </div>
|
||||
<div class="data" data-tag="time">03:45</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="text">The </div>
|
||||
<div class="data" data-tag="name">thing</div>
|
||||
<div class="text"> is </div>
|
||||
<div class="data" data-tag="color">green</div>
|
||||
<div class="text"> til </div>
|
||||
<div class="data" data-tag="time">02:15</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="text">My </div>
|
||||
<div class="data" data-tag="hand">left</div>
|
||||
<div class="text"> hand is </div>
|
||||
<div class="data" data-tag="color">blue</div>
|
||||
<div class="text"> til </div>
|
||||
<div class="data" data-tag="time">03:45</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="text">The </div>
|
||||
<div class="data" data-tag="name">thing</div>
|
||||
<div class="text"> is </div>
|
||||
<div class="data" data-tag="color">green</div>
|
||||
<div class="text"> til </div>
|
||||
<div class="data" data-tag="time">02:15</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="text">My </div>
|
||||
<div class="data" data-tag="hand">left</div>
|
||||
<div class="text"> hand is </div>
|
||||
<div class="data" data-tag="color">blue</div>
|
||||
<div class="text"> til </div>
|
||||
<div class="data" data-tag="time">03:45</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="text">The </div>
|
||||
<div class="data" data-tag="name">thing</div>
|
||||
<div class="text"> is </div>
|
||||
<div class="data" data-tag="color">green</div>
|
||||
<div class="text"> til </div>
|
||||
<div class="data" data-tag="time">02:15</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="text">My </div>
|
||||
<div class="data" data-tag="hand">left</div>
|
||||
<div class="text"> hand is </div>
|
||||
<div class="data" data-tag="color">blue</div>
|
||||
<div class="text"> til </div>
|
||||
<div class="data" data-tag="time">03:45</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="text">The </div>
|
||||
<div class="data" data-tag="name">thing</div>
|
||||
<div class="text"> is </div>
|
||||
<div class="data" data-tag="color">green</div>
|
||||
<div class="text"> til </div>
|
||||
<div class="data" data-tag="time">02:15</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="text">My </div>
|
||||
<div class="data" data-tag="hand">left</div>
|
||||
<div class="text"> hand is </div>
|
||||
<div class="data" data-tag="color">blue</div>
|
||||
<div class="text"> til </div>
|
||||
<div class="data" data-tag="time">03:45</div>
|
||||
</div>
|
0
contrib/libxo/tests/core/saved/test_12.J.err
Normal file
0
contrib/libxo/tests/core/saved/test_12.J.err
Normal file
2
contrib/libxo/tests/core/saved/test_12.J.out
Normal file
2
contrib/libxo/tests/core/saved/test_12.J.out
Normal file
@ -0,0 +1,2 @@
|
||||
{"top": {"data": {"thing": [{"name":"thing","color":"green","time":2:15,"hand":"left","color":"blue","time":3:45}, {"name":"thing","color":"green","time":2:15,"hand":"left","color":"blue","time":3:45}, {"name":"thing","color":"green","time":2:15,"hand":"left","color":"blue","time":3:45}, {"name":"thing","color":"green","time":2:15,"hand":"left","color":"blue","time":3:45}, {"name":"thing","color":"green","time":2:15,"hand":"left","color":"blue","time":3:45}, {"name":"thing","color":"green","time":2:15,"hand":"left","color":"blue","time":3:45}, {"name":"thing","color":"green","time":2:15,"hand":"left","color":"blue","time":3:45}, {"name":"thing","color":"green","time":2:15,"hand":"left","color":"blue","time":3:45}, {"name":"thing","color":"green","time":2:15,"hand":"left","color":"blue","time":3:45}, {"name":"thing","color":"green","time":2:15,"hand":"left","color":"blue","time":3:45}]}}
|
||||
}
|
0
contrib/libxo/tests/core/saved/test_12.JP.err
Normal file
0
contrib/libxo/tests/core/saved/test_12.JP.err
Normal file
88
contrib/libxo/tests/core/saved/test_12.JP.out
Normal file
88
contrib/libxo/tests/core/saved/test_12.JP.out
Normal file
@ -0,0 +1,88 @@
|
||||
{
|
||||
"top": {
|
||||
"data": {
|
||||
"thing": [
|
||||
{
|
||||
"name": "thing",
|
||||
"color": "green",
|
||||
"time": 2:15,
|
||||
"hand": "left",
|
||||
"color": "blue",
|
||||
"time": 3:45
|
||||
},
|
||||
{
|
||||
"name": "thing",
|
||||
"color": "green",
|
||||
"time": 2:15,
|
||||
"hand": "left",
|
||||
"color": "blue",
|
||||
"time": 3:45
|
||||
},
|
||||
{
|
||||
"name": "thing",
|
||||
"color": "green",
|
||||
"time": 2:15,
|
||||
"hand": "left",
|
||||
"color": "blue",
|
||||
"time": 3:45
|
||||
},
|
||||
{
|
||||
"name": "thing",
|
||||
"color": "green",
|
||||
"time": 2:15,
|
||||
"hand": "left",
|
||||
"color": "blue",
|
||||
"time": 3:45
|
||||
},
|
||||
{
|
||||
"name": "thing",
|
||||
"color": "green",
|
||||
"time": 2:15,
|
||||
"hand": "left",
|
||||
"color": "blue",
|
||||
"time": 3:45
|
||||
},
|
||||
{
|
||||
"name": "thing",
|
||||
"color": "green",
|
||||
"time": 2:15,
|
||||
"hand": "left",
|
||||
"color": "blue",
|
||||
"time": 3:45
|
||||
},
|
||||
{
|
||||
"name": "thing",
|
||||
"color": "green",
|
||||
"time": 2:15,
|
||||
"hand": "left",
|
||||
"color": "blue",
|
||||
"time": 3:45
|
||||
},
|
||||
{
|
||||
"name": "thing",
|
||||
"color": "green",
|
||||
"time": 2:15,
|
||||
"hand": "left",
|
||||
"color": "blue",
|
||||
"time": 3:45
|
||||
},
|
||||
{
|
||||
"name": "thing",
|
||||
"color": "green",
|
||||
"time": 2:15,
|
||||
"hand": "left",
|
||||
"color": "blue",
|
||||
"time": 3:45
|
||||
},
|
||||
{
|
||||
"name": "thing",
|
||||
"color": "green",
|
||||
"time": 2:15,
|
||||
"hand": "left",
|
||||
"color": "blue",
|
||||
"time": 3:45
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
0
contrib/libxo/tests/core/saved/test_12.T.err
Normal file
0
contrib/libxo/tests/core/saved/test_12.T.err
Normal file
20
contrib/libxo/tests/core/saved/test_12.T.out
Normal file
20
contrib/libxo/tests/core/saved/test_12.T.out
Normal file
@ -0,0 +1,20 @@
|
||||
The thing is green til 02:15
|
||||
My left hand is blue til 03:45
|
||||
The thing is green til 02:15
|
||||
My left hand is blue til 03:45
|
||||
The thing is green til 02:15
|
||||
My left hand is blue til 03:45
|
||||
The thing is green til 02:15
|
||||
My left hand is blue til 03:45
|
||||
The thing is green til 02:15
|
||||
My left hand is blue til 03:45
|
||||
The thing is green til 02:15
|
||||
My left hand is blue til 03:45
|
||||
The thing is green til 02:15
|
||||
My left hand is blue til 03:45
|
||||
The thing is green til 02:15
|
||||
My left hand is blue til 03:45
|
||||
The thing is green til 02:15
|
||||
My left hand is blue til 03:45
|
||||
The thing is green til 02:15
|
||||
My left hand is blue til 03:45
|
0
contrib/libxo/tests/core/saved/test_12.X.err
Normal file
0
contrib/libxo/tests/core/saved/test_12.X.err
Normal file
1
contrib/libxo/tests/core/saved/test_12.X.out
Normal file
1
contrib/libxo/tests/core/saved/test_12.X.out
Normal file
@ -0,0 +1 @@
|
||||
<top><data><thing><name>thing</name><color>green</color><time>2:15</time><hand>left</hand><color>blue</color><time>3:45</time></thing><thing><name>thing</name><color>green</color><time>2:15</time><hand>left</hand><color>blue</color><time>3:45</time></thing><thing><name>thing</name><color>green</color><time>2:15</time><hand>left</hand><color>blue</color><time>3:45</time></thing><thing><name>thing</name><color>green</color><time>2:15</time><hand>left</hand><color>blue</color><time>3:45</time></thing><thing><name>thing</name><color>green</color><time>2:15</time><hand>left</hand><color>blue</color><time>3:45</time></thing><thing><name>thing</name><color>green</color><time>2:15</time><hand>left</hand><color>blue</color><time>3:45</time></thing><thing><name>thing</name><color>green</color><time>2:15</time><hand>left</hand><color>blue</color><time>3:45</time></thing><thing><name>thing</name><color>green</color><time>2:15</time><hand>left</hand><color>blue</color><time>3:45</time></thing><thing><name>thing</name><color>green</color><time>2:15</time><hand>left</hand><color>blue</color><time>3:45</time></thing><thing><name>thing</name><color>green</color><time>2:15</time><hand>left</hand><color>blue</color><time>3:45</time></thing></data></top>
|
0
contrib/libxo/tests/core/saved/test_12.XP.err
Normal file
0
contrib/libxo/tests/core/saved/test_12.XP.err
Normal file
84
contrib/libxo/tests/core/saved/test_12.XP.out
Normal file
84
contrib/libxo/tests/core/saved/test_12.XP.out
Normal file
@ -0,0 +1,84 @@
|
||||
<top>
|
||||
<data>
|
||||
<thing>
|
||||
<name>thing</name>
|
||||
<color>green</color>
|
||||
<time>2:15</time>
|
||||
<hand>left</hand>
|
||||
<color>blue</color>
|
||||
<time>3:45</time>
|
||||
</thing>
|
||||
<thing>
|
||||
<name>thing</name>
|
||||
<color>green</color>
|
||||
<time>2:15</time>
|
||||
<hand>left</hand>
|
||||
<color>blue</color>
|
||||
<time>3:45</time>
|
||||
</thing>
|
||||
<thing>
|
||||
<name>thing</name>
|
||||
<color>green</color>
|
||||
<time>2:15</time>
|
||||
<hand>left</hand>
|
||||
<color>blue</color>
|
||||
<time>3:45</time>
|
||||
</thing>
|
||||
<thing>
|
||||
<name>thing</name>
|
||||
<color>green</color>
|
||||
<time>2:15</time>
|
||||
<hand>left</hand>
|
||||
<color>blue</color>
|
||||
<time>3:45</time>
|
||||
</thing>
|
||||
<thing>
|
||||
<name>thing</name>
|
||||
<color>green</color>
|
||||
<time>2:15</time>
|
||||
<hand>left</hand>
|
||||
<color>blue</color>
|
||||
<time>3:45</time>
|
||||
</thing>
|
||||
<thing>
|
||||
<name>thing</name>
|
||||
<color>green</color>
|
||||
<time>2:15</time>
|
||||
<hand>left</hand>
|
||||
<color>blue</color>
|
||||
<time>3:45</time>
|
||||
</thing>
|
||||
<thing>
|
||||
<name>thing</name>
|
||||
<color>green</color>
|
||||
<time>2:15</time>
|
||||
<hand>left</hand>
|
||||
<color>blue</color>
|
||||
<time>3:45</time>
|
||||
</thing>
|
||||
<thing>
|
||||
<name>thing</name>
|
||||
<color>green</color>
|
||||
<time>2:15</time>
|
||||
<hand>left</hand>
|
||||
<color>blue</color>
|
||||
<time>3:45</time>
|
||||
</thing>
|
||||
<thing>
|
||||
<name>thing</name>
|
||||
<color>green</color>
|
||||
<time>2:15</time>
|
||||
<hand>left</hand>
|
||||
<color>blue</color>
|
||||
<time>3:45</time>
|
||||
</thing>
|
||||
<thing>
|
||||
<name>thing</name>
|
||||
<color>green</color>
|
||||
<time>2:15</time>
|
||||
<hand>left</hand>
|
||||
<color>blue</color>
|
||||
<time>3:45</time>
|
||||
</thing>
|
||||
</data>
|
||||
</top>
|
@ -79,6 +79,18 @@ main (int argc, char **argv)
|
||||
|
||||
xo_open_container_h(NULL, "top");
|
||||
|
||||
xo_emit("testing argument modifier {a:}.{a:}...\n",
|
||||
"host", "my-box", "domain", "example.com");
|
||||
|
||||
xo_emit("testing argument modifier with encoding to {ea:}.{a:}...\n",
|
||||
"host", "my-box", "domain", "example.com");
|
||||
|
||||
xo_emit("{La:} {a:}\n", "Label text", "label", "value");
|
||||
|
||||
xo_emit_field("Vt", "max-chaos", NULL, NULL, " very ");
|
||||
xo_emit_field("V", "min-chaos", "%d", NULL, 42);
|
||||
xo_emit_field("V", "some-chaos", "%d\n", "[%d]", 42);
|
||||
|
||||
xo_emit("Connecting to {:host}.{:domain}...\n", "my-box", "example.com");
|
||||
|
||||
xo_attr("test", "value");
|
||||
|
@ -42,6 +42,7 @@ main (int argc, char **argv)
|
||||
}
|
||||
|
||||
xo_set_flags(NULL, XOF_UNITS); /* Always test w/ this */
|
||||
xo_set_file(stdout);
|
||||
|
||||
xo_open_container_h(NULL, "top");
|
||||
|
||||
|
76
contrib/libxo/tests/core/test_12.c
Normal file
76
contrib/libxo/tests/core/test_12.c
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Juniper Networks, Inc.
|
||||
* All rights reserved.
|
||||
* This SOFTWARE is licensed under the LICENSE provided in the
|
||||
* ../Copyright file. By downloading, installing, copying, or otherwise
|
||||
* using the SOFTWARE, you agree to be bound by the terms of that
|
||||
* LICENSE.
|
||||
* Phil Shafer, July 2014
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "xo_config.h"
|
||||
#include "xo.h"
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
int i, count = 10;
|
||||
int mon = 0;
|
||||
xo_emit_flags_t flags = XOEF_RETAIN;
|
||||
|
||||
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], "no-retain") == 0)
|
||||
flags &= ~XOEF_RETAIN;
|
||||
else if (strcmp(argv[argc], "big") == 0) {
|
||||
if (argv[argc + 1])
|
||||
count = atoi(argv[++argc]);
|
||||
}
|
||||
}
|
||||
|
||||
xo_set_flags(NULL, XOF_UNITS); /* Always test w/ this */
|
||||
xo_set_file(stdout);
|
||||
|
||||
xo_open_container("top");
|
||||
xo_open_container("data");
|
||||
|
||||
const char *fmt1 = "The {C:fg-red}{k:name}{C:reset} is "
|
||||
"{C:/fg-%s}{:color}{C:reset} til {:time/%02d:%02d}\n";
|
||||
const char *fmt2 = "My {C:fg-red}{:hand}{C:reset} hand is "
|
||||
"{C:/fg-%s}{:color}{C:reset} til {:time/%02d:%02d}\n";
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
xo_open_instance("thing");
|
||||
xo_emit_f(flags, fmt1, "thing", "green", "green", 2, 15);
|
||||
xo_emit_f(flags, fmt2, "left", "blue", "blue", 3, 45);
|
||||
}
|
||||
|
||||
xo_close_container("data");
|
||||
xo_close_container_h(NULL, "top");
|
||||
|
||||
xo_finish();
|
||||
|
||||
return 0;
|
||||
}
|
@ -26,7 +26,7 @@ int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
static char domainname[] = "gt_01";
|
||||
char path[MAXPATHLEN];
|
||||
static char path[MAXPATHLEN];
|
||||
const char *tzone = "EST";
|
||||
const char *lang = "pig_latin";
|
||||
|
||||
|
@ -3,10 +3,10 @@
|
||||
.Fx
|
||||
uses
|
||||
.Nm libxo
|
||||
version 0.4.7.
|
||||
version 0.6.1.
|
||||
Complete documentation can be found on github:
|
||||
.Bd -literal -offset indent
|
||||
http://juniper.github.io/libxo/0.4.7/libxo\-manual.html
|
||||
http://juniper.github.io/libxo/0.6.1/libxo\-manual.html
|
||||
.Ed
|
||||
.Pp
|
||||
.Nm libxo
|
||||
|
@ -88,6 +88,9 @@
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#define HAVE_MEMORY_H 1
|
||||
|
||||
/* Define to 1 if you have the <monitor.h> header file. */
|
||||
/* #undef HAVE_MONITOR_H */
|
||||
|
||||
/* Support printflike */
|
||||
/* #undef HAVE_PRINTFLIKE */
|
||||
|
||||
@ -180,16 +183,16 @@
|
||||
/* #undef LIBXO_TEXT_ONLY */
|
||||
|
||||
/* Version number as dotted value */
|
||||
#define LIBXO_VERSION "0.4.7"
|
||||
#define LIBXO_VERSION "0.6.1"
|
||||
|
||||
/* Version number extra information */
|
||||
#define LIBXO_VERSION_EXTRA ""
|
||||
|
||||
/* Version number as a number */
|
||||
#define LIBXO_VERSION_NUMBER 4007
|
||||
#define LIBXO_VERSION_NUMBER 6001
|
||||
|
||||
/* Version number as string */
|
||||
#define LIBXO_VERSION_STRING "4007"
|
||||
#define LIBXO_VERSION_STRING "6001"
|
||||
|
||||
/* Enable local wcwidth implementation */
|
||||
#define LIBXO_WCWIDTH 1
|
||||
@ -207,7 +210,7 @@
|
||||
#define PACKAGE_NAME "libxo"
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING "libxo 0.4.7"
|
||||
#define PACKAGE_STRING "libxo 0.6.1"
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME "libxo"
|
||||
@ -216,7 +219,7 @@
|
||||
#define PACKAGE_URL ""
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION "0.4.7"
|
||||
#define PACKAGE_VERSION "0.6.1"
|
||||
|
||||
/* If using the C implementation of alloca, define if you know the
|
||||
direction of stack growth for your system; otherwise it will be
|
||||
@ -230,7 +233,10 @@
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "0.4.7"
|
||||
#define VERSION "0.6.1"
|
||||
|
||||
/* Retain hash bucket size */
|
||||
/* #undef XO_RETAIN_SIZE */
|
||||
|
||||
/* 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. */
|
||||
|
Loading…
Reference in New Issue
Block a user