Thursday, June 21, 2012

Porting code_gen.c and db_fileio.c

(This entry was written offline during a flight from Las Vegas to Milwaukee today, June 21st 2012. I'm continuing the task of merging Waverous into Stunt, or put another way, getting Stunt to be C++ compliant).

Here's something you hope to never see:

-*- mode: compilation; default-directory: "/Users/swain/Sites/projects/moowork/waverous/server/" -*-
Compilation started at Thu Jun 21 07:10:01

make
[ config.h : config.status ]
./config.status
config.status: creating Makefile
config.status: creating config.h
config.status: config.h is unchanged
g++ -m32 -O -DHAVE_CONFIG_H  -c -o code_gen.o code_gen.c
code_gen.c: In function 'Bytecodes stmt_to_code(Stmt*, GState*)':
code_gen.c:1220: error: invalid conversion from 'int (*)(int*, int*)' to 'int (*)(const void*, const void*)'
code_gen.c:1220: error:   initializing argument 4 of 'void qsort(void*, size_t, size_t, int (*)(const void*, const void*))'
make: *** [code_gen.o] Error 1

Compilation exited abnormally with code 2 at Thu Jun 21 07:10:01
The issue here is the standard qsort() function wants a pointer to a function whose signature has two const void pointers, but LambdaMOO's implementation has two int pointers:
     void
     qsort(void *base, size_t nel, size_t width,
         int (*compar)(const void *, const void *));
I never caught this when I ported Waverous to C++ because I never defined BYTECODE_REDUCE_REF. This suggests to me a way of testing the server by compiling it with every possible combination of flags... this would be one hell of a build-and-smoke test. For every combination of compile-time options: compile the server, start it up, log in and do some basic tasks, shut down. I would have caught this long ago if I'd thought of writing such a test.

After some dedicated surfing via my phone at Milwaukee's airport, which does not have free wi-fi (pththth) I found the solution on www.cplusplus.com:

#ifdef BYTECODE_REDUCE_REF
// See http://www.cplusplus.com/reference/clibrary/cstdlib/qsort/ for
// this usage of standard C's qsort() function
static int
bbd_cmp(const void *a, const void *b)
{
  return ( *(int *)a - *(int *)b );
}
#endif    /* BYTECODE_REDUCE_REF */
It's curious and non-obvious to me that the args within the function are cast and that this satisfies the compiler. On a side note I think being able to google our compiler errors and find solutions is an exception to Fred Brooks's "No Silver Bullet" argument. It feels like an order of magnitude increase in productivity to get help so easily.

I'm now past one of the stickier parts of porting: past the TRY/EXECEPT/ENDTRY preprocessor macros in code_gen.c. I had to edit the file by hand and incorporate the needed expansion of the macros because the block of code in question had added blank lines spacing out the code. I would think patch would have a command line flag to account for this situation, but patch can only handle changes in leading and trailing whitespace.

No comments:

Post a Comment