Archive for March, 2004

List moderator magic

Wednesday, March 31st, 2004

I spent some time floundering about a while ago trying to figure out a
Javascript hack to allow you to mark all mails in a mailman moderation
queue to be discarded. I certainly wasn’t going to manually click
“Discard” for each of the 400 mails in the gconf-list queue.

DV saved me with some
jamesh magic.

Mailing list admins, bookmark this link –
Discard all mails

(No, don’t click on the link. Right-click, “Bookmark link…”)

St. Patrick’s Day

Wednesday, March 17th, 2004

Recipe for a nice relaxing Paddy’s day:

  • Long walk by the sea to clear the hangover.
  • Cook gorgeous Thai Red Curry. Eat.
  • Snooze.
  • Bake a lemon cake. Eat.
  • Add wireless support to gnome-netstatus:

    Calum is the one responsible for the UI. I just did the fun hack :-)

There be divils here

Thursday, March 11th, 2004

I reckon a lot of hackers don’t realise how wary they need to
be when using enums. Problems occur frequently because people
(usually unwittingly) make assumptions about either the size,
alignment or signedness of the integer representation for the
enum which the compiler uses.

C99 says Each enumerated type shall be compatible with
an integer type. The choice of type is implementation-defined.
An implementation may delay the choice of which integer type
until all enumeration constants have been seen
. What
this means is that once the compiler has seen all the constants
you have defined for that enum, it will then decide what integer
representation to use and that could be a signed or unsigned
integer of any size.

So, GNOME hackers beware. gconf_enum_to_string() is
nasty. Have a look at the prototype:

gboolean  gconf_string_to_enum (GConfEnumStringPair  lookup_table[],
                                const gchar         *str,
                                gint                *enum_value_retloc);
  

Bugs I’ve seen include:

{
  enum { A, B } test_enum;

  gconf_enum_to_string (enum_to_str_table, str, (int *) &test_enum);
}
  

This is guaranteed to cause crashes on some architectures since
alignment of the enum is different from the expected
alignment of an int. So it should be:

{
  enum { A, B } test_enum;
  int test_int;

  if (gconf_enum_to_string (enum_to_str_table, str, &test_int))
    {
      test_enum = test_int;
    }
}
  

Also, this breaks:

{
enum { A, B } test_enum;
int test_int;

test_enum = -1;
gconf_enum_to_string (enum_to_str_table, str, &test_int);
test_enum = test_int;

if (test_enum
The problem here is that you're assuming the enum has a signed
representation when in fact the compiler may choose an unsigned
representation. If the conversion fails, if (test_enum
will not detect it.

Alex also points out that when adding values to an enum in an API
you need to be careful that you're not unwittingly changing the
ABI because the compiler chooses to use a large integer representation
for the enum than was previously used.