[libcxx] Provide locale conversions to tests through lit substitution… · llvm/llvm-project@2da24c3 (original) (raw)
`@@ -425,17 +425,106 @@ def _mingwSupportsModules(cfg):
`
425
425
`"fr_CA.ISO8859-1": ["fr_CA.ISO8859-1", "French_Canada.1252"],
`
426
426
`"cs_CZ.ISO8859-2": ["cs_CZ.ISO8859-2", "Czech_Czech Republic.1250"],
`
427
427
`}
`
``
428
`+
provide_locale_conversions = {
`
``
429
`+
"fr_FR.UTF-8": ["decimal_point", "mon_thousands_sep", "thousands_sep"],
`
``
430
`+
"ru_RU.UTF-8": ["mon_thousands_sep"],
`
``
431
`+
}
`
428
432
`for locale, alts in locales.items():
`
429
433
`# Note: Using alts directly in the lambda body here will bind it to the value at the
`
430
434
`# end of the loop. Assigning it to a default argument works around this issue.
`
431
435
`DEFAULT_FEATURES.append(
`
432
436
`Feature(
`
433
437
`name="locale.{}".format(locale),
`
434
438
`when=lambda cfg, alts=alts: hasAnyLocale(cfg, alts),
`
435
``
`-
)
`
``
439
`+
actions=lambda cfg, locale=locale, alts=alts: _getLocaleFlagsAction(
`
``
440
`+
cfg, locale, alts, provide_locale_conversions[locale]
`
``
441
`+
)
`
``
442
`+
if locale in provide_locale_conversions
`
``
443
`+
and "_LIBCPP_HAS_NO_WIDE_CHARACTERS" not in compilerMacros(cfg)
`
``
444
`+
else [],
`
``
445
`+
),
`
436
446
` )
`
437
447
``
438
448
``
``
449
`+
Provide environment locale conversions through substitutions to avoid platform specific
`
``
450
`+
maintenance.
`
``
451
`+
def _getLocaleFlagsAction(cfg, locale, alts, members):
`
``
452
`+
alts_list = ",".join([f'"{l}"' for l in alts])
`
``
453
`+
get_member_list = ",".join([f"lc->{m}" for m in members])
`
``
454
+
``
455
`+
localeconv_info = programOutput(
`
``
456
`+
cfg,
`
``
457
`+
r"""
`
``
458
`+
#if defined(_WIN32) && !defined(_CRT_SECURE_NO_WARNINGS)
`
``
459
`+
#define _CRT_SECURE_NO_WARNINGS
`
``
460
`+
#endif
`
``
461
`+
#include <stdio.h>
`
``
462
`+
#include <locale.h>
`
``
463
`+
#include <stdlib.h>
`
``
464
`+
#include <wchar.h>
`
``
465
+
``
466
`+
// Print each requested locale conversion member on separate lines.
`
``
467
`+
int main() {
`
``
468
`+
const char* locales[] = { %s };
`
``
469
`+
for (int loc_i = 0; loc_i < %d; ++loc_i) {
`
``
470
`+
if (!setlocale(LC_ALL, locales[loc_i])) {
`
``
471
`+
continue; // Choose first locale name that is recognized.
`
``
472
`+
}
`
``
473
+
``
474
`+
lconv* lc = localeconv();
`
``
475
`+
const char* members[] = { %s };
`
``
476
`+
for (size_t m_i = 0; m_i < %d; ++m_i) {
`
``
477
`+
if (!members[m_i]) {
`
``
478
`+
printf("\n"); // member value is an empty string
`
``
479
`+
continue;
`
``
480
`+
}
`
``
481
+
``
482
`+
size_t len = mbstowcs(nullptr, members[m_i], 0);
`
``
483
`+
if (len == static_cast(-1)) {
`
``
484
`+
fprintf(stderr, "mbstowcs failed unexpectedly\n");
`
``
485
`+
return 1;
`
``
486
`+
}
`
``
487
`+
// Include room for null terminator. Use malloc as these features
`
``
488
`+
// are also used by lit configs that don't use -lc++ (libunwind tests).
`
``
489
`+
wchar_t* dst = (wchar_t*)malloc((len + 1) * sizeof(wchar_t));
`
``
490
`+
size_t ret = mbstowcs(dst, members[m_i], len + 1);
`
``
491
`+
if (ret == static_cast(-1)) {
`
``
492
`+
fprintf(stderr, "mbstowcs failed unexpectedly\n");
`
``
493
`+
free(dst);
`
``
494
`+
return 1;
`
``
495
`+
}
`
``
496
+
``
497
`+
for (size_t i = 0; i < len; ++i) {
`
``
498
`+
if (dst[i] > 0x7F) {
`
``
499
`+
printf("\u%%04x", dst[i]);
`
``
500
`+
} else {
`
``
501
`+
// c++03 does not allow basic ascii-range characters in UCNs
`
``
502
`+
printf("%%c", (char)dst[i]);
`
``
503
`+
}
`
``
504
`+
}
`
``
505
`+
printf("\n");
`
``
506
`+
free(dst);
`
``
507
`+
}
`
``
508
`+
return 0;
`
``
509
`+
}
`
``
510
+
``
511
`+
return 1;
`
``
512
`+
}
`
``
513
`+
"""
`
``
514
`+
% (alts_list, len(alts), get_member_list, len(members)),
`
``
515
`+
)
`
``
516
`+
valid_define_name = re.sub(r"[.-]", "_", locale).upper()
`
``
517
`+
return [
`
``
518
`+
Provide locale conversion through a substitution.
`
``
519
`+
Example: %{LOCALE_CONV_FR_FR_UTF_8_THOUSANDS_SEP} = L"\u202f"
`
``
520
`+
AddSubstitution(
`
``
521
`+
f"%{{LOCALE_CONV_{valid_define_name}_{member.upper()}}}",
`
``
522
`+
lambda cfg, value=value: f"'L"{value}"'",
`
``
523
`+
)
`
``
524
`+
for member, value in zip(members, localeconv_info.split("\n"))
`
``
525
`+
]
`
``
526
+
``
527
+
439
528
`# Add features representing the target platform name: darwin, linux, windows, etc...
`
440
529
`DEFAULT_FEATURES += [
`
441
530
`Feature(name="darwin", when=lambda cfg: "APPLE" in compilerMacros(cfg)),
`