1 /* Copyright (C) 2009-2023 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 <https://www.gnu.org/licenses/>. */
23 #include <libc-lock.h>
26 struct printf_modifier_record
28 struct printf_modifier_record
*next
;
33 struct printf_modifier_record
**__printf_modifier_table attribute_hidden
;
35 __libc_lock_define_initialized (static, lock
)
37 /* Bits to hand out. */
42 __register_printf_modifier (const wchar_t *str
)
51 const wchar_t *wc
= str
;
53 if (*wc
< 0 || *wc
> (wchar_t) UCHAR_MAX
)
58 if (next_bit
/ 8 == sizeof (((struct printf_info
*) NULL
)->user
))
65 __libc_lock_lock (lock
);
67 if (__printf_modifier_table
== NULL
)
69 __printf_modifier_table
= calloc (UCHAR_MAX
,
70 sizeof (*__printf_modifier_table
));
71 if (__printf_modifier_table
== NULL
)
75 /* Create enough room for the string. But we don't need the first
77 struct printf_modifier_record
*newp
= malloc (sizeof (*newp
)
83 newp
->next
= __printf_modifier_table
[(unsigned char) *str
];
84 newp
->bit
= 1 << next_bit
++;
85 __wmemcpy (newp
->str
, str
+ 1, wc
- str
);
87 __printf_modifier_table
[(unsigned char) *str
] = newp
;
92 __libc_lock_unlock (lock
);
96 weak_alias (__register_printf_modifier
, register_printf_modifier
)
102 __handle_registered_modifier_mb (const unsigned char **format
,
103 struct printf_info
*info
)
105 struct printf_modifier_record
*runp
= __printf_modifier_table
[**format
];
109 const unsigned char *best_cp
= NULL
;
113 const unsigned char *cp
= *format
+ 1;
114 wchar_t *fcp
= runp
->str
;
116 while (*cp
!= '\0' && *fcp
!= L
'\0')
122 if (*fcp
== L
'\0' && cp
- *format
> best_len
)
125 best_len
= cp
- *format
;
126 best_bit
= runp
->bit
;
134 info
->user
|= best_bit
;
145 __handle_registered_modifier_wc (const unsigned int **format
,
146 struct printf_info
*info
)
148 struct printf_modifier_record
*runp
= __printf_modifier_table
[**format
];
152 const unsigned int *best_cp
= NULL
;
156 const unsigned int *cp
= *format
+ 1;
157 wchar_t *fcp
= runp
->str
;
159 while (*cp
!= '\0' && *fcp
!= L
'\0')
165 if (*fcp
== L
'\0' && cp
- *format
> best_len
)
168 best_len
= cp
- *format
;
169 best_bit
= runp
->bit
;
177 info
->user
|= best_bit
;
187 __libc_printf_freemem (void)
189 if (__printf_modifier_table
!= NULL
)
191 for (int i
= 0; i
< UCHAR_MAX
; ++i
)
193 struct printf_modifier_record
*runp
= __printf_modifier_table
[i
];
196 struct printf_modifier_record
*oldp
= runp
;
201 free (__printf_modifier_table
);