hubertf's NetBSD Blog
Send interesting links to hubert at feyrer dot de!
 
[20051221] Tripping over not-so-standard standard types
Well, or maybe just non-standard use of them. Trying to build qemu 0.8 today (with SMP for i386 and sparc!), I tripped over some evil code that builds symbols from types using some extended cpp(1) magic:
 #define IN_T int8_t
 
 ...
 
 #define ET glue (ENDIAN_CONVERSION, glue (_, IN_T))
 
 ...
 
 static void glue (glue (conv_, ET), _to_mono)
     (st_sample_t *dst, const void *src, int samples, volume_t *vol)
 { ... }
 
 t_sample *mixeng_conv[2][2][2][2] = {
     { 
         {
             {
 		conv_natural_uint8_t_to_mono,
 		conv_natural_uint16_t_to_mono
 	    }
 	    ...  
(Some data ommitted, see audio/mixeng.c and audio/mixeng_template.h).
This led to fireworks, as conv_natural___uint8_t_to_mono was not defined - note the two extra underscores!

As it turns out, the NetBSD 2.x system I did this on actually has uint8_t (and others) as a #define to the corresponding types with __, which then leads to the above effect. Of course the right way is not to use #define but typedef here, but upgrading to NetBSD 3.0 (which does the right thing) is not an option right now).

So I tried to come up with some equally evil cpp(1) magic to expand the symbol in the second place, replacing:

 	conv_natural_uint8_t_to_mono,
 	conv_natural_uint16_t_to_mono 
with
 	NBglue(conv_natural_, uint8_t, _to_mono),
 	NBglue(conv_natural_, uint16_t, _to_mono) 
the idea here was to add a
 	#define NBglue(x,y,z) x ## y ## z 
that does the right thing, but it didn't - the "y" symbol was not expanded by cpp(1)! I tried a second version:
 	#define NBexpand(x) x
 	#define NBglue(x,y,z) x ## NBexpand(y) ## z 
but here again the symbol was not expanded but used literally, and I got complaints that "conv_natural_NBexpand(uint16_t)_to_mono" was not a valid symbol - surprise. So the final answer was -- thanks to Christos at this point! -- this one:
 	#define _NBglue(x,y,z) x ## y ## z
 	#define NBglue(x,y,z) _NBglue(x,y,z) 
This expands the types properly.

What lesson can be learned from this? 1) don't use #define where typedef is the right thing 2) don't blindly assume someone followed rule 1).

Oh, and someone please feel free to go back and clean up this whole code, apparently it was de-C++-ified at some time, according to some comment... :)

And finally, if someone's got some success with the kqemu or that other kernel-module whose name I forgot, please let me know! :)

[Tags: , ]


Disclaimer: All opinion expressed here is purely my own. No responsibility is taken for anything.

Access count: 35076943
Copyright (c) Hubert Feyrer