1/*-
2 * Copyright (c) 2005 Poul-Henning Kamp
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: src/include/printf.h,v 1.5 2011/03/06 17:45:37 pjd Exp $
27 */
28
29#ifndef _PRINTF_H_
30#define _PRINTF_H_
31
32/****************************************************************************
33 * This is the header file for extensible printf, a set of APIs that allow
34 * adding/modifying conversion specifier(s) for stdio formatted printing.
35 * It is based on the GLIBC API documented in:
36 *
37 *   http://www.gnu.org/software/libc/manual/html_node/Customizing-Printf.html
38 *
39 * Because that API affects printf behavior process-wide and so is unsafe,
40 * we adapt a modified form, based on the concept of printf domains in which
41 * changes to conversion specifiers can be made independent of one another
42 * and which don't affect the normal printf behavior.  In addition, there
43 * is now a set of printf variants that take a printf domain as an argument.
44 *
45 * See xprintf(5) for more details.
46 ****************************************************************************/
47
48#include <stdio.h>
49#include <wchar.h>
50#include <xlocale.h>
51#include <Availability.h>
52
53#ifdef __GNUC__
54#define __XPRINTF_ATTR(x)	__attribute__(x)
55#else /* !__GNUC__ */
56#define __XPRINTF_ATTR(x)	/* nothing */
57#endif /* !__GNUC__ */
58
59/*
60 * The API defined by GLIBC allows a renderer to take multiple arguments
61 * This is obviously usable for things like (ptr+len) pairs etc.
62 * The current limit is to deal with up to __PRINTFMAXARG arguments (any
63 * above this limit are ignored).
64 */
65#define __PRINTFMAXARG		2
66
67struct printf_info {
68	/* Mac OS X extensions */
69	void		*context;		/* User context pointer */
70	locale_t	loc;			/* Extended locale */
71	wchar_t		vsep;			/* Vector separator char */
72						/* one of ,:;_ flag or X by default */
73
74	/* GLIBC compatible */
75	int		prec;			/* precision */
76	int		width;			/* Width */
77	wchar_t		spec;			/* Format letter */
78	wchar_t		pad;			/* Padding char */
79						/* 0 if 0 flag set, otherwise space */
80
81	/* FreeBSD extensions */
82	wchar_t		signchar;		/* Sign char */
83
84	/* GLIBC compatible flags */
85	unsigned	is_long_double	:1;	/* L or ll flag */
86	unsigned	is_char		:1;	/* hh flag */
87	unsigned	is_short	:1;	/* h flag */
88	unsigned	is_long		:1;	/* l flag */
89	unsigned	alt		:1;	/* # flag */
90	unsigned	space		:1;	/* Space flag */
91	unsigned	left		:1;	/* - flag */
92	unsigned	showsign	:1;	/* + flag */
93	unsigned	group		:1;	/* ' flag */
94	unsigned	extra		:1;	/* For special use (currently unused) */
95	unsigned	wide		:1;	/* Nonzero for wide character streams (currently unused) */
96
97	/* FreeBSD flags */
98	unsigned	is_quad		:1;	/* q flag */
99	unsigned	is_intmax	:1;	/* j flag */
100	unsigned	is_ptrdiff	:1;	/* t flag */
101	unsigned	is_size		:1;	/* z flag */
102
103	/* Mac OS X flags */
104	unsigned	is_vec		:1;	/* v flag */
105
106	/* private */
107	int		sofar;
108	unsigned	get_width;
109	unsigned	get_prec;
110	const char	*begin;
111	const char	*end;
112	void 		*arg[__PRINTFMAXARG];
113};
114
115enum {
116	PA_INT		= (1 << 0),	/* int */
117	PA_CHAR		= (1 << 1),	/* int, cast to char */
118	PA_WCHAR	= (1 << 2),	/* wide char */
119	PA_STRING	= (1 << 3),	/* const char * (with '\0') */
120	PA_WSTRING	= (1 << 4),	/* const wchar_t * */
121	PA_POINTER	= (1 << 5),	/* void * */
122	PA_FLOAT	= (1 << 6),	/* float (Defined but unused; best to avoid.) */
123	PA_DOUBLE	= (1 << 7), 	/* double */
124	PA_VECTOR	= (1 << 8), 	/* vector */
125};
126
127#define	PA_FLAG_MASK		0xff0000
128#define	PA_FLAG_LONG_LONG	(1 << 16)
129#define	PA_FLAG_LONG		(1 << 17)
130#define	PA_FLAG_SHORT		(1 << 18)
131#define	PA_FLAG_PTR		(1 << 19)
132#define	PA_FLAG_QUAD		(1 << 20)
133#define	PA_FLAG_INTMAX		(1 << 21)
134#define	PA_FLAG_SIZE		(1 << 22)
135#define	PA_FLAG_PTRDIFF		(1 << 23)
136#define	PA_FLAG_LONG_DOUBLE	PA_FLAG_LONG_LONG
137
138/************************ Basic Extensible Printf APIs ************************/
139
140typedef int printf_arginfo_function(const struct printf_info *__info,
141	     size_t __n, int *__argtypes);
142typedef int printf_function(FILE *__stream,
143	     const struct printf_info *__info, const void *const *__args);
144
145/*
146 * We don't support the GLIBC register_printf_function() or FreeBSD
147 * register_printf_render_std(), because they affect printf globally
148 * and are unsafe.
149 */
150
151/*************** Extensible Printf Domains APIs ****************/
152
153struct _printf_domain; /* forward reference */
154typedef struct _printf_domain *printf_domain_t;
155
156__BEGIN_DECLS
157
158printf_domain_t	copy_printf_domain(printf_domain_t __domain)
159		 __XPRINTF_ATTR((__nonnull__(1)))
160		 __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0);
161void		free_printf_domain(printf_domain_t __domain)
162		 __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0);
163printf_domain_t	new_printf_domain(void)
164		 __XPRINTF_ATTR((__malloc__))
165		 __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0);
166int	register_printf_domain_function(printf_domain_t __domain,
167	 int __spec, printf_function *__render,
168	 printf_arginfo_function *__arginfo, void *__context)
169	 __XPRINTF_ATTR((__nonnull__(1)))
170	 __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0);
171int	register_printf_domain_render_std(printf_domain_t __domain,
172	 const char *__specs)
173	 __XPRINTF_ATTR((__nonnull__(1)))
174	 __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0);
175
176/**** All-in-one extensible printf variants ****/
177int	asxprintf(char ** __restrict __ret,
178	 printf_domain_t __restrict __domain, locale_t __restrict __loc,
179	 const char * __restrict __format, ...)
180	 __XPRINTF_ATTR((__nonnull__(1, 2, 4)))
181	 __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0);
182int	dxprintf(int __fd, printf_domain_t __restrict __domain,
183	 locale_t __restrict __loc, const char * __restrict __format, ...)
184	 __XPRINTF_ATTR((__nonnull__(2, 4)))
185	 __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0);
186int	fxprintf(FILE * __restrict __stream,
187	 printf_domain_t __restrict __domain, locale_t __restrict __loc,
188	 const char * __restrict __format, ...)
189	 __XPRINTF_ATTR((__nonnull__(1, 2, 4)))
190	 __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0);
191int	sxprintf(char * __restrict __str, size_t __size,
192	 printf_domain_t __restrict __domain, locale_t __restrict __loc,
193	 const char * __restrict __format, ...)
194	 __XPRINTF_ATTR((__nonnull__(1, 3, 5)))
195	 __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0);
196int	xprintf(printf_domain_t __restrict __domain,
197	 locale_t __restrict __loc, const char * __restrict __format, ...)
198	 __XPRINTF_ATTR((__nonnull__(1, 3)))
199	 __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0);
200
201int	vasxprintf(char ** __restrict __ret,
202	 printf_domain_t __restrict __domain, locale_t __restrict __loc,
203	 const char * __restrict __format, va_list __ap)
204	 __XPRINTF_ATTR((__nonnull__(1, 2, 4)))
205	 __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0);
206int	vdxprintf(int __fd, printf_domain_t __restrict __domain,
207	 locale_t __restrict __loc, const char * __restrict __format,
208	 va_list __ap)
209	 __XPRINTF_ATTR((__nonnull__(2, 4)))
210	 __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0);
211int	vfxprintf(FILE * __restrict __stream,
212	 printf_domain_t __restrict __domain, locale_t __restrict __loc,
213	 const char * __restrict __format, va_list __ap)
214	 __XPRINTF_ATTR((__nonnull__(1, 2, 4)))
215	 __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0);
216int	vsxprintf(char * __restrict __str, size_t __size,
217	 printf_domain_t __restrict __domain, locale_t __restrict __loc,
218	 const char * __restrict __format, va_list __ap)
219	 __XPRINTF_ATTR((__nonnull__(1, 3, 5)))
220	 __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0);
221int	vxprintf(printf_domain_t __restrict __domain,
222	 locale_t __restrict __loc, const char * __restrict __format,
223	 va_list __ap)
224	 __XPRINTF_ATTR((__nonnull__(1, 3)))
225	 __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0);
226
227__END_DECLS
228
229/******** Extensible Printf Compilation/Execution APIs *********/
230struct _printf_compiled; /* forward reference */
231typedef struct _printf_compiled *printf_comp_t;
232
233__BEGIN_DECLS
234
235void		free_printf_comp(printf_comp_t __pc)
236		 __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0);
237printf_comp_t	new_printf_comp(printf_domain_t __restrict __domain,
238		 locale_t __restrict __loc, const char * __restrict __fmt)
239		 __XPRINTF_ATTR((__nonnull__(1, 3)))
240		 __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0);
241
242/**** Extensible printf execution ****/
243int	asxprintf_exec(char ** __restrict __ret,
244	 printf_comp_t __restrict __pc, ...)
245	 __XPRINTF_ATTR((__nonnull__(1, 2)))
246	 __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0);
247int	dxprintf_exec(int __fd, printf_comp_t __restrict __pc, ...)
248	 __XPRINTF_ATTR((__nonnull__(2)))
249	 __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0);
250int	fxprintf_exec(FILE * __restrict __stream,
251	 printf_comp_t __restrict __pc, ...)
252	 __XPRINTF_ATTR((__nonnull__(1, 2)))
253	 __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0);
254int	sxprintf_exec(char * __restrict __str, size_t __size,
255	 printf_comp_t __restrict __pc, ...)
256	 __XPRINTF_ATTR((__nonnull__(1, 3)))
257	 __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0);
258int	xprintf_exec(printf_comp_t __restrict __pc, ...)
259	 __XPRINTF_ATTR((__nonnull__(1)))
260	 __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0);
261
262int	vasxprintf_exec(char ** __restrict __ret,
263	 printf_comp_t __restrict __pc, va_list __ap)
264	 __XPRINTF_ATTR((__nonnull__(1, 2)))
265	 __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0);
266int	vdxprintf_exec(int __fd, printf_comp_t __restrict __pc,
267	 va_list __ap)
268	 __XPRINTF_ATTR((__nonnull__(2)))
269	 __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0);
270int	vfxprintf_exec(FILE * __restrict __stream,
271	 printf_comp_t __restrict __pc, va_list __ap)
272	 __XPRINTF_ATTR((__nonnull__(1, 2)))
273	 __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0);
274int	vsxprintf_exec(char * __restrict __str, size_t __size,
275	 printf_comp_t __restrict __pc, va_list __ap)
276	 __XPRINTF_ATTR((__nonnull__(1, 3)))
277	 __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0);
278int	vxprintf_exec(printf_comp_t __restrict __pc, va_list __ap)
279	 __XPRINTF_ATTR((__nonnull__(1)))
280	 __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0);
281
282__END_DECLS
283
284#endif /* !_PRINTF_H */
285