diff --git a/bin/main.c b/bin/main.c index 11ad46a..373107f 100644 --- a/bin/main.c +++ b/bin/main.c @@ -92,7 +92,6 @@ struct xtn_t const char* print_path; int vm_running; - int reader_istty; /*hcl_oop_t sym_errstr;*/ }; @@ -102,316 +101,6 @@ static hcl_t* g_hcl = HCL_NULL; /* ========================================================================= */ -static const hcl_bch_t* get_base_name (const hcl_bch_t* path) -{ - const hcl_bch_t* p, * last = HCL_NULL; - - for (p = path; *p != '\0'; p++) - { - if (HCL_IS_PATH_SEP(*p)) last = p; - } - - return (last == HCL_NULL)? path: (last + 1); -} - -static HCL_INLINE int open_input (hcl_t* hcl, hcl_ioinarg_t* arg) -{ - xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl); - bb_t* bb = HCL_NULL; - -/* TOOD: support predefined include directory as well */ - if (arg->includer) - { - /* includee */ - hcl_oow_t ucslen, bcslen, parlen; - const hcl_bch_t* fn, * fb; - - #if defined(HCL_OOCH_IS_UCH) - if (hcl_convootobcstr(hcl, arg->name, &ucslen, HCL_NULL, &bcslen) <= -1) goto oops; - #else - bcslen = hcl_count_bcstr(arg->name); - #endif - - fn = ((bb_t*)arg->includer->handle)->fn; - - fb = get_base_name(fn); - parlen = fb - fn; - - bb = (bb_t*)hcl_callocmem(hcl, HCL_SIZEOF(*bb) + (HCL_SIZEOF(hcl_bch_t) * (parlen + bcslen + 1))); - if (!bb) goto oops; - - bb->fn = (hcl_bch_t*)(bb + 1); - hcl_copy_bchars (bb->fn, fn, parlen); - #if defined(HCL_OOCH_IS_UCH) - hcl_convootobcstr (hcl, arg->name, &ucslen, &bb->fn[parlen], &bcslen); - #else - hcl_copy_bcstr (&bb->fn[parlen], bcslen + 1, arg->name); - #endif - } - else - { - /* main stream */ - hcl_oow_t pathlen; - - pathlen = hcl_count_bcstr(xtn->read_path); - - bb = (bb_t*)hcl_callocmem(hcl, HCL_SIZEOF(*bb) + (HCL_SIZEOF(hcl_bch_t) * (pathlen + 1))); - if (!bb) goto oops; - - bb->fn = (hcl_bch_t*)(bb + 1); - hcl_copy_bcstr (bb->fn, pathlen + 1, xtn->read_path); - } - -#if defined(__DOS__) || defined(_WIN32) || defined(__OS2__) - bb->fp = fopen(bb->fn, "rb"); -#else - bb->fp = fopen(bb->fn, "r"); -#endif - if (!bb->fp) - { - hcl_seterrbfmt (hcl, HCL_EIOERR, "unable to open %hs", bb->fn); - goto oops; - } - - if (!arg->includer) - { - #if defined(HAVE_ISATTY) - xtn->reader_istty = isatty(fileno(bb->fp)); - #endif - } - - arg->handle = bb; - -/* HACK */ - if (!arg->includer) - { - HCL_ASSERT (hcl, arg->name == HCL_NULL); - arg->name = hcl_dupbtooocstr(hcl, xtn->read_path, HCL_NULL); - /* ignore duplication failure */ -/* TODO: change the type of arg->name from const hcl_ooch_t* to hcl_ooch_t*. - * change its specification from [IN] only to [INOUT] in hcl_ioinarg_t. */ - } -/* END HACK */ - - return 0; - -oops: - if (bb) - { - if (bb->fp) fclose (bb->fp); - hcl_freemem (hcl, bb); - } - return -1; -} - -static HCL_INLINE int close_input (hcl_t* hcl, hcl_ioinarg_t* arg) -{ - /*xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl);*/ - bb_t* bb; - - bb = (bb_t*)arg->handle; - HCL_ASSERT (hcl, bb != HCL_NULL && bb->fp != HCL_NULL); - -/* HACK */ - if (!arg->includer && arg->name) - { - hcl_freemem (hcl, arg->name); - arg->name = HCL_NULL; - } -/* END HACK */ - - fclose (bb->fp); - hcl_freemem (hcl, bb); - - arg->handle = HCL_NULL; - return 0; -} - -static HCL_INLINE int read_input (hcl_t* hcl, hcl_ioinarg_t* arg) -{ - /*xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl);*/ - bb_t* bb; - hcl_oow_t bcslen, ucslen, remlen; - int x; - - bb = (bb_t*)arg->handle; - HCL_ASSERT (hcl, bb != HCL_NULL && bb->fp != HCL_NULL); - do - { - x = fgetc(bb->fp); - if (x == EOF) - { - if (ferror((FILE*)bb->fp)) - { - hcl_seterrnum (hcl, HCL_EIOERR); - return -1; - } - break; - } - - bb->buf[bb->len++] = x; - } - while (bb->len < HCL_COUNTOF(bb->buf) && x != '\r' && x != '\n'); - -#if defined(HCL_OOCH_IS_UCH) - bcslen = bb->len; - ucslen = HCL_COUNTOF(arg->buf); - x = hcl_convbtooochars(hcl, bb->buf, &bcslen, arg->buf, &ucslen); - if (x <= -1 && ucslen <= 0) return -1; - /* if ucslen is greater than 0, i assume that some characters have been - * converted properly. as the loop above reads an entire line if not too - * large, the incomplete sequence error (x == -3) must happen after - * successful conversion of at least 1 ooch character. so no explicit - * check for the incomplete sequence error is required */ -#else - bcslen = (bb->len < HCL_COUNTOF(arg->buf))? bb->len: HCL_COUNTOF(arg->buf); - ucslen = bcslen; - hcl_copy_bchars (arg->buf, bb->buf, bcslen); -#endif - - remlen = bb->len - bcslen; - if (remlen > 0) memmove (bb->buf, &bb->buf[bcslen], remlen); - bb->len = remlen; - - arg->xlen = ucslen; - return 0; -} - -static int read_handler (hcl_t* hcl, hcl_iocmd_t cmd, void* arg) -{ - switch (cmd) - { - case HCL_IO_OPEN: - return open_input(hcl, (hcl_ioinarg_t*)arg); - - case HCL_IO_CLOSE: - return close_input(hcl, (hcl_ioinarg_t*)arg); - - case HCL_IO_READ: - return read_input(hcl, (hcl_ioinarg_t*)arg); - - case HCL_IO_FLUSH: - /* no effect on an input stream */ - return 0; - - default: - hcl_seterrnum (hcl, HCL_EINTERN); - return -1; - } -} - -static HCL_INLINE int open_output (hcl_t* hcl, hcl_iooutarg_t* arg) -{ - xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl); - FILE* fp; - -#if defined(__MSDOS__) || defined(_WIN32) || defined(__OS2__) - if (xtn->print_path) fp = fopen(xtn->print_path, "wb"); - else fp = stdout; -#else - if (xtn->print_path) fp = fopen(xtn->print_path, "w"); - else fp = stdout; -#endif - if (!fp) - { - if (xtn->print_path) - hcl_seterrbfmt (hcl, HCL_EIOERR, "unable to open %hs", xtn->print_path); - else - hcl_seterrnum (hcl, HCL_EIOERR); - return -1; - } - - arg->handle = fp; - return 0; -} - -static HCL_INLINE int close_output (hcl_t* hcl, hcl_iooutarg_t* arg) -{ - /*xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl);*/ - FILE* fp; - - fp = (FILE*)arg->handle; - HCL_ASSERT (hcl, fp != HCL_NULL); - - if (fp != stdout) fclose (fp); - arg->handle = HCL_NULL; - return 0; -} - - -static HCL_INLINE int write_output (hcl_t* hcl, hcl_iooutarg_t* arg) -{ - /*xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl);*/ - hcl_bch_t bcsbuf[1024]; - hcl_oow_t bcslen, ucslen, donelen; - int x; - - donelen = 0; - - do - { - #if defined(HCL_OOCH_IS_UCH) - bcslen = HCL_COUNTOF(bcsbuf); - ucslen = arg->len - donelen; - x = hcl_convootobchars(hcl, &arg->ptr[donelen], &ucslen, bcsbuf, &bcslen); - if (x <= -1 && ucslen <= 0) return -1; - #else - bcslen = HCL_COUNTOF(bcsbuf); - ucslen = arg->len - donelen; - if (ucslen > bcslen) ucslen = bcslen; - else if (ucslen < bcslen) bcslen = ucslen; - hcl_copy_bchars (bcsbuf, &arg->ptr[donelen], bcslen); - #endif - - if (fwrite(bcsbuf, HCL_SIZEOF(bcsbuf[0]), bcslen, (FILE*)arg->handle) < bcslen) - { - hcl_seterrnum (hcl, HCL_EIOERR); - return -1; - } - - donelen += ucslen; - } - while (donelen < arg->len); - - arg->xlen = arg->len; - return 0; -} - -static HCL_INLINE int flush_output (hcl_t* hcl, hcl_iooutarg_t* arg) -{ - FILE* fp; - - fp = (FILE*)arg->handle; - HCL_ASSERT (hcl, fp != HCL_NULL); - - fflush (fp); - return 0; -} - -static int print_handler (hcl_t* hcl, hcl_iocmd_t cmd, void* arg) -{ - switch (cmd) - { - case HCL_IO_OPEN: - return open_output(hcl, (hcl_iooutarg_t*)arg); - - case HCL_IO_CLOSE: - return close_output(hcl, (hcl_iooutarg_t*)arg); - - case HCL_IO_WRITE: - return write_output(hcl, (hcl_iooutarg_t*)arg); - - case HCL_IO_FLUSH: - return flush_output(hcl, (hcl_iooutarg_t*)arg); - - default: - hcl_seterrnum (hcl, HCL_EINTERN); - return -1; - } -} - -/* ========================================================================= */ - static int vm_startup (hcl_t* hcl) { xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl); @@ -769,7 +458,7 @@ count++; else if (hcl->errnum == HCL_ESYNERR) { print_synerr (hcl); - if (xtn->reader_istty && hcl_getsynerrnum(hcl) != HCL_SYNERR_EOF) + if (hcl_isstdreadertty(hcl) && hcl_getsynerrnum(hcl) != HCL_SYNERR_EOF) { /* TODO: drain remaining data in the reader including the actual input stream and buffered data in hcl */ continue; @@ -798,16 +487,16 @@ count++; } /* carry on? */ - if (!xtn->reader_istty) goto oops; + if (!hcl_isstdreadertty(hcl)) goto oops; } - else if (xtn->reader_istty) + else if (hcl_isstdreadertty(hcl)) { /* interactive mode */ execute_in_interactive_mode (hcl); } } - if (!xtn->reader_istty && hcl_getbclen(hcl) > 0) execute_in_batch_mode (hcl, verbose); + if (!hcl_isstdreadertty(hcl) && hcl_getbclen(hcl) > 0) execute_in_batch_mode (hcl, verbose); return 0; @@ -826,18 +515,20 @@ static int feed_loop (hcl_t* hcl, xtn_t* xtn, int cflags, int verbose) { hcl_ioinarg_t* inarg; - if (xtn->reader_istty) + /* override the default cnode handler. the default one simply + * compiles the expression node without execution */ + if (hcl_beginfeed (hcl, hcl_isstdreadertty(hcl)? on_fed_cnode_in_interactive_mode: HCL_NULL) <= -1) { - /* override the default cnode handler. the default one simply - * compiles the expression node without execution */ - hcl_beginfeed (hcl, on_fed_cnode_in_interactive_mode); + hcl_logbfmt (hcl, HCL_LOG_STDERR, "ERROR: cannot begin feed - [%d] %js\n", hcl_geterrnum(hcl), hcl_geterrmsg(hcl)); + goto oops; } /* [NOTE] it isn't a very nice idea to get this internal data and use it with read_input() */ inarg = hcl_getbaseinarg(hcl); while (1) { - if (read_input(hcl, inarg) <= -1) goto oops; + //if (read_input(hcl, inarg) <= -1) goto oops; + if (hcl_readbaseinraw(hcl) <= -1) goto oops; if (inarg->xlen <= 0) break; if (hcl_feed(hcl, inarg->buf, inarg->xlen) <= -1) goto feed_error; } @@ -849,7 +540,7 @@ static int feed_loop (hcl_t* hcl, xtn_t* xtn, int cflags, int verbose) goto oops; /* TODO: proceed or just exit? */ } - if (!xtn->reader_istty && hcl_getbclen(hcl) > 0) execute_in_batch_mode (hcl, verbose); + if (!hcl_isstdreadertty(hcl) && hcl_getbclen(hcl) > 0) execute_in_batch_mode (hcl, verbose); return 0; oops: @@ -1015,7 +706,8 @@ int main (int argc, char* argv[]) xtn->read_path = argv[opt.ind++]; if (opt.ind < argc) xtn->print_path = argv[opt.ind++]; - if (hcl_attachio(hcl, read_handler, print_handler) <= -1) + //if (hcl_attachio(hcl, read_handler, print_handler) <= -1) + if (hcl_attachiostdwithbcstr(hcl, xtn->read_path, xtn->print_path) <= -1) { hcl_logbfmt (hcl, HCL_LOG_STDERR, "ERROR: cannot attach IO streams - [%d] %js\n", hcl_geterrnum(hcl), hcl_geterrmsg(hcl)); goto oops; @@ -1051,7 +743,7 @@ int main (int argc, char* argv[]) #endif cflags = 0; - if (xtn->reader_istty) cflags = HCL_COMPILE_CLEAR_CODE | HCL_COMPILE_CLEAR_FNBLK; + if (hcl_isstdreadertty(hcl)) cflags = HCL_COMPILE_CLEAR_CODE | HCL_COMPILE_CLEAR_FNBLK; if (experimental) { diff --git a/lib/Makefile.am b/lib/Makefile.am index da954c8..ef72bb7 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -107,7 +107,7 @@ libhclx_la_SOURCES = \ tmr.c hcl-tmr.h \ xutl.c xutl-sa.h hcl-xutl.h \ json.c hcl-json.h \ - hcl-s.c hcl-s.h \ + hcl-s.c hcl-s2.c hcl-s.h \ hcl-c.c hcl-c.h libhclx_la_CPPFLAGS = $(CPPFLAGS_LIB_COMMON) $(CPPFLAGS_PFMOD) libhclx_la_LDFLAGS = $(LDFLAGS_LIB_COMMON) diff --git a/lib/Makefile.in b/lib/Makefile.in index dbf646f..9ee5fae 100644 --- a/lib/Makefile.in +++ b/lib/Makefile.in @@ -170,10 +170,12 @@ libhcl_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ @ENABLE_HCLX_TRUE@libhclx_la_DEPENDENCIES = libhcl.la \ @ENABLE_HCLX_TRUE@ $(am__DEPENDENCIES_5) am__libhclx_la_SOURCES_DIST = tmr.c hcl-tmr.h xutl.c xutl-sa.h \ - hcl-xutl.h json.c hcl-json.h hcl-s.c hcl-s.h hcl-c.c hcl-c.h + hcl-xutl.h json.c hcl-json.h hcl-s.c hcl-s2.c hcl-s.h hcl-c.c \ + hcl-c.h @ENABLE_HCLX_TRUE@am_libhclx_la_OBJECTS = libhclx_la-tmr.lo \ @ENABLE_HCLX_TRUE@ libhclx_la-xutl.lo libhclx_la-json.lo \ -@ENABLE_HCLX_TRUE@ libhclx_la-hcl-s.lo libhclx_la-hcl-c.lo +@ENABLE_HCLX_TRUE@ libhclx_la-hcl-s.lo libhclx_la-hcl-s2.lo \ +@ENABLE_HCLX_TRUE@ libhclx_la-hcl-c.lo libhclx_la_OBJECTS = $(am_libhclx_la_OBJECTS) libhclx_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ @@ -209,6 +211,7 @@ am__depfiles_remade = ./$(DEPDIR)/libhcl_la-bigint.Plo \ ./$(DEPDIR)/libhcl_la-utl.Plo ./$(DEPDIR)/libhcl_la-xma.Plo \ ./$(DEPDIR)/libhclx_la-hcl-c.Plo \ ./$(DEPDIR)/libhclx_la-hcl-s.Plo \ + ./$(DEPDIR)/libhclx_la-hcl-s2.Plo \ ./$(DEPDIR)/libhclx_la-json.Plo ./$(DEPDIR)/libhclx_la-tmr.Plo \ ./$(DEPDIR)/libhclx_la-xutl.Plo am__mv = mv -f @@ -468,7 +471,7 @@ libhcl_la_LIBADD = $(LIBADD_LIB_COMMON) $(am__append_6) @ENABLE_HCLX_TRUE@ tmr.c hcl-tmr.h \ @ENABLE_HCLX_TRUE@ xutl.c xutl-sa.h hcl-xutl.h \ @ENABLE_HCLX_TRUE@ json.c hcl-json.h \ -@ENABLE_HCLX_TRUE@ hcl-s.c hcl-s.h \ +@ENABLE_HCLX_TRUE@ hcl-s.c hcl-s2.c hcl-s.h \ @ENABLE_HCLX_TRUE@ hcl-c.c hcl-c.h @ENABLE_HCLX_TRUE@libhclx_la_CPPFLAGS = $(CPPFLAGS_LIB_COMMON) $(CPPFLAGS_PFMOD) @@ -597,6 +600,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhcl_la-xma.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhclx_la-hcl-c.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhclx_la-hcl-s.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhclx_la-hcl-s2.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhclx_la-json.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhclx_la-tmr.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhclx_la-xutl.Plo@am__quote@ # am--include-marker @@ -827,6 +831,13 @@ libhclx_la-hcl-s.lo: hcl-s.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhclx_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhclx_la-hcl-s.lo `test -f 'hcl-s.c' || echo '$(srcdir)/'`hcl-s.c +libhclx_la-hcl-s2.lo: hcl-s2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhclx_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libhclx_la-hcl-s2.lo -MD -MP -MF $(DEPDIR)/libhclx_la-hcl-s2.Tpo -c -o libhclx_la-hcl-s2.lo `test -f 'hcl-s2.c' || echo '$(srcdir)/'`hcl-s2.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libhclx_la-hcl-s2.Tpo $(DEPDIR)/libhclx_la-hcl-s2.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hcl-s2.c' object='libhclx_la-hcl-s2.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhclx_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhclx_la-hcl-s2.lo `test -f 'hcl-s2.c' || echo '$(srcdir)/'`hcl-s2.c + libhclx_la-hcl-c.lo: hcl-c.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhclx_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libhclx_la-hcl-c.lo -MD -MP -MF $(DEPDIR)/libhclx_la-hcl-c.Tpo -c -o libhclx_la-hcl-c.lo `test -f 'hcl-c.c' || echo '$(srcdir)/'`hcl-c.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libhclx_la-hcl-c.Tpo $(DEPDIR)/libhclx_la-hcl-c.Plo @@ -1015,6 +1026,7 @@ distclean: distclean-am -rm -f ./$(DEPDIR)/libhcl_la-xma.Plo -rm -f ./$(DEPDIR)/libhclx_la-hcl-c.Plo -rm -f ./$(DEPDIR)/libhclx_la-hcl-s.Plo + -rm -f ./$(DEPDIR)/libhclx_la-hcl-s2.Plo -rm -f ./$(DEPDIR)/libhclx_la-json.Plo -rm -f ./$(DEPDIR)/libhclx_la-tmr.Plo -rm -f ./$(DEPDIR)/libhclx_la-xutl.Plo @@ -1090,6 +1102,7 @@ maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/libhcl_la-xma.Plo -rm -f ./$(DEPDIR)/libhclx_la-hcl-c.Plo -rm -f ./$(DEPDIR)/libhclx_la-hcl-s.Plo + -rm -f ./$(DEPDIR)/libhclx_la-hcl-s2.Plo -rm -f ./$(DEPDIR)/libhclx_la-json.Plo -rm -f ./$(DEPDIR)/libhclx_la-tmr.Plo -rm -f ./$(DEPDIR)/libhclx_la-xutl.Plo diff --git a/lib/comp.c b/lib/comp.c index fe39acb..b231ff0 100644 --- a/lib/comp.c +++ b/lib/comp.c @@ -395,7 +395,7 @@ HCL_INFO2 (hcl, "CLASS NAMED VAR [%.*js]\n", name->len, name->ptr); } } -HCL_INFO2 (hcl, "NOT FOUND => %.*js\n", name->len, name->ptr); +//HCL_INFO2 (hcl, "NOT FOUND => %.*js\n", name->len, name->ptr); return 0; /* not found */ } diff --git a/lib/err.c b/lib/err.c index 0d3b96d..d6d4992 100644 --- a/lib/err.c +++ b/lib/err.c @@ -187,11 +187,47 @@ const hcl_ooch_t* hcl_geterrstr (hcl_t* hcl) return hcl_errnum_to_errstr(hcl->errnum); } +/* const hcl_ooch_t* hcl_geterrmsg (hcl_t* hcl) { if (hcl->errmsg.len <= 0) return hcl_errnum_to_errstr(hcl->errnum); return hcl->errmsg.buf; } +*/ + +const hcl_bch_t* hcl_geterrbmsg (hcl_t* hcl) +{ +#if defined(HCL_OOCH_IS_BCH) + return (hcl->errmsg.len <= 0)? hcl_errnum_to_errstr(hcl->errnum): hcl->errmsg.buf; +#else + const hcl_ooch_t* msg; + hcl_oow_t wcslen, mbslen; + + msg = (hcl->errmsg.len <= 0)? hcl_errnum_to_errstr(hcl->errnum): hcl->errmsg.buf; + + mbslen = HCL_COUNTOF(hcl->errmsg.xerrmsg); + hcl_conv_ucstr_to_bcstr_with_cmgr (msg, &wcslen, hcl->errmsg.xerrmsg, &mbslen, hcl_getcmgr(hcl)); + + return hcl->errmsg.xerrmsg; +#endif +} + +const hcl_uch_t* hcl_geterrumsg (hcl_t* hcl) +{ +#if defined(HCL_OOCH_IS_BCH) + const hcl_ooch_t* msg; + hcl_oow_t wcslen, mbslen; + + msg = (hcl->errmsg.len <= 0)? hcl_errnum_to_errstrerrstr(hcl->errnum): hcl->errmsg.buf; + + wcslen = HCL_COUNTOF(hcl->errmsg.xerrmsg); + hcl_conv_bcstr_to_ucstr_with_cmgr (msg, &mbslen, hcl->errmsg.xerrmsg, &wcslen, hcl_getcmgr(hcl), 1); + + return hcl->errmsg.xerrmsg; +#else + return (hcl->errmsg.len == '\0')? hcl_errnum_to_errstr(hcl->errnum): hcl->errmsg.buf; +#endif +} const hcl_ooch_t* hcl_backuperrmsg (hcl_t* hcl) { diff --git a/lib/fmt.c b/lib/fmt.c index 8362a03..2cc8fca 100644 --- a/lib/fmt.c +++ b/lib/fmt.c @@ -1803,15 +1803,15 @@ static int print_bcs (hcl_fmtout_t* fmtout, const hcl_bch_t* ptr, hcl_oow_t len) ucsptr = ucsbuf; while (ucslen > 0) { - hcl->c->outarg.ptr = ucsptr; - hcl->c->outarg.len = ucslen; + hcl->io.outarg.ptr = ucsptr; + hcl->io.outarg.len = ucslen; - if (hcl->c->printer(hcl, HCL_IO_WRITE, &hcl->c->outarg) <= -1) return -1; - if (hcl->c->outarg.xlen <= 0) return 0; /* end of stream. but not failure */ + if (hcl->io.printer(hcl, HCL_IO_WRITE, &hcl->io.outarg) <= -1) return -1; + if (hcl->io.outarg.xlen <= 0) return 0; /* end of stream. but not failure */ - HCL_ASSERT (hcl, hcl->c->outarg.xlen <= len); - ucsptr += hcl->c->outarg.xlen; - ucslen -= hcl->c->outarg.xlen; + HCL_ASSERT (hcl, hcl->io.outarg.xlen <= len); + ucsptr += hcl->io.outarg.xlen; + ucslen -= hcl->io.outarg.xlen; } ptr += bcslen; @@ -1823,15 +1823,15 @@ static int print_bcs (hcl_fmtout_t* fmtout, const hcl_bch_t* ptr, hcl_oow_t len) optr = (hcl_bch_t*)ptr; while (len > 0) { - hcl->c->outarg.ptr = optr; - hcl->c->outarg.len = len; + hcl->io.outarg.ptr = optr; + hcl->io.outarg.len = len; - if (hcl->c->printer(hcl, HCL_IO_WRITE, &hcl->c->outarg) <= -1) return -1; - if (hcl->c->outarg.xlen <= 0) return 0; /* end of stream. but not failure */ + if (hcl->io.printer(hcl, HCL_IO_WRITE, &hcl->io.outarg) <= -1) return -1; + if (hcl->io.outarg.xlen <= 0) return 0; /* end of stream. but not failure */ - HCL_ASSERT (hcl, hcl->c->outarg.xlen <= len); - optr += hcl->c->outarg.xlen; - len -= hcl->c->outarg.xlen; + HCL_ASSERT (hcl, hcl->io.outarg.xlen <= len); + optr += hcl->io.outarg.xlen; + len -= hcl->io.outarg.xlen; } #endif @@ -1848,15 +1848,15 @@ static int print_ucs (hcl_fmtout_t* fmtout, const hcl_uch_t* ptr, hcl_oow_t len) optr = (hcl_uch_t*)ptr; while (len > 0) { - hcl->c->outarg.ptr = optr; - hcl->c->outarg.len = len; + hcl->io.outarg.ptr = optr; + hcl->io.outarg.len = len; - if (hcl->c->printer(hcl, HCL_IO_WRITE, &hcl->c->outarg) <= -1) return -1; - if (hcl->c->outarg.xlen <= 0) return 0; /* end of stream. but not failure */ + if (hcl->io.printer(hcl, HCL_IO_WRITE, &hcl->io.outarg) <= -1) return -1; + if (hcl->io.outarg.xlen <= 0) return 0; /* end of stream. but not failure */ - HCL_ASSERT (hcl, hcl->c->outarg.xlen <= len); - optr += hcl->c->outarg.xlen; - len -= hcl->c->outarg.xlen; + HCL_ASSERT (hcl, hcl->io.outarg.xlen <= len); + optr += hcl->io.outarg.xlen; + len -= hcl->io.outarg.xlen; } #else hcl_oow_t bcslen, ucslen; @@ -1871,15 +1871,15 @@ static int print_ucs (hcl_fmtout_t* fmtout, const hcl_uch_t* ptr, hcl_oow_t len) bcsptr = bcsbuf; while (bcslen > 0) { - hcl->c->outarg.ptr = bcsptr; - hcl->c->outarg.len = bcslen; + hcl->io.outarg.ptr = bcsptr; + hcl->io.outarg.len = bcslen; - if (hcl->c->printer(hcl, HCL_IO_WRITE, &hcl->c->outarg) <= -1) return -1; - if (hcl->c->outarg.xlen <= 0) return 0; /* end of stream. but not failure */ + if (hcl->io.printer(hcl, HCL_IO_WRITE, &hcl->io.outarg) <= -1) return -1; + if (hcl->io.outarg.xlen <= 0) return 0; /* end of stream. but not failure */ - HCL_ASSERT (hcl, hcl->c->outarg.xlen <= len); - bcsptr += hcl->c->outarg.xlen; - bcslen -= hcl->c->outarg.xlen; + HCL_ASSERT (hcl, hcl->io.outarg.xlen <= len); + bcsptr += hcl->io.outarg.xlen; + bcslen -= hcl->io.outarg.xlen; } ptr += ucslen; diff --git a/lib/hcl-prv.h b/lib/hcl-prv.h index 47e0a22..2a6e84b 100644 --- a/lib/hcl-prv.h +++ b/lib/hcl-prv.h @@ -639,9 +639,8 @@ struct hcl_frd_t struct hcl_compiler_t { - /* output handler */ - hcl_ioimpl_t printer; - hcl_iooutarg_t outarg; + /* callback pointer registerd upon compiler creation */ + hcl_cb_t* cbp; /* input handler */ hcl_ioimpl_t reader; diff --git a/lib/hcl.h b/lib/hcl.h index 1923ae6..8658687 100644 --- a/lib/hcl.h +++ b/lib/hcl.h @@ -1487,8 +1487,14 @@ struct hcl_t hcl_bch_t bch[HCL_ERRMSG_CAPA]; hcl_uch_t uch[HCL_ERRMSG_CAPA]; } tmpbuf; + #if defined(HCL_OOCH_IS_BCH) + hcl_uch_t xerrmsg[HCL_ERRMSG_CAPA]; + #else + hcl_bch_t xerrmsg[HCL_ERRMSG_CAPA * 2]; + #endif hcl_ooch_t buf[HCL_ERRMSG_CAPA]; hcl_oow_t len; + } errmsg; int shuterr; @@ -1715,6 +1721,13 @@ struct hcl_t } stat; } gci; + struct + { + /* output handler */ + hcl_ioimpl_t printer; + hcl_iooutarg_t outarg; + } io; + #if defined(HCL_INCLUDE_COMPILER) hcl_compiler_t* c; #endif @@ -2040,10 +2053,20 @@ HCL_EXPORT const hcl_ooch_t* hcl_geterrstr ( hcl_t* hcl ); -HCL_EXPORT const hcl_ooch_t* hcl_geterrmsg ( - hcl_t* hcl +HCL_EXPORT const hcl_uch_t* hcl_geterrumsg ( + hcl_t* hio ); +HCL_EXPORT const hcl_bch_t* hcl_geterrbmsg ( + hcl_t* hio +); + +#if defined(HCL_OOCH_IS_UCH) +# define hcl_geterrmsg hcl_geterrumsg +#else +# define hcl_geterrmsg hcl_geterrbmsg +#endif + HCL_EXPORT const hcl_ooch_t* hcl_backuperrmsg ( hcl_t* hcl ); @@ -2142,10 +2165,16 @@ HCL_EXPORT void hcl_abort ( # define hcl_switchprocess(hcl) ((hcl)->switch_proc = 1) #endif +/* TODO: don't expose hcl_getbaseinarg(), and hcl_readbaseinraw() + * find a better way not to use them */ HCL_EXPORT hcl_ioinarg_t* hcl_getbaseinarg ( hcl_t* hcl ); +HCL_EXPORT int hcl_readbaseinraw ( + hcl_t* hcl +); + HCL_EXPORT void hcl_setbaseinloc ( hcl_t* hcl, hcl_oow_t line, @@ -2164,6 +2193,16 @@ HCL_EXPORT int hcl_attachio ( hcl_ioimpl_t printer ); +HCL_EXPORT int hcl_attachiostdwithbcstr ( + hcl_t* hcl, + const hcl_bch_t* read_file, + const hcl_bch_t* print_file +); + +HCL_EXPORT int hcl_isstdreadertty ( + hcl_t* hcl +); + HCL_EXPORT void hcl_detachio ( hcl_t* hcl ); @@ -2202,7 +2241,7 @@ HCL_EXPORT void hcl_freecnode ( hcl_cnode_t* cnode ); -HCL_EXPORT void hcl_beginfeed ( +HCL_EXPORT int hcl_beginfeed ( hcl_t* hcl, hcl_on_cnode_t on_cnode ); @@ -2213,7 +2252,9 @@ HCL_EXPORT int hcl_feed ( hcl_oow_t len ); -#define hcl_endfeed(hcl) (hcl_feed((hcl), HCL_NULL, 0)) +HCL_EXPORT int hcl_endfeed ( + hcl_t* hcl +); HCL_EXPORT int hcl_compile ( hcl_t* hcl, diff --git a/lib/print.c b/lib/print.c index f336a47..88eb767 100644 --- a/lib/print.c +++ b/lib/print.c @@ -778,7 +778,7 @@ int hcl_outfmtobj (hcl_t* hcl, hcl_bitmask_t mask, hcl_oop_t obj, hcl_outbfmt_t int hcl_print (hcl_t* hcl, hcl_oop_t obj) { - HCL_ASSERT (hcl, hcl->c->printer != HCL_NULL); + HCL_ASSERT (hcl, hcl->io.printer != HCL_NULL); /*return hcl_outfmtobj(hcl, HCL_LOG_APP | HCL_LOG_FATAL, obj);*/ return hcl_prbfmt(hcl, "%O", obj); } diff --git a/lib/read.c b/lib/read.c index ed03e6c..38bc4ea 100644 --- a/lib/read.c +++ b/lib/read.c @@ -97,6 +97,7 @@ enum list_flag_t #define LIST_FLAG_GET_CONCODE(x) (((x) >> 8) & 0xFF) #define LIST_FLAG_SET_CONCODE(x,type) ((x) = ((x) & ~0xFF00) | ((type) << 8)) +static int init_compiler (hcl_t* hcl); static int string_to_ooi (hcl_t* hcl, hcl_oocs_t* str, int radixed, hcl_ooi_t* num) { @@ -326,7 +327,7 @@ static HCL_INLINE int is_alnumchar (hcl_ooci_t c) static HCL_INLINE int is_delimchar (hcl_ooci_t c) { return c == '(' || c == ')' || c == '[' || c == ']' || c == '{' || c == '}' || - c == ';' || c == '|' || c == ',' || c == '.' || c == ':' || + c == ';' || c == '|' || c == ',' || c == '.' || c == ':' || /* the first characters of tokens in delim_token_tab up to this point */ c == '#' || c == '\"' || c == '\'' || is_spacechar(c) || c == HCL_UCI_EOF; } @@ -437,12 +438,12 @@ static HCL_INLINE void unget_char (hcl_t* hcl, const hcl_iolxc_t* c) static int get_directive_token_type (hcl_t* hcl, hcl_iotok_type_t* tok_type) { - if (does_token_name_match(hcl, VOCA_INCLUDE)) + if (does_token_name_match(hcl, VOCA_INCLUDE)) { *tok_type = HCL_IOTOK_INCLUDE; return 0; } - else if (does_token_name_match(hcl, VOCA_PRAGMA)) + else if (does_token_name_match(hcl, VOCA_PRAGMA)) { *tok_type = HCL_IOTOK_PRAGMA; return 0; @@ -1132,7 +1133,7 @@ retry: hcl_iolxc_t sd; hcl_ooci_t oldc2; - sd = hcl->c->lxc; + sd = hcl->c->lxc; oldc2 = c; GET_CHAR_TO (hcl, c); @@ -1446,7 +1447,8 @@ static int begin_include (hcl_t* hcl) if (hcl->c->reader(hcl, HCL_IO_OPEN, arg) <= -1) { - hcl_setsynerrbfmt (hcl, HCL_SYNERR_INCLUDE, TOKEN_LOC(hcl), TOKEN_NAME(hcl), "unable to include %js", io_name); + const hcl_ooch_t* org_errmsg = hcl_backuperrmsg(hcl); + hcl_setsynerrbfmt (hcl, HCL_SYNERR_INCLUDE, TOKEN_LOC(hcl), TOKEN_NAME(hcl), "unable to include %js - %js", io_name, org_errmsg); goto oops; } @@ -1574,7 +1576,7 @@ static HCL_INLINE hcl_cnode_t* leave_list (hcl_t* hcl, int* flagv, int* oldflagv * (lambda () ...) is equivalent to (lambda #nil ...) * (defun x() ...) */ - if (head) + if (head) { HCL_ASSERT (hcl, HCL_CNODE_IS_CONS(head)); HCL_CNODE_CONS_CONCODE(head) = concode; @@ -1694,7 +1696,7 @@ static int chain_to_list (hcl_t* hcl, hcl_cnode_t* obj) hcl_cnode_t* shell; /* if the last element is another non-data list - * for example, #( 1 2 . [ 3 4 5 ]) + * for example, #( 1 2 . [ 3 4 5 ]) * use a shell node to wrap the actual object list node head * for the compiler. */ @@ -1785,7 +1787,7 @@ static hcl_cnode_t* read_vlist (hcl_t* hcl) if (HCL_UNLIKELY(!sym)) goto oops; cons = hcl_makecnodecons(hcl, HCL_CNODE_GET_LOC(sym), sym, HCL_NULL); - if (HCL_UNLIKELY(!cons)) + if (HCL_UNLIKELY(!cons)) { hcl_freesinglecnode (hcl, sym); /* manual disposal because sym is not chained to the list */ goto oops; @@ -1884,7 +1886,7 @@ static hcl_cnode_t* read_object (hcl_t* hcl) flagv = 0; LIST_FLAG_SET_CONCODE (flagv, HCL_CONCODE_MLIST); goto start_list; - + case HCL_IOTOK_LPAREN: /* ( */ flagv = 0; LIST_FLAG_SET_CONCODE (flagv, HCL_CONCODE_XLIST); @@ -2153,10 +2155,10 @@ static hcl_cnode_t* read_object (hcl_t* hcl) * if we are not at the top level, we must be in a list */ if (chain_to_list(hcl, obj) <= -1) goto oops; - /* because it has been chained to the list, it belongs to the current stack top. + /* because it has been chained to the list, it belongs to the current stack top. * mark that obj is not stand-alone by nullifying it. without this, if a jump * is made to oops, the momory block pointed to by obj may get freed twice. */ - obj = HCL_NULL; + obj = HCL_NULL; clear_comma_colon_flag (hcl); @@ -2205,9 +2207,9 @@ hcl_cnode_t* hcl_read (hcl_t* hcl) hcl_cnodetoobj (hcl_t* hcl, hcl_cnode_t* x) { * drop location information and compose object ?? - * is it doable? can convert a dotted symbol to a proper value? + * is it doable? can convert a dotted symbol to a proper value? } -*/ +*/ /* ---------------------------------------------------------------------- */ @@ -2252,11 +2254,12 @@ static int feed_begin_include (hcl_t* hcl) if (hcl->c->reader(hcl, HCL_IO_OPEN, arg) <= -1) { - hcl_setsynerrbfmt (hcl, HCL_SYNERR_INCLUDE, TOKEN_LOC(hcl), TOKEN_NAME(hcl), "unable to include %js", io_name); + const hcl_ooch_t* org_errmsg = hcl_backuperrmsg(hcl); + hcl_setsynerrbfmt (hcl, HCL_SYNERR_INCLUDE, TOKEN_LOC(hcl), TOKEN_NAME(hcl), "unable to feed-include %js - %js", io_name, org_errmsg); goto oops; } - if (arg->includer == &hcl->c->inarg) + if (arg->includer == &hcl->c->inarg) /* top-level include */ { /* TODO: remove hcl_readbaseinchar() and clean up this part. * hcl_readbaseinchar(), if called in the middle of feeds, @@ -2297,8 +2300,8 @@ 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, + /* 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; @@ -2351,9 +2354,9 @@ static int feed_process_token (hcl_t* hcl) frd->expect_include_file = 0; /* indicate that the file inclusion should be performed soon. - * don't perform actual inclusion here so that the return value of + * don't perform actual inclusion here so that the return value of * feed_char() advances the input pointers properly. */ - frd->do_include_file = 1; + frd->do_include_file = 1; goto ok; } @@ -2394,7 +2397,7 @@ static int feed_process_token (hcl_t* hcl) else { /* opener */ - + /* the vlist is different from other lists in that * it uses the same opener and the closer * it allows only variable names. @@ -2409,7 +2412,7 @@ static int feed_process_token (hcl_t* hcl) /* neither a data list nor an executable list. handle this specially using * a dedicated frd->expect_vlist_item variable */ - frd->flagv = 0; + frd->flagv = 0; LIST_FLAG_SET_CONCODE (frd->flagv, HCL_CONCODE_VLIST); frd->expect_vlist_item = 1; goto start_list; @@ -2439,7 +2442,7 @@ static int feed_process_token (hcl_t* hcl) frd->flagv = 0; LIST_FLAG_SET_CONCODE (frd->flagv, HCL_CONCODE_MLIST); goto start_list; - + case HCL_IOTOK_LPAREN: /* ( */ frd->flagv = 0; LIST_FLAG_SET_CONCODE (frd->flagv, HCL_CONCODE_XLIST); @@ -2687,7 +2690,7 @@ static int feed_process_token (hcl_t* hcl) #endif /* check if we are at the top frd->level */ - if (frd->level <= 0) + if (frd->level <= 0) { int n; @@ -2708,10 +2711,10 @@ static int feed_process_token (hcl_t* hcl) * if we are not at the top frd->level, we must be in a list */ if (chain_to_list(hcl, frd->obj) <= -1) goto oops; - /* because it has been chained to the list, it belongs to the current stack top. + /* because it has been chained to the list, it belongs to the current stack top. * mark that obj is not stand-alone by nullifying it. without this, if a jump * is made to oops, the momory block pointed to by obj may get freed twice. */ - frd->obj = HCL_NULL; + frd->obj = HCL_NULL; clear_comma_colon_flag (hcl); } @@ -2720,7 +2723,7 @@ ok: return 0; oops: - if (frd->obj) + if (frd->obj) { hcl_freecnode (hcl, frd->obj); frd->obj = HCL_NULL; @@ -2752,17 +2755,17 @@ typedef struct delim_token_t delim_token_t; static delim_token_t delim_token_tab[] = { - /* [NOTE 1] - * if you add a new token, ensure the first character is listed in is_delimchar() - * + /* [NOTE 1] + * if you add a new token, ensure the first character is listed in is_delimchar() + * * [NOTE 2] * for the implementation limitation in find_delim_token_char(), * the entries in this table must be laid out in a certain way. - * + * * Group the items with the same prefix together. * List the shorter before the longer items in the same group. * The length must not differ by greater than 1 between 2 items in the same group. - * + * * [NOTE 3] * don't list #( and #[ here because of overlapping use of # for various purposes. * however, # is included in is_delimchar(). @@ -2774,7 +2777,7 @@ static delim_token_t delim_token_tab[] = { "[", 1, HCL_IOTOK_LBRACK }, { "]", 1, HCL_IOTOK_RBRACK }, - + { "{", 1, HCL_IOTOK_LBRACE }, { "}", 1, HCL_IOTOK_RBRACE }, @@ -2797,7 +2800,7 @@ static int find_delim_token_char (hcl_t* hcl, const hcl_ooci_t c, int row_start, for (i = row_start; i <= row_end; i++) { - if (col < delim_token_tab[i].t_len && c == delim_token_tab[i].t_value[col]) + if (col < delim_token_tab[i].t_len && c == delim_token_tab[i].t_value[col]) { if (!found) dt->row_start = i; dt->row_end = i; @@ -2930,10 +2933,10 @@ static int flx_start (hcl_t* hcl, hcl_ooci_t c) reset_flx_token (hcl); //HCL_DEBUG1 (hcl, "XXX[%jc]\n", c); - if (find_delim_token_char(hcl, c, 0, HCL_COUNTOF(delim_token_tab) - 1, 0, FLX_DT(hcl))) + if (find_delim_token_char(hcl, c, 0, HCL_COUNTOF(delim_token_tab) - 1, 0, FLX_DT(hcl))) { /* the character is one of the first character of a delimiter token such as (, [, :, etc */ - if (FLX_DT(hcl)->row_start == FLX_DT(hcl)->row_end && + if (FLX_DT(hcl)->row_start == FLX_DT(hcl)->row_end && FLX_DT(hcl)->col_next == delim_token_tab[FLX_DT(hcl)->row_start].t_len) { /* single character delimiter token */ @@ -3006,13 +3009,13 @@ static int flx_comment (hcl_t* hcl, hcl_ooci_t c) static int flx_delim_token (hcl_t* hcl, hcl_ooci_t c) { - if (find_delim_token_char(hcl, c, FLX_DT(hcl)->row_start, FLX_DT(hcl)->row_end, FLX_DT(hcl)->col_next, FLX_DT(hcl))) + if (find_delim_token_char(hcl, c, FLX_DT(hcl)->row_start, FLX_DT(hcl)->row_end, FLX_DT(hcl)->col_next, FLX_DT(hcl))) { - if (FLX_DT(hcl)->row_start == FLX_DT(hcl)->row_end && + if (FLX_DT(hcl)->row_start == FLX_DT(hcl)->row_end && FLX_DT(hcl)->col_next == delim_token_tab[FLX_DT(hcl)->row_start].t_len) { /* complete token and switch to the HCL_FLX_START state */ - FEED_WRAP_UP_WITH_CHAR (hcl, c, delim_token_tab[FLX_DT(hcl)->row_start].t_type); + FEED_WRAP_UP_WITH_CHAR (hcl, c, delim_token_tab[FLX_DT(hcl)->row_start].t_type); } else { @@ -3023,7 +3026,7 @@ static int flx_delim_token (hcl_t* hcl, hcl_ooci_t c) else { /* the longest match so far */ - FEED_WRAP_UP(hcl, delim_token_tab[FLX_DT(hcl)->row_start].t_type); + FEED_WRAP_UP(hcl, delim_token_tab[FLX_DT(hcl)->row_start].t_type); goto not_consumed; } @@ -3341,7 +3344,7 @@ static int flx_plain_ident (hcl_t* hcl, hcl_ooci_t c) /* identifier */ seg.ptr = &TOKEN_NAME_CHAR(hcl, start); seg.len = pi->seg_len; tok_type = classify_ident_token(hcl, &seg); - if (tok_type != HCL_IOTOK_IDENT) + if (tok_type != HCL_IOTOK_IDENT) { pi->non_ident_seg_count++; pi->last_non_ident_type = tok_type; @@ -3630,7 +3633,7 @@ static int flx_signed_token (hcl_t* hcl, hcl_ooci_t c) reset_flx_token (hcl); /* the current character is on the same line as the hash mark, the column must be greater than 1 */ - HCL_ASSERT (hcl, FLX_LOC(hcl)->colm > 1); + HCL_ASSERT (hcl, FLX_LOC(hcl)->colm > 1); FLX_LOC(hcl)->colm--; /* move back one character location by decrementing the column number */ ADD_TOKEN_CHAR (hcl, '#'); FEED_CONTINUE (hcl, HCL_FLX_HMARKED_TOKEN); @@ -3649,10 +3652,10 @@ static int flx_signed_token (hcl_t* hcl, hcl_ooci_t c) { init_flx_pi (FLX_PI(hcl)); - /* the sign is already in the token name buffer. + /* the sign is already in the token name buffer. * adjust the state data for the sign. */ HCL_ASSERT (hcl, TOKEN_NAME_LEN(hcl) == 1); - FLX_PI(hcl)->char_count++; + FLX_PI(hcl)->char_count++; FLX_PI(hcl)->seg_len++; /* let refeeding of 'c' happen at the next iteration */ @@ -3737,7 +3740,7 @@ static int feed_from_includee (hcl_t* hcl) x = feed_char(hcl, hcl->c->curinp->buf[hcl->c->curinp->b.pos]); if (x <= -1) return -1; - if (x >= 1) + if (x >= 1) { /* consumed */ feed_update_lx_loc (hcl, hcl->c->curinp->buf[hcl->c->curinp->b.pos]); @@ -3746,7 +3749,7 @@ static int feed_from_includee (hcl_t* hcl) if (hcl->c->feed.rd.do_include_file) { - /* feed_process_token(), called for the "filename" token for the #include + /* 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. */ @@ -3759,29 +3762,38 @@ static int feed_from_includee (hcl_t* hcl) return 0; } -void hcl_beginfeed (hcl_t* hcl, hcl_on_cnode_t on_cnode) +int hcl_beginfeed (hcl_t* hcl, hcl_on_cnode_t on_cnode) { + HCL_ASSERT (hcl, hcl->c != HCL_NULL); /* call hcl_attachio() or hcl_attachiostd() first */ + init_feed (hcl); if (on_cnode) hcl->c->feed.on_cnode = on_cnode; - /* if you pass HCL_NULL for on_cnode, hcl->c->feed.on_cnode resets + /* if you pass HCL_NULL for on_cnode, hcl->c->feed.on_cnode resets * back to the default handler in init_feed() */ + + return 0; +} + +int hcl_endfeed (hcl_t* hcl) +{ + return hcl_feed(hcl, HCL_NULL, 0); } int hcl_feed (hcl_t* hcl, const hcl_ooch_t* data, hcl_oow_t len) { /* TODO: need to return the number of processed characters? * need to stop after the first complete expression? */ - hcl_oow_t i; int x; - if (data) + HCL_ASSERT (hcl, hcl->c != HCL_NULL); + if (data) { - for (i = 0; i < len; ) + for (i = 0; i < len; ) { x = feed_char(hcl, data[i]); if (x <= -1) return -1; /* TODO: return the number of processed characters via an argument? */ - + if (x > 0) { /* consumed */ @@ -3795,7 +3807,7 @@ int hcl_feed (hcl_t* hcl, const hcl_ooch_t* data, hcl_oow_t len) hcl->c->feed.rd.do_include_file = 0; } - if (hcl->c->curinp != &hcl->c->inarg && feed_from_includee(hcl) <= -1) + if (hcl->c->curinp && hcl->c->curinp != &hcl->c->inarg && feed_from_includee(hcl) <= -1) { /* TODO: return the number of processed characters via an argument? */ return -1; @@ -3809,12 +3821,12 @@ int hcl_feed (hcl_t* hcl, const hcl_ooch_t* data, hcl_oow_t len) for (i = 0; i < 1;) /* weird loop in case feed_char() returns 0 */ { x = feed_char(hcl, HCL_OOCI_EOF); - if (x <= -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); + /* 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; } @@ -3857,13 +3869,16 @@ default callback for on_eof? /* TODO: rename compiler to something else that can include reader, printer, and compiler * move compiler intialization/finalization here to more common place */ -static void gc_compiler (hcl_t* hcl) +static void gc_compiler_cb (hcl_t* hcl) { - hcl->c->r.s = hcl_moveoop(hcl, hcl->c->r.s); - hcl->c->r.e = hcl_moveoop(hcl, hcl->c->r.e); + if (hcl->c) + { + hcl->c->r.s = hcl_moveoop(hcl, hcl->c->r.s); + hcl->c->r.e = hcl_moveoop(hcl, hcl->c->r.e); + } } -static void fini_compiler (hcl_t* hcl) +static void fini_compiler_cb (hcl_t* hcl) { /* called before the hcl object is closed */ if (hcl->c) @@ -3921,10 +3936,60 @@ static void fini_compiler (hcl_t* hcl) } } + +static void fini_compiler (hcl_t* hcl) +{ + /* unlike fini_compiler_cb(), this is to be used in some error handling + * between init_compiler success and subquent operation failure */ + if (hcl->c) + { + hcl_deregcb (hcl, hcl->c->cbp); + fini_compiler_cb (hcl); + } +} + +static int init_compiler (hcl_t* hcl) +{ + hcl_cb_t cb, * cbp = HCL_NULL; + + HCL_ASSERT (hcl, hcl->c == HCL_NULL); + + HCL_MEMSET (&cb, 0, HCL_SIZEOF(cb)); + cb.gc = gc_compiler_cb; + cb.fini = fini_compiler_cb; + cbp = hcl_regcb(hcl, &cb); + if (HCL_UNLIKELY(!cbp)) return -1; + + hcl->c = (hcl_compiler_t*)hcl_callocmem(hcl, HCL_SIZEOF(*hcl->c)); + if (HCL_UNLIKELY(!hcl->c)) + { + hcl_deregcb (hcl, cbp); + return -1; + } + + hcl->c->ilchr_ucs.ptr = &hcl->c->ilchr; + hcl->c->ilchr_ucs.len = 1; + + hcl->c->r.s = hcl->_nil; + hcl->c->r.e = hcl->_nil; + + hcl->c->cfs.top = -1; + hcl->c->cblk.depth = -1; + hcl->c->clsblk.depth = -1; + hcl->c->fnblk.depth = -1; + + init_feed (hcl); + hcl->c->cbp = cbp; + + return 0; +} + int hcl_attachio (hcl_t* hcl, hcl_ioimpl_t reader, hcl_ioimpl_t printer) { int n; - hcl_cb_t* cbp = HCL_NULL; + int inited_compiler = 0; + hcl_ioinarg_t new_inarg; + hcl_iooutarg_t new_outarg; if (!reader || !printer) { @@ -3934,94 +3999,70 @@ int hcl_attachio (hcl_t* hcl, hcl_ioimpl_t reader, hcl_ioimpl_t printer) if (!hcl->c) { - hcl_cb_t cb; - - HCL_MEMSET (&cb, 0, HCL_SIZEOF(cb)); - cb.gc = gc_compiler; - cb.fini = fini_compiler; - cbp = hcl_regcb(hcl, &cb); - if (!cbp) return -1; - - hcl->c = (hcl_compiler_t*)hcl_callocmem(hcl, HCL_SIZEOF(*hcl->c)); - if (HCL_UNLIKELY(!hcl->c)) - { - hcl_deregcb (hcl, cbp); - return -1; - } - - hcl->c->ilchr_ucs.ptr = &hcl->c->ilchr; - hcl->c->ilchr_ucs.len = 1; - - hcl->c->r.s = hcl->_nil; - hcl->c->r.e = hcl->_nil; - - hcl->c->cfs.top = -1; - hcl->c->cblk.depth = -1; - hcl->c->clsblk.depth = -1; - hcl->c->fnblk.depth = -1; - - init_feed (hcl); - } - else if (hcl->c->reader || hcl->c->printer) - { - hcl_seterrnum (hcl, HCL_EPERM); /* TODO: change this error code */ - return -1; + if (init_compiler(hcl) <= -1) return -1; + inited_compiler = 1; } +#if 0 /* Some IO names could have been stored in earlier calls to this function. - * I clear such names before i begin this function. i don't clear it - * at the end of this function because i may be referenced as an error + * I clear such names before i begin this function. i don't clear them + * at the end of this function because they may be referenced as an error * location */ clear_io_names (hcl); - - /* initialize some key fields */ - hcl->c->printer = printer; - hcl->c->reader = reader; - hcl->c->nungots = 0; +#endif /* The name field and the includer field are HCL_NULL * for the main stream */ - HCL_MEMSET (&hcl->c->inarg, 0, HCL_SIZEOF(hcl->c->inarg)); - hcl->c->inarg.line = 1; - hcl->c->inarg.colm = 1; + HCL_MEMSET (&new_inarg, 0, HCL_SIZEOF(new_inarg)); + new_inarg.line = 1; + new_inarg.colm = 1; - /* open the top-level stream */ - n = hcl->c->reader(hcl, HCL_IO_OPEN, &hcl->c->inarg); + /* open the top-level source input stream */ + n = reader(hcl, HCL_IO_OPEN, &new_inarg); if (n <= -1) goto oops; - HCL_MEMSET (&hcl->c->outarg, 0, HCL_SIZEOF(hcl->c->outarg)); - n = hcl->c->printer(hcl, HCL_IO_OPEN, &hcl->c->outarg); + /* open the new output stream */ + HCL_MEMSET (&new_outarg, 0, HCL_SIZEOF(new_outarg)); + n = printer(hcl, HCL_IO_OPEN, &new_outarg); if (n <= -1) { - hcl->c->reader (hcl, HCL_IO_CLOSE, &hcl->c->inarg); + reader (hcl, HCL_IO_CLOSE, &new_inarg); goto oops; } - /* the stream is open. set it as the current input stream */ + if (hcl->c->reader) + { + /* close the old source input stream */ + hcl->c->reader (hcl, HCL_IO_CLOSE, &hcl->c->inarg); + } + hcl->c->reader = reader; + hcl->c->inarg = new_inarg; + + if (hcl->io.printer) + { + /* close the old output stream */ + hcl->io.printer (hcl, HCL_IO_CLOSE, &hcl->io.outarg); + } + hcl->io.printer = printer; + hcl->io.outarg = new_outarg; + + /* initialize some other key fields */ + hcl->c->nungots = 0; + + /* the source stream is open. set it as the current input stream */ hcl->c->curinp = &hcl->c->inarg; + + clear_io_names (hcl); return 0; oops: - if (cbp) - { - hcl_deregcb (hcl, cbp); - hcl_freemem (hcl, hcl->c); - hcl->c = HCL_NULL; - } - else - { - hcl->c->printer = HCL_NULL; - hcl->c->reader = HCL_NULL; - } + if (inited_compiler) fini_compiler (hcl); return -1; } void hcl_flushio (hcl_t* hcl) { - if (hcl->c) - { - if (hcl->c->printer) hcl->c->printer (hcl, HCL_IO_FLUSH, &hcl->c->outarg); - } + if (hcl->io.printer) hcl->io.printer (hcl, HCL_IO_FLUSH, &hcl->io.outarg); } void hcl_detachio (hcl_t* hcl) @@ -4051,11 +4092,12 @@ void hcl_detachio (hcl_t* hcl) hcl->c->reader = HCL_NULL; /* ready for another attachment */ } - if (hcl->c->printer) - { - hcl->c->printer (hcl, HCL_IO_CLOSE, &hcl->c->outarg); - hcl->c->printer = HCL_NULL; /* ready for another attachment */ - } + } + + if (hcl->io.printer) + { + hcl->io.printer (hcl, HCL_IO_CLOSE, &hcl->io.outarg); + hcl->io.printer = HCL_NULL; /* ready for another attachment */ } } @@ -4072,10 +4114,17 @@ void hcl_setbaseinloc (hcl_t* hcl, hcl_oow_t line, hcl_oow_t colm) hcl_iolxc_t* hcl_readbaseinchar (hcl_t* hcl) { - /* read a character using the base input stream. the caller must care extra + /* read a character using the base input stream. the caller must care extra * care when using this function. this function reads the main stream regardless * of the inclusion status and ignores the ungot characters. */ int n = _get_char(hcl, &hcl->c->inarg); if (n <= -1) return HCL_NULL; return &hcl->c->inarg.lxc; } + + +int hcl_readbaseinraw (hcl_t* hcl) +{ + return hcl->c->reader(hcl, HCL_IO_READ, &hcl->c->inarg); +} + diff --git a/lib/std.c b/lib/std.c index 322b987..651c315 100644 --- a/lib/std.c +++ b/lib/std.c @@ -280,6 +280,10 @@ struct xtn_t hcl_t* next; hcl_t* prev; + const char* read_path; /* main source file */ + const char* print_path; + int reader_istty; + int vm_running; int rcv_tick; @@ -831,7 +835,7 @@ static hcl_errnum_t _syserrstrb (hcl_t* hcl, int syserr_type, int syserr_code, h case 2: #if defined(__OS2__) #if defined(TCPV40HDRS) - if (buf) + if (buf) { char tmp[64]; sprintf (tmp, "socket error %d", (int)syserr_code); @@ -2793,7 +2797,7 @@ attempt_to_bind: /* OS/2 mandates the socket name should begin with \socket\ */ sprintf (sa.sun_path, "\\socket\\hcl-%08lx-%08lx-%08lx", (unsigned long int)pib->pib_ulpid, (unsigned long int)tib->tib_ptib2->tib2_ultid, (unsigned long int)idx); - if (bind(x, (struct sockaddr*)&sa, HCL_SIZEOF(sa)) <= -1) + if (bind(x, (struct sockaddr*)&sa, HCL_SIZEOF(sa)) <= -1) { if (sock_errno() != SOCEADDRINUSE) goto oops; if (idx - msec > 9999) goto oops; /* failure after many attempts */ @@ -2813,7 +2817,7 @@ attempt_to_bind: p[0] = z; p[1] = y; return 0; - + oops: if (y >= 0) soclose (y); if (x >= 0) soclose (x); @@ -3158,3 +3162,347 @@ hcl_t* hcl_openstd (hcl_oow_t xtnsize, hcl_errnum_t* errnum) { return hcl_openstdwithmmgr(&sys_mmgr, xtnsize, errnum); } + + +/* --------------------------------------------------------------------- */ + + +typedef struct bb_t bb_t; +struct bb_t +{ + char buf[4096]; + hcl_oow_t pos; + hcl_oow_t len; + + FILE* fp; + hcl_bch_t* fn; +}; + +static const hcl_bch_t* get_base_name (const hcl_bch_t* path) +{ + const hcl_bch_t* p, * last = HCL_NULL; + + for (p = path; *p != '\0'; p++) + { + if (HCL_IS_PATH_SEP(*p)) last = p; + } + + return (last == HCL_NULL)? path: (last + 1); +} + +static HCL_INLINE int open_input (hcl_t* hcl, hcl_ioinarg_t* arg) +{ + xtn_t* xtn = GET_XTN(hcl); + bb_t* bb = HCL_NULL; + +#if defined(__DOS__) || defined(_WIN32) || defined(__OS2__) +#define FOPEN_R_FLAGS "rb" +#else +#define FOPEN_R_FLAGS "r" +#endif + +/* TOOD: support predefined include directory as well */ + if (arg->includer) + { + /* includee */ + hcl_oow_t ucslen, bcslen, parlen; + const hcl_bch_t* fn, * fb; + + #if defined(HCL_OOCH_IS_UCH) + if (hcl_convootobcstr(hcl, arg->name, &ucslen, HCL_NULL, &bcslen) <= -1) goto oops; + #else + bcslen = hcl_count_bcstr(arg->name); + #endif + + fn = ((bb_t*)arg->includer->handle)->fn; + + fb = get_base_name(fn); + parlen = fb - fn; + + bb = (bb_t*)hcl_callocmem(hcl, HCL_SIZEOF(*bb) + (HCL_SIZEOF(hcl_bch_t) * (parlen + bcslen + 1))); + if (!bb) goto oops; + + bb->fn = (hcl_bch_t*)(bb + 1); + hcl_copy_bchars (bb->fn, fn, parlen); + #if defined(HCL_OOCH_IS_UCH) + hcl_convootobcstr (hcl, arg->name, &ucslen, &bb->fn[parlen], &bcslen); + #else + hcl_copy_bcstr (&bb->fn[parlen], bcslen + 1, arg->name); + #endif + + bb->fp = fopen(bb->fn, FOPEN_R_FLAGS); + } + else + { + /* main stream */ + hcl_oow_t pathlen; + + pathlen = xtn->read_path? hcl_count_bcstr(xtn->read_path): 0; + + bb = (bb_t*)hcl_callocmem(hcl, HCL_SIZEOF(*bb) + (HCL_SIZEOF(hcl_bch_t) * (pathlen + 1))); + if (!bb) goto oops; + + bb->fn = (hcl_bch_t*)(bb + 1); + if (pathlen > 0 && xtn->read_path) + { + hcl_copy_bcstr (bb->fn, pathlen + 1, xtn->read_path); + bb->fp = fopen(bb->fn, FOPEN_R_FLAGS); + } + else + { + bb->fn[0] = '\0'; + bb->fp = stdin; + } + } + + if (!bb->fp) + { + hcl_seterrbfmt (hcl, HCL_EIOERR, "unable to open %hs", bb->fn); + goto oops; + } + + if (!arg->includer) /* if main stream */ + { + #if defined(HAVE_ISATTY) + xtn->reader_istty = isatty(fileno(bb->fp)); + #endif + + /* HACK */ + HCL_ASSERT (hcl, arg->name == HCL_NULL); + arg->name = hcl_dupbtooocstr(hcl, bb->fn, HCL_NULL); + /* ignore duplication failure */ +/* TODO: change the type of arg->name from const hcl_ooch_t* to hcl_ooch_t*. + * change its specification from [IN] only to [INOUT] in hcl_ioinarg_t. */ + /* END HACK */ + } + + arg->handle = bb; + return 0; + +oops: + if (bb) + { + if (bb->fp && bb->fp != stdin) fclose (bb->fp); + hcl_freemem (hcl, bb); + } + return -1; +} + +static HCL_INLINE int close_input (hcl_t* hcl, hcl_ioinarg_t* arg) +{ + /*xtn_t* xtn = GET_XTN(hcl);*/ + bb_t* bb; + + bb = (bb_t*)arg->handle; + HCL_ASSERT (hcl, bb != HCL_NULL && bb->fp != HCL_NULL); + +/* HACK */ + if (!arg->includer && arg->name) + { + hcl_freemem (hcl, arg->name); + arg->name = HCL_NULL; + } +/* END HACK */ + + if (bb->fp != stdin) fclose (bb->fp); + hcl_freemem (hcl, bb); + + arg->handle = HCL_NULL; + return 0; +} + +static HCL_INLINE int read_input (hcl_t* hcl, hcl_ioinarg_t* arg) +{ + /*xtn_t* xtn = GET_XTN(hcl);*/ + bb_t* bb; + hcl_oow_t bcslen, ucslen, remlen; + int x; + + bb = (bb_t*)arg->handle; + HCL_ASSERT (hcl, bb != HCL_NULL && bb->fp != HCL_NULL); + do + { + x = fgetc(bb->fp); + if (x == EOF) + { + if (ferror((FILE*)bb->fp)) + { + hcl_seterrnum (hcl, HCL_EIOERR); + return -1; + } + break; + } + + bb->buf[bb->len++] = x; + } + while (bb->len < HCL_COUNTOF(bb->buf) && x != '\r' && x != '\n'); + +#if defined(HCL_OOCH_IS_UCH) + bcslen = bb->len; + ucslen = HCL_COUNTOF(arg->buf); + x = hcl_convbtooochars(hcl, bb->buf, &bcslen, arg->buf, &ucslen); + if (x <= -1 && ucslen <= 0) return -1; + /* if ucslen is greater than 0, i assume that some characters have been + * converted properly. as the loop above reads an entire line if not too + * large, the incomplete sequence error (x == -3) must happen after + * successful conversion of at least 1 ooch character. so no explicit + * check for the incomplete sequence error is required */ +#else + bcslen = (bb->len < HCL_COUNTOF(arg->buf))? bb->len: HCL_COUNTOF(arg->buf); + ucslen = bcslen; + hcl_copy_bchars (arg->buf, bb->buf, bcslen); +#endif + + remlen = bb->len - bcslen; + if (remlen > 0) memmove (bb->buf, &bb->buf[bcslen], remlen); + bb->len = remlen; + + arg->xlen = ucslen; + return 0; +} + +static int read_handler (hcl_t* hcl, hcl_iocmd_t cmd, void* arg) +{ + switch (cmd) + { + case HCL_IO_OPEN: + return open_input(hcl, (hcl_ioinarg_t*)arg); + + case HCL_IO_CLOSE: + return close_input(hcl, (hcl_ioinarg_t*)arg); + + case HCL_IO_READ: + return read_input(hcl, (hcl_ioinarg_t*)arg); + + case HCL_IO_FLUSH: + /* no effect on an input stream */ + return 0; + + default: + hcl_seterrnum (hcl, HCL_EINTERN); + return -1; + } +} + +static HCL_INLINE int open_output (hcl_t* hcl, hcl_iooutarg_t* arg) +{ + xtn_t* xtn = GET_XTN(hcl); + FILE* fp; +#if defined(__DOS__) || defined(_WIN32) || defined(__OS2__) +#define FOPEN_W_FLAGS "wb" +#else +#define FOPEN_W_FLAGS "w" +#endif + + fp = (xtn->print_path && xtn->print_path[0] != '\0'? fopen(xtn->print_path, FOPEN_W_FLAGS): stdout); + if (!fp) + { + if (xtn->print_path) + hcl_seterrbfmt (hcl, HCL_EIOERR, "unable to open %hs", xtn->print_path); + else + hcl_seterrnum (hcl, HCL_EIOERR); + return -1; + } + + arg->handle = fp; + return 0; +} + +static HCL_INLINE int close_output (hcl_t* hcl, hcl_iooutarg_t* arg) +{ + /*xtn_t* xtn = GET_XTN(hcl);*/ + FILE* fp; + + fp = (FILE*)arg->handle; + HCL_ASSERT (hcl, fp != HCL_NULL); + if (fp != stdout) fclose (fp); + arg->handle = HCL_NULL; + return 0; +} + +static HCL_INLINE int write_output (hcl_t* hcl, hcl_iooutarg_t* arg) +{ + /*xtn_t* xtn = GET_XTN(hcl);*/ + hcl_bch_t bcsbuf[1024]; + hcl_oow_t bcslen, ucslen, donelen; + int x; + + donelen = 0; + + do + { + #if defined(HCL_OOCH_IS_UCH) + bcslen = HCL_COUNTOF(bcsbuf); + ucslen = arg->len - donelen; + x = hcl_convootobchars(hcl, &arg->ptr[donelen], &ucslen, bcsbuf, &bcslen); + if (x <= -1 && ucslen <= 0) return -1; + #else + bcslen = HCL_COUNTOF(bcsbuf); + ucslen = arg->len - donelen; + if (ucslen > bcslen) ucslen = bcslen; + else if (ucslen < bcslen) bcslen = ucslen; + hcl_copy_bchars (bcsbuf, &arg->ptr[donelen], bcslen); + #endif + + if (fwrite(bcsbuf, HCL_SIZEOF(bcsbuf[0]), bcslen, (FILE*)arg->handle) < bcslen) + { + hcl_seterrnum (hcl, HCL_EIOERR); + return -1; + } + + donelen += ucslen; + } + while (donelen < arg->len); + + arg->xlen = arg->len; + return 0; +} + +static HCL_INLINE int flush_output (hcl_t* hcl, hcl_iooutarg_t* arg) +{ + FILE* fp; + + fp = (FILE*)arg->handle; + HCL_ASSERT (hcl, fp != HCL_NULL); + + fflush (fp); + return 0; +} + +static int print_handler (hcl_t* hcl, hcl_iocmd_t cmd, void* arg) +{ + switch (cmd) + { + case HCL_IO_OPEN: + return open_output(hcl, (hcl_iooutarg_t*)arg); + + case HCL_IO_CLOSE: + return close_output(hcl, (hcl_iooutarg_t*)arg); + + case HCL_IO_WRITE: + return write_output(hcl, (hcl_iooutarg_t*)arg); + + case HCL_IO_FLUSH: + return flush_output(hcl, (hcl_iooutarg_t*)arg); + + default: + hcl_seterrnum (hcl, HCL_EINTERN); + return -1; + } +} + +int hcl_attachiostdwithbcstr (hcl_t* hcl, const hcl_bch_t* read_file, const hcl_bch_t* print_file) +{ + xtn_t* xtn = GET_XTN(hcl); + xtn->read_path = read_file; + xtn->print_path = print_file; + return hcl_attachio(hcl, read_handler, print_handler); +} + +int hcl_isstdreadertty (hcl_t* hcl) +{ + xtn_t* xtn = GET_XTN(hcl); + return xtn->reader_istty; +} + +/* TODO: hio_attachiostdwithucstr() */