Skip to content

Commit f741678

Browse files
committed
Add API function Perl_langinfo()
This is designed to generally replace nl_langinfo() in XS code. It is thread-safer, hides the quirks of perl's LC_NUMERIC handling, and can be used on systems lacking nl_langinfo.
1 parent 97a3682 commit f741678

14 files changed

+1096
-54
lines changed

MANIFEST

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4896,6 +4896,7 @@ parser.h parser object header
48964896
patchlevel.h The current patch level of perl
48974897
perl.c main()
48984898
perl.h Global declarations
4899+
perl_langinfo.h Perl's version of <langinfo.h>
48994900
perlapi.c Perl API functions
49004901
perlapi.h Perl API function declarations
49014902
perldtrace.d D script for Perl probes

embed.fnc

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1259,6 +1259,11 @@ ApdO |HV* |get_hv |NN const char *name|I32 flags
12591259
ApdO |CV* |get_cv |NN const char* name|I32 flags
12601260
Apd |CV* |get_cvn_flags |NN const char* name|STRLEN len|I32 flags
12611261
EXnpo |char* |setlocale |int category|NULLOK const char* locale
1262+
#if defined(HAS_NL_LANGINFO) && defined(PERL_LANGINFO_H)
1263+
Ando |const char*|Perl_langinfo|const nl_item item
1264+
#else
1265+
Ando |const char*|Perl_langinfo|const int item
1266+
#endif
12621267
ApOM |int |init_i18nl10n |int printwarn
12631268
ApOM |int |init_i18nl14n |int printwarn
12641269
p |char* |my_strerror |const int errnum
@@ -2718,15 +2723,20 @@ s |bool |isa_lookup |NN HV *stash|NN const char * const name \
27182723
|STRLEN len|U32 flags
27192724
#endif
27202725

2721-
#if defined(USE_LOCALE) && defined(PERL_IN_LOCALE_C)
2726+
#if defined(PERL_IN_LOCALE_C)
2727+
in |const char *|save_to_buffer|NN const char * string \
2728+
|NULLOK char **buf \
2729+
|NN Size_t *buf_size \
2730+
|const Size_t offset
2731+
# if defined(USE_LOCALE)
27222732
s |char* |stdize_locale |NN char* locs
27232733
s |void |new_collate |NULLOK const char* newcoll
27242734
s |void |new_ctype |NN const char* newctype
27252735
s |void |set_numeric_radix
2726-
#ifdef WIN32
2736+
# ifdef WIN32
27272737
s |char* |my_setlocale |int category|NULLOK const char* locale
2728-
#endif
2729-
# ifdef DEBUGGING
2738+
# endif
2739+
# ifdef DEBUGGING
27302740
s |void |print_collxfrm_input_and_return \
27312741
|NN const char * const s \
27322742
|NN const char * const e \
@@ -2738,7 +2748,8 @@ s |void |print_bytes_for_locale |NN const char * const s \
27382748
snR |char * |setlocale_debug_string |const int category \
27392749
|NULLOK const char* const locale \
27402750
|NULLOK const char* const retval
2741-
# endif
2751+
# endif
2752+
# endif
27422753
#endif
27432754

27442755
#if defined(USE_LOCALE) \

embed.h

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1478,6 +1478,13 @@
14781478
# if defined(DEBUGGING)
14791479
#define get_debug_opts(a,b) Perl_get_debug_opts(aTHX_ a,b)
14801480
#define set_padlist Perl_set_padlist
1481+
# if defined(PERL_IN_LOCALE_C)
1482+
# if defined(USE_LOCALE)
1483+
#define print_bytes_for_locale(a,b,c) S_print_bytes_for_locale(aTHX_ a,b,c)
1484+
#define print_collxfrm_input_and_return(a,b,c,d) S_print_collxfrm_input_and_return(aTHX_ a,b,c,d)
1485+
#define setlocale_debug_string S_setlocale_debug_string
1486+
# endif
1487+
# endif
14811488
# if defined(PERL_IN_PAD_C)
14821489
#define cv_dump(a,b) S_cv_dump(aTHX_ a,b)
14831490
# endif
@@ -1488,11 +1495,6 @@
14881495
#define printbuf(a,b) S_printbuf(aTHX_ a,b)
14891496
#define tokereport(a,b) S_tokereport(aTHX_ a,b)
14901497
# endif
1491-
# if defined(USE_LOCALE) && defined(PERL_IN_LOCALE_C)
1492-
#define print_bytes_for_locale(a,b,c) S_print_bytes_for_locale(aTHX_ a,b,c)
1493-
#define print_collxfrm_input_and_return(a,b,c,d) S_print_collxfrm_input_and_return(aTHX_ a,b,c,d)
1494-
#define setlocale_debug_string S_setlocale_debug_string
1495-
# endif
14961498
# endif
14971499
# if defined(DEBUG_LEAKING_SCALARS_FORK_DUMP)
14981500
#define dump_sv_child(a) Perl_dump_sv_child(aTHX_ a)
@@ -1591,6 +1593,18 @@
15911593
#define share_hek_flags(a,b,c,d) S_share_hek_flags(aTHX_ a,b,c,d)
15921594
#define unshare_hek_or_pvn(a,b,c,d) S_unshare_hek_or_pvn(aTHX_ a,b,c,d)
15931595
# endif
1596+
# if defined(PERL_IN_LOCALE_C)
1597+
#define save_to_buffer S_save_to_buffer
1598+
# if defined(USE_LOCALE)
1599+
#define new_collate(a) S_new_collate(aTHX_ a)
1600+
#define new_ctype(a) S_new_ctype(aTHX_ a)
1601+
#define set_numeric_radix() S_set_numeric_radix(aTHX)
1602+
#define stdize_locale(a) S_stdize_locale(aTHX_ a)
1603+
# if defined(WIN32)
1604+
#define my_setlocale(a,b) S_my_setlocale(aTHX_ a,b)
1605+
# endif
1606+
# endif
1607+
# endif
15941608
# if defined(PERL_IN_LOCALE_C) || defined(PERL_IN_SV_C) || defined(PERL_IN_MATHOMS_C)
15951609
# if defined(USE_LOCALE_COLLATE)
15961610
#define _mem_collxfrm(a,b,c,d) Perl__mem_collxfrm(aTHX_ a,b,c,d)
@@ -1882,15 +1896,6 @@
18821896
#define padname_dup(a,b) Perl_padname_dup(aTHX_ a,b)
18831897
#define padnamelist_dup(a,b) Perl_padnamelist_dup(aTHX_ a,b)
18841898
# endif
1885-
# if defined(USE_LOCALE) && defined(PERL_IN_LOCALE_C)
1886-
#define new_collate(a) S_new_collate(aTHX_ a)
1887-
#define new_ctype(a) S_new_ctype(aTHX_ a)
1888-
#define set_numeric_radix() S_set_numeric_radix(aTHX)
1889-
#define stdize_locale(a) S_stdize_locale(aTHX_ a)
1890-
# if defined(WIN32)
1891-
#define my_setlocale(a,b) S_my_setlocale(aTHX_ a,b)
1892-
# endif
1893-
# endif
18941899
# if defined(USE_LOCALE_COLLATE)
18951900
#define magic_setcollxfrm(a,b) Perl_magic_setcollxfrm(aTHX_ a,b)
18961901
#ifndef NO_MATHOMS

embedvar.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,8 @@
176176
#define PL_inplace (vTHX->Iinplace)
177177
#define PL_isarev (vTHX->Iisarev)
178178
#define PL_known_layers (vTHX->Iknown_layers)
179+
#define PL_langinfo_buf (vTHX->Ilanginfo_buf)
180+
#define PL_langinfo_bufsize (vTHX->Ilanginfo_bufsize)
179181
#define PL_last_in_gv (vTHX->Ilast_in_gv)
180182
#define PL_last_swash_hv (vTHX->Ilast_swash_hv)
181183
#define PL_last_swash_key (vTHX->Ilast_swash_key)

ext/XS-APItest/APItest.pm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use strict;
55
use warnings;
66
use Carp;
77

8-
our $VERSION = '0.91';
8+
our $VERSION = '0.92';
99

1010
require XSLoader;
1111

ext/XS-APItest/APItest.xs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6544,6 +6544,13 @@ test_Gconvert(SV * number, SV * num_digits)
65446544
OUTPUT:
65456545
RETVAL
65466546

6547+
SV *
6548+
test_Perl_langinfo(SV * item)
6549+
CODE:
6550+
RETVAL = newSVpv(Perl_langinfo(SvIV(item)), 0);
6551+
OUTPUT:
6552+
RETVAL
6553+
65476554
MODULE = XS::APItest PACKAGE = XS::APItest::Backrefs
65486555

65496556
void

ext/XS-APItest/t/locale.t

Lines changed: 103 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,6 @@ for (@locales) {
2222
}
2323
}
2424

25-
skip_all("no non-dot radix locales available") unless $non_dot_locale;
26-
27-
plan tests => 2;
2825

2926
SKIP: {
3027
if ($Config{usequadmath}) {
@@ -34,3 +31,106 @@ SKIP: {
3431
use locale;
3532
is(test_Gconvert(4.179, 2), "4.2", "Gconvert doesn't recognize underlying locale inside 'use locale'");
3633
}
34+
35+
my %correct_C_responses = (
36+
# Commented out entries are ones which there is room for variation
37+
ABDAY_1 => 'Sun',
38+
ABDAY_2 => 'Mon',
39+
ABDAY_3 => 'Tue',
40+
ABDAY_4 => 'Wed',
41+
ABDAY_5 => 'Thu',
42+
ABDAY_6 => 'Fri',
43+
ABDAY_7 => 'Sat',
44+
ABMON_1 => 'Jan',
45+
ABMON_10 => 'Oct',
46+
ABMON_11 => 'Nov',
47+
ABMON_12 => 'Dec',
48+
ABMON_2 => 'Feb',
49+
ABMON_3 => 'Mar',
50+
ABMON_4 => 'Apr',
51+
ABMON_5 => 'May',
52+
ABMON_6 => 'Jun',
53+
ABMON_7 => 'Jul',
54+
ABMON_8 => 'Aug',
55+
ABMON_9 => 'Sep',
56+
ALT_DIGITS => '',
57+
AM_STR => 'AM',
58+
#CODESET => 'ANSI_X3.4-1968',
59+
#CRNCYSTR => '-',
60+
DAY_1 => 'Sunday',
61+
DAY_2 => 'Monday',
62+
DAY_3 => 'Tuesday',
63+
DAY_4 => 'Wednesday',
64+
DAY_5 => 'Thursday',
65+
DAY_6 => 'Friday',
66+
DAY_7 => 'Saturday',
67+
#D_FMT => '%m/%d/%y',
68+
#D_T_FMT => '%a %b %e %H:%M:%S %Y',
69+
ERA => '',
70+
#ERA_D_FMT => '',
71+
#ERA_D_T_FMT => '',
72+
#ERA_T_FMT => '',
73+
MON_1 => 'January',
74+
MON_10 => 'October',
75+
MON_11 => 'November',
76+
MON_12 => 'December',
77+
MON_2 => 'February',
78+
MON_3 => 'March',
79+
MON_4 => 'April',
80+
MON_5 => 'May',
81+
MON_6 => 'June',
82+
MON_7 => 'July',
83+
MON_8 => 'August',
84+
MON_9 => 'September',
85+
#NOEXPR => '^[nN]',
86+
PM_STR => 'PM',
87+
RADIXCHAR => '.',
88+
THOUSEP => '',
89+
#T_FMT => '%H:%M:%S',
90+
#T_FMT_AMPM => '%I:%M:%S %p',
91+
#YESEXPR => '^[yY]',
92+
);
93+
94+
my $hdr = "../../perl_langinfo.h";
95+
open my $fh, "<", $hdr;
96+
$|=1;
97+
98+
SKIP: {
99+
skip "No LC_ALL", 1 unless find_locales( &LC_ALL );
100+
101+
use POSIX;
102+
setlocale(LC_ALL, "C");
103+
eval "use I18N::Langinfo qw(langinfo RADIXCHAR); langinfo(RADIXCHAR)";
104+
my $has_nl_langinfo = $@ eq "";
105+
106+
skip "Can't open $hdr for reading: $!", 1 unless $fh;
107+
108+
my %items;
109+
110+
# Find all the current items from the header, and their values.
111+
# For non-nl_langinfo systems, those values are arbitrary negative numbers
112+
# set in the header. Otherwise they are the nl_langinfo approved values,
113+
# which for the moment is the item name.
114+
while (<$fh>) {
115+
chomp;
116+
next unless / - \d+ $ /x;
117+
s/ ^ .* PERL_//x;
118+
m/ (.*) \ (.*) /x;
119+
$items{$1} = ($has_nl_langinfo)
120+
? $1
121+
: $2;
122+
}
123+
124+
# Get the translation from item name to numeric value.
125+
I18N::Langinfo->import(keys %items) if $has_nl_langinfo;
126+
127+
foreach my $item (sort keys %items) {
128+
my $result = test_Perl_langinfo(eval $items{$item});
129+
if (exists $correct_C_responses{$item}) {
130+
is ($result, $correct_C_responses{$item},
131+
"Returns expected value for $item");
132+
}
133+
}
134+
}
135+
136+
done_testing();

intrpvar.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,9 @@ PERLVARI(I, collation_standard, bool, TRUE)
588588
/* Assume simple collation */
589589
#endif /* USE_LOCALE_COLLATE */
590590

591+
PERLVARI(I, langinfo_buf, char *, NULL)
592+
PERLVARI(I, langinfo_bufsize, Size_t, 0)
593+
591594
#ifdef PERL_SAWAMPERSAND
592595
PERLVAR(I, sawampersand, U8) /* must save all match strings */
593596
#endif

0 commit comments

Comments
 (0)