diff --git a/bin/main.c b/bin/main.c index d547c6e..881182a 100644 --- a/bin/main.c +++ b/bin/main.c @@ -96,6 +96,9 @@ struct xtn_t /*hcl_oop_t sym_errstr;*/ }; +/* ========================================================================= */ + +static hcl_t* g_hcl = HCL_NULL; /* ========================================================================= */ @@ -426,12 +429,91 @@ static void vm_checkbc (hcl_t* hcl, hcl_oob_t bcode) } */ + static void gc_hcl (hcl_t* hcl) { xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl); /*if (xtn->sym_errstr) xtn->sym_errstr = hcl_moveoop(hcl, xtn->sym_errstr);*/ } +/* ========================================================================= */ + +static hcl_oop_t execute_in_interactive_mode (hcl_t* hcl) +{ + hcl_oop_t retv; + + hcl_decode (hcl, 0, hcl_getbclen(hcl)); + HCL_LOG0 (hcl, HCL_LOG_MNEMONIC, "------------------------------------------\n"); + g_hcl = hcl; + /*setup_tick ();*/ + + retv = hcl_execute(hcl); + + /* flush pending output data in the interactive mode(e.g. printf without a newline) */ + hcl_flushio (hcl); + + if (!retv) + { + hcl_logbfmt (hcl, HCL_LOG_STDERR, "ERROR: cannot execute - [%d] %js\n", hcl_geterrnum(hcl), hcl_geterrmsg(hcl)); + } + else + { + /* print the result in the interactive mode regardless 'verbose' */ + hcl_logbfmt (hcl, HCL_LOG_STDOUT, "%O\n", retv); /* TODO: show this go to the output handler?? */ + /* + * print the value of ERRSTR. + hcl_oop_cons_t cons = hcl_getatsysdic(hcl, xtn->sym_errstr); + if (cons) + { + HCL_ASSERT (hcl, HCL_IS_CONS(hcl, cons)); + HCL_ASSERT (hcl, HCL_CONS_CAR(cons) == xtn->sym_errstr); + hcl_print (hcl, HCL_CONS_CDR(cons)); + } + */ + } + /*cancel_tick();*/ + g_hcl = HCL_NULL; + + return retv; +} + + +static hcl_oop_t execute_in_batch_mode (hcl_t* hcl, int verbose) +{ + hcl_oop_t retv; + + hcl_decode (hcl, 0, hcl_getbclen(hcl)); + HCL_LOG2 (hcl, HCL_LOG_MNEMONIC, "BYTECODES bclen = > %zu lflen => %zu\n", hcl_getbclen(hcl), hcl_getlflen(hcl)); + g_hcl = hcl; + /*setup_tick ();*/ + + retv = hcl_execute(hcl); + hcl_flushio (hcl); + + if (!retv) + { + hcl_logbfmt (hcl, HCL_LOG_STDERR, "ERROR: cannot execute - [%d] %js\n", hcl_geterrnum(hcl), hcl_geterrmsg(hcl)); + } + else if (verbose) + { + hcl_logbfmt (hcl, HCL_LOG_STDERR, "EXECUTION OK - EXITED WITH %O\n", retv); + } + + /*cancel_tick();*/ + g_hcl = HCL_NULL; + /*hcl_dumpsymtab (hcl);*/ + + return retv; +} + +static int on_fed_cnode_in_interactive_mode (hcl_t* hcl, hcl_cnode_t* obj) +{ + if (hcl_compile(hcl, obj, HCL_COMPILE_CLEAR_CODE | HCL_COMPILE_CLEAR_FNBLK) <= -1) return -1; + execute_in_interactive_mode (hcl); + return 0; +} + + /* ========================================================================= */ static int handle_logopt (hcl_t* hcl, const hcl_bch_t* logstr) @@ -565,12 +647,6 @@ static int handle_dbgopt (hcl_t* hcl, const hcl_bch_t* str) return 0; } #endif -/* ========================================================================= */ - -static hcl_t* g_hcl = HCL_NULL; - -/* ========================================================================= */ - /* ========================================================================= */ @@ -704,7 +780,7 @@ count++; print_synerr (hcl); if (xtn->reader_istty && hcl_getsynerrnum(hcl) != HCL_SYNERR_EOF) { - /* TODO: drain remaining data in the reader including the actual inputstream and buffered data in hcl */ + /* TODO: drain remaining data in the reader including the actual input stream and buffered data in hcl */ continue; } } @@ -736,66 +812,11 @@ count++; else if (xtn->reader_istty) { /* interactive mode */ - hcl_oop_t retv; - - hcl_decode (hcl, 0, hcl_getbclen(hcl)); - HCL_LOG0 (hcl, HCL_LOG_MNEMONIC, "------------------------------------------\n"); - g_hcl = hcl; - /*setup_tick ();*/ - - retv = hcl_execute(hcl); - - /* flush pending output data in the interactive mode(e.g. printf without a newline) */ - hcl_flushio (hcl); - - if (!retv) - { - hcl_logbfmt (hcl, HCL_LOG_STDERR, "ERROR: cannot execute - [%d] %js\n", hcl_geterrnum(hcl), hcl_geterrmsg(hcl)); - } - else - { - /* print the result in the interactive mode regardless 'verbose' */ - hcl_logbfmt (hcl, HCL_LOG_STDOUT, "%O\n", retv); /* TODO: show this go to the output handler?? */ - - /* - * print the value of ERRSTR. - hcl_oop_cons_t cons = hcl_getatsysdic(hcl, xtn->sym_errstr); - if (cons) - { - HCL_ASSERT (hcl, HCL_IS_CONS(hcl, cons)); - HCL_ASSERT (hcl, HCL_CONS_CAR(cons) == xtn->sym_errstr); - hcl_print (hcl, HCL_CONS_CDR(cons)); - } - */ - } - /*cancel_tick();*/ - g_hcl = HCL_NULL; + execute_in_interactive_mode (hcl); } } - if (!xtn->reader_istty && hcl_getbclen(hcl) > 0) - { - hcl_oop_t retv; - - hcl_decode (hcl, 0, hcl_getbclen(hcl)); - HCL_LOG2 (hcl, HCL_LOG_MNEMONIC, "BYTECODES bclen = > %zu lflen => %zu\n", hcl_getbclen(hcl), hcl_getlflen(hcl)); - g_hcl = hcl; - /*setup_tick ();*/ - - retv = hcl_execute(hcl); - if (!retv) - { - hcl_logbfmt (hcl, HCL_LOG_STDERR, "ERROR: cannot execute - [%d] %js\n", hcl_geterrnum(hcl), hcl_geterrmsg(hcl)); - } - else if (verbose) - { - hcl_logbfmt (hcl, HCL_LOG_STDERR, "EXECUTION OK - EXITED WITH %O\n", retv); - } - - /*cancel_tick();*/ - g_hcl = HCL_NULL; - /*hcl_dumpsymtab (hcl);*/ - } + if (!xtn->reader_istty && hcl_getbclen(hcl) > 0) execute_in_batch_mode (hcl, verbose); return 0; @@ -822,7 +843,10 @@ static int feed_loop (hcl_t* hcl, xtn_t* xtn, int cflags, int verbose) } /*(setvbuf (fp, NULL, _IONBF, 0);*/ + + if (xtn->reader_istty) hcl_beginfeed (hcl, on_fed_cnode_in_interactive_mode); /* override the default cnode handler */ +/* TODO: use the io handler attached .. */ while (1) { hcl_ooi_t n; @@ -854,7 +878,6 @@ static int feed_loop (hcl_t* hcl, xtn_t* xtn, int cflags, int verbose) /* 'len' must remain 0 in this case */ #endif - /* the compiler must be invoked whenever feed() sees a complete object */ if (x <= -1) goto feed_error; } @@ -884,11 +907,7 @@ static int feed_loop (hcl_t* hcl, xtn_t* xtn, int cflags, int verbose) fclose (fp); -/* TODO: execute code? */ - if (hcl_getbclen(hcl) > 0) - { -/* TODO: execute code... */ - } + if (!xtn->reader_istty && hcl_getbclen(hcl) > 0) execute_in_batch_mode (hcl, verbose); return 0; @@ -1025,7 +1044,7 @@ int main (int argc, char* argv[]) memset (&hclcb, 0, HCL_SIZEOF(hclcb)); hclcb.gc = gc_hcl; - hclcb.vm_startup = vm_startup; + hclcb.vm_startup = vm_startup; hclcb.vm_cleanup = vm_cleanup; /*hclcb.vm_checkbc = vm_checkbc;*/ hcl_regcb (hcl, &hclcb); diff --git a/lib/hcl-prv.h b/lib/hcl-prv.h index 390c3b6..b4caf32 100644 --- a/lib/hcl-prv.h +++ b/lib/hcl-prv.h @@ -702,17 +702,8 @@ struct hcl_compiler_t } u; } lx; - struct - { - int code; - /*union - { - - } u;*/ - } st[100]; - hcl_ooi_t top; - struct hcl_frd_t rd; + hcl_on_cnode_t on_cnode; } feed; /* == COMPILER STACK == */ diff --git a/lib/hcl.h b/lib/hcl.h index 441f3f7..555139c 100644 --- a/lib/hcl.h +++ b/lib/hcl.h @@ -1459,6 +1459,8 @@ struct hcl_dbgi_t typedef struct hcl_compiler_t hcl_compiler_t; typedef struct hcl_cnode_t hcl_cnode_t; +typedef int (*hcl_on_cnode_t) (hcl_t* hcl, hcl_cnode_t* obj); + enum hcl_compile_flag_t { /* clear byte codes at the beginnign of hcl_compile() */ @@ -2082,7 +2084,6 @@ HCL_EXPORT int hcl_setoption ( const void* value ); - HCL_EXPORT hcl_cb_t* hcl_regcb ( hcl_t* hcl, hcl_cb_t* tmpl @@ -2151,9 +2152,9 @@ HCL_EXPORT void hcl_abort ( HCL_EXPORT int hcl_attachio ( - hcl_t* hcl, - hcl_ioimpl_t reader, - hcl_ioimpl_t printer + hcl_t* hcl, + hcl_ioimpl_t reader, + hcl_ioimpl_t printer ); HCL_EXPORT void hcl_detachio ( @@ -2168,11 +2169,6 @@ HCL_EXPORT hcl_cnode_t* hcl_read ( hcl_t* hcl ); -HCL_EXPORT void hcl_freecnode ( - hcl_t* hcl, - hcl_cnode_t* cnode -); - HCL_EXPORT int hcl_print ( hcl_t* hcl, hcl_oop_t obj @@ -2194,6 +2190,16 @@ HCL_EXPORT hcl_ooi_t hcl_proutufmt ( #if defined(HCL_INCLUDE_COMPILER) +HCL_EXPORT void hcl_freecnode ( + hcl_t* hcl, + hcl_cnode_t* cnode +); + +HCL_EXPORT void hcl_beginfeed ( + hcl_t* hcl, + hcl_on_cnode_t on_cnode +); + HCL_EXPORT int hcl_feed ( hcl_t* hcl, const hcl_ooch_t* data, diff --git a/lib/read.c b/lib/read.c index ba56115..8918706 100644 --- a/lib/read.c +++ b/lib/read.c @@ -2247,6 +2247,14 @@ hcl_cnodetoobj (hcl_t* hcl, hcl_cnode_t* x) /* ---------------------------------------------------------------------- */ +static int on_fed_cnode (hcl_t* hcl, hcl_cnode_t* obj) +{ + /* the default handler for a cnode composed via feeding - just compile the object node. */ + return hcl_compile(hcl, obj, 0); +} + +/* ---------------------------------------------------------------------- */ + static void init_feed (hcl_t* hcl) { HCL_MEMSET (&hcl->c->feed, 0, HCL_SIZEOF(hcl->c->feed)); @@ -2256,31 +2264,11 @@ static void init_feed (hcl_t* hcl) hcl->c->feed.lx.loc.colm = 1; hcl->c->feed.lx.loc.file = HCL_NULL; - hcl->c->feed.top = -1; + hcl->c->feed.on_cnode = on_fed_cnode; } /* ------------------------------------------------------------------------ */ -static int fst_push (hcl_t* hcl, int code) -{ - if (hcl->c->feed.top >= HCL_COUNTOF(hcl->c->feed.st) - 1) /* TODO: use a dynamically allocated stack? */ - { - hcl_seterrbfmt (hcl, HCL_EBUFFULL, "feed stack full"); - return -1; - } - - hcl->c->feed.top++; - HCL_MEMSET (&hcl->c->feed.st[hcl->c->feed.top], 0, HCL_SIZEOF(hcl->c->feed.st[hcl->c->feed.top])); - hcl->c->feed.st[hcl->c->feed.top].code = code; - return 0; -} - -static void fst_pop (hcl_t* hcl) -{ - HCL_ASSERT (hcl, hcl->c->feed.top >= 0); - hcl->c->feed.top--; -} - static int feed_begin_include (hcl_t* hcl) { hcl_ioinarg_t* arg; @@ -2327,11 +2315,9 @@ static int feed_end_include (hcl_t* hcl) x = hcl->c->reader(hcl, HCL_IO_CLOSE, hcl->c->curinp); - /* if closing has failed, still destroy the - * sio structure first as normal and return - * the failure below. this way, the caller - * does not call HCL_IO_CLOSE on - * hcl->c->curinp again. */ + /* if closing has failed, still destroy the sio structure + * first as normal and return the failure below. this way, + * the caller doesn't call HCL_IO_CLOSE on hcl->c->curinp again. */ cur = hcl->c->curinp; hcl->c->curinp = hcl->c->curinp->includer; @@ -2683,7 +2669,8 @@ static int feed_process_token (hcl_t* hcl) /* check if we are at the top frd->level */ if (frd->level <= 0) { - // TOOD: callback with frd->obj in case it's complete + int n; + hcl_cb_t* cb; /* upon exit, we must be at the top level */ HCL_ASSERT (hcl, frd->level == 0); @@ -2692,14 +2679,10 @@ static int feed_process_token (hcl_t* hcl) HCL_ASSERT (hcl, hcl->c->r.st == HCL_NULL); HCL_ASSERT (hcl, frd->obj != HCL_NULL); -/* TODO: error handling, etc */ -hcl_compile(hcl, frd->obj, HCL_COMPILE_CLEAR_CODE | HCL_COMPILE_CLEAR_FNBLK); /* flags 0 if non-interactive */ -hcl_freecnode (hcl, frd->obj); /* not needed any more */ -frd->obj = HCL_NULL; -hcl_decode (hcl, 0, hcl_getbclen(hcl)); -hcl_execute (hcl); -hcl_flushio (hcl); - + n = hcl->c->feed.on_cnode(hcl, frd->obj); + hcl_freecnode (hcl, frd->obj); /* not needed any more */ + frd->obj = HCL_NULL; + if (n <= -1) goto oops; } else { @@ -2715,7 +2698,6 @@ hcl_flushio (hcl); clear_comma_colon_flag (hcl); } - ok: return 0; @@ -2949,16 +2931,10 @@ static int flx_start (hcl_t* hcl, hcl_ooci_t c) switch (c) { case HCL_OOCI_EOF: - { - int n; -#if 0 - n = end_include(hcl); - if (n <= -1) return -1; - if (n >= 1) goto retry; -#endif + /* only EOF of the top-level stream is supposed to be fed in. + * the internal logic discard EOFs of included streams */ FEED_WRAP_UP_WITH_CHARS (hcl, vocas[VOCA_EOF].str, vocas[VOCA_EOF].len, HCL_IOTOK_EOF); goto consumed; - } case ';': FEED_CONTINUE_WITH_CHAR (hcl, c, HCL_FLX_COMMENT); @@ -3706,7 +3682,6 @@ static int feed_char (hcl_t* hcl, hcl_ooci_t c) static int feed_from_included (hcl_t* hcl) { int x; - hcl_ooch_t lc; HCL_ASSERT (hcl, hcl->c->curinp != HCL_NULL && hcl->c->curinp != &hcl->c->inarg); @@ -3721,7 +3696,7 @@ static int feed_from_included (hcl_t* hcl) if (hcl->c->curinp->xlen <= 0) { - /* got EOF */ + /* got EOF from an included stream */ #if 0 x = feed_char(hcl, HCL_OOCI_EOF); /* TODO: or call feed_end_include? */ if (x <= -1) return -1; @@ -3735,17 +3710,18 @@ static int feed_from_included (hcl_t* hcl) hcl->c->curinp->b.len = hcl->c->curinp->xlen; } - lc = hcl->c->curinp->buf[hcl->c->curinp->b.pos]; - x = feed_char(hcl, lc); + x = feed_char(hcl, hcl->c->curinp->buf[hcl->c->curinp->b.pos]); if (x <= -1) return -1; hcl->c->curinp->b.pos += x; if (hcl->c->feed.rd.do_include_file) { - /* perform delayed file inclusion. the token buffer must remain unchanged - * since do_include_file has been set to true in feed_process_token(). */ + /* feed_process_token(), called for the "filename" token for the #include + * directive, sets hcl->c->feed.rd.do_include_file to 1 instead of attepmting + * to include the file. the file inclusion is attempted here after the return + * value of feed_char() is used to advance the hcl->c->curinp->b.pos pointer. */ + hcl->c->feed.rd.do_include_file = 0; /* clear this regardless of inclusion result */ if (feed_begin_include(hcl) <= -1) return -1; - hcl->c->feed.rd.do_include_file = 0; } } while (hcl->c->curinp != &hcl->c->inarg); @@ -3753,6 +3729,11 @@ static int feed_from_included (hcl_t* hcl) return 0; } +void hcl_beginfeed (hcl_t* hcl, hcl_on_cnode_t on_cnode) +{ + hcl->c->feed.on_cnode = on_cnode; +} + int hcl_feed (hcl_t* hcl, const hcl_ooch_t* data, hcl_oow_t len) { /* TODO: need to return the number of processed characters? @@ -3761,6 +3742,7 @@ int hcl_feed (hcl_t* hcl, const hcl_ooch_t* data, hcl_oow_t len) hcl_oow_t i; int x; + if (data) { for (i = 0; i < len; ) @@ -3800,10 +3782,23 @@ int hcl_feed (hcl_t* hcl, const hcl_ooch_t* data, hcl_oow_t len) } else { - for (i = 0; i < 1;) + for (i = 0; i < 1;) /* weird loop in case feed_char() returns 0 */ { x = feed_char(hcl, HCL_OOCI_EOF); - if (x <= -1) return -1; + if (x <= -1) + { + if (hcl->c->feed.rd.level <= 0 && hcl_geterrnum(hcl) == HCL_ESYNERR && hcl_getsynerrnum(hcl) == HCL_SYNERR_EOF) + { + /* convert this EOF error to success as the caller knows EOF in the feed mode. + * the caller can safely stop feeding after gettting success from hcl_feed(hcl, HCL_NULL, 0); + * in the feed mode, this function doesn't set HCL_EFINIS. */ + x = 1; + } + else + { + return -1; + } + } i += x; } }