[CM] fn defined in C returns to wrong place

Gregg Reynolds dev at mobileink.com
Fri Aug 26 06:04:57 PDT 2022

I'm using s7 to convert from Dune (the standard OCaml build tool) to Bazel.
Dune files use sexp syntax, so in general this works great; almost all of
the conversion logic is written in s7 scheme.

But I've come across a problem that has me stumped.  The one
incompatibility I've found in dune syntax is use of a dot '.' to mean
"current directory". For example:

(run ocaml-protoc %{deps} -binary -pp -ml_out .)

Notice the dot at the end.  The s7 reader throws an error "unexpected close
paren: ..".  So I catch the error, close the input port, use the C api to
read the file into a C string (dune files are short), convert '.' to './',
and then s7 read the string from a string-port, giving a scheme list.
Works great.

The problem arises when I try to return the result. The routine that reads
the dune files is load-dune, written in C (I use the C fts api to crawl the
source tree, read the dune files, and construct a scheme object that
mirrors the source tree).  So my main routine, in C, loads my convert.scm
and then does s7_call (I've also tried s7_apply_function, no difference) to
run the main routine, which then calls load-dune.  The latter ends by
returning the scheme structure that results from crawling the source tree
and reading the dune files (using C apis).

This works great when the dune files can be read by s7 without error.
Control resumes in convert.scm, which then runs the remaining conversion
code (in scheme).  But when I encounter the bad-dot syntax, I handle the
error as described above, but when I 'return', control does not resume in
convert.scm.  Instead it resumes in the C code at the s7_call invocation
site. So the value I return is returned as the result of s7_call (or
s7_apply_function) which means the rest of my conversion code is skipped.

In other words it seems to skip the scheme call stack.  But I print the
call stack (using backtrace and backtrace_symbols), and its the same for
both good dune files and bad (corrected) dune files.  I also print a bunch
of debug msgs to stdout, and they are the same in both cases. The only
difference I can see is the return location.

I tried using s7_gc_protect functions in various ways to no effect.  I
tried disabling GC by s7_gc_on(s7, s7_f(s7)); but that had no effect.  I
tried eliminating the code that reads the file into a string by using a
string constant, to no effect.

So I think it must be related to the way I've configured error handling.
I've tried to follow the examples, e.g.

    old_err_port = s7_set_current_error_port(s7, s7_open_output_string(s7));
    if (old_err_port != s7_nil(s7)) {
        gc_loc = s7_gc_protect(s7, old_err_port);

I also do this:

s7_pointer _s7_error_handler(s7_scheme *sc, s7_pointer args)
    if (strstr(s7_string(s7_car(args)), "unexpected close paren:") != NULL)
        if (debug)
            printf(RED "Error: BAD DOT" CRESET "\n");
        s7_write(s7, s7_make_string(s7, "BADDOT"),
        return s7_t(s7);
    } else {

   s7_define_function(s7, "error-handler",
                       _s7_error_handler, 1, 0, false,
                       "our error handler");

    s7_eval_c_string(s7, "(set! (hook-functions *error-hook*) \n\
                            (list (lambda (hook) \n\
                                    (error-handler \n\
                                      (apply format #f (hook 'data))) \n\
                                    (set! (hook 'result) 'our-error))))");

and it all seems to work, insofar as the read error is caught, I detect
"BADDOT", and fix the read.  But the return does not work, and I have no
idea why.



-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://cm-mail.stanford.edu/pipermail/cmdist/attachments/20220826/e1f3eec9/attachment.html>

More information about the Cmdist mailing list