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