Обсуждение: MinGW / Windows / printf format specifiers

Поиск
Список
Период
Сортировка

MinGW / Windows / printf format specifiers

От
Chapman Flack
Дата:
So I announce a PL/Java 1.5.0-BETA1 with a comment that windows-MSVC
was well tested but that I hadn't found anyone to test windows-mingw,
and behold, what should happen but someone turns up with an interest
in testing the mingw build, so we might have that back in shape as
well for -BETA2.

Haven't run into any showstoppers, but gcc is issuing printf-format
warnings in three places where JNI values of type jint or jlong are
printed.

The cause seems to be that Windows conventions have int = long = int32
(even on 64-bit platforms) and only 'long long' = int64. The Java JNI
headers of course know this, so they type jlong as 'long long', while
jint they type as 'long' - curiously, because they could just call it
int and get the same width. Maybe a habit from a 16-bit C environment?

gcc warns about %ld used with a jlong argument (and it is right,
because for Windows that really should be %lld or %I64d).

It also complains about %d used with a jint argument (a bit spuriously,
because it wants to see %d paired with 'int' while 'jint' is typed as
'long', producing a warning _even though those have the same width_).

I'm familiar with a common way of handling this using a macro like
PRId64 that expands to the correct printf format code on each platform
(printf("My value is %10" PRId64 "\n", v)) ... which then becomes a
potential localization headache because if the format string is the
message key, it's now not the same between platforms.

In my particular case, PL/Java has never had any localization effort
yet, and the only affected sites right now are two debug messages and
one error, not places where the urgency to localize burns hottest.

But if others here have already considered these issues and settled
on a good approach, I'd be happy to not spend time inventing another.

I found some of the printf format specifier differences, Windows to
other platforms, described well in this StackOverflow thread:

http://stackoverflow.com/questions/6299083/cross-platform-printing-of-64-bit-integers-with-printf

And the MinGW wiki has a directly relevant page:

https://sourceforge.net/p/mingw-w64/wiki2/gnu%20printf/

They provide their own printf that supports %lld (you can get it by
default by defining __USE_MINGW_ANSI_STDIO) ... and, to avoid
spurious compiler warnings, they also define a macro __MINGW_PRINTF_FORMAT
that can be used in __attribute__((__format__ ...))) so gcc's format
checker applies the right checks.

Have issues like this been dealt with in PostgreSQL code before, and did
a favorite approach emerge?

-Chap



Re: MinGW / Windows / printf format specifiers

От
Craig Ringer
Дата:
On 19 February 2016 at 12:15, Chapman Flack <chap@anastigmatix.net> wrote:
 

The cause seems to be that Windows conventions have int = long = int32
(even on 64-bit platforms) and only 'long long' = int64.

Yes, it's an LLP64 platform.

 
The Java JNI
headers of course know this, so they type jlong as 'long long', while
jint they type as 'long' - curiously, because they could just call it
int and get the same width. Maybe a habit from a 16-bit C environment?

They should be using the (u)int(nn)_t typedefs like int64_t, but some compilers lag in their support for them.
 
Have issues like this been dealt with in PostgreSQL code before, and did
a favorite approach emerge?

INT64_FORMAT and UINT64_FORMAT

src/include/c.h 

git grep INT64_FORMAT


--
 Craig Ringer                   http://www.2ndQuadrant.com/
 PostgreSQL Development, 24x7 Support, Training & Services

Re: MinGW / Windows / printf format specifiers

От
Tom Lane
Дата:
Craig Ringer <craig@2ndquadrant.com> writes:
> On 19 February 2016 at 12:15, Chapman Flack <chap@anastigmatix.net> wrote:
>> Have issues like this been dealt with in PostgreSQL code before, and did
>> a favorite approach emerge?

> INT64_FORMAT and UINT64_FORMAT

Yeah.  Note in particular the convention to avoid using those in
translatable strings.  Where necessary, we manage that by using
sprintf(INT64_FORMAT) into a buffer variable and then printing
the buffer with %s in the translatable message.  Grotty, but there
seems no other way that doesn't result in platform-dependent
translatable strings.
        regards, tom lane