Обсуждение: MinGW / Windows / printf format specifiers
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
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 <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