2 * Copyright (c) 2012 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
28 #include "xprintf_domain.h"
29 #include "xprintf_private.h"
31 /* These are flag characters and can never be used as conversion specifiers */
32 static const char _printf_tbl_flags
[] = "#$'*+,-.0123456789:;L_hjlqtvz";
34 struct _printf_tbl_defaults_fbsd
{
36 printf_arginfo_function
*arginfo
;
37 printf_render
*render
;
39 static struct _printf_tbl_defaults_fbsd _printf_tbl_defaults_fbsd
[] = {
40 {"%", __printf_arginfo_pct
, __printf_render_pct
},
41 {"AEFGaefg", __printf_arginfo_float
, __printf_render_float
},
42 {"Cc", __printf_arginfo_chr
, __printf_render_chr
},
43 {"DOUXdioux", __printf_arginfo_int
, __printf_render_int
},
44 {"Ss", __printf_arginfo_str
, __printf_render_str
},
45 {"p", __printf_arginfo_ptr
, __printf_render_ptr
},
47 struct _printf_tbl_defaults_glibc
{
49 printf_arginfo_function
*arginfo
;
50 printf_function
*render
;
52 static struct _printf_tbl_defaults_glibc _printf_tbl_defaults_glibc
[] = {
53 {"n", __printf_arginfo_n
, __printf_render_n
},
56 static printf_domain_t xprintf_domain_default
;
58 __private_extern__ printf_domain_t xprintf_domain_global
= NULL
;
61 __private_extern__ pthread_once_t __xprintf_domain_once
= PTHREAD_ONCE_INIT
;
63 __private_extern__
void
64 __xprintf_domain_init(void)
66 xprintf_domain_default
= (printf_domain_t
)calloc(
72 sizeof(*xprintf_domain_default
));
73 if(xprintf_domain_default
== NULL
)
74 LIBC_ABORT("No memory");
76 xprintf_domain_default
->rwlock
= (pthread_rwlock_t
)PTHREAD_RWLOCK_INITIALIZER
;
79 for(cp
= _printf_tbl_flags
; *cp
; cp
++)
80 xprintf_domain_default
->type
[printf_tbl_index(*cp
)] = PRINTF_DOMAIN_FLAG
;
83 struct _printf_tbl_defaults_fbsd
*d
= _printf_tbl_defaults_fbsd
;
84 int n
= sizeof(_printf_tbl_defaults_fbsd
) / sizeof(*_printf_tbl_defaults_fbsd
);
85 for(; n
> 0; d
++, n
--) {
86 for(const char *cp
= d
->spec
; *cp
; cp
++) {
87 xprintf_domain_default
->type
[printf_tbl_index(*cp
)] = PRINTF_DOMAIN_FBSD_API
;
88 xprintf_domain_default
->tbl
[printf_tbl_index(*cp
)] = (struct _printf_tbl
){d
->arginfo
, d
->render
, NULL
};
93 struct _printf_tbl_defaults_glibc
*d
= _printf_tbl_defaults_glibc
;
94 int n
= sizeof(_printf_tbl_defaults_glibc
) / sizeof(*_printf_tbl_defaults_glibc
);
95 for(; n
> 0; d
++, n
--) {
96 for(const char *cp
= d
->spec
; *cp
; cp
++) {
97 xprintf_domain_default
->type
[printf_tbl_index(*cp
)] = PRINTF_DOMAIN_GLIBC_API
;
98 xprintf_domain_default
->tbl
[printf_tbl_index(*cp
)] = (struct _printf_tbl
){d
->arginfo
, d
->render
, NULL
};
103 xprintf_domain_global
= xprintf_domain_default
+ 1;
104 *xprintf_domain_global
= *xprintf_domain_default
;
109 copy_printf_domain(printf_domain_t src
)
111 printf_domain_t restrict copy
;
117 copy
= (printf_domain_t
)MALLOC(sizeof(*copy
));
118 if(!copy
) return NULL
;
119 xprintf_domain_init();
120 pthread_rwlock_rdlock(&src
->rwlock
);
122 pthread_rwlock_unlock(&src
->rwlock
);
123 copy
->rwlock
= (pthread_rwlock_t
)PTHREAD_RWLOCK_INITIALIZER
;
128 free_printf_domain(printf_domain_t d
)
131 pthread_rwlock_destroy(&d
->rwlock
);
136 new_printf_domain(void)
138 printf_domain_t restrict d
;
140 xprintf_domain_init();
142 d
= (printf_domain_t
)MALLOC(sizeof(*d
));
144 *d
= *xprintf_domain_default
;
149 register_printf_domain_function(printf_domain_t d
, int spec
, printf_function
*render
, printf_arginfo_function
*arginfo
, void *context
)
151 xprintf_domain_init();
153 if(!d
|| !printf_tbl_in_range(spec
)) {
157 xprintf_domain_init();
159 switch(d
->type
[printf_tbl_index(spec
)]) {
160 case PRINTF_DOMAIN_FLAG
:
164 pthread_rwlock_wrlock(&d
->rwlock
);
165 if(!render
|| !arginfo
) {
166 d
->type
[printf_tbl_index(spec
)] = PRINTF_DOMAIN_UNUSED
;
168 d
->type
[printf_tbl_index(spec
)] = PRINTF_DOMAIN_GLIBC_API
;
169 d
->tbl
[printf_tbl_index(spec
)] = (struct _printf_tbl
){arginfo
, render
, context
};
171 pthread_rwlock_unlock(&d
->rwlock
);
177 __private_extern__
int
178 register_printf_domain_render(printf_domain_t d
, int spec
, printf_render
*render
, printf_arginfo_function
*arginfo
)
180 xprintf_domain_init();
182 if(!d
|| !printf_tbl_in_range(spec
)) {
186 xprintf_domain_init();
188 switch(d
->type
[printf_tbl_index(spec
)]) {
189 case PRINTF_DOMAIN_FLAG
:
193 pthread_rwlock_wrlock(&d
->rwlock
);
194 if(!render
|| !arginfo
) {
195 d
->type
[printf_tbl_index(spec
)] = PRINTF_DOMAIN_UNUSED
;
197 d
->type
[printf_tbl_index(spec
)] = PRINTF_DOMAIN_FBSD_API
;
198 d
->tbl
[printf_tbl_index(spec
)] = (struct _printf_tbl
){arginfo
, render
, NULL
};
200 pthread_rwlock_unlock(&d
->rwlock
);
207 register_printf_domain_render_std(printf_domain_t d
, const char *specs
)
211 for (; *specs
!= '\0'; specs
++) {
214 ret
= register_printf_domain_render(d
, *specs
,
215 __printf_render_hexdump
,
216 __printf_arginfo_hexdump
);
219 ret
= register_printf_domain_render(d
, *specs
,
220 __printf_render_errno
,
221 __printf_arginfo_errno
);
224 ret
= register_printf_domain_render(d
, *specs
,
225 __printf_render_quote
,
226 __printf_arginfo_quote
);
229 ret
= register_printf_domain_render(d
, *specs
,
230 __printf_render_time
,
231 __printf_arginfo_time
);
234 ret
= register_printf_domain_render(d
, *specs
,
236 __printf_arginfo_vis
);
242 if(ret
< 0) return ret
;