1/* 2 * Copyright (c) 2014-2018, 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 9 */ 10 11/** 12 * libxo provides a means of generating text, XML, JSON, and HTML output 13 * using a single set of function calls, maximizing the value of output 14 * while minimizing the cost/impact on the code. 15 * 16 * Full documentation is available in ./doc/libxo.txt or online at: 17 * http://juniper.github.io/libxo/libxo-manual.html 18 */ 19 20#ifndef INCLUDE_XO_H 21#define INCLUDE_XO_H 22 23#include <stdio.h> 24#include <sys/types.h> 25#include <stdarg.h> 26#include <limits.h> 27#include <stdlib.h> 28#include <errno.h> 29 30#ifdef __dead2 31#define NORETURN __dead2 32#else 33#define NORETURN 34#endif /* __dead2 */ 35 36/* 37 * Normally we'd use the HAVE_PRINTFLIKE define triggered by the 38 * --enable-printflike option to configure, but we don't install 39 * our internal "xoconfig.h", and I'd rather not. Taking the 40 * coward's path, we'll turn it on inside a #if that allows 41 * others to turn it off where needed. Not ideal, but functional. 42 */ 43#if !defined(NO_PRINTFLIKE) 44#if defined(__linux) && !defined(__printflike) 45#define __printflike(_x, _y) __attribute__((__format__ (__printf__, _x, _y))) 46#endif 47#define PRINTFLIKE(_x, _y) __printflike(_x, _y) 48#else 49#define PRINTFLIKE(_x, _y) 50#endif /* NO_PRINTFLIKE */ 51 52/** Formatting types */ 53typedef unsigned short xo_style_t; 54#define XO_STYLE_TEXT 0 /** Generate text output */ 55#define XO_STYLE_XML 1 /** Generate XML output */ 56#define XO_STYLE_JSON 2 /** Generate JSON output */ 57#define XO_STYLE_HTML 3 /** Generate HTML output */ 58#define XO_STYLE_SDPARAMS 4 /* Generate syslog structured data params */ 59#define XO_STYLE_ENCODER 5 /* Generate calls to external encoder */ 60 61/** Flags for libxo */ 62typedef unsigned long long xo_xof_flags_t; 63#define XOF_BIT(_n) ((xo_xof_flags_t) 1 << (_n)) 64#define XOF_CLOSE_FP XOF_BIT(0) /** Close file pointer on xo_close() */ 65#define XOF_PRETTY XOF_BIT(1) /** Make 'pretty printed' output */ 66#define XOF_LOG_SYSLOG XOF_BIT(2) /** Log (on stderr) our syslog content */ 67#define XOF_RESV3 XOF_BIT(3) /* Unused */ 68 69#define XOF_WARN XOF_BIT(4) /** Generate warnings for broken calls */ 70#define XOF_XPATH XOF_BIT(5) /** Emit XPath attributes in HTML */ 71#define XOF_INFO XOF_BIT(6) /** Emit additional info fields (HTML) */ 72#define XOF_WARN_XML XOF_BIT(7) /** Emit warnings in XML (on stdout) */ 73 74#define XOF_NO_ENV XOF_BIT(8) /** Don't look at LIBXO_OPTIONS env var */ 75#define XOF_NO_VA_ARG XOF_BIT(9) /** Don't advance va_list w/ va_arg() */ 76#define XOF_DTRT XOF_BIT(10) /** Enable "do the right thing" mode */ 77#define XOF_KEYS XOF_BIT(11) /** Flag 'key' fields for xml and json */ 78 79#define XOF_IGNORE_CLOSE XOF_BIT(12) /** Ignore errors on close tags */ 80#define XOF_NOT_FIRST XOF_BIT(13) /* Not the first item (JSON) */ 81#define XOF_NO_LOCALE XOF_BIT(14) /** Don't bother with locale */ 82#define XOF_RESV15 XOF_BIT(15) /* Unused */ 83 84#define XOF_NO_TOP XOF_BIT(16) /** Don't emit the top braces in JSON */ 85#define XOF_RESV17 XOF_BIT(17) /* Unused */ 86#define XOF_UNITS XOF_BIT(18) /** Encode units in XML */ 87#define XOF_RESV19 XOF_BIT(19) /* Unused */ 88 89#define XOF_UNDERSCORES XOF_BIT(20) /** Replace dashes with underscores (JSON)*/ 90#define XOF_COLUMNS XOF_BIT(21) /** xo_emit should return a column count */ 91#define XOF_FLUSH XOF_BIT(22) /** Flush after each xo_emit call */ 92#define XOF_FLUSH_LINE XOF_BIT(23) /** Flush after each newline */ 93 94#define XOF_NO_CLOSE XOF_BIT(24) /** xo_finish won't close open elements */ 95#define XOF_COLOR_ALLOWED XOF_BIT(25) /** Allow color/effects to be enabled */ 96#define XOF_COLOR XOF_BIT(26) /** Enable color and effects */ 97#define XOF_NO_HUMANIZE XOF_BIT(27) /** Block the {h:} modifier */ 98 99#define XOF_LOG_GETTEXT XOF_BIT(28) /** Log (stderr) gettext lookup strings */ 100#define XOF_UTF8 XOF_BIT(29) /** Force text output to be UTF8 */ 101#define XOF_RETAIN_ALL XOF_BIT(30) /** Force use of XOEF_RETAIN */ 102#define XOF_RETAIN_NONE XOF_BIT(31) /** Prevent use of XOEF_RETAIN */ 103 104#define XOF_COLOR_MAP XOF_BIT(32) /** Color map has been initialized */ 105#define XOF_CONTINUATION XOF_BIT(33) /** Continuation of previous line */ 106 107typedef unsigned xo_emit_flags_t; /* Flags to xo_emit() and friends */ 108#define XOEF_RETAIN (1<<0) /* Retain parsed formatting information */ 109 110/* 111 * The xo_info_t structure provides a mapping between names and 112 * additional data emitted via HTML. 113 */ 114typedef struct xo_info_s { 115 const char *xi_name; /* Name of the element */ 116 const char *xi_type; /* Type of field */ 117 const char *xi_help; /* Description of field */ 118} xo_info_t; 119 120#define XO_INFO_NULL NULL, NULL, NULL /* Use '{ XO_INFO_NULL }' to end lists */ 121 122struct xo_handle_s; /* Opaque structure forward */ 123typedef struct xo_handle_s xo_handle_t; /* Handle for XO output */ 124 125/* 126 * Early versions of the API used "int" instead of "size_t" for buffer 127 * sizes. We want to fix this but allow for backwards compatibility 128 * where needed. 129 */ 130#ifdef XO_USE_INT_RETURN_CODES 131typedef int xo_ssize_t; /* Buffer size */ 132#else /* XO_USE_INT_RETURN_CODES */ 133typedef ssize_t xo_ssize_t; /* Buffer size */ 134#endif /* XO_USE_INT_RETURN_CODES */ 135 136typedef xo_ssize_t (*xo_write_func_t)(void *, const char *); 137typedef void (*xo_close_func_t)(void *); 138typedef int (*xo_flush_func_t)(void *); 139typedef void *(*xo_realloc_func_t)(void *, size_t); 140typedef void (*xo_free_func_t)(void *); 141 142/* 143 * The formatter function mirrors "vsnprintf", with an additional argument 144 * of the xo handle. The caller should return the number of bytes _needed_ 145 * to fit the data, even if this exceeds 'len'. 146 */ 147typedef xo_ssize_t (*xo_formatter_t)(xo_handle_t *, char *, xo_ssize_t, 148 const char *, va_list); 149typedef void (*xo_checkpointer_t)(xo_handle_t *, va_list, int); 150 151xo_handle_t * 152xo_create (xo_style_t style, xo_xof_flags_t flags); 153 154xo_handle_t * 155xo_create_to_file (FILE *fp, xo_style_t style, xo_xof_flags_t flags); 156 157void 158xo_destroy (xo_handle_t *xop); 159 160void 161xo_set_writer (xo_handle_t *xop, void *opaque, xo_write_func_t write_func, 162 xo_close_func_t close_func, xo_flush_func_t flush_func); 163 164void 165xo_set_allocator (xo_realloc_func_t realloc_func, xo_free_func_t free_func); 166 167void 168xo_set_style (xo_handle_t *xop, xo_style_t style); 169 170xo_style_t 171xo_get_style (xo_handle_t *xop); 172 173int 174xo_set_style_name (xo_handle_t *xop, const char *style); 175 176int 177xo_set_options (xo_handle_t *xop, const char *input); 178 179xo_xof_flags_t 180xo_get_flags (xo_handle_t *xop); 181 182void 183xo_set_flags (xo_handle_t *xop, xo_xof_flags_t flags); 184 185void 186xo_clear_flags (xo_handle_t *xop, xo_xof_flags_t flags); 187 188int 189xo_set_file_h (xo_handle_t *xop, FILE *fp); 190 191int 192xo_set_file (FILE *fp); 193 194void 195xo_set_info (xo_handle_t *xop, xo_info_t *infop, int count); 196 197void 198xo_set_formatter (xo_handle_t *xop, xo_formatter_t func, xo_checkpointer_t); 199 200void 201xo_set_depth (xo_handle_t *xop, int depth); 202 203xo_ssize_t 204xo_emit_hv (xo_handle_t *xop, const char *fmt, va_list vap); 205 206xo_ssize_t 207xo_emit_h (xo_handle_t *xop, const char *fmt, ...); 208 209xo_ssize_t 210xo_emit (const char *fmt, ...); 211 212xo_ssize_t 213xo_emit_hvf (xo_handle_t *xop, xo_emit_flags_t flags, 214 const char *fmt, va_list vap); 215 216xo_ssize_t 217xo_emit_hf (xo_handle_t *xop, xo_emit_flags_t flags, const char *fmt, ...); 218 219xo_ssize_t 220xo_emit_f (xo_emit_flags_t flags, const char *fmt, ...); 221 222PRINTFLIKE(2, 0) 223static inline xo_ssize_t 224xo_emit_hvp (xo_handle_t *xop, const char *fmt, va_list vap) 225{ 226 return xo_emit_hv(xop, fmt, vap); 227} 228 229PRINTFLIKE(2, 3) 230static inline xo_ssize_t 231xo_emit_hp (xo_handle_t *xop, const char *fmt, ...) 232{ 233 va_list vap; 234 va_start(vap, fmt); 235 xo_ssize_t rc = xo_emit_hv(xop, fmt, vap); 236 va_end(vap); 237 return rc; 238} 239 240PRINTFLIKE(1, 2) 241static inline xo_ssize_t 242xo_emit_p (const char *fmt, ...) 243{ 244 va_list vap; 245 va_start(vap, fmt); 246 xo_ssize_t rc = xo_emit_hv(NULL, fmt, vap); 247 va_end(vap); 248 return rc; 249} 250 251PRINTFLIKE(3, 0) 252static inline xo_ssize_t 253xo_emit_hvfp (xo_handle_t *xop, xo_emit_flags_t flags, 254 const char *fmt, va_list vap) 255{ 256 return xo_emit_hvf(xop, flags, fmt, vap); 257} 258 259PRINTFLIKE(3, 4) 260static inline xo_ssize_t 261xo_emit_hfp (xo_handle_t *xop, xo_emit_flags_t flags, const char *fmt, ...) 262{ 263 va_list vap; 264 va_start(vap, fmt); 265 xo_ssize_t rc = xo_emit_hvf(xop, flags, fmt, vap); 266 va_end(vap); 267 return rc; 268} 269 270PRINTFLIKE(2, 3) 271static inline xo_ssize_t 272xo_emit_fp (xo_emit_flags_t flags, const char *fmt, ...) 273{ 274 va_list vap; 275 va_start(vap, fmt); 276 xo_ssize_t rc = xo_emit_hvf(NULL, flags, fmt, vap); 277 va_end(vap); 278 return rc; 279} 280 281xo_ssize_t 282xo_open_container_hf (xo_handle_t *xop, xo_xof_flags_t flags, const char *name); 283 284xo_ssize_t 285xo_open_container_h (xo_handle_t *xop, const char *name); 286 287xo_ssize_t 288xo_open_container (const char *name); 289 290xo_ssize_t 291xo_open_container_hd (xo_handle_t *xop, const char *name); 292 293xo_ssize_t 294xo_open_container_d (const char *name); 295 296xo_ssize_t 297xo_close_container_h (xo_handle_t *xop, const char *name); 298 299xo_ssize_t 300xo_close_container (const char *name); 301 302xo_ssize_t 303xo_close_container_hd (xo_handle_t *xop); 304 305xo_ssize_t 306xo_close_container_d (void); 307 308xo_ssize_t 309xo_open_list_hf (xo_handle_t *xop, xo_xof_flags_t flags, const char *name); 310 311xo_ssize_t 312xo_open_list_h (xo_handle_t *xop, const char *name); 313 314xo_ssize_t 315xo_open_list (const char *name); 316 317xo_ssize_t 318xo_open_list_hd (xo_handle_t *xop, const char *name); 319 320xo_ssize_t 321xo_open_list_d (const char *name); 322 323xo_ssize_t 324xo_close_list_h (xo_handle_t *xop, const char *name); 325 326xo_ssize_t 327xo_close_list (const char *name); 328 329xo_ssize_t 330xo_close_list_hd (xo_handle_t *xop); 331 332xo_ssize_t 333xo_close_list_d (void); 334 335xo_ssize_t 336xo_open_instance_hf (xo_handle_t *xop, xo_xof_flags_t flags, const char *name); 337 338xo_ssize_t 339xo_open_instance_h (xo_handle_t *xop, const char *name); 340 341xo_ssize_t 342xo_open_instance (const char *name); 343 344xo_ssize_t 345xo_open_instance_hd (xo_handle_t *xop, const char *name); 346 347xo_ssize_t 348xo_open_instance_d (const char *name); 349 350xo_ssize_t 351xo_close_instance_h (xo_handle_t *xop, const char *name); 352 353xo_ssize_t 354xo_close_instance (const char *name); 355 356xo_ssize_t 357xo_close_instance_hd (xo_handle_t *xop); 358 359xo_ssize_t 360xo_close_instance_d (void); 361 362xo_ssize_t 363xo_open_marker_h (xo_handle_t *xop, const char *name); 364 365xo_ssize_t 366xo_open_marker (const char *name); 367 368xo_ssize_t 369xo_close_marker_h (xo_handle_t *xop, const char *name); 370 371xo_ssize_t 372xo_close_marker (const char *name); 373 374xo_ssize_t 375xo_attr_h (xo_handle_t *xop, const char *name, const char *fmt, ...); 376 377xo_ssize_t 378xo_attr_hv (xo_handle_t *xop, const char *name, const char *fmt, va_list vap); 379 380xo_ssize_t 381xo_attr (const char *name, const char *fmt, ...); 382 383void 384xo_error_hv (xo_handle_t *xop, const char *fmt, va_list vap); 385 386void 387xo_error_h (xo_handle_t *xop, const char *fmt, ...); 388 389void 390xo_error (const char *fmt, ...); 391 392void 393xo_errorn_hv (xo_handle_t *xop, int need_newline, const char *fmt, va_list vap); 394 395void 396xo_errorn_h (xo_handle_t *xop, const char *fmt, ...); 397 398void 399xo_errorn (const char *fmt, ...); 400 401xo_ssize_t 402xo_flush_h (xo_handle_t *xop); 403 404xo_ssize_t 405xo_flush (void); 406 407xo_ssize_t 408xo_finish_h (xo_handle_t *xop); 409 410xo_ssize_t 411xo_finish (void); 412 413void 414xo_finish_atexit (void); 415 416void 417xo_set_leading_xpath (xo_handle_t *xop, const char *path); 418 419void 420xo_warn_hc (xo_handle_t *xop, int code, const char *fmt, ...) PRINTFLIKE(3, 4); 421 422void 423xo_warn_c (int code, const char *fmt, ...) PRINTFLIKE(2, 3); 424 425void 426xo_warn (const char *fmt, ...) PRINTFLIKE(1, 2); 427 428void 429xo_warnx (const char *fmt, ...) PRINTFLIKE(1, 2); 430 431void 432xo_err (int eval, const char *fmt, ...) NORETURN PRINTFLIKE(2, 3); 433 434void 435xo_errx (int eval, const char *fmt, ...) NORETURN PRINTFLIKE(2, 3); 436 437void 438xo_errc (int eval, int code, const char *fmt, ...) NORETURN PRINTFLIKE(3, 4); 439 440void 441xo_message_hcv (xo_handle_t *xop, int code, const char *fmt, va_list vap) PRINTFLIKE(3, 0); 442 443void 444xo_message_hc (xo_handle_t *xop, int code, const char *fmt, ...) PRINTFLIKE(3, 4); 445 446void 447xo_message_c (int code, const char *fmt, ...) PRINTFLIKE(2, 3); 448 449void 450xo_message_e (const char *fmt, ...) PRINTFLIKE(1, 2); 451 452void 453xo_message (const char *fmt, ...) PRINTFLIKE(1, 2); 454 455void 456xo_emit_warn_hcv (xo_handle_t *xop, int as_warning, int code, 457 const char *fmt, va_list vap); 458 459void 460xo_emit_warn_hc (xo_handle_t *xop, int code, const char *fmt, ...); 461 462void 463xo_emit_warn_c (int code, const char *fmt, ...); 464 465void 466xo_emit_warn (const char *fmt, ...); 467 468void 469xo_emit_warnx (const char *fmt, ...); 470 471void 472xo_emit_err (int eval, const char *fmt, ...) NORETURN; 473 474void 475xo_emit_errx (int eval, const char *fmt, ...) NORETURN; 476 477void 478xo_emit_errc (int eval, int code, const char *fmt, ...) NORETURN; 479 480PRINTFLIKE(4, 0) 481static inline void 482xo_emit_warn_hcvp (xo_handle_t *xop, int as_warning, int code, 483 const char *fmt, va_list vap) 484{ 485 xo_emit_warn_hcv(xop, as_warning, code, fmt, vap); 486} 487 488PRINTFLIKE(3, 4) 489static inline void 490xo_emit_warn_hcp (xo_handle_t *xop, int code, const char *fmt, ...) 491{ 492 va_list vap; 493 va_start(vap, fmt); 494 xo_emit_warn_hcv(xop, 1, code, fmt, vap); 495 va_end(vap); 496} 497 498PRINTFLIKE(2, 3) 499static inline void 500xo_emit_warn_cp (int code, const char *fmt, ...) 501{ 502 va_list vap; 503 va_start(vap, fmt); 504 xo_emit_warn_hcv(NULL, 1, code, fmt, vap); 505 va_end(vap); 506} 507 508PRINTFLIKE(1, 2) 509static inline void 510xo_emit_warn_p (const char *fmt, ...) 511{ 512 int code = errno; 513 va_list vap; 514 va_start(vap, fmt); 515 xo_emit_warn_hcv(NULL, 1, code, fmt, vap); 516 va_end(vap); 517} 518 519PRINTFLIKE(1, 2) 520static inline void 521xo_emit_warnx_p (const char *fmt, ...) 522{ 523 va_list vap; 524 va_start(vap, fmt); 525 xo_emit_warn_hcv(NULL, 1, -1, fmt, vap); 526 va_end(vap); 527} 528 529NORETURN PRINTFLIKE(2, 3) 530static inline void 531xo_emit_err_p (int eval, const char *fmt, ...) 532{ 533 int code = errno; 534 va_list vap; 535 va_start(vap, fmt); 536 xo_emit_warn_hcv(NULL, 0, code, fmt, vap); 537 va_end(vap); 538 539 exit(eval); 540} 541 542PRINTFLIKE(2, 3) 543static inline void 544xo_emit_errx_p (int eval, const char *fmt, ...) 545{ 546 va_list vap; 547 va_start(vap, fmt); 548 xo_emit_warn_hcv(NULL, 0, -1, fmt, vap); 549 va_end(vap); 550 exit(eval); 551} 552 553PRINTFLIKE(3, 4) 554static inline void 555xo_emit_errc_p (int eval, int code, const char *fmt, ...) 556{ 557 va_list vap; 558 va_start(vap, fmt); 559 xo_emit_warn_hcv(NULL, 0, code, fmt, vap); 560 va_end(vap); 561 exit(eval); 562} 563 564void 565xo_emit_err_v (int eval, int code, const char *fmt, va_list vap) NORETURN PRINTFLIKE(3, 0); 566 567void 568xo_no_setlocale (void); 569 570/** 571 * @brief Lift libxo-specific arguments from a set of arguments 572 * 573 * libxo-enable programs typically use command line options to enable 574 * all the nifty-cool libxo features. xo_parse_args() makes this simple 575 * by pre-processing the command line arguments given to main(), handling 576 * and removing the libxo-specific ones, meaning anything starting with 577 * "--libxo". A full description of these arguments is in the base 578 * documentation. 579 * @param[in] argc Number of arguments (ala #main()) 580 * @param[in] argc Array of argument strings (ala #main()) 581 * @return New number of arguments, or -1 for failure. 582 */ 583int 584xo_parse_args (int argc, char **argv); 585 586/** 587 * This is the "magic" number returned by libxo-supporting commands 588 * when passed the equally magic "--libxo-check" option. If you 589 * return this, we can (unsafely) assume that since you know the magic 590 * handshake, you'll happily handle future --libxo options and not do 591 * something violent like reboot the box or create another hole in the 592 * ozone layer. 593 */ 594#define XO_HAS_LIBXO 121 595 596/** 597 * externs for libxo's version number strings 598 */ 599extern const char xo_version[]; /** Base version triple string */ 600extern const char xo_version_extra[]; /** Extra version magic content */ 601 602/** 603 * @brief Dump the internal stack of a libxo handle. 604 * 605 * This diagnostic function is something I will ask you to call from 606 * your program when you write to tell me libxo has gone bat-stink 607 * crazy and has discarded your list or container or content. Output 608 * content will be what we lovingly call "developer entertainment". 609 * @param[in] xop A valid libxo handle, or NULL for the default handle 610 */ 611void 612xo_dump_stack (xo_handle_t *xop); 613 614/** 615 * @brief Recode the name of the program, suitable for error output. 616 * 617 * libxo will record the given name for use while generating error 618 * messages. The contents are not copied, so the value must continue 619 * to point to a valid memory location. This allows the caller to change 620 * the value, but requires the caller to manage the memory. Typically 621 * this is called with argv[0] from main(). 622 * @param[in] name The name of the current application program 623 */ 624void 625xo_set_program (const char *name); 626 627/** 628 * @brief Add a version string to the output, where possible. 629 * 630 * Adds a version number to the output, suitable for tracking 631 * changes in the content. This is only important for the "encoding" 632 * format styles (XML and JSON) and allows a user of the data to 633 * discern which version of the data model is in use. 634 * @param[in] version The version number, encoded as a string 635 */ 636void 637xo_set_version (const char *version); 638 639/** 640 * #xo_set_version with a handle. 641 * @param[in] xop A valid libxo handle, or NULL for the default handle 642 * @param[in] version The version number, encoded as a string 643 */ 644void 645xo_set_version_h (xo_handle_t *xop, const char *version); 646 647void 648xo_open_log (const char *ident, int logopt, int facility); 649 650void 651xo_close_log (void); 652 653int 654xo_set_logmask (int maskpri); 655 656void 657xo_set_unit_test_mode (int value); 658 659void 660xo_syslog (int priority, const char *name, const char *message, ...); 661 662void 663xo_vsyslog (int priority, const char *name, const char *message, va_list args); 664 665typedef void (*xo_syslog_open_t)(void); 666typedef void (*xo_syslog_send_t)(const char *full_msg, 667 const char *v0_hdr, const char *text_only); 668typedef void (*xo_syslog_close_t)(void); 669 670void 671xo_set_syslog_handler (xo_syslog_open_t open_func, xo_syslog_send_t send_func, 672 xo_syslog_close_t close_func); 673 674void 675xo_set_syslog_enterprise_id (unsigned short eid); 676 677typedef void (*xo_simplify_field_func_t)(const char *, unsigned, int); 678 679char * 680xo_simplify_format (xo_handle_t *xop, const char *fmt, int with_numbers, 681 xo_simplify_field_func_t field_cb); 682 683xo_ssize_t 684xo_emit_field_hv (xo_handle_t *xop, const char *rolmod, const char *contents, 685 const char *fmt, const char *efmt, 686 va_list vap); 687 688xo_ssize_t 689xo_emit_field_h (xo_handle_t *xop, const char *rolmod, const char *contents, 690 const char *fmt, const char *efmt, ...); 691 692xo_ssize_t 693xo_emit_field (const char *rolmod, const char *contents, 694 const char *fmt, const char *efmt, ...); 695 696void 697xo_retain_clear_all (void); 698 699void 700xo_retain_clear (const char *fmt); 701 702#endif /* INCLUDE_XO_H */ 703