One of my major tasks at work at the moment is writing a BSP (Board Support Package - a set of drivers) for the Freescale MPC55xx processor. The catch - it's being written in Ada, because this is the language our micro-controller programs are written in (ah, defense industry...).

Freescale supplies a set of C header files that define the memory mapped registers, as follows:

union {
    vuint32_t R;
    struct {
        vuint32_t:26;
        vuint32_t VTES:1;
        vuint32_t:4;
        vuint32_t HVEN:1;
    } B;
} MCR;  /* Module Configuration Register */

Basically, this is a memory-mapped struct. When I tell the compiler that some pointer points to it, I can then access the register's bits through the struct.

In Ada, this is done differently, and there's a lot of code that needs to be translated, quite mechanically. The mpc5554.h header file is over 3000 lines long. And I really hate mechanic work, really really hate it. I prefer to spend 2 hours writing a script that will solve me 1 hour of nasty work.

After much looking around, I finally settled on using Perl's Parse::RecDescent module. I've had some experience with it before, and managed to craft a script that parses a small subset of C - these struct/union declarations, and spits out the corresponding Ada code. It took me a few hours and I had lots of fun, which is important :-)

Later at home, I run across some interesting tools that can help with this even further. For example c2c - a program that reads C source code, analyzes and type-checks it, builds an AST and spits out C code from this AST. The cool thing is that you can ask it to just leave the AST and print it out.

It was the usual nightmare of compiling Unix-y stuff on Windows, but I managed it. MinGW really helps, because it's very much GCC compatible.

Another interesting tool is TCC - tiny C compiler. A fully functional, C99 compatible compiler with open source code.