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.