Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

locale.c: Fix compilation on platforms with only a C locale #22569

Merged
merged 1 commit into from
Sep 9, 2024

Conversation

the-horo
Copy link
Contributor

@the-horo the-horo commented Sep 4, 2024

Reported downstream in: https://bugs.gentoo.org/939014. The bug is about being impossible to bootstrap a Gentoo prefix with perl-5.40.0.

A Gentoo prefix is a Linux installation under some custom directory, modifiable by a non-root user. Bootstrapping such an installation starts with a host compiler and a shell and builds packages until the full installation is complete. Because of the nature of perl, it ends up being compiled relatively early during the whole process, before the installation is complete and the user has had the chance to select which locales to generate.

In this situation perl ends up being compiled on a bare system with only the C locale. The code in Configure

perl5/Configure

Lines 17672 to 17675 in 67e8521

if (distincts_count < C_ARRAY_LENGTH(categories)) {
fprintf(stderr, "Couldn't find a locale distinguishable from C\n");
return 1;
}
then exits early failing to prove the format of LC_ALL which then takes the second case branch

perl5/Configure

Lines 17812 to 17834 in 67e8521

output=`$run ./try 2>/dev/null`
separator=`echo "$output" | $sed 1q`
case $separator in
"\"=;\"")
d_perl_lc_all_uses_name_value_pairs="$define"
d_perl_lc_all_separator="$undef"
perl_lc_all_separator=
d_perl_lc_all_category_positions_init="$undef"
perl_lc_all_category_positions_init=
;;
"") d_perl_lc_all_uses_name_value_pairs="$undef"
d_perl_lc_all_separator="$undef"
perl_lc_all_separator=
d_perl_lc_all_category_positions_init="$undef"
perl_lc_all_category_positions_init=
;;
*) d_perl_lc_all_uses_name_value_pairs="$undef"
d_perl_lc_all_separator="$define"
perl_lc_all_separator="$separator"
d_perl_lc_all_category_positions_init="$define"
perl_lc_all_category_positions_init=`echo "$output" | sed -n 2p`
;;
esac
which makes all three of PERL_LC_ALL_USES_NAME_VALUE_PAIRS, PERL_LC_ALL_SEPARATOR, and PERL_LC_ALL_CATEGORY_POSITIONS_INIT end up being undefined. The locale.c code, however, assumes that either PERL_LC_ALL_USES_NAME_VALUE_PAIRS or the other two macros are defined which leads to a compilation failure because of the usage of PERL_LC_ALL_CATEGORY_POSITIONS_INIT:

x86_64-pc-linux-gnu-gcc -c -DPERL_CORE -O2 -pipe -O2 -pipe -fno-strict-aliasing -DNO_PERL_RAND_SEED -fwrapv -I/home/gabi/ghentu/usr/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -std=c99 -O2 -pipe -O2 -pipe -fno-strict-aliasing -Wall -Werror=pointer-arith -Werror=vla -Wextra -Wno-long-long -Wno-declaration-after-statement -Wc++-compat -Wwrite-strings -fPIC locale.c
locale.c: In function 'Perl_init_i18nl10n':
locale.c:8812:43: error: 'PERL_LC_ALL_CATEGORY_POSITIONS_INIT' undeclared (first use in this function)
 8812 |         int lc_all_category_positions[] = PERL_LC_ALL_CATEGORY_POSITIONS_INIT;
      |                                           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
locale.c:8812:43: note: each undeclared identifier is reported only once for each function it appears in

There is already code:

perl5/locale.c

Lines 649 to 658 in 67e8521

# else /* name=value */
/* In the, hopefully never occurring, event that the platform doesn't use
* either mechanism for disparate LC_ALL's, assume the name=value pairs
* form, rather than taking the extreme step of refusing to compile. Many
* programs won't have disparate locales, so will generally work */
# define PERL_LC_ALL_SEPARATOR ";"
# define is_disparate_LC_ALL(name) cBOOL( strchr(name, ';') \
&& strchr(name, '='))
# endif
that prevents compilation failures with missing PERL_LC_ALL_SEPARATOR. This is a similar situation in purpose but, because PERL_LC_ALL_CATEGORY_POSITIONS_INIT is suppose to be an array initializer and, if generated inside the code, it would require a #include "locale_table.h" I think it's simpler to replace its single usage point. The map_LC_ALL_position_to_index array should still be initialized, even with logically wrong values, to prevent possible out-of-bounds errors in other parts of the code.

Signed-off-by: Andrei Horodniceanu <a.horodniceanu@proton.me>
@thesamesam
Copy link

cc @khwilliamson

@khwilliamson
Copy link
Contributor

Thank you for this. I will also look into changing Configure to handle things so that this case doesn't arise. But it is a good fallback for Configure failures

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants