From 308b39d50b64602cbab301adab946dd9afead42a Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Thu, 22 Feb 2024 01:21:11 +0900 Subject: [PATCH] change to read a line before starting to feed input in the interactive mode fixed the union issue in go wrapper code --- bin/main.c | 120 +++++++++++++++++++++++++++++++++++++++++------------ go/cb.go | 21 +++++++++- lib/read.c | 8 ++-- 3 files changed, 117 insertions(+), 32 deletions(-) diff --git a/bin/main.c b/bin/main.c index 83665ca..63eef93 100644 --- a/bin/main.c +++ b/bin/main.c @@ -29,6 +29,7 @@ #endif #include +#include #include #include @@ -103,6 +104,15 @@ struct xtn_t const char* udo_path; int vm_running; + + struct + { + hcl_bch_t buf[1024]; + hcl_oow_t len; + hcl_oow_t pos; + int eof; + int ongoing; + } feed; /*hcl_oop_t sym_errstr;*/ }; @@ -492,26 +502,82 @@ static hcl_oop_t execute_in_batch_mode(hcl_t* hcl, int verbose) static int on_fed_cnode_in_interactive_mode (hcl_t* hcl, hcl_cnode_t* obj) { xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl); - int flags = HCL_COMPILE_CLEAR_CODE | HCL_COMPILE_CLEAR_FNBLK; + int flags = 0; /* in the interactive, the compile error must not break the input loop. - * this function returns 0 to go on despite a compile-time error */ + * this function returns 0 to go on despite a compile-time error. + * + * if a single line or continued lines contain multiple expressions, + * execution is delayed until the last expression is compiled. */ + + if (!xtn->feed.ongoing) + { + flags = HCL_COMPILE_CLEAR_CODE | HCL_COMPILE_CLEAR_FNBLK; + xtn->feed.ongoing = 1; + } if (hcl_compile(hcl, obj, flags) <= -1) + { print_error(hcl, "failed to compile"); + xtn->feed.pos = xtn->feed.len; /* arrange to discard the rest of the line */ + show_prompt (hcl, 0); + } else - execute_in_interactive_mode (hcl); + { + hcl_oow_t i; + for (i = xtn->feed.pos; i < xtn->feed.len; i++) + { + if (!hcl_is_bch_space(xtn->feed.buf[i])) break; + } + + if (i >= xtn->feed.len || xtn->feed.pos >= xtn->feed.len) + { + /* nothing more to feed */ + execute_in_interactive_mode (hcl); + xtn->feed.ongoing = 0; + show_prompt (hcl, 0); + } + } - show_prompt (hcl, 0); return 0; } static int on_fed_cnode_in_batch_mode (hcl_t* hcl, hcl_cnode_t* obj) { - xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl); + /*xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl);*/ return hcl_compile(hcl, obj, 0); } +static int get_line (hcl_t* hcl, xtn_t* xtn, FILE* fp) +{ + if (xtn->feed.eof) return 0; + + xtn->feed.pos = 0; + xtn->feed.len = 0; + + while (1) + { + int ch = fgetc(fp); + if (ch == EOF) + { + if (ferror(fp)) + { + hcl_logbfmt (hcl, HCL_LOG_STDERR, "ERROR: failed to read - %hs - %hs\n", xtn->cci_path, strerror(errno)); + return -1; + } + + xtn->feed.eof = 1; + break; + } + + /* TOTO: buffer check... */ + xtn->feed.buf[xtn->feed.len++] = (hcl_bch_t)(unsigned int)ch; + if (ch == '\n') break; + } + + return 1; +} + static int feed_loop (hcl_t* hcl, xtn_t* xtn, int verbose) { FILE* fp = HCL_NULL; @@ -548,32 +614,34 @@ static int feed_loop (hcl_t* hcl, xtn_t* xtn, int verbose) goto oops; } - if (is_tty) show_prompt (hcl, 0); - - while (1) + if (is_tty) { - if (is_tty) - { - hcl_bch_t bch; - int ch = fgetc(fp); - if (ch == EOF) - { - if (ferror(fp)) - { - hcl_logbfmt (hcl, HCL_LOG_STDERR, "ERROR: failed to read - %hs - %hs\n", xtn->cci_path, strerror(errno)); - goto oops; - } - break; - } + show_prompt (hcl, 0); - bch = ch; - if (hcl_feedbchars(hcl, &bch, 1) <= -1) + while (1) + { + int n; + + /* read a while line regardless of the actual expression */ + n = get_line(hcl, xtn, fp); + if (n <= -1) goto oops; + if (n == 0) break; + + /* feed the line */ + while (xtn->feed.pos < xtn->feed.len) { - print_error (hcl, "failed to feed"); - show_prompt (hcl, 0); + hcl_bch_t c = xtn->feed.buf[xtn->feed.pos++]; + if (hcl_feedbchars(hcl, &c, 1) <= -1) + { + print_error (hcl, "failed to feed"); + show_prompt (hcl, 0); + } } } - else + } + else + { + while (1) { hcl_bch_t buf[1024]; hcl_oow_t xlen; diff --git a/go/cb.go b/go/cb.go index 76311ea..2fd404d 100644 --- a/go/cb.go +++ b/go/cb.go @@ -3,6 +3,7 @@ package hcl /* #include #include +#include // for memcpy */ import "C" @@ -130,6 +131,7 @@ func hcl_go_cci_handler(c *C.hcl_t, cmd C.hcl_io_cmd_t, arg unsafe.Pointer) C.in n int i int buf []rune + dummy C.hcl_uch_t ) ioarg = (*C.hcl_io_cciarg_t)(arg) @@ -140,9 +142,24 @@ func hcl_go_cci_handler(c *C.hcl_t, cmd C.hcl_io_cmd_t, arg unsafe.Pointer) C.in return -1 } - for i = 0; i < n; i++ { // TODO: use a proper conversion when the rune size is different from hio_uch_t - ioarg.buf[i] = C.hcl_uch_t(buf[i]) + ioarg.is_bytes = 0 + if unsafe.Sizeof(buf[0]) == unsafe.Sizeof(dummy) { + C.memcpy ( + unsafe.Pointer(&ioarg.buf[0]), + unsafe.Pointer(&buf[0]), + C.size_t(unsafe.Sizeof(buf[0]) * uintptr(n))) + } else { + var dst uintptr + // work around cgo's union issue. not able to access individual union + // member fields. cgo treats union as byte aggregates. + dst = uintptr(unsafe.Pointer(&ioarg.buf[0])) + for i = 0; i < n; i++ { + //ioarg.buf.c[i] = C.hcl_uch_t(buf[i]) + *(*C.hcl_uch_t)(unsafe.Pointer(dst)) = C.hcl_uch_t(buf[i]); + dst += unsafe.Sizeof(dummy) + } } + ioarg.xlen = C.hcl_oow_t(n) return 0 } diff --git a/lib/read.c b/lib/read.c index dfe73b0..4443d79 100644 --- a/lib/read.c +++ b/lib/read.c @@ -167,7 +167,7 @@ static int init_compiler (hcl_t* hcl); static HCL_INLINE int is_spacechar (hcl_ooci_t c) { - /* TODO: handle other space unicode characters */ +#if 0 switch (c) { case ' ': @@ -181,6 +181,9 @@ static HCL_INLINE int is_spacechar (hcl_ooci_t c) default: return 0; } +#else + return c != HCL_OOCI_EOF && hcl_is_ooch_space(c); +#endif } static HCL_INLINE int is_linebreak (hcl_ooci_t c) @@ -3507,7 +3510,6 @@ int hcl_attachccio (hcl_t* hcl, hcl_io_impl_t cci_rdr) inited_compiler = 1; } - if (cci_rdr) { /* The name field and the includer field are HCL_NULL @@ -3650,8 +3652,6 @@ void hcl_flushudio (hcl_t* hcl) if (hcl->io.udo_wrtr) hcl->io.udo_wrtr (hcl, HCL_IO_FLUSH, &hcl->io.udo_arg); } - - /* TODO: discard the fwollowing three functions - hcl_setbasesrloc, hcl_readbasesrchar */ void hcl_setbasesrloc (hcl_t* hcl, hcl_oow_t line, hcl_oow_t colm) {