/*- * Copyright (c) 2005 Poul-Henning Kamp * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD: src/include/printf.h,v 1.5 2011/03/06 17:45:37 pjd Exp $ */ #ifndef _PRINTF_H_ #define _PRINTF_H_ /**************************************************************************** * This is the header file for extensible printf, a set of APIs that allow * adding/modifying conversion specifier(s) for stdio formatted printing. * It is based on the GLIBC API documented in: * * http://www.gnu.org/software/libc/manual/html_node/Customizing-Printf.html * * Because that API affects printf behavior process-wide and so is unsafe, * we adapt a modified form, based on the concept of printf domains in which * changes to conversion specifiers can be made independent of one another * and which don't affect the normal printf behavior. In addition, there * is now a set of printf variants that take a printf domain as an argument. * * See xprintf(5) for more details. ****************************************************************************/ #include #include #include #include #ifdef __GNUC__ #define __XPRINTF_ATTR(x) __attribute__(x) #else /* !__GNUC__ */ #define __XPRINTF_ATTR(x) /* nothing */ #endif /* !__GNUC__ */ /* * The API defined by GLIBC allows a renderer to take multiple arguments * This is obviously usable for things like (ptr+len) pairs etc. * The current limit is to deal with up to __PRINTFMAXARG arguments (any * above this limit are ignored). */ #define __PRINTFMAXARG 2 struct printf_info { /* Mac OS X extensions */ void *context; /* User context pointer */ locale_t loc; /* Extended locale */ wchar_t vsep; /* Vector separator char */ /* one of ,:;_ flag or X by default */ /* GLIBC compatible */ int prec; /* precision */ int width; /* Width */ wchar_t spec; /* Format letter */ wchar_t pad; /* Padding char */ /* 0 if 0 flag set, otherwise space */ /* FreeBSD extensions */ wchar_t signchar; /* Sign char */ /* GLIBC compatible flags */ unsigned is_long_double :1; /* L or ll flag */ unsigned is_char :1; /* hh flag */ unsigned is_short :1; /* h flag */ unsigned is_long :1; /* l flag */ unsigned alt :1; /* # flag */ unsigned space :1; /* Space flag */ unsigned left :1; /* - flag */ unsigned showsign :1; /* + flag */ unsigned group :1; /* ' flag */ unsigned extra :1; /* For special use (currently unused) */ unsigned wide :1; /* Nonzero for wide character streams (currently unused) */ /* FreeBSD flags */ unsigned is_quad :1; /* q flag */ unsigned is_intmax :1; /* j flag */ unsigned is_ptrdiff :1; /* t flag */ unsigned is_size :1; /* z flag */ /* Mac OS X flags */ unsigned is_vec :1; /* v flag */ /* private */ int sofar; unsigned get_width; unsigned get_prec; const char *begin; const char *end; void *arg[__PRINTFMAXARG]; }; enum { PA_INT = (1 << 0), /* int */ PA_CHAR = (1 << 1), /* int, cast to char */ PA_WCHAR = (1 << 2), /* wide char */ PA_STRING = (1 << 3), /* const char * (with '\0') */ PA_WSTRING = (1 << 4), /* const wchar_t * */ PA_POINTER = (1 << 5), /* void * */ PA_FLOAT = (1 << 6), /* float (Defined but unused; best to avoid.) */ PA_DOUBLE = (1 << 7), /* double */ PA_VECTOR = (1 << 8), /* vector */ }; #define PA_FLAG_MASK 0xff0000 #define PA_FLAG_LONG_LONG (1 << 16) #define PA_FLAG_LONG (1 << 17) #define PA_FLAG_SHORT (1 << 18) #define PA_FLAG_PTR (1 << 19) #define PA_FLAG_QUAD (1 << 20) #define PA_FLAG_INTMAX (1 << 21) #define PA_FLAG_SIZE (1 << 22) #define PA_FLAG_PTRDIFF (1 << 23) #define PA_FLAG_LONG_DOUBLE PA_FLAG_LONG_LONG /************************ Basic Extensible Printf APIs ************************/ typedef int printf_arginfo_function(const struct printf_info *__info, size_t __n, int *__argtypes); typedef int printf_function(FILE *__stream, const struct printf_info *__info, const void *const *__args); /* * We don't support the GLIBC register_printf_function() or FreeBSD * register_printf_render_std(), because they affect printf globally * and are unsafe. */ /*************** Extensible Printf Domains APIs ****************/ struct _printf_domain; /* forward reference */ typedef struct _printf_domain *printf_domain_t; __BEGIN_DECLS printf_domain_t copy_printf_domain(printf_domain_t __domain) __XPRINTF_ATTR((__nonnull__(1))) __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0); void free_printf_domain(printf_domain_t __domain) __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0); printf_domain_t new_printf_domain(void) __XPRINTF_ATTR((__malloc__)) __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0); int register_printf_domain_function(printf_domain_t __domain, int __spec, printf_function *__render, printf_arginfo_function *__arginfo, void *__context) __XPRINTF_ATTR((__nonnull__(1))) __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0); int register_printf_domain_render_std(printf_domain_t __domain, const char *__specs) __XPRINTF_ATTR((__nonnull__(1))) __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0); /**** All-in-one extensible printf variants ****/ int asxprintf(char ** __restrict __ret, printf_domain_t __restrict __domain, locale_t __restrict __loc, const char * __restrict __format, ...) __XPRINTF_ATTR((__nonnull__(1, 2, 4))) __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0); int dxprintf(int __fd, printf_domain_t __restrict __domain, locale_t __restrict __loc, const char * __restrict __format, ...) __XPRINTF_ATTR((__nonnull__(2, 4))) __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0); int fxprintf(FILE * __restrict __stream, printf_domain_t __restrict __domain, locale_t __restrict __loc, const char * __restrict __format, ...) __XPRINTF_ATTR((__nonnull__(1, 2, 4))) __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0); int sxprintf(char * __restrict __str, size_t __size, printf_domain_t __restrict __domain, locale_t __restrict __loc, const char * __restrict __format, ...) __XPRINTF_ATTR((__nonnull__(1, 3, 5))) __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0); int xprintf(printf_domain_t __restrict __domain, locale_t __restrict __loc, const char * __restrict __format, ...) __XPRINTF_ATTR((__nonnull__(1, 3))) __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0); int vasxprintf(char ** __restrict __ret, printf_domain_t __restrict __domain, locale_t __restrict __loc, const char * __restrict __format, va_list __ap) __XPRINTF_ATTR((__nonnull__(1, 2, 4))) __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0); int vdxprintf(int __fd, printf_domain_t __restrict __domain, locale_t __restrict __loc, const char * __restrict __format, va_list __ap) __XPRINTF_ATTR((__nonnull__(2, 4))) __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0); int vfxprintf(FILE * __restrict __stream, printf_domain_t __restrict __domain, locale_t __restrict __loc, const char * __restrict __format, va_list __ap) __XPRINTF_ATTR((__nonnull__(1, 2, 4))) __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0); int vsxprintf(char * __restrict __str, size_t __size, printf_domain_t __restrict __domain, locale_t __restrict __loc, const char * __restrict __format, va_list __ap) __XPRINTF_ATTR((__nonnull__(1, 3, 5))) __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0); int vxprintf(printf_domain_t __restrict __domain, locale_t __restrict __loc, const char * __restrict __format, va_list __ap) __XPRINTF_ATTR((__nonnull__(1, 3))) __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0); __END_DECLS /******** Extensible Printf Compilation/Execution APIs *********/ struct _printf_compiled; /* forward reference */ typedef struct _printf_compiled *printf_comp_t; __BEGIN_DECLS void free_printf_comp(printf_comp_t __pc) __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0); printf_comp_t new_printf_comp(printf_domain_t __restrict __domain, locale_t __restrict __loc, const char * __restrict __fmt) __XPRINTF_ATTR((__nonnull__(1, 3))) __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0); /**** Extensible printf execution ****/ int asxprintf_exec(char ** __restrict __ret, printf_comp_t __restrict __pc, ...) __XPRINTF_ATTR((__nonnull__(1, 2))) __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0); int dxprintf_exec(int __fd, printf_comp_t __restrict __pc, ...) __XPRINTF_ATTR((__nonnull__(2))) __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0); int fxprintf_exec(FILE * __restrict __stream, printf_comp_t __restrict __pc, ...) __XPRINTF_ATTR((__nonnull__(1, 2))) __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0); int sxprintf_exec(char * __restrict __str, size_t __size, printf_comp_t __restrict __pc, ...) __XPRINTF_ATTR((__nonnull__(1, 3))) __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0); int xprintf_exec(printf_comp_t __restrict __pc, ...) __XPRINTF_ATTR((__nonnull__(1))) __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0); int vasxprintf_exec(char ** __restrict __ret, printf_comp_t __restrict __pc, va_list __ap) __XPRINTF_ATTR((__nonnull__(1, 2))) __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0); int vdxprintf_exec(int __fd, printf_comp_t __restrict __pc, va_list __ap) __XPRINTF_ATTR((__nonnull__(2))) __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0); int vfxprintf_exec(FILE * __restrict __stream, printf_comp_t __restrict __pc, va_list __ap) __XPRINTF_ATTR((__nonnull__(1, 2))) __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0); int vsxprintf_exec(char * __restrict __str, size_t __size, printf_comp_t __restrict __pc, va_list __ap) __XPRINTF_ATTR((__nonnull__(1, 3))) __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0); int vxprintf_exec(printf_comp_t __restrict __pc, va_list __ap) __XPRINTF_ATTR((__nonnull__(1))) __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0); __END_DECLS #endif /* !_PRINTF_H */