I finally figured out why XPM decoding is broken on my system.
It uses sort() to sort the colors, but a binary comparison in a quicksearch algorithm. sort() uses strcmp. strcmp doesn't sort in binary order on my system¹.
I thought it had something to do with large INT_TYPE, but now I'm convinced so isn't the case. This is the order I get:
... "*Y c #eecc22", "*Z c #ffcc22", "=` c #00dd22", "=. c #11dd22", "=+ c #22dd22", "=@ c #33dd22", "=# c #44dd22", ...
Note the '`' before '.'.
The bug makes the XPM module not find most of the colors, and thus rendering an almost completely black image.
Could we make the Pike sort()'s strcmp compare binary? Or does anyone feel up to fixing the XPM module?
(¹ appearantly, my default locale is good enough - the bug only appears if the main testsuite is run before. )
Huh? What is pike's "sort" here, and why would *any* operation on pike strings ever use strcmp rather than memcmp?
/ Niels Möller ()
Previous text:
2003-01-30 22:39: Subject: XPM and sort
I finally figured out why XPM decoding is broken on my system.
It uses sort() to sort the colors, but a binary comparison in a quicksearch algorithm. sort() uses strcmp. strcmp doesn't sort in binary order on my system¹.
I thought it had something to do with large INT_TYPE, but now I'm convinced so isn't the case. This is the order I get:
... "*Y c #eecc22", "*Z c #ffcc22", "=` c #00dd22", "=. c #11dd22", "=+ c #22dd22", "=@ c #33dd22", "=# c #44dd22", ...
Note the '`' before '.'.
The bug makes the XPM module not find most of the colors, and thus rendering an almost completely black image.
Could we make the Pike sort()'s strcmp compare binary? Or does anyone feel up to fixing the XPM module?
(¹ appearantly, my default locale is good enough - the bug only appears if the main testsuite is run before. )
/ Mirar
I guess one has to check the ANSI C standard to be sure, but at least the glibc manual says "The value returned has the same sign as the difference between the first differing pair of bytes (interpreted as `unsigned char' objects, then promoted to `int')."
/ Niels Möller ()
Previous text:
2003-01-31 12:14: Subject: XPM and sort
I belive memcmp compares bytes as unsigned on some systems and signed on others. Is that wrong?
/ Martin Nilsson (Åskblod)
Yes, that's what ANSI says, but it's not the way it's implemented in many cases...
/ Henrik Grubbström (Lysator)
Previous text:
2003-01-31 15:55: Subject: XPM and sort
I guess one has to check the ANSI C standard to be sure, but at least the glibc manual says "The value returned has the same sign as the difference between the first differing pair of bytes (interpreted as `unsigned char' objects, then promoted to `int')."
/ Niels Möller ()
Then bug report it... What odd system is it that we're talking about? Still mirar's glibc based system (I'd not expect the memcmp bug in glibs), or something more obscure?
/ Niels Möller ()
Previous text:
2003-01-31 23:16: Subject: XPM and sort
It apparently doesn't...
/ Henrik Grubbström (Lysator)
After some research, I can clearly see that memcmp isn't sorting binary either. But I don't know which operation in the main testsuite that makes it behave that way.
Right now I plan to do some research and add a configure test to spot the behaviour, and then undefine HAVE_MEMCMP if it's broken...
/ Mirar
Previous text:
2003-01-30 22:57: Subject: XPM and sort
Huh? What is pike's "sort" here, and why would *any* operation on pike strings ever use strcmp rather than memcmp?
/ Niels Möller ()
According to the docs, AC_FUNC_MEMCMP already detects some broken memcmp variants.
- Macro: AC_FUNC_MEMCMP If the `memcmp' function is not available, or does not work on 8-bit data (like the one on SunOS 4.1.3), or fails when comparing 16 bytes or more and with at least one buffer not starting on a 4-byte boundary (such as the one on NeXT x86 OpenStep), require an `AC_LIBOBJ' replacement for `memcmp'.
What kind of system are you running on?
/ Niels Möller ()
Previous text:
2003-01-31 08:11: Subject: XPM and sort
After some research, I can clearly see that memcmp isn't sorting binary either. But I don't know which operation in the main testsuite that makes it behave that way.
Right now I plan to do some research and add a configure test to spot the behaviour, and then undefine HAVE_MEMCMP if it's broken...
/ Mirar
Linux glibc-2.3.1-r2. But I have moved on from suspecting memcmp now.
/ Mirar
Previous text:
2003-01-31 08:38: Subject: XPM and sort
According to the docs, AC_FUNC_MEMCMP already detects some broken memcmp variants.
- Macro: AC_FUNC_MEMCMP If the `memcmp' function is not available, or does not work on 8-bit data (like the one on SunOS 4.1.3), or fails when comparing 16 bytes or more and with at least one buffer not starting on a 4-byte boundary (such as the one on NeXT x86 OpenStep), require an `AC_LIBOBJ' replacement for `memcmp'.
What kind of system are you running on?
/ Niels Möller ()
Aahrg, my mind is breaking up here.
The code snippet that needs to run to get XPM to break is, *drumroll*,
test_do([[ mixed eat_stack() { mixed err = 1; if (catch (err = eat_stack()) || err != 10) return intp (err) && err ? err + 1 : err; if (err = catch { class Foo { object foo; static void create(object o) {foo = o;} }; Foo foo; for(int i=0; i < 10000; i++) foo = Foo(foo); gc(); }) return err; }; if (mixed err = eat_stack()) throw (err); ]])
I found it through manual binary search. Every other test is commented out with dnl. If I comment out this one, XPM works again.
I'm starting to suspect that there is something other then memcmp that is funny here... I can't seem to find any way of forcing sort to behave, so I consider sort() as totally ok (for now). But I'm slowly going insane now, so don't trust me.
/ Mirar
Previous text:
2003-01-31 08:11: Subject: XPM and sort
After some research, I can clearly see that memcmp isn't sorting binary either. But I don't know which operation in the main testsuite that makes it behave that way.
Right now I plan to do some research and add a configure test to spot the behaviour, and then undefine HAVE_MEMCMP if it's broken...
/ Mirar
Ok, I'm getting somewhere now. This code breaks:
[_Image_XMP.pike] | if(sizeof(data) < ncolors+2) | error("Too few elements in array to decode color values\n"); | array colors; | if(cpp < 4) | colors = data[1..ncolors]; | else | colors = sort(data[1..ncolors]); | | // sort(colors); | // werror("cpp:%d\n",cpp);
If I add that extra sort, it sorts correctly and works. The werror reveals cpp to be 21 (not <4).
/ Mirar
Previous text:
2003-01-31 08:39: Subject: XPM and sort
Aahrg, my mind is breaking up here.
The code snippet that needs to run to get XPM to break is, *drumroll*,
test_do([[ mixed eat_stack() { mixed err = 1; if (catch (err = eat_stack()) || err != 10) return intp (err) && err ? err + 1 : err; if (err = catch { class Foo { object foo; static void create(object o) {foo = o;} }; Foo foo; for(int i=0; i < 10000; i++) foo = Foo(foo); gc(); }) return err; }; if (mixed err = eat_stack()) throw (err); ]])
I found it through manual binary search. Every other test is commented out with dnl. If I comment out this one, XPM works again.
I'm starting to suspect that there is something other then memcmp that is funny here... I can't seem to find any way of forcing sort to behave, so I consider sort() as totally ok (for now). But I'm slowly going insane now, so don't trust me.
/ Mirar
pike-devel@lists.lysator.liu.se