Skip to content

Commit c8e9662

Browse files
committed
Mark UTF-8 locale names with their encoding
1 parent 615080c commit c8e9662

2 files changed

Lines changed: 35 additions & 9 deletions

File tree

src/main/platform.c

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2218,15 +2218,17 @@ attribute_hidden SEXP do_getlocale(SEXP call, SEXP op, SEXP args, SEXP rho)
22182218
default: cat = NA_INTEGER;
22192219
}
22202220
if (cat != NA_INTEGER) p = setlocale(cat, NULL);
2221-
return mkString(p ? p : "");
2221+
/* setlocale() returns text in the current LC_CTYPE encoding. */
2222+
return ScalarString(mkCharCE(p ? p : "",
2223+
utf8locale ? CE_UTF8 : CE_NATIVE));
22222224
}
22232225

2224-
/* Locale specs are always ASCII */
22252226
attribute_hidden SEXP do_setlocale(SEXP call, SEXP op, SEXP args, SEXP rho)
22262227
{
22272228
SEXP locale = CADR(args), ans;
22282229
int cat;
22292230
const char *p;
2231+
char *locale_result = NULL;
22302232
bool warned = FALSE;
22312233

22322234
checkArity(op, args);
@@ -2322,13 +2324,10 @@ attribute_hidden SEXP do_setlocale(SEXP call, SEXP op, SEXP args, SEXP rho)
23222324
p = NULL; /* -Wall */
23232325
error(_("invalid '%s' argument"), "category");
23242326
}
2325-
PROTECT(ans = allocVector(STRSXP, 1));
2326-
if (p) SET_STRING_ELT(ans, 0, mkChar(p));
2327-
else {
2328-
SET_STRING_ELT(ans, 0, mkChar(""));
2329-
if (!warned)
2330-
warning(_("OS reports request to set locale to \"%s\" cannot be honored"),
2331-
CHAR(STRING_ELT(locale, 0)));
2327+
if (p) {
2328+
size_t n = strlen(p) + 1;
2329+
locale_result = R_alloc(n, 1);
2330+
memcpy(locale_result, p, n);
23322331
}
23332332
#ifdef Win32
23342333
int oldCP = localeCP;
@@ -2343,6 +2342,18 @@ attribute_hidden SEXP do_setlocale(SEXP call, SEXP op, SEXP args, SEXP rho)
23432342
}
23442343
#endif
23452344
invalidate_cached_recodings();
2345+
2346+
PROTECT(ans = allocVector(STRSXP, 1));
2347+
if (locale_result)
2348+
SET_STRING_ELT(ans, 0,
2349+
mkCharCE(locale_result,
2350+
utf8locale ? CE_UTF8 : CE_NATIVE));
2351+
else {
2352+
SET_STRING_ELT(ans, 0, mkChar(""));
2353+
if (!warned)
2354+
warning(_("OS reports request to set locale to \"%s\" cannot be honored"),
2355+
CHAR(STRING_ELT(locale, 0)));
2356+
}
23462357
UNPROTECT(1);
23472358
return ans;
23482359
}

tests/reg-encodings.R

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,21 @@ if(!is.null(lc <- lcct) && nzchar(lc)) Sys.setlocale("LC_CTYPE", lc) # revert
429429
## <chars>(a1)[3:4] were different in R <= 4.6.0
430430

431431

432+
## Sys.[gs]etlocale() return non-ASCII locale names with known encoding
433+
if(onWindows && UTF8) local({
434+
old <- Sys.getlocale("LC_TIME")
435+
on.exit(Sys.setlocale("LC_TIME", old))
436+
437+
## UCRT may expand this ASCII alias to a name containing "Bokm\u00e5l".
438+
setloc <- suppressWarnings(Sys.setlocale("LC_TIME", "Norwegian_Norway.UTF-8"))
439+
if(nzchar(setloc) && any(as.integer(charToRaw(setloc)) > 127L)) {
440+
getloc <- Sys.getlocale("LC_TIME")
441+
stopifnot(identical(Encoding(getloc), "UTF-8"),
442+
identical(Encoding(setloc), "UTF-8"))
443+
}
444+
})
445+
446+
432447

433448

434449
## PR#19112 -- writeChar() overflows its output buffer .. multibyte ..

0 commit comments

Comments
 (0)