1 /* Copyright (C) 2009 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <http://www.gnu.org/licenses/>. */
22 #include <bits/libc-lock.h>
25 struct printf_modifier_record
27 struct printf_modifier_record
*next
;
32 struct printf_modifier_record
**__printf_modifier_table attribute_hidden
;
34 __libc_lock_define_initialized (static, lock
)
36 /* Bits to hand out. */
41 __register_printf_modifier (const wchar_t *str
)
50 const wchar_t *wc
= str
;
52 if (*wc
< 0 || *wc
> (wchar_t) UCHAR_MAX
)
57 if (next_bit
/ 8 == sizeof (((struct printf_info
*) NULL
)->user
))
64 __libc_lock_lock (lock
);
66 if (__printf_modifier_table
== NULL
)
68 __printf_modifier_table
= calloc (UCHAR_MAX
,
69 sizeof (*__printf_modifier_table
));
70 if (__printf_modifier_table
== NULL
)
74 /* Create enough room for the string. But we don't need the first
76 struct printf_modifier_record
*newp
= malloc (sizeof (*newp
)
82 newp
->next
= __printf_modifier_table
[(unsigned char) *str
];
83 newp
->bit
= 1 << next_bit
++;
84 __wmemcpy (newp
->str
, str
+ 1, wc
- str
);
86 __printf_modifier_table
[(unsigned char) *str
] = newp
;
91 __libc_lock_unlock (lock
);
95 weak_alias (__register_printf_modifier
, register_printf_modifier
)
101 __handle_registered_modifier_mb (const unsigned char **format
,
102 struct printf_info
*info
)
104 struct printf_modifier_record
*runp
= __printf_modifier_table
[**format
];
108 const unsigned char *best_cp
= NULL
;
112 const unsigned char *cp
= *format
+ 1;
113 wchar_t *fcp
= runp
->str
;
115 while (*cp
!= '\0' && *fcp
!= L
'\0')
121 if (*fcp
== L
'\0' && cp
- *format
> best_len
)
124 best_len
= cp
- *format
;
125 best_bit
= runp
->bit
;
133 info
->user
|= best_bit
;
144 __handle_registered_modifier_wc (const unsigned int **format
,
145 struct printf_info
*info
)
147 struct printf_modifier_record
*runp
= __printf_modifier_table
[**format
];
151 const unsigned int *best_cp
= NULL
;
155 const unsigned int *cp
= *format
+ 1;
156 wchar_t *fcp
= runp
->str
;
158 while (*cp
!= '\0' && *fcp
!= L
'\0')
164 if (*fcp
== L
'\0' && cp
- *format
> best_len
)
167 best_len
= cp
- *format
;
168 best_bit
= runp
->bit
;
176 info
->user
|= best_bit
;
185 libc_freeres_fn (free_mem
)
187 if (__printf_modifier_table
!= NULL
)
189 for (int i
= 0; i
< UCHAR_MAX
; ++i
)
191 struct printf_modifier_record
*runp
= __printf_modifier_table
[i
];
194 struct printf_modifier_record
*oldp
= runp
;
199 free (__printf_modifier_table
);