Update to FreeBSD head 2019-09-24

Git mirror commit 6b0307a0a5184339393f555d5d424190d8a8277a.
This commit is contained in:
Sebastian Huber
2019-09-24 11:05:03 +02:00
parent 83afe13399
commit a5ddb0ea69
903 changed files with 39332 additions and 17958 deletions

View File

@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
* Copyright (c) 2014-2015, Juniper Networks, Inc.
* Copyright (c) 2014-2019, Juniper Networks, Inc.
* All rights reserved.
* This SOFTWARE is licensed under the LICENSE provided in the
* ../Copyright file. By downloading, installing, copying, or otherwise
@@ -49,6 +49,7 @@
#include "xo.h"
#include "xo_encoder.h"
#include "xo_buf.h"
#include "xo_explicit.h"
/*
* We ask wcwidth() to do an impossible job, really. It's supposed to
@@ -163,40 +164,9 @@ typedef unsigned xo_xsf_flags_t; /* XSF_* flags */
(XSF_NOT_FIRST | XSF_CONTENT | XSF_EMIT | XSF_EMIT_KEY | XSF_EMIT_LEAF_LIST )
/*
* A word about states: We use a finite state machine (FMS) approach
* to help remove fragility from the caller's code. Instead of
* requiring a specific order of calls, we'll allow the caller more
* flexibility and make the library responsible for recovering from
* missed steps. The goal is that the library should not be capable
* of emitting invalid xml or json, but the developer shouldn't need
* to know or understand all the details about these encodings.
*
* You can think of states as either states or events, since they
* function rather like both. None of the XO_CLOSE_* events will
* persist as states, since the matching stack frame will be popped.
* Same is true of XSS_EMIT, which is an event that asks us to
* prep for emitting output fields.
* Turn the transition between two states into a number suitable for
* a "switch" statement.
*/
/* Stack frame states */
typedef unsigned xo_state_t;
#define XSS_INIT 0 /* Initial stack state */
#define XSS_OPEN_CONTAINER 1
#define XSS_CLOSE_CONTAINER 2
#define XSS_OPEN_LIST 3
#define XSS_CLOSE_LIST 4
#define XSS_OPEN_INSTANCE 5
#define XSS_CLOSE_INSTANCE 6
#define XSS_OPEN_LEAF_LIST 7
#define XSS_CLOSE_LEAF_LIST 8
#define XSS_DISCARDING 9 /* Discarding data until recovered */
#define XSS_MARKER 10 /* xo_open_marker's marker */
#define XSS_EMIT 11 /* xo_emit has a leaf field */
#define XSS_EMIT_LEAF_LIST 12 /* xo_emit has a leaf-list ({l:}) */
#define XSS_FINISH 13 /* xo_finish was called */
#define XSS_MAX 13
#define XSS_TRANSITION(_old, _new) ((_old) << 8 | (_new))
/*
@@ -293,8 +263,8 @@ struct xo_handle_s {
ssize_t xo_units_offset; /* Start of units insertion point */
ssize_t xo_columns; /* Columns emitted during this xo_emit call */
#ifndef LIBXO_TEXT_ONLY
uint8_t xo_color_map_fg[XO_NUM_COLORS]; /* Foreground color mappings */
uint8_t xo_color_map_bg[XO_NUM_COLORS]; /* Background color mappings */
xo_color_t xo_color_map_fg[XO_NUM_COLORS]; /* Foreground color mappings */
xo_color_t xo_color_map_bg[XO_NUM_COLORS]; /* Background color mappings */
#endif /* LIBXO_TEXT_ONLY */
xo_colors_t xo_colors; /* Current color and effect values */
xo_buffer_t xo_color_buf; /* HTML: buffer of colors and effects */
@@ -326,6 +296,7 @@ struct xo_handle_s {
#define XOIF_UNITS_PENDING XOF_BIT(4) /* We have a units-insertion pending */
#define XOIF_INIT_IN_PROGRESS XOF_BIT(5) /* Init of handle is in progress */
#define XOIF_MADE_OUTPUT XOF_BIT(6) /* Have already made output */
/* Flags for formatting functions */
typedef unsigned long xo_xff_flags_t;
@@ -473,7 +444,7 @@ static void
xo_failure (xo_handle_t *xop, const char *fmt, ...);
static ssize_t
xo_transition (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name,
xo_transition (xo_handle_t *xop, xo_xof_flags_t flags, const char *name,
xo_state_t new_state);
static int
@@ -510,6 +481,20 @@ xo_style (xo_handle_t *xop UNUSED)
#endif /* LIBXO_TEXT_ONLY */
}
/*
* Allow the compiler to optimize out non-text-only code while
* still compiling it.
*/
static inline int
xo_text_only (void)
{
#ifdef LIBXO_TEXT_ONLY
return TRUE;
#else /* LIBXO_TEXT_ONLY */
return FALSE;
#endif /* LIBXO_TEXT_ONLY */
}
/*
* Callback to write data to a FILE pointer
*/
@@ -611,6 +596,28 @@ xo_no_setlocale (void)
xo_locale_inited = 1; /* Skip initialization */
}
/*
* For XML, the first character of a tag cannot be numeric, but people
* will likely not notice. So we people-proof them by forcing a leading
* underscore if they use invalid tags. Note that this doesn't cover
* all broken tags, just this fairly specific case.
*/
static const char *
xo_xml_leader_len (xo_handle_t *xop, const char *name, xo_ssize_t nlen)
{
if (name == NULL || isalpha(name[0]) || name[0] == '_')
return "";
xo_failure(xop, "invalid XML tag name: '%.*s'", nlen, name);
return "_";
}
static const char *
xo_xml_leader (xo_handle_t *xop, const char *name)
{
return xo_xml_leader_len(xop, name, strlen(name));
}
/*
* We need to decide if stdout is line buffered (_IOLBF). Lacking a
* standard way to decide this (e.g. getlinebuf()), we have configure
@@ -2199,9 +2206,8 @@ xo_set_style_name (xo_handle_t *xop, const char *name)
static void
xo_set_color_map (xo_handle_t *xop, char *value)
{
#ifdef LIBXO_TEXT_ONLY
return;
#endif /* LIBXO_TEXT_ONLY */
if (xo_text_only())
return;
char *cp, *ep, *vp, *np;
ssize_t len = value ? strlen(value) + 1 : 0;
@@ -2219,8 +2225,11 @@ xo_set_color_map (xo_handle_t *xop, char *value)
fg = *cp ? xo_color_find(cp) : -1;
bg = (vp && *vp) ? xo_color_find(vp) : -1;
#ifndef LIBXO_TEXT_ONLY
xop->xo_color_map_fg[num] = (fg < 0) ? num : fg;
xop->xo_color_map_bg[num] = (bg < 0) ? num : bg;
#endif /* LIBXO_TEXT_ONLY */
if (++num > XO_NUM_COLORS)
break;
}
@@ -2231,9 +2240,11 @@ xo_set_color_map (xo_handle_t *xop, char *value)
else
XOF_CLEAR(xop, XOF_COLOR_MAP);
#ifndef LIBXO_TEXT_ONLY
/* Fill in the rest of the colors with the defaults */
for ( ; num < XO_NUM_COLORS; num++)
xop->xo_color_map_fg[num] = xop->xo_color_map_bg[num] = num;
#endif /* LIBXO_TEXT_ONLY */
}
static int
@@ -2605,6 +2616,12 @@ xo_line_ensure_open (xo_handle_t *xop, xo_xff_flags_t flags UNUSED)
static char div_open[] = "<div class=\"line\">";
static char div_open_blank[] = "<div class=\"blank-line\">";
if (XOF_ISSET(xop, XOF_CONTINUATION)) {
XOF_CLEAR(xop, XOF_CONTINUATION);
XOIF_SET(xop, XOIF_DIV_OPEN);
return;
}
if (XOIF_ISSET(xop, XOIF_DIV_OPEN))
return;
@@ -3510,51 +3527,54 @@ xo_do_format_field (xo_handle_t *xop, xo_buffer_t *xbp,
ssize_t columns = rc = xo_vsnprintf(xop, xbp, newfmt,
xop->xo_vap);
/*
* For XML and HTML, we need "&<>" processing; for JSON,
* it's quotes. Text gets nothing.
*/
switch (style) {
case XO_STYLE_XML:
if (flags & XFF_TRIM_WS)
columns = rc = xo_trim_ws(xbp, rc);
/* FALLTHRU */
case XO_STYLE_HTML:
rc = xo_escape_xml(xbp, rc, (flags & XFF_ATTR));
break;
if (rc > 0) {
/*
* For XML and HTML, we need "&<>" processing; for JSON,
* it's quotes. Text gets nothing.
*/
switch (style) {
case XO_STYLE_XML:
if (flags & XFF_TRIM_WS)
columns = rc = xo_trim_ws(xbp, rc);
/* FALLTHRU */
case XO_STYLE_HTML:
rc = xo_escape_xml(xbp, rc, (flags & XFF_ATTR));
break;
case XO_STYLE_JSON:
if (flags & XFF_TRIM_WS)
columns = rc = xo_trim_ws(xbp, rc);
rc = xo_escape_json(xbp, rc, 0);
break;
case XO_STYLE_JSON:
if (flags & XFF_TRIM_WS)
columns = rc = xo_trim_ws(xbp, rc);
rc = xo_escape_json(xbp, rc, 0);
break;
case XO_STYLE_SDPARAMS:
if (flags & XFF_TRIM_WS)
columns = rc = xo_trim_ws(xbp, rc);
rc = xo_escape_sdparams(xbp, rc, 0);
break;
case XO_STYLE_SDPARAMS:
if (flags & XFF_TRIM_WS)
columns = rc = xo_trim_ws(xbp, rc);
rc = xo_escape_sdparams(xbp, rc, 0);
break;
case XO_STYLE_ENCODER:
if (flags & XFF_TRIM_WS)
columns = rc = xo_trim_ws(xbp, rc);
break;
case XO_STYLE_ENCODER:
if (flags & XFF_TRIM_WS)
columns = rc = xo_trim_ws(xbp, rc);
break;
}
/*
* We can assume all the non-%s data we've
* added is ASCII, so the columns and bytes are the
* same. xo_format_string handles all the fancy
* string conversions and updates xo_anchor_columns
* accordingly.
*/
if (XOF_ISSET(xop, XOF_COLUMNS))
xop->xo_columns += columns;
if (XOIF_ISSET(xop, XOIF_ANCHOR))
xop->xo_anchor_columns += columns;
}
/*
* We can assume all the non-%s data we've
* added is ASCII, so the columns and bytes are the
* same. xo_format_string handles all the fancy
* string conversions and updates xo_anchor_columns
* accordingly.
*/
if (XOF_ISSET(xop, XOF_COLUMNS))
xop->xo_columns += columns;
if (XOIF_ISSET(xop, XOIF_ANCHOR))
xop->xo_anchor_columns += columns;
}
xbp->xb_curp += rc;
if (rc > 0)
xbp->xb_curp += rc;
}
/*
@@ -4238,6 +4258,21 @@ xo_format_is_numeric (const char *fmt, ssize_t flen)
return (strchr("diouDOUeEfFgG", *fmt) == NULL) ? FALSE : TRUE;
}
/*
* Update the stack flags using the object flags, allowing callers
* to monkey with the stack flags without even knowing they exist.
*/
static void
xo_stack_set_flags (xo_handle_t *xop)
{
if (XOF_ISSET(xop, XOF_NOT_FIRST)) {
xo_stack_t *xsp = &xop->xo_stack[xop->xo_depth];
xsp->xs_flags |= XSF_NOT_FIRST;
XOF_CLEAR(xop, XOF_NOT_FIRST);
}
}
static void
xo_format_prep (xo_handle_t *xop, xo_xff_flags_t flags)
{
@@ -4342,6 +4377,8 @@ xo_format_value (xo_handle_t *xop, const char *name, ssize_t nlen,
xo_buffer_t *xbp = &xop->xo_data;
xo_humanize_save_t save; /* Save values for humanizing logic */
const char *leader = xo_xml_leader_len(xop, name, nlen);
switch (xo_style(xop)) {
case XO_STYLE_TEXT:
if (flags & XFF_ENCODE_ONLY)
@@ -4396,6 +4433,8 @@ xo_format_value (xo_handle_t *xop, const char *name, ssize_t nlen,
if (pretty)
xo_buf_indent(xop, -1);
xo_data_append(xop, "<", 1);
if (*leader)
xo_data_append(xop, leader, 1);
xo_data_escape(xop, name, nlen);
if (xop->xo_attrs.xb_curp != xop->xo_attrs.xb_bufp) {
@@ -4428,6 +4467,8 @@ xo_format_value (xo_handle_t *xop, const char *name, ssize_t nlen,
xo_simple_field(xop, FALSE, value, vlen, fmt, flen, flags);
xo_data_append(xop, "</", 2);
if (*leader)
xo_data_append(xop, leader, 1);
xo_data_escape(xop, name, nlen);
xo_data_append(xop, ">", 1);
if (pretty)
@@ -4451,6 +4492,8 @@ xo_format_value (xo_handle_t *xop, const char *name, ssize_t nlen,
flen = strlen(fmt);
}
xo_stack_set_flags(xop);
int first = (xop->xo_stack[xop->xo_depth].xs_flags & XSF_NOT_FIRST)
? 0 : 1;
@@ -4756,9 +4799,8 @@ xo_effect_find (const char *str)
static void
xo_colors_parse (xo_handle_t *xop, xo_colors_t *xocp, char *str)
{
#ifdef LIBXO_TEXT_ONLY
return;
#endif /* LIBXO_TEXT_ONLY */
if (xo_text_only())
return;
char *cp, *ep, *np, *xp;
ssize_t len = strlen(str);
@@ -4842,12 +4884,9 @@ xo_colors_enabled (xo_handle_t *xop UNUSED)
* the incoming foreground and background colors from the map.
*/
static void
xo_colors_update (xo_handle_t *xop, xo_colors_t *newp)
xo_colors_update (xo_handle_t *xop UNUSED, xo_colors_t *newp UNUSED)
{
#ifdef LIBXO_TEXT_ONLY
return;
#endif /* LIBXO_TEXT_ONLY */
#ifndef LIBXO_TEXT_ONLY
xo_color_t fg = newp->xoc_col_fg;
if (XOF_ISSET(xop, XOF_COLOR_MAP) && fg < XO_NUM_COLORS)
fg = xop->xo_color_map_fg[fg]; /* Fetch from color map */
@@ -4857,6 +4896,7 @@ xo_colors_update (xo_handle_t *xop, xo_colors_t *newp)
if (XOF_ISSET(xop, XOF_COLOR_MAP) && bg < XO_NUM_COLORS)
bg = xop->xo_color_map_bg[bg]; /* Fetch from color map */
newp->xoc_col_bg = bg;
#endif /* LIBXO_TEXT_ONLY */
}
static void
@@ -6459,9 +6499,7 @@ xo_do_emit_fields (xo_handle_t *xop, xo_field_info_t *fields,
/* If we don't have an anchor, write the text out */
if (flush && !XOIF_ISSET(xop, XOIF_ANCHOR)) {
if (xo_write(xop) < 0)
rc = -1; /* Report failure */
else if (xo_flush_h(xop) < 0)
if (xo_flush_h(xop) < 0)
rc = -1;
}
@@ -6808,17 +6846,6 @@ xo_attr (const char *name, const char *fmt, ...)
return rc;
}
static void
xo_stack_set_flags (xo_handle_t *xop)
{
if (XOF_ISSET(xop, XOF_NOT_FIRST)) {
xo_stack_t *xsp = &xop->xo_stack[xop->xo_depth];
xsp->xs_flags |= XSF_NOT_FIRST;
XOF_CLEAR(xop, XOF_NOT_FIRST);
}
}
static void
xo_depth_change (xo_handle_t *xop, const char *name,
int delta, int indent, xo_state_t state, xo_xsf_flags_t flags)
@@ -6894,6 +6921,15 @@ xo_set_depth (xo_handle_t *xop, int depth)
xop->xo_depth += depth;
xop->xo_indent += depth;
/*
* Handling the "top wrapper" for JSON is a bit of a pain. Here
* we need to detect that the depth has been changed to set the
* "XOIF_TOP_EMITTED" flag correctly.
*/
if (xop->xo_style == XO_STYLE_JSON
&& !XOF_ISSET(xop, XOF_NO_TOP) && xop->xo_depth > 0)
XOIF_SET(xop, XOIF_TOP_EMITTED);
}
static xo_xsf_flags_t
@@ -6930,11 +6966,12 @@ xo_do_open_container (xo_handle_t *xop, xo_xof_flags_t flags, const char *name)
name = XO_FAILURE_NAME;
}
const char *leader = xo_xml_leader(xop, name);
flags |= xop->xo_flags; /* Pick up handle flags */
switch (xo_style(xop)) {
case XO_STYLE_XML:
rc = xo_printf(xop, "%*s<%s", xo_indent(xop), "", name);
rc = xo_printf(xop, "%*s<%s%s", xo_indent(xop), "", leader, name);
if (xop->xo_attrs.xb_curp != xop->xo_attrs.xb_bufp) {
rc += xop->xo_attrs.xb_curp - xop->xo_attrs.xb_bufp;
@@ -6975,7 +7012,7 @@ xo_do_open_container (xo_handle_t *xop, xo_xof_flags_t flags, const char *name)
return rc;
}
static int
xo_ssize_t
xo_open_container_hf (xo_handle_t *xop, xo_xof_flags_t flags, const char *name)
{
return xo_transition(xop, flags, name, XSS_OPEN_CONTAINER);
@@ -7030,15 +7067,20 @@ xo_do_close_container (xo_handle_t *xop, const char *name)
}
}
const char *leader = xo_xml_leader(xop, name);
switch (xo_style(xop)) {
case XO_STYLE_XML:
xo_depth_change(xop, name, -1, -1, XSS_CLOSE_CONTAINER, 0);
rc = xo_printf(xop, "%*s</%s>%s", xo_indent(xop), "", name, ppn);
rc = xo_printf(xop, "%*s</%s%s>%s", xo_indent(xop), "", leader, name, ppn);
break;
case XO_STYLE_JSON:
xo_stack_set_flags(xop);
pre_nl = XOF_ISSET(xop, XOF_PRETTY) ? "\n" : "";
ppn = (xop->xo_depth <= 1) ? "\n" : "";
ppn = (xop->xo_depth <= 1) ? pre_nl : "";
ppn = "";
xo_depth_change(xop, name, -1, -1, XSS_CLOSE_CONTAINER, 0);
rc = xo_printf(xop, "%s%*s}%s", pre_nl, xo_indent(xop), "", ppn);
@@ -7087,7 +7129,7 @@ xo_close_container_d (void)
}
static int
xo_do_open_list (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name)
xo_do_open_list (xo_handle_t *xop, xo_xof_flags_t flags, const char *name)
{
ssize_t rc = 0;
int indent = 0;
@@ -7131,8 +7173,8 @@ xo_do_open_list (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name)
return rc;
}
static int
xo_open_list_hf (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name)
xo_ssize_t
xo_open_list_hf (xo_handle_t *xop, xo_xof_flags_t flags, const char *name)
{
return xo_transition(xop, flags, name, XSS_OPEN_LIST);
}
@@ -7233,7 +7275,7 @@ xo_close_list_d (void)
}
static int
xo_do_open_leaf_list (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name)
xo_do_open_leaf_list (xo_handle_t *xop, xo_xof_flags_t flags, const char *name)
{
ssize_t rc = 0;
int indent = 0;
@@ -7327,7 +7369,7 @@ xo_do_close_leaf_list (xo_handle_t *xop, const char *name)
}
static int
xo_do_open_instance (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name)
xo_do_open_instance (xo_handle_t *xop, xo_xof_flags_t flags, const char *name)
{
xop = xo_default(xop);
@@ -7335,16 +7377,17 @@ xo_do_open_instance (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name)
const char *ppn = XOF_ISSET(xop, XOF_PRETTY) ? "\n" : "";
const char *pre_nl = "";
flags |= xop->xo_flags;
if (name == NULL) {
xo_failure(xop, "NULL passed for instance name");
name = XO_FAILURE_NAME;
}
const char *leader = xo_xml_leader(xop, name);
flags |= xop->xo_flags;
switch (xo_style(xop)) {
case XO_STYLE_XML:
rc = xo_printf(xop, "%*s<%s", xo_indent(xop), "", name);
rc = xo_printf(xop, "%*s<%s%s", xo_indent(xop), "", leader, name);
if (xop->xo_attrs.xb_curp != xop->xo_attrs.xb_bufp) {
rc += xop->xo_attrs.xb_curp - xop->xo_attrs.xb_bufp;
@@ -7380,8 +7423,8 @@ xo_do_open_instance (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name)
return rc;
}
static int
xo_open_instance_hf (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name)
xo_ssize_t
xo_open_instance_hf (xo_handle_t *xop, xo_xof_flags_t flags, const char *name)
{
return xo_transition(xop, flags, name, XSS_OPEN_INSTANCE);
}
@@ -7435,10 +7478,12 @@ xo_do_close_instance (xo_handle_t *xop, const char *name)
}
}
const char *leader = xo_xml_leader(xop, name);
switch (xo_style(xop)) {
case XO_STYLE_XML:
xo_depth_change(xop, name, -1, -1, XSS_CLOSE_INSTANCE, 0);
rc = xo_printf(xop, "%*s</%s>%s", xo_indent(xop), "", name, ppn);
rc = xo_printf(xop, "%*s</%s%s>%s", xo_indent(xop), "", leader, name, ppn);
break;
case XO_STYLE_JSON:
@@ -7604,7 +7649,7 @@ xo_do_close (xo_handle_t *xop, const char *name, xo_state_t new_state)
* We are in a given state and need to transition to the new state.
*/
static ssize_t
xo_transition (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name,
xo_transition (xo_handle_t *xop, xo_xof_flags_t flags, const char *name,
xo_state_t new_state)
{
xo_stack_t *xsp;
@@ -7860,9 +7905,12 @@ xo_transition (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name,
/* Handle the flush flag */
if (rc >= 0 && XOF_ISSET(xop, XOF_FLUSH))
if (xo_flush_h(xop))
if (xo_flush_h(xop) < 0)
rc = -1;
/* We have now official made output */
XOIF_SET(xop, XOIF_MADE_OUTPUT);
return rc;
marker_prevents_close:
@@ -7955,7 +8003,7 @@ xo_flush (void)
xo_ssize_t
xo_finish_h (xo_handle_t *xop)
{
const char *cp = "";
const char *open_if_empty = "";
xop = xo_default(xop);
if (!XOF_ISSET(xop, XOF_NO_CLOSE))
@@ -7964,11 +8012,17 @@ xo_finish_h (xo_handle_t *xop)
switch (xo_style(xop)) {
case XO_STYLE_JSON:
if (!XOF_ISSET(xop, XOF_NO_TOP)) {
const char *pre_nl = XOF_ISSET(xop, XOF_PRETTY) ? "\n" : "";
if (XOIF_ISSET(xop, XOIF_TOP_EMITTED))
XOIF_CLEAR(xop, XOIF_TOP_EMITTED); /* Turn off before output */
else
cp = "{ ";
xo_printf(xop, "%*s%s}\n",xo_indent(xop), "", cp);
else if (!XOIF_ISSET(xop, XOIF_MADE_OUTPUT)) {
open_if_empty = "{ ";
pre_nl = "";
}
xo_printf(xop, "%s%*s%s}\n",
pre_nl, xo_indent(xop), "", open_if_empty);
}
break;
@@ -8407,3 +8461,46 @@ xo_set_encoder (xo_handle_t *xop, xo_encoder_func_t encoder)
xop->xo_style = XO_STYLE_ENCODER;
xop->xo_encoder = encoder;
}
/*
* The xo(1) utility needs to be able to open and close lists and
* instances, but since it's called without "state", we cannot
* rely on the state transitions (in xo_transition) to DTRT, so
* we have a mechanism for external parties to "force" transitions
* that would otherwise be impossible. This is not a general
* mechanism, and is really tailored only for xo(1).
*/
void
xo_explicit_transition (xo_handle_t *xop, xo_state_t new_state,
const char *name, xo_xof_flags_t flags)
{
xo_xsf_flags_t xsf_flags;
xop = xo_default(xop);
switch (new_state) {
case XSS_OPEN_LIST:
xo_do_open_list(xop, flags, name);
break;
case XSS_OPEN_INSTANCE:
xo_do_open_instance(xop, flags, name);
break;
case XSS_CLOSE_INSTANCE:
xo_depth_change(xop, name, 1, 1, XSS_OPEN_INSTANCE,
xo_stack_flags(flags));
xo_stack_set_flags(xop);
xo_do_close_instance(xop, name);
break;
case XSS_CLOSE_LIST:
xsf_flags = XOF_ISSET(xop, XOF_NOT_FIRST) ? XSF_NOT_FIRST : 0;
xo_depth_change(xop, name, 1, 1, XSS_OPEN_LIST,
XSF_LIST | xsf_flags | xo_stack_flags(flags));
xo_do_close_list(xop, name);
break;
}
}

View File

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

View File

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

View File

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