Handle Linux extra locale categories

Linux has six locale categories that aren't in the POSIX standard.  This
commit enables their use.  For example there is meta data about a
locale, and information about how telephone numbers are formatted for
it.

On non-Linux boxes, you can now request them as well, but you will get
stub values, as if the locale were C.
This commit is contained in:
Karl Williamson 2024-01-16 13:12:53 -07:00
parent c23c19c029
commit 3c45ca2e15
10 changed files with 681 additions and 16 deletions

View File

@ -68,6 +68,46 @@ our @EXPORT_OK = qw(
T_FMT_AMPM
YESEXPR
YESSTR
_NL_ADDRESS_POSTAL_FMT
_NL_ADDRESS_COUNTRY_NAME
_NL_ADDRESS_COUNTRY_POST
_NL_ADDRESS_COUNTRY_AB2
_NL_ADDRESS_COUNTRY_AB3
_NL_ADDRESS_COUNTRY_CAR
_NL_ADDRESS_COUNTRY_NUM
_NL_ADDRESS_COUNTRY_ISBN
_NL_ADDRESS_LANG_NAME
_NL_ADDRESS_LANG_AB
_NL_ADDRESS_LANG_TERM
_NL_ADDRESS_LANG_LIB
_NL_IDENTIFICATION_TITLE
_NL_IDENTIFICATION_SOURCE
_NL_IDENTIFICATION_ADDRESS
_NL_IDENTIFICATION_CONTACT
_NL_IDENTIFICATION_EMAIL
_NL_IDENTIFICATION_TEL
_NL_IDENTIFICATION_FAX
_NL_IDENTIFICATION_LANGUAGE
_NL_IDENTIFICATION_TERRITORY
_NL_IDENTIFICATION_AUDIENCE
_NL_IDENTIFICATION_APPLICATION
_NL_IDENTIFICATION_ABBREVIATION
_NL_IDENTIFICATION_REVISION
_NL_IDENTIFICATION_DATE
_NL_IDENTIFICATION_CATEGORY
_NL_MEASUREMENT_MEASUREMENT
_NL_NAME_NAME_FMT
_NL_NAME_NAME_GEN
_NL_NAME_NAME_MR
_NL_NAME_NAME_MRS
_NL_NAME_NAME_MISS
_NL_NAME_NAME_MS
_NL_PAPER_HEIGHT
_NL_PAPER_WIDTH
_NL_TELEPHONE_TEL_INT_FMT
_NL_TELEPHONE_TEL_DOM_FMT
_NL_TELEPHONE_INT_SELECT
_NL_TELEPHONE_INT_PREFIX
);
our $VERSION = '0.23';
@ -209,6 +249,114 @@ For the eras based on typically some ruler, such as the Japanese Emperor
=back
In addition, Linux boxes have extra items, as follows. (When called from
other platform types, these return a stub value, of not much use.)
=over
=item C<_NL_ADDRESS_POSTAL_FMT>
=item C<_NL_ADDRESS_COUNTRY_NAME>
=item C<_NL_ADDRESS_COUNTRY_POST>
=item C<_NL_ADDRESS_COUNTRY_AB2>
=item C<_NL_ADDRESS_COUNTRY_AB3>
=item C<_NL_ADDRESS_COUNTRY_CAR>
=item C<_NL_ADDRESS_COUNTRY_NUM>
=item C<_NL_ADDRESS_COUNTRY_ISBN>
=item C<_NL_ADDRESS_LANG_NAME>
=item C<_NL_ADDRESS_LANG_AB>
=item C<_NL_ADDRESS_LANG_TERM>
=item C<_NL_ADDRESS_LANG_LIB>
On Linux boxes, these return information about the country for the current
locale. Further information is found in F<langinfo.h>
=item C<_NL_IDENTIFICATION_TITLE>
=item C<_NL_IDENTIFICATION_SOURCE>
=item C<_NL_IDENTIFICATION_ADDRESS>
=item C<_NL_IDENTIFICATION_CONTACT>
=item C<_NL_IDENTIFICATION_EMAIL>
=item C<_NL_IDENTIFICATION_TEL>
=item C<_NL_IDENTIFICATION_FAX>
=item C<_NL_IDENTIFICATION_LANGUAGE>
=item C<_NL_IDENTIFICATION_TERRITORY>
=item C<_NL_IDENTIFICATION_AUDIENCE>
=item C<_NL_IDENTIFICATION_APPLICATION>
=item C<_NL_IDENTIFICATION_ABBREVIATION>
=item C<_NL_IDENTIFICATION_REVISION>
=item C<_NL_IDENTIFICATION_DATE>
=item C<_NL_IDENTIFICATION_CATEGORY>
On Linux boxes, these return meta information about the current locale,
such as how to get in touch with its maintainers.
Further information is found in F<langinfo.h>
=item C<_NL_MEASUREMENT_MEASUREMENT>
On Linux boxes, it returns 1 if the metric system of measurement prevails in
the locale; or 2 if US customary units prevail.
=item C<_NL_NAME_NAME_FMT>
=item C<_NL_NAME_NAME_GEN>
=item C<_NL_NAME_NAME_MR>
=item C<_NL_NAME_NAME_MRS>
=item C<_NL_NAME_NAME_MISS>
=item C<_NL_NAME_NAME_MS>
On Linux boxes, these return information about how names are formatted and
the personal salutations used in the current locale. Further information
is found in L<locale(7)> and F<langinfo.h>
=item C<_NL_PAPER_HEIGHT>
=item C<_NL_PAPER_WIDTH>
On Linux boxes, these return the standard size of sheets of paper (in
millimeters) in the current locale.
=item C<_NL_TELEPHONE_TEL_INT_FMT>
=item C<_NL_TELEPHONE_TEL_DOM_FMT>
=item C<_NL_TELEPHONE_INT_SELECT>
=item C<_NL_TELEPHONE_INT_PREFIX>
On Linux boxes, these return information about how telephone numbers are
formatted (both domestically and international calling) in the current locale.
Further information is found in F<langinfo.h>
=back
=head2 For systems without C<nl_langinfo>
This module originally was just a wrapper for the libc C<nl_langinfo>
@ -275,6 +423,11 @@ L<https://github.com/Perl/perl5/issues>.
These are derived by using C<strftime()>, and not all versions of that function
know about them. C<""> is returned for these on such systems.
=item All C<_NL_I<foo>> items
These return the same values as they do on boxes that don't have the
appropriate underlying locale categories.
=back
See your L<nl_langinfo(3)> for more information about the available

View File

@ -26,15 +26,7 @@ langinfo(code)
int code
PROTOTYPE: _
CODE:
#ifdef HAS_NL_LANGINFO
if (code < 0) {
SETERRNO(EINVAL, LIB_INVARG);
RETVAL = &PL_sv_undef;
} else
#endif
{
RETVAL = sv_langinfo(code);
}
RETVAL = sv_langinfo(code);
OUTPUT:
RETVAL

View File

@ -14,7 +14,7 @@ WriteMakefile(
my @names = 'CODESET'; # CODESET isn't an enum in old glibc's langinfo.h
push @names, # This lot are always enums in old langinfo.h:
{name=>$_, type=>"IV",
macro=>["#if defined($_) || (defined(__GNU_LIBRARY__) && defined(_NL_ITEM))\n",
macro=>["#if defined($_) || (defined(_NL_ITEM))\n",
"#endif\n"]}
foreach qw (ABDAY_1 ABDAY_2 ABDAY_3 ABDAY_4 ABDAY_5 ABDAY_6 ABDAY_7
ABMON_1 ABMON_10 ABMON_11 ABMON_12 ABMON_2 ABMON_3 ABMON_4
@ -22,7 +22,48 @@ push @names, # This lot are always enums in old langinfo.h:
DAY_1 DAY_2 DAY_3 DAY_4 DAY_5 DAY_6 DAY_7 D_FMT D_T_FMT ERA
ERA_D_FMT ERA_D_T_FMT ERA_T_FMT MON_1 MON_10 MON_11 MON_12
MON_2 MON_3 MON_4 MON_5 MON_6 MON_7 MON_8 MON_9 NOEXPR NOSTR
PM_STR T_FMT T_FMT_AMPM YESEXPR YESSTR);
PM_STR T_FMT T_FMT_AMPM YESEXPR YESSTR
_NL_ADDRESS_POSTAL_FMT
_NL_ADDRESS_COUNTRY_NAME
_NL_ADDRESS_COUNTRY_POST
_NL_ADDRESS_COUNTRY_AB2
_NL_ADDRESS_COUNTRY_AB3
_NL_ADDRESS_COUNTRY_CAR
_NL_ADDRESS_COUNTRY_NUM
_NL_ADDRESS_COUNTRY_ISBN
_NL_ADDRESS_LANG_NAME
_NL_ADDRESS_LANG_AB
_NL_ADDRESS_LANG_TERM
_NL_ADDRESS_LANG_LIB
_NL_IDENTIFICATION_TITLE
_NL_IDENTIFICATION_SOURCE
_NL_IDENTIFICATION_ADDRESS
_NL_IDENTIFICATION_CONTACT
_NL_IDENTIFICATION_EMAIL
_NL_IDENTIFICATION_TEL
_NL_IDENTIFICATION_FAX
_NL_IDENTIFICATION_LANGUAGE
_NL_IDENTIFICATION_TERRITORY
_NL_IDENTIFICATION_AUDIENCE
_NL_IDENTIFICATION_APPLICATION
_NL_IDENTIFICATION_ABBREVIATION
_NL_IDENTIFICATION_REVISION
_NL_IDENTIFICATION_DATE
_NL_IDENTIFICATION_CATEGORY
_NL_MEASUREMENT_MEASUREMENT
_NL_NAME_NAME_FMT
_NL_NAME_NAME_GEN
_NL_NAME_NAME_MR
_NL_NAME_NAME_MRS
_NL_NAME_NAME_MISS
_NL_NAME_NAME_MS
_NL_PAPER_HEIGHT
_NL_PAPER_WIDTH
_NL_TELEPHONE_TEL_INT_FMT
_NL_TELEPHONE_TEL_DOM_FMT
_NL_TELEPHONE_INT_SELECT
_NL_TELEPHONE_INT_PREFIX
);
push @names, # This lot are only enums for __SVR4_I386_ABI_L1__:
{name=>$_, type=>"IV",
macro=>["#if defined($_) || (defined(__GNU_LIBRARY__) && defined(_NL_ITEM) && defined(__SVR4_I386_ABI_L1__))\n",

View File

@ -22,6 +22,13 @@ my %want = ( RADIXCHAR => qr/ ^ \. $ /x,
# these. In the C locale, there is nothing after the first
# character.
CRNCYSTR => qr/ ^ [+-.]? $ /x,
_NL_ADDRESS_COUNTRY_NUM => qr/^ 0 $/x,
_NL_IDENTIFICATION_TERRITORY => qr/ ^ ISO $/x,
_NL_MEASUREMENT_MEASUREMENT => qr/ ^ [01] $/x,
_NL_PAPER_HEIGHT => qr/^ \d+ $/x,
_NL_NAME_NAME_GEN => qr/ .* /x,
_NL_TELEPHONE_INT_SELECT => qr/ .* /x,
);
# Abbreviated and full are swapped in many locales in early netbsd. Skip
@ -145,7 +152,51 @@ sub check_utf8_validity($$$) {
my @want = sort keys %want;
my @illegal_utf8;
use_ok('I18N::Langinfo', 'langinfo', @constants, 'CRNCYSTR');
my %extra_items = (
_NL_ADDRESS_POSTAL_FMT => 'LC_ADDRESS',
_NL_ADDRESS_COUNTRY_NAME => 'LC_ADDRESS',
_NL_ADDRESS_COUNTRY_POST => 'LC_ADDRESS',
_NL_ADDRESS_COUNTRY_AB2 => 'LC_ADDRESS',
_NL_ADDRESS_COUNTRY_AB3 => 'LC_ADDRESS',
_NL_ADDRESS_COUNTRY_CAR => 'LC_ADDRESS',
_NL_ADDRESS_COUNTRY_NUM => 'LC_ADDRESS',
_NL_ADDRESS_COUNTRY_ISBN => 'LC_ADDRESS',
_NL_ADDRESS_LANG_NAME => 'LC_ADDRESS',
_NL_ADDRESS_LANG_AB => 'LC_ADDRESS',
_NL_ADDRESS_LANG_TERM => 'LC_ADDRESS',
_NL_ADDRESS_LANG_LIB => 'LC_ADDRESS',
_NL_IDENTIFICATION_TITLE => 'LC_IDENTIFICATION',
_NL_IDENTIFICATION_SOURCE => 'LC_IDENTIFICATION',
_NL_IDENTIFICATION_ADDRESS => 'LC_IDENTIFICATION',
_NL_IDENTIFICATION_CONTACT => 'LC_IDENTIFICATION',
_NL_IDENTIFICATION_EMAIL => 'LC_IDENTIFICATION',
_NL_IDENTIFICATION_TEL => 'LC_IDENTIFICATION',
_NL_IDENTIFICATION_FAX => 'LC_IDENTIFICATION',
_NL_IDENTIFICATION_LANGUAGE => 'LC_IDENTIFICATION',
_NL_IDENTIFICATION_TERRITORY => 'LC_IDENTIFICATION',
_NL_IDENTIFICATION_AUDIENCE => 'LC_IDENTIFICATION',
_NL_IDENTIFICATION_APPLICATION => 'LC_IDENTIFICATION',
_NL_IDENTIFICATION_ABBREVIATION => 'LC_IDENTIFICATION',
_NL_IDENTIFICATION_REVISION => 'LC_IDENTIFICATION',
_NL_IDENTIFICATION_DATE => 'LC_IDENTIFICATION',
_NL_IDENTIFICATION_CATEGORY => 'LC_IDENTIFICATION',
_NL_MEASUREMENT_MEASUREMENT => 'LC_MEASUREMENT',
_NL_NAME_NAME_FMT => 'LC_NAME',
_NL_NAME_NAME_GEN => 'LC_NAME',
_NL_NAME_NAME_MR => 'LC_NAME',
_NL_NAME_NAME_MRS => 'LC_NAME',
_NL_NAME_NAME_MISS => 'LC_NAME',
_NL_NAME_NAME_MS => 'LC_NAME',
_NL_PAPER_HEIGHT => 'LC_PAPER',
_NL_PAPER_WIDTH => 'LC_PAPER',
_NL_TELEPHONE_TEL_INT_FMT => 'LC_TELEPHONE',
_NL_TELEPHONE_TEL_DOM_FMT => 'LC_TELEPHONE',
_NL_TELEPHONE_INT_SELECT => 'LC_TELEPHONE',
_NL_TELEPHONE_INT_PREFIX => 'LC_TELEPHONE',
);
use_ok('I18N::Langinfo', 'langinfo', @constants, 'CRNCYSTR',
keys %extra_items);
use POSIX;

View File

@ -151,6 +151,46 @@ my %correct_C_responses = (
T_FMT_AMPM => undef,
YESEXPR => undef,
YESSTR => undef,
_NL_ADDRESS_POSTAL_FMT => undef,
_NL_ADDRESS_COUNTRY_NAME => undef,
_NL_ADDRESS_COUNTRY_POST => undef,
_NL_ADDRESS_COUNTRY_AB2 => undef,
_NL_ADDRESS_COUNTRY_AB3 => undef,
_NL_ADDRESS_COUNTRY_CAR => undef,
_NL_ADDRESS_COUNTRY_NUM => 0,
_NL_ADDRESS_COUNTRY_ISBN => undef,
_NL_ADDRESS_LANG_NAME => undef,
_NL_ADDRESS_LANG_AB => undef,
_NL_ADDRESS_LANG_TERM => undef,
_NL_ADDRESS_LANG_LIB => undef,
_NL_IDENTIFICATION_TITLE => undef,
_NL_IDENTIFICATION_SOURCE => undef,
_NL_IDENTIFICATION_ADDRESS => undef,
_NL_IDENTIFICATION_CONTACT => undef,
_NL_IDENTIFICATION_EMAIL => undef,
_NL_IDENTIFICATION_TEL => undef,
_NL_IDENTIFICATION_FAX => undef,
_NL_IDENTIFICATION_LANGUAGE => undef,
_NL_IDENTIFICATION_TERRITORY => "ISO",
_NL_IDENTIFICATION_AUDIENCE => undef,
_NL_IDENTIFICATION_APPLICATION => undef,
_NL_IDENTIFICATION_ABBREVIATION => undef,
_NL_IDENTIFICATION_REVISION => undef,
_NL_IDENTIFICATION_DATE => undef,
_NL_IDENTIFICATION_CATEGORY => undef,
_NL_MEASUREMENT_MEASUREMENT => undef,
_NL_NAME_NAME_FMT => undef,
_NL_NAME_NAME_GEN => undef,
_NL_NAME_NAME_MR => undef,
_NL_NAME_NAME_MRS => undef,
_NL_NAME_NAME_MISS => undef,
_NL_NAME_NAME_MS => undef,
_NL_PAPER_HEIGHT => undef,
_NL_PAPER_WIDTH => undef,
_NL_TELEPHONE_TEL_INT_FMT => undef,
_NL_TELEPHONE_TEL_DOM_FMT => undef,
_NL_TELEPHONE_INT_SELECT => undef,
_NL_TELEPHONE_INT_PREFIX => undef,
);
my $hdr = "../../perl_langinfo.h";

View File

@ -84,6 +84,46 @@ BEGIN {
ERA_T_FMT
T_FMT
T_FMT_AMPM
_NL_ADDRESS_POSTAL_FMT
_NL_ADDRESS_COUNTRY_NAME
_NL_ADDRESS_COUNTRY_POST
_NL_ADDRESS_COUNTRY_AB2
_NL_ADDRESS_COUNTRY_AB3
_NL_ADDRESS_COUNTRY_CAR
_NL_ADDRESS_COUNTRY_NUM
_NL_ADDRESS_COUNTRY_ISBN
_NL_ADDRESS_LANG_NAME
_NL_ADDRESS_LANG_AB
_NL_ADDRESS_LANG_TERM
_NL_ADDRESS_LANG_LIB
_NL_IDENTIFICATION_TITLE
_NL_IDENTIFICATION_SOURCE
_NL_IDENTIFICATION_ADDRESS
_NL_IDENTIFICATION_CONTACT
_NL_IDENTIFICATION_EMAIL
_NL_IDENTIFICATION_TEL
_NL_IDENTIFICATION_FAX
_NL_IDENTIFICATION_LANGUAGE
_NL_IDENTIFICATION_TERRITORY
_NL_IDENTIFICATION_AUDIENCE
_NL_IDENTIFICATION_APPLICATION
_NL_IDENTIFICATION_ABBREVIATION
_NL_IDENTIFICATION_REVISION
_NL_IDENTIFICATION_DATE
_NL_IDENTIFICATION_CATEGORY
_NL_MEASUREMENT_MEASUREMENT
_NL_NAME_NAME_FMT
_NL_NAME_NAME_GEN
_NL_NAME_NAME_MR
_NL_NAME_NAME_MRS
_NL_NAME_NAME_MISS
_NL_NAME_NAME_MS
_NL_PAPER_HEIGHT
_NL_PAPER_WIDTH
_NL_TELEPHONE_TEL_INT_FMT
_NL_TELEPHONE_TEL_DOM_FMT
_NL_TELEPHONE_INT_SELECT
_NL_TELEPHONE_INT_PREFIX
);
}
@ -1062,6 +1102,8 @@ my $locales_test_number;
my $not_necessarily_a_problem_test_number;
my $first_casing_test_number;
my %setlocale_failed; # List of locales that setlocale() didn't work on
my $has_glibc_extra_categories = grep { $_ =~ /^ _NL /x }
valid_locale_categories();
foreach my $Locale (@Locale) {
$locales_test_number = $first_locales_test_number - 1;
@ -1089,6 +1131,13 @@ foreach my $Locale (@Locale) {
for my $item (@langinfo) {
my $numeric_item = eval $item;
my $value = langinfo($numeric_item);
# All items should return a value; if not, this will warn. But on
# platforms without the extra categories, almost all items will be
# empty. Skip reporting such.
next if $value eq ""
&& $item =~ / ^ _NL_ / && ! $has_glibc_extra_categories;
debug "$item = " . disp_str($value);
}
}

269
locale.c
View File

@ -5975,6 +5975,82 @@ S_external_call_langinfo(pTHX_ const nl_item item,
break;
case _NL_ADDRESS_POSTAL_FMT:
case _NL_ADDRESS_COUNTRY_NAME:
case _NL_ADDRESS_COUNTRY_POST:
case _NL_ADDRESS_COUNTRY_AB2:
case _NL_ADDRESS_COUNTRY_AB3:
case _NL_ADDRESS_COUNTRY_CAR:
case _NL_ADDRESS_COUNTRY_NUM:
case _NL_ADDRESS_COUNTRY_ISBN:
case _NL_ADDRESS_LANG_NAME:
case _NL_ADDRESS_LANG_AB:
case _NL_ADDRESS_LANG_TERM:
case _NL_ADDRESS_LANG_LIB:
# ifdef USE_LOCALE_ADDRESS
cat_index = LC_ADDRESS_INDEX_;
# endif
break;
case _NL_IDENTIFICATION_TITLE:
case _NL_IDENTIFICATION_SOURCE:
case _NL_IDENTIFICATION_ADDRESS:
case _NL_IDENTIFICATION_CONTACT:
case _NL_IDENTIFICATION_EMAIL:
case _NL_IDENTIFICATION_TEL:
case _NL_IDENTIFICATION_FAX:
case _NL_IDENTIFICATION_LANGUAGE:
case _NL_IDENTIFICATION_TERRITORY:
case _NL_IDENTIFICATION_AUDIENCE:
case _NL_IDENTIFICATION_APPLICATION:
case _NL_IDENTIFICATION_ABBREVIATION:
case _NL_IDENTIFICATION_REVISION:
case _NL_IDENTIFICATION_DATE:
case _NL_IDENTIFICATION_CATEGORY:
# ifdef USE_LOCALE_IDENTIFICATION
cat_index = LC_IDENTIFICATION_INDEX_;
# endif
break;
case _NL_MEASUREMENT_MEASUREMENT:
# ifdef USE_LOCALE_MEASUREMENT
cat_index = LC_MEASUREMENT_INDEX_;
# endif
break;
case _NL_NAME_NAME_FMT:
case _NL_NAME_NAME_GEN:
case _NL_NAME_NAME_MR:
case _NL_NAME_NAME_MRS:
case _NL_NAME_NAME_MISS:
case _NL_NAME_NAME_MS:
# ifdef USE_LOCALE_NAME
cat_index = LC_NAME_INDEX_;
# endif
break;
case _NL_PAPER_HEIGHT:
case _NL_PAPER_WIDTH:
# ifdef USE_LOCALE_PAPER
cat_index = LC_PAPER_INDEX_;
# endif
break;
case _NL_TELEPHONE_TEL_INT_FMT:
case _NL_TELEPHONE_TEL_DOM_FMT:
case _NL_TELEPHONE_INT_SELECT:
case _NL_TELEPHONE_INT_PREFIX:
# ifdef USE_LOCALE_TELEPHONE
cat_index = LC_TELEPHONE_INDEX_;
# endif
break;
default: /* The other possible items are all in LC_TIME. */
# ifdef USE_LOCALE_TIME
cat_index = LC_TIME_INDEX_;
@ -6137,9 +6213,93 @@ S_langinfo_sv_i(pTHX_
* needed.) So, a copy of the result is made in this case as
* well.
*/
const char * retval = NULL;
/* Do a bit of extra work so avoid
* switch() { default: ... }
* where the only case in it is the default: */
# if defined(USE_LOCALE_PAPER) \
|| defined(USE_LOCALE_MEASUREMENT) \
|| defined(USE_LOCALE_ADDRESS)
# define IS_SWITCH 1
# define MAYBE_SWITCH(n) switch(n)
# else
# define IS_SWITCH 0
# define MAYBE_SWITCH(n)
# endif
GCC_DIAG_IGNORE_STMT(-Wimplicit-fallthrough);
MAYBE_SWITCH(item) {
# if defined(USE_LOCALE_MEASUREMENT)
case _NL_MEASUREMENT_MEASUREMENT:
{
/* An ugly API; only the first byte of the returned char* address means
* anything */
gwLOCALE_LOCK;
char char_value = nl_langinfo(item)[0];
gwLOCALE_UNLOCK;
sv_setuv(sv, char_value);
}
goto non_string_common;
# endif
# if defined(USE_LOCALE_ADDRESS) || defined(USE_LOCALE_PAPER)
# if defined(USE_LOCALE_ADDRESS)
case _NL_ADDRESS_COUNTRY_NUM:
/* FALLTHROUGH */
# endif
# if defined(USE_LOCALE_PAPER)
case _NL_PAPER_HEIGHT: case _NL_PAPER_WIDTH:
# endif
{ /* A slightly less ugly API; the int portion of the returned char*
* address is an integer. */
gwLOCALE_LOCK;
int int_value = (int) PTR2UV(nl_langinfo(item));
gwLOCALE_UNLOCK;
sv_setuv(sv, int_value);
}
# endif
# if IS_SWITCH
# if defined(USE_LOCALE_MEASUREMENT)
non_string_common:
# endif
/* In all cases that get here, the char* instead delivers a numeric
* value, so its UTF-8ness is meaningless */
if (sv == PL_scratch_langinfo) {
retval = SvPV_nomg_const_nolen(sv);
if (utf8ness) {
*utf8ness = UTF8NESS_IMMATERIAL;
}
}
break;
default:
# endif
/* The rest of the possibilities deliver a true char* pointer to a
* string (or sequence of strings in the case of ALT_DIGITS) */
gwLOCALE_LOCK;
const char * retval = nl_langinfo(item);
retval = nl_langinfo(item);
Size_t total_len = strlen(retval);
sv_setpvn(sv, retval, total_len);
@ -6156,6 +6316,9 @@ S_langinfo_sv_i(pTHX_
SvUTF8_on(sv);
}
}
}
GCC_DIAG_RESTORE_STMT;
restore_toggled_locale_i(cat_index, orig_switched_locale);
end_DEALING_WITH_MISMATCHED_CTYPE(locale)
@ -6163,6 +6326,8 @@ S_langinfo_sv_i(pTHX_
return retval;
}
# undef IS_SWITCH
# undef MAYBE_SWITCH
#endif
#ifndef HAS_DEFINITIVE_UTF8NESS_DETERMINATION
@ -6571,6 +6736,108 @@ S_emulate_langinfo(pTHX_ const int item,
# endif /* ! WIN32 */
# endif /* USE_LOCALE_CTYPE */
# endif
/* The _NL_foo items are mostly empty; the rest are copied from Ubuntu C
* locale values. khw fairly arbitrarily decided which of its non-empty
* values to copy and which to change to empty. All the numeric ones needed
* some value */
# if ! defined(HAS_SOME_LANGINFO) || ! LC_ADDRESS_AVAIL_
case _NL_ADDRESS_POSTAL_FMT:
case _NL_ADDRESS_COUNTRY_NAME:
case _NL_ADDRESS_COUNTRY_POST:
case _NL_ADDRESS_COUNTRY_AB2:
case _NL_ADDRESS_COUNTRY_AB3:
case _NL_ADDRESS_COUNTRY_CAR:
case _NL_ADDRESS_COUNTRY_ISBN:
case _NL_ADDRESS_LANG_NAME:
case _NL_ADDRESS_LANG_AB:
case _NL_ADDRESS_LANG_TERM:
case _NL_ADDRESS_LANG_LIB:
retval = "";
break;
case _NL_ADDRESS_COUNTRY_NUM:
sv_setuv(sv, 0);
retval_type = RETVAL_IN_sv;
break;
# endif
# if ! defined(HAS_SOME_LANGINFO) || ! LC_IDENTIFICATION_AVAIL_
case _NL_IDENTIFICATION_ADDRESS:
case _NL_IDENTIFICATION_CONTACT:
case _NL_IDENTIFICATION_EMAIL:
case _NL_IDENTIFICATION_TEL:
case _NL_IDENTIFICATION_FAX:
case _NL_IDENTIFICATION_LANGUAGE:
case _NL_IDENTIFICATION_AUDIENCE:
case _NL_IDENTIFICATION_APPLICATION:
case _NL_IDENTIFICATION_ABBREVIATION:
retval = "";
break;
case _NL_IDENTIFICATION_DATE: retval = "1997-12-20"; break;
case _NL_IDENTIFICATION_REVISION: retval = "1.0"; break;
case _NL_IDENTIFICATION_CATEGORY: retval = "i18n:1999"; break;
case _NL_IDENTIFICATION_TERRITORY:retval = "ISO"; break;
case _NL_IDENTIFICATION_TITLE:
retval = "ISO/IEC 14652 i18n FDCC-set";
break;
case _NL_IDENTIFICATION_SOURCE:
retval = "ISO/IEC JTC1/SC22/WG20 - internationalization";
break;
# endif
# if ! defined(HAS_SOME_LANGINFO) || ! LC_MEASUREMENT_AVAIL_
case _NL_MEASUREMENT_MEASUREMENT:
sv_setuv(sv, 1);
retval_type = RETVAL_IN_sv;
break;
# endif
# if ! defined(HAS_SOME_LANGINFO) || ! LC_NAME_AVAIL_
case _NL_NAME_NAME_FMT:
case _NL_NAME_NAME_GEN:
case _NL_NAME_NAME_MR:
case _NL_NAME_NAME_MRS:
case _NL_NAME_NAME_MISS:
case _NL_NAME_NAME_MS:
retval = "";
break;
# endif
# if ! defined(HAS_SOME_LANGINFO) || ! LC_PAPER_AVAIL_
case _NL_PAPER_HEIGHT:
sv_setuv(sv, 297);
retval_type = RETVAL_IN_sv;
break;
case _NL_PAPER_WIDTH:
sv_setuv(sv, 210);
retval_type = RETVAL_IN_sv;
break;
# endif
# if ! defined(HAS_SOME_LANGINFO) || ! LC_TELEPHONE_AVAIL_
case _NL_TELEPHONE_INT_SELECT:
case _NL_TELEPHONE_INT_PREFIX:
case _NL_TELEPHONE_TEL_DOM_FMT:
retval = "";
break;
case _NL_TELEPHONE_TEL_INT_FMT:
retval = "+%c %a %l";
break;
# endif
/* When we have to emulate TIME-related items, this bit of code is compiled

View File

@ -248,4 +248,74 @@ typedef int nl_item; /* Substitute 'int' for emulated nl_langinfo() */
# define HAS_MISSING_LANGINFO_ITEM_
#endif
/* The rest of the items are gnu extensions, and are not #defined by its
* langinfo.h. There is a slight possibility that one of these numbers could
* conflict with some other value, in which case after much gnashing of teeth
* you will find this comment, and end up having to adjust the numbers. But
* glibc values are not (so far) negative */
#if ! defined(HAS_NL_LANGINFO) || ! defined(LC_ADDRESS)
# define _NL_ADDRESS_POSTAL_FMT -58
# define _NL_ADDRESS_COUNTRY_NAME -59
# define _NL_ADDRESS_COUNTRY_POST -60
# define _NL_ADDRESS_COUNTRY_AB2 -61
# define _NL_ADDRESS_COUNTRY_AB3 -62
# define _NL_ADDRESS_COUNTRY_CAR -63
# define _NL_ADDRESS_COUNTRY_NUM -64
# define _NL_ADDRESS_COUNTRY_ISBN -65
# define _NL_ADDRESS_LANG_NAME -66
# define _NL_ADDRESS_LANG_AB -67
# define _NL_ADDRESS_LANG_TERM -68
# define _NL_ADDRESS_LANG_LIB -69
# define HAS_MISSING_LANGINFO_ITEM_
#endif
#if ! defined(HAS_NL_LANGINFO) || ! defined(LC_IDENTIFICATION)
# define _NL_IDENTIFICATION_TITLE -70
# define _NL_IDENTIFICATION_SOURCE -71
# define _NL_IDENTIFICATION_ADDRESS -72
# define _NL_IDENTIFICATION_CONTACT -73
# define _NL_IDENTIFICATION_EMAIL -74
# define _NL_IDENTIFICATION_TEL -75
# define _NL_IDENTIFICATION_FAX -76
# define _NL_IDENTIFICATION_LANGUAGE -77
# define _NL_IDENTIFICATION_TERRITORY -78
# define _NL_IDENTIFICATION_AUDIENCE -79
# define _NL_IDENTIFICATION_APPLICATION -80
# define _NL_IDENTIFICATION_ABBREVIATION -81
# define _NL_IDENTIFICATION_REVISION -82
# define _NL_IDENTIFICATION_DATE -83
# define _NL_IDENTIFICATION_CATEGORY -84
# define HAS_MISSING_LANGINFO_ITEM_
#endif
#if ! defined(HAS_NL_LANGINFO) || ! defined(LC_MEASUREMENT)
# define _NL_MEASUREMENT_MEASUREMENT -85
# define HAS_MISSING_LANGINFO_ITEM_
#endif
#if ! defined(HAS_NL_LANGINFO) || ! defined(LC_NAME)
# define _NL_NAME_NAME_FMT -86
# define _NL_NAME_NAME_GEN -87
# define _NL_NAME_NAME_MR -88
# define _NL_NAME_NAME_MRS -89
# define _NL_NAME_NAME_MISS -90
# define _NL_NAME_NAME_MS -91
# define HAS_MISSING_LANGINFO_ITEM_
#endif
#if ! defined(HAS_NL_LANGINFO) || ! defined(LC_PAPER)
# define _NL_PAPER_HEIGHT -92
# define _NL_PAPER_WIDTH -93
# define HAS_MISSING_LANGINFO_ITEM_
#endif
#if ! defined(HAS_NL_LANGINFO) || ! defined(LC_TELEPHONE)
# define _NL_TELEPHONE_TEL_INT_FMT -94
# define _NL_TELEPHONE_TEL_DOM_FMT -95
# define _NL_TELEPHONE_INT_SELECT -96
# define _NL_TELEPHONE_INT_PREFIX -97
# define HAS_MISSING_LANGINFO_ITEM_
#endif
#endif /* PERL_LANGINFO_H */

View File

@ -125,9 +125,10 @@ XXX Remove this section if Porting/corelist-perldelta.pl did not add any content
=item *
L<XXX> has been upgraded from version A.xx to B.yy.
L<I18N::Langinfo> has been upgraded from version 0.22 to 0.23.
XXX If there was something important to note about this change, include that here.
It now handles the additional locale categories that Linux defines
beyond those in the POSIX Standard.
=back

View File

@ -1,4 +1,4 @@
# This file is the data file for porting/podcheck.t.
# This file is the data file for t/porting/podcheck.t.
# There are three types of lines.
# Comment lines are white-space only or begin with a '#', like this one. Any
# changes you make to the comment lines will be lost when the file is
@ -188,6 +188,7 @@ Lingua::ZH::Romanize::Pinyin
List::Gather
listen(2)
local::lib
locale(7)
Locale::Codes
Locale::Country
Locale::Language