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 #pragma clang diagnostic push
32 #pragma clang diagnostic ignored "-Wpointer-bool-conversion"
34 /* These are flag characters and can never be used as conversion specifiers */
35 static const char _printf_tbl_flags
[] = "#$'*+,-.0123456789:;L_hjlqtvz";
37 struct _printf_tbl_defaults_fbsd
{
39 printf_arginfo_function
*arginfo
;
40 printf_render
*render
;
42 static struct _printf_tbl_defaults_fbsd _printf_tbl_defaults_fbsd
[] = {
43 {"%", __printf_arginfo_pct
, __printf_render_pct
},
44 {"AEFGaefg", __printf_arginfo_float
, __printf_render_float
},
45 {"Cc", __printf_arginfo_chr
, __printf_render_chr
},
46 {"DOUXdioux", __printf_arginfo_int
, __printf_render_int
},
47 {"Ss", __printf_arginfo_str
, __printf_render_str
},
48 {"p", __printf_arginfo_ptr
, __printf_render_ptr
},
50 struct _printf_tbl_defaults_glibc
{
52 printf_arginfo_function
*arginfo
;
53 printf_function
*render
;
55 static struct _printf_tbl_defaults_glibc _printf_tbl_defaults_glibc
[] = {
56 {"n", __printf_arginfo_n
, __printf_render_n
},
59 static printf_domain_t xprintf_domain_default
;
61 __private_extern__ printf_domain_t xprintf_domain_global
= NULL
;
64 __private_extern__ pthread_once_t __xprintf_domain_once
= PTHREAD_ONCE_INIT
;
66 __private_extern__
void
67 __xprintf_domain_init(void)
69 xprintf_domain_default
= (printf_domain_t
)calloc(
75 sizeof(*xprintf_domain_default
));
76 if(xprintf_domain_default
== NULL
)
77 LIBC_ABORT("No memory");
79 xprintf_domain_default
->rwlock
= (pthread_rwlock_t
)PTHREAD_RWLOCK_INITIALIZER
;
82 for(cp
= _printf_tbl_flags
; *cp
; cp
++)
83 xprintf_domain_default
->type
[printf_tbl_index(*cp
)] = PRINTF_DOMAIN_FLAG
;
86 struct _printf_tbl_defaults_fbsd
*d
= _printf_tbl_defaults_fbsd
;
87 int n
= sizeof(_printf_tbl_defaults_fbsd
) / sizeof(*_printf_tbl_defaults_fbsd
);
88 for(; n
> 0; d
++, n
--) {
89 for(const char *cp
= d
->spec
; *cp
; cp
++) {
90 xprintf_domain_default
->type
[printf_tbl_index(*cp
)] = PRINTF_DOMAIN_FBSD_API
;
91 xprintf_domain_default
->tbl
[printf_tbl_index(*cp
)] = (struct _printf_tbl
){d
->arginfo
, d
->render
, NULL
};
96 struct _printf_tbl_defaults_glibc
*d
= _printf_tbl_defaults_glibc
;
97 int n
= sizeof(_printf_tbl_defaults_glibc
) / sizeof(*_printf_tbl_defaults_glibc
);
98 for(; n
> 0; d
++, n
--) {
99 for(const char *cp
= d
->spec
; *cp
; cp
++) {
100 xprintf_domain_default
->type
[printf_tbl_index(*cp
)] = PRINTF_DOMAIN_GLIBC_API
;
101 xprintf_domain_default
->tbl
[printf_tbl_index(*cp
)] = (struct _printf_tbl
){d
->arginfo
, d
->render
, NULL
};
106 xprintf_domain_global
= xprintf_domain_default
+ 1;
107 *xprintf_domain_global
= *xprintf_domain_default
;
112 copy_printf_domain(printf_domain_t src
)
114 printf_domain_t restrict copy
;
120 copy
= (printf_domain_t
)MALLOC(sizeof(*copy
));
121 if(!copy
) return NULL
;
122 xprintf_domain_init();
123 pthread_rwlock_rdlock(&src
->rwlock
);
125 pthread_rwlock_unlock(&src
->rwlock
);
126 copy
->rwlock
= (pthread_rwlock_t
)PTHREAD_RWLOCK_INITIALIZER
;
131 free_printf_domain(printf_domain_t d
)
134 pthread_rwlock_destroy(&d
->rwlock
);
139 new_printf_domain(void)
141 printf_domain_t restrict d
;
143 xprintf_domain_init();
145 d
= (printf_domain_t
)MALLOC(sizeof(*d
));
147 *d
= *xprintf_domain_default
;
152 register_printf_domain_function(printf_domain_t d
, int spec
, printf_function
*render
, printf_arginfo_function
*arginfo
, void *context
)
154 xprintf_domain_init();
156 if(!d
|| !printf_tbl_in_range(spec
)) {
160 xprintf_domain_init();
162 switch(d
->type
[printf_tbl_index(spec
)]) {
163 case PRINTF_DOMAIN_FLAG
:
167 pthread_rwlock_wrlock(&d
->rwlock
);
168 if(!render
|| !arginfo
) {
169 d
->type
[printf_tbl_index(spec
)] = PRINTF_DOMAIN_UNUSED
;
171 d
->type
[printf_tbl_index(spec
)] = PRINTF_DOMAIN_GLIBC_API
;
172 d
->tbl
[printf_tbl_index(spec
)] = (struct _printf_tbl
){arginfo
, render
, context
};
174 pthread_rwlock_unlock(&d
->rwlock
);
180 __private_extern__
int
181 register_printf_domain_render(printf_domain_t d
, int spec
, printf_render
*render
, printf_arginfo_function
*arginfo
)
183 xprintf_domain_init();
185 if(!d
|| !printf_tbl_in_range(spec
)) {
189 xprintf_domain_init();
191 switch(d
->type
[printf_tbl_index(spec
)]) {
192 case PRINTF_DOMAIN_FLAG
:
196 pthread_rwlock_wrlock(&d
->rwlock
);
197 if(!render
|| !arginfo
) {
198 d
->type
[printf_tbl_index(spec
)] = PRINTF_DOMAIN_UNUSED
;
200 d
->type
[printf_tbl_index(spec
)] = PRINTF_DOMAIN_FBSD_API
;
201 d
->tbl
[printf_tbl_index(spec
)] = (struct _printf_tbl
){arginfo
, render
, NULL
};
203 pthread_rwlock_unlock(&d
->rwlock
);
210 register_printf_domain_render_std(printf_domain_t d
, const char *specs
)
214 for (; *specs
!= '\0'; specs
++) {
217 ret
= register_printf_domain_render(d
, *specs
,
218 __printf_render_hexdump
,
219 __printf_arginfo_hexdump
);
222 ret
= register_printf_domain_render(d
, *specs
,
223 __printf_render_errno
,
224 __printf_arginfo_errno
);
227 ret
= register_printf_domain_render(d
, *specs
,
228 __printf_render_quote
,
229 __printf_arginfo_quote
);
232 ret
= register_printf_domain_render(d
, *specs
,
233 __printf_render_time
,
234 __printf_arginfo_time
);
237 ret
= register_printf_domain_render(d
, *specs
,
239 __printf_arginfo_vis
);
245 if(ret
< 0) return ret
;
249 #pragma clang diagnostic pop