Skip to content

Fix langinfo(ALT_DIGITS) #21833

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

Merged
merged 2 commits into from
Jan 21, 2024
Merged

Fix langinfo(ALT_DIGITS) #21833

merged 2 commits into from
Jan 21, 2024

Conversation

khwilliamson
Copy link
Contributor

@khwilliamson khwilliamson commented Jan 15, 2024

This has never worked properly before in Perl. The code is returning
the result of the libc function nl_langinfo(). The documentation for it
that I have found (and presumably my predecessors) is very unclear. But
what actually happens (from using gdb) is that the return is very C
unfriendly.

Instead of returning a NUL-terminated string, it returns 100 (perhaps
fewer) NUL-terminated strings in a row. When it is fewer (given the
few examples I've seen), the final one ends with two NULs in a row. (I
can't think of a way for it to work and be otherwise). The 100th one
doesn't necessarily have two terminating NULs.

Prior to this commit, only the string for the zeroth digit was returned;
now the entire ALT_DIGIT string sequence is returned, forcing a double
NUL at the end of the final one.

This information is accessible in several ways. Via XS, one can use any
of several functions, including the newly introduced sv_langinfo(),
returning an SV, which allows for easier handling of embedded NULs.
(Otherwise in XS, using the functions that return a char*, one has to
look for the double-NUL.)

From Perl-space, the access is via I18N::Langinfo, which behind the
scenes also uses an SV. The documentation added in this commit gives
advice for how to turn the return into an @array for more convenient
access.

@khwilliamson khwilliamson force-pushed the alt_dig branch 2 times, most recently from d4df740 to 9e7376a Compare January 16, 2024 15:04
@tonycoz
Copy link
Contributor

tonycoz commented Jan 16, 2024

I found https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html when looking today:

ALT_DIGITS
The alternative symbols for digits, corresponding to the %O conversion specification modifier. The value consists of <semicolon>-separated symbols. The first is the alternative symbol corresponding to zero, the second is the symbol corresponding to one, and so on. Up to 100 alternative symbols may be specified.

though glibc doesn't follow this. (I don't expect any action on this comment)

@khwilliamson
Copy link
Contributor Author

I changed the comments inlocale.c based on @tonycoz findings, and I cleaned up the pod the Langinfo module. Otherwise there were no changes since his approval.

This and the next commit fix the incorrect behavior that perl has always
had for nl_langinfo(ALT_DIGITS).

If there are no alternate digits, an empty string is returned by
nl_langinfo when there are no such alternate digits.  This should also
be the case on platforms where we emulate nl_langinfo, but instead "0"
was being returned.  This commit makes things consistent.

The next commit adds tests
This has never worked properly before in Perl.  The code is returning
the result of the libc function nl_langinfo().  The documentation for it
that I have found (and presumably my predecessors) is very unclear.  But
what actually happens (from using gdb) is that the return is very C
unfriendly.

Instead of returning a NUL-terminated string, it returns 100 (perhaps
fewer) NUL-terminated strings in a row.  When it is fewer (given the
few examples I've seen), the final one ends with two NULs in a row.  (I
can't think of a way for it to work and be otherwise).  The 100th one
doesn't necessarily have two terminating NULs.

Prior to this commit, only the string for the zeroth digit was returned;
now the entire ALT_DIGIT string sequence is returned, forcing a double
NUL at the end of the final one.

This information is accessible in several ways.  Via XS, one can use any
of several functions, including the newly introduced sv_langinfo(),
returning an SV, which allows for easier handling of embedded NULs.
(Otherwise in XS, using the functions that return a char*, one has to
look for the double-NUL.)

From Perl-space, the access is via I18N::Langinfo, which behind the
scenes also uses an SV.  The documentation added in this commit gives
advice for how to turn the return into an @array for more convenient
access.
@tonycoz
Copy link
Contributor

tonycoz commented Jan 21, 2024

The glibc ALT_DIGITS bug is mentioned in passing here though this mostly talks about a similar bug with ERA.

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.

2 participants