libxo.c (298067) | libxo.c (298083) |
---|---|
1/* 2 * Copyright (c) 2014-2015, Juniper Networks, Inc. 3 * All rights reserved. 4 * This SOFTWARE is licensed under the LICENSE provided in the 5 * ../Copyright file. By downloading, installing, copying, or otherwise 6 * using the SOFTWARE, you agree to be bound by the terms of that 7 * LICENSE. 8 * Phil Shafer, July 2014 --- 5 unchanged lines hidden (view full) --- 14 * HTML output that encodes the text output annotated with additional 15 * information. Specialized encoders can be built that allow custom 16 * encoding including binary ones like CBOR, thrift, protobufs, etc. 17 * 18 * Full documentation is available in ./doc/libxo.txt or online at: 19 * http://juniper.github.io/libxo/libxo-manual.html 20 * 21 * For first time readers, the core bits of code to start looking at are: | 1/* 2 * Copyright (c) 2014-2015, Juniper Networks, Inc. 3 * All rights reserved. 4 * This SOFTWARE is licensed under the LICENSE provided in the 5 * ../Copyright file. By downloading, installing, copying, or otherwise 6 * using the SOFTWARE, you agree to be bound by the terms of that 7 * LICENSE. 8 * Phil Shafer, July 2014 --- 5 unchanged lines hidden (view full) --- 14 * HTML output that encodes the text output annotated with additional 15 * information. Specialized encoders can be built that allow custom 16 * encoding including binary ones like CBOR, thrift, protobufs, etc. 17 * 18 * Full documentation is available in ./doc/libxo.txt or online at: 19 * http://juniper.github.io/libxo/libxo-manual.html 20 * 21 * For first time readers, the core bits of code to start looking at are: |
22 * - xo_do_emit() -- the central function of the library | 22 * - xo_do_emit() -- parse and emit a set of fields 23 * - xo_do_emit_fields -- the central function of the library |
23 * - xo_do_format_field() -- handles formatting a single field 24 * - xo_transiton() -- the state machine that keeps things sane 25 * and of course the "xo_handle_t" data structure, which carries all 26 * configuration and state. 27 */ 28 29#include <stdio.h> 30#include <stdlib.h> --- 84 unchanged lines hidden (view full) --- 115#elif HAVE_THREAD_LOCAL == THREAD_LOCAL_declspec 116#define THREAD_LOCAL(_x) __declspec(_x) 117#else 118#error unknown thread-local setting 119#endif /* HAVE_THREADS_H */ 120 121const char xo_version[] = LIBXO_VERSION; 122const char xo_version_extra[] = LIBXO_VERSION_EXTRA; | 24 * - xo_do_format_field() -- handles formatting a single field 25 * - xo_transiton() -- the state machine that keeps things sane 26 * and of course the "xo_handle_t" data structure, which carries all 27 * configuration and state. 28 */ 29 30#include <stdio.h> 31#include <stdlib.h> --- 84 unchanged lines hidden (view full) --- 116#elif HAVE_THREAD_LOCAL == THREAD_LOCAL_declspec 117#define THREAD_LOCAL(_x) __declspec(_x) 118#else 119#error unknown thread-local setting 120#endif /* HAVE_THREADS_H */ 121 122const char xo_version[] = LIBXO_VERSION; 123const char xo_version_extra[] = LIBXO_VERSION_EXTRA; |
124static const char xo_default_format[] = "%s"; |
|
123 124#ifndef UNUSED 125#define UNUSED __attribute__ ((__unused__)) 126#endif /* UNUSED */ 127 128#define XO_INDENT_BY 2 /* Amount to indent when pretty printing */ 129#define XO_DEPTH 128 /* Default stack depth */ 130#define XO_MAX_ANCHOR_WIDTH (8*1024) /* Anything wider is just sillyb */ --- 202 unchanged lines hidden (view full) --- 333#define XFF_HUMANIZE (1<<15) /* Humanize the value (for display styles) */ 334 335#define XFF_HN_SPACE (1<<16) /* Humanize: put space before suffix */ 336#define XFF_HN_DECIMAL (1<<17) /* Humanize: add one decimal place if <10 */ 337#define XFF_HN_1000 (1<<18) /* Humanize: use 1000, not 1024 */ 338#define XFF_GT_FIELD (1<<19) /* Call gettext() on a field */ 339 340#define XFF_GT_PLURAL (1<<20) /* Call dngettext to find plural form */ | 125 126#ifndef UNUSED 127#define UNUSED __attribute__ ((__unused__)) 128#endif /* UNUSED */ 129 130#define XO_INDENT_BY 2 /* Amount to indent when pretty printing */ 131#define XO_DEPTH 128 /* Default stack depth */ 132#define XO_MAX_ANCHOR_WIDTH (8*1024) /* Anything wider is just sillyb */ --- 202 unchanged lines hidden (view full) --- 335#define XFF_HUMANIZE (1<<15) /* Humanize the value (for display styles) */ 336 337#define XFF_HN_SPACE (1<<16) /* Humanize: put space before suffix */ 338#define XFF_HN_DECIMAL (1<<17) /* Humanize: add one decimal place if <10 */ 339#define XFF_HN_1000 (1<<18) /* Humanize: use 1000, not 1024 */ 340#define XFF_GT_FIELD (1<<19) /* Call gettext() on a field */ 341 342#define XFF_GT_PLURAL (1<<20) /* Call dngettext to find plural form */ |
343#define XFF_ARGUMENT (1<<21) /* Content provided via argument */ |
|
341 342/* Flags to turn off when we don't want i18n processing */ 343#define XFF_GT_FLAGS (XFF_GT_FIELD | XFF_GT_PLURAL) 344 345/* 346 * Normal printf has width and precision, which for strings operate as 347 * min and max number of columns. But this depends on the idea that 348 * one byte means one column, which UTF-8 and multi-byte characters --- 692 unchanged lines hidden (view full) --- 1041static int xo_utf8_bits[7] = { 0, 0x7f, 0x1f, 0x0f, 0x07, 0x03, 0x01 }; 1042 1043static int 1044xo_is_utf8 (char ch) 1045{ 1046 return (ch & 0x80); 1047} 1048 | 344 345/* Flags to turn off when we don't want i18n processing */ 346#define XFF_GT_FLAGS (XFF_GT_FIELD | XFF_GT_PLURAL) 347 348/* 349 * Normal printf has width and precision, which for strings operate as 350 * min and max number of columns. But this depends on the idea that 351 * one byte means one column, which UTF-8 and multi-byte characters --- 692 unchanged lines hidden (view full) --- 1044static int xo_utf8_bits[7] = { 0, 0x7f, 0x1f, 0x0f, 0x07, 0x03, 0x01 }; 1045 1046static int 1047xo_is_utf8 (char ch) 1048{ 1049 return (ch & 0x80); 1050} 1051 |
1049static int | 1052static inline int |
1050xo_utf8_to_wc_len (const char *buf) 1051{ 1052 unsigned b = (unsigned char) *buf; 1053 int len; 1054 1055 if ((b & 0x80) == 0x0) 1056 len = 1; 1057 else if ((b & 0xe0) == 0xc0) --- 42 unchanged lines hidden (view full) --- 1100 return len; 1101} 1102 1103/* 1104 * Build a wide character from the input buffer; the number of 1105 * bits we pull off the first character is dependent on the length, 1106 * but we put 6 bits off all other bytes. 1107 */ | 1053xo_utf8_to_wc_len (const char *buf) 1054{ 1055 unsigned b = (unsigned char) *buf; 1056 int len; 1057 1058 if ((b & 0x80) == 0x0) 1059 len = 1; 1060 else if ((b & 0xe0) == 0xc0) --- 42 unchanged lines hidden (view full) --- 1103 return len; 1104} 1105 1106/* 1107 * Build a wide character from the input buffer; the number of 1108 * bits we pull off the first character is dependent on the length, 1109 * but we put 6 bits off all other bytes. 1110 */ |
1108static wchar_t | 1111static inline wchar_t |
1109xo_utf8_char (const char *buf, int len) 1110{ | 1112xo_utf8_char (const char *buf, int len) 1113{ |
1114 /* Most common case: singleton byte */ 1115 if (len == 1) 1116 return (unsigned char) buf[0]; 1117 |
|
1111 int i; 1112 wchar_t wc; 1113 const unsigned char *cp = (const unsigned char *) buf; 1114 1115 wc = *cp & xo_utf8_bits[len]; 1116 for (i = 1; i < len; i++) { 1117 wc <<= 6; 1118 wc |= cp[i] & 0x3f; --- 157 unchanged lines hidden (view full) --- 1276 * Append the given string to the given buffer 1277 */ 1278static void 1279xo_data_escape (xo_handle_t *xop, const char *str, int len) 1280{ 1281 xo_buf_escape(xop, &xop->xo_data, str, len, 0); 1282} 1283 | 1118 int i; 1119 wchar_t wc; 1120 const unsigned char *cp = (const unsigned char *) buf; 1121 1122 wc = *cp & xo_utf8_bits[len]; 1123 for (i = 1; i < len; i++) { 1124 wc <<= 6; 1125 wc |= cp[i] & 0x3f; --- 157 unchanged lines hidden (view full) --- 1283 * Append the given string to the given buffer 1284 */ 1285static void 1286xo_data_escape (xo_handle_t *xop, const char *str, int len) 1287{ 1288 xo_buf_escape(xop, &xop->xo_data, str, len, 0); 1289} 1290 |
1291#ifdef LIBXO_NO_RETAIN |
|
1284/* | 1292/* |
1293 * Empty implementations of the retain logic 1294 */ 1295 1296void 1297xo_retain_clear_all (void) 1298{ 1299 return; 1300} 1301 1302void 1303xo_retain_clear (const char *fmt UNUSED) 1304{ 1305 return; 1306} 1307static void 1308xo_retain_add (const char *fmt UNUSED, xo_field_info_t *fields UNUSED, 1309 unsigned num_fields UNUSED) 1310{ 1311 return; 1312} 1313 1314static int 1315xo_retain_find (const char *fmt UNUSED, xo_field_info_t **valp UNUSED, 1316 unsigned *nump UNUSED) 1317{ 1318 return -1; 1319} 1320 1321#else /* !LIBXO_NO_RETAIN */ 1322/* 1323 * Retain: We retain parsed field definitions to enhance performance, 1324 * especially inside loops. We depend on the caller treating the format 1325 * strings as immutable, so that we can retain pointers into them. We 1326 * hold the pointers in a hash table, so allow quick access. Retained 1327 * information is retained until xo_retain_clear is called. 1328 */ 1329 1330/* 1331 * xo_retain_entry_t holds information about one retained set of 1332 * parsed fields. 1333 */ 1334typedef struct xo_retain_entry_s { 1335 struct xo_retain_entry_s *xre_next; /* Pointer to next (older) entry */ 1336 unsigned long xre_hits; /* Number of times we've hit */ 1337 const char *xre_format; /* Pointer to format string */ 1338 unsigned xre_num_fields; /* Number of fields saved */ 1339 xo_field_info_t *xre_fields; /* Pointer to fields */ 1340} xo_retain_entry_t; 1341 1342/* 1343 * xo_retain_t holds a complete set of parsed fields as a hash table. 1344 */ 1345#ifndef XO_RETAIN_SIZE 1346#define XO_RETAIN_SIZE 6 1347#endif /* XO_RETAIN_SIZE */ 1348#define RETAIN_HASH_SIZE (1<<XO_RETAIN_SIZE) 1349 1350typedef struct xo_retain_s { 1351 xo_retain_entry_t *xr_bucket[RETAIN_HASH_SIZE]; 1352} xo_retain_t; 1353 1354static THREAD_LOCAL(xo_retain_t) xo_retain; 1355static THREAD_LOCAL(unsigned) xo_retain_count; 1356 1357/* 1358 * Simple hash function based on Thomas Wang's paper. The original is 1359 * gone, but an archive is available on the Way Back Machine: 1360 * 1361 * http://web.archive.org/web/20071223173210/\ 1362 * http://www.concentric.net/~Ttwang/tech/inthash.htm 1363 * 1364 * For our purposes, we can assume the low four bits are uninteresting 1365 * since any string less that 16 bytes wouldn't be worthy of 1366 * retaining. We toss the high bits also, since these bits are likely 1367 * to be common among constant format strings. We then run Wang's 1368 * algorithm, and cap the result at RETAIN_HASH_SIZE. 1369 */ 1370static unsigned 1371xo_retain_hash (const char *fmt) 1372{ 1373 volatile uintptr_t iptr = (uintptr_t) (const void *) fmt; 1374 1375 /* Discard low four bits and high bits; they aren't interesting */ 1376 uint32_t val = (uint32_t) ((iptr >> 4) & (((1 << 24) - 1))); 1377 1378 val = (val ^ 61) ^ (val >> 16); 1379 val = val + (val << 3); 1380 val = val ^ (val >> 4); 1381 val = val * 0x3a8f05c5; /* My large prime number */ 1382 val = val ^ (val >> 15); 1383 val &= RETAIN_HASH_SIZE - 1; 1384 1385 return val; 1386} 1387 1388/* 1389 * Walk all buckets, clearing all retained entries 1390 */ 1391void 1392xo_retain_clear_all (void) 1393{ 1394 int i; 1395 xo_retain_entry_t *xrep, *next; 1396 1397 for (i = 0; i < RETAIN_HASH_SIZE; i++) { 1398 for (xrep = xo_retain.xr_bucket[i]; xrep; xrep = next) { 1399 next = xrep->xre_next; 1400 xo_free(xrep); 1401 } 1402 xo_retain.xr_bucket[i] = NULL; 1403 } 1404 xo_retain_count = 0; 1405} 1406 1407/* 1408 * Walk all buckets, clearing all retained entries 1409 */ 1410void 1411xo_retain_clear (const char *fmt) 1412{ 1413 xo_retain_entry_t **xrepp; 1414 unsigned hash = xo_retain_hash(fmt); 1415 1416 for (xrepp = &xo_retain.xr_bucket[hash]; *xrepp; 1417 xrepp = &(*xrepp)->xre_next) { 1418 if ((*xrepp)->xre_format == fmt) { 1419 *xrepp = (*xrepp)->xre_next; 1420 xo_retain_count -= 1; 1421 return; 1422 } 1423 } 1424} 1425 1426/* 1427 * Search the hash for an entry matching 'fmt'; return it's fields. 1428 */ 1429static int 1430xo_retain_find (const char *fmt, xo_field_info_t **valp, unsigned *nump) 1431{ 1432 if (xo_retain_count == 0) 1433 return -1; 1434 1435 unsigned hash = xo_retain_hash(fmt); 1436 xo_retain_entry_t *xrep; 1437 1438 for (xrep = xo_retain.xr_bucket[hash]; xrep != NULL; 1439 xrep = xrep->xre_next) { 1440 if (xrep->xre_format == fmt) { 1441 *valp = xrep->xre_fields; 1442 *nump = xrep->xre_num_fields; 1443 xrep->xre_hits += 1; 1444 return 0; 1445 } 1446 } 1447 1448 return -1; 1449} 1450 1451static void 1452xo_retain_add (const char *fmt, xo_field_info_t *fields, unsigned num_fields) 1453{ 1454 unsigned hash = xo_retain_hash(fmt); 1455 xo_retain_entry_t *xrep; 1456 unsigned sz = sizeof(*xrep) + (num_fields + 1) * sizeof(*fields); 1457 xo_field_info_t *xfip; 1458 1459 xrep = xo_realloc(NULL, sz); 1460 if (xrep == NULL) 1461 return; 1462 1463 xfip = (xo_field_info_t *) &xrep[1]; 1464 memcpy(xfip, fields, num_fields * sizeof(*fields)); 1465 1466 bzero(xrep, sizeof(*xrep)); 1467 1468 xrep->xre_format = fmt; 1469 xrep->xre_fields = xfip; 1470 xrep->xre_num_fields = num_fields; 1471 1472 /* Record the field info in the retain bucket */ 1473 xrep->xre_next = xo_retain.xr_bucket[hash]; 1474 xo_retain.xr_bucket[hash] = xrep; 1475 xo_retain_count += 1; 1476} 1477 1478#endif /* !LIBXO_NO_RETAIN */ 1479 1480/* |
|
1285 * Generate a warning. Normally, this is a text message written to 1286 * standard error. If the XOF_WARN_XML flag is set, then we generate 1287 * XMLified content on standard output. 1288 */ 1289static void 1290xo_warn_hcv (xo_handle_t *xop, int code, int check_warn, 1291 const char *fmt, va_list vap) 1292{ --- 276 unchanged lines hidden (view full) --- 1569 } 1570 } 1571 if (need_nl) 1572 xo_printf(xop, "\n"); 1573 1574 break; 1575 } 1576 | 1481 * Generate a warning. Normally, this is a text message written to 1482 * standard error. If the XOF_WARN_XML flag is set, then we generate 1483 * XMLified content on standard output. 1484 */ 1485static void 1486xo_warn_hcv (xo_handle_t *xop, int code, int check_warn, 1487 const char *fmt, va_list vap) 1488{ --- 276 unchanged lines hidden (view full) --- 1765 } 1766 } 1767 if (need_nl) 1768 xo_printf(xop, "\n"); 1769 1770 break; 1771 } 1772 |
1773 switch (xo_style(xop)) { 1774 case XO_STYLE_HTML: 1775 if (XOIF_ISSET(xop, XOIF_DIV_OPEN)) { 1776 static char div_close[] = "</div>"; 1777 XOIF_CLEAR(xop, XOIF_DIV_OPEN); 1778 xo_data_append(xop, div_close, sizeof(div_close) - 1); 1779 1780 if (XOF_ISSET(xop, XOF_PRETTY)) 1781 xo_data_append(xop, "\n", 1); 1782 } 1783 break; 1784 } 1785 |
|
1577 (void) xo_flush_h(xop); 1578} 1579 1580void 1581xo_message_hc (xo_handle_t *xop, int code, const char *fmt, ...) 1582{ 1583 va_list vap; 1584 --- 90 unchanged lines hidden (view full) --- 1675 xop->xo_close = xo_close_file; 1676 xop->xo_flush = xo_flush_file; 1677 } 1678 1679 return xop; 1680} 1681 1682/** | 1786 (void) xo_flush_h(xop); 1787} 1788 1789void 1790xo_message_hc (xo_handle_t *xop, int code, const char *fmt, ...) 1791{ 1792 va_list vap; 1793 --- 90 unchanged lines hidden (view full) --- 1884 xop->xo_close = xo_close_file; 1885 xop->xo_flush = xo_flush_file; 1886 } 1887 1888 return xop; 1889} 1890 1891/** |
1892 * Set the default handler to output to a file. 1893 * @xop libxo handle 1894 * @fp FILE pointer to use 1895 */ 1896int 1897xo_set_file_h (xo_handle_t *xop, FILE *fp) 1898{ 1899 xop = xo_default(xop); 1900 1901 if (fp == NULL) { 1902 xo_failure(xop, "xo_set_file: NULL fp"); 1903 return -1; 1904 } 1905 1906 xop->xo_opaque = fp; 1907 xop->xo_write = xo_write_to_file; 1908 xop->xo_close = xo_close_file; 1909 xop->xo_flush = xo_flush_file; 1910 1911 return 0; 1912} 1913 1914/** 1915 * Set the default handler to output to a file. 1916 * @fp FILE pointer to use 1917 */ 1918int 1919xo_set_file (FILE *fp) 1920{ 1921 return xo_set_file_h(NULL, fp); 1922} 1923 1924/** |
|
1683 * Release any resources held by the handle. 1684 * @xop XO handle to alter (or NULL for default handle) 1685 */ 1686void 1687xo_destroy (xo_handle_t *xop_arg) 1688{ 1689 xo_handle_t *xop = xo_default(xop_arg); 1690 --- 128 unchanged lines hidden (view full) --- 1819 { XOF_FLUSH, "flush" }, 1820 { XOF_IGNORE_CLOSE, "ignore-close" }, 1821 { XOF_INFO, "info" }, 1822 { XOF_KEYS, "keys" }, 1823 { XOF_LOG_GETTEXT, "log-gettext" }, 1824 { XOF_LOG_SYSLOG, "log-syslog" }, 1825 { XOF_NO_HUMANIZE, "no-humanize" }, 1826 { XOF_NO_LOCALE, "no-locale" }, | 1925 * Release any resources held by the handle. 1926 * @xop XO handle to alter (or NULL for default handle) 1927 */ 1928void 1929xo_destroy (xo_handle_t *xop_arg) 1930{ 1931 xo_handle_t *xop = xo_default(xop_arg); 1932 --- 128 unchanged lines hidden (view full) --- 2061 { XOF_FLUSH, "flush" }, 2062 { XOF_IGNORE_CLOSE, "ignore-close" }, 2063 { XOF_INFO, "info" }, 2064 { XOF_KEYS, "keys" }, 2065 { XOF_LOG_GETTEXT, "log-gettext" }, 2066 { XOF_LOG_SYSLOG, "log-syslog" }, 2067 { XOF_NO_HUMANIZE, "no-humanize" }, 2068 { XOF_NO_LOCALE, "no-locale" }, |
2069 { XOF_RETAIN_NONE, "no-retain" }, |
|
1827 { XOF_NO_TOP, "no-top" }, 1828 { XOF_NOT_FIRST, "not-first" }, 1829 { XOF_PRETTY, "pretty" }, | 2070 { XOF_NO_TOP, "no-top" }, 2071 { XOF_NOT_FIRST, "not-first" }, 2072 { XOF_PRETTY, "pretty" }, |
2073 { XOF_RETAIN_ALL, "retain" }, |
|
1830 { XOF_UNDERSCORES, "underscores" }, 1831 { XOF_UNITS, "units" }, 1832 { XOF_WARN, "warn" }, 1833 { XOF_WARN_XML, "warn-xml" }, 1834 { XOF_XPATH, "xpath" }, 1835 { 0, NULL } 1836}; 1837 --- 1770 unchanged lines hidden (view full) --- 3608 3609 case XO_STYLE_HTML: 3610 xo_buf_append_div(xop, "text", 0, NULL, 0, str, len, NULL, 0); 3611 break; 3612 } 3613} 3614 3615static void | 2074 { XOF_UNDERSCORES, "underscores" }, 2075 { XOF_UNITS, "units" }, 2076 { XOF_WARN, "warn" }, 2077 { XOF_WARN_XML, "warn-xml" }, 2078 { XOF_XPATH, "xpath" }, 2079 { 0, NULL } 2080}; 2081 --- 1770 unchanged lines hidden (view full) --- 3852 3853 case XO_STYLE_HTML: 3854 xo_buf_append_div(xop, "text", 0, NULL, 0, str, len, NULL, 0); 3855 break; 3856 } 3857} 3858 3859static void |
3616xo_format_title (xo_handle_t *xop, xo_field_info_t *xfip) | 3860xo_format_title (xo_handle_t *xop, xo_field_info_t *xfip, 3861 const char *str, unsigned len) |
3617{ | 3862{ |
3618 const char *str = xfip->xfi_content; 3619 unsigned len = xfip->xfi_clen; | |
3620 const char *fmt = xfip->xfi_format; 3621 unsigned flen = xfip->xfi_flen; 3622 xo_xff_flags_t flags = xfip->xfi_flags; 3623 3624 static char div_open[] = "<div class=\"title"; 3625 static char div_middle[] = "\">"; 3626 static char div_close[] = "</div>"; 3627 --- 450 unchanged lines hidden (view full) --- 4078 xo_buf_data(&xop->xo_data, name_offset), 4079 xo_buf_data(&xop->xo_data, value_offset)); 4080 xo_buf_reset(&xop->xo_data); 4081 break; 4082 } 4083} 4084 4085static void | 3863 const char *fmt = xfip->xfi_format; 3864 unsigned flen = xfip->xfi_flen; 3865 xo_xff_flags_t flags = xfip->xfi_flags; 3866 3867 static char div_open[] = "<div class=\"title"; 3868 static char div_middle[] = "\">"; 3869 static char div_close[] = "</div>"; 3870 --- 450 unchanged lines hidden (view full) --- 4321 xo_buf_data(&xop->xo_data, name_offset), 4322 xo_buf_data(&xop->xo_data, value_offset)); 4323 xo_buf_reset(&xop->xo_data); 4324 break; 4325 } 4326} 4327 4328static void |
4086xo_set_gettext_domain (xo_handle_t *xop, xo_field_info_t *xfip) | 4329xo_set_gettext_domain (xo_handle_t *xop, xo_field_info_t *xfip, 4330 const char *str, unsigned len) |
4087{ | 4331{ |
4088 const char *str = xfip->xfi_content; 4089 unsigned len = xfip->xfi_clen; | |
4090 const char *fmt = xfip->xfi_format; 4091 unsigned flen = xfip->xfi_flen; 4092 4093 /* Start by discarding previous domain */ 4094 if (xop->xo_gt_domain) { 4095 xo_free(xop->xo_gt_domain); 4096 xop->xo_gt_domain = NULL; 4097 } --- 232 unchanged lines hidden (view full) --- 4330#ifdef LIBXO_TEXT_ONLY 4331 return 0; 4332#else /* LIBXO_TEXT_ONLY */ 4333 return XOF_ISSET(xop, XOF_COLOR); 4334#endif /* LIBXO_TEXT_ONLY */ 4335} 4336 4337static void | 4332 const char *fmt = xfip->xfi_format; 4333 unsigned flen = xfip->xfi_flen; 4334 4335 /* Start by discarding previous domain */ 4336 if (xop->xo_gt_domain) { 4337 xo_free(xop->xo_gt_domain); 4338 xop->xo_gt_domain = NULL; 4339 } --- 232 unchanged lines hidden (view full) --- 4572#ifdef LIBXO_TEXT_ONLY 4573 return 0; 4574#else /* LIBXO_TEXT_ONLY */ 4575 return XOF_ISSET(xop, XOF_COLOR); 4576#endif /* LIBXO_TEXT_ONLY */ 4577} 4578 4579static void |
4338xo_colors_handle_text (xo_handle_t *xop UNUSED, xo_colors_t *newp) | 4580xo_colors_handle_text (xo_handle_t *xop, xo_colors_t *newp) |
4339{ 4340 char buf[BUFSIZ]; 4341 char *cp = buf, *ep = buf + sizeof(buf); 4342 unsigned i, bit; 4343 xo_colors_t *oldp = &xop->xo_colors; | 4581{ 4582 char buf[BUFSIZ]; 4583 char *cp = buf, *ep = buf + sizeof(buf); 4584 unsigned i, bit; 4585 xo_colors_t *oldp = &xop->xo_colors; |
4344 const char *code; | 4586 const char *code = NULL; |
4345 4346 /* 4347 * Start the buffer with an escape. We don't want to add the '[' 4348 * now, since we let xo_effect_text_add unconditionally add the ';'. 4349 * We'll replace the first ';' with a '[' when we're done. 4350 */ 4351 *cp++ = 0x1b; /* Escape */ 4352 --- 102 unchanged lines hidden (view full) --- 4455 4456 if (bg) { 4457 xo_buf_append_str(xbp, " color-bg-"); 4458 xo_buf_append_str(xbp, bg); 4459 } 4460} 4461 4462static void | 4587 4588 /* 4589 * Start the buffer with an escape. We don't want to add the '[' 4590 * now, since we let xo_effect_text_add unconditionally add the ';'. 4591 * We'll replace the first ';' with a '[' when we're done. 4592 */ 4593 *cp++ = 0x1b; /* Escape */ 4594 --- 102 unchanged lines hidden (view full) --- 4697 4698 if (bg) { 4699 xo_buf_append_str(xbp, " color-bg-"); 4700 xo_buf_append_str(xbp, bg); 4701 } 4702} 4703 4704static void |
4463xo_format_colors (xo_handle_t *xop, xo_field_info_t *xfip) | 4705xo_format_colors (xo_handle_t *xop, xo_field_info_t *xfip, 4706 const char *str, unsigned len) |
4464{ | 4707{ |
4465 const char *str = xfip->xfi_content; 4466 unsigned len = xfip->xfi_clen; | |
4467 const char *fmt = xfip->xfi_format; 4468 unsigned flen = xfip->xfi_flen; 4469 4470 xo_buffer_t xb; 4471 4472 /* If the string is static and we've in an encoding style, bail */ 4473 if (len != 0 && xo_style_is_encoding(xop)) 4474 return; --- 54 unchanged lines hidden (view full) --- 4529 break; 4530 } 4531 } 4532 4533 xo_buf_cleanup(&xb); 4534} 4535 4536static void | 4708 const char *fmt = xfip->xfi_format; 4709 unsigned flen = xfip->xfi_flen; 4710 4711 xo_buffer_t xb; 4712 4713 /* If the string is static and we've in an encoding style, bail */ 4714 if (len != 0 && xo_style_is_encoding(xop)) 4715 return; --- 54 unchanged lines hidden (view full) --- 4770 break; 4771 } 4772 } 4773 4774 xo_buf_cleanup(&xb); 4775} 4776 4777static void |
4537xo_format_units (xo_handle_t *xop, xo_field_info_t *xfip) | 4778xo_format_units (xo_handle_t *xop, xo_field_info_t *xfip, 4779 const char *str, unsigned len) |
4538{ | 4780{ |
4539 const char *str = xfip->xfi_content; 4540 unsigned len = xfip->xfi_clen; | |
4541 const char *fmt = xfip->xfi_format; 4542 unsigned flen = xfip->xfi_flen; 4543 xo_xff_flags_t flags = xfip->xfi_flags; 4544 4545 static char units_start_xml[] = " units=\""; 4546 static char units_start_html[] = " data-units=\""; 4547 4548 if (!XOIF_ISSET(xop, XOIF_UNITS_PENDING)) { --- 35 unchanged lines hidden (view full) --- 4584 char *buf = alloca(delta); 4585 4586 memcpy(buf, xbp->xb_bufp + stop, delta); 4587 memmove(xbp->xb_bufp + start + delta, xbp->xb_bufp + start, stop - start); 4588 memmove(xbp->xb_bufp + start, buf, delta); 4589} 4590 4591static int | 4781 const char *fmt = xfip->xfi_format; 4782 unsigned flen = xfip->xfi_flen; 4783 xo_xff_flags_t flags = xfip->xfi_flags; 4784 4785 static char units_start_xml[] = " units=\""; 4786 static char units_start_html[] = " data-units=\""; 4787 4788 if (!XOIF_ISSET(xop, XOIF_UNITS_PENDING)) { --- 35 unchanged lines hidden (view full) --- 4824 char *buf = alloca(delta); 4825 4826 memcpy(buf, xbp->xb_bufp + stop, delta); 4827 memmove(xbp->xb_bufp + start + delta, xbp->xb_bufp + start, stop - start); 4828 memmove(xbp->xb_bufp + start, buf, delta); 4829} 4830 4831static int |
4592xo_find_width (xo_handle_t *xop, xo_field_info_t *xfip) | 4832xo_find_width (xo_handle_t *xop, xo_field_info_t *xfip, 4833 const char *str, unsigned len) |
4593{ | 4834{ |
4594 const char *str = xfip->xfi_content; 4595 unsigned len = xfip->xfi_clen; | |
4596 const char *fmt = xfip->xfi_format; 4597 unsigned flen = xfip->xfi_flen; 4598 4599 long width = 0; 4600 char *bp; 4601 char *cp; 4602 4603 if (len) { --- 30 unchanged lines hidden (view full) --- 4634 * An anchor is a marker used to delay field width implications. 4635 * Imagine the format string "{[:10}{min:%d}/{cur:%d}/{max:%d}{:]}". 4636 * We are looking for output like " 1/4/5" 4637 * 4638 * To make this work, we record the anchor and then return to 4639 * format it when the end anchor tag is seen. 4640 */ 4641static void | 4835 const char *fmt = xfip->xfi_format; 4836 unsigned flen = xfip->xfi_flen; 4837 4838 long width = 0; 4839 char *bp; 4840 char *cp; 4841 4842 if (len) { --- 30 unchanged lines hidden (view full) --- 4873 * An anchor is a marker used to delay field width implications. 4874 * Imagine the format string "{[:10}{min:%d}/{cur:%d}/{max:%d}{:]}". 4875 * We are looking for output like " 1/4/5" 4876 * 4877 * To make this work, we record the anchor and then return to 4878 * format it when the end anchor tag is seen. 4879 */ 4880static void |
4642xo_anchor_start (xo_handle_t *xop, xo_field_info_t *xfip) | 4881xo_anchor_start (xo_handle_t *xop, xo_field_info_t *xfip, 4882 const char *str, unsigned len) |
4643{ 4644 if (xo_style(xop) != XO_STYLE_TEXT && xo_style(xop) != XO_STYLE_HTML) 4645 return; 4646 4647 if (XOIF_ISSET(xop, XOIF_ANCHOR)) 4648 xo_failure(xop, "the anchor already recording is discarded"); 4649 4650 XOIF_SET(xop, XOIF_ANCHOR); 4651 xo_buffer_t *xbp = &xop->xo_data; 4652 xop->xo_anchor_offset = xbp->xb_curp - xbp->xb_bufp; 4653 xop->xo_anchor_columns = 0; 4654 4655 /* 4656 * Now we find the width, if possible. If it's not there, 4657 * we'll get it on the end anchor. 4658 */ | 4883{ 4884 if (xo_style(xop) != XO_STYLE_TEXT && xo_style(xop) != XO_STYLE_HTML) 4885 return; 4886 4887 if (XOIF_ISSET(xop, XOIF_ANCHOR)) 4888 xo_failure(xop, "the anchor already recording is discarded"); 4889 4890 XOIF_SET(xop, XOIF_ANCHOR); 4891 xo_buffer_t *xbp = &xop->xo_data; 4892 xop->xo_anchor_offset = xbp->xb_curp - xbp->xb_bufp; 4893 xop->xo_anchor_columns = 0; 4894 4895 /* 4896 * Now we find the width, if possible. If it's not there, 4897 * we'll get it on the end anchor. 4898 */ |
4659 xop->xo_anchor_min_width = xo_find_width(xop, xfip); | 4899 xop->xo_anchor_min_width = xo_find_width(xop, xfip, str, len); |
4660} 4661 4662static void | 4900} 4901 4902static void |
4663xo_anchor_stop (xo_handle_t *xop, xo_field_info_t *xfip) | 4903xo_anchor_stop (xo_handle_t *xop, xo_field_info_t *xfip, 4904 const char *str, unsigned len) |
4664{ 4665 if (xo_style(xop) != XO_STYLE_TEXT && xo_style(xop) != XO_STYLE_HTML) 4666 return; 4667 4668 if (!XOIF_ISSET(xop, XOIF_ANCHOR)) { 4669 xo_failure(xop, "no start anchor"); 4670 return; 4671 } 4672 4673 XOIF_CLEAR(xop, XOIF_UNITS_PENDING); 4674 | 4905{ 4906 if (xo_style(xop) != XO_STYLE_TEXT && xo_style(xop) != XO_STYLE_HTML) 4907 return; 4908 4909 if (!XOIF_ISSET(xop, XOIF_ANCHOR)) { 4910 xo_failure(xop, "no start anchor"); 4911 return; 4912 } 4913 4914 XOIF_CLEAR(xop, XOIF_UNITS_PENDING); 4915 |
4675 int width = xo_find_width(xop, xfip); | 4916 int width = xo_find_width(xop, xfip, str, len); |
4676 if (width == 0) 4677 width = xop->xo_anchor_min_width; 4678 4679 if (width == 0) /* No width given; nothing to do */ 4680 goto done; 4681 4682 xo_buffer_t *xbp = &xop->xo_data; 4683 int start = xop->xo_anchor_offset; --- 98 unchanged lines hidden (view full) --- 4782 { 0, NULL } 4783}; 4784 4785#define XO_ROLE_EBRACE '{' /* Escaped braces */ 4786#define XO_ROLE_TEXT '+' 4787#define XO_ROLE_NEWLINE '\n' 4788 4789static xo_mapping_t xo_modifier_names[] = { | 4917 if (width == 0) 4918 width = xop->xo_anchor_min_width; 4919 4920 if (width == 0) /* No width given; nothing to do */ 4921 goto done; 4922 4923 xo_buffer_t *xbp = &xop->xo_data; 4924 int start = xop->xo_anchor_offset; --- 98 unchanged lines hidden (view full) --- 5023 { 0, NULL } 5024}; 5025 5026#define XO_ROLE_EBRACE '{' /* Escaped braces */ 5027#define XO_ROLE_TEXT '+' 5028#define XO_ROLE_NEWLINE '\n' 5029 5030static xo_mapping_t xo_modifier_names[] = { |
5031 { XFF_ARGUMENT, "argument" }, |
|
4790 { XFF_COLON, "colon" }, 4791 { XFF_COMMA, "comma" }, 4792 { XFF_DISPLAY_ONLY, "display" }, 4793 { XFF_ENCODE_ONLY, "encoding" }, 4794 { XFF_GT_FIELD, "gettext" }, 4795 { XFF_HUMANIZE, "humanize" }, 4796 { XFF_HUMANIZE, "hn" }, 4797 { XFF_HN_SPACE, "hn-space" }, --- 55 unchanged lines hidden (view full) --- 4853 * 'P': padding; whitespace 4854 * 'T': Title, where 'content' is a column title 4855 * 'U': Units, where 'content' is the unit label 4856 * 'V': value, where 'content' is the name of the field (the default) 4857 * 'W': warning message 4858 * '[': start a section of anchored text 4859 * ']': end a section of anchored text 4860 * The following modifiers are also supported: | 5032 { XFF_COLON, "colon" }, 5033 { XFF_COMMA, "comma" }, 5034 { XFF_DISPLAY_ONLY, "display" }, 5035 { XFF_ENCODE_ONLY, "encoding" }, 5036 { XFF_GT_FIELD, "gettext" }, 5037 { XFF_HUMANIZE, "humanize" }, 5038 { XFF_HUMANIZE, "hn" }, 5039 { XFF_HN_SPACE, "hn-space" }, --- 55 unchanged lines hidden (view full) --- 5095 * 'P': padding; whitespace 5096 * 'T': Title, where 'content' is a column title 5097 * 'U': Units, where 'content' is the unit label 5098 * 'V': value, where 'content' is the name of the field (the default) 5099 * 'W': warning message 5100 * '[': start a section of anchored text 5101 * ']': end a section of anchored text 5102 * The following modifiers are also supported: |
5103 * 'a': content is provided via argument (const char *), not descriptor |
|
4861 * 'c': flag: emit a colon after the label 4862 * 'd': field is only emitted for display styles (text and html) 4863 * 'e': field is only emitted for encoding styles (xml and json) 4864 * 'g': gettext() the field 4865 * 'h': humanize a numeric value (only for display styles) 4866 * 'k': this field is a key, suitable for XPath predicates 4867 * 'l': a leaf-list, a simple list of values 4868 * 'n': no quotes around this field --- 10 unchanged lines hidden (view full) --- 4879xo_parse_roles (xo_handle_t *xop, const char *fmt, 4880 const char *basep, xo_field_info_t *xfip) 4881{ 4882 const char *sp; 4883 unsigned ftype = 0; 4884 xo_xff_flags_t flags = 0; 4885 uint8_t fnum = 0; 4886 | 5104 * 'c': flag: emit a colon after the label 5105 * 'd': field is only emitted for display styles (text and html) 5106 * 'e': field is only emitted for encoding styles (xml and json) 5107 * 'g': gettext() the field 5108 * 'h': humanize a numeric value (only for display styles) 5109 * 'k': this field is a key, suitable for XPath predicates 5110 * 'l': a leaf-list, a simple list of values 5111 * 'n': no quotes around this field --- 10 unchanged lines hidden (view full) --- 5122xo_parse_roles (xo_handle_t *xop, const char *fmt, 5123 const char *basep, xo_field_info_t *xfip) 5124{ 5125 const char *sp; 5126 unsigned ftype = 0; 5127 xo_xff_flags_t flags = 0; 5128 uint8_t fnum = 0; 5129 |
4887 for (sp = basep; sp; sp++) { | 5130 for (sp = basep; sp && *sp; sp++) { |
4888 if (*sp == ':' || *sp == '/' || *sp == '}') 4889 break; 4890 4891 if (*sp == '\\') { 4892 if (sp[1] == '\0') { 4893 xo_failure(xop, "backslash at the end of string"); 4894 return NULL; 4895 } --- 60 unchanged lines hidden (view full) --- 4956 case '5': 4957 case '6': 4958 case '7': 4959 case '8': 4960 case '9': 4961 fnum = (fnum * 10) + (*sp - '0'); 4962 break; 4963 | 5131 if (*sp == ':' || *sp == '/' || *sp == '}') 5132 break; 5133 5134 if (*sp == '\\') { 5135 if (sp[1] == '\0') { 5136 xo_failure(xop, "backslash at the end of string"); 5137 return NULL; 5138 } --- 60 unchanged lines hidden (view full) --- 5199 case '5': 5200 case '6': 5201 case '7': 5202 case '8': 5203 case '9': 5204 fnum = (fnum * 10) + (*sp - '0'); 5205 break; 5206 |
5207 case 'a': 5208 flags |= XFF_ARGUMENT; 5209 break; 5210 |
|
4964 case 'c': 4965 flags |= XFF_COLON; 4966 break; 4967 4968 case 'd': 4969 flags |= XFF_DISPLAY_ONLY; 4970 break; 4971 --- 156 unchanged lines hidden (view full) --- 5128 5129 return 0; 5130} 5131 5132static int 5133xo_parse_fields (xo_handle_t *xop, xo_field_info_t *fields, 5134 unsigned num_fields, const char *fmt) 5135{ | 5211 case 'c': 5212 flags |= XFF_COLON; 5213 break; 5214 5215 case 'd': 5216 flags |= XFF_DISPLAY_ONLY; 5217 break; 5218 --- 156 unchanged lines hidden (view full) --- 5375 5376 return 0; 5377} 5378 5379static int 5380xo_parse_fields (xo_handle_t *xop, xo_field_info_t *fields, 5381 unsigned num_fields, const char *fmt) 5382{ |
5136 static const char default_format[] = "%s"; | |
5137 const char *cp, *sp, *ep, *basep; 5138 unsigned field = 0; 5139 xo_field_info_t *xfip = fields; 5140 unsigned seen_fnum = 0; 5141 5142 for (cp = fmt; *cp && field < num_fields; field++, xfip++) { 5143 xfip->xfi_start = cp; 5144 --- 117 unchanged lines hidden (view full) --- 5262 xo_failure(xop, "missing closing '}': %s", xo_printable(fmt)); 5263 return -1; 5264 } 5265 5266 xfip->xfi_len = sp - xfip->xfi_start; 5267 xfip->xfi_next = ++sp; 5268 5269 /* If we have content, then we have a default format */ | 5383 const char *cp, *sp, *ep, *basep; 5384 unsigned field = 0; 5385 xo_field_info_t *xfip = fields; 5386 unsigned seen_fnum = 0; 5387 5388 for (cp = fmt; *cp && field < num_fields; field++, xfip++) { 5389 xfip->xfi_start = cp; 5390 --- 117 unchanged lines hidden (view full) --- 5508 xo_failure(xop, "missing closing '}': %s", xo_printable(fmt)); 5509 return -1; 5510 } 5511 5512 xfip->xfi_len = sp - xfip->xfi_start; 5513 xfip->xfi_next = ++sp; 5514 5515 /* If we have content, then we have a default format */ |
5270 if (xfip->xfi_clen || format) { | 5516 if (xfip->xfi_clen || format || (xfip->xfi_flags & XFF_ARGUMENT)) { |
5271 if (format) { 5272 xfip->xfi_format = format; 5273 xfip->xfi_flen = flen; 5274 } else if (xo_role_wants_default_format(xfip->xfi_ftype)) { | 5517 if (format) { 5518 xfip->xfi_format = format; 5519 xfip->xfi_flen = flen; 5520 } else if (xo_role_wants_default_format(xfip->xfi_ftype)) { |
5275 xfip->xfi_format = default_format; | 5521 xfip->xfi_format = xo_default_format; |
5276 xfip->xfi_flen = 2; 5277 } 5278 } 5279 5280 cp = sp; 5281 } 5282 5283 int rc = 0; --- 279 unchanged lines hidden (view full) --- 5563 * format string: 5564 * "cluse-a {:fd} retoorned {:test}. Bork {:error} Bork. Bork.\n" 5565 * If we have to reorder fields within the message, then things get 5566 * complicated. See xo_gettext_rewrite_fields. 5567 * 5568 * Summary: i18n aighn't cheap. 5569 */ 5570static const char * | 5522 xfip->xfi_flen = 2; 5523 } 5524 } 5525 5526 cp = sp; 5527 } 5528 5529 int rc = 0; --- 279 unchanged lines hidden (view full) --- 5809 * format string: 5810 * "cluse-a {:fd} retoorned {:test}. Bork {:error} Bork. Bork.\n" 5811 * If we have to reorder fields within the message, then things get 5812 * complicated. See xo_gettext_rewrite_fields. 5813 * 5814 * Summary: i18n aighn't cheap. 5815 */ 5816static const char * |
5571xo_gettext_build_format (xo_handle_t *xop UNUSED, 5572 xo_field_info_t *fields UNUSED, 5573 int this_field UNUSED, | 5817xo_gettext_build_format (xo_handle_t *xop, 5818 xo_field_info_t *fields, int this_field, |
5574 const char *fmt, char **new_fmtp) 5575{ 5576 if (xo_style_is_encoding(xop)) 5577 goto bail; 5578 5579 xo_buffer_t xb; 5580 xo_buf_init(&xb); 5581 --- 99 unchanged lines hidden (view full) --- 5681 unsigned *fstart UNUSED, unsigned min_fstart UNUSED, 5682 unsigned *fend UNUSED, unsigned max_fend UNUSED) 5683{ 5684 return; 5685} 5686#endif /* HAVE_GETTEXT */ 5687 5688/* | 5819 const char *fmt, char **new_fmtp) 5820{ 5821 if (xo_style_is_encoding(xop)) 5822 goto bail; 5823 5824 xo_buffer_t xb; 5825 xo_buf_init(&xb); 5826 --- 99 unchanged lines hidden (view full) --- 5926 unsigned *fstart UNUSED, unsigned min_fstart UNUSED, 5927 unsigned *fend UNUSED, unsigned max_fend UNUSED) 5928{ 5929 return; 5930} 5931#endif /* HAVE_GETTEXT */ 5932 5933/* |
5689 * The central function for emitting libxo output. | 5934 * Emit a set of fields. This is really the core of libxo. |
5690 */ 5691static int | 5935 */ 5936static int |
5692xo_do_emit (xo_handle_t *xop, const char *fmt) | 5937xo_do_emit_fields (xo_handle_t *xop, xo_field_info_t *fields, 5938 unsigned max_fields, const char *fmt) |
5693{ 5694 int gettext_inuse = 0; 5695 int gettext_changed = 0; 5696 int gettext_reordered = 0; | 5939{ 5940 int gettext_inuse = 0; 5941 int gettext_changed = 0; 5942 int gettext_reordered = 0; |
5943 unsigned ftype; 5944 xo_xff_flags_t flags; |
|
5697 xo_field_info_t *new_fields = NULL; | 5945 xo_field_info_t *new_fields = NULL; |
5698 | 5946 xo_field_info_t *xfip; 5947 unsigned field; |
5699 int rc = 0; | 5948 int rc = 0; |
5949 |
|
5700 int flush = XOF_ISSET(xop, XOF_FLUSH); 5701 int flush_line = XOF_ISSET(xop, XOF_FLUSH_LINE); 5702 char *new_fmt = NULL; 5703 5704 if (XOIF_ISSET(xop, XOIF_REORDER) || xo_style(xop) == XO_STYLE_ENCODER) 5705 flush_line = 0; 5706 | 5950 int flush = XOF_ISSET(xop, XOF_FLUSH); 5951 int flush_line = XOF_ISSET(xop, XOF_FLUSH_LINE); 5952 char *new_fmt = NULL; 5953 5954 if (XOIF_ISSET(xop, XOIF_REORDER) || xo_style(xop) == XO_STYLE_ENCODER) 5955 flush_line = 0; 5956 |
5707 xop->xo_columns = 0; /* Always reset it */ 5708 xop->xo_errno = errno; /* Save for "%m" */ 5709 5710 unsigned max_fields = xo_count_fields(xop, fmt), field; 5711 xo_field_info_t fields[max_fields], *xfip; 5712 5713 bzero(fields, max_fields * sizeof(fields[0])); 5714 5715 if (xo_parse_fields(xop, fields, max_fields, fmt)) 5716 return -1; /* Warning already displayed */ 5717 5718 unsigned ftype; 5719 xo_xff_flags_t flags; 5720 | |
5721 /* 5722 * Some overhead for gettext; if the fields in the msgstr returned 5723 * by gettext are reordered, then we need to record start and end 5724 * for each field. We'll go ahead and render the fields in the 5725 * normal order, but later we can then reconstruct the reordered 5726 * fields using these fstart/fend values. 5727 */ 5728 unsigned flimit = max_fields * 2; /* Pessimistic limit */ --- 11 unchanged lines hidden (view full) --- 5740 5741 /* Record field start offset */ 5742 if (gettext_reordered) { 5743 fstart[field] = xo_buf_offset(&xop->xo_data); 5744 if (min_fstart > field) 5745 min_fstart = field; 5746 } 5747 | 5957 /* 5958 * Some overhead for gettext; if the fields in the msgstr returned 5959 * by gettext are reordered, then we need to record start and end 5960 * for each field. We'll go ahead and render the fields in the 5961 * normal order, but later we can then reconstruct the reordered 5962 * fields using these fstart/fend values. 5963 */ 5964 unsigned flimit = max_fields * 2; /* Pessimistic limit */ --- 11 unchanged lines hidden (view full) --- 5976 5977 /* Record field start offset */ 5978 if (gettext_reordered) { 5979 fstart[field] = xo_buf_offset(&xop->xo_data); 5980 if (min_fstart > field) 5981 min_fstart = field; 5982 } 5983 |
5984 const char *content = xfip->xfi_content; 5985 int clen = xfip->xfi_clen; 5986 5987 if (flags & XFF_ARGUMENT) { 5988 /* 5989 * Argument flag means the content isn't given in the descriptor, 5990 * but as a UTF-8 string ('const char *') argument in xo_vap. 5991 */ 5992 content = va_arg(xop->xo_vap, char *); 5993 clen = content ? strlen(content) : 0; 5994 } 5995 |
|
5748 if (ftype == XO_ROLE_NEWLINE) { 5749 xo_line_close(xop); 5750 if (flush_line && xo_flush_h(xop) < 0) 5751 return -1; 5752 goto bottom; 5753 5754 } else if (ftype == XO_ROLE_EBRACE) { 5755 xo_format_text(xop, xfip->xfi_start, xfip->xfi_len); --- 12 unchanged lines hidden (view full) --- 5768 if (flags & XFF_WS) { 5769 xo_format_content(xop, "padding", NULL, " ", 1, 5770 NULL, 0, flags); 5771 flags &= ~XFF_WS; /* Block later handling of this */ 5772 } 5773 } 5774 5775 if (ftype == 'V') | 5996 if (ftype == XO_ROLE_NEWLINE) { 5997 xo_line_close(xop); 5998 if (flush_line && xo_flush_h(xop) < 0) 5999 return -1; 6000 goto bottom; 6001 6002 } else if (ftype == XO_ROLE_EBRACE) { 6003 xo_format_text(xop, xfip->xfi_start, xfip->xfi_len); --- 12 unchanged lines hidden (view full) --- 6016 if (flags & XFF_WS) { 6017 xo_format_content(xop, "padding", NULL, " ", 1, 6018 NULL, 0, flags); 6019 flags &= ~XFF_WS; /* Block later handling of this */ 6020 } 6021 } 6022 6023 if (ftype == 'V') |
5776 xo_format_value(xop, xfip->xfi_content, xfip->xfi_clen, | 6024 xo_format_value(xop, content, clen, |
5777 xfip->xfi_format, xfip->xfi_flen, 5778 xfip->xfi_encoding, xfip->xfi_elen, flags); 5779 else if (ftype == '[') | 6025 xfip->xfi_format, xfip->xfi_flen, 6026 xfip->xfi_encoding, xfip->xfi_elen, flags); 6027 else if (ftype == '[') |
5780 xo_anchor_start(xop, xfip); | 6028 xo_anchor_start(xop, xfip, content, clen); |
5781 else if (ftype == ']') | 6029 else if (ftype == ']') |
5782 xo_anchor_stop(xop, xfip); | 6030 xo_anchor_stop(xop, xfip, content, clen); |
5783 else if (ftype == 'C') | 6031 else if (ftype == 'C') |
5784 xo_format_colors(xop, xfip); | 6032 xo_format_colors(xop, xfip, content, clen); |
5785 5786 else if (ftype == 'G') { 5787 /* 5788 * A {G:domain} field; disect the domain name and translate 5789 * the remaining portion of the input string. If the user 5790 * didn't put the {G:} at the start of the format string, then 5791 * assumably they just want us to translate the rest of it. 5792 * Since gettext returns strings in a static buffer, we make 5793 * a copy in new_fmt. 5794 */ | 6033 6034 else if (ftype == 'G') { 6035 /* 6036 * A {G:domain} field; disect the domain name and translate 6037 * the remaining portion of the input string. If the user 6038 * didn't put the {G:} at the start of the format string, then 6039 * assumably they just want us to translate the rest of it. 6040 * Since gettext returns strings in a static buffer, we make 6041 * a copy in new_fmt. 6042 */ |
5795 xo_set_gettext_domain(xop, xfip); | 6043 xo_set_gettext_domain(xop, xfip, content, clen); |
5796 5797 if (!gettext_inuse) { /* Only translate once */ 5798 gettext_inuse = 1; 5799 if (new_fmt) { 5800 xo_free(new_fmt); 5801 new_fmt = NULL; 5802 } 5803 --- 34 unchanged lines hidden (view full) --- 5838 xfip = new_fields; 5839 max_fields = new_max_fields; 5840 } 5841 } 5842 } 5843 } 5844 continue; 5845 | 6044 6045 if (!gettext_inuse) { /* Only translate once */ 6046 gettext_inuse = 1; 6047 if (new_fmt) { 6048 xo_free(new_fmt); 6049 new_fmt = NULL; 6050 } 6051 --- 34 unchanged lines hidden (view full) --- 6086 xfip = new_fields; 6087 max_fields = new_max_fields; 6088 } 6089 } 6090 } 6091 } 6092 continue; 6093 |
5846 } else if (xfip->xfi_clen || xfip->xfi_format) { | 6094 } else if (clen || xfip->xfi_format) { |
5847 5848 const char *class_name = xo_class_name(ftype); 5849 if (class_name) 5850 xo_format_content(xop, class_name, xo_tag_name(ftype), | 6095 6096 const char *class_name = xo_class_name(ftype); 6097 if (class_name) 6098 xo_format_content(xop, class_name, xo_tag_name(ftype), |
5851 xfip->xfi_content, xfip->xfi_clen, | 6099 content, clen, |
5852 xfip->xfi_format, xfip->xfi_flen, flags); 5853 else if (ftype == 'T') | 6100 xfip->xfi_format, xfip->xfi_flen, flags); 6101 else if (ftype == 'T') |
5854 xo_format_title(xop, xfip); | 6102 xo_format_title(xop, xfip, content, clen); |
5855 else if (ftype == 'U') | 6103 else if (ftype == 'U') |
5856 xo_format_units(xop, xfip); | 6104 xo_format_units(xop, xfip, content, clen); |
5857 else 5858 xo_failure(xop, "unknown field type: '%c'", ftype); 5859 } 5860 5861 if (flags & XFF_COLON) 5862 xo_format_content(xop, "decoration", NULL, ":", 1, NULL, 0, 0); 5863 5864 if (flags & XFF_WS) --- 14 unchanged lines hidden (view full) --- 5879 } 5880 5881 XOIF_CLEAR(xop, XOIF_REORDER); 5882 5883 /* If we don't have an anchor, write the text out */ 5884 if (flush && !XOIF_ISSET(xop, XOIF_ANCHOR)) { 5885 if (xo_write(xop) < 0) 5886 rc = -1; /* Report failure */ | 6105 else 6106 xo_failure(xop, "unknown field type: '%c'", ftype); 6107 } 6108 6109 if (flags & XFF_COLON) 6110 xo_format_content(xop, "decoration", NULL, ":", 1, NULL, 0, 0); 6111 6112 if (flags & XFF_WS) --- 14 unchanged lines hidden (view full) --- 6127 } 6128 6129 XOIF_CLEAR(xop, XOIF_REORDER); 6130 6131 /* If we don't have an anchor, write the text out */ 6132 if (flush && !XOIF_ISSET(xop, XOIF_ANCHOR)) { 6133 if (xo_write(xop) < 0) 6134 rc = -1; /* Report failure */ |
5887 else if (xop->xo_flush && xop->xo_flush(xop->xo_opaque) < 0) | 6135 else if (xo_flush_h(xop) < 0) |
5888 rc = -1; 5889 } 5890 5891 if (new_fmt) 5892 xo_free(new_fmt); 5893 5894 /* 5895 * We've carried the gettext domainname inside our handle just for --- 4 unchanged lines hidden (view full) --- 5900 xo_free(xop->xo_gt_domain); 5901 xop->xo_gt_domain = NULL; 5902 } 5903 5904 return (rc < 0) ? rc : (int) xop->xo_columns; 5905} 5906 5907/* | 6136 rc = -1; 6137 } 6138 6139 if (new_fmt) 6140 xo_free(new_fmt); 6141 6142 /* 6143 * We've carried the gettext domainname inside our handle just for --- 4 unchanged lines hidden (view full) --- 6148 xo_free(xop->xo_gt_domain); 6149 xop->xo_gt_domain = NULL; 6150 } 6151 6152 return (rc < 0) ? rc : (int) xop->xo_columns; 6153} 6154 6155/* |
6156 * Parse and emit a set of fields 6157 */ 6158static int 6159xo_do_emit (xo_handle_t *xop, xo_emit_flags_t flags, const char *fmt) 6160{ 6161 xop->xo_columns = 0; /* Always reset it */ 6162 xop->xo_errno = errno; /* Save for "%m" */ 6163 6164 if (fmt == NULL) 6165 return 0; 6166 6167 unsigned max_fields; 6168 xo_field_info_t *fields = NULL; 6169 6170 /* Adjust XOEF_RETAIN based on global flags */ 6171 if (XOF_ISSET(xop, XOF_RETAIN_ALL)) 6172 flags |= XOEF_RETAIN; 6173 if (XOF_ISSET(xop, XOF_RETAIN_NONE)) 6174 flags &= ~XOEF_RETAIN; 6175 6176 /* 6177 * Check for 'retain' flag, telling us to retain the field 6178 * information. If we've already saved it, then we can avoid 6179 * re-parsing the format string. 6180 */ 6181 if (!(flags & XOEF_RETAIN) 6182 || xo_retain_find(fmt, &fields, &max_fields) != 0 6183 || fields == NULL) { 6184 6185 /* Nothing retained; parse the format string */ 6186 max_fields = xo_count_fields(xop, fmt); 6187 fields = alloca(max_fields * sizeof(fields[0])); 6188 bzero(fields, max_fields * sizeof(fields[0])); 6189 6190 if (xo_parse_fields(xop, fields, max_fields, fmt)) 6191 return -1; /* Warning already displayed */ 6192 6193 if (flags & XOEF_RETAIN) { 6194 /* Retain the info */ 6195 xo_retain_add(fmt, fields, max_fields); 6196 } 6197 } 6198 6199 return xo_do_emit_fields(xop, fields, max_fields, fmt); 6200} 6201 6202/* |
|
5908 * Rebuild a format string in a gettext-friendly format. This function 5909 * is exposed to tools can perform this function. See xo(1). 5910 */ 5911char * 5912xo_simplify_format (xo_handle_t *xop, const char *fmt, int with_numbers, 5913 xo_simplify_field_func_t field_cb) 5914{ 5915 xop = xo_default(xop); --- 23 unchanged lines hidden (view full) --- 5939 5940int 5941xo_emit_hv (xo_handle_t *xop, const char *fmt, va_list vap) 5942{ 5943 int rc; 5944 5945 xop = xo_default(xop); 5946 va_copy(xop->xo_vap, vap); | 6203 * Rebuild a format string in a gettext-friendly format. This function 6204 * is exposed to tools can perform this function. See xo(1). 6205 */ 6206char * 6207xo_simplify_format (xo_handle_t *xop, const char *fmt, int with_numbers, 6208 xo_simplify_field_func_t field_cb) 6209{ 6210 xop = xo_default(xop); --- 23 unchanged lines hidden (view full) --- 6234 6235int 6236xo_emit_hv (xo_handle_t *xop, const char *fmt, va_list vap) 6237{ 6238 int rc; 6239 6240 xop = xo_default(xop); 6241 va_copy(xop->xo_vap, vap); |
5947 rc = xo_do_emit(xop, fmt); | 6242 rc = xo_do_emit(xop, 0, fmt); |
5948 va_end(xop->xo_vap); 5949 bzero(&xop->xo_vap, sizeof(xop->xo_vap)); 5950 5951 return rc; 5952} 5953 5954int 5955xo_emit_h (xo_handle_t *xop, const char *fmt, ...) 5956{ 5957 int rc; 5958 5959 xop = xo_default(xop); 5960 va_start(xop->xo_vap, fmt); | 6243 va_end(xop->xo_vap); 6244 bzero(&xop->xo_vap, sizeof(xop->xo_vap)); 6245 6246 return rc; 6247} 6248 6249int 6250xo_emit_h (xo_handle_t *xop, const char *fmt, ...) 6251{ 6252 int rc; 6253 6254 xop = xo_default(xop); 6255 va_start(xop->xo_vap, fmt); |
5961 rc = xo_do_emit(xop, fmt); | 6256 rc = xo_do_emit(xop, 0, fmt); |
5962 va_end(xop->xo_vap); 5963 bzero(&xop->xo_vap, sizeof(xop->xo_vap)); 5964 5965 return rc; 5966} 5967 5968int 5969xo_emit (const char *fmt, ...) 5970{ 5971 xo_handle_t *xop = xo_default(NULL); 5972 int rc; 5973 5974 va_start(xop->xo_vap, fmt); | 6257 va_end(xop->xo_vap); 6258 bzero(&xop->xo_vap, sizeof(xop->xo_vap)); 6259 6260 return rc; 6261} 6262 6263int 6264xo_emit (const char *fmt, ...) 6265{ 6266 xo_handle_t *xop = xo_default(NULL); 6267 int rc; 6268 6269 va_start(xop->xo_vap, fmt); |
5975 rc = xo_do_emit(xop, fmt); | 6270 rc = xo_do_emit(xop, 0, fmt); |
5976 va_end(xop->xo_vap); 5977 bzero(&xop->xo_vap, sizeof(xop->xo_vap)); 5978 5979 return rc; 5980} 5981 5982int | 6271 va_end(xop->xo_vap); 6272 bzero(&xop->xo_vap, sizeof(xop->xo_vap)); 6273 6274 return rc; 6275} 6276 6277int |
6278xo_emit_hvf (xo_handle_t *xop, xo_emit_flags_t flags, 6279 const char *fmt, va_list vap) 6280{ 6281 int rc; 6282 6283 xop = xo_default(xop); 6284 va_copy(xop->xo_vap, vap); 6285 rc = xo_do_emit(xop, flags, fmt); 6286 va_end(xop->xo_vap); 6287 bzero(&xop->xo_vap, sizeof(xop->xo_vap)); 6288 6289 return rc; 6290} 6291 6292int 6293xo_emit_hf (xo_handle_t *xop, xo_emit_flags_t flags, const char *fmt, ...) 6294{ 6295 int rc; 6296 6297 xop = xo_default(xop); 6298 va_start(xop->xo_vap, fmt); 6299 rc = xo_do_emit(xop, flags, fmt); 6300 va_end(xop->xo_vap); 6301 bzero(&xop->xo_vap, sizeof(xop->xo_vap)); 6302 6303 return rc; 6304} 6305 6306int 6307xo_emit_f (xo_emit_flags_t flags, const char *fmt, ...) 6308{ 6309 xo_handle_t *xop = xo_default(NULL); 6310 int rc; 6311 6312 va_start(xop->xo_vap, fmt); 6313 rc = xo_do_emit(xop, flags, fmt); 6314 va_end(xop->xo_vap); 6315 bzero(&xop->xo_vap, sizeof(xop->xo_vap)); 6316 6317 return rc; 6318} 6319 6320/* 6321 * Emit a single field by providing the info information typically provided 6322 * inside the field description (role, modifiers, and formats). This is 6323 * a convenience function to avoid callers using snprintf to build field 6324 * descriptions. 6325 */ 6326int 6327xo_emit_field_hv (xo_handle_t *xop, const char *rolmod, const char *contents, 6328 const char *fmt, const char *efmt, 6329 va_list vap) 6330{ 6331 int rc; 6332 6333 xop = xo_default(xop); 6334 6335 if (rolmod == NULL) 6336 rolmod = "V"; 6337 6338 xo_field_info_t xfi; 6339 6340 bzero(&xfi, sizeof(xfi)); 6341 6342 const char *cp; 6343 cp = xo_parse_roles(xop, rolmod, rolmod, &xfi); 6344 if (cp == NULL) 6345 return -1; 6346 6347 xfi.xfi_start = fmt; 6348 xfi.xfi_content = contents; 6349 xfi.xfi_format = fmt; 6350 xfi.xfi_encoding = efmt; 6351 xfi.xfi_clen = contents ? strlen(contents) : 0; 6352 xfi.xfi_flen = fmt ? strlen(fmt) : 0; 6353 xfi.xfi_elen = efmt ? strlen(efmt) : 0; 6354 6355 /* If we have content, then we have a default format */ 6356 if (contents && fmt == NULL 6357 && xo_role_wants_default_format(xfi.xfi_ftype)) { 6358 xfi.xfi_format = xo_default_format; 6359 xfi.xfi_flen = 2; 6360 } 6361 6362 6363 6364 va_copy(xop->xo_vap, vap); 6365 6366 rc = xo_do_emit_fields(xop, &xfi, 1, fmt ?: contents ?: "field"); 6367 6368 va_end(xop->xo_vap); 6369 6370 return rc; 6371} 6372 6373int 6374xo_emit_field_h (xo_handle_t *xop, const char *rolmod, const char *contents, 6375 const char *fmt, const char *efmt, ...) 6376{ 6377 int rc; 6378 va_list vap; 6379 6380 va_start(vap, efmt); 6381 rc = xo_emit_field_hv(xop, rolmod, contents, fmt, efmt, vap); 6382 va_end(vap); 6383 6384 return rc; 6385} 6386 6387int 6388xo_emit_field (const char *rolmod, const char *contents, 6389 const char *fmt, const char *efmt, ...) 6390{ 6391 int rc; 6392 va_list vap; 6393 6394 va_start(vap, efmt); 6395 rc = xo_emit_field_hv(NULL, rolmod, contents, fmt, efmt, vap); 6396 va_end(vap); 6397 6398 return rc; 6399} 6400 6401int |
|
5983xo_attr_hv (xo_handle_t *xop, const char *name, const char *fmt, va_list vap) 5984{ 5985 const int extra = 5; /* space, equals, quote, quote, and nul */ 5986 xop = xo_default(xop); 5987 5988 int rc = 0; 5989 int nlen = strlen(name); 5990 xo_buffer_t *xbp = &xop->xo_attrs; --- 396 unchanged lines hidden (view full) --- 6387 6388static int 6389xo_open_list_hf (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name) 6390{ 6391 return xo_transition(xop, flags, name, XSS_OPEN_LIST); 6392} 6393 6394int | 6402xo_attr_hv (xo_handle_t *xop, const char *name, const char *fmt, va_list vap) 6403{ 6404 const int extra = 5; /* space, equals, quote, quote, and nul */ 6405 xop = xo_default(xop); 6406 6407 int rc = 0; 6408 int nlen = strlen(name); 6409 xo_buffer_t *xbp = &xop->xo_attrs; --- 396 unchanged lines hidden (view full) --- 6806 6807static int 6808xo_open_list_hf (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name) 6809{ 6810 return xo_transition(xop, flags, name, XSS_OPEN_LIST); 6811} 6812 6813int |
6395xo_open_list_h (xo_handle_t *xop, const char *name UNUSED) | 6814xo_open_list_h (xo_handle_t *xop, const char *name) |
6396{ 6397 return xo_open_list_hf(xop, 0, name); 6398} 6399 6400int 6401xo_open_list (const char *name) 6402{ 6403 return xo_open_list_hf(NULL, 0, name); 6404} 6405 6406int | 6815{ 6816 return xo_open_list_hf(xop, 0, name); 6817} 6818 6819int 6820xo_open_list (const char *name) 6821{ 6822 return xo_open_list_hf(NULL, 0, name); 6823} 6824 6825int |
6407xo_open_list_hd (xo_handle_t *xop, const char *name UNUSED) | 6826xo_open_list_hd (xo_handle_t *xop, const char *name) |
6408{ 6409 return xo_open_list_hf(xop, XOF_DTRT, name); 6410} 6411 6412int 6413xo_open_list_d (const char *name) 6414{ 6415 return xo_open_list_hf(NULL, XOF_DTRT, name); --- 692 unchanged lines hidden (view full) --- 7108 */ 7109 break; 7110 7111 default: 7112 xo_failure(xop, "unknown transition: (%u -> %u)", 7113 xsp->xs_state, new_state); 7114 } 7115 | 6827{ 6828 return xo_open_list_hf(xop, XOF_DTRT, name); 6829} 6830 6831int 6832xo_open_list_d (const char *name) 6833{ 6834 return xo_open_list_hf(NULL, XOF_DTRT, name); --- 692 unchanged lines hidden (view full) --- 7527 */ 7528 break; 7529 7530 default: 7531 xo_failure(xop, "unknown transition: (%u -> %u)", 7532 xsp->xs_state, new_state); 7533 } 7534 |
7535 /* Handle the flush flag */ 7536 if (rc >= 0 && XOF_ISSET(xop, XOF_FLUSH)) 7537 if (xo_flush_h(xop)) 7538 rc = -1; 7539 |
|
7116 return rc; 7117 7118 marker_prevents_close: 7119 xo_failure(xop, "marker '%s' prevents transition from %s to %s", 7120 xop->xo_stack[xop->xo_depth].xs_name, 7121 xo_state_name(old_state), xo_state_name(new_state)); 7122 return -1; 7123} --- 50 unchanged lines hidden (view full) --- 7174{ 7175 xo_realloc = realloc_func; 7176 xo_free = free_func; 7177} 7178 7179int 7180xo_flush_h (xo_handle_t *xop) 7181{ | 7540 return rc; 7541 7542 marker_prevents_close: 7543 xo_failure(xop, "marker '%s' prevents transition from %s to %s", 7544 xop->xo_stack[xop->xo_depth].xs_name, 7545 xo_state_name(old_state), xo_state_name(new_state)); 7546 return -1; 7547} --- 50 unchanged lines hidden (view full) --- 7598{ 7599 xo_realloc = realloc_func; 7600 xo_free = free_func; 7601} 7602 7603int 7604xo_flush_h (xo_handle_t *xop) 7605{ |
7182 static char div_close[] = "</div>"; | |
7183 int rc; 7184 7185 xop = xo_default(xop); 7186 7187 switch (xo_style(xop)) { | 7606 int rc; 7607 7608 xop = xo_default(xop); 7609 7610 switch (xo_style(xop)) { |
7188 case XO_STYLE_HTML: 7189 if (XOIF_ISSET(xop, XOIF_DIV_OPEN)) { 7190 XOIF_CLEAR(xop, XOIF_DIV_OPEN); 7191 xo_data_append(xop, div_close, sizeof(div_close) - 1); 7192 7193 if (XOF_ISSET(xop, XOF_PRETTY)) 7194 xo_data_append(xop, "\n", 1); 7195 } 7196 break; 7197 | |
7198 case XO_STYLE_ENCODER: 7199 xo_encoder_handle(xop, XO_OP_FLUSH, NULL, NULL); 7200 } 7201 7202 rc = xo_write(xop); 7203 if (rc >= 0 && xop->xo_flush) 7204 if (xop->xo_flush(xop->xo_opaque) < 0) 7205 return -1; --- 224 unchanged lines hidden (view full) --- 7430 */ 7431void 7432xo_set_program (const char *name) 7433{ 7434 xo_program = name; 7435} 7436 7437void | 7611 case XO_STYLE_ENCODER: 7612 xo_encoder_handle(xop, XO_OP_FLUSH, NULL, NULL); 7613 } 7614 7615 rc = xo_write(xop); 7616 if (rc >= 0 && xop->xo_flush) 7617 if (xop->xo_flush(xop->xo_opaque) < 0) 7618 return -1; --- 224 unchanged lines hidden (view full) --- 7843 */ 7844void 7845xo_set_program (const char *name) 7846{ 7847 xo_program = name; 7848} 7849 7850void |
7438xo_set_version_h (xo_handle_t *xop, const char *version UNUSED) | 7851xo_set_version_h (xo_handle_t *xop, const char *version) |
7439{ 7440 xop = xo_default(xop); 7441 7442 if (version == NULL || strchr(version, '"') != NULL) 7443 return; 7444 7445 if (!xo_style_is_encoding(xop)) 7446 return; --- 213 unchanged lines hidden --- | 7852{ 7853 xop = xo_default(xop); 7854 7855 if (version == NULL || strchr(version, '"') != NULL) 7856 return; 7857 7858 if (!xo_style_is_encoding(xop)) 7859 return; --- 213 unchanged lines hidden --- |