mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-05-28 01:11:15 -03:00
Fix printf's Unicode support
https://github.com/fish-shell/fish-shell/issues/625
This commit is contained in:
@@ -342,29 +342,39 @@ long builtin_printf_state_t::print_esc(const wchar_t *escstart, bool octal_0)
|
|||||||
else if (*p == L'u' || *p == L'U')
|
else if (*p == L'u' || *p == L'U')
|
||||||
{
|
{
|
||||||
wchar_t esc_char = *p;
|
wchar_t esc_char = *p;
|
||||||
unsigned int uni_value;
|
p++;
|
||||||
|
uint32_t uni_value = 0;
|
||||||
uni_value = 0;
|
for (size_t esc_length = 0; esc_length < (esc_char == L'u' ? 4 : 8); esc_length++)
|
||||||
for (esc_length = (esc_char == L'u' ? 4 : 8), ++p;
|
|
||||||
esc_length > 0;
|
|
||||||
--esc_length, ++p)
|
|
||||||
{
|
{
|
||||||
if (! is_hex_digit(*p))
|
if (! is_hex_digit(*p))
|
||||||
this->fatal_error(_(L"missing hexadecimal number in escape"));
|
{
|
||||||
|
/* Escape sequence must be done. Complain if we didn't get anything */
|
||||||
|
if (esc_length == 0)
|
||||||
|
{
|
||||||
|
this->fatal_error(_(L"Missing hexadecimal number in Unicode escape"));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
uni_value = uni_value * 16 + hex_to_bin(*p);
|
uni_value = uni_value * 16 + hex_to_bin(*p);
|
||||||
|
p++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* A universal character name shall not specify a character short
|
/* PCA GNU printf respects the limitations described in ISO N717, about which universal characters "shall not" be specified. I believe this limitation is for the benefit of compilers; I see no reason to impose it in builtin_printf.
|
||||||
identifier in the range 00000000 through 00000020, 0000007F through
|
|
||||||
0000009F, or 0000D800 through 0000DFFF inclusive. A universal
|
If __STDC_ISO_10646__ is defined, then it means wchar_t can and does hold Unicode code points, so just use that. If not defined, use the %lc printf conversion; this probably won't do anything good if your wide character set is not Unicode, but such platforms are exceedingly rare.
|
||||||
character name shall not designate a character in the required
|
*/
|
||||||
character set. */
|
if (uni_value > 0x10FFFF)
|
||||||
if ((uni_value <= 0x9f
|
{
|
||||||
&& uni_value != 0x24 && uni_value != 0x40 && uni_value != 0x60)
|
this->fatal_error(_(L"Unicode character out of range: \\%c%0*x"), esc_char, (esc_char == L'u' ? 4 : 8), uni_value);
|
||||||
|| (uni_value >= 0xd800 && uni_value <= 0xdfff))
|
}
|
||||||
this->fatal_error(_(L"invalid universal character name \\%c%0*x"),
|
else
|
||||||
esc_char, (esc_char == L'u' ? 4 : 8), uni_value);
|
{
|
||||||
this->append_format_output(L"%lc", uni_value);
|
#if defined(__STDC_ISO_10646__)
|
||||||
|
this->append_output(uni_value);
|
||||||
|
#else
|
||||||
|
this->append_format_output(L"%lc", uni_value);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user