On Sat, Nov 14, 2009 at 01:30:16AM -0600, Peter Karman wrote:
CC to the Lucy developers list...
>> I threw some fprintf to stderr in the (generated?)
>> charmonizer/gen/Charmonizer/Core/Compiler.c
Yes, it's generated.
trunk/charmonizer/src/Charmonizer/Core/Compiler.charm <-- orig
trunk/charmonizer/gen/Charmonizer/Core/Compiler.c <-- generated
The philosophy of Charmonizer is to use C to bootstrap C, but embedding C code
in C string literals is messy. To avoid that, we surround code blocks with
"METAQUOTE" tags and run ".charm" files through a filter to produce ".c" files.
Source code in trunk/charmonizer/src/Charmonizer/Probe/LargeFiles.charm:
/* Code for checking 64-bit lseek. */
static char lseek_code[] = METAQUOTE
%s
#include "_charm.h"
int main() {
int fd;
Charm_Setup;
fd = open("_charm_lseek", O_WRONLY | O_CREAT, 0666);
if (fd == -1) { exit(-1); }
%s(stdout, 0, SEEK_SET);
printf("%%d", 1);
if (close(fd)) { exit(-1); }
return 0;
}
METAQUOTE;
Generated code in trunk/charmonizer/gen/Charmonizer/Probe/LargeFiles.c:
/* Code for checking 64-bit lseek. */
static char lseek_code[] = "\n"
" %s\n"
" #include \"_charm.h\"\n"
" int main() {\n"
" int fd;\n"
" Charm_Setup;\n"
" fd = open(\"_charm_lseek\", O_WRONLY | O_CREAT, 0666);\n"
" if (fd == -1) { exit(-1); }\n"
" %s(stdout, 0, SEEK_SET);\n"
" printf(\"%%d\", 1);\n"
" if (close(fd)) { exit(-1); }\n"
" return 0;\n"
" }\n"
"";
Browsing through the generated code just now, though, I have to say that the
messy-string-literals problem isn't as bad as we anticipated it would be when
we were designing Charmonizer. It might be worth ditching it.
Benefits:
* Big gain in terms of conceptual simplicity.
* The statement "Charmonizer uses C to bootstrap C" would be 100% true.
* We'd rid ourselves of the trunk/charmonizer/bin/metaquote utility app,
which is currently implemented in Perl.
* No more Perl dependency for Charmonizer.
* No more need to pre-generate files when prepping non-Perl distros.
* Slightly simpler build processes, since our build scripts will be able to
use the source files directly and won't have to run metaquote to get
usable C files.
To achieve those gains, we have to resign ourselves to writing code like
this...
" printf(\"%%d\", 1);\n"
... instead of this...
printf("%%d", 1);
... to put this line into our mini test-compile:
printf("%d", 1);
Thoughts?
> More info. The problem seems to come in the call to add_inc_dir(".") at line
> 58
> in Compiler.c. If I comment that out, everything compiles and tests out just
> fine.
>
> I threw some more debugging in add_inc_dir() to see what was going on.
> strdup()
> returns a copy of "." as expected, but the assignment to self->inc_dirs breaks
> somehow.
Seems like a fencepost error of some sort.
FWIW, the intent of add_inc_dir(), translated into Perl, is simply:
push @{ $self->{inc_dirs} }, $dir;
> [0] == ' ('
> passed in '.', num_dirs=1, last=' ('
That's whack. The inc_dirs member var is an array of strings -- a
NULL-terminated list of NULL-terminated char* vars. During chaz_CC_new, "."
is the first dir that gets added; at that point, self->inc_dirs should be a
single-element array with NULL as its only member. This is where we start
off, just a few lines above the call to add_inc_dir():
self->inc_dirs = (char**)calloc(sizeof(char*), 1);
There shouldn't *be* a "last" at that point -- the first element in that array
should be a NULL and trying to dereference it by printing self->inc_dirs[0]
as a string should segfault. Is self->inc_dirs[0] non-NULL?
Also, maybe there's something weird with the realloc?
self->inc_dirs = realloc(self->inc_dirs, num_dirs + 1);
Yeah, that's probably a problem. Should be a "* sizeof(char*)" multiplier in
there, methinks.
Marvin Humphrey