diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-08-07 14:56:50 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-09-21 10:29:37 +0200 |
commit | c37f9fba70085fedc8eede7559489d2321393005 (patch) | |
tree | 042455ebf1fa89a277a825f72e1ed805d0b4d296 /freebsd/contrib | |
parent | Update to FreeBSD head 2017-06-01 (diff) | |
download | rtems-libbsd-c37f9fba70085fedc8eede7559489d2321393005.tar.bz2 |
Update to FreeBSD head 2017-08-01
Git mirror commit f5002f5e5f78cae9f0269d812dc0aedb0339312c.
Update #3472.
Diffstat (limited to 'freebsd/contrib')
-rw-r--r-- | freebsd/contrib/libxo/libxo/libxo.c | 672 | ||||
-rw-r--r-- | freebsd/contrib/libxo/libxo/xo.h | 2 | ||||
-rw-r--r-- | freebsd/contrib/libxo/libxo/xo_buf.h | 2 | ||||
-rw-r--r-- | freebsd/contrib/libxo/libxo/xo_encoder.c | 8 | ||||
-rw-r--r-- | freebsd/contrib/libxo/libxo/xo_encoder.h | 5 |
5 files changed, 462 insertions, 227 deletions
diff --git a/freebsd/contrib/libxo/libxo/libxo.c b/freebsd/contrib/libxo/libxo/libxo.c index f36e7480..d922ba0b 100644 --- a/freebsd/contrib/libxo/libxo/libxo.c +++ b/freebsd/contrib/libxo/libxo/libxo.c @@ -97,6 +97,14 @@ #include <libintl.h> #endif /* HAVE_GETTEXT */ +/* Rather lame that we can't count on these... */ +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif + /* * Three styles of specifying thread-local variables are supported. * configure.ac has the brains to run each possibility through the @@ -205,6 +213,7 @@ typedef struct xo_stack_s { * XO_COL_* ("colors") refers to fancy ansi codes, while X__EFF_* * ("effects") are bits since we need to maintain state. */ +typedef uint8_t xo_color_t; #define XO_COL_DEFAULT 0 #define XO_COL_BLACK 1 #define XO_COL_RED 2 @@ -240,7 +249,6 @@ typedef struct xo_stack_s { #define XO_EFF_CLEAR_BITS XO_EFF_RESET /* Reset gets reset, surprisingly */ typedef uint8_t xo_effect_t; -typedef uint8_t xo_color_t; typedef struct xo_colors_s { xo_effect_t xoc_effects; /* Current effect set */ xo_color_t xoc_col_fg; /* Foreground color */ @@ -281,8 +289,10 @@ struct xo_handle_s { ssize_t xo_anchor_min_width; /* Desired width of anchored text */ 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 */ +#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 */ char *xo_version; /* Version string */ @@ -463,10 +473,17 @@ static ssize_t xo_transition (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name, xo_state_t new_state); +static int +xo_set_options_simple (xo_handle_t *xop, const char *input); + +static int +xo_color_find (const char *str); + static void xo_buf_append_div (xo_handle_t *xop, const char *class, xo_xff_flags_t flags, const char *name, ssize_t nlen, const char *value, ssize_t vlen, + const char *fmt, ssize_t flen, const char *encoding, ssize_t elen); static void @@ -630,13 +647,6 @@ xo_init_handle (xo_handle_t *xop) XOF_SET(xop, XOF_FLUSH_LINE); /* - * We only want to do color output on terminals, but we only want - * to do this if the user has asked for color. - */ - if (XOF_ISSET(xop, XOF_COLOR_ALLOWED) && isatty(1)) - XOF_SET(xop, XOF_COLOR); - - /* * We need to initialize the locale, which isn't really pretty. * Libraries should depend on their caller to set up the * environment. But we really can't count on the caller to do @@ -669,15 +679,6 @@ xo_init_handle (xo_handle_t *xop) xop->xo_indent_by = XO_INDENT_BY; xo_depth_check(xop, XO_DEPTH); -#if !defined(NO_LIBXO_OPTIONS) - if (!XOF_ISSET(xop, XOF_NO_ENV)) { - char *env = getenv("LIBXO_OPTIONS"); - if (env) - xo_set_options(xop, env); - - } -#endif /* NO_GETENV */ - XOIF_CLEAR(xop, XOIF_INIT_IN_PROGRESS); } @@ -691,6 +692,16 @@ xo_default_init (void) xo_init_handle(xop); +#if !defined(NO_LIBXO_OPTIONS) + if (!XOF_ISSET(xop, XOF_NO_ENV)) { + char *env = getenv("LIBXO_OPTIONS"); + + if (env) + xo_set_options_simple(xop, env); + + } +#endif /* NO_LIBXO_OPTIONS */ + xo_default_inited = 1; } @@ -1043,32 +1054,36 @@ xo_printf (xo_handle_t *xop, const char *fmt, ...) * These next few function are make The Essential UTF-8 Ginsu Knife. * Identify an input and output character, and convert it. */ -static uint8_t xo_utf8_bits[7] = { 0, 0x7f, 0x1f, 0x0f, 0x07, 0x03, 0x01 }; +static uint8_t xo_utf8_data_bits[5] = { 0, 0x7f, 0x1f, 0x0f, 0x07 }; +static uint8_t xo_utf8_len_bits[5] = { 0, 0x00, 0xc0, 0xe0, 0xf0 }; +/* + * If the byte has a high-bit set, it's UTF-8, not ASCII. + */ static int xo_is_utf8 (char ch) { return (ch & 0x80); } +/* + * Look at the high bits of the first byte to determine the length + * of the UTF-8 character. + */ static inline ssize_t xo_utf8_to_wc_len (const char *buf) { - unsigned b = (unsigned char) *buf; + uint8_t bval = (uint8_t) *buf; ssize_t len; - if ((b & 0x80) == 0x0) + if ((bval & 0x80) == 0x0) len = 1; - else if ((b & 0xe0) == 0xc0) + else if ((bval & 0xe0) == 0xc0) len = 2; - else if ((b & 0xf0) == 0xe0) + else if ((bval & 0xf0) == 0xe0) len = 3; - else if ((b & 0xf8) == 0xf0) + else if ((bval & 0xf8) == 0xf0) len = 4; - else if ((b & 0xfc) == 0xf8) - len = 5; - else if ((b & 0xfe) == 0xfc) - len = 6; else len = -1; @@ -1078,12 +1093,11 @@ xo_utf8_to_wc_len (const char *buf) static ssize_t xo_buf_utf8_len (xo_handle_t *xop, const char *buf, ssize_t bufsiz) { - unsigned b = (unsigned char) *buf; ssize_t len, i; len = xo_utf8_to_wc_len(buf); - if (len == -1) { + if (len < 0) { xo_failure(xop, "invalid UTF-8 data: %02hhx", b); return -1; } @@ -1121,9 +1135,9 @@ xo_utf8_char (const char *buf, ssize_t len) wchar_t wc; const unsigned char *cp = (const unsigned char *) buf; - wc = *cp & xo_utf8_bits[len]; + wc = *cp & xo_utf8_data_bits[len]; for (i = 1; i < len; i++) { - wc <<= 6; + wc <<= 6; /* Low six bits have data */ wc |= cp[i] & 0x3f; if ((cp[i] & 0xc0) != 0x80) return (wchar_t) -1; @@ -1140,22 +1154,23 @@ xo_utf8_emit_len (wchar_t wc) { ssize_t len; - if ((wc & ((1<<7) - 1)) == wc) /* Simple case */ + if ((wc & ((1 << 7) - 1)) == wc) /* Simple case */ len = 1; - else if ((wc & ((1<<11) - 1)) == wc) + else if ((wc & ((1 << 11) - 1)) == wc) len = 2; - else if ((wc & ((1<<16) - 1)) == wc) + else if ((wc & ((1 << 16) - 1)) == wc) len = 3; - else if ((wc & ((1<<21) - 1)) == wc) + else if ((wc & ((1 << 21) - 1)) == wc) len = 4; - else if ((wc & ((1<<26) - 1)) == wc) - len = 5; else - len = 6; + len = -1; /* Invalid */ return len; } +/* + * Emit one wide character into the given buffer + */ static void xo_utf8_emit_char (char *buf, ssize_t len, wchar_t wc) { @@ -1166,15 +1181,22 @@ xo_utf8_emit_char (char *buf, ssize_t len, wchar_t wc) return; } + /* Start with the low bits and insert them, six bits at a time */ for (i = len - 1; i >= 0; i--) { buf[i] = 0x80 | (wc & 0x3f); - wc >>= 6; + wc >>= 6; /* Drop the low six bits */ } - buf[0] &= xo_utf8_bits[len]; - buf[0] |= ~xo_utf8_bits[len] << 1; + /* Finish off the first byte with the length bits */ + buf[0] &= xo_utf8_data_bits[len]; /* Clear out the length bits */ + buf[0] |= xo_utf8_len_bits[len]; /* Drop in new length bits */ } +/* + * Append a single UTF-8 character to a buffer, converting it to locale + * encoding. Returns the number of columns consumed by that character, + * as best we can determine it. + */ static ssize_t xo_buf_append_locale_from_utf8 (xo_handle_t *xop, xo_buffer_t *xbp, const char *ibuf, ssize_t ilen) @@ -1189,7 +1211,7 @@ xo_buf_append_locale_from_utf8 (xo_handle_t *xop, xo_buffer_t *xbp, */ wc = xo_utf8_char(ibuf, ilen); if (wc == (wchar_t) -1) { - xo_failure(xop, "invalid utf-8 byte sequence"); + xo_failure(xop, "invalid UTF-8 byte sequence"); return 0; } @@ -1218,6 +1240,9 @@ xo_buf_append_locale_from_utf8 (xo_handle_t *xop, xo_buffer_t *xbp, return xo_wcwidth(wc); } +/* + * Append a UTF-8 string to a buffer, converting it into locale encoding + */ static void xo_buf_append_locale (xo_handle_t *xop, xo_buffer_t *xbp, const char *cp, ssize_t len) @@ -1504,6 +1529,7 @@ xo_warn_hcv (xo_handle_t *xop, int code, int check_warn, newfmt[plen++] = ':'; newfmt[plen++] = ' '; } + memcpy(newfmt + plen, fmt, len); newfmt[len + plen] = '\0'; @@ -1523,6 +1549,7 @@ xo_warn_hcv (xo_handle_t *xop, int code, int check_warn, ssize_t left = xbp->xb_size - (xbp->xb_curp - xbp->xb_bufp); ssize_t rc = vsnprintf(xbp->xb_curp, left, newfmt, vap); + if (rc >= left) { if (!xo_buf_has_room(xbp, rc)) { va_end(va_local); @@ -1535,6 +1562,7 @@ xo_warn_hcv (xo_handle_t *xop, int code, int check_warn, left = xbp->xb_size - (xbp->xb_curp - xbp->xb_bufp); rc = vsnprintf(xbp->xb_curp, left, fmt, vap); } + va_end(va_local); rc = xo_escape_xml(xbp, rc, 1); @@ -1545,6 +1573,7 @@ xo_warn_hcv (xo_handle_t *xop, int code, int check_warn, if (code >= 0) { const char *msg = strerror(code); + if (msg) { xo_buf_append(xbp, ": ", 2); xo_buf_append(xbp, msg, strlen(msg)); @@ -1558,6 +1587,7 @@ xo_warn_hcv (xo_handle_t *xop, int code, int check_warn, vfprintf(stderr, newfmt, vap); if (code >= 0) { const char *msg = strerror(code); + if (msg) fprintf(stderr, ": %s", msg); } @@ -1674,6 +1704,7 @@ xo_message_hcv (xo_handle_t *xop, int code, const char *fmt, va_list vap) va_copy(va_local, vap); ssize_t left = xbp->xb_size - (xbp->xb_curp - xbp->xb_bufp); + rc = vsnprintf(xbp->xb_curp, left, fmt, vap); if (rc >= left) { if (!xo_buf_has_room(xbp, rc)) { @@ -1687,6 +1718,7 @@ xo_message_hcv (xo_handle_t *xop, int code, const char *fmt, va_list vap) left = xbp->xb_size - (xbp->xb_curp - xbp->xb_bufp); rc = vsnprintf(xbp->xb_curp, left, fmt, vap); } + va_end(va_local); rc = xo_escape_xml(xbp, rc, 0); @@ -1694,6 +1726,7 @@ xo_message_hcv (xo_handle_t *xop, int code, const char *fmt, va_list vap) if (need_nl && code > 0) { const char *msg = strerror(code); + if (msg) { xo_buf_append(xbp, ": ", 2); xo_buf_append(xbp, msg, strlen(msg)); @@ -1727,6 +1760,7 @@ xo_message_hcv (xo_handle_t *xop, int code, const char *fmt, va_list vap) va_copy(va_local, vap); rc = vsnprintf(bp, bufsiz, fmt, va_local); } + va_end(va_local); cp = bp + rc; @@ -1738,7 +1772,8 @@ xo_message_hcv (xo_handle_t *xop, int code, const char *fmt, va_list vap) rc += rc2; } - xo_buf_append_div(xop, "message", 0, NULL, 0, bp, rc, NULL, 0); + xo_buf_append_div(xop, "message", 0, NULL, 0, bp, rc, + NULL, 0, NULL, 0); } break; @@ -1762,6 +1797,7 @@ xo_message_hcv (xo_handle_t *xop, int code, const char *fmt, va_list vap) if (need_nl && code > 0) { const char *msg = strerror(code); + if (msg) { xo_printf(xop, ": %s", msg); } @@ -1776,6 +1812,7 @@ xo_message_hcv (xo_handle_t *xop, int code, const char *fmt, va_list vap) case XO_STYLE_HTML: if (XOIF_ISSET(xop, XOIF_DIV_OPEN)) { static char div_close[] = "</div>"; + XOIF_CLEAR(xop, XOIF_DIV_OPEN); xo_data_append(xop, div_close, sizeof(div_close) - 1); @@ -1848,8 +1885,10 @@ xo_failure (xo_handle_t *xop, const char *fmt, ...) * Note: normal use of libxo does not require a distinct handle, since * the default handle (used when NULL is passed) generates text on stdout. * - * @style Style of output desired (XO_STYLE_* value) - * @flags Set of XOF_* flags in use with this handle + * @param style Style of output desired (XO_STYLE_* value) + * @param flags Set of XOF_* flags in use with this handle + * @return Newly allocated handle + * @see xo_destroy */ xo_handle_t * xo_create (xo_style_t style, xo_xof_flags_t flags) @@ -1871,9 +1910,12 @@ xo_create (xo_style_t style, xo_xof_flags_t flags) /** * Create a handle that will write to the given file. Use * the XOF_CLOSE_FP flag to have the file closed on xo_destroy(). - * @fp FILE pointer to use - * @style Style of output desired (XO_STYLE_* value) - * @flags Set of XOF_* flags to use with this handle + * + * @param fp FILE pointer to use + * @param style Style of output desired (XO_STYLE_* value) + * @param flags Set of XOF_* flags to use with this handle + * @return Newly allocated handle + * @see xo_destroy */ xo_handle_t * xo_create_to_file (FILE *fp, xo_style_t style, xo_xof_flags_t flags) @@ -1892,8 +1934,10 @@ xo_create_to_file (FILE *fp, xo_style_t style, xo_xof_flags_t flags) /** * Set the default handler to output to a file. - * @xop libxo handle - * @fp FILE pointer to use + * + * @param xop libxo handle + * @param fp FILE pointer to use + * @return 0 on success, non-zero on failure */ int xo_set_file_h (xo_handle_t *xop, FILE *fp) @@ -1915,7 +1959,9 @@ xo_set_file_h (xo_handle_t *xop, FILE *fp) /** * Set the default handler to output to a file. - * @fp FILE pointer to use + * + * @param fp FILE pointer to use + * @return 0 on success, non-zero on failure */ int xo_set_file (FILE *fp) @@ -1925,7 +1971,8 @@ xo_set_file (FILE *fp) /** * Release any resources held by the handle. - * @xop XO handle to alter (or NULL for default handle) + * + * @param xop XO handle to alter (or NULL for default handle) */ void xo_destroy (xo_handle_t *xop_arg) @@ -1958,8 +2005,8 @@ xo_destroy (xo_handle_t *xop_arg) * Record a new output style to use for the given handle (or default if * handle is NULL). This output style will be used for any future output. * - * @xop XO handle to alter (or NULL for default handle) - * @style new output style (XO_STYLE_*) + * @param xop XO handle to alter (or NULL for default handle) + * @param style new output style (XO_STYLE_*) */ void xo_set_style (xo_handle_t *xop, xo_style_t style) @@ -1968,6 +2015,12 @@ xo_set_style (xo_handle_t *xop, xo_style_t style) xop->xo_style = style; } +/** + * Return the current style of a handle + * + * @param xop XO handle to access + * @return The handle's current style + */ xo_style_t xo_get_style (xo_handle_t *xop) { @@ -1975,6 +2028,12 @@ xo_get_style (xo_handle_t *xop) return xo_style(xop); } +/** + * Return the XO_STYLE_* value matching a given name + * + * @param name String name of a style + * @return XO_STYLE_* value + */ static int xo_name_to_style (const char *name) { @@ -2010,8 +2069,8 @@ xo_style_is_encoding (xo_handle_t *xop) /* Simple name-value mapping */ typedef struct xo_mapping_s { - xo_xff_flags_t xm_value; - const char *xm_name; + xo_xff_flags_t xm_value; /* Flag value */ + const char *xm_name; /* String name */ } xo_mapping_t; static xo_xff_flags_t @@ -2058,6 +2117,7 @@ xo_value_lookup (xo_mapping_t *map, xo_xff_flags_t value) static xo_mapping_t xo_xof_names[] = { { XOF_COLOR_ALLOWED, "color" }, + { XOF_COLOR, "color-force" }, { XOF_COLUMNS, "columns" }, { XOF_DTRT, "dtrt" }, { XOF_FLUSH, "flush" }, @@ -2082,6 +2142,21 @@ static xo_mapping_t xo_xof_names[] = { { 0, NULL } }; +/* Options available via the environment variable ($LIBXO_OPTIONS) */ +static xo_mapping_t xo_xof_simple_names[] = { + { XOF_COLOR_ALLOWED, "color" }, + { XOF_FLUSH, "flush" }, + { XOF_FLUSH_LINE, "flush-line" }, + { XOF_NO_HUMANIZE, "no-humanize" }, + { XOF_NO_LOCALE, "no-locale" }, + { XOF_RETAIN_NONE, "no-retain" }, + { XOF_PRETTY, "pretty" }, + { XOF_RETAIN_ALL, "retain" }, + { XOF_UNDERSCORES, "underscores" }, + { XOF_WARN, "warn" }, + { 0, NULL } +}; + /* * Convert string name to XOF_* flag value. * Not all are useful. Or safe. Or sane. @@ -2092,6 +2167,13 @@ xo_name_to_flag (const char *name) return (unsigned) xo_name_lookup(xo_xof_names, name, -1); } +/** + * Set the style of an libxo handle based on a string name + * + * @param xop XO handle + * @param name String value of name + * @return 0 on success, non-zero on failure + */ int xo_set_style_name (xo_handle_t *xop, const char *name) { @@ -2099,6 +2181,7 @@ xo_set_style_name (xo_handle_t *xop, const char *name) return -1; int style = xo_name_to_style(name); + if (style < 0) return -1; @@ -2107,9 +2190,95 @@ xo_set_style_name (xo_handle_t *xop, const char *name) } /* + * Fill in the color map, based on the input string; currently unimplemented + * Look for something like "colors=red/blue+green/yellow" as fg/bg pairs. + */ +static void +xo_set_color_map (xo_handle_t *xop, char *value) +{ +#ifdef LIBXO_TEXT_ONLY + return; +#endif /* LIBXO_TEXT_ONLY */ + + char *cp, *ep, *vp, *np; + ssize_t len = value ? strlen(value) + 1 : 0; + int num = 1, fg, bg; + + for (cp = value, ep = cp + len - 1; cp && *cp && cp < ep; cp = np) { + np = strchr(cp, '+'); + if (np) + *np++ = '\0'; + + vp = strchr(cp, '/'); + if (vp) + *vp++ = '\0'; + + fg = *cp ? xo_color_find(cp) : -1; + bg = (vp && *vp) ? xo_color_find(vp) : -1; + + xop->xo_color_map_fg[num] = (fg < 0) ? num : fg; + xop->xo_color_map_bg[num] = (bg < 0) ? num : bg; + if (++num > XO_NUM_COLORS) + break; + } + + /* If no color initialization happened, then we don't need the map */ + if (num > 0) + XOF_SET(xop, XOF_COLOR_MAP); + else + XOF_CLEAR(xop, XOF_COLOR_MAP); + + /* 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; +} + +static int +xo_set_options_simple (xo_handle_t *xop, const char *input) +{ + xo_xof_flags_t new_flag; + char *cp, *ep, *vp, *np, *bp; + ssize_t len = strlen(input) + 1; + + bp = alloca(len); + memcpy(bp, input, len); + + for (cp = bp, ep = cp + len - 1; cp && cp < ep; cp = np) { + np = strchr(cp, ','); + if (np) + *np++ = '\0'; + + vp = strchr(cp, '='); + if (vp) + *vp++ = '\0'; + + if (strcmp("colors", cp) == 0) { + xo_set_color_map(xop, vp); + continue; + } + + new_flag = xo_name_lookup(xo_xof_simple_names, cp, -1); + if (new_flag != 0) { + XOF_SET(xop, new_flag); + } else if (strcmp(cp, "no-color") == 0) { + XOF_CLEAR(xop, XOF_COLOR_ALLOWED); + } else { + xo_failure(xop, "unknown simple option: %s", cp); + return -1; + } + } + + return 0; +} + +/** * Set the options for a handle using a string of options * passed in. The input is a comma-separated set of names * and optional values: "xml,pretty,indent=4" + * + * @param xop XO handle + * @param input Comma-separated set of option values + * @return 0 on success, non-zero on failure */ int xo_set_options (xo_handle_t *xop, const char *input) @@ -2229,7 +2398,7 @@ xo_set_options (xo_handle_t *xop, const char *input) *vp++ = '\0'; if (strcmp("colors", cp) == 0) { - /* XXX Look for colors=red-blue+green-yellow */ + xo_set_color_map(xop, vp); continue; } @@ -2247,28 +2416,26 @@ xo_set_options (xo_handle_t *xop, const char *input) new_flag = xo_name_to_flag(cp); if (new_flag != 0) XOF_SET(xop, new_flag); - else { - if (strcmp(cp, "no-color") == 0) { - XOF_CLEAR(xop, XOF_COLOR_ALLOWED); - } else if (strcmp(cp, "indent") == 0) { - if (vp) - xop->xo_indent_by = atoi(vp); - else - xo_failure(xop, "missing value for indent option"); - } else if (strcmp(cp, "encoder") == 0) { - if (vp == NULL) - xo_failure(xop, "missing value for encoder option"); - else { - if (xo_encoder_init(xop, vp)) { - xo_failure(xop, "encoder not found: %s", vp); - rc = -1; - } + else if (strcmp(cp, "no-color") == 0) + XOF_CLEAR(xop, XOF_COLOR_ALLOWED); + else if (strcmp(cp, "indent") == 0) { + if (vp) + xop->xo_indent_by = atoi(vp); + else + xo_failure(xop, "missing value for indent option"); + } else if (strcmp(cp, "encoder") == 0) { + if (vp == NULL) + xo_failure(xop, "missing value for encoder option"); + else { + if (xo_encoder_init(xop, vp)) { + xo_failure(xop, "encoder not found: %s", vp); + rc = -1; } - - } else { - xo_warnx("unknown libxo option value: '%s'", cp); - rc = -1; } + + } else { + xo_warnx("unknown libxo option value: '%s'", cp); + rc = -1; } } } @@ -2283,8 +2450,8 @@ xo_set_options (xo_handle_t *xop, const char *input) * Set one or more flags for a given handle (or default if handle is NULL). * These flags will affect future output. * - * @xop XO handle to alter (or NULL for default handle) - * @flags Flags to be set (XOF_*) + * @param xop XO handle to alter (or NULL for default handle) + * @param flags Flags to be set (XOF_*) */ void xo_set_flags (xo_handle_t *xop, xo_xof_flags_t flags) @@ -2294,6 +2461,11 @@ xo_set_flags (xo_handle_t *xop, xo_xof_flags_t flags) XOF_SET(xop, flags); } +/** + * Accessor to return the current set of flags for a handle + * @param xop XO handle + * @return Current set of flags + */ xo_xof_flags_t xo_get_flags (xo_handle_t *xop) { @@ -2302,8 +2474,8 @@ xo_get_flags (xo_handle_t *xop) return xop->xo_flags; } -/* - * strndup with a twist: len < 0 means strlen +/** + * strndup with a twist: len < 0 means len = strlen(str) */ static char * xo_strndup (const char *str, ssize_t len) @@ -2325,8 +2497,8 @@ xo_strndup (const char *str, ssize_t len) * generated data to be placed within an XML hierarchy but still have * accurate XPath expressions. * - * @xop XO handle to alter (or NULL for default handle) - * @path The XPath expression + * @param xop XO handle to alter (or NULL for default handle) + * @param path The XPath expression */ void xo_set_leading_xpath (xo_handle_t *xop, const char *path) @@ -2347,9 +2519,9 @@ xo_set_leading_xpath (xo_handle_t *xop, const char *path) /** * Record the info data for a set of tags * - * @xop XO handle to alter (or NULL for default handle) - * @info Info data (xo_info_t) to be recorded (or NULL) (MUST BE SORTED) - * @count Number of entries in info (or -1 to count them ourselves) + * @param xop XO handle to alter (or NULL for default handle) + * @param info Info data (xo_info_t) to be recorded (or NULL) (MUST BE SORTED) + * @pararm count Number of entries in info (or -1 to count them ourselves) */ void xo_set_info (xo_handle_t *xop, xo_info_t *infop, int count) @@ -2386,8 +2558,8 @@ xo_set_formatter (xo_handle_t *xop, xo_formatter_t func, * Clear one or more flags for a given handle (or default if handle is NULL). * These flags will affect future output. * - * @xop XO handle to alter (or NULL for default handle) - * @flags Flags to be cleared (XOF_*) + * @param xop XO handle to alter (or NULL for default handle) + * @param flags Flags to be cleared (XOF_*) */ void xo_clear_flags (xo_handle_t *xop, xo_xof_flags_t flags) @@ -2543,6 +2715,8 @@ xo_format_string_direct (xo_handle_t *xop, xo_buffer_t *xbp, if ((flags & XFF_UNESCAPE) && (*cp == '\\' || *cp == '%')) { cp += 1; len -= 1; + if (len == 0 || *cp == '\0') + break; } } @@ -3079,6 +3253,11 @@ xo_data_append_content (xo_handle_t *xop, const char *str, ssize_t len, xop->xo_anchor_columns += cols; } +/** + * Bump one of the 'width' values in a format strings (e.g. "%40.50.60s"). + * @param xfp Formatting instructions + * @param digit Single digit (0-9) of input + */ static void xo_bump_width (xo_format_t *xfp, int digit) { @@ -3325,7 +3504,8 @@ xo_do_format_field (xo_handle_t *xop, xo_buffer_t *xbp, rc = xo_trim_ws(xbp, rc); } else { - ssize_t columns = rc = xo_vsnprintf(xop, xbp, newfmt, xop->xo_vap); + ssize_t columns = rc = xo_vsnprintf(xop, xbp, newfmt, + xop->xo_vap); /* * For XML and HTML, we need "&<>" processing; for JSON, @@ -3478,6 +3658,10 @@ xo_do_format_field (xo_handle_t *xop, xo_buffer_t *xbp, return 0; } +/* + * Remove any numeric precision/width format from the format string by + * inserting the "%" after the [0-9]+, returning the substring. + */ static char * xo_fix_encoding (xo_handle_t *xop UNUSED, char *encoding) { @@ -3491,8 +3675,7 @@ xo_fix_encoding (xo_handle_t *xop UNUSED, char *encoding) break; } - cp -= 1; - *cp = '%'; + *--cp = '%'; /* Back off and insert the '%' */ return cp; } @@ -3611,10 +3794,35 @@ xo_format_humanize (xo_handle_t *xop, xo_buffer_t *xbp, } } +/* + * Convenience function that either append a fixed value (if one is + * given) or formats a field using a format string. If it's + * encode_only, then we can't skip formatting the field, since it may + * be pulling arguments off the stack. + */ +static inline void +xo_simple_field (xo_handle_t *xop, unsigned encode_only, + const char *value, ssize_t vlen, + const char *fmt, ssize_t flen, xo_xff_flags_t flags) +{ + if (encode_only) + flags |= XFF_NO_OUTPUT; + + if (vlen == 0) + xo_do_format_field(xop, NULL, fmt, flen, flags); + else if (!encode_only) + xo_data_append_content(xop, value, vlen, flags); +} + +/* + * Html mode: append a <div> to the output buffer contain a field + * along with all the supporting information indicated by the flags. + */ static void xo_buf_append_div (xo_handle_t *xop, const char *class, xo_xff_flags_t flags, const char *name, ssize_t nlen, const char *value, ssize_t vlen, + const char *fmt, ssize_t flen, const char *encoding, ssize_t elen) { static char div_start[] = "<div class=\""; @@ -3625,10 +3833,10 @@ xo_buf_append_div (xo_handle_t *xop, const char *class, xo_xff_flags_t flags, static char div_close[] = "</div>"; /* The encoding format defaults to the normal format */ - if (encoding == NULL) { - char *enc = alloca(vlen + 1); - memcpy(enc, value, vlen); - enc[vlen] = '\0'; + if (encoding == NULL && fmt != NULL) { + char *enc = alloca(flen + 1); + memcpy(enc, fmt, flen); + enc[flen] = '\0'; encoding = xo_fix_encoding(xop, enc); elen = strlen(encoding); } @@ -3695,10 +3903,10 @@ xo_buf_append_div (xo_handle_t *xop, const char *class, xo_xff_flags_t flags, /* * Even if this is encode-only, we need to go through the * work of formatting it to make sure the args are cleared - * from xo_vap. + * from xo_vap. This is not true when vlen is zero, since + * that means our "value" isn't on the stack. */ - xo_do_format_field(xop, NULL, encoding, elen, - flags | XFF_NO_OUTPUT); + xo_simple_field(xop, TRUE, NULL, 0, encoding, elen, flags); return; } @@ -3806,7 +4014,7 @@ xo_buf_append_div (xo_handle_t *xop, const char *class, xo_xff_flags_t flags, save.xhs_columns = xop->xo_columns; save.xhs_anchor_columns = xop->xo_anchor_columns; - xo_do_format_field(xop, NULL, value, vlen, flags); + xo_simple_field(xop, FALSE, value, vlen, fmt, flen, flags); if (flags & XFF_HUMANIZE) { /* @@ -3857,14 +4065,14 @@ xo_format_text (xo_handle_t *xop, const char *str, ssize_t len) break; case XO_STYLE_HTML: - xo_buf_append_div(xop, "text", 0, NULL, 0, str, len, NULL, 0); + xo_buf_append_div(xop, "text", 0, NULL, 0, str, len, NULL, 0, NULL, 0); break; } } static void xo_format_title (xo_handle_t *xop, xo_field_info_t *xfip, - const char *str, ssize_t len) + const char *value, ssize_t vlen) { const char *fmt = xfip->xfi_format; ssize_t flen = xfip->xfi_flen; @@ -3888,8 +4096,7 @@ xo_format_title (xo_handle_t *xop, xo_field_info_t *xfip, * Even though we don't care about text, we need to do * enough parsing work to skip over the right bits of xo_vap. */ - if (len == 0) - xo_do_format_field(xop, NULL, fmt, flen, flags | XFF_NO_OUTPUT); + xo_simple_field(xop, TRUE, value, vlen, fmt, flen, flags); return; } @@ -3908,17 +4115,17 @@ xo_format_title (xo_handle_t *xop, xo_field_info_t *xfip, } start = xbp->xb_curp - xbp->xb_bufp; /* Reset start */ - if (len) { + if (vlen) { char *newfmt = alloca(flen + 1); memcpy(newfmt, fmt, flen); newfmt[flen] = '\0'; /* If len is non-zero, the format string apply to the name */ - char *newstr = alloca(len + 1); - memcpy(newstr, str, len); - newstr[len] = '\0'; + char *newstr = alloca(vlen + 1); + memcpy(newstr, value, vlen); + newstr[vlen] = '\0'; - if (newstr[len - 1] == 's') { + if (newstr[vlen - 1] == 's') { char *bp; rc = snprintf(NULL, 0, newfmt, newstr); @@ -4000,8 +4207,9 @@ xo_arg (xo_handle_t *xop) static void xo_format_value (xo_handle_t *xop, const char *name, ssize_t nlen, - const char *format, ssize_t flen, - const char *encoding, ssize_t elen, xo_xff_flags_t flags) + const char *value, ssize_t vlen, + const char *fmt, ssize_t flen, + const char *encoding, ssize_t elen, xo_xff_flags_t flags) { int pretty = XOF_ISSET(xop, XOF_PRETTY); int quote; @@ -4087,7 +4295,7 @@ xo_format_value (xo_handle_t *xop, const char *name, ssize_t nlen, save.xhs_columns = xop->xo_columns; save.xhs_anchor_columns = xop->xo_anchor_columns; - xo_do_format_field(xop, NULL, format, flen, flags); + xo_simple_field(xop, FALSE, value, vlen, fmt, flen, flags); if (flags & XFF_HUMANIZE) xo_format_humanize(xop, xbp, &save, flags); @@ -4097,8 +4305,8 @@ xo_format_value (xo_handle_t *xop, const char *name, ssize_t nlen, if (flags & XFF_ENCODE_ONLY) flags |= XFF_NO_OUTPUT; - xo_buf_append_div(xop, "data", flags, name, nlen, - format, flen, encoding, elen); + xo_buf_append_div(xop, "data", flags, name, nlen, value, vlen, + fmt, flen, encoding, elen); break; case XO_STYLE_XML: @@ -4107,25 +4315,24 @@ xo_format_value (xo_handle_t *xop, const char *name, ssize_t nlen, * let the formatting code handle the va_arg popping. */ if (flags & XFF_DISPLAY_ONLY) { - flags |= XFF_NO_OUTPUT; - xo_do_format_field(xop, NULL, format, flen, flags); + xo_simple_field(xop, TRUE, value, vlen, fmt, flen, flags); break; } if (encoding) { - format = encoding; + fmt = encoding; flen = elen; } else { char *enc = alloca(flen + 1); - memcpy(enc, format, flen); + memcpy(enc, fmt, flen); enc[flen] = '\0'; - format = xo_fix_encoding(xop, enc); - flen = strlen(format); + fmt = xo_fix_encoding(xop, enc); + flen = strlen(fmt); } if (nlen == 0) { static char missing[] = "missing-field-name"; - xo_failure(xop, "missing field name: %s", format); + xo_failure(xop, "missing field name: %s", fmt); name = missing; nlen = sizeof(missing) - 1; } @@ -4161,7 +4368,9 @@ xo_format_value (xo_handle_t *xop, const char *name, ssize_t nlen, } xo_data_append(xop, ">", 1); - xo_do_format_field(xop, NULL, format, flen, flags); + + xo_simple_field(xop, FALSE, value, vlen, fmt, flen, flags); + xo_data_append(xop, "</", 2); xo_data_escape(xop, name, nlen); xo_data_append(xop, ">", 1); @@ -4171,20 +4380,19 @@ xo_format_value (xo_handle_t *xop, const char *name, ssize_t nlen, case XO_STYLE_JSON: if (flags & XFF_DISPLAY_ONLY) { - flags |= XFF_NO_OUTPUT; - xo_do_format_field(xop, NULL, format, flen, flags); + xo_simple_field(xop, TRUE, value, vlen, fmt, flen, flags); break; } if (encoding) { - format = encoding; + fmt = encoding; flen = elen; } else { char *enc = alloca(flen + 1); - memcpy(enc, format, flen); + memcpy(enc, fmt, flen); enc[flen] = '\0'; - format = xo_fix_encoding(xop, enc); - flen = strlen(format); + fmt = xo_fix_encoding(xop, enc); + flen = strlen(fmt); } int first = (xop->xo_stack[xop->xo_depth].xs_flags & XSF_NOT_FIRST) @@ -4196,18 +4404,20 @@ xo_format_value (xo_handle_t *xop, const char *name, ssize_t nlen, quote = 1; else if (flags & XFF_NOQUOTE) quote = 0; + else if (vlen != 0) + quote = 1; else if (flen == 0) { quote = 0; - format = "true"; /* JSON encodes empty tags as a boolean true */ + fmt = "true"; /* JSON encodes empty tags as a boolean true */ flen = 4; - } else if (strchr("diouDOUeEfFgG", format[flen - 1]) == NULL) + } else if (strchr("diouDOUeEfFgG", fmt[flen - 1]) == NULL) quote = 1; else quote = 0; if (nlen == 0) { static char missing[] = "missing-field-name"; - xo_failure(xop, "missing field name: %s", format); + xo_failure(xop, "missing field name: %s", fmt); name = missing; nlen = sizeof(missing) - 1; } @@ -4241,7 +4451,7 @@ xo_format_value (xo_handle_t *xop, const char *name, ssize_t nlen, if (quote) xo_data_append(xop, "\"", 1); - xo_do_format_field(xop, NULL, format, flen, flags); + xo_simple_field(xop, FALSE, value, vlen, fmt, flen, flags); if (quote) xo_data_append(xop, "\"", 1); @@ -4249,39 +4459,39 @@ xo_format_value (xo_handle_t *xop, const char *name, ssize_t nlen, case XO_STYLE_SDPARAMS: if (flags & XFF_DISPLAY_ONLY) { - flags |= XFF_NO_OUTPUT; - xo_do_format_field(xop, NULL, format, flen, flags); + xo_simple_field(xop, TRUE, value, vlen, fmt, flen, flags); break; } if (encoding) { - format = encoding; + fmt = encoding; flen = elen; } else { char *enc = alloca(flen + 1); - memcpy(enc, format, flen); + memcpy(enc, fmt, flen); enc[flen] = '\0'; - format = xo_fix_encoding(xop, enc); - flen = strlen(format); + fmt = xo_fix_encoding(xop, enc); + flen = strlen(fmt); } if (nlen == 0) { static char missing[] = "missing-field-name"; - xo_failure(xop, "missing field name: %s", format); + xo_failure(xop, "missing field name: %s", fmt); name = missing; nlen = sizeof(missing) - 1; } xo_data_escape(xop, name, nlen); xo_data_append(xop, "=\"", 2); - xo_do_format_field(xop, NULL, format, flen, flags); + + xo_simple_field(xop, FALSE, value, vlen, fmt, flen, flags); + xo_data_append(xop, "\" ", 2); break; case XO_STYLE_ENCODER: if (flags & XFF_DISPLAY_ONLY) { - flags |= XFF_NO_OUTPUT; - xo_do_format_field(xop, NULL, format, flen, flags); + xo_simple_field(xop, TRUE, value, vlen, fmt, flen, flags); break; } @@ -4291,27 +4501,27 @@ xo_format_value (xo_handle_t *xop, const char *name, ssize_t nlen, quote = 0; else if (flen == 0) { quote = 0; - format = "true"; /* JSON encodes empty tags as a boolean true */ + fmt = "true"; /* JSON encodes empty tags as a boolean true */ flen = 4; - } else if (strchr("diouxXDOUeEfFgGaAcCp", format[flen - 1]) == NULL) + } else if (strchr("diouxXDOUeEfFgGaAcCp", fmt[flen - 1]) == NULL) quote = 1; else quote = 0; if (encoding) { - format = encoding; + fmt = encoding; flen = elen; } else { char *enc = alloca(flen + 1); - memcpy(enc, format, flen); + memcpy(enc, fmt, flen); enc[flen] = '\0'; - format = xo_fix_encoding(xop, enc); - flen = strlen(format); + fmt = xo_fix_encoding(xop, enc); + flen = strlen(fmt); } if (nlen == 0) { static char missing[] = "missing-field-name"; - xo_failure(xop, "missing field name: %s", format); + xo_failure(xop, "missing field name: %s", fmt); name = missing; nlen = sizeof(missing) - 1; } @@ -4321,12 +4531,14 @@ xo_format_value (xo_handle_t *xop, const char *name, ssize_t nlen, xo_data_append(xop, "", 1); ssize_t value_offset = xo_buf_offset(&xop->xo_data); - xo_do_format_field(xop, NULL, format, flen, flags); + + xo_simple_field(xop, FALSE, value, vlen, fmt, flen, flags); + xo_data_append(xop, "", 1); xo_encoder_handle(xop, quote ? XO_OP_STRING : XO_OP_CONTENT, xo_buf_data(&xop->xo_data, name_offset), - xo_buf_data(&xop->xo_data, value_offset)); + xo_buf_data(&xop->xo_data, value_offset), flags); xo_buf_reset(&xop->xo_data); break; } @@ -4370,37 +4582,27 @@ xo_set_gettext_domain (xo_handle_t *xop, xo_field_info_t *xfip, static void xo_format_content (xo_handle_t *xop, const char *class_name, const char *tag_name, - const char *str, ssize_t len, const char *fmt, ssize_t flen, + const char *value, ssize_t vlen, + const char *fmt, ssize_t flen, xo_xff_flags_t flags) { switch (xo_style(xop)) { case XO_STYLE_TEXT: - if (len) - xo_data_append_content(xop, str, len, flags); - else - xo_do_format_field(xop, NULL, fmt, flen, flags); + xo_simple_field(xop, FALSE, value, vlen, fmt, flen, flags); break; case XO_STYLE_HTML: - if (len == 0) { - str = fmt; - len = flen; - } - - xo_buf_append_div(xop, class_name, flags, NULL, 0, str, len, NULL, 0); + xo_buf_append_div(xop, class_name, flags, NULL, 0, + value, vlen, fmt, flen, NULL, 0); break; case XO_STYLE_XML: case XO_STYLE_JSON: case XO_STYLE_SDPARAMS: if (tag_name) { - if (len == 0) { - str = fmt; - len = flen; - } - xo_open_container_h(xop, tag_name); - xo_format_value(xop, "message", 7, str, len, NULL, 0, flags); + xo_format_value(xop, "message", 7, value, vlen, + fmt, flen, NULL, 0, flags); xo_close_container_h(xop, tag_name); } else { @@ -4408,16 +4610,12 @@ xo_format_content (xo_handle_t *xop, const char *class_name, * Even though we don't care about labels, we need to do * enough parsing work to skip over the right bits of xo_vap. */ - if (len == 0) - xo_do_format_field(xop, NULL, fmt, flen, - flags | XFF_NO_OUTPUT); + xo_simple_field(xop, TRUE, value, vlen, fmt, flen, flags); } break; case XO_STYLE_ENCODER: - if (len == 0) - xo_do_format_field(xop, NULL, fmt, flen, - flags | XFF_NO_OUTPUT); + xo_simple_field(xop, TRUE, value, vlen, fmt, flen, flags); break; } } @@ -4583,6 +4781,28 @@ xo_colors_enabled (xo_handle_t *xop UNUSED) #endif /* LIBXO_TEXT_ONLY */ } +/* + * If the color map is in use (--libxo colors=xxxx), then update + * the incoming foreground and background colors from the map. + */ +static void +xo_colors_update (xo_handle_t *xop, xo_colors_t *newp) +{ +#ifdef LIBXO_TEXT_ONLY + return; +#endif /* 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 */ + newp->xoc_col_fg = fg; + + xo_color_t bg = newp->xoc_col_bg; + 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; +} + static void xo_colors_handle_text (xo_handle_t *xop, xo_colors_t *newp) { @@ -4629,16 +4849,16 @@ xo_colors_handle_text (xo_handle_t *xop, xo_colors_t *newp) } } - if (newp->xoc_col_fg != oldp->xoc_col_fg) { + xo_color_t fg = newp->xoc_col_fg; + if (fg != oldp->xoc_col_fg) { cp += snprintf(cp, ep - cp, ";3%u", - (newp->xoc_col_fg != XO_COL_DEFAULT) - ? newp->xoc_col_fg - 1 : 9); + (fg != XO_COL_DEFAULT) ? fg - 1 : 9); } - if (newp->xoc_col_bg != oldp->xoc_col_bg) { + xo_color_t bg = newp->xoc_col_bg; + if (bg != oldp->xoc_col_bg) { cp += snprintf(cp, ep - cp, ";4%u", - (newp->xoc_col_bg != XO_COL_DEFAULT) - ? newp->xoc_col_bg - 1 : 9); + (bg != XO_COL_DEFAULT) ? bg - 1 : 9); } if (cp - buf != 1 && cp < ep - 3) { @@ -4710,7 +4930,7 @@ xo_colors_handle_html (xo_handle_t *xop, xo_colors_t *newp) static void xo_format_colors (xo_handle_t *xop, xo_field_info_t *xfip, - const char *str, ssize_t len) + const char *value, ssize_t vlen) { const char *fmt = xfip->xfi_format; ssize_t flen = xfip->xfi_flen; @@ -4718,13 +4938,13 @@ xo_format_colors (xo_handle_t *xop, xo_field_info_t *xfip, xo_buffer_t xb; /* If the string is static and we've in an encoding style, bail */ - if (len != 0 && xo_style_is_encoding(xop)) + if (vlen != 0 && xo_style_is_encoding(xop)) return; xo_buf_init(&xb); - if (len) - xo_buf_append(&xb, str, len); + if (vlen) + xo_buf_append(&xb, value, vlen); else if (flen) xo_do_format_field(xop, &xb, fmt, flen, 0); else @@ -4738,6 +4958,7 @@ xo_format_colors (xo_handle_t *xop, xo_field_info_t *xfip, xo_colors_t xoc = xop->xo_colors; xo_colors_parse(xop, &xoc, xb.xb_bufp); + xo_colors_update(xop, &xoc); if (xo_style(xop) == XO_STYLE_TEXT) { /* @@ -4783,7 +5004,7 @@ xo_format_colors (xo_handle_t *xop, xo_field_info_t *xfip, static void xo_format_units (xo_handle_t *xop, xo_field_info_t *xfip, - const char *str, ssize_t len) + const char *value, ssize_t vlen) { const char *fmt = xfip->xfi_format; ssize_t flen = xfip->xfi_flen; @@ -4793,7 +5014,7 @@ xo_format_units (xo_handle_t *xop, xo_field_info_t *xfip, static char units_start_html[] = " data-units=\""; if (!XOIF_ISSET(xop, XOIF_UNITS_PENDING)) { - xo_format_content(xop, "units", NULL, str, len, fmt, flen, flags); + xo_format_content(xop, "units", NULL, value, vlen, fmt, flen, flags); return; } @@ -4808,8 +5029,8 @@ xo_format_units (xo_handle_t *xop, xo_field_info_t *xfip, else return; - if (len) - xo_data_escape(xop, str, len); + if (vlen) + xo_data_escape(xop, value, vlen); else xo_do_format_field(xop, NULL, fmt, flen, flags); @@ -4837,7 +5058,7 @@ xo_format_units (xo_handle_t *xop, xo_field_info_t *xfip, static ssize_t xo_find_width (xo_handle_t *xop, xo_field_info_t *xfip, - const char *str, ssize_t len) + const char *value, ssize_t vlen) { const char *fmt = xfip->xfi_format; ssize_t flen = xfip->xfi_flen; @@ -4846,10 +5067,10 @@ xo_find_width (xo_handle_t *xop, xo_field_info_t *xfip, char *bp; char *cp; - if (len) { - bp = alloca(len + 1); /* Make local NUL-terminated copy of str */ - memcpy(bp, str, len); - bp[len] = '\0'; + if (vlen) { + bp = alloca(vlen + 1); /* Make local NUL-terminated copy of value */ + memcpy(bp, value, vlen); + bp[vlen] = '\0'; width = strtol(bp, &cp, 0); if (width == LONG_MIN || width == LONG_MAX @@ -4886,7 +5107,7 @@ xo_anchor_clear (xo_handle_t *xop) */ static void xo_anchor_start (xo_handle_t *xop, xo_field_info_t *xfip, - const char *str, ssize_t len) + const char *value, ssize_t vlen) { if (xo_style(xop) != XO_STYLE_TEXT && xo_style(xop) != XO_STYLE_HTML) return; @@ -4903,12 +5124,12 @@ xo_anchor_start (xo_handle_t *xop, xo_field_info_t *xfip, * Now we find the width, if possible. If it's not there, * we'll get it on the end anchor. */ - xop->xo_anchor_min_width = xo_find_width(xop, xfip, str, len); + xop->xo_anchor_min_width = xo_find_width(xop, xfip, value, vlen); } static void xo_anchor_stop (xo_handle_t *xop, xo_field_info_t *xfip, - const char *str, ssize_t len) + const char *value, ssize_t vlen) { if (xo_style(xop) != XO_STYLE_TEXT && xo_style(xop) != XO_STYLE_HTML) return; @@ -4920,7 +5141,7 @@ xo_anchor_stop (xo_handle_t *xop, xo_field_info_t *xfip, XOIF_CLEAR(xop, XOIF_UNITS_PENDING); - ssize_t width = xo_find_width(xop, xfip, str, len); + ssize_t width = xo_find_width(xop, xfip, value, vlen); if (width == 0) width = xop->xo_anchor_min_width; @@ -5839,12 +6060,12 @@ xo_gettext_build_format (xo_handle_t *xop, if (gtfmt == NULL || gtfmt == fmt || strcmp(gtfmt, fmt) == 0) goto bail2; - xo_buf_cleanup(&xb); - char *new_fmt = xo_strndup(gtfmt, -1); if (new_fmt == NULL) goto bail2; + xo_buf_cleanup(&xb); + *new_fmtp = new_fmt; return new_fmt; @@ -5977,7 +6198,7 @@ xo_do_emit_fields (xo_handle_t *xop, xo_field_info_t *fields, ssize_t fend[flimit]; bzero(fend, flimit * sizeof(fend[0])); - for (xfip = fields, field = 0; xfip->xfi_ftype && field < max_fields; + for (xfip = fields, field = 0; field < max_fields && xfip->xfi_ftype; xfip++, field++) { ftype = xfip->xfi_ftype; flags = xfip->xfi_flags; @@ -6024,12 +6245,12 @@ xo_do_emit_fields (xo_handle_t *xop, xo_field_info_t *fields, if (flags & XFF_WS) { xo_format_content(xop, "padding", NULL, " ", 1, NULL, 0, flags); - flags &= ~XFF_WS; /* Block later handling of this */ + flags &= ~XFF_WS; /* Prevent later handling of this flag */ } } if (ftype == 'V') - xo_format_value(xop, content, clen, + xo_format_value(xop, content, clen, NULL, 0, xfip->xfi_format, xfip->xfi_flen, xfip->xfi_encoding, xfip->xfi_elen, flags); else if (ftype == '[') @@ -6460,7 +6681,7 @@ xo_attr_hv (xo_handle_t *xop, const char *name, const char *fmt, va_list vap) *xbp->xb_curp = '\0'; rc = xo_encoder_handle(xop, XO_OP_ATTRIBUTE, xo_buf_data(xbp, name_offset), - xo_buf_data(xbp, value_offset)); + xo_buf_data(xbp, value_offset), 0); } } @@ -6538,7 +6759,7 @@ xo_depth_change (xo_handle_t *xop, const char *name, xo_stack_t *xsp = &xop->xo_stack[xop->xo_depth]; if (XOF_ISSET(xop, XOF_WARN)) { const char *top = xsp->xs_name; - if (top && strcmp(name, top) != 0) { + if (top != NULL && name != NULL && strcmp(name, top) != 0) { xo_failure(xop, "incorrect close: '%s' .vs. '%s'", name, top); return; @@ -6650,7 +6871,7 @@ xo_do_open_container (xo_handle_t *xop, xo_xof_flags_t flags, const char *name) break; case XO_STYLE_ENCODER: - rc = xo_encoder_handle(xop, XO_OP_OPEN_CONTAINER, name, NULL); + rc = xo_encoder_handle(xop, XO_OP_OPEN_CONTAINER, name, NULL, flags); break; } @@ -6740,7 +6961,7 @@ xo_do_close_container (xo_handle_t *xop, const char *name) case XO_STYLE_ENCODER: xo_depth_change(xop, name, -1, 0, XSS_CLOSE_CONTAINER, 0); - rc = xo_encoder_handle(xop, XO_OP_CLOSE_CONTAINER, name, NULL); + rc = xo_encoder_handle(xop, XO_OP_CLOSE_CONTAINER, name, NULL, 0); break; } @@ -6806,7 +7027,7 @@ xo_do_open_list (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name) break; case XO_STYLE_ENCODER: - rc = xo_encoder_handle(xop, XO_OP_OPEN_LIST, name, NULL); + rc = xo_encoder_handle(xop, XO_OP_OPEN_LIST, name, NULL, flags); break; } @@ -6881,7 +7102,7 @@ xo_do_close_list (xo_handle_t *xop, const char *name) case XO_STYLE_ENCODER: xo_depth_change(xop, name, -1, 0, XSS_CLOSE_LIST, XSF_LIST); - rc = xo_encoder_handle(xop, XO_OP_CLOSE_LIST, name, NULL); + rc = xo_encoder_handle(xop, XO_OP_CLOSE_LIST, name, NULL, 0); break; default: @@ -6955,7 +7176,7 @@ xo_do_open_leaf_list (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name) break; case XO_STYLE_ENCODER: - rc = xo_encoder_handle(xop, XO_OP_OPEN_LEAF_LIST, name, NULL); + rc = xo_encoder_handle(xop, XO_OP_OPEN_LEAF_LIST, name, NULL, flags); break; } @@ -6999,7 +7220,7 @@ xo_do_close_leaf_list (xo_handle_t *xop, const char *name) break; case XO_STYLE_ENCODER: - rc = xo_encoder_handle(xop, XO_OP_CLOSE_LEAF_LIST, name, NULL); + rc = xo_encoder_handle(xop, XO_OP_CLOSE_LEAF_LIST, name, NULL, 0); /* FALLTHRU */ default: @@ -7056,7 +7277,7 @@ xo_do_open_instance (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name) break; case XO_STYLE_ENCODER: - rc = xo_encoder_handle(xop, XO_OP_OPEN_INSTANCE, name, NULL); + rc = xo_encoder_handle(xop, XO_OP_OPEN_INSTANCE, name, NULL, flags); break; } @@ -7144,7 +7365,7 @@ xo_do_close_instance (xo_handle_t *xop, const char *name) case XO_STYLE_ENCODER: xo_depth_change(xop, name, -1, 0, XSS_CLOSE_INSTANCE, 0); - rc = xo_encoder_handle(xop, XO_OP_CLOSE_INSTANCE, name, NULL); + rc = xo_encoder_handle(xop, XO_OP_CLOSE_INSTANCE, name, NULL, 0); break; } @@ -7620,7 +7841,7 @@ xo_flush_h (xo_handle_t *xop) switch (xo_style(xop)) { case XO_STYLE_ENCODER: - xo_encoder_handle(xop, XO_OP_FLUSH, NULL, NULL); + xo_encoder_handle(xop, XO_OP_FLUSH, NULL, NULL, 0); } rc = xo_write(xop); @@ -7658,7 +7879,7 @@ xo_finish_h (xo_handle_t *xop) break; case XO_STYLE_ENCODER: - xo_encoder_handle(xop, XO_OP_FINISH, NULL, NULL); + xo_encoder_handle(xop, XO_OP_FINISH, NULL, NULL, 0); break; } @@ -7710,7 +7931,8 @@ xo_error_hv (xo_handle_t *xop, const char *fmt, va_list vap) case XO_STYLE_HTML: va_copy(xop->xo_vap, vap); - xo_buf_append_div(xop, "error", 0, NULL, 0, fmt, strlen(fmt), NULL, 0); + xo_buf_append_div(xop, "error", 0, NULL, 0, NULL, 0, + fmt, strlen(fmt), NULL, 0); if (XOIF_ISSET(xop, XOIF_DIV_OPEN)) xo_line_close(xop); @@ -7726,7 +7948,8 @@ xo_error_hv (xo_handle_t *xop, const char *fmt, va_list vap) va_copy(xop->xo_vap, vap); xo_open_container_h(xop, "error"); - xo_format_value(xop, "message", 7, fmt, strlen(fmt), NULL, 0, 0); + xo_format_value(xop, "message", 7, NULL, 0, + fmt, strlen(fmt), NULL, 0, 0); xo_close_container_h(xop, "error"); va_end(xop->xo_vap); @@ -7781,6 +8004,8 @@ xo_parse_args (int argc, char **argv) if (cp) xo_program = cp + 1; + xo_handle_t *xop = xo_default(NULL); + for (save = i = 1; i < argc; i++) { if (argv[i] == NULL || strncmp(argv[i], libxo_opt, sizeof(libxo_opt) - 1) != 0) { @@ -7798,14 +8023,14 @@ xo_parse_args (int argc, char **argv) return -1; } - if (xo_set_options(NULL, cp) < 0) + if (xo_set_options(xop, cp) < 0) return -1; } else if (*cp == ':') { - if (xo_set_options(NULL, cp) < 0) + if (xo_set_options(xop, cp) < 0) return -1; } else if (*cp == '=') { - if (xo_set_options(NULL, ++cp) < 0) + if (xo_set_options(xop, ++cp) < 0) return -1; } else if (*cp == '-') { @@ -7823,6 +8048,13 @@ xo_parse_args (int argc, char **argv) } } + /* + * We only want to do color output on terminals, but we only want + * to do this if the user has asked for color. + */ + if (XOF_ISSET(xop, XOF_COLOR_ALLOWED) && isatty(1)) + XOF_SET(xop, XOF_COLOR); + argv[save] = NULL; return save; } @@ -7884,7 +8116,7 @@ xo_set_version_h (xo_handle_t *xop, const char *version) break; case XO_STYLE_ENCODER: - xo_encoder_handle(xop, XO_OP_VERSION, NULL, version); + xo_encoder_handle(xop, XO_OP_VERSION, NULL, version, 0); break; } } @@ -7934,7 +8166,7 @@ xo_emit_warn_hcv (xo_handle_t *xop, int as_warning, int code, xo_buffer_t *src = &temp.xo_data; xo_format_value(xop, "message", 7, src->xb_bufp, - src->xb_curp - src->xb_bufp, NULL, 0, 0); + src->xb_curp - src->xb_bufp, NULL, 0, NULL, 0, 0); xo_free(temp.xo_stack); xo_buf_cleanup(src); diff --git a/freebsd/contrib/libxo/libxo/xo.h b/freebsd/contrib/libxo/libxo/xo.h index 13023d38..c39fa47e 100644 --- a/freebsd/contrib/libxo/libxo/xo.h +++ b/freebsd/contrib/libxo/libxo/xo.h @@ -101,6 +101,8 @@ typedef unsigned long long xo_xof_flags_t; #define XOF_RETAIN_ALL XOF_BIT(30) /** Force use of XOEF_RETAIN */ #define XOF_RETAIN_NONE XOF_BIT(31) /** Prevent use of XOEF_RETAIN */ +#define XOF_COLOR_MAP XOF_BIT(32) /** Color map has been initialized */ + typedef unsigned xo_emit_flags_t; /* Flags to xo_emit() and friends */ #define XOEF_RETAIN (1<<0) /* Retain parsed formatting information */ diff --git a/freebsd/contrib/libxo/libxo/xo_buf.h b/freebsd/contrib/libxo/libxo/xo_buf.h index 3bb5628a..d6a05005 100644 --- a/freebsd/contrib/libxo/libxo/xo_buf.h +++ b/freebsd/contrib/libxo/libxo/xo_buf.h @@ -133,7 +133,7 @@ xo_buf_has_room (xo_buffer_t *xbp, ssize_t len) static inline void xo_buf_append (xo_buffer_t *xbp, const char *str, ssize_t len) { - if (!xo_buf_has_room(xbp, len)) + if (str == NULL || len == 0 || !xo_buf_has_room(xbp, len)) return; memcpy(xbp->xb_curp, str, len); diff --git a/freebsd/contrib/libxo/libxo/xo_encoder.c b/freebsd/contrib/libxo/libxo/xo_encoder.c index 436e57f5..b114ea78 100644 --- a/freebsd/contrib/libxo/libxo/xo_encoder.c +++ b/freebsd/contrib/libxo/libxo/xo_encoder.c @@ -311,7 +311,7 @@ xo_encoder_init (xo_handle_t *xop, const char *name) xo_set_encoder(xop, xep->xe_handler); - return xo_encoder_handle(xop, XO_OP_CREATE, NULL, NULL); + return xo_encoder_handle(xop, XO_OP_CREATE, NULL, NULL, 0); } /* @@ -337,7 +337,7 @@ xo_encoder_create (const char *name, xo_xof_flags_t flags) int xo_encoder_handle (xo_handle_t *xop, xo_encoder_op_t op, - const char *name, const char *value) + const char *name, const char *value, xo_xof_flags_t flags) { void *private = xo_get_private(xop); xo_encoder_func_t func = xo_get_encoder(xop); @@ -345,7 +345,7 @@ xo_encoder_handle (xo_handle_t *xop, xo_encoder_op_t op, if (func == NULL) return -1; - return func(xop, op, name, value, private); + return func(xop, op, name, value, private, flags); } const char * @@ -416,7 +416,7 @@ xo_encoder_create (const char *name, xo_xof_flags_t flags) int xo_encoder_handle (xo_handle_t *xop, xo_encoder_op_t op, - const char *name, const char *value) + const char *name, const char *value, xo_xof_flags_t flags) { return -1; } diff --git a/freebsd/contrib/libxo/libxo/xo_encoder.h b/freebsd/contrib/libxo/libxo/xo_encoder.h index f73552b1..0e20e72a 100644 --- a/freebsd/contrib/libxo/libxo/xo_encoder.h +++ b/freebsd/contrib/libxo/libxo/xo_encoder.h @@ -50,7 +50,8 @@ typedef unsigned xo_encoder_op_t; xo_encoder_op_t op __attribute__ ((__unused__)), \ const char *name __attribute__ ((__unused__)), \ const char *value __attribute__ ((__unused__)), \ - void *private __attribute__ ((__unused__)) + void *private __attribute__ ((__unused__)), \ + xo_xof_flags_t flags __attribute__ ((__unused__)) typedef int (*xo_encoder_func_t)(XO_ENCODER_HANDLER_ARGS); @@ -105,7 +106,7 @@ xo_encoder_create (const char *name, xo_xof_flags_t flags); int xo_encoder_handle (xo_handle_t *xop, xo_encoder_op_t op, - const char *name, const char *value); + const char *name, const char *value, xo_xof_flags_t flags); void xo_encoders_clean (void); |