Skip to content

Commit

Permalink
locale.c: Split ancillary from S_emulate_setlocale
Browse files Browse the repository at this point in the history
This takes the code to update LC_ALL, used only in some Configurations,
out of the main line, making the main line more readable.

It also allows the removal of temporary code added a few commits back
  • Loading branch information
khwilliamson committed May 5, 2021
1 parent 387a2b3 commit 015787f
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 49 deletions.
6 changes: 5 additions & 1 deletion embed.fnc
Expand Up @@ -3252,10 +3252,14 @@ S |void |new_numeric |NULLOK const char* newnum
S |void |new_LC_ALL |NULLOK const char* unused
# ifdef USE_POSIX_2008_LOCALE
S |const char*|emulate_setlocale_i|const unsigned int index \
|NULLOK const char* new_locale
|NULLOK const char* new_locale \
|const int recalc_LC_ALL
S |const char*|my_querylocale_i|const unsigned int index
S |const char *|setlocale_from_aggregate_LC_ALL \
|NN const char * locale
S |const char*|update_PL_curlocales_i|const unsigned int index \
|NN const char * new_locale \
|int recalc_LC_ALL
# endif
# ifdef WIN32
S |char* |win32_setlocale|int category|NULLOK const char* locale
Expand Down
3 changes: 2 additions & 1 deletion embed.h
Expand Up @@ -1710,9 +1710,10 @@
#define stdize_locale(a,b,c,d) S_stdize_locale(aTHX_ a,b,c,d)
#define switch_category_locale_to_template(a,b,c) S_switch_category_locale_to_template(aTHX_ a,b,c)
# if defined(USE_POSIX_2008_LOCALE)
#define emulate_setlocale_i(a,b) S_emulate_setlocale_i(aTHX_ a,b)
#define emulate_setlocale_i(a,b,c) S_emulate_setlocale_i(aTHX_ a,b,c)
#define my_querylocale_i(a) S_my_querylocale_i(aTHX_ a)
#define setlocale_from_aggregate_LC_ALL(a) S_setlocale_from_aggregate_LC_ALL(aTHX_ a)
#define update_PL_curlocales_i(a,b,c) S_update_PL_curlocales_i(aTHX_ a,b,c)
# endif
# if defined(USE_QUERYLOCALE)
#define calculate_LC_ALL(a) S_calculate_LC_ALL(aTHX_ a)
Expand Down
138 changes: 92 additions & 46 deletions locale.c
Expand Up @@ -490,10 +490,14 @@ S_category_name(const int category)
* are equivalents, like LC_NUMERIC_MASK, which we use instead, converting to
* by using get_category_index() followed by table lookup. */

# define emulate_setlocale_c(cat, locale) \
emulate_setlocale_i(cat##_INDEX_, locale)
# define emulate_setlocale_c(cat, locale, recalc_LC_ALL) \
emulate_setlocale_i(cat##_INDEX_, locale, recalc_LC_ALL)

# define setlocale_i(i, locale) emulate_setlocale_i(i, locale)
/* A wrapper for the macros below. TRUE => do recalculate LC_ALL */
# define common_emulate_setlocale(i, locale) \
emulate_setlocale_i(i, locale, TRUE)

# define setlocale_i(i, locale) common_emulate_setlocale(i, locale)
# define setlocale_c(cat, locale) setlocale_i(cat##_INDEX_, locale)
# define setlocale_r(cat, locale) \
setlocale_i(get_category_index(cat, locale), locale)
Expand Down Expand Up @@ -649,7 +653,61 @@ S_my_querylocale_i(pTHX_ const unsigned int index)
return retval;
}

# ifndef USE_QUERYLOCALE
# define LOOPING -1 /* Special value for 'recalc_LC_ALL' parameter below */

# ifdef USE_PL_CURLOCALES

STATIC const char *
S_update_PL_curlocales_i(pTHX_
const unsigned int index,
const char * new_locale,

/* 0 => skip recalculating LC_ALL;
* 1 => do recalculate LC_ALL
* LOOPING => this call is part of a loop that goes
* through all categories by index-order.
* Recalculate only on the final iteration,
* after all values are known */
int recalc_LC_ALL)
{
/* This is a helper function for emulate_setlocale_i(), mostly used to
* make that function easier to read. */

PERL_ARGS_ASSERT_UPDATE_PL_CURLOCALES_I;
assert(index <= NOMINAL_LC_ALL_INDEX);

if (index == LC_ALL_INDEX_) {
unsigned int i;

/* For LC_ALL, we change all individual categories to correspond */
/* PL_curlocales is a parallel array, so has same
* length as 'categories' */
for (i = 0; i < LC_ALL_INDEX_; i++) {
Safefree(PL_curlocales[i]);
PL_curlocales[i] = savepv(new_locale);
}

recalc_LC_ALL = TRUE;
}
else {

/* Update the single category's record */
Safefree(PL_curlocales[index]);
PL_curlocales[index] = savepv(new_locale);

if (recalc_LC_ALL == LOOPING) {
recalc_LC_ALL = (index == NOMINAL_LC_ALL_INDEX - 1);
}
}

if (recalc_LC_ALL) { /* And recalculate LC_ALL */
Safefree(PL_curlocales[LC_ALL_INDEX_]);
PL_curlocales[LC_ALL_INDEX_] =
savepv(calculate_LC_ALL(PL_curlocales));
}

return PL_curlocales[index];
}

STATIC const char *
S_setlocale_from_aggregate_LC_ALL(pTHX_ const char * locale)
Expand Down Expand Up @@ -688,8 +746,9 @@ S_setlocale_from_aggregate_LC_ALL(pTHX_ const char * locale)
/* If the string that gives what to set doesn't include all categories,
* the omitted ones get set to "C". To get this behavior, first set
* all the individual categories to "C", and override the furnished
* ones below */
if (! emulate_setlocale_c(LC_ALL, "C")) {
* ones below. FALSE => No need to recalculate LC_ALL, as this is a
* temporary state */
if (! emulate_setlocale_c(LC_ALL, "C", FALSE)) {
setlocale_failure_panic_c(LC_ALL, locale_on_entry,
"C", __LINE__, 0);
NOT_REACHED; /* NOTREACHED */
Expand Down Expand Up @@ -740,8 +799,13 @@ S_setlocale_from_aggregate_LC_ALL(pTHX_ const char * locale)

individ_locale = Perl_form(aTHX_ "%.*s",
(int) (name_end - name_start), name_start);
if (! emulate_setlocale_i(i, individ_locale)) {
if (! emulate_setlocale_c(LC_ALL, locale_on_entry)) {

/* FALSE => Don't recalculate LC_ALL; we'll do it ourselves after
* the loop */
if (! emulate_setlocale_i(i, individ_locale, FALSE)) {

/* But if we have to back out, do fix up LC_ALL */
if (! emulate_setlocale_c(LC_ALL, locale_on_entry, TRUE)) {
Safefree(locale_on_entry);
setlocale_failure_panic_i(i, individ_locale,
locale, __LINE__, 0);
Expand Down Expand Up @@ -770,10 +834,13 @@ S_setlocale_from_aggregate_LC_ALL(pTHX_ const char * locale)
return retval;
}

# endif /* No querylocale() */
# endif /* Need PL_curlocales[] */

STATIC const char *
S_emulate_setlocale_i(pTHX_ const unsigned int index, const char * new_locale)
S_emulate_setlocale_i(pTHX_
const unsigned int index,
const char * new_locale,
const int recalc_LC_ALL)
{
/* This function effectively performs a setlocale() on just the current
* thread; thus it is thread-safe. It does this by using the POSIX 2008
Expand All @@ -788,7 +855,14 @@ S_emulate_setlocale_i(pTHX_ const unsigned int index, const char * new_locale)
*
* This function takes our internal index of the 'category' setlocale is
* called with, and the 'new_locale' to set the category to. It uses the
* index to find the category mask that the POSIX 2008 functions use. */
* index to find the category mask that the POSIX 2008 functions use.
*
* The function can be called recursively on all the individual categories,
* when the outer call is for LC_ALL. It would be unnecessary work to
* recalculate LC_ALL in the middle of all this; so the 'recalc_LC_ALL'
* parameter is set to LOOPING in this circumstance, to indicate to
* recalculate only on the final category; 0 to indicate to not recalculate
* at all; and 1 to indicate to do so unconditionally */

int mask;
locale_t old_obj;
Expand Down Expand Up @@ -888,7 +962,7 @@ S_emulate_setlocale_i(pTHX_ const unsigned int index, const char * new_locale)
&& strNE(env_override, ""))
? env_override
: default_name;
if (! emulate_setlocale_i(i, this_locale))
if (! emulate_setlocale_i(i, this_locale, LOOPING))
{
return NULL;
}
Expand Down Expand Up @@ -1064,38 +1138,11 @@ S_emulate_setlocale_i(pTHX_ const unsigned int index, const char * new_locale)
new_locale = querylocale_i(index);
}

# else

/* Here, 'new_locale' is the return value */

/* Without querylocale(), we have to update our records */

if (index == LC_ALL_INDEX_) {
unsigned int i;

/* For LC_ALL, we change all individual categories to correspond */
/* PL_curlocales is a parallel array, so has same
* length as 'categories' */
for (i = 0; i <= LC_ALL_INDEX_; i++) {
Safefree(PL_curlocales[i]);
PL_curlocales[i] = savepv(new_locale);
}
}
else {

/* Otherwise, update the single category, plus LC_ALL */
PERL_UNUSED_ARG(recalc_LC_ALL);

Safefree(PL_curlocales[index]);
PL_curlocales[index] = savepv(new_locale);
# else

if ( PL_curlocales[LC_ALL_INDEX_] == NULL
|| strNE(PL_curlocales[LC_ALL_INDEX_], new_locale))
{
Safefree(PL_curlocales[LC_ALL_INDEX_]);
PL_curlocales[LC_ALL_INDEX_] =
savepv(calculate_LC_ALL(PL_curlocales));
}
}
new_locale = update_PL_curlocales_i(index, new_locale, recalc_LC_ALL);

# endif
# ifdef HAS_GLIBC_LC_MESSAGES_BUG
Expand Down Expand Up @@ -1349,7 +1396,6 @@ S_calculate_LC_ALL(pTHX_ const char ** individ_locales)
const char * entry = individ_locales[i];
# endif

if (entry == NULL) continue; /* XXX Temporary */
names_len += strlen(category_names[i])
+ 1 /* '=' */
+ strlen(entry)
Expand All @@ -1371,7 +1417,6 @@ S_calculate_LC_ALL(pTHX_ const char ** individ_locales)
const char * entry = individ_locales[i];
# endif

if (entry == NULL) continue; /* XXX Temporary */
new_len = my_strlcat(aggregate_locale, category_names[i], names_len);
assert(new_len <= names_len);
new_len = my_strlcat(aggregate_locale, "=", names_len);
Expand Down Expand Up @@ -3959,9 +4004,10 @@ Perl_init_i18nl10n(pTHX_ int printwarn)
# ifdef USE_POSIX_2008_LOCALE

/* The stdized setlocales haven't affected the P2008 locales. Initialize
* them now, */
* them now, calculating LC_ALL only on the final go round, when all have
* been set. */
for (i = 0; i < NOMINAL_LC_ALL_INDEX; i++) {
void_setlocale_i(i, curlocales[i]);
(void) emulate_setlocale_i(i, curlocales[i], LOOPING);
}

# endif
Expand Down
5 changes: 4 additions & 1 deletion proto.h
Expand Up @@ -5155,13 +5155,16 @@ STATIC const char* S_stdize_locale(pTHX_ const int category, const char* input_l
STATIC const char* S_switch_category_locale_to_template(pTHX_ const int switch_category, const int template_category, const char * template_locale);
#define PERL_ARGS_ASSERT_SWITCH_CATEGORY_LOCALE_TO_TEMPLATE
# if defined(USE_POSIX_2008_LOCALE)
STATIC const char* S_emulate_setlocale_i(pTHX_ const unsigned int index, const char* new_locale);
STATIC const char* S_emulate_setlocale_i(pTHX_ const unsigned int index, const char* new_locale, const int recalc_LC_ALL);
#define PERL_ARGS_ASSERT_EMULATE_SETLOCALE_I
STATIC const char* S_my_querylocale_i(pTHX_ const unsigned int index);
#define PERL_ARGS_ASSERT_MY_QUERYLOCALE_I
STATIC const char * S_setlocale_from_aggregate_LC_ALL(pTHX_ const char * locale);
#define PERL_ARGS_ASSERT_SETLOCALE_FROM_AGGREGATE_LC_ALL \
assert(locale)
STATIC const char* S_update_PL_curlocales_i(pTHX_ const unsigned int index, const char * new_locale, int recalc_LC_ALL);
#define PERL_ARGS_ASSERT_UPDATE_PL_CURLOCALES_I \
assert(new_locale)
# endif
# if defined(USE_QUERYLOCALE)
STATIC const char * S_calculate_LC_ALL(pTHX_ const locale_t cur_obj);
Expand Down

0 comments on commit 015787f

Please sign in to comment.