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

Reply via email to