[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)),

`