mruby/mruby — pull request #144 by mitchblank (2012-05-16 12:40:28+00:00)
Title: Support building using C++ compiler

One thing that I've found handy when working with Lua is that the codebase can be compiled with either a C or C++ compiler -- this sometimes makes integrating with a C++ environment easier. It also allows Lua to optionally use C++ exceptions in place of setjmp/longjmp which can be important in some embedded environments (although that's a mruby pull request for another day!)

Being able to be compiled in C++ has other advantages; the stricter typechecking in C++ goes some way to keeping C code honest, in my experience.

So I decided to see what would be needed to make mruby build under C++. It turned out to be a LOT more than I had anticipated, but I kept slogging through until I got to the end. This builds for me, but I fully understand if this is too large to merge at once. If you are willing to take these changes but not in such a big piece I can resubmit them in smaller chunks. At the very least we can discuss it.

It does seem to build a working mirb with g++ 4.2.1, and doesn't seem to regress building with plain-old gcc.

CHANGES:
* Lots and lots of explicit "void *" casts (since C++ won't autoconvert
a void* pointer to a different pointer w/o a cast) Given the number of
places that do these calls, it might make more sense to make some
macros to wrap this functionality

* Don't declare types inside another type, i.e.

struct mystruct {
struct foo {
int a, b;
} s;
int c;
};

It's syntactically correct C++, but it won't put "struct foo" in the global namespace

* Avoid C++ keywords:
- change "new" to "new_val"
- change "not" to "is_not"
- change "try" to "should_try"

* mrb_gc_mark_ht_size and mrb_gc_free_ht both had mismatches between
their declarations in a .h and their implementations (this is just a straight-up
bug in the code that C++ name-mangling caught)

* In parse.y, C++ didn't like "node" both being a union member and a
type. Change the type to "node_t" Unfortunately that required a lot
of edits

* In a few places, C++'s stricter rules about "goto" crossing a variable
definition bit me. In each case I just had to introduce another
level of {} braces to sequester the variable definitions a little more

REMAINING ISSUES:
* I had to modify files generated by gperf to not use K&R style function
declarations. Really those should be regenerated with the --language=ANSI-C
option or whatever

* sprintf.c uses the "volatile" keyword in ways that didn't make sense
to me. This prevented structures from being automatically copied because
"volatile struct foo" and "struct foo" won't implicitly convert.
For now I just got rid of the volatile in that file when compiling with
C++; if volatile semantics are really needed there for some reason
some other fix will be needed