diff options
Diffstat (limited to 'freebsd/contrib/libxo/libxo/libxo.c')
-rw-r--r-- | freebsd/contrib/libxo/libxo/libxo.c | 345 |
1 files changed, 221 insertions, 124 deletions
diff --git a/freebsd/contrib/libxo/libxo/libxo.c b/freebsd/contrib/libxo/libxo/libxo.c index 0287360f..e1de7b38 100644 --- a/freebsd/contrib/libxo/libxo/libxo.c +++ b/freebsd/contrib/libxo/libxo/libxo.c @@ -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 @@ -511,6 +482,20 @@ xo_style (xo_handle_t *xop UNUSED) } /* + * 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 */ static xo_ssize_t @@ -612,6 +597,28 @@ xo_no_setlocale (void) } /* + * 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 * look to find __flbf, which glibc supported. If not, we'll rely on @@ -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; - - 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; + 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_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; } @@ -6809,17 +6847,6 @@ xo_attr (const char *name, const char *fmt, ...) } 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; + } +} |