I have no idea how it actually works, but it would be easy enough to implement by having nested functions take a parameter that's a pointer to a structure containing the variables that are in scope in the outer function.
In your example, it could be something like this:
struct variables_in_a_that_are_visible_in_d {
int aa;
};
void d_nested_in_a(struct variables_in_a_that_are_visible_in_d *ascope) {
// Variable dd, not accessible from a
int dd = 42;
// Increment a's aa
ascope->aa += 1;
}
void a() {
int aa = 0;
// Pack up variables for d()
struct variables_in_a_that_are_visible_in_d ford;
ford.aa = aa;
// actually call d)
d_nested_in_a(&ford);
// Unpack after calling d()
aa = ford.aa;
// Continue with a()
// ...
}
I'm a little surprised people are so hung up on this. They don't call C "portable assembly language" for nothing. If it can be done compiling to native code or some virtual machine assembly language, it can be done compiling to C.