diff options
author | marcel <marcel@FreeBSD.org> | 2015-01-19 02:22:03 +0000 |
---|---|---|
committer | marcel <marcel@FreeBSD.org> | 2015-01-19 02:22:03 +0000 |
commit | ea59bea59330a848548ce834189e97959e8ebae4 (patch) | |
tree | 8db7c468a655beb61f455f2901342b8b7884e50d | |
parent | cb3a27ad28c1f0dde8ed5051245175152b16ce26 (diff) | |
download | FreeBSD-src-ea59bea59330a848548ce834189e97959e8ebae4.zip FreeBSD-src-ea59bea59330a848548ce834189e97959e8ebae4.tar.gz |
Upgrade libxo to 0.2.0.
Obtained from: https://github.com/Juniper/libxo
Requested by: Phil Shafer <phil@juniper.net>
Revisions 276253 & 276273 were incorporated into 0.2.0.
Revision 276260 has been merged-in.
83 files changed, 4081 insertions, 714 deletions
diff --git a/contrib/libxo/Makefile.am b/contrib/libxo/Makefile.am index f1fc999..4ff2aad 100644 --- a/contrib/libxo/Makefile.am +++ b/contrib/libxo/Makefile.am @@ -35,6 +35,7 @@ docs: DIST_FILES_DIR = ~/Dropbox/dist-files/ GH_PAGES_DIR = gh-pages/ +GH_PAGES_DIR_VER = gh-pages/${PACKAGE_VERSION} PACKAGE_FILE = ${PACKAGE_TARNAME}-${PACKAGE_VERSION}.tar.gz upload: dist upload-docs @@ -45,10 +46,14 @@ upload-docs: docs @echo "Uploading libxo-manual.html ... " @-[ -d ${GH_PAGES_DIR} ] \ && echo "Updating manual on gh-pages ..." \ + && mkdir -p ${GH_PAGES_DIR_VER} \ && cp doc/libxo-manual.html ${GH_PAGES_DIR} \ + && cp doc/libxo-manual.html ${GH_PAGES_DIR_VER} \ && (cd ${GH_PAGES_DIR} \ + && git add ${PACKAGE_VERSION} \ + && git add libxo-manual.html \ && git commit -m 'new docs' \ - libxo-manual.html \ + libxo-manual.html ${PACKAGE_VERSION} \ && git push origin gh-pages ) ; true pkgconfigdir=$(libdir)/pkgconfig @@ -66,7 +71,7 @@ UPDATE_PACKAGE_FILE = \ -e "s;__SHA256__;SHA256 (textproc/${PACKAGE_FILE}) = $$SHA256;" \ -e "s;__SIZE__;SIZE (textproc/${PACKAGE_FILE}) = $$SIZE;" -GH_PACKAGING_DIR = packaging/${PACKAGE_VERSION} +GH_PACKAGING_DIR = ${PACKAGE_VERSION}/packaging GH_PAGES_PACKAGE_DIR = ${GH_PAGES_DIR}/${GH_PACKAGING_DIR} packages: @@ -75,7 +80,6 @@ packages: && SHA1="`openssl sha1 ${PACKAGE_FILE} | awk '{print $$2}'`" \ && SHA256="`openssl sha256 ${PACKAGE_FILE} | awk '{print $$2}'`" \ && SIZE="`ls -l ${PACKAGE_FILE} | awk '{print $$5}'`" \ - && mkdir -p ${GH_PAGES_PACKAGE_DIR}/freebsd \ && echo "... ${GH_PAGES_PACKAGE_DIR}/${PACKAGE_NAME}.rb ..." \ && sed ${UPDATE_PACKAGE_FILE} \ packaging/${PACKAGE_NAME}.rb.base \ @@ -83,20 +87,10 @@ packages: && echo "... ${GH_PAGES_PACKAGE_DIR}/${PACKAGE_NAME}.spec ..." \ && cp packaging/${PACKAGE_NAME}.spec \ ${GH_PAGES_PACKAGE_DIR}/${PACKAGE_NAME}.spec \ - && echo "... ${GH_PAGES_PACKAGE_DIR}/freebsd ..." \ - && sed ${UPDATE_PACKAGE_FILE} \ - ${srcdir}/packaging/freebsd/distinfo.base \ - > ${GH_PAGES_PACKAGE_DIR}/freebsd/distinfo \ - && cp ${srcdir}/packaging/freebsd/pkg-descr \ - ${GH_PAGES_PACKAGE_DIR}/freebsd/pkg-descr \ - && cp ${srcdir}/packaging/freebsd/pkg-plist \ - ${GH_PAGES_PACKAGE_DIR}/freebsd/pkg-plist \ - && cp ${srcdir}/packaging/freebsd/pkg-plist \ - ${GH_PAGES_PACKAGE_DIR}/freebsd/pkg-plist \ - && cp packaging/freebsd/port-Makefile \ - ${GH_PAGES_PACKAGE_DIR}/freebsd/Makefile \ && (cd ${GH_PAGES_DIR} \ && git add ${GH_PACKAGING_DIR} \ + && git add ${GH_PACKAGING_DIR}/libxo.rb \ + ${GH_PACKAGING_DIR}/libxo.spec \ && git commit -m 'new packaging data' \ ${GH_PACKAGING_DIR} \ && git push origin gh-pages ) ; true diff --git a/contrib/libxo/bin/Zaliases b/contrib/libxo/bin/Zaliases index a24d33e..b8fb5db 100644 --- a/contrib/libxo/bin/Zaliases +++ b/contrib/libxo/bin/Zaliases @@ -1,5 +1,5 @@ set top_src=`pwd` -alias Zautoreconf "(cd $top_src ; autoreconf --install)" +alias Zautoreconf "(cd $top_src ; autoreconf)" set opts=' \ --with-libslax-prefix=/Users/phil/work/root \ diff --git a/contrib/libxo/configure.ac b/contrib/libxo/configure.ac index 904af12..b2553b8 100644 --- a/contrib/libxo/configure.ac +++ b/contrib/libxo/configure.ac @@ -12,7 +12,7 @@ # AC_PREREQ(2.2) -AC_INIT([libxo], [0.1.6], [phil@juniper.net]) +AC_INIT([libxo], [0.2.0], [phil@juniper.net]) AM_INIT_AUTOMAKE([-Wall -Werror foreign -Wno-portability]) # Support silent build rules. Requires at least automake-1.11. @@ -57,8 +57,10 @@ AC_CHECK_FUNCS([getpass]) AC_CHECK_FUNCS([sysctlbyname]) AC_CHECK_FUNCS([flock]) AC_CHECK_FUNCS([asprintf]) +AC_CHECK_FUNCS([__flbf]) AC_CHECK_HEADERS([dlfcn.h]) +AC_CHECK_HEADERS([stdio_ext.h]) AC_CHECK_HEADERS([tzfile.h]) AC_CHECK_HEADERS([stdtime/tzfile.h]) AC_CHECK_FUNCS([dlfunc]) @@ -164,7 +166,6 @@ AC_ARG_ENABLE([libxo-options], AC_MSG_RESULT([$LIBXO_OPTS]) AM_CONDITIONAL([NO_LIBXO_OPTIONS], [test "$LIBXO_OPTS" != "yes"]) - case $host_os in darwin*) LIBTOOL=glibtool @@ -238,6 +239,7 @@ AC_CONFIG_FILES([ tests/core/Makefile tests/xo/Makefile packaging/libxo.spec + packaging/libxo.rb.base ]) AC_OUTPUT diff --git a/contrib/libxo/doc/libxo.txt b/contrib/libxo/doc/libxo.txt index 5148de0..31aec53 100644 --- a/contrib/libxo/doc/libxo.txt +++ b/contrib/libxo/doc/libxo.txt @@ -12,14 +12,15 @@ libxo - A Library for Generating Text, XML, JSON, and HTML Output -You live in the present, but you want to live in the future. You'd -love a flying car, but need to get to work today. You want to support -features like XML, JSON, and HTML rendering to allow integration with -NETCONF, REST, and web browsers, but you need to make text output for -command line users. And you don't want multiple code paths that can't -help but get out of sync. None of this "if (xml) {... } else {...}" -logic. And ifdefs are right out. But you'd really, really like all -the fancy features that modern encoding formats can provide. +You want to prepare for the future, but you need to live in the +present. You'd love a flying car, but need to get to work today. You +want to support features like XML, JSON, and HTML rendering to allow +integration with NETCONF, REST, and web browsers, but you need to make +text output for command line users. And you don't want multiple code +paths that can't help but get out of sync. None of this "if (xml) +{... } else {...}" logic. And ifdefs are right out. But you'd +really, really like all the fancy features that modern encoding +formats can provide. libxo can help. The libxo library allows an application to generate text, XML, JSON, and HTML output using a common set of function calls. The application @@ -83,31 +84,37 @@ The latest release of libxo is available at: https://github.com/Juniper/libxo/releases -We are following the branching scheme from -^http://nvie.com/posts/a-successful-git-branching-model/^ -which means we will do development under the "develop" branch, and -release from the master. To clone a developer tree, run the following +We are following the branching scheme from +^http://nvie.com/posts/a-successful-git-branching-model/^ which means +we will do development under the "develop" branch, and release from +the "master" branch. To clone a developer tree, run the following command: git clone https://github.com/Juniper/libxo.git -b develop -We're using semantic release numbering. +We're using semantic release numbering, as defined in +^http://semver.org/spec/v2.0.0.html^. + +libxo is open source, distributed under the BSD license. It +is shipped as part of FreeBSD 11.0. * Overview Most unix commands emit text output aimed at humans. It is designed -to be parsed and understood by a user. Humans are gifted at extracted -details and pattern matching. Often programmers need to extract -information from this human-oriented output. Programmers use tools -like grep, awk, and regular expressions to ferret out the pieces of -information they need. Such solutions are fragile and require -updates when output contents change or evolve, requiring testing and -validation. - -Modern tool developers favors encoding schemes like XML and JSON, +to be parsed and understood by a user. Humans are gifted at +extracting details and pattern matching in such output. Often +programmers need to extract information from this human-oriented +output. Programmers use tools like grep, awk, and regular expressions +to ferret out the pieces of information they need. Such solutions are +fragile and require maintenance when output contents change or evolve, +along with testing and validation. + +Modern tool developers favor encoding schemes like XML and JSON, which allow trivial parsing and extraction of data. Such formats are simple, well understood, hierarchical, easily parsed, and often -integrate easier with common tools and environments. +integrate easier with common tools and environments. Changes to +content can be done in ways that do not break existing users of the +data, which can reduce maintenance costs and increase feature velocity. In addition, modern reality means that more output ends up in web browsers than in terminals, making HTML output valuable. @@ -278,7 +285,7 @@ content. The roles are listed below; only one role is permitted: |---+--------------+-------------------------------------------------| | M | Name | Description | |---+--------------+-------------------------------------------------| -| D | decoration | Field is non-text (e.g. colon, comma) | +| D | decoration | Field is non-text (e.g., colon, comma) | | E | error | Field is an error message | | L | label | Field is text that prefixes a value | | N | note | Field is text that follows a value | @@ -321,7 +328,7 @@ the field descriptor, or a printf-style format descriptor can be used, if preceded by a slash ("/"): xo_emit("{P: }{Lwc:Cost}{:cost/%u}\n", cost); - xo_emit("{P:/30s}{Lwc:Cost}{:cost/%u}\n", "", cost); + xo_emit("{P:/%30s}{Lwc:Cost}{:cost/%u}\n", "", cost); **** The Title Role ({T:}) @@ -333,6 +340,16 @@ if preceded by a slash ("/"): xo_emit("{T:Interface Statistics}\n"); xo_emit("{T:/%20.20s}{T:/%6.6s}\n", "Item Name", "Cost"); +Title fields have an extra convenience feature; if both content and +format are specified, instead of looking to the argument list for a +value, the content is used, allowing a mixture of format and content +within the field descriptor: + + xo_emit("{T:Name/%20s}{T:Count/%6s}\n"); + +Since the incoming argument is a string, the format must be "%s" or +something suitable. + **** The Units Role ({U:}) Units are the dimension by which values are measured, such as degrees, @@ -412,6 +429,7 @@ content emitted for some output styles: | d | display | Only emit field for display styles (text/HTML) | | e | encoding | Only emit for encoding styles (XML/JSON) | | k | key | Field is a key, suitable for XPath predicates | +| l | leaf-list | Field is a leaf-list | n | no-quotes | Do not quote the field when using JSON style | | q | quotes | Quote the field when using JSON style | | w | white space | A blank (" ") is appended after the label | @@ -433,7 +451,7 @@ The colon modifier appends a single colon to the data value: Name:phil The colon modifier is only used for the TEXT and HTML output -styles. It is commonly combined with the space modifier ('{w:'). +styles. It is commonly combined with the space modifier ('{w:}'). It is purely a convenience feature. **** The Display Modifier ({d:}) @@ -485,6 +503,24 @@ Currently the key modifier is only used when generating XPath value for the HTML output style when XOF_XPATH is set, but other uses are likely in the near future. +**** The Leaf-List Modifier ({l:}) + +The leaf-list modifier is used to distinguish lists where each +instance consists of only a single value. In XML, these are +rendered as single elements, where JSON renders them as arrays. + + EXAMPLE: + for (i = 0; i < num_users; i++) { + xo_emit("Member {l:user}\n", user[i].u_name); + } + XML: + <user>phil</user> + <user>pallavi</user> + JSON: + "user": [ "phil", "pallavi" ] + +The name of the field must match the name of the leaf list. + **** The No-Quotes Modifier ({n:}) The no-quotes modifier (and its twin, the 'quotes' modifier) affect @@ -522,7 +558,7 @@ The white space modifier appends a single space to the data value: Name phil The white space modifier is only used for the TEXT and HTML output -styles. It is commonly combined with the colon modifier ('{c:'). +styles. It is commonly combined with the colon modifier ('{c:}'). It is purely a convenience feature. Note that the sense of the 'w' modifier is reversed for the units role @@ -530,14 +566,15 @@ Note that the sense of the 'w' modifier is reversed for the units role *** Field Formatting -The field format is similar to the format string for printf(3). It's -used varies based on the role of the field, but generally is used to +The field format is similar to the format string for printf(3). Its +use varies based on the role of the field, but generally is used to format the field's contents. -If not provided, the format string defaults to "%s". +If the format string is not provided for a value field, it defaults to +"%s". Note a field definition can contain zero or more printf-style -'directives', which are sequences that start with a '%' and end with a +'directives', which are sequences that start with a '%' and end with one of following characters: "diouxXDOUeEfFgGaAcCsSp". Each directive is matched by one of more arguments to the xo_emit function. @@ -557,7 +594,7 @@ argument. If the width in columns of the output value is less that the minumum width, the value will be padded to reach the minimum. - a period followed by one or more digits indicating the maximum number of bytes which will be examined for a string argument, or the maximum -width for a non-string argument. When handling ASCII strings this is +width for a non-string argument. When handling ASCII strings this functions as the field width but for multi-byte characters, a single character may be composed of multiple bytes. xo_emit will never dereference memory beyond the given number of bytes. @@ -630,8 +667,8 @@ ASCII data, a normal 7-bit ASCII string can be used. '%ls' expects a Unicode values. '%hs' expects a 'char *' pointer to a multi-byte string encoded with the current locale, as given by the LC_CTYPE, LANG, or LC_ALL environment varibles. The first of this list of -variables is used and if none of the variables, the locale defaults to -"UTF-8". +variables is used and if none of the variables are set, the locale +defaults to "UTF-8". For example, a function is passed a locale-base name, a hat size, and a time value. The hat size is formatted in a UTF-8 (ASCII) @@ -676,10 +713,10 @@ columns. *** Characters Outside of Field Definitions -Characters in the format string are not part of a field definition are -copied to the output for the TEXT style, and are ignored for the JSON -and XML styles. For HTML, these characters are placed in a <div> with -class "text". +Characters in the format string that are not part of a field +definition are copied to the output for the TEXT style, and are +ignored for the JSON and XML styles. For HTML, these characters are +placed in a <div> with class "text". EXAMPLE: xo_emit("The hat is {:size/%s}.\n", size_val); @@ -854,7 +891,7 @@ container, a warning will be generated. *** Lists and Instances A list is set of one or more instances that appear under the same -parent. The instances contains details about a specific object. One +parent. The instances contain details about a specific object. One can think of instances as objects or records. A call is needed to open and close the list, while a distinct call is needed to open and close each instance of the list: @@ -874,8 +911,8 @@ generation of XML and JSON data. *** DTRT Mode -Some user may find tracking the names of open containers, lists, and -instances inconvenient. libxo offers "Do The Right Thing" mode, where +Some users may find tracking the names of open containers, lists, and +instances inconvenient. libxo offers a "Do The Right Thing" mode, where libxo will track the names of open containers, lists, and instances so the close function can be called without a name. To enable DTRT mode, turn on the XOF_DTRT flag prior to making any other libxo output. @@ -889,10 +926,42 @@ will close the open container, list, or instance: ... xo_close_container_d(); +This also works for lists and instances: + + xo_open_list("item"); + for (...) { + xo_open_instance("item"); + xo_emit(...); + xo_close_instance_d(); + } + xo_close_list_d(); + Note that the XOF_WARN flag will also cause libxo to track open -containers, lists, and instances. A warning is generated with the +containers, lists, and instances. A warning is generated when the name given to the close function and the name recorded do not match. +*** Markers + +Markers are used to protect and restore the state of open constructs. +While a marker is open, no other open constructs can be closed. When +a marker is closed, all constructs open since the marker was opened +will be closed. + +Markers use names which are not user-visible, allowing the caller to +choose appropriate internal names. + +In this example, the code whiffles through a list of fish, calling a +function to emit details about each fish. The marker "fish-guts" is +used to ensure that any constructs opened by the function are closed +properly. + + for (i = 0; fish[i]; i++) { + xo_open_instance("fish"); + xo_open_marker("fish-guts"); + dump_fish_details(i); + xo_close_marker("fish-guts"); + } + ** Handles libxo uses "handles" to control its rendering functionality. The @@ -952,7 +1021,7 @@ be passed NULL to access the default handle. For the typical command that is generating output on standard output, there is no need to create an explicit handle, but they are available -when needed, e.g. for daemons that generate multiple streams of +when needed, e.g., for daemons that generate multiple streams of output. *** xo_create @@ -972,7 +1041,7 @@ See also ^styles^ and ^flags^. By default, libxo writes output to standard output. A convenience function is provided for situations when output should be written to -different file: +a different file: xo_handle_t *xo_create_to_file (FILE *fp, unsigned style, unsigned flags); @@ -987,10 +1056,13 @@ which can tailor how libxo writes data. An opaque argument is recorded and passed back to the write function, allowing the function to acquire context information. The 'close' function can release this opaque data and any other resources as needed. +The flush function can flush buffered data associated with the opaque +object. void xo_set_writer (xo_handle_t *xop, void *opaque, xo_write_func_t write_func, xo_close_func_t close_func); + xo_flush_func_t flush_func); *** xo_set_style @@ -1068,7 +1140,7 @@ XML, JSON, and HTML output. Text output is not affected. The XOF_WARN flag requests that warnings will trigger diagnostic output (on standard error) when the library notices errors during -operations, or with arguments to functions. Without warning enabled, +operations, or with arguments to functions. Without warnings enabled, such conditions are ignored. Warnings allow developers to debug their interaction with libxo. @@ -1178,6 +1250,13 @@ parameter passed to xo_attr_hv(). XML: <login-time seconds="1408336270">00:14</login-time> +xo_attr is placed on the next container, instance, leaf, or leaf list +that is emitted. + +Since attributes are only emitted in XML, their use should be limited +to meta-data and additional or redundant representations of data +already emitted in other form. + *** Flushing Output (xo_flush) libxo buffers data, both for performance and consistency, but also to @@ -1188,6 +1267,10 @@ xo_flush() call is used for this: void xo_flush (void); void xo_flush_h (xo_handle_t *xop); +Calling xo_flush also triggers the flush function associated with the +handle. For the default handle, this is equivalent to +"fflush(stdio);". + *** Finishing Output (xo_finish) When the program is ready to exit or close a handle, a call to @@ -1250,7 +1333,7 @@ styles. Calls must be made to open and close a list, and for each instance of data in that list, calls must be make to open and close that instance. -The name given to all calls must be identical, and it is strong +The name given to all calls must be identical, and it is strongly suggested that the name be singular, not plural, as a matter of style and usage expectations. @@ -1314,6 +1397,16 @@ Following the call to xo_parse_args, the application can process the remaining arguments in a normal manner. See ^command-line-arguments^ for a description of valid arguments. +*** xo_set_program + +The xo_set_program function sets name of the program as reported by +functions like xo_failure, xo_warn, xo_err, etc. The program name is +initialized by xo_parse_args, but subsequent calls to xo_set_program +can override this value. + +Note that the value is not copied, so the memory passed to +xo_set_program (and xo_parse_args) must be maintained by the caller. + *** Field Information (xo_info_t) @info@ HTML data can include additional information in attributes that @@ -1353,7 +1446,7 @@ known to the application: ... xo_set_info(NULL, info, info_count); -Third, the emitting of info must be triggered with the XOF_INFO flag +Third, the emission of info must be triggered with the XOF_INFO flag using either the xo_set_flags() function or the "--libxo=info" command line argument. @@ -1405,6 +1498,10 @@ Complete HTML output can be generated with: % env LIBXO_OPTIONS=HXI my-app +Since environment variables are inherited, child processes will have +the same options, which may be undesirable, making the use of the +"--libxo" option is preferable in most situations. + *** Errors, Warnings, and Messages Many programs make use of the standard library functions err() and @@ -1435,6 +1532,20 @@ message associated with either "errno" or the "code" parameter. if (open(filename, O_RDONLY) < 0) xo_err(1, "cannot open file '%s'", filename); +*** xo_error + +The xo_error function can be used for generic errors that should be +reported over the handle, rather than to stderr. The xo_error +function behaves like xo_err for TEXT and HTML output styles, but puts +the error into XML or JSON elements: + + EXAMPLE:: + xo_error("Does not %s", "compute"); + XML:: + <error><message>Does not compute</message></error> + JSON:: + "error": { "message": "Does not compute" } + *** xo_no_setlocale libxo automatically initializes the locale based on setting of the @@ -1580,7 +1691,7 @@ and errors, warning, or informational messages as needed. | -X | Extract samples from xolint, suitable for testing | |------------+---------------------------------------------------| -Output message contain the source filename and line number, the +The output message will contain the source filename and line number, the class of the message, the message, and, if -p is given, the line that contains the error: @@ -1627,6 +1738,88 @@ libxo is an effort to mix the best aspects of the JUNOS strategy into FreeBSD in a seemless way, allowing commands to make printf-like output calls without needing to care how the output is rendered. +*** Did the complex semantics of format strings evolve over time? + +The history is both long and short: libxo's functionality is based +on what JUNOS does in a data modeling language called ODL (output +definition language). In JUNOS, all subcomponents generate XML, +which is feed to the CLI, where data from the ODL files tell is +how to render that XML into text. ODL might had a set of tags +like: + + tag docsis-state { + help "State of the DOCSIS interface"; + type string; + } + + tag docsis-mode { + help "DOCSIS mode (2.0/3.0) of the DOCSIS interface"; + type string; + } + + tag docsis-upstream-speed { + help "Operational upstream speed of the interface"; + type string; + } + + tag downstream-scanning { + help "Result of scanning in downstream direction"; + type string; + } + + tag ranging { + help "Result of ranging action"; + type string; + } + + tag signal-to-noise-ratio { + help "Signal to noise ratio for all channels"; + type string; + } + + tag power { + help "Operational power of the signal on all channels"; + type string; + } + + format docsis-status-format { + picture " + State : @, Mode: @, Upstream speed: @ + Downstream scanning: @, Ranging: @ + Signal to noise ratio: @ + Power: @ +"; + line { + field docsis-state; + field docsis-mode; + field docsis-upstream-speed; + field downstream-scanning; + field ranging; + field signal-to-noise-ratio; + field power; + } + } + +These tag definitions are compiled into field definitions +that are triggered when matching XML elements are seen. ODL +also supports other means of defining output. + +The roles and modifiers describe these details. + +In moving these ideas to bsd, two things had to happen: the +formatting had to happen at the source since BSD won't have +a JUNOS-like CLI to do the rendering, and we can't depend on +external data models like ODL, which was seen as too hard a +sell to the BSD community. + +The results were that the xo_emit strings are used to encode the +roles, modifiers, names, and formats. They are dense and a bit +cryptic, but not so unlike printf format strings that developers will +be lost. + +libxo is a new implementation of these ideas and is distinct from +the previous implementation in JUNOS. + *** What makes a good field name? To make useful, consistent field names, follow these guidelines: @@ -1660,7 +1853,7 @@ Nothing's worse than writing expressions like: } Find someone else who is expressing similar data and follow their -field's and hierarchy. Remember the quote is not "Consistency is the +fields and hierarchy. Remember the quote is not "Consistency is the hobgoblin of little minds", but "A foolish consistency is the hobgoblin of little minds". = Think about your users @@ -1670,7 +1863,7 @@ content with xo_attr() calls (^xo_attr^) or "{e:}" fields (^e-modifier^) to make the data useful. = Don't use an arbitrary number postfix What does "errors2" mean? No one will know. "errors-after-restart" -would be a better choice. Think of you users, and think of the +would be a better choice. Think of your users, and think of the future. If you make "errors2", the next guy will happily make "errors3" and before you know it, someone will be asking what's the difference between errors37 and errors63. @@ -1689,7 +1882,7 @@ After using "xolint" to find errors in your field descriptors, use "xolint -V" to spell check your field names and to detect different names for the same data. "dropped-short" and "dropped-too-short" are both reasonable names, but using them both will lead users to ask the -difference between the two fields. If there isn't a difference, +difference between the two fields. If there is no difference, use only one of the field names. If there is a difference, change the names to make that difference more obvious. diff --git a/contrib/libxo/libxo/libxo.3 b/contrib/libxo/libxo/libxo.3 index fca0774..f9b0e6f8 100644 --- a/contrib/libxo/libxo/libxo.3 +++ b/contrib/libxo/libxo/libxo.3 @@ -7,7 +7,7 @@ .\" # LICENSE. .\" # Phil Shafer, July 2014 .\" -.Dd July, 2014 +.Dd December 8, 2014 .Dt LIBXO 3 .Os .Sh NAME @@ -19,58 +19,82 @@ .In libxo/xo.h .Sh DESCRIPTION The functions defined in -.Lb libxo +.Nm are used to generate a choice of .Em TEXT , .Em XML , .Em JSON , or .Em HTML -output. A common set of functions are used, with +output. +A common set of functions are used, with command line switches passed to the library to control the details of the output. .Pp -Most commands emit text output aimed at humans. It is designed -to be parsed and understood by a user. Humans are gifted at extracted -details and pattern matching. Often programmers need to extract -information from this human-oriented output. Programmers use tools -like grep, awk, and regular expressions to ferret out the pieces of -information they need. Such solutions are fragile and require +Most commands emit text output aimed at humans. +It is designed +to be parsed and understood by a user. +Humans are gifted at extracting +details and pattern matching. +Often programmers need to extract +information from this human-oriented output. +Programmers use tools +like +.Xr grep 1 , +.Xr awk 1 , +and regular expressions to ferret out the pieces of +information they need. +Such solutions are fragile and require updates when output contents change or evolve, requiring testing and validation. .Pp -Modern tool developers favors encoding schemes like XML and JSON, -which allow trivial parsing and extraction of data. Such formats are +Modern tool developers favor encoding schemes like XML and JSON, +which allow trivial parsing and extraction of data. +Such formats are simple, well understood, hierarchical, easily parsed, and often integrate easier with common tools and environments. .Pp In addition, modern reality means that more output ends up in web browsers than in terminals, making HTML output valuable. .Pp -.Em libxo +.Nm allows a single set of function calls in source code to generate -traditional text output, as well as XML and JSON formatted data. HTML +traditional text output, as well as XML and JSON formatted data. +HTML can also be generated; "<div>" elements surround the traditional text output, with attributes that detail how to render the data. .Pp -There are four encoding styles supported by libxo: TEXT, HTML, JSON, -and XML. JSON and XML are suitable for encoding data, while TEXT and -HTML are suited for display to the user. TEXT output can be display +There are four encoding styles supported by +.Nm : +TEXT, HTML, JSON, +and XML. +JSON and XML are suitable for encoding data, while TEXT and +HTML are suited for display to the user. +TEXT output can be display on a terminal session, allowing compatibility with traditional usage. HTML can be matched with a small CSS file to permit rendering in any -HTML5 browser. XML output is suitable for tools like XPath and -protocols like NETCONF. JSON output can be used for RESTful APIs. +HTML5 browser. +XML output is suitable for tools like XPath and +protocols like NETCONF. +JSON output can be used for RESTful APIs. .Pp The -.Em libxo +.Nm library allows an application to generate text, XML, JSON, -and HTML output using a common set of function calls. The application -decides at run time which output style should be produced. The +and HTML output using a common set of function calls. +The application +decides at run time which output style should be produced. +The application calls a function -.Fn xo_emit +.Xr xo_emit 3 to product output that is -described in a format string. A "field descriptor" tells libxo what -the field is and what it means. Each field descriptor is placed in +described in a format string. +A +.Dq field descriptor +tells +.Nm +what the field is and what it means. +Each field descriptor is placed in braces with a printf-like format string: .Bd -literal -offset indent xo_emit(" {:lines/%7ju} {:words/%7ju} " @@ -79,55 +103,199 @@ braces with a printf-like format string: .Ed .Pp Each field can have a role, with the 'value' role being the default, -and the role tells libxo how and when to render that field, as well as +and the role tells +.Nm +how and when to render that field, as well as a -.Xr printf 3 -like +.Xr printf 3 Ns -like format string. .Pp Output can then be generated in various style, using the "--libxo" option. .Sh DEFAULT HANDLE -Handles give an abstraction for libxo that encapsulates the state of a -stream of output. Handles have the data type "xo_handle_t" and are +Handles give an abstraction for +.Nm +that encapsulates the state of a +stream of output. +Handles have the data type "xo_handle_t" and are opaque to the caller. - +.Pp The library has a default handle that is automatically initialized. By default, this handle will send text style output to standard output. -The xo_set_style and xo_set_flags functions can be used to change this +The +.Xr xo_set_style 3 +and +.Xr xo_set_flags 3 +functions can be used to change this behavior. - -Many libxo functions take a handle as their first parameter; most that -do not use the default handle. Any function taking a handle can -be passed NULL to access the default handle. - +.Pp +Many +.Nm +functions take a handle as their first parameter; most that +do not use the default handle. +Any function taking a handle can +be passed +.Dv NULL +to access the default handle. +.Pp For the typical command that is generating output on standard output, there is no need to create an explicit handle, but they are available -when needed, e.g. for daemons that generate multiple streams of +when needed, e.g., for daemons that generate multiple streams of output. +.Sh FUNCTION OVERVIEW +The +.Nm +library includes the following functions: +.Bl -tag -width "xo_close_container_hd" +.It Sy "Function Description" +.It Fn xo_attr +.It Fn xo_attr_h +.It Fn xo_attr_hv +Allows the caller to emit XML attributes with the next open element. +.It Fn xo_create +.It Fn xo_create_to_file +Allow the caller to create a new handle. +Note that +.Nm +has a default handle that allows the caller to avoid use of an +explicitly created handle. +Only callers writing to files other than +.Dv stdout +would need to call +.Fn xo_create . +.It Fn xo_destroy +Frees any resources associated with the handle, including the handle +itself. +.It Fn xo_emit +.It Fn xo_emit_h +.It Fn xo_emit_hv +Emit formatted output. +The +.Fa fmt +string controls the conversion of the remaining arguments into +formatted output. +See +.Xr xo_format 5 +for details. +.It Fn xo_warn +.It Fn xo_warnx +.It Fn xo_warn_c +.It Fn xo_warn_hc +.It Fn xo_err +.It Fn xo_errc +.It Fn xo_errx +.It Fn xo_message +.It Fn xo_message_c +.It Fn xo_message_hc +.It Fn xo_message_hcv +These functions are meant to be compatible with their standard libc namesakes. +.It Fn xo_finish +.It Fn xo_finish_h +Flush output, close open construct, and complete any pending +operations. +.It Fn xo_flush +.It Fn xo_flush_h +Allow the caller to flush any pending output for a handle. +.It Fn xo_no_setlocale +Direct +.Nm +to avoid initializing the locale. +This function should be called before any other +.Nm +function is called. +.It Fn xo_open_container +.It Fn xo_open_container_h +.It Fn xo_open_container_hd +.It Fn xo_open_container_d +.It Fn xo_close_container +.It Fn xo_close_container_h +.It Fn xo_close_container_hd +.It Fn xo_close_container_d +Containers a singleton levels of hierarchy, typically used to organize +related content. +.It Fn xo_open_list_h +.It Fn xo_open_list +.It Fn xo_open_list_hd +.It Fn xo_open_list_d +.It Fn xo_open_instance_h +.It Fn xo_open_instance +.It Fn xo_open_instance_hd +.It Fn xo_open_instance_d +.It Fn xo_close_instance_h +.It Fn xo_close_instance +.It Fn xo_close_instance_hd +.It Fn xo_close_instance_d +.It Fn xo_close_list_h +.It Fn xo_close_list +.It Fn xo_close_list_hd +.It Fn xo_close_list_d +Lists are levels of hierarchy that can appear multiple times within +the same parent. +Two calls are needed to encapsulate them, one for +the list and one for each instance of that list. +Typically +.Fn xo_open_list +and +.Fn xo_close_list +are called outside a +for-loop, where +.Fn xo_open_instance +it called at the top of the loop, and +.Fn xo_close_instance +is called at the bottom of the loop. +.It Fn xo_parse_args +Inspects command line arguments for directions to +.Nm . +This function should be called before +.Va argv +is inspected by the application. +.It Fn xo_set_allocator +Instructs +.Nm +to use an alternative memory allocator and deallocator. +.It Fn xo_set_flags +.It Fn xo_clear_flags +Change the flags set for a handle. +.It Fn xo_set_info +Provides additional information about elements for use with HTML +rendering. +.It Fn xo_set_options +Changes formatting options used by handle. +.It Fn xo_set_style +.It Fn xo_set_style_name +Changes the output style used by a handle. +.It Fn xo_set_writer +Instructs +.Nm +to use an alternative set of low-level output functions. +.El .Sh ADDITIONAL DOCUMENTATION -.Pp Complete documentation can be found on github: .Bd -literal -offset indent http://juniper.github.io/libxo/libxo-manual.html .Ed .Pp -libxo lives on github as: +.Nm +lives on github as: .Bd -literal -offset indent https://github.com/Juniper/libxo .Ed .Pp -The latest release of libxo is available at: +The latest release of +.Nm +is available at: .Bd -literal -offset indent https://github.com/Juniper/libxo/releases .Ed .Sh SEE ALSO +.Xr xo 1 , +.Xr xolint 1 , .Xr xo_attr 3 , .Xr xo_create 3 , .Xr xo_emit 3 , .Xr xo_err 3 , .Xr xo_finish 3 , .Xr xo_flush 3 , -.Xr xo_format 5 , .Xr xo_no_setlocale 3 , .Xr xo_open_container 3 , .Xr xo_open_list 3 , @@ -138,12 +306,11 @@ https://github.com/Juniper/libxo/releases .Xr xo_set_options 3 , .Xr xo_set_style 3 , .Xr xo_set_writer 3 , -.Xr xo 1 , -and -.Xr xolint 1 . +.Xr xo_format 5 .Sh HISTORY The -.Fa libxo -library was added in FreeBSD 11.0. +.Nm +library was added in +.Fx 11.0 . .Sh AUTHOR Phil Shafer diff --git a/contrib/libxo/libxo/libxo.c b/contrib/libxo/libxo/libxo.c index 2c97337..e9d05ce 100644 --- a/contrib/libxo/libxo/libxo.c +++ b/contrib/libxo/libxo/libxo.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Juniper Networks, Inc. + * Copyright (c) 2014-2015, Juniper Networks, Inc. * All rights reserved. * This SOFTWARE is licensed under the LICENSE provided in the * ../Copyright file. By downloading, installing, copying, or otherwise @@ -11,6 +11,7 @@ #include <stdio.h> #include <stdlib.h> #include <stdint.h> +#include <unistd.h> #include <stddef.h> #include <wchar.h> #include <locale.h> @@ -27,6 +28,10 @@ #include "xo.h" #include "xoversion.h" +#ifdef HAVE_STDIO_EXT_H +#include <stdio_ext.h> +#endif /* HAVE_STDIO_EXT_H */ + const char xo_version[] = LIBXO_VERSION; const char xo_version_extra[] = LIBXO_VERSION_EXTRA; @@ -58,6 +63,52 @@ typedef unsigned xo_xsf_flags_t; /* XSF_* flags */ #define XSF_INSTANCE (1<<2) /* Frame is an instance */ #define XSF_DTRT (1<<3) /* Save the name for DTRT mode */ +#define XSF_CONTENT (1<<4) /* Some content has been emitted */ +#define XSF_EMIT (1<<5) /* Some field has been emitted */ +#define XSF_EMIT_KEY (1<<6) /* A key has been emitted */ +#define XSF_EMIT_LEAF_LIST (1<<7) /* A leaf-list field has been emitted */ + +/* These are the flags we propagate between markers and their parents */ +#define XSF_MARKER_FLAGS \ + (XSF_NOT_FIRST | XSF_CONTENT | XSF_EMIT | XSF_EMIT_KEY | XSF_EMIT_LEAF_LIST ) + +/* + * A word about states: We're moving to a finite state machine (FMS) + * approach to help remove fragility from the caller's code. Instead + * of requiring a specific order of calls, we'll allow the caller more + * flexibility and make the library responsible for recovering from + * missed steps. The goal is that the library should not be capable of + * emitting invalid xml or json, but the developer shouldn't need + * to know or understand all the details about these encodings. + * + * You can think of states as either states or event, since they + * function rather like both. None of the XO_CLOSE_* events will + * persist as states, since their stack frame will be popped. + * Same is true of XSS_EMIT, which is an event that asks us to + * prep for emitting output fields. + */ + +/* Stack frame states */ +typedef unsigned xo_state_t; +#define XSS_INIT 0 /* Initial stack state */ +#define XSS_OPEN_CONTAINER 1 +#define XSS_CLOSE_CONTAINER 2 +#define XSS_OPEN_LIST 3 +#define XSS_CLOSE_LIST 4 +#define XSS_OPEN_INSTANCE 5 +#define XSS_CLOSE_INSTANCE 6 +#define XSS_OPEN_LEAF_LIST 7 +#define XSS_CLOSE_LEAF_LIST 8 +#define XSS_DISCARDING 9 /* Discarding data until recovered */ +#define XSS_MARKER 10 /* xo_open_marker's marker */ +#define XSS_EMIT 11 /* xo_emit has a leaf field */ +#define XSS_EMIT_LEAF_LIST 12 /* xo_emit has a leaf-list ({l:}) */ +#define XSS_FINISH 13 /* xo_finish was called */ + +#define XSS_MAX 13 + +#define XSS_TRANSITION(_old, _new) ((_old) << 8 | (_new)) + /* * xo_stack_t: As we open and close containers and levels, we * create a stack of frames to track them. This is needed for @@ -65,6 +116,7 @@ typedef unsigned xo_xsf_flags_t; /* XSF_* flags */ */ typedef struct xo_stack_s { xo_xsf_flags_t xs_flags; /* Flags for this frame */ + xo_state_t xs_state; /* State for this stack frame */ char *xs_name; /* Name (for XPath value) */ char *xs_keys; /* XPath predicate for any key fields */ } xo_stack_t; @@ -74,12 +126,13 @@ typedef struct xo_stack_s { * It's used as a store for state, options, and content. */ struct xo_handle_s { - unsigned long xo_flags; /* Flags */ + xo_xof_flags_t xo_flags; /* Flags */ unsigned short xo_style; /* XO_STYLE_* value */ unsigned short xo_indent; /* Indent level (if pretty) */ unsigned short xo_indent_by; /* Indent amount (tab stop) */ xo_write_func_t xo_write; /* Write callback */ xo_close_func_t xo_close; /* Close callback */ + xo_flush_func_t xo_flush; /* Flush callback */ xo_formatter_t xo_formatter; /* Custom formating function */ xo_checkpointer_t xo_checkpointer; /* Custom formating support function */ void *xo_opaque; /* Opaque data for write function */ @@ -197,7 +250,7 @@ typedef struct xo_format_s { static xo_handle_t xo_default_handle; static int xo_default_inited; static int xo_locale_inited; -static char *xo_program; +static const char *xo_program; /* * To allow libxo to be used in diverse environment, we allow the @@ -210,6 +263,10 @@ static xo_free_func_t xo_free = free; static void xo_failure (xo_handle_t *xop, const char *fmt, ...); +static int +xo_transition (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name, + xo_state_t new_state); + static void xo_buf_append_div (xo_handle_t *xop, const char *class, xo_xff_flags_t flags, const char *name, int nlen, @@ -226,6 +283,7 @@ static int xo_write_to_file (void *opaque, const char *data) { FILE *fp = (FILE *) opaque; + return fprintf(fp, "%s", data); } @@ -236,10 +294,22 @@ static void xo_close_file (void *opaque) { FILE *fp = (FILE *) opaque; + fclose(fp); } /* + * Callback to flush a FILE pointer + */ +static int +xo_flush_file (void *opaque) +{ + FILE *fp = (FILE *) opaque; + + return fflush(fp); +} + +/* * Initialize the contents of an xo_buffer_t. */ static void @@ -291,6 +361,29 @@ xo_no_setlocale (void) } /* + * We need to decide if stdout is line buffered (_IOLBF). Lacking a + * standard way to decide this (e.g. getlinebuf()), we have configure + * look to find __flbf, which glibc supported. If not, we'll rely + * on isatty, with the assumption that terminals are the only thing + * that's line buffered. We _could_ test for "steam._flags & _IOLBF", + * which is all __flbf does, but that's even tackier. Like a + * bedazzled Elvis outfit on an ugly lap dog sort of tacky. Not + * something we're willing to do. + */ +static int +xo_is_line_buffered (FILE *stream) +{ +#if HAVE___FLBF + if (__flbf(stream)) + return 1; +#else /* HAVE___FLBF */ + if (isatty(fileno(stream))) + return 1; +#endif /* HAVE___FLBF */ + return 0; +} + +/* * Initialize an xo_handle_t, using both static defaults and * the global settings from the LIBXO_OPTIONS environment * variable. @@ -300,6 +393,10 @@ xo_init_handle (xo_handle_t *xop) { xop->xo_opaque = stdout; xop->xo_write = xo_write_to_file; + xop->xo_flush = xo_flush_file; + + if (xo_is_line_buffered(stdout)) + xop->xo_flags |= XOF_FLUSH_LINE; /* * We need to initialize the locale, which isn't really pretty. @@ -415,7 +512,7 @@ xo_indent (xo_handle_t *xop) rc += xop->xo_indent_by; } - return rc; + return (rc > 0) ? rc : 0; } static void @@ -500,9 +597,9 @@ xo_escape_json (xo_buffer_t *xbp, int len) char *cp, *ep, *ip; for (cp = xbp->xb_curp, ep = cp + len; cp < ep; cp++) { - if (*cp == '\\') + if (*cp == '\\' || *cp == '"') delta += 1; - else if (*cp == '"') + else if (*cp == '\n' || *cp == '\r') delta += 1; } @@ -519,13 +616,18 @@ xo_escape_json (xo_buffer_t *xbp, int len) cp -= 1; ip -= 1; - if (*cp != '\\' && *cp != '"') { + if (*cp == '\\' || *cp == '"') { + *ip-- = *cp; + *ip = '\\'; + } else if (*cp == '\n') { + *ip-- = 'n'; + *ip = '\\'; + } else if (*cp == '\r') { + *ip-- = 'r'; + *ip = '\\'; + } else { *ip = *cp; - continue; } - - *ip-- = *cp; - *ip = '\\'; } while (cp > ep && cp != ip); @@ -572,20 +674,23 @@ xo_buf_escape (xo_handle_t *xop, xo_buffer_t *xbp, * Write the current contents of the data buffer using the handle's * xo_write function. */ -static void +static int xo_write (xo_handle_t *xop) { + int rc = 0; xo_buffer_t *xbp = &xop->xo_data; if (xbp->xb_curp != xbp->xb_bufp) { xo_buf_append(xbp, "", 1); /* Append ending NUL */ xo_anchor_clear(xop); - xop->xo_write(xop->xo_opaque, xbp->xb_bufp); + rc = xop->xo_write(xop->xo_opaque, xbp->xb_bufp); xbp->xb_curp = xbp->xb_bufp; } /* Turn off the flags that don't survive across writes */ xop->xo_flags &= ~(XOF_UNITS_PENDING); + + return rc; } /* @@ -947,7 +1052,7 @@ xo_warn_hcv (xo_handle_t *xop, int code, int check_warn, int len = strlen(fmt); int plen = xo_program ? strlen(xo_program) : 0; - char *newfmt = alloca(len + 2 + plen + 2); /* newline, NUL, and ": " */ + char *newfmt = alloca(len + 1 + plen + 2); /* NUL, and ": " */ if (plen) { memcpy(newfmt, xo_program, plen); @@ -955,7 +1060,6 @@ xo_warn_hcv (xo_handle_t *xop, int code, int check_warn, newfmt[plen++] = ' '; } memcpy(newfmt + plen, fmt, len); - newfmt[len + plen] = '\0'; if (xop->xo_flags & XOF_WARN_XML) { @@ -994,7 +1098,7 @@ xo_warn_hcv (xo_handle_t *xop, int code, int check_warn, xo_buf_append(xbp, msg_close, sizeof(msg_close) - 1); xo_buf_append(xbp, err_close, sizeof(err_close) - 1); - if (code > 0) { + if (code >= 0) { const char *msg = strerror(code); if (msg) { xo_buf_append(xbp, ": ", 2); @@ -1003,11 +1107,16 @@ xo_warn_hcv (xo_handle_t *xop, int code, int check_warn, } xo_buf_append(xbp, "\n", 2); /* Append newline and NUL to string */ - xo_write(xop); + (void) xo_write(xop); } else { vfprintf(stderr, newfmt, vap); - fprintf(stderr, ": %s\n", strerror(code)); + if (code >= 0) { + const char *msg = strerror(code); + if (msg) + fprintf(stderr, ": %s", msg); + } + fprintf(stderr, "\n"); } } @@ -1027,7 +1136,7 @@ xo_warn_c (int code, const char *fmt, ...) va_list vap; va_start(vap, fmt); - xo_warn_hcv(NULL, 0, code, fmt, vap); + xo_warn_hcv(NULL, code, 0, fmt, vap); va_end(vap); } @@ -1149,7 +1258,7 @@ xo_message_hcv (xo_handle_t *xop, int code, const char *fmt, va_list vap) xo_buf_append(xbp, msg_close, sizeof(msg_close) - 1); if (need_nl) xo_buf_append(xbp, "\n", 2); /* Append newline and NUL to string */ - xo_write(xop); + (void) xo_write(xop); break; case XO_STYLE_HTML: @@ -1211,7 +1320,7 @@ xo_message_hcv (xo_handle_t *xop, int code, const char *fmt, va_list vap) break; } - xo_flush_h(xop); + (void) xo_flush_h(xop); } void @@ -1299,6 +1408,7 @@ xo_create_to_file (FILE *fp, xo_style_t style, xo_xof_flags_t flags) xop->xo_opaque = fp; xop->xo_write = xo_write_to_file; xop->xo_close = xo_close_file; + xop->xo_flush = xo_flush_file; } return xop; @@ -1323,7 +1433,7 @@ xo_destroy (xo_handle_t *xop_arg) xo_buf_cleanup(&xop->xo_attrs); if (xop_arg == NULL) { - bzero(&xo_default_handle, sizeof(&xo_default_handle)); + bzero(&xo_default_handle, sizeof(xo_default_handle)); xo_default_inited = 0; } else xo_free(xop); @@ -1451,6 +1561,10 @@ xo_set_options (xo_handle_t *xop, const char *input) xop->xo_flags |= XOF_FLUSH; break; + case 'F': + xop->xo_flags |= XOF_FLUSH_LINE; + break; + case 'H': xop->xo_style = XO_STYLE_HTML; break; @@ -1651,6 +1765,33 @@ xo_clear_flags (xo_handle_t *xop, xo_xof_flags_t flags) xop->xo_flags &= ~flags; } +static const char * +xo_state_name (xo_state_t state) +{ + static const char *names[] = { + "init", + "open_container", + "close_container", + "open_list", + "close_list", + "open_instance", + "close_instance", + "open_leaf_list", + "close_leaf_list", + "discarding", + "marker", + "emit", + "emit_leaf_list", + "finish", + NULL + }; + + if (state < (sizeof(names) / sizeof(names[0]))) + return names[state]; + + return "unknown"; +} + static void xo_line_ensure_open (xo_handle_t *xop, xo_xff_flags_t flags UNUSED) { @@ -1867,14 +2008,20 @@ xo_format_string_direct (xo_handle_t *xop, xo_buffer_t *xbp, goto done_with_encoding; /* Need multi-level 'break' */ case XO_STYLE_JSON: - if (wc != '\\' && wc != '"') + if (wc != '\\' && wc != '"' && wc != '\n' && wc != '\r') break; if (!xo_buf_has_room(xbp, 2)) return -1; *xbp->xb_curp++ = '\\'; - *xbp->xb_curp++ = wc & 0x7f; + if (wc == '\n') + wc = 'n'; + else if (wc == '\r') + wc = 'r'; + else wc = wc & 0x7f; + + *xbp->xb_curp++ = wc; goto done_with_encoding; } @@ -2550,6 +2697,15 @@ xo_buf_append_div (xo_handle_t *xop, const char *class, xo_xff_flags_t flags, if (xsp->xs_name == NULL) continue; + /* + * XSS_OPEN_LIST and XSS_OPEN_LEAF_LIST stack frames + * are directly under XSS_OPEN_INSTANCE frames so we + * don't need to put these in our XPath expressions. + */ + if (xsp->xs_state == XSS_OPEN_LIST + || xsp->xs_state == XSS_OPEN_LEAF_LIST) + continue; + xo_data_append(xop, "/", 1); xo_data_escape(xop, xsp->xs_name, strlen(xsp->xs_name)); if (xsp->xs_keys) { @@ -2615,6 +2771,11 @@ xo_format_title (xo_handle_t *xop, const char *str, int len, static char div_open[] = "<div class=\"title\">"; static char div_close[] = "</div>"; + if (flen == 0) { + fmt = "%s"; + flen = 2; + } + switch (xop->xo_style) { case XO_STYLE_XML: case XO_STYLE_JSON: @@ -2748,6 +2909,75 @@ xo_format_value (xo_handle_t *xop, const char *name, int nlen, int quote; xo_buffer_t *xbp; + /* + * Before we emit a value, we need to know that the frame is ready. + */ + xo_stack_t *xsp = &xop->xo_stack[xop->xo_depth]; + + if (flags & XFF_LEAF_LIST) { + /* + * Check if we've already started to emit normal leafs + * or if we're not in a leaf list. + */ + if ((xsp->xs_flags & (XSF_EMIT | XSF_EMIT_KEY)) + || !(xsp->xs_flags & XSF_EMIT_LEAF_LIST)) { + char nbuf[nlen + 1]; + memcpy(nbuf, name, nlen); + nbuf[nlen] = '\0'; + + int rc = xo_transition(xop, 0, nbuf, XSS_EMIT_LEAF_LIST); + if (rc < 0) + flags |= XFF_DISPLAY_ONLY | XFF_ENCODE_ONLY; + else + xop->xo_stack[xop->xo_depth].xs_flags |= XSF_EMIT_LEAF_LIST; + } + + xsp = &xop->xo_stack[xop->xo_depth]; + if (xsp->xs_name) { + name = xsp->xs_name; + nlen = strlen(name); + } + + } else if (flags & XFF_KEY) { + /* Emitting a 'k' (key) field */ + if ((xsp->xs_flags & XSF_EMIT) && !(flags & XFF_DISPLAY_ONLY)) { + xo_failure(xop, "key field emitted after normal value field: '%.*s'", + nlen, name); + + } else if (!(xsp->xs_flags & XSF_EMIT_KEY)) { + char nbuf[nlen + 1]; + memcpy(nbuf, name, nlen); + nbuf[nlen] = '\0'; + + int rc = xo_transition(xop, 0, nbuf, XSS_EMIT); + if (rc < 0) + flags |= XFF_DISPLAY_ONLY | XFF_ENCODE_ONLY; + else + xop->xo_stack[xop->xo_depth].xs_flags |= XSF_EMIT_KEY; + + xsp = &xop->xo_stack[xop->xo_depth]; + xsp->xs_flags |= XSF_EMIT_KEY; + } + + } else { + /* Emitting a normal value field */ + if ((xsp->xs_flags & XSF_EMIT_LEAF_LIST) + || !(xsp->xs_flags & XSF_EMIT)) { + char nbuf[nlen + 1]; + memcpy(nbuf, name, nlen); + nbuf[nlen] = '\0'; + + int rc = xo_transition(xop, 0, nbuf, XSS_EMIT); + if (rc < 0) + flags |= XFF_DISPLAY_ONLY | XFF_ENCODE_ONLY; + else + xop->xo_stack[xop->xo_depth].xs_flags |= XSF_EMIT; + + xsp = &xop->xo_stack[xop->xo_depth]; + xsp->xs_flags |= XSF_EMIT; + } + } + switch (xop->xo_style) { case XO_STYLE_TEXT: if (flags & XFF_ENCODE_ONLY) @@ -3157,13 +3387,15 @@ xo_do_emit (xo_handle_t *xop, const char *fmt) const char *cp, *sp, *ep, *basep; char *newp = NULL; int flush = (xop->xo_flags & XOF_FLUSH) ? 1 : 0; + int flush_line = (xop->xo_flags & XOF_FLUSH_LINE) ? 1 : 0; xop->xo_columns = 0; /* Always reset it */ for (cp = fmt; *cp; ) { if (*cp == '\n') { xo_line_close(xop); - xo_flush_h(xop); + if (flush_line && xo_flush_h(xop) < 0) + return -1; cp += 1; continue; @@ -3375,42 +3607,53 @@ xo_do_emit (xo_handle_t *xop, const char *fmt) return -1; } - if (format == NULL && ftype != '[' && ftype != ']' ) { - format = "%s"; - flen = 2; - } + if (ftype == 0 || ftype == 'V') { + if (format == NULL) { + /* Default format for value fields is '%s' */ + format = "%s"; + flen = 2; + } - if (ftype == 0 || ftype == 'V') xo_format_value(xop, content, clen, format, flen, encoding, elen, flags); - else if (ftype == 'D') - xo_format_content(xop, "decoration", NULL, 1, - content, clen, format, flen); - else if (ftype == 'E') - xo_format_content(xop, "error", "error", 0, - content, clen, format, flen); - else if (ftype == 'L') - xo_format_content(xop, "label", NULL, 1, - content, clen, format, flen); - else if (ftype == 'N') - xo_format_content(xop, "note", NULL, 1, - content, clen, format, flen); - else if (ftype == 'P') - xo_format_content(xop, "padding", NULL, 1, - content, clen, format, flen); - else if (ftype == 'T') - xo_format_title(xop, content, clen, format, flen); - else if (ftype == 'U') { - if (flags & XFF_WS) - xo_format_content(xop, "padding", NULL, 1, " ", 1, NULL, 0); - xo_format_units(xop, content, clen, format, flen); - } else if (ftype == 'W') - xo_format_content(xop, "warning", "warning", 0, - content, clen, format, flen); - else if (ftype == '[') - xo_anchor_start(xop, content, clen, format, flen); + + } else if (ftype == '[') + xo_anchor_start(xop, content, clen, format, flen); else if (ftype == ']') - xo_anchor_stop(xop, content, clen, format, flen); + xo_anchor_stop(xop, content, clen, format, flen); + + else if (clen || format) { /* Need either content or format */ + if (format == NULL) { + /* Default format for value fields is '%s' */ + format = "%s"; + flen = 2; + } + + if (ftype == 'D') + xo_format_content(xop, "decoration", NULL, 1, + content, clen, format, flen); + else if (ftype == 'E') + xo_format_content(xop, "error", "error", 0, + content, clen, format, flen); + else if (ftype == 'L') + xo_format_content(xop, "label", NULL, 1, + content, clen, format, flen); + else if (ftype == 'N') + xo_format_content(xop, "note", NULL, 1, + content, clen, format, flen); + else if (ftype == 'P') + xo_format_content(xop, "padding", NULL, 1, + content, clen, format, flen); + else if (ftype == 'T') + xo_format_title(xop, content, clen, format, flen); + else if (ftype == 'U') { + if (flags & XFF_WS) + xo_format_content(xop, "padding", NULL, 1, " ", 1, NULL, 0); + xo_format_units(xop, content, clen, format, flen); + } else if (ftype == 'W') + xo_format_content(xop, "warning", "warning", 0, + content, clen, format, flen); + } if (flags & XFF_COLON) xo_format_content(xop, "decoration", NULL, 1, ":", 1, NULL, 0); @@ -3425,8 +3668,12 @@ xo_do_emit (xo_handle_t *xop, const char *fmt) } /* If we don't have an anchor, write the text out */ - if (flush && !(xop->xo_flags & XOF_ANCHOR)) - xo_write(xop); + if (flush && !(xop->xo_flags & XOF_ANCHOR)) { + if (xo_write(xop) < 0) + rc = -1; /* Report failure */ + else if (xop->xo_flush && xop->xo_flush(xop->xo_opaque) < 0) + rc = -1; + } return (rc < 0) ? rc : (int) xop->xo_columns; } @@ -3549,8 +3796,11 @@ xo_stack_set_flags (xo_handle_t *xop) static void xo_depth_change (xo_handle_t *xop, const char *name, - int delta, int indent, xo_xsf_flags_t flags) + int delta, int indent, xo_state_t state, xo_xsf_flags_t flags) { + if (xop->xo_style == XO_STYLE_HTML || xop->xo_style == XO_STYLE_TEXT) + indent = 0; + if (xop->xo_flags & XOF_DTRT) flags |= XSF_DTRT; @@ -3560,18 +3810,17 @@ xo_depth_change (xo_handle_t *xop, const char *name, xo_stack_t *xsp = &xop->xo_stack[xop->xo_depth + delta]; xsp->xs_flags = flags; + xsp->xs_state = state; xo_stack_set_flags(xop); - unsigned save = (xop->xo_flags & (XOF_XPATH | XOF_WARN | XOF_DTRT)); - save |= (flags & XSF_DTRT); + if (name == NULL) + name = XO_FAILURE_NAME; - if (name && save) { - int len = strlen(name) + 1; - char *cp = xo_realloc(NULL, len); - if (cp) { - memcpy(cp, name, len); - xsp->xs_name = cp; - } + int len = strlen(name) + 1; + char *cp = xo_realloc(NULL, len); + if (cp) { + memcpy(cp, name, len); + xsp->xs_name = cp; } } else { /* Pop operation */ @@ -3636,10 +3885,8 @@ xo_stack_flags (unsigned xflags) } static int -xo_open_container_hf (xo_handle_t *xop, xo_xof_flags_t flags, const char *name) +xo_do_open_container (xo_handle_t *xop, xo_xof_flags_t flags, const char *name) { - xop = xo_default(xop); - int rc = 0; const char *ppn = (xop->xo_flags & XOF_PRETTY) ? "\n" : ""; const char *pre_nl = ""; @@ -3653,9 +3900,16 @@ xo_open_container_hf (xo_handle_t *xop, xo_xof_flags_t flags, const char *name) switch (xop->xo_style) { case XO_STYLE_XML: - rc = xo_printf(xop, "%*s<%s>%s", xo_indent(xop), "", - name, ppn); - xo_depth_change(xop, name, 1, 1, xo_stack_flags(flags)); + rc = xo_printf(xop, "%*s<%s", xo_indent(xop), "", name); + + if (xop->xo_attrs.xb_curp != xop->xo_attrs.xb_bufp) { + rc += xop->xo_attrs.xb_curp - xop->xo_attrs.xb_bufp; + xo_data_append(xop, xop->xo_attrs.xb_bufp, + xop->xo_attrs.xb_curp - xop->xo_attrs.xb_bufp); + xop->xo_attrs.xb_curp = xop->xo_attrs.xb_bufp; + } + + rc += xo_printf(xop, ">%s", ppn); break; case XO_STYLE_JSON: @@ -3674,18 +3928,21 @@ xo_open_container_hf (xo_handle_t *xop, xo_xof_flags_t flags, const char *name) rc = xo_printf(xop, "%s%*s\"%s\": {%s", pre_nl, xo_indent(xop), "", name, ppn); - xo_depth_change(xop, name, 1, 1, xo_stack_flags(flags)); - break; - - case XO_STYLE_HTML: - case XO_STYLE_TEXT: - xo_depth_change(xop, name, 1, 0, xo_stack_flags(flags)); break; } + xo_depth_change(xop, name, 1, 1, XSS_OPEN_CONTAINER, + xo_stack_flags(flags)); + return rc; } +static int +xo_open_container_hf (xo_handle_t *xop, xo_xof_flags_t flags, const char *name) +{ + return xo_transition(xop, flags, name, XSS_OPEN_CONTAINER); +} + int xo_open_container_h (xo_handle_t *xop, const char *name) { @@ -3710,8 +3967,8 @@ xo_open_container_d (const char *name) return xo_open_container_hf(NULL, XOF_DTRT, name); } -int -xo_close_container_h (xo_handle_t *xop, const char *name) +static int +xo_do_close_container (xo_handle_t *xop, const char *name) { xop = xo_default(xop); @@ -3721,8 +3978,6 @@ xo_close_container_h (xo_handle_t *xop, const char *name) if (name == NULL) { xo_stack_t *xsp = &xop->xo_stack[xop->xo_depth]; - if (!(xsp->xs_flags & XSF_DTRT)) - xo_failure(xop, "missing name without 'dtrt' mode"); name = xsp->xs_name; if (name) { @@ -3731,13 +3986,15 @@ xo_close_container_h (xo_handle_t *xop, const char *name) char *cp = alloca(len); memcpy(cp, name, len); name = cp; - } else + } else if (!(xsp->xs_flags & XSF_DTRT)) { + xo_failure(xop, "missing name without 'dtrt' mode"); name = XO_FAILURE_NAME; + } } switch (xop->xo_style) { case XO_STYLE_XML: - xo_depth_change(xop, name, -1, -1, 0); + xo_depth_change(xop, name, -1, -1, XSS_CLOSE_CONTAINER, 0); rc = xo_printf(xop, "%*s</%s>%s", xo_indent(xop), "", name, ppn); break; @@ -3745,14 +4002,14 @@ xo_close_container_h (xo_handle_t *xop, const char *name) pre_nl = (xop->xo_flags & XOF_PRETTY) ? "\n" : ""; ppn = (xop->xo_depth <= 1) ? "\n" : ""; - xo_depth_change(xop, name, -1, -1, 0); + xo_depth_change(xop, name, -1, -1, XSS_CLOSE_CONTAINER, 0); rc = xo_printf(xop, "%s%*s}%s", pre_nl, xo_indent(xop), "", ppn); xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST; break; case XO_STYLE_HTML: case XO_STYLE_TEXT: - xo_depth_change(xop, name, -1, 0, 0); + xo_depth_change(xop, name, -1, 0, XSS_CLOSE_CONTAINER, 0); break; } @@ -3760,6 +4017,12 @@ xo_close_container_h (xo_handle_t *xop, const char *name) } int +xo_close_container_h (xo_handle_t *xop, const char *name) +{ + return xo_transition(xop, 0, name, XSS_CLOSE_CONTAINER); +} + +int xo_close_container (const char *name) { return xo_close_container_h(NULL, name); @@ -3778,42 +4041,52 @@ xo_close_container_d (void) } static int -xo_open_list_hf (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name) +xo_do_open_list (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name) { + int rc = 0; + int indent = 0; + xop = xo_default(xop); - if (xop->xo_style != XO_STYLE_JSON) - return 0; + if (xop->xo_style == XO_STYLE_JSON) { + const char *ppn = (xop->xo_flags & XOF_PRETTY) ? "\n" : ""; + const char *pre_nl = ""; - int rc = 0; - const char *ppn = (xop->xo_flags & XOF_PRETTY) ? "\n" : ""; - const char *pre_nl = ""; + indent = 1; + if (!(xop->xo_flags & XOF_NO_TOP)) { + if (!(xop->xo_flags & XOF_TOP_EMITTED)) { + xo_printf(xop, "%*s{%s", xo_indent(xop), "", ppn); + xop->xo_flags |= XOF_TOP_EMITTED; + } + } - if (!(xop->xo_flags & XOF_NO_TOP)) { - if (!(xop->xo_flags & XOF_TOP_EMITTED)) { - xo_printf(xop, "%*s{%s", xo_indent(xop), "", ppn); - xop->xo_flags |= XOF_TOP_EMITTED; + if (name == NULL) { + xo_failure(xop, "NULL passed for list name"); + name = XO_FAILURE_NAME; } - } - if (name == NULL) { - xo_failure(xop, "NULL passed for list name"); - name = XO_FAILURE_NAME; - } + xo_stack_set_flags(xop); - xo_stack_set_flags(xop); + if (xop->xo_stack[xop->xo_depth].xs_flags & XSF_NOT_FIRST) + pre_nl = (xop->xo_flags & XOF_PRETTY) ? ",\n" : ", "; + xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST; - if (xop->xo_stack[xop->xo_depth].xs_flags & XSF_NOT_FIRST) - pre_nl = (xop->xo_flags & XOF_PRETTY) ? ",\n" : ", "; - xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST; + rc = xo_printf(xop, "%s%*s\"%s\": [%s", + pre_nl, xo_indent(xop), "", name, ppn); + } - rc = xo_printf(xop, "%s%*s\"%s\": [%s", - pre_nl, xo_indent(xop), "", name, ppn); - xo_depth_change(xop, name, 1, 1, XSF_LIST | xo_stack_flags(flags)); + xo_depth_change(xop, name, 1, indent, XSS_OPEN_LIST, + XSF_LIST | xo_stack_flags(flags)); return rc; } +static int +xo_open_list_hf (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name) +{ + return xo_transition(xop, flags, name, XSS_OPEN_LIST); +} + int xo_open_list_h (xo_handle_t *xop, const char *name UNUSED) { @@ -3838,21 +4111,14 @@ xo_open_list_d (const char *name) return xo_open_list_hf(NULL, XOF_DTRT, name); } -int -xo_close_list_h (xo_handle_t *xop, const char *name) +static int +xo_do_close_list (xo_handle_t *xop, const char *name) { int rc = 0; const char *pre_nl = ""; - xop = xo_default(xop); - - if (xop->xo_style != XO_STYLE_JSON) - return 0; - if (name == NULL) { xo_stack_t *xsp = &xop->xo_stack[xop->xo_depth]; - if (!(xsp->xs_flags & XSF_DTRT)) - xo_failure(xop, "missing name without 'dtrt' mode"); name = xsp->xs_name; if (name) { @@ -3861,22 +4127,36 @@ xo_close_list_h (xo_handle_t *xop, const char *name) char *cp = alloca(len); memcpy(cp, name, len); name = cp; - } else + } else if (!(xsp->xs_flags & XSF_DTRT)) { + xo_failure(xop, "missing name without 'dtrt' mode"); name = XO_FAILURE_NAME; + } } - if (xop->xo_stack[xop->xo_depth].xs_flags & XSF_NOT_FIRST) - pre_nl = (xop->xo_flags & XOF_PRETTY) ? "\n" : ""; - xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST; + if (xop->xo_style == XO_STYLE_JSON) { + if (xop->xo_stack[xop->xo_depth].xs_flags & XSF_NOT_FIRST) + pre_nl = (xop->xo_flags & XOF_PRETTY) ? "\n" : ""; + xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST; - xo_depth_change(xop, name, -1, -1, XSF_LIST); - rc = xo_printf(xop, "%s%*s]", pre_nl, xo_indent(xop), ""); - xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST; + xo_depth_change(xop, name, -1, -1, XSS_CLOSE_LIST, XSF_LIST); + rc = xo_printf(xop, "%s%*s]", pre_nl, xo_indent(xop), ""); + xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST; + + } else { + xo_depth_change(xop, name, -1, 0, XSS_CLOSE_LIST, XSF_LIST); + xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST; + } return rc; } int +xo_close_list_h (xo_handle_t *xop, const char *name) +{ + return xo_transition(xop, 0, name, XSS_CLOSE_LIST); +} + +int xo_close_list (const char *name) { return xo_close_list_h(NULL, name); @@ -3895,7 +4175,88 @@ xo_close_list_d (void) } static int -xo_open_instance_hf (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name) +xo_do_open_leaf_list (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name) +{ + int rc = 0; + int indent = 0; + + xop = xo_default(xop); + + if (xop->xo_style == XO_STYLE_JSON) { + const char *ppn = (xop->xo_flags & XOF_PRETTY) ? "\n" : ""; + const char *pre_nl = ""; + + indent = 1; + + if (!(xop->xo_flags & XOF_NO_TOP)) { + if (!(xop->xo_flags & XOF_TOP_EMITTED)) { + xo_printf(xop, "%*s{%s", xo_indent(xop), "", ppn); + xop->xo_flags |= XOF_TOP_EMITTED; + } + } + + if (name == NULL) { + xo_failure(xop, "NULL passed for list name"); + name = XO_FAILURE_NAME; + } + + xo_stack_set_flags(xop); + + if (xop->xo_stack[xop->xo_depth].xs_flags & XSF_NOT_FIRST) + pre_nl = (xop->xo_flags & XOF_PRETTY) ? ",\n" : ", "; + xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST; + + rc = xo_printf(xop, "%s%*s\"%s\": [%s", + pre_nl, xo_indent(xop), "", name, ppn); + } + + xo_depth_change(xop, name, 1, indent, XSS_OPEN_LEAF_LIST, + XSF_LIST | xo_stack_flags(flags)); + + return rc; +} + +static int +xo_do_close_leaf_list (xo_handle_t *xop, const char *name) +{ + int rc = 0; + const char *pre_nl = ""; + + if (name == NULL) { + xo_stack_t *xsp = &xop->xo_stack[xop->xo_depth]; + + name = xsp->xs_name; + if (name) { + int len = strlen(name) + 1; + /* We need to make a local copy; xo_depth_change will free it */ + char *cp = alloca(len); + memcpy(cp, name, len); + name = cp; + } else if (!(xsp->xs_flags & XSF_DTRT)) { + xo_failure(xop, "missing name without 'dtrt' mode"); + name = XO_FAILURE_NAME; + } + } + + if (xop->xo_style == XO_STYLE_JSON) { + if (xop->xo_stack[xop->xo_depth].xs_flags & XSF_NOT_FIRST) + pre_nl = (xop->xo_flags & XOF_PRETTY) ? "\n" : ""; + xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST; + + xo_depth_change(xop, name, -1, -1, XSS_CLOSE_LEAF_LIST, XSF_LIST); + rc = xo_printf(xop, "%s%*s]", pre_nl, xo_indent(xop), ""); + xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST; + + } else { + xo_depth_change(xop, name, -1, 0, XSS_CLOSE_LEAF_LIST, XSF_LIST); + xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST; + } + + return rc; +} + +static int +xo_do_open_instance (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name) { xop = xo_default(xop); @@ -3912,8 +4273,16 @@ xo_open_instance_hf (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name) switch (xop->xo_style) { case XO_STYLE_XML: - rc = xo_printf(xop, "%*s<%s>%s", xo_indent(xop), "", name, ppn); - xo_depth_change(xop, name, 1, 1, xo_stack_flags(flags)); + rc = xo_printf(xop, "%*s<%s", xo_indent(xop), "", name); + + if (xop->xo_attrs.xb_curp != xop->xo_attrs.xb_bufp) { + rc += xop->xo_attrs.xb_curp - xop->xo_attrs.xb_bufp; + xo_data_append(xop, xop->xo_attrs.xb_bufp, + xop->xo_attrs.xb_curp - xop->xo_attrs.xb_bufp); + xop->xo_attrs.xb_curp = xop->xo_attrs.xb_bufp; + } + + rc += xo_printf(xop, ">%s", ppn); break; case XO_STYLE_JSON: @@ -3925,18 +4294,20 @@ xo_open_instance_hf (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name) rc = xo_printf(xop, "%s%*s{%s", pre_nl, xo_indent(xop), "", ppn); - xo_depth_change(xop, name, 1, 1, xo_stack_flags(flags)); - break; - - case XO_STYLE_HTML: - case XO_STYLE_TEXT: - xo_depth_change(xop, name, 1, 0, xo_stack_flags(flags)); break; } + xo_depth_change(xop, name, 1, 1, XSS_OPEN_INSTANCE, xo_stack_flags(flags)); + return rc; } +static int +xo_open_instance_hf (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name) +{ + return xo_transition(xop, flags, name, XSS_OPEN_INSTANCE); +} + int xo_open_instance_h (xo_handle_t *xop, const char *name) { @@ -3961,8 +4332,8 @@ xo_open_instance_d (const char *name) return xo_open_instance_hf(NULL, XOF_DTRT, name); } -int -xo_close_instance_h (xo_handle_t *xop, const char *name) +static int +xo_do_close_instance (xo_handle_t *xop, const char *name) { xop = xo_default(xop); @@ -3972,8 +4343,6 @@ xo_close_instance_h (xo_handle_t *xop, const char *name) if (name == NULL) { xo_stack_t *xsp = &xop->xo_stack[xop->xo_depth]; - if (!(xsp->xs_flags & XSF_DTRT)) - xo_failure(xop, "missing name without 'dtrt' mode"); name = xsp->xs_name; if (name) { @@ -3982,27 +4351,29 @@ xo_close_instance_h (xo_handle_t *xop, const char *name) char *cp = alloca(len); memcpy(cp, name, len); name = cp; - } else + } else if (!(xsp->xs_flags & XSF_DTRT)) { + xo_failure(xop, "missing name without 'dtrt' mode"); name = XO_FAILURE_NAME; + } } switch (xop->xo_style) { case XO_STYLE_XML: - xo_depth_change(xop, name, -1, -1, 0); + xo_depth_change(xop, name, -1, -1, XSS_CLOSE_INSTANCE, 0); rc = xo_printf(xop, "%*s</%s>%s", xo_indent(xop), "", name, ppn); break; case XO_STYLE_JSON: pre_nl = (xop->xo_flags & XOF_PRETTY) ? "\n" : ""; - xo_depth_change(xop, name, -1, -1, 0); + xo_depth_change(xop, name, -1, -1, XSS_CLOSE_INSTANCE, 0); rc = xo_printf(xop, "%s%*s}", pre_nl, xo_indent(xop), ""); xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST; break; case XO_STYLE_HTML: case XO_STYLE_TEXT: - xo_depth_change(xop, name, -1, 0, 0); + xo_depth_change(xop, name, -1, 0, XSS_CLOSE_INSTANCE, 0); break; } @@ -4010,6 +4381,12 @@ xo_close_instance_h (xo_handle_t *xop, const char *name) } int +xo_close_instance_h (xo_handle_t *xop, const char *name) +{ + return xo_transition(xop, 0, name, XSS_CLOSE_INSTANCE); +} + +int xo_close_instance (const char *name) { return xo_close_instance_h(NULL, name); @@ -4027,15 +4404,421 @@ xo_close_instance_d (void) return xo_close_instance_h(NULL, NULL); } +static int +xo_do_close_all (xo_handle_t *xop, xo_stack_t *limit) +{ + xo_stack_t *xsp; + int rc = 0; + xo_xsf_flags_t flags; + + for (xsp = &xop->xo_stack[xop->xo_depth]; xsp >= limit; xsp--) { + switch (xsp->xs_state) { + case XSS_INIT: + /* Nothing */ + rc = 0; + break; + + case XSS_OPEN_CONTAINER: + rc = xo_do_close_container(xop, NULL); + break; + + case XSS_OPEN_LIST: + rc = xo_do_close_list(xop, NULL); + break; + + case XSS_OPEN_INSTANCE: + rc = xo_do_close_instance(xop, NULL); + break; + + case XSS_OPEN_LEAF_LIST: + rc = xo_do_close_leaf_list(xop, NULL); + break; + + case XSS_MARKER: + flags = xsp->xs_flags & XSF_MARKER_FLAGS; + xo_depth_change(xop, xsp->xs_name, -1, 0, XSS_MARKER, 0); + xop->xo_stack[xop->xo_depth].xs_flags |= flags; + rc = 0; + break; + } + + if (rc < 0) + xo_failure(xop, "close %d failed: %d", xsp->xs_state, rc); + } + + return 0; +} + +/* + * This function is responsible for clearing out whatever is needed + * to get to the desired state, if possible. + */ +static int +xo_do_close (xo_handle_t *xop, const char *name, xo_state_t new_state) +{ + xo_stack_t *xsp, *limit = NULL; + int rc; + xo_state_t need_state = new_state; + + if (new_state == XSS_CLOSE_CONTAINER) + need_state = XSS_OPEN_CONTAINER; + else if (new_state == XSS_CLOSE_LIST) + need_state = XSS_OPEN_LIST; + else if (new_state == XSS_CLOSE_INSTANCE) + need_state = XSS_OPEN_INSTANCE; + else if (new_state == XSS_CLOSE_LEAF_LIST) + need_state = XSS_OPEN_LEAF_LIST; + else if (new_state == XSS_MARKER) + need_state = XSS_MARKER; + else + return 0; /* Unknown or useless new states are ignored */ + + for (xsp = &xop->xo_stack[xop->xo_depth]; xsp > xop->xo_stack; xsp--) { + /* + * Marker's normally stop us from going any further, unless + * we are popping a marker (new_state == XSS_MARKER). + */ + if (xsp->xs_state == XSS_MARKER && need_state != XSS_MARKER) { + if (name) { + xo_failure(xop, "close (xo_%s) fails at marker '%s'; " + "not found '%s'", + xo_state_name(new_state), + xsp->xs_name, name); + return 0; + + } else { + limit = xsp; + xo_failure(xop, "close stops at marker '%s'", xsp->xs_name); + } + break; + } + + if (xsp->xs_state != need_state) + continue; + + if (name && xsp->xs_name && strcmp(name, xsp->xs_name) != 0) + continue; + + limit = xsp; + break; + } + + if (limit == NULL) { + xo_failure(xop, "xo_%s can't find match for '%s'", + xo_state_name(new_state), name); + return 0; + } + + rc = xo_do_close_all(xop, limit); + + return rc; +} + +/* + * We are in a given state and need to transition to the new state. + */ +static int +xo_transition (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name, + xo_state_t new_state) +{ + xo_stack_t *xsp; + int rc; + int old_state, on_marker; + + xop = xo_default(xop); + + rc = 0; + xsp = &xop->xo_stack[xop->xo_depth]; + old_state = xsp->xs_state; + on_marker = (old_state == XSS_MARKER); + + /* If there's a marker on top of the stack, we need to find a real state */ + while (old_state == XSS_MARKER) { + if (xsp == xop->xo_stack) + break; + xsp -= 1; + old_state = xsp->xs_state; + } + + /* + * At this point, the list of possible states are: + * XSS_INIT, XSS_OPEN_CONTAINER, XSS_OPEN_LIST, + * XSS_OPEN_INSTANCE, XSS_OPEN_LEAF_LIST, XSS_DISCARDING + */ + switch (XSS_TRANSITION(old_state, new_state)) { + + open_container: + case XSS_TRANSITION(XSS_INIT, XSS_OPEN_CONTAINER): + case XSS_TRANSITION(XSS_OPEN_INSTANCE, XSS_OPEN_CONTAINER): + case XSS_TRANSITION(XSS_OPEN_CONTAINER, XSS_OPEN_CONTAINER): + rc = xo_do_open_container(xop, flags, name); + break; + + case XSS_TRANSITION(XSS_OPEN_LIST, XSS_OPEN_CONTAINER): + if (on_marker) + goto marker_prevents_close; + rc = xo_do_close_list(xop, NULL); + if (rc >= 0) + goto open_container; + break; + + case XSS_TRANSITION(XSS_OPEN_LEAF_LIST, XSS_OPEN_CONTAINER): + if (on_marker) + goto marker_prevents_close; + rc = xo_do_close_leaf_list(xop, NULL); + if (rc >= 0) + goto open_container; + break; + + /*close_container:*/ + case XSS_TRANSITION(XSS_OPEN_CONTAINER, XSS_CLOSE_CONTAINER): + if (on_marker) + goto marker_prevents_close; + rc = xo_do_close(xop, name, new_state); + break; + + case XSS_TRANSITION(XSS_INIT, XSS_CLOSE_CONTAINER): + /* This is an exception for "xo --close" */ + rc = xo_do_close_container(xop, name); + break; + + case XSS_TRANSITION(XSS_OPEN_LIST, XSS_CLOSE_CONTAINER): + case XSS_TRANSITION(XSS_OPEN_INSTANCE, XSS_CLOSE_CONTAINER): + if (on_marker) + goto marker_prevents_close; + rc = xo_do_close(xop, name, new_state); + break; + + case XSS_TRANSITION(XSS_OPEN_LEAF_LIST, XSS_CLOSE_CONTAINER): + if (on_marker) + goto marker_prevents_close; + rc = xo_do_close_leaf_list(xop, NULL); + if (rc >= 0) + rc = xo_do_close(xop, name, new_state); + break; + + open_list: + case XSS_TRANSITION(XSS_INIT, XSS_OPEN_LIST): + case XSS_TRANSITION(XSS_OPEN_CONTAINER, XSS_OPEN_LIST): + case XSS_TRANSITION(XSS_OPEN_INSTANCE, XSS_OPEN_LIST): + rc = xo_do_open_list(xop, flags, name); + break; + + case XSS_TRANSITION(XSS_OPEN_LIST, XSS_OPEN_LIST): + if (on_marker) + goto marker_prevents_close; + rc = xo_do_close_list(xop, NULL); + if (rc >= 0) + goto open_list; + break; + + case XSS_TRANSITION(XSS_OPEN_LEAF_LIST, XSS_OPEN_LIST): + if (on_marker) + goto marker_prevents_close; + rc = xo_do_close_leaf_list(xop, NULL); + if (rc >= 0) + goto open_list; + break; + + /*close_list:*/ + case XSS_TRANSITION(XSS_OPEN_LIST, XSS_CLOSE_LIST): + if (on_marker) + goto marker_prevents_close; + rc = xo_do_close(xop, name, new_state); + break; + + case XSS_TRANSITION(XSS_INIT, XSS_CLOSE_LIST): + case XSS_TRANSITION(XSS_OPEN_CONTAINER, XSS_CLOSE_LIST): + case XSS_TRANSITION(XSS_OPEN_INSTANCE, XSS_CLOSE_LIST): + case XSS_TRANSITION(XSS_OPEN_LEAF_LIST, XSS_CLOSE_LIST): + rc = xo_do_close(xop, name, new_state); + break; + + open_instance: + case XSS_TRANSITION(XSS_OPEN_LIST, XSS_OPEN_INSTANCE): + rc = xo_do_open_instance(xop, flags, name); + break; + + case XSS_TRANSITION(XSS_OPEN_CONTAINER, XSS_OPEN_INSTANCE): + case XSS_TRANSITION(XSS_INIT, XSS_OPEN_INSTANCE): + rc = xo_do_open_list(xop, flags, name); + if (rc >= 0) + goto open_instance; + break; + + case XSS_TRANSITION(XSS_OPEN_INSTANCE, XSS_OPEN_INSTANCE): + if (on_marker) { + rc = xo_do_open_list(xop, flags, name); + } else { + rc = xo_do_close_instance(xop, NULL); + } + if (rc >= 0) + goto open_instance; + break; + + case XSS_TRANSITION(XSS_OPEN_LEAF_LIST, XSS_OPEN_INSTANCE): + if (on_marker) + goto marker_prevents_close; + rc = xo_do_close_leaf_list(xop, NULL); + if (rc >= 0) + goto open_instance; + break; + + /*close_instance:*/ + case XSS_TRANSITION(XSS_OPEN_INSTANCE, XSS_CLOSE_INSTANCE): + if (on_marker) + goto marker_prevents_close; + rc = xo_do_close_instance(xop, name); + break; + + case XSS_TRANSITION(XSS_INIT, XSS_CLOSE_INSTANCE): + /* This one makes no sense; ignore it */ + break; + + case XSS_TRANSITION(XSS_OPEN_CONTAINER, XSS_CLOSE_INSTANCE): + case XSS_TRANSITION(XSS_OPEN_LIST, XSS_CLOSE_INSTANCE): + if (on_marker) + goto marker_prevents_close; + rc = xo_do_close(xop, name, new_state); + break; + + case XSS_TRANSITION(XSS_OPEN_LEAF_LIST, XSS_CLOSE_INSTANCE): + if (on_marker) + goto marker_prevents_close; + rc = xo_do_close_leaf_list(xop, NULL); + if (rc >= 0) + rc = xo_do_close(xop, name, new_state); + break; + + open_leaf_list: + case XSS_TRANSITION(XSS_OPEN_CONTAINER, XSS_OPEN_LEAF_LIST): + case XSS_TRANSITION(XSS_OPEN_INSTANCE, XSS_OPEN_LEAF_LIST): + case XSS_TRANSITION(XSS_INIT, XSS_OPEN_LEAF_LIST): + rc = xo_do_open_leaf_list(xop, flags, name); + break; + + case XSS_TRANSITION(XSS_OPEN_LIST, XSS_OPEN_LEAF_LIST): + case XSS_TRANSITION(XSS_OPEN_LEAF_LIST, XSS_OPEN_LEAF_LIST): + if (on_marker) + goto marker_prevents_close; + rc = xo_do_close_list(xop, NULL); + if (rc >= 0) + goto open_leaf_list; + break; + + /*close_leaf_list:*/ + case XSS_TRANSITION(XSS_OPEN_LEAF_LIST, XSS_CLOSE_LEAF_LIST): + if (on_marker) + goto marker_prevents_close; + rc = xo_do_close_leaf_list(xop, name); + break; + + case XSS_TRANSITION(XSS_INIT, XSS_CLOSE_LEAF_LIST): + /* Makes no sense; ignore */ + break; + + case XSS_TRANSITION(XSS_OPEN_CONTAINER, XSS_CLOSE_LEAF_LIST): + case XSS_TRANSITION(XSS_OPEN_LIST, XSS_CLOSE_LEAF_LIST): + case XSS_TRANSITION(XSS_OPEN_INSTANCE, XSS_CLOSE_LEAF_LIST): + if (on_marker) + goto marker_prevents_close; + rc = xo_do_close(xop, name, new_state); + break; + + /*emit:*/ + case XSS_TRANSITION(XSS_OPEN_CONTAINER, XSS_EMIT): + case XSS_TRANSITION(XSS_OPEN_INSTANCE, XSS_EMIT): + break; + + case XSS_TRANSITION(XSS_OPEN_LIST, XSS_EMIT): + if (on_marker) + goto marker_prevents_close; + rc = xo_do_close(xop, NULL, XSS_CLOSE_LIST); + break; + + case XSS_TRANSITION(XSS_INIT, XSS_EMIT): + break; + + case XSS_TRANSITION(XSS_OPEN_LEAF_LIST, XSS_EMIT): + if (on_marker) + goto marker_prevents_close; + rc = xo_do_close_leaf_list(xop, NULL); + break; + + /*emit_leaf_list:*/ + case XSS_TRANSITION(XSS_INIT, XSS_EMIT_LEAF_LIST): + case XSS_TRANSITION(XSS_OPEN_CONTAINER, XSS_EMIT_LEAF_LIST): + case XSS_TRANSITION(XSS_OPEN_INSTANCE, XSS_EMIT_LEAF_LIST): + rc = xo_do_open_leaf_list(xop, flags, name); + break; + + case XSS_TRANSITION(XSS_OPEN_LEAF_LIST, XSS_EMIT_LEAF_LIST): + break; + + case XSS_TRANSITION(XSS_OPEN_LIST, XSS_EMIT_LEAF_LIST): + /* + * We need to be backward compatible with the pre-xo_open_leaf_list + * API, where both lists and leaf-lists were opened as lists. So + * if we find an open list that hasn't had anything written to it, + * we'll accept it. + */ + break; + + default: + xo_failure(xop, "unknown transition: (%u -> %u)", + xsp->xs_state, new_state); + } + + return rc; + + marker_prevents_close: + xo_failure(xop, "marker '%s' prevents transition from %s to %s", + xop->xo_stack[xop->xo_depth].xs_name, + xo_state_name(old_state), xo_state_name(new_state)); + return -1; +} + +int +xo_open_marker_h (xo_handle_t *xop, const char *name) +{ + xop = xo_default(xop); + + xo_depth_change(xop, name, 1, 0, XSS_MARKER, + xop->xo_stack[xop->xo_depth].xs_flags & XSF_MARKER_FLAGS); + + return 0; +} + +int +xo_open_marker (const char *name) +{ + return xo_open_marker_h(NULL, name); +} + +int +xo_close_marker_h (xo_handle_t *xop, const char *name) +{ + xop = xo_default(xop); + + return xo_do_close(xop, name, XSS_MARKER); +} + +int +xo_close_marker (const char *name) +{ + return xo_close_marker_h(NULL, name); +} + void xo_set_writer (xo_handle_t *xop, void *opaque, xo_write_func_t write_func, - xo_close_func_t close_func) + xo_close_func_t close_func, xo_flush_func_t flush_func) { xop = xo_default(xop); xop->xo_opaque = opaque; xop->xo_write = write_func; xop->xo_close = close_func; + xop->xo_flush = flush_func; } void @@ -4045,10 +4828,11 @@ xo_set_allocator (xo_realloc_func_t realloc_func, xo_free_func_t free_func) xo_free = free_func; } -void +int xo_flush_h (xo_handle_t *xop) { static char div_close[] = "</div>"; + int rc; xop = xo_default(xop); @@ -4064,21 +4848,29 @@ xo_flush_h (xo_handle_t *xop) break; } - xo_write(xop); + rc = xo_write(xop); + if (rc >= 0 && xop->xo_flush) + if (xop->xo_flush(xop->xo_opaque) < 0) + return -1; + + return rc; } -void +int xo_flush (void) { - xo_flush_h(NULL); + return xo_flush_h(NULL); } -void +int xo_finish_h (xo_handle_t *xop) { const char *cp = ""; xop = xo_default(xop); + if (!(xop->xo_flags & XOF_NO_CLOSE)) + xo_do_close_all(xop, xop->xo_stack); + switch (xop->xo_style) { case XO_STYLE_JSON: if (!(xop->xo_flags & XOF_NO_TOP)) { @@ -4091,13 +4883,13 @@ xo_finish_h (xo_handle_t *xop) break; } - xo_flush_h(xop); + return xo_flush_h(xop); } -void +int xo_finish (void) { - xo_finish_h(NULL); + return xo_finish_h(NULL); } /* @@ -4141,6 +4933,7 @@ xo_error_hv (xo_handle_t *xop, const char *fmt, va_list vap) break; case XO_STYLE_XML: + case XO_STYLE_JSON: va_copy(xop->xo_vap, vap); xo_open_container_h(xop, "error"); @@ -4235,6 +5028,30 @@ xo_parse_args (int argc, char **argv) return save; } +void +xo_dump_stack (xo_handle_t *xop) +{ + int i; + xo_stack_t *xsp; + + xop = xo_default(xop); + + fprintf(stderr, "Stack dump:\n"); + + xsp = xop->xo_stack; + for (i = 1, xsp++; i <= xop->xo_depth; i++, xsp++) { + fprintf(stderr, " [%d] %s '%s' [%x]\n", + i, xo_state_name(xsp->xs_state), + xsp->xs_name ?: "--", xsp->xs_flags); + } +} + +void +xo_set_program (const char *name) +{ + xo_program = name; +} + #ifdef UNIT_TEST int main (int argc, char **argv) diff --git a/contrib/libxo/libxo/xo.h b/contrib/libxo/libxo/xo.h index 3a59e4c..82b965a 100644 --- a/contrib/libxo/libxo/xo.h +++ b/contrib/libxo/libxo/xo.h @@ -25,35 +25,39 @@ typedef unsigned xo_style_t; #define XO_STYLE_HTML 3 /** Generate HTML output */ /** Flags for libxo */ -typedef unsigned long xo_xof_flags_t; -#define XOF_CLOSE_FP (1<<0) /** Close file pointer on xo_close() */ -#define XOF_PRETTY (1<<1) /** Make 'pretty printed' output */ -#define XOF_DIV_OPEN (1<<2) /** Internal use only: a <div> is open */ -#define XOF_LINE_OPEN (1<<3) /** Internal use only: a <div class="line"> */ - -#define XOF_WARN (1<<4) /** Generate warnings for broken calls */ -#define XOF_XPATH (1<<5) /** Emit XPath attributes in HTML */ -#define XOF_INFO (1<<6) /** Emit additional info fields (HTML) */ -#define XOF_WARN_XML (1<<7) /** Emit warnings in XML (on stdout) */ - -#define XOF_NO_ENV (1<<8) /** Don't look at the LIBXO_OPTIONS env var */ -#define XOF_NO_VA_ARG (1<<9) /** Don't advance va_list w/ va_arg() */ -#define XOF_DTRT (1<<10) /** Enable "do the right thing" mode */ -#define XOF_KEYS (1<<11) /** Flag 'key' fields for xml and json */ - -#define XOF_IGNORE_CLOSE (1<<12) /** Ignore errors on close tags */ -#define XOF_NOT_FIRST (1<<13) /* Not the first item (JSON) */ -#define XOF_NO_LOCALE (1<<14) /** Don't bother with locale */ -#define XOF_TOP_EMITTED (1<<15) /* The top JSON braces have been emitted */ - -#define XOF_NO_TOP (1<<16) /** Don't emit the top braces in JSON */ -#define XOF_ANCHOR (1<<17) /** An anchor is in place */ -#define XOF_UNITS (1<<18) /** Encode units in XML */ -#define XOF_UNITS_PENDING (1<<19) /** We have a units-insertion pending */ - -#define XOF_UNDERSCORES (1<<20) /** Replace dashes with underscores (JSON) */ -#define XOF_COLUMNS (1<<21) /** xo_emit should return a column count */ -#define XOF_FLUSH (1<<22) /** Flush after each xo_emit call */ +typedef unsigned long long xo_xof_flags_t; +#define XOF_BIT(_n) ((xo_xof_flags_t) 1 << (_n)) +#define XOF_CLOSE_FP XOF_BIT(0) /** Close file pointer on xo_close() */ +#define XOF_PRETTY XOF_BIT(1) /** Make 'pretty printed' output */ +#define XOF_DIV_OPEN XOF_BIT(2) /** Internal use only: a <div> is open */ +#define XOF_LINE_OPEN XOF_BIT(3) /** Internal use only: <div class="line"> */ + +#define XOF_WARN XOF_BIT(4) /** Generate warnings for broken calls */ +#define XOF_XPATH XOF_BIT(5) /** Emit XPath attributes in HTML */ +#define XOF_INFO XOF_BIT(6) /** Emit additional info fields (HTML) */ +#define XOF_WARN_XML XOF_BIT(7) /** Emit warnings in XML (on stdout) */ + +#define XOF_NO_ENV XOF_BIT(8) /** Don't look at LIBXO_OPTIONS env var */ +#define XOF_NO_VA_ARG XOF_BIT(9) /** Don't advance va_list w/ va_arg() */ +#define XOF_DTRT XOF_BIT(10) /** Enable "do the right thing" mode */ +#define XOF_KEYS XOF_BIT(11) /** Flag 'key' fields for xml and json */ + +#define XOF_IGNORE_CLOSE XOF_BIT(12) /** Ignore errors on close tags */ +#define XOF_NOT_FIRST XOF_BIT(13) /* Not the first item (JSON) */ +#define XOF_NO_LOCALE XOF_BIT(14) /** Don't bother with locale */ +#define XOF_TOP_EMITTED XOF_BIT(15) /* The top JSON braces have been emitted */ + +#define XOF_NO_TOP XOF_BIT(16) /** Don't emit the top braces in JSON */ +#define XOF_ANCHOR XOF_BIT(17) /** An anchor is in place */ +#define XOF_UNITS XOF_BIT(18) /** Encode units in XML */ +#define XOF_UNITS_PENDING XOF_BIT(19) /** We have a units-insertion pending */ + +#define XOF_UNDERSCORES XOF_BIT(20) /** Replace dashes with underscores (JSON)*/ +#define XOF_COLUMNS XOF_BIT(21) /** xo_emit should return a column count */ +#define XOF_FLUSH XOF_BIT(22) /** Flush after each xo_emit call */ +#define XOF_FLUSH_LINE XOF_BIT(23) /** Flush after each newline */ + +#define XOF_NO_CLOSE XOF_BIT(24) /** xo_finish won't close open elements */ /* * The xo_info_t structure provides a mapping between names and @@ -70,6 +74,7 @@ typedef struct xo_handle_s xo_handle_t; /* Handle for XO output */ typedef int (*xo_write_func_t)(void *, const char *); typedef void (*xo_close_func_t)(void *); +typedef int (*xo_flush_func_t)(void *); typedef void *(*xo_realloc_func_t)(void *, size_t); typedef void (*xo_free_func_t)(void *); @@ -93,7 +98,7 @@ xo_destroy (xo_handle_t *xop); void xo_set_writer (xo_handle_t *xop, void *opaque, xo_write_func_t write_func, - xo_close_func_t close_func); + xo_close_func_t close_func, xo_flush_func_t flush_func); void xo_set_allocator (xo_realloc_func_t realloc_func, xo_free_func_t free_func); @@ -210,6 +215,18 @@ int xo_close_instance_d (void); int +xo_open_marker_h (xo_handle_t *xop, const char *name); + +int +xo_open_marker (const char *name); + +int +xo_close_marker_h (xo_handle_t *xop, const char *name); + +int +xo_close_marker (const char *name); + +int xo_attr_h (xo_handle_t *xop, const char *name, const char *fmt, ...); int @@ -227,16 +244,16 @@ xo_error_h (xo_handle_t *xop, const char *fmt, ...); void xo_error (const char *fmt, ...); -void +int xo_flush_h (xo_handle_t *xop); -void +int xo_flush (void); -void +int xo_finish_h (xo_handle_t *xop); -void +int xo_finish (void); void @@ -297,4 +314,10 @@ xo_parse_args (int argc, char **argv); extern const char xo_version[]; extern const char xo_version_extra[]; +void +xo_dump_stack (xo_handle_t *xop); + +void +xo_set_program (const char *name); + #endif /* INCLUDE_XO_H */ diff --git a/contrib/libxo/libxo/xo_attr.3 b/contrib/libxo/libxo/xo_attr.3 index afd805f..1c18360 100644 --- a/contrib/libxo/libxo/xo_attr.3 +++ b/contrib/libxo/libxo/xo_attr.3 @@ -51,6 +51,10 @@ parameter as passed to XML: <login-time seconds="1408336270">00:14</login-time> .Ed +.Pp +Since attributes are only emitted in XML, their use should be limited +to meta-data and additional or redundant representations of data +already emitted in other form. .Sh ADDITIONAL DOCUMENTATION .Pp Complete documentation can be found on github: diff --git a/contrib/libxo/libxo/xo_create.3 b/contrib/libxo/libxo/xo_create.3 index ec241ee..b0e8965 100644 --- a/contrib/libxo/libxo/xo_create.3 +++ b/contrib/libxo/libxo/xo_create.3 @@ -7,7 +7,7 @@ .\" # LICENSE. .\" # Phil Shafer, July 2014 .\" -.Dd July, 2014 +.Dd December 4, 2014 .Dt LIBXO 3 .Os .Sh NAME @@ -25,7 +25,7 @@ .Fn xo_destroy "xo_handle_t *handle" .Sh DESCRIPTION A -.Em libxo +.Nm libxo handle can be allocated using the .Fn xo_create function. @@ -37,49 +37,55 @@ function. .Ed .Pp By default, -.Em libxo -writes output to standard output. A convenience -function is provided for situations when output should be written to +.Nm libxo +writes output to standard output. +A convenience +function is provided for situations when output should be written to a different file. .Pp Use the -.Em XOF_CLOSE_FP +.Dv XOF_CLOSE_FP flag to trigger a call to -.Em fclose 3 -for the FILE pointer when the handle is destroyed. +.Xr fclose 3 +for the +.Dv FILE +pointer when the handle is destroyed. .Pp The .Fn xo_destroy function releases a handle and any resources it is -using. Calling +using. +Calling .Fn xo_destroy with a -.Em NULL +.Dv NULL handle will release any resources associated with the default handle. .Sh ADDITIONAL DOCUMENTATION -.Pp Complete documentation can be found on github: .Bd -literal -offset indent http://juniper.github.io/libxo/libxo-manual.html .Ed .Pp -libxo lives on github as: +.Nm libxo +lives on github as: .Bd -literal -offset indent https://github.com/Juniper/libxo .Ed .Pp -The latest release of libxo is available at: +The latest release of +.Nm libxo +is available at: .Bd -literal -offset indent https://github.com/Juniper/libxo/releases .Ed .Sh SEE ALSO -.Xr xo_emit 3 -and -.Xr xo_set_options 3 . +.Xr xo_emit 3 , +.Xr xo_set_options 3 .Sh HISTORY The -.Fa libxo -library was added in FreeBSD 11.0. +.Nm libxo +library was added in +.Fx 11.0 . .Sh AUTHOR Phil Shafer diff --git a/contrib/libxo/libxo/xo_emit.3 b/contrib/libxo/libxo/xo_emit.3 index 9f76e13..7060824 100644 --- a/contrib/libxo/libxo/xo_emit.3 +++ b/contrib/libxo/libxo/xo_emit.3 @@ -7,7 +7,7 @@ .\" # LICENSE. .\" # Phil Shafer, July 2014 .\" -.Dd July, 2014 +.Dd December 4, 2014 .Dt LIBXO 3 .Os .Sh NAME @@ -44,13 +44,13 @@ accepts a .Fa va_list for additional flexibility. .Sh ADDITIONAL DOCUMENTATION -.Pp Complete documentation can be found on github: .Bd -literal -offset indent http://juniper.github.io/libxo/libxo-manual.html .Ed .Pp -libxo lives on github as: +.Nm libxo +lives on github as: .Bd -literal -offset indent https://github.com/Juniper/libxo .Ed @@ -61,11 +61,12 @@ https://github.com/Juniper/libxo/releases .Ed .Sh SEE ALSO .Xr xo_open_container 3 , -.Xr xo_open_list 3 , and -.Xr xo_format 5 . +.Xr xo_open_list 3 , +.Xr xo_format 5 .Sh HISTORY The -.Fa libxo -library was added in FreeBSD 11.0. +.Nm libxo +library was added in +.Fx 11.0 . .Sh AUTHOR Phil Shafer diff --git a/contrib/libxo/libxo/xo_err.3 b/contrib/libxo/libxo/xo_err.3 index 2445aa7..5584309 100644 --- a/contrib/libxo/libxo/xo_err.3 +++ b/contrib/libxo/libxo/xo_err.3 @@ -7,7 +7,7 @@ .\" # LICENSE. .\" # Phil Shafer, July 2014 .\" -.Dd July, 2014 +.Dd December 4, 2014 .Dt LIBXO 3 .Os .Sh NAME @@ -45,32 +45,38 @@ Many programs make use of the standard library functions and .Xr warn 3 to generate errors and warnings for the user. -.Em libxo +.Nm libxo wants to pass that information via the current output style, and provides compatible functions to allow this. .Pp These functions display the program name, a colon, a formatted message based on the arguments, and then optionally a colon and an error -message associated with either "errno" or the "code" parameter. +message associated with either +.Fa errno +or the +.Fa code +parameter. .Bd -literal -offset indent EXAMPLE: if (open(filename, O_RDONLY) < 0) xo_err(1, "cannot open file '%s'", filename); .Ed .Sh ADDITIONAL DOCUMENTATION -.Pp Complete documentation can be found on github: .Bd -literal -offset indent http://juniper.github.io/libxo/libxo-manual.html .Ed .Pp -libxo lives on github as: +.Nm libxo +lives on github as: .Bd -literal -offset indent https://github.com/Juniper/libxo .Ed .Pp -The latest release of libxo is available at: +The latest release of +.Nm libxo +is available at: .Bd -literal -offset indent https://github.com/Juniper/libxo/releases .Ed @@ -78,7 +84,8 @@ https://github.com/Juniper/libxo/releases .Xr xo_emit 3 .Sh HISTORY The -.Fa libxo -library was added in FreeBSD 11.0. +.Nm libxo +library was added in +.Fx 11.0 . .Sh AUTHOR Phil Shafer diff --git a/contrib/libxo/libxo/xo_error.3 b/contrib/libxo/libxo/xo_error.3 new file mode 100644 index 0000000..da91785 --- /dev/null +++ b/contrib/libxo/libxo/xo_error.3 @@ -0,0 +1,64 @@ +.\" # +.\" # Copyright (c) 2014, Juniper Networks, Inc. +.\" # All rights reserved. +.\" # This SOFTWARE is licensed under the LICENSE provided in the +.\" # ../Copyright file. By downloading, installing, copying, or +.\" # using the SOFTWARE, you agree to be bound by the terms of that +.\" # LICENSE. +.\" # Phil Shafer, July 2014 +.\" +.Dd December 4, 2014 +.Dt LIBXO 3 +.Os +.Sh NAME +.Nm xo_error +.Nd generate error messages +.Sh LIBRARY +.Lb libxo +.Sh SYNOPSIS +.In libxo/xo.h +.Ft void +.Fn xo_error "const char *fmt" "..." +.Sh DESCRIPTION +Use the +.Fn xo_error +function to generate error messages to standard error. +The +.Fa fmt +argument is a string containing printf-style formatting +instructions that describe the remaining arguments. +.Pp +When converting an application to libxo, one can replace +.Em "fprintf(stderr,...)" +calls with +.Fn xo_error +calls. +.Pp +.Sh ADDITIONAL DOCUMENTATION +Complete documentation can be found on github: +.Bd -literal -offset indent +http://juniper.github.io/libxo/libxo-manual.html +.Ed +.Pp +.Nm libxo +lives on github as: +.Bd -literal -offset indent +https://github.com/Juniper/libxo +.Ed +.Pp +The latest release of +.Nm libxo +is available at: +.Bd -literal -offset indent +https://github.com/Juniper/libxo/releases +.Ed +.Sh SEE ALSO +.Xr printf 3 +.Xr xo_emit 3 +.Sh HISTORY +The +.Nm libxo +library was added in +.Fx 11.0 . +.Sh AUTHOR +Phil Shafer diff --git a/contrib/libxo/libxo/xo_finish.3 b/contrib/libxo/libxo/xo_finish.3 index 3b25dc3..421e945 100644 --- a/contrib/libxo/libxo/xo_finish.3 +++ b/contrib/libxo/libxo/xo_finish.3 @@ -7,7 +7,7 @@ .\" # LICENSE. .\" # Phil Shafer, July 2014 .\" -.Dd July, 2014 +.Dd December 4, 2014 .Dt LIBXO 3 .Os .Sh NAME @@ -24,9 +24,10 @@ .Sh DESCRIPTION When the program is ready to exit or close a handle, a call to .Fn xo_finish -is required. This flushes any buffered data, closes +is required. +This flushes any buffered data, closes open -.Em libxo +.Nm libxo constructs, and completes any pending operations. .Pp Calling this function is @@ -34,18 +35,20 @@ Calling this function is to the proper operation of libxo, especially for the non-TEXT output styles. .Sh ADDITIONAL DOCUMENTATION -.Pp Complete documentation can be found on github: .Bd -literal -offset indent http://juniper.github.io/libxo/libxo-manual.html .Ed .Pp -libxo lives on github as: +.Nm libxo +lives on github as: .Bd -literal -offset indent https://github.com/Juniper/libxo .Ed .Pp -The latest release of libxo is available at: +The latest release of +.Nm libxo +is available at: .Bd -literal -offset indent https://github.com/Juniper/libxo/releases .Ed @@ -53,7 +56,8 @@ https://github.com/Juniper/libxo/releases .Xr xo_emit 3 .Sh HISTORY The -.Fa libxo -library was added in FreeBSD 11.0. +.Nm libxo +library was added in +.Fx 11.0 . .Sh AUTHOR Phil Shafer diff --git a/contrib/libxo/libxo/xo_flush.3 b/contrib/libxo/libxo/xo_flush.3 index 160f634..b85e9f7 100644 --- a/contrib/libxo/libxo/xo_flush.3 +++ b/contrib/libxo/libxo/xo_flush.3 @@ -7,7 +7,7 @@ .\" # LICENSE. .\" # Phil Shafer, July 2014 .\" -.Dd July, 2014 +.Dd December 4, 2014 .Dt LIBXO 3 .Os .Sh NAME @@ -22,25 +22,29 @@ .Ft void .Fn xo_flush_h "xo_handle_t *handle" .Sh DESCRIPTION -.Em libxo +.Nm libxo buffers data, both for performance and consistency, but also to -allow some advanced features to work properly. At various times, the -caller may wish to flush any data buffered within the library. The +allow some advanced features to work properly. +At various times, the +caller may wish to flush any data buffered within the library. +The .Fn xo_flush function is used for this. .Sh ADDITIONAL DOCUMENTATION -.Pp Complete documentation can be found on github: .Bd -literal -offset indent http://juniper.github.io/libxo/libxo-manual.html .Ed .Pp -libxo lives on github as: +.Nm libxo +lives on github as: .Bd -literal -offset indent https://github.com/Juniper/libxo .Ed .Pp -The latest release of libxo is available at: +The latest release of +.Nm libxo +is available at: .Bd -literal -offset indent https://github.com/Juniper/libxo/releases .Ed @@ -48,7 +52,8 @@ https://github.com/Juniper/libxo/releases .Xr xo_emit 3 .Sh HISTORY The -.Fa libxo -library was added in FreeBSD 11.0. +.Nm libxo +library was added in +.Fx 11.0 . .Sh AUTHOR Phil Shafer diff --git a/contrib/libxo/libxo/xo_format.5 b/contrib/libxo/libxo/xo_format.5 index 62cfeb6..b021b98 100644 --- a/contrib/libxo/libxo/xo_format.5 +++ b/contrib/libxo/libxo/xo_format.5 @@ -7,7 +7,7 @@ .\" # LICENSE. .\" # Phil Shafer, July 2014 .\" -.Dd July, 2014 +.Dd December 4, 2014 .Dt LIBXO 3 .Os .Sh NAME @@ -15,7 +15,7 @@ .Nd content of format descriptors for xo_emit .Sh DESCRIPTION .Pp -.Em libxo +.Nm libxo uses format strings to control the rendering of data into various output styles, including .Em text , @@ -25,25 +25,28 @@ and .Em HTML . Each format string contains a set of zero or more .Dq field descriptions , -which describe independent data fields. Each -field description contains a set of +which describe independent data fields. +Each field description contains a set of .Dq modifiers , a .Dq content string , and zero, one, or two .Dq format descriptors . The modifiers tell -.Em libxo +.Nm libxo what the field is and how to treat it, while the format descriptors are formatting instructions using -.Xr printf 3 -style +.Xr printf 3 Ns -style format strings, telling -libxo how to format the field. The field description is placed inside +.Nm libxo +how to format the field. +The field description is placed inside a set of braces, with a colon .Ql ( \&: ) after the modifiers and a slash .Ql ( \&/ ) -before each format descriptors. Text may be intermixed with +before each format descriptors. +Text may be intermixed with field descriptions within the format string. .Pp The field description is given as follows: @@ -53,15 +56,19 @@ The field description is given as follows: .Ed .Pp The role describes the function of the field, while the modifiers -enable optional behaviors. The contents, field-format, and -encoding-format are used in varying ways, based on the role. These -are described in the following sections. +enable optional behaviors. +The contents, field-format, and +encoding-format are used in varying ways, based on the role. +These are described in the following sections. .Pp -In the following example, three field descriptors appear. The first +In the following example, three field descriptors appear. +The first is a padding field containing three spaces of padding, the second is a -label ("In stock"), and the third is a value field ("in-stock"). The -in-stock field has a "%u" format that will parse the next argument -passed to the xo_emit function as an unsigned integer. +label ("In stock"), and the third is a value field ("in-stock"). +The in-stock field has a "%u" format that will parse the next argument +passed to the +.Xr xo_emit 3 , +function as an unsigned integer. .Bd -literal -offset indent xo_emit("{P: }{Lwc:In stock}{:in-stock/%u}\\n", 65); .Ed @@ -71,7 +78,8 @@ This single line of code can generate text ("In stock: 65\\n"), XML lengthy to be listed here). .Ss Modifier Roles Modifiers are optional, and indicate the role and formatting of the -content. The roles are listed below; only one role is permitted: +content. +The roles are listed below; only one role is permitted: .Pp .Bl -column "M" "Name12341234" .It Sy "M Name Description" @@ -91,7 +99,8 @@ content. The roles are listed below; only one role is permitted: .Ss The Decoration Role ({D:}) Decorations are typically punctuation marks such as colons, semi-colons, and commas used to decorate the text and make it simpler -for human readers. By marking these distinctly, HTML usage scenarios +for human readers. +By marking these distinctly, HTML usage scenarios can use CSS to direct their display parameters. .Bd -literal -offset indent xo_emit("{D:((}{:name}{D:))}\\n", name); @@ -116,8 +125,9 @@ if preceded by a slash ("/"): xo_emit("{P:/30s}{Lwc:Cost}{:cost/%u}\\n", "", cost); .Ed .Ss The Title Role ({T:}) -Title are heading or column headers that are meant to be displayed to -the user. The title can be either static, when placed directly within +Titles are heading or column headers that are meant to be displayed to +the user. +The title can be either static, when placed directly within the field descriptor, or a printf-style format descriptor can be used, if preceded by a slash ("/"): .Bd -literal -offset indent @@ -126,7 +136,8 @@ if preceded by a slash ("/"): .Ed .Ss The Units Role ({U:}) Units are the dimension by which values are measured, such as degrees, -miles, bytes, and decibels. The units field carries this information +miles, bytes, and decibels. +The units field carries this information for the previous value field. .Bd -literal -offset indent xo_emit("{Lwc:Distance}{:distance/%u}{Uw:miles}\\n", miles); @@ -136,7 +147,7 @@ Note that the sense of the 'w' modifier is reversed for units; a blank is added before the contents, rather than after it. .Pp When the -.Em XOF_UNITS +.Dv XOF_UNITS flag is set, units are rendered in XML as the .Dq units attribute: @@ -151,14 +162,19 @@ Units can also be rendered in HTML as the "data-units" attribute: .Ed .Ss The Value Role ({V:} and {:}) The value role is used to represent the a data value that is -interesting for the non-display output styles (XML and JSON). Value +interesting for the non-display output styles (XML and JSON). +Value is the default role; if no other role designation is given, the field -is a value. The field name must appear within the field descriptor, -followed by one or two format descriptors. The first format +is a value. +The field name must appear within the field descriptor, +followed by one or two format descriptors. +The first format descriptor is used for display styles (TEXT and HTML), while the -second one is used for encoding styles (XML and JSON). If no second +second one is used for encoding styles (XML and JSON). +If no second format is given, the encoding format defaults to the first format, -with any minimum width removed. If no first format is given, both +with any minimum width removed. +If no first format is given, both format descriptors default to "%s". .Bd -literal -offset indent xo_emit("{:length/%02u}x{:width/%02u}x{:height/%02u}\\n", @@ -168,9 +184,13 @@ format descriptors default to "%s". .Ed .Ss The Anchor Modifiers ({[:} and {]:}) The anchor roles allow a set of strings by be padded as a group, -but still be visible to xo_emit as distinct fields. Either the start +but still be visible to +.Xr xo_emit 3 +as distinct fields. +Either the start or stop anchor can give a field width and it can be either directly in -the descriptor or passed as an argument. Any fields between the start +the descriptor or passed as an argument. +Any fields between the start and stop anchor are padded to meet the minimum width given. .Pp To give a width directly, encode it as the content of the anchor tag: @@ -179,21 +199,26 @@ To give a width directly, encode it as the content of the anchor tag: .Ed .Pp To pass a width as an argument, use "%d" as the format, which must -appear after the "/". Note that only "%d" is supported for widths. +appear after the "/". +Note that only "%d" is supported for widths. Using any other value could ruin your day. .Bd -literal -offset indent xo_emit("({[:/%d}{:min/%d}/{:max/%d}{]:})\\n", width, min, max); .Ed .Pp If the width is negative, padding will be added on the right, suitable -for left justification. Otherwise the padding will be added to the +for left justification. +Otherwise the padding will be added to the left of the fields between the start and stop anchors, suitable for -right justification. If the width is zero, nothing happens. If the +right justification. +If the width is zero, nothing happens. +If the number of columns of output between the start and stop anchors is less than the absolute value of the given width, nothing happens. .Pp -Widths over 8k are considered probable errors and not supported. If -.Em XOF_WARN +Widths over 8k are considered probable errors and not supported. +If +.Dv XOF_WARN is set, a warning will be generated. .Ss Modifier Flags The modifiers can also include the following flags, which modify the @@ -201,19 +226,20 @@ content emitted for some output styles: .Pp .Bl -column M "Name12341234" .It Sy M "Name Description" -.It c "colon " "A colon (":") is appended after the label" +.It c "colon " "A colon ("":"") is appended after the label" .It d "display " "Only emit field for display styles (text/HTML)" .It e "encoding " "Only emit for encoding styles (XML/JSON)" .It k "key " "Field is a key, suitable for XPath predicates" .It n "no-quotes " "Do not quote the field when using JSON style" .It q "quotes " "Quote the field when using JSON style" -.It w "white space " "A blank (" ") is appended after the label" +.It w "white space " "A blank ("" "") is appended after the label" .El .Pp For example, the modifier string "Lwc" means the field has a label role (text that describes the next field) and should be followed by a -colon ('c') and a space ('w'). The modifier string "Vkq" means the -field is has value role, that it is a key for the current instance, and +colon ('c') and a space ('w'). +The modifier string "Vkq" means the +field has a value role, that it is a key for the current instance, and that the value should be quoted when encoded for JSON. .Ss The Colon Modifier ({c:}) The colon modifier appends a single colon to the data value: @@ -225,7 +251,8 @@ The colon modifier appends a single colon to the data value: .Ed .Pp The colon modifier is only used for the TEXT and HTML output -styles. It is commonly combined with the space modifier ('{w:'). +styles. +It is commonly combined with the space modifier ('{w:}'). It is purely a convenience feature. .Ss The Display Modifier ({d:}) The display modifier indicated the field should only be generated for @@ -270,15 +297,34 @@ uniquely identify an instance of list data. xo_close_list("user"); .Ed .Pp -Currently the key modifier is only used when generating XPath value +Currently the key modifier is only used when generating XPath values for the HTML output style when -.Em XOF_XPATH +.Dv XOF_XPATH is set, but other uses are likely in the near future. +.Ss The Leaf-List Modifier ({l:}) +The leaf-list modifier is used to distinguish lists where each +instance consists of only a single value. In XML, these are +rendered as single elements, where JSON renders them as arrays. +.Bd -literal -offset indent + EXAMPLE: + xo_open_list("user"); + for (i = 0; i < num_users; i++) { + xo_emit("Member {l:name}\n", user[i].u_name); + } + xo_close_list("user"); + XML: + <user>phil</user> + <user>pallavi</user> + JSON: + "user": [ "phil", "pallavi" ] +.Ed .Ss The No-Quotes Modifier ({n:}) The no-quotes modifier (and its twin, the 'quotes' modifier) affect -the quoting of values in the JSON output style. JSON uses quotes for -string value, but no quotes for numeric, boolean, and null data. -xo_emit applies a simple heuristic to determine whether quotes are +the quoting of values in the JSON output style. +JSON uses quotes for +string values, but no quotes for numeric, boolean, and null data. +.Xr xo_emit 3 +applies a simple heuristic to determine whether quotes are needed, but often this needs to be controlled by the caller. .Bd -literal -offset indent EXAMPLE: @@ -289,9 +335,11 @@ needed, but often this needs to be controlled by the caller. .Ed .Ss The Quotes Modifier ({q:}) The quotes modifier (and its twin, the 'no-quotes' modifier) affect -the quoting of values in the JSON output style. JSON uses quotes for -string value, but no quotes for numeric, boolean, and null data. -xo_emit applies a simple heuristic to determine whether quotes are +the quoting of values in the JSON output style. +JSON uses quotes for +string values, but no quotes for numeric, boolean, and null data. +.Xr xo_emit 3 +applies a simple heuristic to determine whether quotes are needed, but often this needs to be controlled by the caller. .Bd -literal -offset indent EXAMPLE: @@ -309,7 +357,8 @@ The white space modifier appends a single space to the data value: .Ed .Pp The white space modifier is only used for the TEXT and HTML output -styles. It is commonly combined with the colon modifier ('{c:'). +styles. +It is commonly combined with the colon modifier ('{c:}'). It is purely a convenience feature. .Pp Note that the sense of the 'w' modifier is reversed for the units role @@ -317,16 +366,20 @@ Note that the sense of the 'w' modifier is reversed for the units role .Ss Field Formatting The field format is similar to the format string for .Xr printf 3 . -It's used varies based on the role of the field, but generally is used to +Its use varies based on the role of the field, but generally is used to format the field's contents. .Pp -If not provided, the format string defaults to "%s". +If the format string is not provided for a value field, it defaults +to "%s". .Pp Note a field definition can contain zero or more printf-style .Dq directives , -which are sequences that start with a '%' and end with a -one of following characters: "diouxXDOUeEfFgGaAcCsSp". Each directive -is matched by one of more arguments to the xo_emit function. +which are sequences that start with a '%' and end with +one of following characters: "diouxXDOUeEfFgGaAcCsSp". +Each directive +is matched by one of more arguments to the +.Xr xo_emit 3 +function. .Pp The format string has the form: .Bd -literal -offset indent @@ -346,19 +399,22 @@ a leading zero ('0') indicating the output value should be padded on the left with zeroes instead of spaces (' '). .It one or more digits ('0' - '9') indicating the minimum width of the -argument. If the width in columns of the output value is less that -the minumum width, the value will be padded to reach the minimum. +argument. +If the width in columns of the output value is less than +the minimum width, the value will be padded to reach the minimum. .It a period followed by one or more digits indicating the maximum number of bytes which will be examined for a string argument, or the maximum -width for a non-string argument. When handling ASCII strings this is +width for a non-string argument. +When handling ASCII strings this functions as the field width but for multi-byte characters, a single character may be composed of multiple bytes. -xo_emit will never dereference memory beyond the given number of bytes. +.Xr xo_emit 3 +will never dereference memory beyond the given number of bytes. .It a second period followed by one or more digits indicating the maximum -width for a string argument. This modifier cannot be given for non-string -arguments. +width for a string argument. +This modifier cannot be given for non-string arguments. .It one or more 'h' characters, indicating shorter input data. .It @@ -420,39 +476,50 @@ argument: .El .Pp .Ss UTF-8 and Locale Strings -All strings for libxo must be UTF-8. libxo will handle turning them +All strings for +.Nm libxo +must be UTF-8. +.Nm libxo +will handle turning them into locale-based strings for display to the user. .Pp For strings, the 'h' and 'l' modifiers affect the interpretation of -the bytes pointed to argument. The default '%s' string is a 'char *' -pointer to a string encoded as UTF-8. Since UTF-8 is compatible with +the bytes pointed to argument. +The default '%s' string is a 'char *' +pointer to a string encoded as UTF-8. +Since UTF-8 is compatible with .Em ASCII data, a normal 7-bit .Em ASCII - string can be used. '%ls' expects a -'wchar_t *' pointer to a wide-character string, encoded as a 32-bit -Unicode values. '%hs' expects a 'char *' pointer to a multi-byte +string can be used. +'%ls' expects a +'wchar_t *' pointer to a wide-character string, encoded as 32-bit +Unicode values. +'%hs' expects a 'char *' pointer to a multi-byte string encoded with the current locale, as given by the -.Em LC_CTYPE , -.Em LANG , +.Ev LC_CTYPE , +.Ev LANG , or -.Em LC_ALL -environment varibles. The first of this list of -variables is used and if none of the variables, the locale defaults to -.Em UTF-8. -.Pp -libxo will +.Ev LC_ALL +environment variables. +The first of this list of +variables is used and if none of the variables are set, the locale defaults to +.Em UTF-8 . +.Pp +.Nm libxo +will convert these arguments as needed to either UTF-8 (for XML, JSON, and HTML styles) or locale-based strings for display in text style. .Bd -literal -offset indent - xo_emit("Alll strings are utf-8 content {:tag/%ls}", + xo_emit("All strings are utf-8 content {:tag/%ls}", L"except for wide strings"); .Ed .Pp "%S" is equivalent to "%ls". .Pp For example, a function is passed a locale-base name, a hat size, -and a time value. The hat size is formatted in a UTF-8 (ASCII) +and a time value. +The hat size is formatted in a UTF-8 (ASCII) string, and the time value is formatted into a wchar_t string. .Bd -literal -offset indent void print_order (const char *name, int size, @@ -475,29 +542,35 @@ string, and the time value is formatted into a wchar_t string. } .Ed .Pp -It is important to note that xo_emit will perform the conversion -required to make appropriate output. Text style output uses the +It is important to note that +.Xr xo_emit 3 +will perform the conversion +required to make appropriate output. +Text style output uses the current locale (as described above), while XML, JSON, and HTML use UTF-8. .Pp UTF-8 and locale-encoded strings can use multiple bytes to encode one -column of data. The traditional "precision'" (aka "max-width") value +column of data. +The traditional "precision'" (aka "max-width") value for "%s" printf formatting becomes overloaded since it specifies both the number of bytes that can be safely referenced and the maximum -number of columns to emit. xo_emit uses the precision as the former, +number of columns to emit. +.Xr xo_emit 3 +uses the precision as the former, and adds a third value for specifying the maximum number of columns. .Pp In this example, the name field is printed with a minimum of 3 columns -and a maximum of 6. Up to ten bytes are in used in filling those -columns. +and a maximum of 6. +Up to ten bytes are in used in filling those columns. .Bd -literal -offset indent xo_emit("{:name/%3.10.6s}", name); .Ed .Ss Characters Outside of Field Definitions -Characters in the format string are not part of a field definition are +Characters in the format string that are not part of a field definition are copied to the output for the TEXT style, and are ignored for the JSON -and XML styles. For HTML, these characters are placed in a <div> with -class "text". +and XML styles. +For HTML, these characters are placed in a <div> with class "text". .Bd -literal -offset indent EXAMPLE: xo_emit("The hat is {:size/%s}.\\n", size_val); @@ -513,13 +586,16 @@ class "text". <div class="text">.</div> .Ed .Ss "%n" is Not Supported -libxo does not support the '%n' directive. It's a bad idea and we -just don't do it. +.Nm libxo +does not support the '%n' directive. +It is a bad idea and we +just do not do it. .Ss The Encoding Format (eformat) The "eformat" string is the format string used when encoding the field -for JSON and XML. If not provided, it defaults to the primary format -with any minimum width removed. If the primary is not given, both -default to "%s". +for JSON and XML. +If not provided, it defaults to the primary format +with any minimum width removed. +If the primary is not given, both default to "%s". .Sh EXAMPLE In this example, the value for the number of items in stock is emitted: .Bd -literal -offset indent @@ -547,9 +623,9 @@ This call will generate the following output: .Pp Clearly HTML wins the verbosity award, and this output does not include -.Em XOF_XPATH +.Dv XOF_XPATH or -.Em XOF_INFO +.Dv XOF_INFO data, which would expand the penultimate line to: .Bd -literal -offset indent <div class="data" data-tag="in-stock" @@ -561,28 +637,33 @@ data, which would expand the penultimate line to: To make useful, consistent field names, follow these guidelines: .Pp .Ss Use lower case, even for TLAs -Lower case is more civilized. Even TLAs should be lower case +Lower case is more civilized. +Even TLAs should be lower case to avoid scenarios where the differences between "XPath" and -"Xpath" drive your users crazy. Using "xpath" is simpler and better. +"Xpath" drive your users crazy. +Using "xpath" is simpler and better. .Ss Use hyphens, not underscores Use of hyphens is traditional in XML, and the -.Em XOF_UNDERSCORES +.Dv XOF_UNDERSCORES flag can be used to generate underscores in JSON, if desired. But the raw field name should use hyphens. -.Se Use full words -Don't abbreviate especially when the abbreviation is not obvious or -not widely used. Use "data-size", not "dsz" or "dsize". Use +.Ss Use full words +Do not abbreviate especially when the abbreviation is not obvious or +not widely used. +Use "data-size", not "dsz" or "dsize". +Use "interface" instead of "ifname", "if-name", "iface", "if", or "intf". -.Se Use <verb>-<units> +.Ss Use <verb>-<units> Using the form <verb>-<units> or <verb>-<classifier>-<units> helps in making consistent, useful names, avoiding the situation where one app uses "sent-packet" and another "packets-sent" and another -"packets-we-have-sent". The <units> can be dropped when it is +"packets-we-have-sent". +The <units> can be dropped when it is obvious, as can obvious words in the classification. Use "receive-after-window-packets" instead of "received-packets-of-data-after-window". -.Se Reuse existing field names -Nothing's worse than writing expressions like: +.Ss Reuse existing field names +Nothing is worse than writing expressions like: .Bd -literal -offset indent if ($src1/process[pid == $pid]/name == $src2/proc-table/proc/p[process-id == $pid]/proc-name) { @@ -591,32 +672,38 @@ Nothing's worse than writing expressions like: .Ed .Pp Find someone else who is expressing similar data and follow their -field's and hierarchy. Remember the quote is not +fields and hierarchy. +Remember the quote is not .Dq Consistency is the hobgoblin of little minds but -.Dq A foolish consistency is the hobgoblin of little minds. +.Dq A foolish consistency is the hobgoblin of little minds . .Ss Think about your users Have empathy for your users, choosing clear and useful fields that -contain clear and useful data. You may need to augment the display -content with +contain clear and useful data. +You may need to augment the display content with .Xr xo_attr 3 calls or "{e:}" fields to make the data useful. -.Ss Don't use an arbitrary number postfix -What does "errors2" mean? No one will know. "errors-after-restart" -would be a better choice. Think of you users, and think of the -future. If you make "errors2", the next guy will happily make -"errors3" and before you know it, someone will be asking what's the +.Ss Do not use an arbitrary number postfix +What does "errors2" mean? +No one will know. +"errors-after-restart" would be a better choice. +Think of your users, and think of the future. +If you make "errors2", the next guy will happily make +"errors3" and before you know it, someone will be asking what is the difference between errors37 and errors63. .Ss Be consistent, uniform, unsurprising, and predictable -Think of your field vocabulary as an API. You want it useful, -expressive, meaningful, direct, and obvious. You want the client +Think of your field vocabulary as an API. +You want it useful, +expressive, meaningful, direct, and obvious. +You want the client application's programmer to move between without the need to -understand a variety of opinions on how fields are named. They should +understand a variety of opinions on how fields are named. +They should see the system as a single cohesive whole, not a sack of cats. .Pp Field names constitute the means by which client programmers interact -with our system. By choosing wise names now, you are making their -lives better. +with our system. +By choosing wise names now, you are making their lives better. .Pp After using .Xr xolint 1 @@ -628,30 +715,36 @@ names for the same data. and .Dq dropped-too-short are both reasonable names, but using them both will lead users to ask the -difference between the two fields. If there isn't a difference, -use only one of the field names. If there is a difference, change the +difference between the two fields. +If there is no difference, +use only one of the field names. +If there is a difference, change the names to make that difference more obvious. .Sh ADDITIONAL DOCUMENTATION -.Pp Complete documentation can be found on github: .Bd -literal -offset indent http://juniper.github.io/libxo/libxo-manual.html .Ed .Pp -libxo lives on github as: +.Nm libxo +lives on github as: .Bd -literal -offset indent https://github.com/Juniper/libxo .Ed .Pp -The latest release of libxo is available at: +The latest release of +.Nm libxo +is available at: .Bd -literal -offset indent https://github.com/Juniper/libxo/releases .Ed .Sh SEE ALSO +.Xr xolint 1 , .Xr xo_emit 3 .Sh HISTORY The -.Fa libxo -library was added in FreeBSD 11.0. +.Nm libxo +library was added in +.Fx 11.0 . .Sh AUTHOR Phil Shafer diff --git a/contrib/libxo/libxo/xo_no_setlocale.3 b/contrib/libxo/libxo/xo_no_setlocale.3 index 94a1264..c3f32a4 100644 --- a/contrib/libxo/libxo/xo_no_setlocale.3 +++ b/contrib/libxo/libxo/xo_no_setlocale.3 @@ -7,12 +7,13 @@ .\" # LICENSE. .\" # Phil Shafer, July 2014 .\" -.Dd July, 2014 +.Dd December 4, 2014 .Dt LIBXO 3 .Os .Sh NAME .Nm xo_no_setlocale -.Nd prevent implicit call to setlocale() +.Nd prevent implicit call to +.Fn setlocale .Sh LIBRARY .Lb libxo .Sh SYNOPSIS @@ -20,44 +21,48 @@ .Ft void .Fn xo_no_setlocale "void" .Sh DESCRIPTION -.Em libxo -automatically initializes the locale based on setting of the +.Nm libxo +automatically initializes the locale based on the setting of the environment variables -.Em LC_CTYPE , -.Em LANG , +.Ev LC_CTYPE , +.Ev LANG , and -.Em LC_ALL . +.Ev LC_ALL . The first of this -list of variables is used and if none of the variables, the locale +list of variables is used and if none of the variables are set, the locale defaults to -.Em UTF-8. The caller may wish to avoid this behavior, and +.Em UTF-8 . +The caller may wish to avoid this behavior, and can do so by calling the .Fn xo_no_setlocale function. .Sh ADDITIONAL DOCUMENTATION -.Pp Complete documentation can be found on github: .Bd -literal -offset indent http://juniper.github.io/libxo/libxo-manual.html .Ed .Pp -libxo lives on github as: +.Nm libxo +lives on github as: .Bd -literal -offset indent https://github.com/Juniper/libxo .Ed .Pp -The latest release of libxo is available at: +The latest release of +.Nm libxo +is available at: .Bd -literal -offset indent https://github.com/Juniper/libxo/releases .Ed .Sh SEE ALSO .Xr xo_emit 3 , .Xr xo_open_container 3 , -.Xr xo_open_list 3 , and -.Xr xo_format 5 . +.Xr xo_open_list 3 , +.Xr xo_format 5 .Sh HISTORY The -.Fa libxo -library was added in FreeBSD 11.0. +.Nm libxo +library was added in +.Fx 11.0 . .Sh AUTHOR Phil Shafer diff --git a/contrib/libxo/libxo/xo_open_container.3 b/contrib/libxo/libxo/xo_open_container.3 index 9ba32c9..86412ca 100644 --- a/contrib/libxo/libxo/xo_open_container.3 +++ b/contrib/libxo/libxo/xo_open_container.3 @@ -7,7 +7,7 @@ .\" # LICENSE. .\" # Phil Shafer, July 2014 .\" -.Dd July, 2014 +.Dd December 4, 2014 .Dt LIBXO 3 .Os .Sh NAME @@ -47,13 +47,14 @@ .Ft int .Fn xo_close_container_d "void" .Sh DESCRIPTION -.Fa libxo +.Nm libxo represents to types of hierarchy: .Dq containers and .Dq lists . A container appears once under a given parent where a list contains -instances that can appear multiple times. A container is used to hold +instances that can appear multiple times. +A container is used to hold related fields and to give the data organization and scope. The container has no value, but serves to contain other nodes. @@ -71,8 +72,9 @@ or .Fn xo_close_container_h functions. .Pp -Each open call must have a matching close call. If the -.Fa XOF_WARN +Each open call must have a matching close call. +If the +.Dv XOF_WARN flag is set and the name given does not match the name of the currently open container, a warning will be generated. @@ -115,8 +117,8 @@ The .Fa handle parameter contains a handle such as returned by .Xr xo_create 3 -or a -.Em NULL +or +.Dv NULL to use the default handle. The .Fa name @@ -134,18 +136,18 @@ suffix are used in .Dq \&Do The Right Thing mode, where the name of the open containers, lists, and instances are maintained internally by -.Em libxo +.Nm libxo to allow the caller to avoid keeping track of the open container name. .Pp Use the -.Em XOF_WARN +.Dv XOF_WARN flag to generate a warning if the name given on the close does not match the current open container. .Pp For TEXT and HTML output, containers are not rendered into output text, though for HTML they are used when the -.Em XOF_XPATH +.Dv XOF_XPATH flag is set. .Pp .Bd -literal -offset indent -compact @@ -157,21 +159,22 @@ flag is set. <system><host-name>foo</host-name></system> .Ed .Sh DTRT MODE -Some user may find tracking the names of open containers, lists, and +Some users may find tracking the names of open containers, lists, and instances inconvenient. -.Em libxo -offers +.Nm libxo +offers a .Dq \&Do The Right Thing mode, where -.Em libxo +.Nm libxo will track the names of open containers, lists, and instances so -the close function can be called without a name. To enable +the close function can be called without a name. +To enable .Em DTRT mode, turn on the -.Em XOF_DTRT +.Dv XOF_DTRT flag prior to making any other -.Em libxo +.Nm libxo output. .Bd -literal -offset indent -compact xo_set_flags(NULL, XOF_DTRT); @@ -185,24 +188,28 @@ which will close the open container, list, or instance: xo_close_container_d(); .Ed Note that the -.Em XOF_WARN -flag will also cause libxo to track open +.Dv XOF_WARN +flag will also cause +.Nm libxo +to track open containers, lists, and instances. -A warning is generated with the name given to the close function +A warning is generated when the name given to the close function and the name recorded do not match. .Sh ADDITIONAL DOCUMENTATION -.Pp Complete documentation can be found on github: .Bd -literal -offset indent http://juniper.github.io/libxo/libxo-manual.html .Ed .Pp -libxo lives on github as: +.Nm libxo +lives on github as: .Bd -literal -offset indent https://github.com/Juniper/libxo .Ed .Pp -The latest release of libxo is available at: +The latest release of +.Nm libxo +is available at: .Bd -literal -offset indent https://github.com/Juniper/libxo/releases .Ed @@ -210,7 +217,8 @@ https://github.com/Juniper/libxo/releases .Xr xo_emit 3 .Sh HISTORY The -.Fa libxo -library was added in FreeBSD 11.0. +.Nm libxo +library was added in +.Fx 11.0 . .Sh AUTHOR Phil Shafer diff --git a/contrib/libxo/libxo/xo_open_list.3 b/contrib/libxo/libxo/xo_open_list.3 index 9a6a215..047af87 100644 --- a/contrib/libxo/libxo/xo_open_list.3 +++ b/contrib/libxo/libxo/xo_open_list.3 @@ -7,7 +7,7 @@ .\" # LICENSE. .\" # Phil Shafer, July 2014 .\" -.Dd July, 2014 +.Dd December 4, 2014 .Dt LIBXO 3 .Os .Sh NAME @@ -71,19 +71,23 @@ .Ft int .Fn xo_close_list_d "void" .Sh DESCRIPTION -Lists are sequences of instances of homogeneous data objects. Two +Lists are sequences of instances of homogeneous data objects. +Two distinct levels of calls are needed to represent them in our output -styles. Calls must be made to open and close a list, and for each +styles. +Calls must be made to open and close a list, and for each instance of data in that list, calls must be make to open and close that instance. .Pp -The name given to all calls must be identical, and it is strong +The name given to all calls must be identical, and it is strongly suggested that the name be singular, not plural, as a matter of style and usage expectations. .Pp -A list is set of one or more instances that appear under the same -parent. The instances contains details about a specific object. One -can think of instances as objects or records. A call is needed to +A list is a set of one or more instances that appear under the same +parent. +The instances contain details about a specific object. +One can think of instances as objects or records. +A call is needed to open and close the list, while a distinct call is needed to open and close each instance of the list: .Bd -literal -offset indent -compact @@ -143,19 +147,45 @@ generation of XML and JSON data. } ] .Ed -.Sh ADDITIONAL DOCUMENTATION .Pp +.Sh LEAF LISTS +In contrast to a list of instances, a "leaf list" is list of simple +values. +To emit a leaf list, call the +.Fn xo_emit +function using the ""l"" modifier: +.Bd -literal -offset indent -compact + for (ip = list; ip->i_title; ip++) { + xo_emit("{Lwc:Item}{l:item}\n", ip->i_title); + } +.Ed +.Pp +The name of the field must match the name of the leaf list. +.Pp +In JSON, leaf lists are rendered as arrays of values. In XML, they +are rendered as multiple leaf elements. +.Bd -literal -offset indent -compact + JSON: + "item": "hammer", "nail" + XML: + <item>hammer</item> + <item>nail</item> +.Ed +.Sh ADDITIONAL DOCUMENTATION Complete documentation can be found on github: .Bd -literal -offset indent http://juniper.github.io/libxo/libxo-manual.html .Ed .Pp -libxo lives on github as: +.Nm libxo +lives on github as: .Bd -literal -offset indent https://github.com/Juniper/libxo .Ed .Pp -The latest release of libxo is available at: +The latest release of +.Nm libxo +is available at: .Bd -literal -offset indent https://github.com/Juniper/libxo/releases .Ed @@ -163,7 +193,8 @@ https://github.com/Juniper/libxo/releases .Xr xo_emit 3 .Sh HISTORY The -.Fa libxo -library was added in FreeBSD 11.0. +.Nm libxo +library was added in +.Fx 11.0 . .Sh AUTHOR Phil Shafer diff --git a/contrib/libxo/libxo/xo_parse_args.3 b/contrib/libxo/libxo/xo_parse_args.3 index a9b4cec..f66546b 100644 --- a/contrib/libxo/libxo/xo_parse_args.3 +++ b/contrib/libxo/libxo/xo_parse_args.3 @@ -7,27 +7,31 @@ .\" # LICENSE. .\" # Phil Shafer, July 2014 .\" -.Dd July, 2014 +.Dd December 4, 2014 .Dt LIBXO 3 .Os .Sh NAME .Nm xo_parse_args .Nd detect, parse, and remove arguments for libxo .Sh LIBRARY -.Nm libxo +.Lb libxo .Sh SYNOPSIS .In libxo/xo.h .Ft int .Fn xo_parse_args "int argc" "char **argv" +.Ft int +.Fn xo_set_program "const char *name" .Sh DESCRIPTION The .Fn xo_parse_args function is used to process command-line arguments. -.Em libxo -specific +.Nm libxo +specific options are processed and removed from the argument list so the calling application does not -need to process them. If successful, a new value for argc -is returned. On failure, a message it emitted and -1 is returned. +need to process them. +If successful, a new value for argc is returned. +On failure, a message it emitted and -1 is returned. .Bd -literal -offset indent argc = xo_parse_args(argc, argv); if (argc < 0) @@ -38,9 +42,9 @@ Following the call to .Fn xo_parse_args , the application can process the remaining arguments in a normal manner. .Pp -.Em libxo -uses command line options to trigger rendering behavior. The -following options are recognised: +.Nm libxo +uses command line options to trigger rendering behavior. +The following options are recognised: .Pp .Bl -tag -width "--libxo" .It @@ -56,44 +60,45 @@ styles, flags, or features: .Pp .Bl -tag -width "12345678" .It Sy "Token Action" -.It dtrt +.It Dv dtrt Enable "Do The Right Thing" mode -.It html +.It Dv html Emit HTML output -.It indent=xx +.It Dv indent=xx Set the indentation level -.It info +.It Dv info Add info attributes (HTML) -.It json +.It Dv json Emit JSON output -.It keys +.It Dv keys Emit the key attribute for keys (XML) -.It no-locale +.It Dv no-locale Do not initialize the locale setting -.It no-top +.It Dv no-top Do not emit a top set of braces (JSON) -.It not-first +.It Dv not-first Pretend the 1st output item was not 1st (JSON) -.It pretty +.It Dv pretty Emit pretty-printed output -.It text +.It Dv text Emit TEXT output -.It units +.It Dv units Add the 'units' (XML) or 'data-units (HTML) attribute -.It warn +.It Dv warn Emit warnings when libxo detects bad calls -.It warn-xml +.It Dv warn-xml Emit warnings in XML -.It xml +.It Dv xml Emit XML output -.It xpath +.It Dv xpath Add XPath expressions (HTML) .El .Pp The .Dq brief-options are single letter commands, designed for those with -too little patience to use real tokens. No comma separator is used. +too little patience to use real tokens. +No comma separator is used. .Bl -column "i<num>" .It Sy "Token Action" .It "H " "Enable HTML output (XO_STYLE_HTML)" @@ -107,19 +112,41 @@ too little patience to use real tokens. No comma separator is used. .It "x " "Enable XPath data (XOF_XPATH)" .El .Pp -.Sh ADDITIONAL DOCUMENTATION +The +.Fn xo_set_program +function sets name of the program as reported by +functions like +.Fn xo_failure , +.Fn xo_warn , +.Fn xo_err , +etc. +The program name is initialized by +.Fn xo_parse_args , +but subsequent calls to +.Fn xo_set_program +can override this value. +.Pp +Note that the value is not copied, so the memory passed to +.Fn xo_set_program +(and +.Fn xo_parse_args ) +must be maintained by the caller. .Pp +.Sh ADDITIONAL DOCUMENTATION Complete documentation can be found on github: .Bd -literal -offset indent http://juniper.github.io/libxo/libxo-manual.html .Ed .Pp -libxo lives on github as: +.Nm libxo +lives on github as: .Bd -literal -offset indent https://github.com/Juniper/libxo .Ed .Pp -The latest release of libxo is available at: +The latest release of +.Nm libxo +is available at: .Bd -literal -offset indent https://github.com/Juniper/libxo/releases .Ed @@ -127,7 +154,8 @@ https://github.com/Juniper/libxo/releases .Xr xo_emit 3 .Sh HISTORY The -.Fa libxo -library was added in FreeBSD 11.0. +.Nm libxo +library was added in +.Fx 11.0 . .Sh AUTHOR Phil Shafer diff --git a/contrib/libxo/libxo/xo_set_allocator.3 b/contrib/libxo/libxo/xo_set_allocator.3 index 508cc8e..70bfdd5 100644 --- a/contrib/libxo/libxo/xo_set_allocator.3 +++ b/contrib/libxo/libxo/xo_set_allocator.3 @@ -7,7 +7,7 @@ .\" # LICENSE. .\" # Phil Shafer, July 2014 .\" -.Dd July, 2014 +.Dd December 4, 2014 .Dt LIBXO 3 .Os .Sh NAME @@ -25,7 +25,9 @@ .Sh DESCRIPTION The .Fn xo_set_allocator -function allows libxo to be used in environments +function allows +.Nm libxo +to be used in environments where the standard .Xr realloc 3 and @@ -40,7 +42,7 @@ a pointer to memory following the same convention. .Fa free_func will receive the same argument as .Xr free 3 -and should release it, asappropriate for the environment. +and should release it, as appropriate for the environment. .Pp By default, the standard .Xr realloc 3 @@ -48,18 +50,20 @@ and .Xr free 3 functions are used. .Sh ADDITIONAL DOCUMENTATION -.Pp Complete documentation can be found on github: .Bd -literal -offset indent http://juniper.github.io/libxo/libxo-manual.html .Ed .Pp -libxo lives on github as: +.Nm libxo +lives on github as: .Bd -literal -offset indent https://github.com/Juniper/libxo .Ed .Pp -The latest release of libxo is available at: +The latest release of +.Nm libxo +is available at: .Bd -literal -offset indent https://github.com/Juniper/libxo/releases .Ed @@ -67,7 +71,8 @@ https://github.com/Juniper/libxo/releases .Xr xo_emit 3 .Sh HISTORY The -.Fa libxo -library was added in FreeBSD 11.0. +.Nm libxo +library was added in +.Fx 11.0 . .Sh AUTHOR Phil Shafer diff --git a/contrib/libxo/libxo/xo_set_flags.3 b/contrib/libxo/libxo/xo_set_flags.3 index a23de7b..ca66553 100644 --- a/contrib/libxo/libxo/xo_set_flags.3 +++ b/contrib/libxo/libxo/xo_set_flags.3 @@ -7,7 +7,7 @@ .\" # LICENSE. .\" # Phil Shafer, July 2014 .\" -.Dd July, 2014 +.Dd December 4, 2014 .Dt LIBXO 3 .Os .Sh NAME @@ -25,96 +25,121 @@ Use the .Fn xo_set_flags function to set the flags for a -.Em libxo -handle. To use the default handle, pass a NULL handle. +.Nm libxo +handle. +To use the default handle, pass a +.Dv NULL +handle. .Pp The set of valid flags include: .Bl -tag -width "XOF_UNDERSCORES" .It Sy "Flag Description" -.It XOF_CLOSE_FP -Close file pointer on xo_destroy(). This -flag will trigger the call of the close_func +.It Dv XOF_CLOSE_FP +Close file pointer on +.Xr xo_destroy 3 . +This flag will trigger the call of the +.Fn close_func (provided via -.Fn xo_set_writer 3 ) +.Xr xo_set_writer 3 ) when the handle is destroyed. -.It XOF_DTRT +.It Dv XOF_DTRT Enable "do the right thing" mode -.It XOF_INFO +.It Dv XOF_INFO Display info data attributes (HTML) -.It XOF_KEYS +.It Dv XOF_KEYS Emit the key attribute (XML) -.It XOF_NO_ENV -Do not use the LIBXO_OPTIONS env var -.It XOF_PRETTY +.It Dv XOF_NO_ENV +Do not use the +.Ev LIBXO_OPTIONS +environment variable. +.It Dv XOF_PRETTY Make 'pretty printed' output, with the addition of indentation and newlines to enhance the readability of -XML, JSON, and HTML output. Text output is not affected. -.It XOF_UNDERSCORES +XML, JSON, and HTML output. +Text output is not affected. +.It Dv XOF_UNDERSCORES Replaces hyphens with underscores -.It XOF_UNITS +.It Dv XOF_UNITS Display units (XML and HMTL) -.It XOF_WARN +.It Dv XOF_WARN Generate warnings for broken calls, triggering diagnostic output (on standard error) when the library notices errors during -operations, or with arguments to functions. Without warning enabled, -such conditions are ignored. -Warnings allow developers to debug their interaction with libxo. -The function "xo_failure" can used as a breakpoint for a debugger, +operations, or with arguments to functions. +Without warnings enabled, such conditions are ignored. +Warnings allow developers to debug their interaction with +.Nm libxo . +The function +.Fn xo_failure +can be used as a breakpoint for a debugger, regardless of whether warnings are enabled. -.It XOF_WARN_XML +.It Dv XOF_WARN_XML Generate warnings in XML on stdout -.It XOF_XPATH +.It Dv XOF_XPATH Emit XPath expressions (HTML) -.It XOF_COLUMNS -Force xo_emit to return columns used -.It XOF_FLUSH -Flush output after each xo_emit call +.It Dv XOF_COLUMNS +Force +.Xr xo_emit 3 +to return columns used +.It Dv XOF_FLUSH +Flush output after each +.Xr xo_emit 3 +call .El .Pp -If the style is XO_STYLE_HTML, the following additional flags can be +If the style is +.Dv XO_STYLE_HTML , +the following additional flags can be used: .Bl -tag -width "XOF_UNDERSCORES" .It Sy "Flag Description" -.It XOF_XPATH +.It Dv XOF_XPATH Emit "data-xpath" attributes -.It XOF_INFO +.It Dv XOF_INFO Emit additional informational fields for HTML -output. See +output. +See .Xr xo_set_info 3 for details. .El .Pp The -.Em XOF_XPATH +.Dv XOF_XPATH flag enables the emission of XPath expressions detailing the hierarchy of XML elements used to encode the data field, if the XPATH style of output were requested. .Pp -If the style is XO_STYLE_XML, the following additional flags can be +If the style is +.Dv XO_STYLE_XML , +the following additional flags can be used: .Bl -tag -width "XOF_UNDERSCORES" .It Sy "Flag Description" .It XOF_KEYS Add 'key' attribute to the XML encoding for -field definitions that use the 'k' modifier. The key attribute has +field definitions that use the 'k' modifier. +The key attribute has the value "key". .El .Pp -The xo_clear_flags() function turns off the given flags in a specific +The +.Fn xo_clear_flags +function turns off the given flags in a specific handle. .Sh ADDITIONAL DOCUMENTATION -.Pp Complete documentation can be found on github: .Bd -literal -offset indent http://juniper.github.io/libxo/libxo-manual.html .Ed .Pp -libxo lives on github as: +.Nm libxo +lives on github as: .Bd -literal -offset indent https://github.com/Juniper/libxo .Ed .Pp -The latest release of libxo is available at: +The latest release of +.Nm libxo +is available at: .Bd -literal -offset indent https://github.com/Juniper/libxo/releases .Ed @@ -122,7 +147,8 @@ https://github.com/Juniper/libxo/releases .Xr xo_emit 3 .Sh HISTORY The -.Fa libxo -library was added in FreeBSD 11.0. +.Nm libxo +library was added in +.Fx 11.0 . .Sh AUTHOR Phil Shafer diff --git a/contrib/libxo/libxo/xo_set_info.3 b/contrib/libxo/libxo/xo_set_info.3 index dbb3c9c..4f8c587 100644 --- a/contrib/libxo/libxo/xo_set_info.3 +++ b/contrib/libxo/libxo/xo_set_info.3 @@ -7,7 +7,7 @@ .\" # LICENSE. .\" # Phil Shafer, July 2014 .\" -.Dd July, 2014 +.Dd December 4, 2014 .Dt LIBXO 3 .Os .Sh NAME @@ -21,19 +21,23 @@ .Fn xo_set_info "xo_handle_t *handle" "xo_info_t *info" "int count" .Sh DESCRIPTION HTML data can include additional information in attributes that -begin with "data-". To enable this, three things must occur: +begin with "data-". +To enable this, three things must occur: .Pp -First the application must build an array of xo_info_t structures, -one per tag. The array must be sorted by name, since -.Em libxo +First the application must build an array of +.Dv xo_info_t +structures, +one per tag. +The array must be sorted by name, since +.Nm libxo uses a binary search to find the entry that matches names from format instructions. .Pp The -.Em xo_info_t +.Dv xo_info_t structure is defined in -.Em <libxo/xo.h> : +.In libxo/xo.h : .Bd -literal -offset indent typedef struct xo_info_s { const char *xi_name; /* Name of the element */ @@ -43,21 +47,27 @@ structure is defined in .Ed .Pp Second, the application must inform -.Em libxo +.Nm libxo about this information using the .Fn xo_set_info -call. Like other libxo calls, passing NULL for the handle tells -.Em libxo +call. +Like other +.Nm libxo +calls, passing +.Dv NULL +for the handle tells +.Nm libxo to use the default handle. .Pp If the .Fa count is -1, -.Em libxo +.Nm libxo will count the elements of .Fa info , but there -must be an empty element at the end. More typically, the number is +must be an empty element at the end. +More typically, the number is known to the application: .Bd -literal -offset indent xo_info_t info[] = { @@ -72,8 +82,8 @@ known to the application: xo_set_info(NULL, info, info_count); .Ed .Pp -Third, the emitting of info must be triggered with the -.Em XOF_INFO +Third, the emission of info must be triggered with the +.Dv XOF_INFO flag using either the .Fn xo_set_flags @@ -88,18 +98,20 @@ and "data-help" attributes: data-help="Stock Keeping Unit">GRO-000-533</div> .Ed .Sh ADDITIONAL DOCUMENTATION -.Pp Complete documentation can be found on github: .Bd -literal -offset indent http://juniper.github.io/libxo/libxo-manual.html .Ed .Pp -libxo lives on github as: +.Nm libxo +lives on github as: .Bd -literal -offset indent https://github.com/Juniper/libxo .Ed .Pp -The latest release of libxo is available at: +The latest release of +.Nm libxo +is available at: .Bd -literal -offset indent https://github.com/Juniper/libxo/releases .Ed @@ -107,7 +119,8 @@ https://github.com/Juniper/libxo/releases .Xr xo_emit 3 .Sh HISTORY The -.Fa libxo -library was added in FreeBSD 11.0. +.Nm libxo +library was added in +.Fx 11.0 . .Sh AUTHOR Phil Shafer diff --git a/contrib/libxo/libxo/xo_set_options.3 b/contrib/libxo/libxo/xo_set_options.3 index af7e95c..bedbf91 100644 --- a/contrib/libxo/libxo/xo_set_options.3 +++ b/contrib/libxo/libxo/xo_set_options.3 @@ -7,12 +7,12 @@ .\" # LICENSE. .\" # Phil Shafer, July 2014 .\" -.Dd July, 2014 +.Dd December 4, 2014 .Dt LIBXO 3 .Os .Sh NAME -.Nm xo_emit -.Nd emit formatted output based on format string and arguments +.Nm xo_set_options +.Nd change options used by a handle .Sh LIBRARY .Lb libxo .Sh SYNOPSIS @@ -27,18 +27,20 @@ and flags and enables them for a specific handle. The options are identical to those listed in .Xr xo_parse_args 3 . .Sh ADDITIONAL DOCUMENTATION -.Pp Complete documentation can be found on github: .Bd -literal -offset indent http://juniper.github.io/libxo/libxo-manual.html .Ed .Pp -libxo lives on github as: +.Nm libxo +lives on github as: .Bd -literal -offset indent https://github.com/Juniper/libxo .Ed .Pp -The latest release of libxo is available at: +The latest release of +.Nm libxo +is available at: .Bd -literal -offset indent https://github.com/Juniper/libxo/releases .Ed @@ -46,7 +48,8 @@ https://github.com/Juniper/libxo/releases .Xr xo_emit 3 .Sh HISTORY The -.Fa libxo -library was added in FreeBSD 11.0. +.Nm libxo +library was added in +.Fx 11.0 . .Sh AUTHOR Phil Shafer diff --git a/contrib/libxo/libxo/xo_set_style.3 b/contrib/libxo/libxo/xo_set_style.3 index 83371ac..f11f190 100644 --- a/contrib/libxo/libxo/xo_set_style.3 +++ b/contrib/libxo/libxo/xo_set_style.3 @@ -7,7 +7,7 @@ .\" # LICENSE. .\" # Phil Shafer, July 2014 .\" -.Dd July, 2014 +.Dd December 4, 2014 .Dt LIBXO 3 .Os .Sh NAME @@ -25,9 +25,11 @@ Use the .Fn xo_set_style function to set the output style for a handle. -To use the default handle, pass a NULL handle. +To use the default handle, pass a +.Dv NULL +handle. The set of output styles used by -.Em libxo +.Nm libxo is: .Bl -column "XO_STYLE_TEXT12" .It Sy "Flag Description" @@ -47,18 +49,20 @@ The name can be any of the styles: "text", "xml", "json", or "html". xo_set_style_name(NULL, "html"); .Ed .Sh ADDITIONAL DOCUMENTATION -.Pp Complete documentation can be found on github: .Bd -literal -offset indent http://juniper.github.io/libxo/libxo-manual.html .Ed .Pp -libxo lives on github as: +.Nm libxo +lives on github as: .Bd -literal -offset indent https://github.com/Juniper/libxo .Ed .Pp -The latest release of libxo is available at: +The latest release of +.Nm libxo +is available at: .Bd -literal -offset indent https://github.com/Juniper/libxo/releases .Ed @@ -66,7 +70,8 @@ https://github.com/Juniper/libxo/releases .Xr xo_emit 3 .Sh HISTORY The -.Fa libxo -library was added in FreeBSD 11.0. +.Nm libxo +library was added in +.Fx 11.0 . .Sh AUTHOR Phil Shafer diff --git a/contrib/libxo/libxo/xo_set_writer.3 b/contrib/libxo/libxo/xo_set_writer.3 index 9185f10..942bcc2 100644 --- a/contrib/libxo/libxo/xo_set_writer.3 +++ b/contrib/libxo/libxo/xo_set_writer.3 @@ -7,7 +7,7 @@ .\" # LICENSE. .\" # Phil Shafer, July 2014 .\" -.Dd July, 2014 +.Dd December 4, 2014 .Dt LIBXO 3 .Os .Sh NAME @@ -21,9 +21,12 @@ .Sy typedef int (*xo_write_func_t)(void *, const char *); .Pp .Sy typedef void (*xo_close_func_t)(void *); +.Pp +.Sy typedef int (*xo_flush_func_t)(void *); .Fn xo_set_writer "xo_handle_t *handle" "void *opaque" "xo_write_func_t write_func" "xo_close_func_t close_func" + "xo_flush_func_t flush_func" .Sh DESCRIPTION The .Fn xo_set_writer @@ -31,30 +34,38 @@ function allows custom .Dq write functions which can tailor how -.Em libxo -writes data. An +.Nm libxo +writes data. +An .Fa opaque argument is recorded and passed back to the .Fa write_func function, allowing the function -to acquire context information. The +to acquire context information. +The .Fa close_func function can release this opaque data and any other resources as needed. +The +.Fa flush_func +function should +flush any pending data associated with the opaque pointer. .Sh ADDITIONAL DOCUMENTATION -.Pp Complete documentation can be found on github: .Bd -literal -offset indent http://juniper.github.io/libxo/libxo-manual.html .Ed .Pp -libxo lives on github as: +.Nm libxo +lives on github as: .Bd -literal -offset indent https://github.com/Juniper/libxo .Ed .Pp -The latest release of libxo is available at: +The latest release of +.Nm libxo +is available at: .Bd -literal -offset indent https://github.com/Juniper/libxo/releases .Ed @@ -62,7 +73,8 @@ https://github.com/Juniper/libxo/releases .Xr xo_emit 3 .Sh HISTORY The -.Fa libxo -library was added in FreeBSD 11.0. +.Nm libxo +library was added in +.Fx 11.0 . .Sh AUTHOR Phil Shafer diff --git a/contrib/libxo/libxo/xoconfig.h b/contrib/libxo/libxo/xoconfig.h index 0870e35..4c596b4 100644 --- a/contrib/libxo/libxo/xoconfig.h +++ b/contrib/libxo/libxo/xoconfig.h @@ -87,6 +87,9 @@ /* Define to 1 if you have the <stdint.h> header file. */ #define HAVE_STDINT_H 1 +/* Define to 1 if you have the <stdio_ext.h> header file. */ +/* #undef HAVE_STDIO_EXT_H */ + /* Define to 1 if you have the <stdio.h> header file. */ #define HAVE_STDIO_H 1 @@ -141,6 +144,9 @@ /* Define to 1 if you have the <unistd.h> header file. */ #define HAVE_UNISTD_H 1 +/* Define to 1 if you have the `__flbf' function. */ +/* #undef HAVE___FLBF */ + /* Enable debugging */ /* #undef LIBXO_DEBUG */ @@ -158,7 +164,7 @@ #define PACKAGE_NAME "libxo" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "libxo 0.1.6" +#define PACKAGE_STRING "libxo 0.2.0" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "libxo" @@ -167,7 +173,7 @@ #define PACKAGE_URL "" /* Define to the version of this package. */ -#define PACKAGE_VERSION "0.1.6" +#define PACKAGE_VERSION "0.2.0" /* If using the C implementation of alloca, define if you know the direction of stack growth for your system; otherwise it will be @@ -181,7 +187,7 @@ #define STDC_HEADERS 1 /* Version number of package */ -#define VERSION "0.1.6" +#define VERSION "0.2.0" /* Define to `__inline__' or `__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ diff --git a/contrib/libxo/libxo/xoconfig.h.in b/contrib/libxo/libxo/xoconfig.h.in index 3fe7365..467f564 100644 --- a/contrib/libxo/libxo/xoconfig.h.in +++ b/contrib/libxo/libxo/xoconfig.h.in @@ -86,6 +86,9 @@ /* Define to 1 if you have the <stdint.h> header file. */ #undef HAVE_STDINT_H +/* Define to 1 if you have the <stdio_ext.h> header file. */ +#undef HAVE_STDIO_EXT_H + /* Define to 1 if you have the <stdio.h> header file. */ #undef HAVE_STDIO_H @@ -140,6 +143,9 @@ /* Define to 1 if you have the <unistd.h> header file. */ #undef HAVE_UNISTD_H +/* Define to 1 if you have the `__flbf' function. */ +#undef HAVE___FLBF + /* Enable debugging */ #undef LIBXO_DEBUG diff --git a/contrib/libxo/libxo/xoversion.h b/contrib/libxo/libxo/xoversion.h index 60c6118b..4c29e82 100644 --- a/contrib/libxo/libxo/xoversion.h +++ b/contrib/libxo/libxo/xoversion.h @@ -18,17 +18,17 @@ /** * The version string */ -#define LIBXO_VERSION "0.1.6" +#define LIBXO_VERSION "0.2.0" /** * The version number */ -#define LIBXO_VERSION_NUMBER 1006 +#define LIBXO_VERSION_NUMBER 2000 /** * The version number as a string */ -#define LIBXO_VERSION_STRING "1006" +#define LIBXO_VERSION_STRING "2000" /** * The version number extra info as a string diff --git a/contrib/libxo/packaging/libxo.rb.base.in b/contrib/libxo/packaging/libxo.rb.base.in new file mode 100644 index 0000000..70b712d --- /dev/null +++ b/contrib/libxo/packaging/libxo.rb.base.in @@ -0,0 +1,20 @@ +# +# Homebrew formula file for libxo +# https://github.com/mxcl/homebrew +# + +require 'formula' + +class Libxo < Formula + homepage 'https://github.com/Juniper/@PACKAGE-NAME@' + url 'https://github.com/Juniper/@PACKAGE_NAME@/releases/@PACKAGE_VERSION@/@PACKAGE_NAME@-@PACKAGE_VERSION@.tar.gz' + sha1 '__SHA1__' + + depends_on 'libtool' => :build + + def install + system "./configure", "--disable-dependency-tracking", + "--prefix=#{prefix}" + system "make install" + end +end diff --git a/contrib/libxo/tests/core/Makefile.am b/contrib/libxo/tests/core/Makefile.am index a5470f3..f145d18 100644 --- a/contrib/libxo/tests/core/Makefile.am +++ b/contrib/libxo/tests/core/Makefile.am @@ -18,7 +18,9 @@ test_03.c \ test_04.c \ test_05.c \ test_06.c \ -test_07.c +test_07.c \ +test_08.c \ +test_09.c test_01_test_SOURCES = test_01.c test_02_test_SOURCES = test_02.c @@ -27,6 +29,8 @@ test_04_test_SOURCES = test_04.c test_05_test_SOURCES = test_05.c test_06_test_SOURCES = test_06.c test_07_test_SOURCES = test_07.c +test_08_test_SOURCES = test_08.c +test_09_test_SOURCES = test_09.c # TEST_CASES := $(shell cd ${srcdir} ; echo *.c ) diff --git a/contrib/libxo/tests/core/saved/test_01.H.out b/contrib/libxo/tests/core/saved/test_01.H.out index e61eecc..4d4f2f1 100644 --- a/contrib/libxo/tests/core/saved/test_01.H.out +++ b/contrib/libxo/tests/core/saved/test_01.H.out @@ -1 +1 @@ -<div class="line"><div class="title">Item </div><div class="title"> Total Sold</div><div class="title"> In Stock</div><div class="title"> On Order</div><div class="title"> SKU</div></div><div class="line"><div class="data" data-tag="name" data-key="key">gum </div><div class="data" data-tag="sold"> 1412</div><div class="data" data-tag="in-stock"> 54</div><div class="data" data-tag="on-order"> 10</div><div class="data" data-tag="sku" data-key="key"> GRO-000-415</div></div><div class="line"><div class="data" data-tag="name" data-key="key">rope </div><div class="data" data-tag="sold"> 85</div><div class="data" data-tag="in-stock"> 4</div><div class="data" data-tag="on-order"> 2</div><div class="data" data-tag="sku" data-key="key"> HRD-000-212</div></div><div class="line"><div class="data" data-tag="name" data-key="key">ladder </div><div class="data" data-tag="sold"> 0</div><div class="data" data-tag="in-stock"> 2</div><div class="data" data-tag="on-order"> 1</div><div class="data" data-tag="sku" data-key="key"> HRD-000-517</div></div><div class="line"><div class="data" data-tag="name" data-key="key">bolt </div><div class="data" data-tag="sold"> 4123</div><div class="data" data-tag="in-stock"> 144</div><div class="data" data-tag="on-order"> 42</div><div class="data" data-tag="sku" data-key="key"> HRD-000-632</div></div><div class="line"><div class="data" data-tag="name" data-key="key">water </div><div class="data" data-tag="sold"> 17</div><div class="data" data-tag="in-stock"> 14</div><div class="data" data-tag="on-order"> 2</div><div class="data" data-tag="sku" data-key="key"> GRO-000-2331</div></div><div class="line"></div><div class="line"></div><div class="line"><div class="label">Item</div><div class="text"> '</div><div class="data" data-tag="name" data-key="key">gum</div><div class="text">':</div></div><div class="line"><div class="padding"> </div><div class="label">Total sold</div><div class="text">: </div><div class="data" data-tag="sold">1412.0</div></div><div class="line"><div class="padding"> </div><div class="label">In stock</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="in-stock">54</div></div><div class="line"><div class="padding"> </div><div class="label">On order</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="on-order">10</div></div><div class="line"><div class="padding"> </div><div class="label">SKU</div><div class="text">: </div><div class="data" data-tag="sku" data-key="key">GRO-000-415</div></div><div class="line"><div class="label">Item</div><div class="text"> '</div><div class="data" data-tag="name" data-key="key">rope</div><div class="text">':</div></div><div class="line"><div class="padding"> </div><div class="label">Total sold</div><div class="text">: </div><div class="data" data-tag="sold">85.0</div></div><div class="line"><div class="padding"> </div><div class="label">In stock</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="in-stock">4</div></div><div class="line"><div class="padding"> </div><div class="label">On order</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="on-order">2</div></div><div class="line"><div class="padding"> </div><div class="label">SKU</div><div class="text">: </div><div class="data" data-tag="sku" data-key="key">HRD-000-212</div></div><div class="line"><div class="label">Item</div><div class="text"> '</div><div class="data" data-tag="name" data-key="key">ladder</div><div class="text">':</div></div><div class="line"><div class="padding"> </div><div class="label">Total sold</div><div class="text">: </div><div class="data" data-tag="sold">0</div></div><div class="line"><div class="padding"> </div><div class="label">In stock</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="in-stock">2</div></div><div class="line"><div class="padding"> </div><div class="label">On order</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="on-order">1</div></div><div class="line"><div class="padding"> </div><div class="label">SKU</div><div class="text">: </div><div class="data" data-tag="sku" data-key="key">HRD-000-517</div></div><div class="line"><div class="label">Item</div><div class="text"> '</div><div class="data" data-tag="name" data-key="key">bolt</div><div class="text">':</div></div><div class="line"><div class="padding"> </div><div class="label">Total sold</div><div class="text">: </div><div class="data" data-tag="sold">4123.0</div></div><div class="line"><div class="padding"> </div><div class="label">In stock</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="in-stock">144</div></div><div class="line"><div class="padding"> </div><div class="label">On order</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="on-order">42</div></div><div class="line"><div class="padding"> </div><div class="label">SKU</div><div class="text">: </div><div class="data" data-tag="sku" data-key="key">HRD-000-632</div></div><div class="line"><div class="label">Item</div><div class="text"> '</div><div class="data" data-tag="name" data-key="key">water</div><div class="text">':</div></div><div class="line"><div class="padding"> </div><div class="label">Total sold</div><div class="text">: </div><div class="data" data-tag="sold">17.0</div></div><div class="line"><div class="padding"> </div><div class="label">In stock</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="in-stock">14</div></div><div class="line"><div class="padding"> </div><div class="label">On order</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="on-order">2</div></div><div class="line"><div class="padding"> </div><div class="label">SKU</div><div class="text">: </div><div class="data" data-tag="sku" data-key="key">GRO-000-2331</div></div><div class="line"><div class="label">Item</div><div class="text"> '</div><div class="data" data-tag="name" data-key="key">fish</div><div class="text">':</div></div><div class="line"><div class="padding"> </div><div class="label">Total sold</div><div class="text">: </div><div class="data" data-tag="sold">1321.0</div></div><div class="line"><div class="padding"> </div><div class="label">In stock</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="in-stock">45</div></div><div class="line"><div class="padding"> </div><div class="label">On order</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="on-order">1</div></div><div class="line"><div class="padding"> </div><div class="label">SKU</div><div class="text">: </div><div class="data" data-tag="sku" data-key="key">GRO-000-533</div></div>
\ No newline at end of file +<div class="line"><div class="title">Item </div><div class="title"> Total Sold</div><div class="title"> In Stock</div><div class="title"> On Order</div><div class="title"> SKU</div></div><div class="line"><div class="data" data-tag="name" data-key="key">gum </div><div class="data" data-tag="sold"> 1412</div><div class="data" data-tag="in-stock"> 54</div><div class="data" data-tag="on-order"> 10</div><div class="data" data-tag="sku" data-key="key"> GRO-000-415</div></div><div class="line"><div class="data" data-tag="name" data-key="key">rope </div><div class="data" data-tag="sold"> 85</div><div class="data" data-tag="in-stock"> 4</div><div class="data" data-tag="on-order"> 2</div><div class="data" data-tag="sku" data-key="key"> HRD-000-212</div></div><div class="line"><div class="data" data-tag="name" data-key="key">ladder </div><div class="data" data-tag="sold"> 0</div><div class="data" data-tag="in-stock"> 2</div><div class="data" data-tag="on-order"> 1</div><div class="data" data-tag="sku" data-key="key"> HRD-000-517</div></div><div class="line"><div class="data" data-tag="name" data-key="key">bolt </div><div class="data" data-tag="sold"> 4123</div><div class="data" data-tag="in-stock"> 144</div><div class="data" data-tag="on-order"> 42</div><div class="data" data-tag="sku" data-key="key"> HRD-000-632</div></div><div class="line"><div class="data" data-tag="name" data-key="key">water </div><div class="data" data-tag="sold"> 17</div><div class="data" data-tag="in-stock"> 14</div><div class="data" data-tag="on-order"> 2</div><div class="data" data-tag="sku" data-key="key"> GRO-000-2331</div></div><div class="line"></div><div class="line"></div><div class="line"><div class="label">Item</div><div class="text"> '</div><div class="data" data-tag="name" data-key="key">gum</div><div class="text">':</div></div><div class="line"><div class="padding"> </div><div class="label">Total sold</div><div class="text">: </div><div class="data" data-tag="sold">1412.0</div></div><div class="line"><div class="padding"> </div><div class="label">In stock</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="in-stock">54</div></div><div class="line"><div class="padding"> </div><div class="label">On order</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="on-order">10</div></div><div class="line"><div class="padding"> </div><div class="label">SKU</div><div class="text">: </div><div class="data" data-tag="sku" data-key="key">GRO-000-415</div></div><div class="line"><div class="label">Item</div><div class="text"> '</div><div class="data" data-tag="name" data-key="key">rope</div><div class="text">':</div></div><div class="line"><div class="padding"> </div><div class="label">Total sold</div><div class="text">: </div><div class="data" data-tag="sold">85.0</div></div><div class="line"><div class="padding"> </div><div class="label">In stock</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="in-stock">4</div></div><div class="line"><div class="padding"> </div><div class="label">On order</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="on-order">2</div></div><div class="line"><div class="padding"> </div><div class="label">SKU</div><div class="text">: </div><div class="data" data-tag="sku" data-key="key">HRD-000-212</div></div><div class="line"><div class="label">Item</div><div class="text"> '</div><div class="data" data-tag="name" data-key="key">ladder</div><div class="text">':</div></div><div class="line"><div class="padding"> </div><div class="label">Total sold</div><div class="text">: </div><div class="data" data-tag="sold">0</div></div><div class="line"><div class="padding"> </div><div class="label">In stock</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="in-stock">2</div></div><div class="line"><div class="padding"> </div><div class="label">On order</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="on-order">1</div></div><div class="line"><div class="padding"> </div><div class="label">SKU</div><div class="text">: </div><div class="data" data-tag="sku" data-key="key">HRD-000-517</div></div><div class="line"><div class="label">Item</div><div class="text"> '</div><div class="data" data-tag="name" data-key="key">bolt</div><div class="text">':</div></div><div class="line"><div class="padding"> </div><div class="label">Total sold</div><div class="text">: </div><div class="data" data-tag="sold">4123.0</div></div><div class="line"><div class="padding"> </div><div class="label">In stock</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="in-stock">144</div></div><div class="line"><div class="padding"> </div><div class="label">On order</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="on-order">42</div></div><div class="line"><div class="padding"> </div><div class="label">SKU</div><div class="text">: </div><div class="data" data-tag="sku" data-key="key">HRD-000-632</div></div><div class="line"><div class="label">Item</div><div class="text"> '</div><div class="data" data-tag="name" data-key="key">water</div><div class="text">':</div></div><div class="line"><div class="padding"> </div><div class="label">Total sold</div><div class="text">: </div><div class="data" data-tag="sold">17.0</div></div><div class="line"><div class="padding"> </div><div class="label">In stock</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="in-stock">14</div></div><div class="line"><div class="padding"> </div><div class="label">On order</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="on-order">2</div></div><div class="line"><div class="padding"> </div><div class="label">SKU</div><div class="text">: </div><div class="data" data-tag="sku" data-key="key">GRO-000-2331</div></div><div class="line"><div class="label">Item</div><div class="text"> '</div><div class="data" data-tag="name" data-key="key">fish</div><div class="text">':</div></div><div class="line"><div class="padding"> </div><div class="label">Total sold</div><div class="text">: </div><div class="data" data-tag="sold">1321.0</div></div><div class="line"><div class="padding"> </div><div class="label">In stock</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="in-stock">45</div></div><div class="line"><div class="padding"> </div><div class="label">On order</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="on-order">1</div></div><div class="line"><div class="padding"> </div><div class="label">SKU</div><div class="text">: </div><div class="data" data-tag="sku" data-key="key">GRO-000-533</div></div><div class="line"><div class="label">Item</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="item">gum</div></div><div class="line"><div class="label">Item</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="item">rope</div></div><div class="line"><div class="label">Item</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="item">ladder</div></div><div class="line"><div class="label">Item</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="item">bolt</div></div><div class="line"><div class="label">Item</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="item">water</div></div><div class="line"><div class="text">X</div><div class="text">X</div><div class="text">X</div><div class="text">X</div><div class="text">X</div><div class="text">X</div><div class="text">X</div><div class="text">X</div></div><div class="line"><div class="text">X</div><div class="padding"> </div><div class="text">X</div><div class="label">Cost</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="cost">425</div></div><div class="line"><div class="text">X</div><div class="padding"> </div><div class="text">X</div><div class="label">Cost</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="cost">455</div></div>
\ No newline at end of file diff --git a/contrib/libxo/tests/core/saved/test_01.HIPx.out b/contrib/libxo/tests/core/saved/test_01.HIPx.out index c38eb04..2bafff9 100644 --- a/contrib/libxo/tests/core/saved/test_01.HIPx.out +++ b/contrib/libxo/tests/core/saved/test_01.HIPx.out @@ -236,3 +236,61 @@ <div class="text">: </div> <div class="data" data-tag="sku" data-xpath="/top/data/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key">GRO-000-533</div> </div> +<div class="line"> + <div class="label">Item</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="item" data-xpath="/top/data/item">gum</div> +</div> +<div class="line"> + <div class="label">Item</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="item" data-xpath="/top/data/item">rope</div> +</div> +<div class="line"> + <div class="label">Item</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="item" data-xpath="/top/data/item">ladder</div> +</div> +<div class="line"> + <div class="label">Item</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="item" data-xpath="/top/data/item">bolt</div> +</div> +<div class="line"> + <div class="label">Item</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="item" data-xpath="/top/data/item">water</div> +</div> +<div class="line"> + <div class="text">X</div> + <div class="text">X</div> + <div class="text">X</div> + <div class="text">X</div> + <div class="text">X</div> + <div class="text">X</div> + <div class="text">X</div> + <div class="text">X</div> +</div> +<div class="line"> + <div class="text">X</div> + <div class="padding"> </div> + <div class="text">X</div> + <div class="label">Cost</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="cost" data-xpath="/top/cost">425</div> +</div> +<div class="line"> + <div class="text">X</div> + <div class="padding"> </div> + <div class="text">X</div> + <div class="label">Cost</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="cost" data-xpath="/top/cost">455</div> +</div> diff --git a/contrib/libxo/tests/core/saved/test_01.HP.out b/contrib/libxo/tests/core/saved/test_01.HP.out index a887476..a007778 100644 --- a/contrib/libxo/tests/core/saved/test_01.HP.out +++ b/contrib/libxo/tests/core/saved/test_01.HP.out @@ -236,3 +236,61 @@ <div class="text">: </div> <div class="data" data-tag="sku" data-key="key">GRO-000-533</div> </div> +<div class="line"> + <div class="label">Item</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="item">gum</div> +</div> +<div class="line"> + <div class="label">Item</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="item">rope</div> +</div> +<div class="line"> + <div class="label">Item</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="item">ladder</div> +</div> +<div class="line"> + <div class="label">Item</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="item">bolt</div> +</div> +<div class="line"> + <div class="label">Item</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="item">water</div> +</div> +<div class="line"> + <div class="text">X</div> + <div class="text">X</div> + <div class="text">X</div> + <div class="text">X</div> + <div class="text">X</div> + <div class="text">X</div> + <div class="text">X</div> + <div class="text">X</div> +</div> +<div class="line"> + <div class="text">X</div> + <div class="padding"> </div> + <div class="text">X</div> + <div class="label">Cost</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="cost">425</div> +</div> +<div class="line"> + <div class="text">X</div> + <div class="padding"> </div> + <div class="text">X</div> + <div class="label">Cost</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="cost">455</div> +</div> diff --git a/contrib/libxo/tests/core/saved/test_01.J.out b/contrib/libxo/tests/core/saved/test_01.J.out index 289a952..6fcdbd4 100644 --- a/contrib/libxo/tests/core/saved/test_01.J.out +++ b/contrib/libxo/tests/core/saved/test_01.J.out @@ -1,2 +1,2 @@ -{"top": {"data": {"item": [{"sku":"GRO-000-415","name":"gum","sold":1412,"in-stock":54,"on-order":10}, {"sku":"HRD-000-212","name":"rope","sold":85,"in-stock":4,"on-order":2}, {"sku":"HRD-000-517","name":"ladder","sold":0,"in-stock":2,"on-order":1}, {"sku":"HRD-000-632","name":"bolt","sold":4123,"in-stock":144,"on-order":42}, {"sku":"GRO-000-2331","name":"water","sold":17,"in-stock":14,"on-order":2}]}, "data": {"item": [{"sku":"GRO-000-415","name":"gum","sold":1412.0,"in-stock":54,"on-order":10}, {"sku":"HRD-000-212","name":"rope","sold":85.0,"in-stock":4,"on-order":2}, {"sku":"HRD-000-517","name":"ladder","sold":0,"in-stock":2,"on-order":1}, {"sku":"HRD-000-632","name":"bolt","sold":4123.0,"in-stock":144,"on-order":42}, {"sku":"GRO-000-2331","name":"water","sold":17.0,"in-stock":14,"on-order":2}]}, "data": {"item": [{"sku":"GRO-000-533","name":"fish","sold":1321.0,"in-stock":45,"on-order":1}]}} +{"top": {"data": {"item": [{"sku":"GRO-000-415","name":"gum","sold":1412,"in-stock":54,"on-order":10}, {"sku":"HRD-000-212","name":"rope","sold":85,"in-stock":4,"on-order":2}, {"sku":"HRD-000-517","name":"ladder","sold":0,"in-stock":2,"on-order":1}, {"sku":"HRD-000-632","name":"bolt","sold":4123,"in-stock":144,"on-order":42}, {"sku":"GRO-000-2331","name":"water","sold":17,"in-stock":14,"on-order":2}]}, "data": {"item": [{"sku":"GRO-000-415","name":"gum","sold":1412.0,"in-stock":54,"on-order":10}, {"sku":"HRD-000-212","name":"rope","sold":85.0,"in-stock":4,"on-order":2}, {"sku":"HRD-000-517","name":"ladder","sold":0,"in-stock":2,"on-order":1}, {"sku":"HRD-000-632","name":"bolt","sold":4123.0,"in-stock":144,"on-order":42}, {"sku":"GRO-000-2331","name":"water","sold":17.0,"in-stock":14,"on-order":2}]}, "data": {"item": [{"sku":"GRO-000-533","name":"fish","sold":1321.0,"in-stock":45,"on-order":1}]}, "data": {"item": ["gum","rope","ladder","bolt","water"]},"cost":425,"cost":455} } diff --git a/contrib/libxo/tests/core/saved/test_01.JP.out b/contrib/libxo/tests/core/saved/test_01.JP.out index 5675845..e1fd231 100644 --- a/contrib/libxo/tests/core/saved/test_01.JP.out +++ b/contrib/libxo/tests/core/saved/test_01.JP.out @@ -88,6 +88,13 @@ "on-order": 1 } ] - } + }, + "data": { + "item": [ + "gum", "rope", "ladder", "bolt", "water" + ] + }, + "cost": 425, + "cost": 455 } } diff --git a/contrib/libxo/tests/core/saved/test_01.T.out b/contrib/libxo/tests/core/saved/test_01.T.out index c2ad7a0..c45b130 100644 --- a/contrib/libxo/tests/core/saved/test_01.T.out +++ b/contrib/libxo/tests/core/saved/test_01.T.out @@ -36,3 +36,11 @@ Item 'fish': In stock: 45 On order: 1 SKU: GRO-000-533 +Item: gum +Item: rope +Item: ladder +Item: bolt +Item: water +XXXXXXXX +X XCost: 425 +X XCost: 455 diff --git a/contrib/libxo/tests/core/saved/test_01.X.out b/contrib/libxo/tests/core/saved/test_01.X.out index c3e07c8..ce27192 100644 --- a/contrib/libxo/tests/core/saved/test_01.X.out +++ b/contrib/libxo/tests/core/saved/test_01.X.out @@ -1 +1 @@ -<top><data><item><sku key="key">GRO-000-415</sku><name key="key">gum</name><sold>1412</sold><in-stock>54</in-stock><on-order>10</on-order></item><item><sku key="key">HRD-000-212</sku><name key="key">rope</name><sold>85</sold><in-stock>4</in-stock><on-order>2</on-order></item><item><sku key="key">HRD-000-517</sku><name key="key">ladder</name><sold>0</sold><in-stock>2</in-stock><on-order>1</on-order></item><item><sku key="key">HRD-000-632</sku><name key="key">bolt</name><sold>4123</sold><in-stock>144</in-stock><on-order>42</on-order></item><item><sku key="key">GRO-000-2331</sku><name key="key">water</name><sold>17</sold><in-stock>14</in-stock><on-order>2</on-order></item></data><data><item><sku key="key">GRO-000-415</sku><name key="key">gum</name><sold>1412.0</sold><in-stock>54</in-stock><on-order>10</on-order></item><item><sku key="key">HRD-000-212</sku><name key="key">rope</name><sold>85.0</sold><in-stock>4</in-stock><on-order>2</on-order></item><item><sku key="key">HRD-000-517</sku><name key="key">ladder</name><sold>0</sold><in-stock>2</in-stock><on-order>1</on-order></item><item><sku key="key">HRD-000-632</sku><name key="key">bolt</name><sold>4123.0</sold><in-stock>144</in-stock><on-order>42</on-order></item><item><sku key="key">GRO-000-2331</sku><name key="key">water</name><sold>17.0</sold><in-stock>14</in-stock><on-order>2</on-order></item></data><data><item><sku key="key">GRO-000-533</sku><name key="key">fish</name><sold>1321.0</sold><in-stock>45</in-stock><on-order>1</on-order></item></data></top>
\ No newline at end of file +<top><data test="value"><item test2="value2"><sku test3="value3" key="key">GRO-000-415</sku><name key="key">gum</name><sold>1412</sold><in-stock>54</in-stock><on-order>10</on-order></item><item><sku test3="value3" key="key">HRD-000-212</sku><name key="key">rope</name><sold>85</sold><in-stock>4</in-stock><on-order>2</on-order></item><item><sku test3="value3" key="key">HRD-000-517</sku><name key="key">ladder</name><sold>0</sold><in-stock>2</in-stock><on-order>1</on-order></item><item><sku test3="value3" key="key">HRD-000-632</sku><name key="key">bolt</name><sold>4123</sold><in-stock>144</in-stock><on-order>42</on-order></item><item><sku test3="value3" key="key">GRO-000-2331</sku><name key="key">water</name><sold>17</sold><in-stock>14</in-stock><on-order>2</on-order></item></data><data><item><sku key="key">GRO-000-415</sku><name key="key">gum</name><sold>1412.0</sold><in-stock>54</in-stock><on-order>10</on-order></item><item><sku key="key">HRD-000-212</sku><name key="key">rope</name><sold>85.0</sold><in-stock>4</in-stock><on-order>2</on-order></item><item><sku key="key">HRD-000-517</sku><name key="key">ladder</name><sold>0</sold><in-stock>2</in-stock><on-order>1</on-order></item><item><sku key="key">HRD-000-632</sku><name key="key">bolt</name><sold>4123.0</sold><in-stock>144</in-stock><on-order>42</on-order></item><item><sku key="key">GRO-000-2331</sku><name key="key">water</name><sold>17.0</sold><in-stock>14</in-stock><on-order>2</on-order></item></data><data><item><sku key="key">GRO-000-533</sku><name key="key">fish</name><sold>1321.0</sold><in-stock>45</in-stock><on-order>1</on-order></item></data><data><item test4="value4">gum</item><item test4="value4">rope</item><item test4="value4">ladder</item><item test4="value4">bolt</item><item test4="value4">water</item></data><cost>425</cost><cost>455</cost></top>
\ No newline at end of file diff --git a/contrib/libxo/tests/core/saved/test_01.XP.out b/contrib/libxo/tests/core/saved/test_01.XP.out index 49fc6da..e5ea3e0 100644 --- a/contrib/libxo/tests/core/saved/test_01.XP.out +++ b/contrib/libxo/tests/core/saved/test_01.XP.out @@ -1,35 +1,35 @@ <top> - <data> - <item> - <sku key="key">GRO-000-415</sku> + <data test="value"> + <item test2="value2"> + <sku test3="value3" key="key">GRO-000-415</sku> <name key="key">gum</name> <sold>1412</sold> <in-stock>54</in-stock> <on-order>10</on-order> </item> <item> - <sku key="key">HRD-000-212</sku> + <sku test3="value3" key="key">HRD-000-212</sku> <name key="key">rope</name> <sold>85</sold> <in-stock>4</in-stock> <on-order>2</on-order> </item> <item> - <sku key="key">HRD-000-517</sku> + <sku test3="value3" key="key">HRD-000-517</sku> <name key="key">ladder</name> <sold>0</sold> <in-stock>2</in-stock> <on-order>1</on-order> </item> <item> - <sku key="key">HRD-000-632</sku> + <sku test3="value3" key="key">HRD-000-632</sku> <name key="key">bolt</name> <sold>4123</sold> <in-stock>144</in-stock> <on-order>42</on-order> </item> <item> - <sku key="key">GRO-000-2331</sku> + <sku test3="value3" key="key">GRO-000-2331</sku> <name key="key">water</name> <sold>17</sold> <in-stock>14</in-stock> @@ -82,4 +82,13 @@ <on-order>1</on-order> </item> </data> + <data> + <item test4="value4">gum</item> + <item test4="value4">rope</item> + <item test4="value4">ladder</item> + <item test4="value4">bolt</item> + <item test4="value4">water</item> + </data> + <cost>425</cost> + <cost>455</cost> </top> diff --git a/contrib/libxo/tests/core/saved/test_02.J.out b/contrib/libxo/tests/core/saved/test_02.J.out index 621e061..5b4502a 100644 --- a/contrib/libxo/tests/core/saved/test_02.J.out +++ b/contrib/libxo/tests/core/saved/test_02.J.out @@ -1,2 +1,2 @@ -{"top": {"data": {"mbuf-current":10,"mbuf-cache":20,"mbuf-total":30,"distance":50,"location":"Boston","memory":64,"total":640,"memory":64,"total":640,"ten":10,"eleven":11,"unknown":1010,"min":15,"cur":20,"max":30,"min":15,"cur":20,"max":125,"min":15,"cur":20,"max":125,"min":15,"cur":20,"max":125, "flag": ["one","two","three"],"empty-tag":true,"t1":"1000","t2":"test5000","t3":"ten-longx","t4":"xtest","count":10,"test":4}} +{"top": {"data": {"mbuf-current":10,"mbuf-cache":20,"mbuf-total":30,"distance":50,"location":"Boston","memory":64,"total":640,"memory":64,"total":640,"ten":10,"eleven":11,"unknown":1010,"min":15,"cur":20,"max":30,"min":15,"cur":20,"max":125,"min":15,"cur":20,"max":125,"min":15,"cur":20,"max":125, "flag": ["one","two","three"],"empty-tag":true,"t1":"1000","t2":"test5000","t3":"ten-longx","t4":"xtest","count":10,"test":4, "error": {"message":"Shut 'er down, Clancey! She's a-pumpin' mud! <>!,\"!<>\n"}}} } diff --git a/contrib/libxo/tests/core/saved/test_02.JP.out b/contrib/libxo/tests/core/saved/test_02.JP.out index 9479817..21b168b 100644 --- a/contrib/libxo/tests/core/saved/test_02.JP.out +++ b/contrib/libxo/tests/core/saved/test_02.JP.out @@ -34,7 +34,10 @@ "t3": "ten-longx", "t4": "xtest", "count": 10, - "test": 4 + "test": 4, + "error": { + "message": "Shut 'er down, Clancey! She's a-pumpin' mud! <>!,\"!<>\n" + } } } } diff --git a/contrib/libxo/tests/core/saved/test_07.J.out b/contrib/libxo/tests/core/saved/test_07.J.out index 9285ff5..8e9efae 100644 --- a/contrib/libxo/tests/core/saved/test_07.J.out +++ b/contrib/libxo/tests/core/saved/test_07.J.out @@ -1,2 +1,2 @@ -{"employees": {"test": [{"filename":"(null)"}],"v1":"γιγνώσκειν","v2":"ὦ ἄνδρες ᾿Αθηναῖοι","columns":28,"columns":2,"v1":"ახლავე გაიაროთ რეგისტრაცია","v2":"Unicode-ის მეათე საერთაშორისო","columns":55, "employee": ["columns":0, {"first-name":"Jim","nic-name":"\"რეგტ\"","last-name":"გთხოვთ ახ","department":431,"percent-time":90,"columns":23,"benefits":"full"}, {"first-name":"Terry","nic-name":"\"<one\"","last-name":"Οὐχὶ ταὐτὰ παρίσταταί μοι Jones","department":660,"percent-time":90,"columns":47,"benefits":"full"}, {"first-name":"Leslie","nic-name":"\"Les\"","last-name":"Patterson","department":341,"percent-time":60,"columns":25,"benefits":"full"}, {"first-name":"Ashley","nic-name":"\"Ash\"","last-name":"Meter & Smith","department":1440,"percent-time":40,"columns":30}, {"first-name":"0123456789","nic-name":"\"0123456789\"","last-name":"012345678901234567890","department":1440,"percent-time":40,"columns":49}, {"first-name":"ახლა","nic-name":"\"გაიარო\"","last-name":"საერთაშორისო","department":123,"percent-time":90,"columns":29,"benefits":"full"}]} +{"employees": {"test": [{"filename":"(null)"}],"v1":"γιγνώσκειν","v2":"ὦ ἄνδρες ᾿Αθηναῖοι","columns":28,"columns":2,"v1":"ახლავე გაიაროთ რეგისტრაცია","v2":"Unicode-ის მეათე საერთაშორისო","columns":55,"columns":0, "employee": [{"first-name":"Jim","nic-name":"\"რეგტ\"","last-name":"გთხოვთ ახ","department":431,"percent-time":90,"columns":23,"benefits":"full"}, {"first-name":"Terry","nic-name":"\"<one\"","last-name":"Οὐχὶ ταὐτὰ παρίσταταί μοι Jones","department":660,"percent-time":90,"columns":47,"benefits":"full"}, {"first-name":"Leslie","nic-name":"\"Les\"","last-name":"Patterson","department":341,"percent-time":60,"columns":25,"benefits":"full"}, {"first-name":"Ashley","nic-name":"\"Ash\"","last-name":"Meter & Smith","department":1440,"percent-time":40,"columns":30}, {"first-name":"0123456789","nic-name":"\"0123456789\"","last-name":"012345678901234567890","department":1440,"percent-time":40,"columns":49}, {"first-name":"ახლა","nic-name":"\"გაიარო\"","last-name":"საერთაშორისო","department":123,"percent-time":90,"columns":29,"benefits":"full"}]} } diff --git a/contrib/libxo/tests/core/saved/test_07.JP.out b/contrib/libxo/tests/core/saved/test_07.JP.out index 206a146..9c969f9 100644 --- a/contrib/libxo/tests/core/saved/test_07.JP.out +++ b/contrib/libxo/tests/core/saved/test_07.JP.out @@ -12,8 +12,8 @@ "v1": "ახლავე გაიაროთ რეგისტრაცია", "v2": "Unicode-ის მეათე საერთაშორისო", "columns": 55, + "columns": 0, "employee": [ - "columns": 0, { "first-name": "Jim", "nic-name": "\"რეგტ\"", diff --git a/contrib/libxo/tests/core/saved/test_08.H.err b/contrib/libxo/tests/core/saved/test_08.H.err new file mode 100644 index 0000000..445bfb7 --- /dev/null +++ b/contrib/libxo/tests/core/saved/test_08.H.err @@ -0,0 +1,18 @@ +test: close (xo_close_container) fails at marker 'm1'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm1'; not found 'data' +test: close (xo_close_container) fails at marker 'm1'; not found 'top' diff --git a/contrib/libxo/tests/core/saved/test_08.H.out b/contrib/libxo/tests/core/saved/test_08.H.out new file mode 100644 index 0000000..81f12d8 --- /dev/null +++ b/contrib/libxo/tests/core/saved/test_08.H.out @@ -0,0 +1 @@ +<div class="line"><div class="title">Item </div><div class="title"> Count</div></div><div class="line"><div class="data" data-tag="name" data-key="key">gum </div><div class="data" data-tag="count"> 1412</div></div><div class="line"><div class="data" data-tag="name" data-key="key">rope </div><div class="data" data-tag="count"> 85</div></div><div class="line"><div class="data" data-tag="name" data-key="key">ladder </div><div class="data" data-tag="count"> 0</div></div><div class="line"><div class="data" data-tag="name" data-key="key">bolt </div><div class="data" data-tag="count"> 4123</div></div><div class="line"><div class="data" data-tag="name" data-key="key">water </div><div class="data" data-tag="count"> 17</div></div><div class="line"></div><div class="line"></div><div class="line"><div class="title">Item </div><div class="title"> Count</div></div><div class="line"><div class="data" data-tag="name" data-key="key">gum </div><div class="data" data-tag="count"> 1412</div></div><div class="line"><div class="data" data-tag="name" data-key="key">rope </div><div class="data" data-tag="count"> 85</div></div><div class="line"><div class="data" data-tag="name" data-key="key">ladder </div><div class="data" data-tag="count"> 0</div></div><div class="line"><div class="data" data-tag="name" data-key="key">bolt </div><div class="data" data-tag="count"> 4123</div></div><div class="line"><div class="data" data-tag="name" data-key="key">water </div><div class="data" data-tag="count"> 17</div></div><div class="line"></div><div class="line"></div><div class="line"><div class="title">Item </div><div class="title"> Count</div></div><div class="line"><div class="data" data-tag="name" data-key="key">gum </div><div class="data" data-tag="count"> 1412</div></div><div class="line"><div class="data" data-tag="name" data-key="key">rope </div><div class="data" data-tag="count"> 85</div></div><div class="line"><div class="data" data-tag="name" data-key="key">ladder </div><div class="data" data-tag="count"> 0</div></div><div class="line"><div class="data" data-tag="name" data-key="key">bolt </div><div class="data" data-tag="count"> 4123</div></div><div class="line"><div class="data" data-tag="name" data-key="key">water </div><div class="data" data-tag="count"> 17</div></div><div class="line"><div class="data" data-tag="test">one</div></div><div class="line"></div><div class="line"><div class="title">Item </div><div class="title"> Count</div></div><div class="line"><div class="data" data-tag="name" data-key="key">gum </div><div class="data" data-tag="count"> 1412</div></div><div class="line"><div class="label">Name</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="name">0</div><div class="text"> + 1 = </div><div class="data" data-tag="next">1</div></div><div class="line"><div class="label">Name</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="name">1</div><div class="text"> + 1 = </div><div class="data" data-tag="next">2</div></div><div class="line"><div class="label">Name</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="name">2</div><div class="text"> + 1 = </div><div class="data" data-tag="next">3</div></div><div class="line"><div class="label">Last</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="last">3</div></div><div class="line"><div class="data" data-tag="name" data-key="key">rope </div><div class="data" data-tag="count"> 85</div></div><div class="line"><div class="label">Name</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="name">0</div><div class="text"> + 1 = </div><div class="data" data-tag="next">1</div></div><div class="line"><div class="label">Name</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="name">1</div><div class="text"> + 1 = </div><div class="data" data-tag="next">2</div></div><div class="line"><div class="label">Name</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="name">2</div><div class="text"> + 1 = </div><div class="data" data-tag="next">3</div></div><div class="line"><div class="label">Last</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="last">3</div></div><div class="line"><div class="data" data-tag="name" data-key="key">ladder </div><div class="data" data-tag="count"> 0</div></div><div class="line"><div class="label">Name</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="name">0</div><div class="text"> + 1 = </div><div class="data" data-tag="next">1</div></div><div class="line"><div class="label">Name</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="name">1</div><div class="text"> + 1 = </div><div class="data" data-tag="next">2</div></div><div class="line"><div class="label">Name</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="name">2</div><div class="text"> + 1 = </div><div class="data" data-tag="next">3</div></div><div class="line"><div class="label">Last</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="last">3</div></div><div class="line"><div class="data" data-tag="name" data-key="key">bolt </div><div class="data" data-tag="count"> 4123</div></div><div class="line"><div class="label">Name</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="name">0</div><div class="text"> + 1 = </div><div class="data" data-tag="next">1</div></div><div class="line"><div class="label">Name</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="name">1</div><div class="text"> + 1 = </div><div class="data" data-tag="next">2</div></div><div class="line"><div class="label">Name</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="name">2</div><div class="text"> + 1 = </div><div class="data" data-tag="next">3</div></div><div class="line"><div class="label">Last</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="last">3</div></div><div class="line"><div class="data" data-tag="name" data-key="key">water </div><div class="data" data-tag="count"> 17</div></div><div class="line"><div class="label">Name</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="name">0</div><div class="text"> + 1 = </div><div class="data" data-tag="next">1</div></div><div class="line"><div class="label">Name</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="name">1</div><div class="text"> + 1 = </div><div class="data" data-tag="next">2</div></div><div class="line"><div class="label">Name</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="name">2</div><div class="text"> + 1 = </div><div class="data" data-tag="next">3</div></div><div class="line"><div class="label">Last</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="last">3</div></div><div class="line"><div class="data" data-tag="test">one</div></div><div class="line"></div>
\ No newline at end of file diff --git a/contrib/libxo/tests/core/saved/test_08.HIPx.err b/contrib/libxo/tests/core/saved/test_08.HIPx.err new file mode 100644 index 0000000..445bfb7 --- /dev/null +++ b/contrib/libxo/tests/core/saved/test_08.HIPx.err @@ -0,0 +1,18 @@ +test: close (xo_close_container) fails at marker 'm1'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm1'; not found 'data' +test: close (xo_close_container) fails at marker 'm1'; not found 'top' diff --git a/contrib/libxo/tests/core/saved/test_08.HIPx.out b/contrib/libxo/tests/core/saved/test_08.HIPx.out new file mode 100644 index 0000000..87bfbed --- /dev/null +++ b/contrib/libxo/tests/core/saved/test_08.HIPx.out @@ -0,0 +1,264 @@ +<div class="line"> + <div class="title">Item </div> + <div class="title"> Count</div> +</div> +<div class="line"> + <div class="data" data-tag="name" data-xpath="/top/data/contents/item/name" data-key="key">gum </div> + <div class="data" data-tag="count" data-xpath="/top/data/contents/item[name = 'gum']/count"> 1412</div> +</div> +<div class="line"> + <div class="data" data-tag="name" data-xpath="/top/data/contents/item/name" data-key="key">rope </div> + <div class="data" data-tag="count" data-xpath="/top/data/contents/item[name = 'rope']/count"> 85</div> +</div> +<div class="line"> + <div class="data" data-tag="name" data-xpath="/top/data/contents/item/name" data-key="key">ladder </div> + <div class="data" data-tag="count" data-xpath="/top/data/contents/item[name = 'ladder']/count"> 0</div> +</div> +<div class="line"> + <div class="data" data-tag="name" data-xpath="/top/data/contents/item/name" data-key="key">bolt </div> + <div class="data" data-tag="count" data-xpath="/top/data/contents/item[name = 'bolt']/count"> 4123</div> +</div> +<div class="line"> + <div class="data" data-tag="name" data-xpath="/top/data/contents/item/name" data-key="key">water </div> + <div class="data" data-tag="count" data-xpath="/top/data/contents/item[name = 'water']/count"> 17</div> +</div> +<div class="line"> +</div> +<div class="line"> +</div> +<div class="line"> + <div class="title">Item </div> + <div class="title"> Count</div> +</div> +<div class="line"> + <div class="data" data-tag="name" data-xpath="/top/data/contents/item/name" data-key="key">gum </div> + <div class="data" data-tag="count" data-xpath="/top/data/contents/item[name = 'gum']/count"> 1412</div> +</div> +<div class="line"> + <div class="data" data-tag="name" data-xpath="/top/data/contents/item/name" data-key="key">rope </div> + <div class="data" data-tag="count" data-xpath="/top/data/contents/item[name = 'rope']/count"> 85</div> +</div> +<div class="line"> + <div class="data" data-tag="name" data-xpath="/top/data/contents/item/name" data-key="key">ladder </div> + <div class="data" data-tag="count" data-xpath="/top/data/contents/item[name = 'ladder']/count"> 0</div> +</div> +<div class="line"> + <div class="data" data-tag="name" data-xpath="/top/data/contents/item/name" data-key="key">bolt </div> + <div class="data" data-tag="count" data-xpath="/top/data/contents/item[name = 'bolt']/count"> 4123</div> +</div> +<div class="line"> + <div class="data" data-tag="name" data-xpath="/top/data/contents/item/name" data-key="key">water </div> + <div class="data" data-tag="count" data-xpath="/top/data/contents/item[name = 'water']/count"> 17</div> +</div> +<div class="line"> +</div> +<div class="line"> +</div> +<div class="line"> + <div class="title">Item </div> + <div class="title"> Count</div> +</div> +<div class="line"> + <div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item/name" data-key="key">gum </div> + <div class="data" data-tag="count" data-xpath="/top/data/m1/contents/item[name = 'gum']/count"> 1412</div> +</div> +<div class="line"> + <div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item/name" data-key="key">rope </div> + <div class="data" data-tag="count" data-xpath="/top/data/m1/contents/item[name = 'rope']/count"> 85</div> +</div> +<div class="line"> + <div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item/name" data-key="key">ladder </div> + <div class="data" data-tag="count" data-xpath="/top/data/m1/contents/item[name = 'ladder']/count"> 0</div> +</div> +<div class="line"> + <div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item/name" data-key="key">bolt </div> + <div class="data" data-tag="count" data-xpath="/top/data/m1/contents/item[name = 'bolt']/count"> 4123</div> +</div> +<div class="line"> + <div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item/name" data-key="key">water </div> + <div class="data" data-tag="count" data-xpath="/top/data/m1/contents/item[name = 'water']/count"> 17</div> +</div> +<div class="line"> + <div class="data" data-tag="test" data-xpath="/top/data/m1/contents/item[name = 'water']/test">one</div> +</div> +<div class="line"> +</div> +<div class="line"> + <div class="title">Item </div> + <div class="title"> Count</div> +</div> +<div class="line"> + <div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item/name" data-key="key">gum </div> + <div class="data" data-tag="count" data-xpath="/top/data/m1/contents/item[name = 'gum']/count"> 1412</div> +</div> +<div class="line"> + <div class="label">Name</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item[name = 'gum']/m2/sub/name">0</div> + <div class="text"> + 1 = </div> + <div class="data" data-tag="next" data-xpath="/top/data/m1/contents/item[name = 'gum']/m2/sub/next">1</div> +</div> +<div class="line"> + <div class="label">Name</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item[name = 'gum']/m2/sub/name">1</div> + <div class="text"> + 1 = </div> + <div class="data" data-tag="next" data-xpath="/top/data/m1/contents/item[name = 'gum']/m2/sub/next">2</div> +</div> +<div class="line"> + <div class="label">Name</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item[name = 'gum']/m2/sub/name">2</div> + <div class="text"> + 1 = </div> + <div class="data" data-tag="next" data-xpath="/top/data/m1/contents/item[name = 'gum']/m2/sub/next">3</div> +</div> +<div class="line"> + <div class="label">Last</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="last" data-xpath="/top/data/m1/contents/item[name = 'gum']/last">3</div> +</div> +<div class="line"> + <div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item/name" data-key="key">rope </div> + <div class="data" data-tag="count" data-xpath="/top/data/m1/contents/item[name = 'rope']/count"> 85</div> +</div> +<div class="line"> + <div class="label">Name</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item[name = 'rope']/m2/sub/name">0</div> + <div class="text"> + 1 = </div> + <div class="data" data-tag="next" data-xpath="/top/data/m1/contents/item[name = 'rope']/m2/sub/next">1</div> +</div> +<div class="line"> + <div class="label">Name</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item[name = 'rope']/m2/sub/name">1</div> + <div class="text"> + 1 = </div> + <div class="data" data-tag="next" data-xpath="/top/data/m1/contents/item[name = 'rope']/m2/sub/next">2</div> +</div> +<div class="line"> + <div class="label">Name</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item[name = 'rope']/m2/sub/name">2</div> + <div class="text"> + 1 = </div> + <div class="data" data-tag="next" data-xpath="/top/data/m1/contents/item[name = 'rope']/m2/sub/next">3</div> +</div> +<div class="line"> + <div class="label">Last</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="last" data-xpath="/top/data/m1/contents/item[name = 'rope']/last">3</div> +</div> +<div class="line"> + <div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item/name" data-key="key">ladder </div> + <div class="data" data-tag="count" data-xpath="/top/data/m1/contents/item[name = 'ladder']/count"> 0</div> +</div> +<div class="line"> + <div class="label">Name</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item[name = 'ladder']/m2/sub/name">0</div> + <div class="text"> + 1 = </div> + <div class="data" data-tag="next" data-xpath="/top/data/m1/contents/item[name = 'ladder']/m2/sub/next">1</div> +</div> +<div class="line"> + <div class="label">Name</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item[name = 'ladder']/m2/sub/name">1</div> + <div class="text"> + 1 = </div> + <div class="data" data-tag="next" data-xpath="/top/data/m1/contents/item[name = 'ladder']/m2/sub/next">2</div> +</div> +<div class="line"> + <div class="label">Name</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item[name = 'ladder']/m2/sub/name">2</div> + <div class="text"> + 1 = </div> + <div class="data" data-tag="next" data-xpath="/top/data/m1/contents/item[name = 'ladder']/m2/sub/next">3</div> +</div> +<div class="line"> + <div class="label">Last</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="last" data-xpath="/top/data/m1/contents/item[name = 'ladder']/last">3</div> +</div> +<div class="line"> + <div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item/name" data-key="key">bolt </div> + <div class="data" data-tag="count" data-xpath="/top/data/m1/contents/item[name = 'bolt']/count"> 4123</div> +</div> +<div class="line"> + <div class="label">Name</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item[name = 'bolt']/m2/sub/name">0</div> + <div class="text"> + 1 = </div> + <div class="data" data-tag="next" data-xpath="/top/data/m1/contents/item[name = 'bolt']/m2/sub/next">1</div> +</div> +<div class="line"> + <div class="label">Name</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item[name = 'bolt']/m2/sub/name">1</div> + <div class="text"> + 1 = </div> + <div class="data" data-tag="next" data-xpath="/top/data/m1/contents/item[name = 'bolt']/m2/sub/next">2</div> +</div> +<div class="line"> + <div class="label">Name</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item[name = 'bolt']/m2/sub/name">2</div> + <div class="text"> + 1 = </div> + <div class="data" data-tag="next" data-xpath="/top/data/m1/contents/item[name = 'bolt']/m2/sub/next">3</div> +</div> +<div class="line"> + <div class="label">Last</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="last" data-xpath="/top/data/m1/contents/item[name = 'bolt']/last">3</div> +</div> +<div class="line"> + <div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item/name" data-key="key">water </div> + <div class="data" data-tag="count" data-xpath="/top/data/m1/contents/item[name = 'water']/count"> 17</div> +</div> +<div class="line"> + <div class="label">Name</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item[name = 'water']/m2/sub/name">0</div> + <div class="text"> + 1 = </div> + <div class="data" data-tag="next" data-xpath="/top/data/m1/contents/item[name = 'water']/m2/sub/next">1</div> +</div> +<div class="line"> + <div class="label">Name</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item[name = 'water']/m2/sub/name">1</div> + <div class="text"> + 1 = </div> + <div class="data" data-tag="next" data-xpath="/top/data/m1/contents/item[name = 'water']/m2/sub/next">2</div> +</div> +<div class="line"> + <div class="label">Name</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="name" data-xpath="/top/data/m1/contents/item[name = 'water']/m2/sub/name">2</div> + <div class="text"> + 1 = </div> + <div class="data" data-tag="next" data-xpath="/top/data/m1/contents/item[name = 'water']/m2/sub/next">3</div> +</div> +<div class="line"> + <div class="label">Last</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="last" data-xpath="/top/data/m1/contents/item[name = 'water']/last">3</div> +</div> +<div class="line"> + <div class="data" data-tag="test" data-xpath="/top/data/m1/contents/item[name = 'water']/test">one</div> +</div> +<div class="line"> +</div> diff --git a/contrib/libxo/tests/core/saved/test_08.HP.err b/contrib/libxo/tests/core/saved/test_08.HP.err new file mode 100644 index 0000000..445bfb7 --- /dev/null +++ b/contrib/libxo/tests/core/saved/test_08.HP.err @@ -0,0 +1,18 @@ +test: close (xo_close_container) fails at marker 'm1'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm1'; not found 'data' +test: close (xo_close_container) fails at marker 'm1'; not found 'top' diff --git a/contrib/libxo/tests/core/saved/test_08.HP.out b/contrib/libxo/tests/core/saved/test_08.HP.out new file mode 100644 index 0000000..3524f5e --- /dev/null +++ b/contrib/libxo/tests/core/saved/test_08.HP.out @@ -0,0 +1,264 @@ +<div class="line"> + <div class="title">Item </div> + <div class="title"> Count</div> +</div> +<div class="line"> + <div class="data" data-tag="name" data-key="key">gum </div> + <div class="data" data-tag="count"> 1412</div> +</div> +<div class="line"> + <div class="data" data-tag="name" data-key="key">rope </div> + <div class="data" data-tag="count"> 85</div> +</div> +<div class="line"> + <div class="data" data-tag="name" data-key="key">ladder </div> + <div class="data" data-tag="count"> 0</div> +</div> +<div class="line"> + <div class="data" data-tag="name" data-key="key">bolt </div> + <div class="data" data-tag="count"> 4123</div> +</div> +<div class="line"> + <div class="data" data-tag="name" data-key="key">water </div> + <div class="data" data-tag="count"> 17</div> +</div> +<div class="line"> +</div> +<div class="line"> +</div> +<div class="line"> + <div class="title">Item </div> + <div class="title"> Count</div> +</div> +<div class="line"> + <div class="data" data-tag="name" data-key="key">gum </div> + <div class="data" data-tag="count"> 1412</div> +</div> +<div class="line"> + <div class="data" data-tag="name" data-key="key">rope </div> + <div class="data" data-tag="count"> 85</div> +</div> +<div class="line"> + <div class="data" data-tag="name" data-key="key">ladder </div> + <div class="data" data-tag="count"> 0</div> +</div> +<div class="line"> + <div class="data" data-tag="name" data-key="key">bolt </div> + <div class="data" data-tag="count"> 4123</div> +</div> +<div class="line"> + <div class="data" data-tag="name" data-key="key">water </div> + <div class="data" data-tag="count"> 17</div> +</div> +<div class="line"> +</div> +<div class="line"> +</div> +<div class="line"> + <div class="title">Item </div> + <div class="title"> Count</div> +</div> +<div class="line"> + <div class="data" data-tag="name" data-key="key">gum </div> + <div class="data" data-tag="count"> 1412</div> +</div> +<div class="line"> + <div class="data" data-tag="name" data-key="key">rope </div> + <div class="data" data-tag="count"> 85</div> +</div> +<div class="line"> + <div class="data" data-tag="name" data-key="key">ladder </div> + <div class="data" data-tag="count"> 0</div> +</div> +<div class="line"> + <div class="data" data-tag="name" data-key="key">bolt </div> + <div class="data" data-tag="count"> 4123</div> +</div> +<div class="line"> + <div class="data" data-tag="name" data-key="key">water </div> + <div class="data" data-tag="count"> 17</div> +</div> +<div class="line"> + <div class="data" data-tag="test">one</div> +</div> +<div class="line"> +</div> +<div class="line"> + <div class="title">Item </div> + <div class="title"> Count</div> +</div> +<div class="line"> + <div class="data" data-tag="name" data-key="key">gum </div> + <div class="data" data-tag="count"> 1412</div> +</div> +<div class="line"> + <div class="label">Name</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="name">0</div> + <div class="text"> + 1 = </div> + <div class="data" data-tag="next">1</div> +</div> +<div class="line"> + <div class="label">Name</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="name">1</div> + <div class="text"> + 1 = </div> + <div class="data" data-tag="next">2</div> +</div> +<div class="line"> + <div class="label">Name</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="name">2</div> + <div class="text"> + 1 = </div> + <div class="data" data-tag="next">3</div> +</div> +<div class="line"> + <div class="label">Last</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="last">3</div> +</div> +<div class="line"> + <div class="data" data-tag="name" data-key="key">rope </div> + <div class="data" data-tag="count"> 85</div> +</div> +<div class="line"> + <div class="label">Name</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="name">0</div> + <div class="text"> + 1 = </div> + <div class="data" data-tag="next">1</div> +</div> +<div class="line"> + <div class="label">Name</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="name">1</div> + <div class="text"> + 1 = </div> + <div class="data" data-tag="next">2</div> +</div> +<div class="line"> + <div class="label">Name</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="name">2</div> + <div class="text"> + 1 = </div> + <div class="data" data-tag="next">3</div> +</div> +<div class="line"> + <div class="label">Last</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="last">3</div> +</div> +<div class="line"> + <div class="data" data-tag="name" data-key="key">ladder </div> + <div class="data" data-tag="count"> 0</div> +</div> +<div class="line"> + <div class="label">Name</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="name">0</div> + <div class="text"> + 1 = </div> + <div class="data" data-tag="next">1</div> +</div> +<div class="line"> + <div class="label">Name</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="name">1</div> + <div class="text"> + 1 = </div> + <div class="data" data-tag="next">2</div> +</div> +<div class="line"> + <div class="label">Name</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="name">2</div> + <div class="text"> + 1 = </div> + <div class="data" data-tag="next">3</div> +</div> +<div class="line"> + <div class="label">Last</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="last">3</div> +</div> +<div class="line"> + <div class="data" data-tag="name" data-key="key">bolt </div> + <div class="data" data-tag="count"> 4123</div> +</div> +<div class="line"> + <div class="label">Name</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="name">0</div> + <div class="text"> + 1 = </div> + <div class="data" data-tag="next">1</div> +</div> +<div class="line"> + <div class="label">Name</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="name">1</div> + <div class="text"> + 1 = </div> + <div class="data" data-tag="next">2</div> +</div> +<div class="line"> + <div class="label">Name</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="name">2</div> + <div class="text"> + 1 = </div> + <div class="data" data-tag="next">3</div> +</div> +<div class="line"> + <div class="label">Last</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="last">3</div> +</div> +<div class="line"> + <div class="data" data-tag="name" data-key="key">water </div> + <div class="data" data-tag="count"> 17</div> +</div> +<div class="line"> + <div class="label">Name</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="name">0</div> + <div class="text"> + 1 = </div> + <div class="data" data-tag="next">1</div> +</div> +<div class="line"> + <div class="label">Name</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="name">1</div> + <div class="text"> + 1 = </div> + <div class="data" data-tag="next">2</div> +</div> +<div class="line"> + <div class="label">Name</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="name">2</div> + <div class="text"> + 1 = </div> + <div class="data" data-tag="next">3</div> +</div> +<div class="line"> + <div class="label">Last</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="last">3</div> +</div> +<div class="line"> + <div class="data" data-tag="test">one</div> +</div> +<div class="line"> +</div> diff --git a/contrib/libxo/tests/core/saved/test_08.J.err b/contrib/libxo/tests/core/saved/test_08.J.err new file mode 100644 index 0000000..445bfb7 --- /dev/null +++ b/contrib/libxo/tests/core/saved/test_08.J.err @@ -0,0 +1,18 @@ +test: close (xo_close_container) fails at marker 'm1'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm1'; not found 'data' +test: close (xo_close_container) fails at marker 'm1'; not found 'top' diff --git a/contrib/libxo/tests/core/saved/test_08.J.out b/contrib/libxo/tests/core/saved/test_08.J.out new file mode 100644 index 0000000..cbce091 --- /dev/null +++ b/contrib/libxo/tests/core/saved/test_08.J.out @@ -0,0 +1,2 @@ +{"top": {"data": {"contents": {"item": [{"name":"gum","count":1412}, {"name":"rope","count":85}, {"name":"ladder","count":0}, {"name":"bolt","count":4123}, {"name":"water","count":17}]}}, "data": {"contents": {"item": [{"name":"gum","count":1412}, {"name":"rope","count":85}, {"name":"ladder","count":0}, {"name":"bolt","count":4123}, {"name":"water","count":17}]}}, "data": {"contents": {"item": [{"name":"gum","count":1412}, {"name":"rope","count":85}, {"name":"ladder","count":0}, {"name":"bolt","count":4123}, {"name":"water","count":17,"test":"one"}]}}, "data": {"contents": {"item": [{"name":"gum","count":1412, "sub": [{"name":0,"next":1}, {"name":1,"next":2}, {"name":2,"next":3}],"last":3}, {"name":"rope","count":85, "sub": [{"name":0,"next":1}, {"name":1,"next":2}, {"name":2,"next":3}],"last":3}, {"name":"ladder","count":0, "sub": [{"name":0,"next":1}, {"name":1,"next":2}, {"name":2,"next":3}],"last":3}, {"name":"bolt","count":4123, "sub": [{"name":0,"next":1}, {"name":1,"next":2}, {"name":2,"next":3}],"last":3}, {"name":"water","count":17, "sub": [{"name":0,"next":1}, {"name":1,"next":2}, {"name":2,"next":3}],"last":3,"test":"one"}]}}} +} diff --git a/contrib/libxo/tests/core/saved/test_08.JP.err b/contrib/libxo/tests/core/saved/test_08.JP.err new file mode 100644 index 0000000..445bfb7 --- /dev/null +++ b/contrib/libxo/tests/core/saved/test_08.JP.err @@ -0,0 +1,18 @@ +test: close (xo_close_container) fails at marker 'm1'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm1'; not found 'data' +test: close (xo_close_container) fails at marker 'm1'; not found 'top' diff --git a/contrib/libxo/tests/core/saved/test_08.JP.out b/contrib/libxo/tests/core/saved/test_08.JP.out new file mode 100644 index 0000000..932d6a1 --- /dev/null +++ b/contrib/libxo/tests/core/saved/test_08.JP.out @@ -0,0 +1,185 @@ +{ + "top": { + "data": { + "contents": { + "item": [ + { + "name": "gum", + "count": 1412 + }, + { + "name": "rope", + "count": 85 + }, + { + "name": "ladder", + "count": 0 + }, + { + "name": "bolt", + "count": 4123 + }, + { + "name": "water", + "count": 17 + } + ] + } + }, + "data": { + "contents": { + "item": [ + { + "name": "gum", + "count": 1412 + }, + { + "name": "rope", + "count": 85 + }, + { + "name": "ladder", + "count": 0 + }, + { + "name": "bolt", + "count": 4123 + }, + { + "name": "water", + "count": 17 + } + ] + } + }, + "data": { + "contents": { + "item": [ + { + "name": "gum", + "count": 1412 + }, + { + "name": "rope", + "count": 85 + }, + { + "name": "ladder", + "count": 0 + }, + { + "name": "bolt", + "count": 4123 + }, + { + "name": "water", + "count": 17, + "test": "one" + } + ] + } + }, + "data": { + "contents": { + "item": [ + { + "name": "gum", + "count": 1412, + "sub": [ + { + "name": 0, + "next": 1 + }, + { + "name": 1, + "next": 2 + }, + { + "name": 2, + "next": 3 + } + ], + "last": 3 + }, + { + "name": "rope", + "count": 85, + "sub": [ + { + "name": 0, + "next": 1 + }, + { + "name": 1, + "next": 2 + }, + { + "name": 2, + "next": 3 + } + ], + "last": 3 + }, + { + "name": "ladder", + "count": 0, + "sub": [ + { + "name": 0, + "next": 1 + }, + { + "name": 1, + "next": 2 + }, + { + "name": 2, + "next": 3 + } + ], + "last": 3 + }, + { + "name": "bolt", + "count": 4123, + "sub": [ + { + "name": 0, + "next": 1 + }, + { + "name": 1, + "next": 2 + }, + { + "name": 2, + "next": 3 + } + ], + "last": 3 + }, + { + "name": "water", + "count": 17, + "sub": [ + { + "name": 0, + "next": 1 + }, + { + "name": 1, + "next": 2 + }, + { + "name": 2, + "next": 3 + } + ], + "last": 3, + "test": "one" + } + ] + } + } + } +} diff --git a/contrib/libxo/tests/core/saved/test_08.T.err b/contrib/libxo/tests/core/saved/test_08.T.err new file mode 100644 index 0000000..445bfb7 --- /dev/null +++ b/contrib/libxo/tests/core/saved/test_08.T.err @@ -0,0 +1,18 @@ +test: close (xo_close_container) fails at marker 'm1'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm1'; not found 'data' +test: close (xo_close_container) fails at marker 'm1'; not found 'top' diff --git a/contrib/libxo/tests/core/saved/test_08.T.out b/contrib/libxo/tests/core/saved/test_08.T.out new file mode 100644 index 0000000..8923b93 --- /dev/null +++ b/contrib/libxo/tests/core/saved/test_08.T.out @@ -0,0 +1,52 @@ +Item Count +gum 1412 +rope 85 +ladder 0 +bolt 4123 +water 17 + + +Item Count +gum 1412 +rope 85 +ladder 0 +bolt 4123 +water 17 + + +Item Count +gum 1412 +rope 85 +ladder 0 +bolt 4123 +water 17 +one + +Item Count +gum 1412 +Name: 0 + 1 = 1 +Name: 1 + 1 = 2 +Name: 2 + 1 = 3 +Last: 3 +rope 85 +Name: 0 + 1 = 1 +Name: 1 + 1 = 2 +Name: 2 + 1 = 3 +Last: 3 +ladder 0 +Name: 0 + 1 = 1 +Name: 1 + 1 = 2 +Name: 2 + 1 = 3 +Last: 3 +bolt 4123 +Name: 0 + 1 = 1 +Name: 1 + 1 = 2 +Name: 2 + 1 = 3 +Last: 3 +water 17 +Name: 0 + 1 = 1 +Name: 1 + 1 = 2 +Name: 2 + 1 = 3 +Last: 3 +one + diff --git a/contrib/libxo/tests/core/saved/test_08.X.err b/contrib/libxo/tests/core/saved/test_08.X.err new file mode 100644 index 0000000..445bfb7 --- /dev/null +++ b/contrib/libxo/tests/core/saved/test_08.X.err @@ -0,0 +1,18 @@ +test: close (xo_close_container) fails at marker 'm1'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm1'; not found 'data' +test: close (xo_close_container) fails at marker 'm1'; not found 'top' diff --git a/contrib/libxo/tests/core/saved/test_08.X.out b/contrib/libxo/tests/core/saved/test_08.X.out new file mode 100644 index 0000000..5eb72b2 --- /dev/null +++ b/contrib/libxo/tests/core/saved/test_08.X.out @@ -0,0 +1 @@ +<top><data><contents><item><name key="key">gum</name><count>1412</count></item><item><name key="key">rope</name><count>85</count></item><item><name key="key">ladder</name><count>0</count></item><item><name key="key">bolt</name><count>4123</count></item><item><name key="key">water</name><count>17</count></item></contents></data><data><contents><item><name key="key">gum</name><count>1412</count></item><item><name key="key">rope</name><count>85</count></item><item><name key="key">ladder</name><count>0</count></item><item><name key="key">bolt</name><count>4123</count></item><item><name key="key">water</name><count>17</count></item></contents></data><data><contents><item><name key="key">gum</name><count>1412</count></item><item><name key="key">rope</name><count>85</count></item><item><name key="key">ladder</name><count>0</count></item><item><name key="key">bolt</name><count>4123</count></item><item><name key="key">water</name><count>17</count><test>one</test></item></contents></data><data><contents><item><name key="key">gum</name><count>1412</count><sub><name>0</name><next>1</next></sub><sub><name>1</name><next>2</next></sub><sub><name>2</name><next>3</next></sub><last>3</last></item><item><name key="key">rope</name><count>85</count><sub><name>0</name><next>1</next></sub><sub><name>1</name><next>2</next></sub><sub><name>2</name><next>3</next></sub><last>3</last></item><item><name key="key">ladder</name><count>0</count><sub><name>0</name><next>1</next></sub><sub><name>1</name><next>2</next></sub><sub><name>2</name><next>3</next></sub><last>3</last></item><item><name key="key">bolt</name><count>4123</count><sub><name>0</name><next>1</next></sub><sub><name>1</name><next>2</next></sub><sub><name>2</name><next>3</next></sub><last>3</last></item><item><name key="key">water</name><count>17</count><sub><name>0</name><next>1</next></sub><sub><name>1</name><next>2</next></sub><sub><name>2</name><next>3</next></sub><last>3</last><test>one</test></item></contents></data></top>
\ No newline at end of file diff --git a/contrib/libxo/tests/core/saved/test_08.XP.err b/contrib/libxo/tests/core/saved/test_08.XP.err new file mode 100644 index 0000000..445bfb7 --- /dev/null +++ b/contrib/libxo/tests/core/saved/test_08.XP.err @@ -0,0 +1,18 @@ +test: close (xo_close_container) fails at marker 'm1'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm2'; not found 'data' +test: close (xo_close_container) fails at marker 'm1'; not found 'data' +test: close (xo_close_container) fails at marker 'm1'; not found 'top' diff --git a/contrib/libxo/tests/core/saved/test_08.XP.out b/contrib/libxo/tests/core/saved/test_08.XP.out new file mode 100644 index 0000000..99520c0 --- /dev/null +++ b/contrib/libxo/tests/core/saved/test_08.XP.out @@ -0,0 +1,165 @@ +<top> + <data> + <contents> + <item> + <name key="key">gum</name> + <count>1412</count> + </item> + <item> + <name key="key">rope</name> + <count>85</count> + </item> + <item> + <name key="key">ladder</name> + <count>0</count> + </item> + <item> + <name key="key">bolt</name> + <count>4123</count> + </item> + <item> + <name key="key">water</name> + <count>17</count> + </item> + </contents> + </data> + <data> + <contents> + <item> + <name key="key">gum</name> + <count>1412</count> + </item> + <item> + <name key="key">rope</name> + <count>85</count> + </item> + <item> + <name key="key">ladder</name> + <count>0</count> + </item> + <item> + <name key="key">bolt</name> + <count>4123</count> + </item> + <item> + <name key="key">water</name> + <count>17</count> + </item> + </contents> + </data> + <data> + <contents> + <item> + <name key="key">gum</name> + <count>1412</count> + </item> + <item> + <name key="key">rope</name> + <count>85</count> + </item> + <item> + <name key="key">ladder</name> + <count>0</count> + </item> + <item> + <name key="key">bolt</name> + <count>4123</count> + </item> + <item> + <name key="key">water</name> + <count>17</count> + <test>one</test> + </item> + </contents> + </data> + <data> + <contents> + <item> + <name key="key">gum</name> + <count>1412</count> + <sub> + <name>0</name> + <next>1</next> + </sub> + <sub> + <name>1</name> + <next>2</next> + </sub> + <sub> + <name>2</name> + <next>3</next> + </sub> + <last>3</last> + </item> + <item> + <name key="key">rope</name> + <count>85</count> + <sub> + <name>0</name> + <next>1</next> + </sub> + <sub> + <name>1</name> + <next>2</next> + </sub> + <sub> + <name>2</name> + <next>3</next> + </sub> + <last>3</last> + </item> + <item> + <name key="key">ladder</name> + <count>0</count> + <sub> + <name>0</name> + <next>1</next> + </sub> + <sub> + <name>1</name> + <next>2</next> + </sub> + <sub> + <name>2</name> + <next>3</next> + </sub> + <last>3</last> + </item> + <item> + <name key="key">bolt</name> + <count>4123</count> + <sub> + <name>0</name> + <next>1</next> + </sub> + <sub> + <name>1</name> + <next>2</next> + </sub> + <sub> + <name>2</name> + <next>3</next> + </sub> + <last>3</last> + </item> + <item> + <name key="key">water</name> + <count>17</count> + <sub> + <name>0</name> + <next>1</next> + </sub> + <sub> + <name>1</name> + <next>2</next> + </sub> + <sub> + <name>2</name> + <next>3</next> + </sub> + <last>3</last> + <test>one</test> + </item> + </contents> + </data> +</top> diff --git a/contrib/libxo/tests/core/saved/test_09.H.err b/contrib/libxo/tests/core/saved/test_09.H.err new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/contrib/libxo/tests/core/saved/test_09.H.err diff --git a/contrib/libxo/tests/core/saved/test_09.H.out b/contrib/libxo/tests/core/saved/test_09.H.out new file mode 100644 index 0000000..899cd2f --- /dev/null +++ b/contrib/libxo/tests/core/saved/test_09.H.out @@ -0,0 +1 @@ +<div class="line"><div class="title">Item </div><div class="title"> Count</div></div><div class="line"><div class="text">Name: </div><div class="data" data-tag="name">gum </div></div><div class="line"><div class="text">Name: </div><div class="data" data-tag="name">rope </div></div><div class="line"><div class="text">Name: </div><div class="data" data-tag="name">ladder </div></div><div class="line"><div class="text">Name: </div><div class="data" data-tag="name">bolt </div></div><div class="line"><div class="text">Name: </div><div class="data" data-tag="name">water </div></div><div class="line"></div><div class="line"></div><div class="line"><div class="title">Item </div><div class="title"> Count</div></div><div class="line"><div class="text">Name: </div><div class="data" data-tag="item">gum </div></div><div class="line"><div class="text">Name: </div><div class="data" data-tag="item">rope </div></div><div class="line"><div class="text">Name: </div><div class="data" data-tag="item">ladder </div></div><div class="line"><div class="text">Name: </div><div class="data" data-tag="item">bolt </div></div><div class="line"><div class="text">Name: </div><div class="data" data-tag="item">water </div></div><div class="line"></div><div class="line"></div><div class="line"><div class="title">Test </div><div class="title"> Three</div></div><div class="line"><div class="text">Name: </div><div class="data" data-tag="item">gum </div></div><div class="line"><div class="text">Name: </div><div class="data" data-tag="item">rope </div></div><div class="line"><div class="text">Name: </div><div class="data" data-tag="item">ladder </div></div><div class="line"><div class="text">Name: </div><div class="data" data-tag="item">bolt </div></div><div class="line"><div class="text">Name: </div><div class="data" data-tag="item">water </div></div><div class="line"><div class="label">Total:</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="total">six</div></div><div class="line"><div class="data" data-tag="one">one</div><div class="data" data-tag="two">two</div><div class="data" data-tag="three">three</div></div><div class="line"></div>
\ No newline at end of file diff --git a/contrib/libxo/tests/core/saved/test_09.HIPx.err b/contrib/libxo/tests/core/saved/test_09.HIPx.err new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/contrib/libxo/tests/core/saved/test_09.HIPx.err diff --git a/contrib/libxo/tests/core/saved/test_09.HIPx.out b/contrib/libxo/tests/core/saved/test_09.HIPx.out new file mode 100644 index 0000000..a63f292 --- /dev/null +++ b/contrib/libxo/tests/core/saved/test_09.HIPx.out @@ -0,0 +1,93 @@ +<div class="line"> + <div class="title">Item </div> + <div class="title"> Count</div> +</div> +<div class="line"> + <div class="text">Name: </div> + <div class="data" data-tag="name" data-xpath="/top/data/contents/name">gum </div> +</div> +<div class="line"> + <div class="text">Name: </div> + <div class="data" data-tag="name" data-xpath="/top/data/contents/name">rope </div> +</div> +<div class="line"> + <div class="text">Name: </div> + <div class="data" data-tag="name" data-xpath="/top/data/contents/name">ladder </div> +</div> +<div class="line"> + <div class="text">Name: </div> + <div class="data" data-tag="name" data-xpath="/top/data/contents/name">bolt </div> +</div> +<div class="line"> + <div class="text">Name: </div> + <div class="data" data-tag="name" data-xpath="/top/data/contents/name">water </div> +</div> +<div class="line"> +</div> +<div class="line"> +</div> +<div class="line"> + <div class="title">Item </div> + <div class="title"> Count</div> +</div> +<div class="line"> + <div class="text">Name: </div> + <div class="data" data-tag="item" data-xpath="/top/data/contents/item">gum </div> +</div> +<div class="line"> + <div class="text">Name: </div> + <div class="data" data-tag="item" data-xpath="/top/data/contents/item">rope </div> +</div> +<div class="line"> + <div class="text">Name: </div> + <div class="data" data-tag="item" data-xpath="/top/data/contents/item">ladder </div> +</div> +<div class="line"> + <div class="text">Name: </div> + <div class="data" data-tag="item" data-xpath="/top/data/contents/item">bolt </div> +</div> +<div class="line"> + <div class="text">Name: </div> + <div class="data" data-tag="item" data-xpath="/top/data/contents/item">water </div> +</div> +<div class="line"> +</div> +<div class="line"> +</div> +<div class="line"> + <div class="title">Test </div> + <div class="title"> Three</div> +</div> +<div class="line"> + <div class="text">Name: </div> + <div class="data" data-tag="item" data-xpath="/top/data/contents/item">gum </div> +</div> +<div class="line"> + <div class="text">Name: </div> + <div class="data" data-tag="item" data-xpath="/top/data/contents/item">rope </div> +</div> +<div class="line"> + <div class="text">Name: </div> + <div class="data" data-tag="item" data-xpath="/top/data/contents/item">ladder </div> +</div> +<div class="line"> + <div class="text">Name: </div> + <div class="data" data-tag="item" data-xpath="/top/data/contents/item">bolt </div> +</div> +<div class="line"> + <div class="text">Name: </div> + <div class="data" data-tag="item" data-xpath="/top/data/contents/item">water </div> +</div> +<div class="line"> + <div class="label">Total:</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="total" data-xpath="/top/data/contents/total">six</div> +</div> +<div class="line"> + <div class="data" data-tag="one" data-xpath="/top/data/contents/one">one</div> + <div class="data" data-tag="two" data-xpath="/top/data/contents/two">two</div> + <div class="data" data-tag="three" data-xpath="/top/data/contents/three">three</div> +</div> +<div class="line"> +</div> diff --git a/contrib/libxo/tests/core/saved/test_09.HP.err b/contrib/libxo/tests/core/saved/test_09.HP.err new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/contrib/libxo/tests/core/saved/test_09.HP.err diff --git a/contrib/libxo/tests/core/saved/test_09.HP.out b/contrib/libxo/tests/core/saved/test_09.HP.out new file mode 100644 index 0000000..8a8f700 --- /dev/null +++ b/contrib/libxo/tests/core/saved/test_09.HP.out @@ -0,0 +1,93 @@ +<div class="line"> + <div class="title">Item </div> + <div class="title"> Count</div> +</div> +<div class="line"> + <div class="text">Name: </div> + <div class="data" data-tag="name">gum </div> +</div> +<div class="line"> + <div class="text">Name: </div> + <div class="data" data-tag="name">rope </div> +</div> +<div class="line"> + <div class="text">Name: </div> + <div class="data" data-tag="name">ladder </div> +</div> +<div class="line"> + <div class="text">Name: </div> + <div class="data" data-tag="name">bolt </div> +</div> +<div class="line"> + <div class="text">Name: </div> + <div class="data" data-tag="name">water </div> +</div> +<div class="line"> +</div> +<div class="line"> +</div> +<div class="line"> + <div class="title">Item </div> + <div class="title"> Count</div> +</div> +<div class="line"> + <div class="text">Name: </div> + <div class="data" data-tag="item">gum </div> +</div> +<div class="line"> + <div class="text">Name: </div> + <div class="data" data-tag="item">rope </div> +</div> +<div class="line"> + <div class="text">Name: </div> + <div class="data" data-tag="item">ladder </div> +</div> +<div class="line"> + <div class="text">Name: </div> + <div class="data" data-tag="item">bolt </div> +</div> +<div class="line"> + <div class="text">Name: </div> + <div class="data" data-tag="item">water </div> +</div> +<div class="line"> +</div> +<div class="line"> +</div> +<div class="line"> + <div class="title">Test </div> + <div class="title"> Three</div> +</div> +<div class="line"> + <div class="text">Name: </div> + <div class="data" data-tag="item">gum </div> +</div> +<div class="line"> + <div class="text">Name: </div> + <div class="data" data-tag="item">rope </div> +</div> +<div class="line"> + <div class="text">Name: </div> + <div class="data" data-tag="item">ladder </div> +</div> +<div class="line"> + <div class="text">Name: </div> + <div class="data" data-tag="item">bolt </div> +</div> +<div class="line"> + <div class="text">Name: </div> + <div class="data" data-tag="item">water </div> +</div> +<div class="line"> + <div class="label">Total:</div> + <div class="decoration">:</div> + <div class="padding"> </div> + <div class="data" data-tag="total">six</div> +</div> +<div class="line"> + <div class="data" data-tag="one">one</div> + <div class="data" data-tag="two">two</div> + <div class="data" data-tag="three">three</div> +</div> +<div class="line"> +</div> diff --git a/contrib/libxo/tests/core/saved/test_09.J.err b/contrib/libxo/tests/core/saved/test_09.J.err new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/contrib/libxo/tests/core/saved/test_09.J.err diff --git a/contrib/libxo/tests/core/saved/test_09.J.out b/contrib/libxo/tests/core/saved/test_09.J.out new file mode 100644 index 0000000..e43ad31 --- /dev/null +++ b/contrib/libxo/tests/core/saved/test_09.J.out @@ -0,0 +1,2 @@ +{"top": {"data": {"contents": {"name": ["gum","rope","ladder","bolt","water"]}, "contents": {"item": ["gum","rope","ladder","bolt","water"]}, "contents": {"item": ["gum","rope","ladder","bolt","water"],"total":"six","one":"one", "two": ["two"],"three":"three"}}} +} diff --git a/contrib/libxo/tests/core/saved/test_09.JP.err b/contrib/libxo/tests/core/saved/test_09.JP.err new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/contrib/libxo/tests/core/saved/test_09.JP.err diff --git a/contrib/libxo/tests/core/saved/test_09.JP.out b/contrib/libxo/tests/core/saved/test_09.JP.out new file mode 100644 index 0000000..8340b27 --- /dev/null +++ b/contrib/libxo/tests/core/saved/test_09.JP.out @@ -0,0 +1,27 @@ +{ + "top": { + "data": { + "contents": { + "name": [ + "gum", "rope", "ladder", "bolt", "water" + ] + }, + "contents": { + "item": [ + "gum", "rope", "ladder", "bolt", "water" + ] + }, + "contents": { + "item": [ + "gum", "rope", "ladder", "bolt", "water" + ], + "total": "six", + "one": "one", + "two": [ + "two" + ], + "three": "three" + } + } + } +} diff --git a/contrib/libxo/tests/core/saved/test_09.T.err b/contrib/libxo/tests/core/saved/test_09.T.err new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/contrib/libxo/tests/core/saved/test_09.T.err diff --git a/contrib/libxo/tests/core/saved/test_09.T.out b/contrib/libxo/tests/core/saved/test_09.T.out new file mode 100644 index 0000000..5bb163e --- /dev/null +++ b/contrib/libxo/tests/core/saved/test_09.T.out @@ -0,0 +1,25 @@ +Item Count +Name: gum +Name: rope +Name: ladder +Name: bolt +Name: water + + +Item Count +Name: gum +Name: rope +Name: ladder +Name: bolt +Name: water + + +Test Three +Name: gum +Name: rope +Name: ladder +Name: bolt +Name: water +Total:: six +onetwothree + diff --git a/contrib/libxo/tests/core/saved/test_09.X.err b/contrib/libxo/tests/core/saved/test_09.X.err new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/contrib/libxo/tests/core/saved/test_09.X.err diff --git a/contrib/libxo/tests/core/saved/test_09.X.out b/contrib/libxo/tests/core/saved/test_09.X.out new file mode 100644 index 0000000..21ce1ce --- /dev/null +++ b/contrib/libxo/tests/core/saved/test_09.X.out @@ -0,0 +1 @@ +<top><data><contents><name>gum</name><name>rope</name><name>ladder</name><name>bolt</name><name>water</name></contents><contents><item>gum</item><item>rope</item><item>ladder</item><item>bolt</item><item>water</item></contents><contents><item>gum</item><item>rope</item><item>ladder</item><item>bolt</item><item>water</item><total>six</total><one>one</one><two>two</two><three>three</three></contents></data></top>
\ No newline at end of file diff --git a/contrib/libxo/tests/core/saved/test_09.XP.err b/contrib/libxo/tests/core/saved/test_09.XP.err new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/contrib/libxo/tests/core/saved/test_09.XP.err diff --git a/contrib/libxo/tests/core/saved/test_09.XP.out b/contrib/libxo/tests/core/saved/test_09.XP.out new file mode 100644 index 0000000..9476126 --- /dev/null +++ b/contrib/libxo/tests/core/saved/test_09.XP.out @@ -0,0 +1,29 @@ +<top> + <data> + <contents> + <name>gum</name> + <name>rope</name> + <name>ladder</name> + <name>bolt</name> + <name>water</name> + </contents> + <contents> + <item>gum</item> + <item>rope</item> + <item>ladder</item> + <item>bolt</item> + <item>water</item> + </contents> + <contents> + <item>gum</item> + <item>rope</item> + <item>ladder</item> + <item>bolt</item> + <item>water</item> + <total>six</total> + <one>one</one> + <two>two</two> + <three>three</three> + </contents> + </data> +</top> diff --git a/contrib/libxo/tests/core/test_01.c b/contrib/libxo/tests/core/test_01.c index 164a38b..9a9ed2c 100644 --- a/contrib/libxo/tests/core/test_01.c +++ b/contrib/libxo/tests/core/test_01.c @@ -11,6 +11,8 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <unistd.h> +#include <errno.h> #include "xo.h" @@ -69,6 +71,10 @@ main (int argc, char **argv) xo_set_flags(NULL, XOF_XPATH); else if (strcmp(argv[argc], "info") == 0) xo_set_flags(NULL, XOF_INFO); + else if (strcmp(argv[argc], "error") == 0) { + close(-1); + xo_err(1, "error detected"); + } } xo_set_info(NULL, info, info_count); @@ -76,14 +82,17 @@ main (int argc, char **argv) xo_open_container_h(NULL, "top"); + xo_attr("test", "value"); xo_open_container("data"); xo_open_list("item"); + xo_attr("test2", "value2"); xo_emit("{T:Item/%-10s}{T:Total Sold/%12s}{T:In Stock/%12s}" "{T:On Order/%12s}{T:SKU/%5s}\n"); for (ip = list; ip->i_title; ip++) { xo_open_instance("item"); + xo_attr("test3", "value3"); xo_emit("{keq:sku/%s-%u/%s-000-%u}" "{k:name/%-10s/%s}{n:sold/%12u/%u}{:in-stock/%12u/%u}" @@ -142,6 +151,25 @@ main (int argc, char **argv) xo_close_list("item"); xo_close_container("data"); + xo_open_container("data"); + xo_open_list("item"); + + for (ip = list; ip->i_title; ip++) { + xo_attr("test4", "value4"); + xo_emit("{Lwc:Item}{l:item}\n", ip->i_title); + } + + xo_close_list("item"); + xo_close_container("data"); + + xo_emit("X{P:}X", "epic fail"); + xo_emit("X{T:}X", "epic fail"); + xo_emit("X{N:}X", "epic fail"); + xo_emit("X{L:}X\n", "epic fail"); + + xo_emit("X{P: }X{Lwc:Cost}{:cost/%u}\n", 425); + xo_emit("X{P:/%30s}X{Lwc:Cost}{:cost/%u}\n", "", 455); + xo_close_container_h(NULL, "top"); xo_finish(); diff --git a/contrib/libxo/tests/core/test_07.c b/contrib/libxo/tests/core/test_07.c index 18b7baa..5b1ed57 100644 --- a/contrib/libxo/tests/core/test_07.c +++ b/contrib/libxo/tests/core/test_07.c @@ -68,11 +68,12 @@ main (int argc, char **argv) "Unicode-ის მეათე საერთაშორისო"); xo_emit("{:columns/%d}\n", rc); - xo_open_list("employee"); rc = xo_emit("{T:First Name/%-25s}{T:Last Name/%-14s}" "{T:/%-12s}{T:Time (%)}\n", "Department"); xo_emit("{:columns/%d}\n", rc); + + xo_open_list("employee"); for ( ; ep->e_first; ep++) { xo_open_instance("employee"); rc = xo_emit("{[:-25}{:first-name/%s} ({:nic-name/\"%s\"}){]:}" diff --git a/contrib/libxo/tests/core/test_08.c b/contrib/libxo/tests/core/test_08.c new file mode 100644 index 0000000..eb3776d --- /dev/null +++ b/contrib/libxo/tests/core/test_08.c @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2015, Juniper Networks, Inc. + * All rights reserved. + * This SOFTWARE is licensed under the LICENSE provided in the + * ../Copyright file. By downloading, installing, copying, or otherwise + * using the SOFTWARE, you agree to be bound by the terms of that + * LICENSE. + * Phil Shafer, July 2015 + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> + +#include "xo.h" + +int +main (int argc, char **argv) +{ + struct item { + const char *i_title; + int i_count; + }; + struct item list[] = { + { "gum", 1412 }, + { "rope", 85 }, + { "ladder", 0 }, + { "bolt", 4123 }, + { "water", 17 }, + { NULL, 0 } + }; + struct item *ip; + int i; + + argc = xo_parse_args(argc, argv); + if (argc < 0) + return 1; + + for (argc = 1; argv[argc]; argc++) { + if (strcmp(argv[argc], "xml") == 0) + xo_set_style(NULL, XO_STYLE_XML); + else if (strcmp(argv[argc], "json") == 0) + xo_set_style(NULL, XO_STYLE_JSON); + else if (strcmp(argv[argc], "text") == 0) + xo_set_style(NULL, XO_STYLE_TEXT); + else if (strcmp(argv[argc], "html") == 0) + xo_set_style(NULL, XO_STYLE_HTML); + else if (strcmp(argv[argc], "pretty") == 0) + xo_set_flags(NULL, XOF_PRETTY); + else if (strcmp(argv[argc], "xpath") == 0) + xo_set_flags(NULL, XOF_XPATH); + else if (strcmp(argv[argc], "info") == 0) + xo_set_flags(NULL, XOF_INFO); + else if (strcmp(argv[argc], "error") == 0) { + close(-1); + xo_err(1, "error detected"); + } + } + + xo_set_flags(NULL, XOF_KEYS); + xo_set_program("test"); + + xo_open_container_h(NULL, "top"); + + xo_open_container("data"); + xo_open_container("contents"); + xo_open_list("item"); + + xo_emit("{T:Item/%-10s}{T:Count/%12s}\n"); + + for (ip = list; ip->i_title; ip++) { + xo_open_instance("item"); + + xo_emit("{k:name/%-10s/%s}{n:count/%12u/%u}\n", + ip->i_title, ip->i_count); + + xo_close_instance("item"); + } + + xo_close_list("item"); + xo_close_container("contents"); + xo_close_container("data"); + + xo_emit("\n\n"); + + xo_open_container("data"); + xo_open_container("contents"); + + xo_emit("{T:Item/%-10s}{T:Count/%12s}\n"); + + for (ip = list; ip->i_title; ip++) { + xo_open_instance("item"); + + xo_emit("{k:name/%-10s/%s}{n:count/%12u/%u}\n", + ip->i_title, ip->i_count); + } + + xo_close_container("data"); + + xo_emit("\n\n"); + + xo_open_container("data"); + xo_open_marker("m1"); + xo_open_container("contents"); + + xo_emit("{T:Item/%-10s}{T:Count/%12s}\n"); + + for (ip = list; ip->i_title; ip++) { + xo_open_instance("item"); + + xo_emit("{k:name/%-10s/%s}{n:count/%12u/%u}\n", + ip->i_title, ip->i_count); + } + + xo_close_container("data"); /* Should be a noop */ + xo_emit("{:test}", "one"); + + xo_close_marker("m1"); + xo_close_container("data"); /* Should be a noop */ + + xo_emit("\n\n"); + + xo_open_container("data"); + xo_open_marker("m1"); + xo_open_container("contents"); + + xo_emit("{T:Item/%-10s}{T:Count/%12s}\n"); + + for (ip = list; ip->i_title; ip++) { + xo_open_instance("item"); + + xo_emit("{k:name/%-10s/%s}{n:count/%12u/%u}\n", + ip->i_title, ip->i_count); + + xo_open_marker("m2"); + for (i = 0; i < 3; i++) { + xo_open_instance("sub"); + xo_emit("{Lwc:/Name}{:name/%d} + 1 = {:next/%d}\n", i, i + 1); + xo_close_container("data"); + } + xo_close_marker("m2"); + xo_emit("{Lwc:/Last}{:last/%d}\n", i); + } + + xo_close_container("data"); /* Should be a noop */ + xo_emit("{:test}", "one"); + + xo_emit("\n\n"); + + xo_close_container_h(NULL, "top"); + + xo_finish(); + + return 0; +} diff --git a/contrib/libxo/tests/core/test_09.c b/contrib/libxo/tests/core/test_09.c new file mode 100644 index 0000000..a612a64 --- /dev/null +++ b/contrib/libxo/tests/core/test_09.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2015, Juniper Networks, Inc. + * All rights reserved. + * This SOFTWARE is licensed under the LICENSE provided in the + * ../Copyright file. By downloading, installing, copying, or otherwise + * using the SOFTWARE, you agree to be bound by the terms of that + * LICENSE. + * Phil Shafer, July 2015 + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> + +#include "xo.h" + +int +main (int argc, char **argv) +{ + struct item { + const char *i_title; + int i_count; + }; + struct item list[] = { + { "gum", 1412 }, + { "rope", 85 }, + { "ladder", 0 }, + { "bolt", 4123 }, + { "water", 17 }, + { NULL, 0 } + }; + struct item *ip; + int i; + + argc = xo_parse_args(argc, argv); + if (argc < 0) + return 1; + + for (argc = 1; argv[argc]; argc++) { + if (strcmp(argv[argc], "xml") == 0) + xo_set_style(NULL, XO_STYLE_XML); + else if (strcmp(argv[argc], "json") == 0) + xo_set_style(NULL, XO_STYLE_JSON); + else if (strcmp(argv[argc], "text") == 0) + xo_set_style(NULL, XO_STYLE_TEXT); + else if (strcmp(argv[argc], "html") == 0) + xo_set_style(NULL, XO_STYLE_HTML); + else if (strcmp(argv[argc], "pretty") == 0) + xo_set_flags(NULL, XOF_PRETTY); + else if (strcmp(argv[argc], "xpath") == 0) + xo_set_flags(NULL, XOF_XPATH); + else if (strcmp(argv[argc], "info") == 0) + xo_set_flags(NULL, XOF_INFO); + else if (strcmp(argv[argc], "error") == 0) { + close(-1); + xo_err(1, "error detected"); + } + } + + xo_set_flags(NULL, XOF_KEYS); + xo_set_program("test"); + + xo_open_container_h(NULL, "top"); + + xo_open_container("data"); + xo_open_container("contents"); + + xo_emit("{T:Item/%-10s}{T:Count/%12s}\n"); + + for (ip = list; ip->i_title; ip++) { + xo_emit("Name: {l:name/%-10s/%s}\n", ip->i_title); + } + + xo_close_container("contents"); + + xo_emit("\n\n"); + xo_open_container("contents"); + + xo_emit("{T:Item/%-10s}{T:Count/%12s}\n"); + + for (ip = list; ip->i_title; ip++) { + xo_emit("Name: {l:item/%-10s/%s}\n", ip->i_title); + } + + xo_close_container("contents"); + + xo_emit("\n\n"); + + xo_open_container("contents"); + xo_emit("{T:Test/%-10s}{T:Three/%12s}\n"); + + xo_open_list("item"); + for (ip = list; ip->i_title; ip++) { + xo_emit("Name: {l:item/%-10s/%s}\n", ip->i_title); + } + xo_emit("{Lwc:/Total:}{:total}\n", "six"); + + xo_emit("{:one}", "one"); + xo_emit("{l:two}", "two"); + xo_emit("{:three}", "three"); + + + xo_close_container("contents"); + + xo_emit("\n\n"); + + xo_close_container_h(NULL, "top"); + + xo_finish(); + + return 0; +} diff --git a/contrib/libxo/xo/xo.1 b/contrib/libxo/xo/xo.1 index 1833b0a..12fc959 100644 --- a/contrib/libxo/xo/xo.1 +++ b/contrib/libxo/xo/xo.1 @@ -7,27 +7,29 @@ .\" # LICENSE. .\" # Phil Shafer, July 2014 .\" -.Dd July, 2014 -.Dt LIBXO 3 +.Dd December 4, 2014 +.Dt XO 1 .Os .Sh NAME .Nm xo .Nd emit formatted output based on format string and arguments .Sh SYNOPSIS -.Nm xo +.Nm .Op Fl options .Op Ar argument... .Sh DESCRIPTION The -.Nm xo +.Nm utility allows command line access to the functionality of the -.Em libxo -library. Using -.Nm xo , +.Nm libxo +library. +Using +.Nm , shell scripts can emit .Em XML , -.Em JSON , or +.Em JSON , +or .Em HTML using the same commands that emit text output. .Pp @@ -63,11 +65,11 @@ Wrap output in a set of containers .It Fl "-xml OR -X" Generate XML output .It Fl "-xpath" -Add XPath data to HTML output); +Add XPath data to HTML output .El .Pp The -.Nm xo +.Nm utility accepts a format string suitable for .Xr xo_emit 3 and a set of zero or more arguments used to supply data for that string. @@ -95,7 +97,8 @@ and a set of zero or more arguments used to supply data for that string. The .Fl "-wrap <path>" option can be used to wrap emitted content in a -specific hierarchy. The path is a set of hierarchical names separated +specific hierarchy. +The path is a set of hierarchical names separated by the '/' character. .Bd -literal -offset indent xo --wrap top/a/b/c '{:tag}' value @@ -128,11 +131,14 @@ and .Fl "\-close <path>" can be used to emit hierarchical information without the matching close and open -tag. This allows a shell script to emit open tags, data, and -then close tags. The +tag. +This allows a shell script to emit open tags, data, and +then close tags. +The .Fl \-depth option may be used to set the -depth for indentation. The +depth for indentation. +The .Fl "\-leading-xpath" may be used to prepend data to the XPath values used for HTML output style. @@ -154,37 +160,39 @@ prepend data to the XPath values used for HTML output style. } } .Ed -.Pp .Sh EXAMPLE -.Bd -literal -offset indent +.Bd -literal % xo 'The {:product} is {:status}\n' stereo "in route" The stereo is in route % xo -p -X 'The {:product} is {:status}\n' stereo "in route" <product>stereo</product> <status>in route</status> .Ed -.Pp .Sh ADDITIONAL DOCUMENTATION -.Pp Complete documentation can be found on github: .Bd -literal -offset indent http://juniper.github.io/libxo/libxo-manual.html .Ed .Pp -libxo lives on github as: +.Nm libxo +lives on github as: .Bd -literal -offset indent https://github.com/Juniper/libxo .Ed .Pp -The latest release of libxo is available at: +The latest release of +.Nm libxo +is available at: .Bd -literal -offset indent https://github.com/Juniper/libxo/releases .Ed .Sh SEE ALSO +.Xr libxo 3 , .Xr xo_emit 3 .Sh HISTORY The -.Fa libxo -library was added in FreeBSD 11.0. +.Nm libxo +library was added in +.Fx 11.0 . .Sh AUTHOR Phil Shafer diff --git a/contrib/libxo/xo/xo.c b/contrib/libxo/xo/xo.c index 698d9d6..c364539 100644 --- a/contrib/libxo/xo/xo.c +++ b/contrib/libxo/xo/xo.c @@ -362,8 +362,7 @@ main (int argc UNUSED, char **argv) } xo_set_formatter(NULL, formatter, checkpoint); - xo_set_flags(NULL, XOF_NO_VA_ARG); - xo_set_flags(NULL, XOF_NO_TOP); + xo_set_flags(NULL, XOF_NO_VA_ARG | XOF_NO_TOP | XOF_NO_CLOSE); fmt = *argv++; if (opt_opener == NULL && opt_closer == NULL && fmt == NULL) { diff --git a/contrib/libxo/xolint/Makefile.am b/contrib/libxo/xolint/Makefile.am index 0f8ef62..a847e72 100644 --- a/contrib/libxo/xolint/Makefile.am +++ b/contrib/libxo/xolint/Makefile.am @@ -11,4 +11,4 @@ man_MANS = xolint.1 EXTRA_DIST = xolint.1 xolint.pl install-exec-hook: - install ${srcdir}/xolint.pl ${bindir}/xolint + install ${srcdir}/xolint.pl ${DESTDIR}${bindir}/xolint diff --git a/contrib/libxo/xolint/xolint.1 b/contrib/libxo/xolint/xolint.1 index b7ed130..fcf7bcd 100644 --- a/contrib/libxo/xolint/xolint.1 +++ b/contrib/libxo/xolint/xolint.1 @@ -7,12 +7,13 @@ .\" # LICENSE. .\" # Phil Shafer, July 2014 .\" -.Dd July, 2014 -.Dt LIBXO 3 +.Dd December 4, 2014 +.Dt XOLINT 1 .Os .Sh NAME .Nm xolint -.Nd detect errors in programs using xo_emit +.Nd detect errors in programs using +.Xr xo_emit 3 .Sh SYNOPSIS .Nm xolint .Op Fl c @@ -25,34 +26,45 @@ .Op Fl "X" .Op Ar files... .Sh DESCRIPTION -xolint is a tool for reporting common mistakes in format strings -in source code that invokes xo_emit(). It allows these errors +.Nm +is a tool for reporting common mistakes in format strings +in source code that invokes +.Xr xo_emit 3 . +It allows these errors to be diagnosed at build time, rather than waiting until runtime. .Pp -xolint takes the one or more C files as arguments, and reports -and errors, warning, or informational messages as needed. +.Nm +takes one or more C files as arguments, and reports +error, warning, or informational messages as needed. .Bl -tag -width "C <flags>" .It Fl c Invoke 'cpp' against the input file .It Fl "C <flags>" -Flags that are passed to 'cpp +Flags that are passed to 'cpp' .It Fl "d" Enable debug output .It Fl "D" -Generate documentation for all xolint messages +Generate documentation for all +.Nm +messages .It Fl "I" -Generate a table of xo_info_t structures. +Generate a table of +.Dv xo_info_t +structures. .It Fl "p" Print the offending lines after the error message is displayed .It Fl "V" Do not report errors, but instead print a complete list of -all field names, sorted alphabetically. The output can help spot +all field names, sorted alphabetically. +The output can help spot inconsistencies and spelling errors. .It Fl "X" -Extract samples from xolint, suitable for internal testing. +Extract samples from +.Nm , +suitable for internal testing. .El .Pp -Output message contain the source filename and line number, the +The output message contains the source filename and line number, the class of the message, the message, and, if .Fl p is given, the @@ -62,28 +74,31 @@ line that contains the error: xolint.c: 16: error: anchor format should be "%d" 16 xo_emit("{[:/%s}"); .Ed -.Pp .Sh ADDITIONAL DOCUMENTATION -.Pp Complete documentation can be found on github: .Bd -literal -offset indent http://juniper.github.io/libxo/libxo-manual.html .Ed .Pp -libxo lives on github as: +.Nm libxo +lives on github as: .Bd -literal -offset indent https://github.com/Juniper/libxo .Ed .Pp -The latest release of libxo is available at: +The latest release of +.Nm libxo +is available at: .Bd -literal -offset indent https://github.com/Juniper/libxo/releases .Ed .Sh SEE ALSO +.Xr libxo 3 , .Xr xo_emit 3 .Sh HISTORY The -.Fa libxo -library was added in FreeBSD 10.1. +.Nm libxo +library was added in +.Fx 10.1 . .Sh AUTHOR Phil Shafer diff --git a/lib/libxo/Makefile b/lib/libxo/Makefile index 770db20..cc0e72a 100644 --- a/lib/libxo/Makefile +++ b/lib/libxo/Makefile @@ -21,6 +21,7 @@ MAN+= xo_attr.3 \ xo_create.3 \ xo_emit.3 \ xo_err.3 \ + xo_error.3 \ xo_finish.3 \ xo_flush.3 \ xo_no_setlocale.3 \ |