News:

Want to praise Simutrans?
Your feedback is important for us ;D.

Printf order

Started by VS, June 06, 2011, 09:35:14 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

VS

Translators just love to change order of words, don't they...

It turns out that there is an easy way to make printf et al switch order of arguments - glibc already supports it by default everywhere, and Microsoft has that too. It's been there for at least 5 years already :)

Attached is a proof of concept patch that extends cbuffer_t with this functionality. I have tested only against MSVC, since there is no point with gcc - I tested this a few years ago and concluded that it indeed works with unpatched Simutrans (didn't know about MS support at the time).

To my best knowledge, there is not a target platform that does not support it. All Apple stuff is based on BSD or whatever Unix clone, so is Haiku, and Amiga uses GCC. So... discussion?

My projects... Tools for messing with Simutrans graphics. Graphic archive - templates and some other stuff for painters. Development logs for most recent information on what is going on. And of course pak128!

prissi

#1
MSVC does not really support reordering but some other features of this, at least the last time I tried.

According to the documents I found this is not a Posix feature. It is a feature of libc 6.x, so it may be present on all systems which are using the full libc. It might not work on iPhones etc. where often only reduce libc functionality is given, even with gcc.

BeOS/Haiku used gcc 2.95.xx and mingw stable gcc 3.4.5 and both did not support this last time (some years ago) when I tested. (I haven't tried to call _vsprintf_p from mingw however, which might work, since mingw calls anyway the msvc runtime lib.) For that reason I search for a portable small library, at that time without much success.

I will test and research this again, and if it works now on all our platforms, we can include it.

EDIT: Unfourtunately this patch misses still the many occasions where sprintf is still used to cobble the translated strings together ...

Tron

Quote from: VS on June 06, 2011, 09:35:14 PMAttached is a proof of concept patch that extends cbuffer_t with this functionality.
Does this patch solve something which
#ifdef _WIN32
# define vsnprintf _vsprintf_p
#endif

in utils/cbuffer_t.cc wouldn't? Am I missing something?

Quote from: VS on June 06, 2011, 09:35:14 PM[...] since there is no point with gcc [...]
gcc != libc and especially not glibc. It's not a matter of the compiler supporting this, it is only dependent on the used standard C library.

Quote from: prissi on June 09, 2011, 12:39:53 PMAccording to the documents I found this is not a Posix feature.
http://pubs.opengroup.org/onlinepubs/9699919799/functions/fprintf.html
Quote from: IEEE Std 1003.1-2008[...] Conversions can be applied to the nth argument [...] In this case, the conversion specifier character % (see below) is replaced by the sequence "%n$" [...]

VS

#3
Quote from: Tron on June 12, 2011, 05:26:16 AM
Does this patch solve something which
#ifdef _WIN32
# define vsnprintf _vsprintf_p
#endif

in utils/cbuffer_t.cc wouldn't? Am I missing something?
There are lots and lots of uses where it makes no sense, and it is slower... Only the "user facing" strings need this feature, and then again only some. Or so I think.

Quote from: Tron on June 12, 2011, 05:26:16 AM
gcc != libc and especially not glibc. It's not a matter of the compiler supporting this, it is only dependent on the used standard C library.
I didn't want to spend two paragraphs explaining that relationship, but I did actually check for glibc for all the targets. Sorry...

My projects... Tools for messing with Simutrans graphics. Graphic archive - templates and some other stuff for painters. Development logs for most recent information on what is going on. And of course pak128!

Tron

Quote from: VS on June 12, 2011, 12:58:57 PM
There are lots and lots of uses where it makes no sense, and it is slower... Only the "user facing" strings need this feature, and then again only some. Or so I think.
You don't have to use positional arguments. It's perfectly fine to pass a normal "%d" to _vsprintf_p(). For slower, there are a metric fuckton of reasons why Simutrans could be slow, this is not one of them and it is no reason to complicate string handling by having two functions doing almost (and on non-Windows entierly, which is a source of bugs) the same.

prissi

Ok, the Posix document leave my head scratching. Does this mean we can reliable print also int64 by using %lld since this is part of the posix specification? That would solve also some saving/loading issues with int64 and xml saving.

I changed already some of the sprintf's into buf.printf to prepare for the feature.

Tron

Quote from: prissi on June 12, 2011, 07:09:55 PMOk, the Posix document leave my head scratching.
Why's that so?

QuoteDoes this mean we can reliable print also int64 by using %lld since this is part of the posix specification?
As long as you stick to what both Posix and Windows support (and, specifically, if you assume that long long is exactly 64 bits wide).

TurfIt

MinGW does not like %lld... %I64d works.

prissi

#8
Aparently MinGW does also still not understand ordering:

#include <stdio.h>
#include <stdlib.h>

int main (int argc, char *argv[])
{
printf("%1$ld,%3$d,%2$d", 1234567891lu, (short)-1, (short)-3 );
}

Result:

prissi@SIMUTRANS ~/simutrans/simutrans
$ gcc test.cc
prissi@SIMUTRANS ~/simutrans/simutrans
$ a.exe
$ld,$d,$d
prissi@SIMUTRANS ~/simutrans/simutrans
$

Or did I do something wrong?

EDIT: I forgot, using the "-posix" switch just produced "%1$ld,%3$d,%2$d" which is still not the desired result.

EDIT2: Much more googling: http://www.gnu.org/software/gnulib/manual/html_node/printf.html and especially ther the two lines:
Quote
8.711 printf
...
- This function does not support size specifiers as in C99 (hh, ll, j, t, z) on some platforms: AIX 5.1, HP-UX 11.23, IRIX 6.5, OSF/1 5.1, Solaris 9, Cygwin 1.5.24, mingw, BeOS.
...
- This function does not support format directives that access arguments in an arbitrary order, such as "%2$s", on some platforms: NetBSD 3.0, mingw, BeOS.
So much for this patch ... (still having all sprintf to char [] eliminated could help to solve problems with overflows by translators and may prepare us for a better solution when present. One may even parse the string to buf.printf() by hand before passing it to other printf calls ...

Tron

Quote from: prissi on June 12, 2011, 09:53:28 PM
Aparently MinGW does also still not understand ordering:

#include <stdio.h>
#include <stdlib.h>

int main (int argc, char *argv[])
{
printf("%1$ld,%3$d,%2$d", 1234567891lu, (short)-1, (short)-3 );
}

Result:

prissi@SIMUTRANS ~/simutrans/simutrans
$ gcc test.cc
prissi@SIMUTRANS ~/simutrans/simutrans
$ a.exe
$ld,$d,$d
prissi@SIMUTRANS ~/simutrans/simutrans
$

Or did I do something wrong?
As clarified earlier, Windows has separate functions if you want to use argument positions. So in this case it is _printf_p().

By the way, the format specifier for an unsigned long (suffix UL, which you used), is %lu, not %ld. In this particular case it would work, because your number is sufficiently small, but a value >= 2^31 would give the wrong result.

VS

Quote from: prissi on June 12, 2011, 09:53:28 PM
One may even parse the string to buf.printf() by hand before passing it to other printf calls ...
I could try that, too...

My projects... Tools for messing with Simutrans graphics. Graphic archive - templates and some other stuff for painters. Development logs for most recent information on what is going on. And of course pak128!

prissi

#11
@tron:
Of course I tried _printf_p(). But MinGW does not know about these functions.

$ gcc test.cc
test.cc: In function `int main(int, char**)':
test.cc:9: error: `_printf_p' was not declared in this scope


MSVC does very well know this function ...

Some more googleling: _vsnprintf_p was introduced in XP.

Anyway, I programmed a poor mans version of vsnprintf_p which can do the trick on all systems. If you are sure you system has this funtionality, you can define "-DHAVE_UNIX98_PRINTF" which uses the normal library function.

Ters

Doesn't mingw get it's C runtime from msvcrt.dll? According to Wikipedia, this DLL is the C runtime for MSVC 4 though 6. Later versions of MSVC uses DLLs with the MSVC version in their name. This might mean that mingw is bound to the C library features of MSVC 6.

Maybe it's possible to tell mingw to use a different DLL?

prissi

Unfourtunately that version is not exported. Of course I can export any function from a DLL I like. But said function was introduced within MSVC 2005 SP2 with is a MSVC 7 version, and thus not part of MSVC 6.x runtime.

Moreover, mingw uses own printf library, but explicitely without parameter reordering.

VS

So, today I went to write a custom implementation... and it was already done! Thanks!

My projects... Tools for messing with Simutrans graphics. Graphic archive - templates and some other stuff for painters. Development logs for most recent information on what is going on. And of course pak128!