Skip to content

Commit

Permalink
Address GH Perl#20571
Browse files Browse the repository at this point in the history
The blamed commit, 04de022, exposed a bug in the module itself.  I will
submit a PR to fix it.

But this ticket did tell me that there was a problem with that commit.
It returned a C language value, CHAR_MAX, which doesn't really have a
corresponding concept in Perl.  Instead we use -1 to indicate that a
positive-valued variable is in some abnormal state.  This commit changes
to do that, and documents the changes, which should have been done in
04de022.
  • Loading branch information
khwilliamson committed Dec 18, 2022
1 parent 6f959d8 commit 42a2594
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 14 deletions.
2 changes: 1 addition & 1 deletion ext/POSIX/lib/POSIX.pm
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use warnings;

our ($AUTOLOAD, %SIGRT);

our $VERSION = '2.09';
our $VERSION = '2.10';

require XSLoader;

Expand Down
12 changes: 12 additions & 0 deletions ext/POSIX/lib/POSIX.pod
Original file line number Diff line number Diff line change
Expand Up @@ -1015,6 +1015,18 @@ Here is how to query the database for the B<de> (Deutsch or German) locale.
The members whose names begin with C<int_p_> and C<int_n_> were added by
POSIX.1-2008 and are only available on systems that support them.

A value of -1 returned for numeric entries indicates that the field is
not applicable to the locale. This is rare except in the C and related
locales, which don't have most monetary values defined. It can also
happen, quirkily, in fields that are otherwise boolean to indicate that
the value is kind of neither true nor false. This happens in C<p_cs_precedes>
and C<int_p_cs_precedes> when the currency symbol neither precedes nor
succeeds a positive value but is infixed, by replacing the radix
character.

Prior to Perl v5.37.7, empty string fields and numeric fields with value
-1 were omittted from the returned hash.

=item C<localtime>

This is identical to Perl's builtin C<localtime()> function for
Expand Down
54 changes: 41 additions & 13 deletions locale.c
Original file line number Diff line number Diff line change
Expand Up @@ -3519,15 +3519,21 @@ S_my_localeconv(pTHX_ const int item)

/* Here, the hash has been completely populated.
*
* Now go through all the string items and see if they should be marked as
* UTF-8 or not. This would have been more convenient and faster to do
* while populating the hash in the first place, but that operation has to
* be done within a critical section, keeping other threads from executing,
* so only the minimal amount of work necessary is done at that time.
* Now go through all the items and:
* a) For string items, see if they should be marked as UTF-8 or not.
* This would have been more convenient and faster to do while
* populating the hash in the first place, but that operation has to be
* done within a critical section, keeping other threads from
* executing, so only the minimal amount of work necessary is done at
* that time.
* b) For integer items, convert the C CHAR_MAX value into -1. Again,
* this could have been done in the critical section, but was deferred
* to here to keep to the bare minimum amount the time spent owning the
* processor. CHAR_MAX is a C concept for an 8-bit character type.
* Perl has no such type; the closest fit is a -1.
*
* XXX On unthreaded perls, and on platforms where localeconv (or
* localeconv_l if present) this code could be #ifdef'd out, and the
* UTF8ness determined at hash population time, at an extra maintenance
* XXX On unthreaded perls, this code could be #ifdef'd out, and the
* corrections determined at hash population time, at an extra maintenance
* cost which khw doesn't think is worth it
*/
for (unsigned int i = 0; i < 2; i++) { /* Try both types of strings */
Expand Down Expand Up @@ -3588,6 +3594,28 @@ S_my_localeconv(pTHX_ const int item)
}
} /* End of fixing up UTF8ness */


/* Examine each integer */
if (integers) while (1) {
const char * name = integers->name;

if (! name) { /* Reached the end */
break;
}

SV ** value = hv_fetch(hv, name, strlen(name), true);
if (! value) {
continue;
}

/* Change CHAR_MAX to -1 */
if (SvIV(*value) == CHAR_MAX) {
sv_setiv(*value, -1);
}

integers++; /* Iterate */
}

return hv;
}

Expand Down Expand Up @@ -4335,14 +4363,14 @@ S_my_langinfo_i(pTHX_

/* The modification is to prefix the localeconv() return with a
* single byte, calculated as follows: */
char prefix = (LIKELY(SvIV(precedes) != CHAR_MAX))
char prefix = (LIKELY(SvIV(precedes) != -1))
? ((precedes != 0) ? '-' : '+')

/* khw couldn't find any documentation that
* CHAR_MAX is the signal, but cygwin uses it
* thusly, and it makes sense given that CHAR_MAX
* indicates the value isn't used, so it neither
* precedes nor succeeds */
* CHAR_MAX (which we modify to -1) is the signal,
* but cygwin uses it thusly, and it makes sense
* given that CHAR_MAX indicates the value isn't
* used, so it neither precedes nor succeeds */
: '.';

/* Now get CRNCYSTR */
Expand Down
7 changes: 7 additions & 0 deletions pod/perldelta.pod
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,13 @@ L<Pod::Html> has been upgraded from version 1.33 to 1.34. Three auxiliary
subroutines previously importable from Pod::Html must now be imported from
Pod::Html::Util.

=item *

L<POSIX> has been upgraded from version 2.09 to 2.10. All fields known
to the platform in L<localeconv(3)> are now returned by
L<POSIX/localeconv>. Previously, empty string fields and numeric fields
that aren't applicable to the current locale were omitted.

=back

=head2 Removed Modules and Pragmata
Expand Down

0 comments on commit 42a2594

Please sign in to comment.