diff --git a/bin/main.c b/bin/main.c index 5aef944..5923a36 100644 --- a/bin/main.c +++ b/bin/main.c @@ -705,9 +705,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_attachiostdwithbcstr(hcl, xtn->read_path, xtn->print_path) <= -1) +/* TODO: add scan path */ + 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; diff --git a/lib/hcl.h b/lib/hcl.h index 92e44a7..6a8b7d8 100644 --- a/lib/hcl.h +++ b/lib/hcl.h @@ -2220,12 +2220,14 @@ HCL_EXPORT int hcl_attachio ( HCL_EXPORT int hcl_attachiostdwithbcstr ( hcl_t* hcl, const hcl_bch_t* read_file, + const hcl_bch_t* scan_file, const hcl_bch_t* print_file ); HCL_EXPORT int hcl_attachiostdwithucstr ( hcl_t* hcl, const hcl_uch_t* read_file, + const hcl_uch_t* scan_file, const hcl_uch_t* print_file ); diff --git a/lib/read.c b/lib/read.c index 065e652..a386882 100644 --- a/lib/read.c +++ b/lib/read.c @@ -3875,6 +3875,15 @@ int hcl_feed (hcl_t* hcl, const hcl_ooch_t* data, hcl_oow_t len) return 0; oops: + /* if enter_list() is in feed_process_token(), the stack grows. + * leave_list() pops an element off the stack. the stack can be + * not empty if an error occurs outside feed_process_token() after + * leave_list() in it. for example, + * + * ( #aaa + * ^ ^ + * leave_list() error in flx_hmarked_ident() before a full cnode is processed + */ feed_clean_up_reader_stack (hcl); return -1; } diff --git a/lib/std.c b/lib/std.c index 2ca18f3..468f2ef 100644 --- a/lib/std.c +++ b/lib/std.c @@ -285,6 +285,7 @@ struct xtn_t * since hcl_attachio() callls the open handler, these fields * are valid only inside the open handelr */ const char* read_path; /* main source file */ + const char* scan_path; /* runtime input file */ const char* print_path; /* runtime output file */ int reader_istty; @@ -3389,6 +3390,139 @@ static int read_handler (hcl_t* hcl, hcl_iocmd_t cmd, void* arg) } } +/* --------------------------------------------------------------------- */ +static HCL_INLINE int open_in_stream (hcl_t* hcl, hcl_ioinarg_t* arg) +{ + xtn_t* xtn = GET_XTN(hcl); + bb_t* bb = HCL_NULL; + + 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; + } + + 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_in_stream (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); + + if (bb->fp != stdin) fclose (bb->fp); + hcl_freemem (hcl, bb); + + arg->handle = HCL_NULL; + return 0; +} + +static HCL_INLINE int read_in_stream (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 scan_handler (hcl_t* hcl, hcl_iocmd_t cmd, void* arg) +{ + switch (cmd) + { + case HCL_IO_OPEN: + return open_in_stream(hcl, (hcl_ioinarg_t*)arg); + + case HCL_IO_CLOSE: + return close_in_stream(hcl, (hcl_ioinarg_t*)arg); + + case HCL_IO_READ: + return read_in_stream(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_out_stream (hcl_t* hcl, hcl_iooutarg_t* arg) { xtn_t* xtn = GET_XTN(hcl); @@ -3496,50 +3630,68 @@ static int print_handler (hcl_t* hcl, hcl_iocmd_t cmd, void* arg) } } -int hcl_attachiostdwithbcstr (hcl_t* hcl, const hcl_bch_t* read_file, const hcl_bch_t* print_file) +/* --------------------------------------------------------------------- */ + +int hcl_attachiostdwithbcstr (hcl_t* hcl, const hcl_bch_t* read_file, const hcl_bch_t* scan_file, const hcl_bch_t* print_file) { xtn_t* xtn = GET_XTN(hcl); int n; HCL_ASSERT (hcl, xtn->read_path == HCL_NULL); + HCL_ASSERT (hcl, xtn->scan_path == HCL_NULL); HCL_ASSERT (hcl, xtn->print_path == HCL_NULL); xtn->read_path = read_file; + xtn->scan_path = scan_file; xtn->print_path = print_file; - n = hcl_attachio(hcl, read_handler, HCL_NULL, print_handler); + n = hcl_attachio(hcl, read_handler, scan_handler, print_handler); xtn->read_path = HCL_NULL; + xtn->scan_path = HCL_NULL; xtn->print_path = HCL_NULL; return n; } -int hcl_attachiostdwithucstr (hcl_t* hcl, const hcl_uch_t* read_file, const hcl_uch_t* print_file) +int hcl_attachiostdwithucstr (hcl_t* hcl, const hcl_uch_t* read_file, const hcl_uch_t* scan_file, const hcl_uch_t* print_file) { xtn_t* xtn = GET_XTN(hcl); int n; HCL_ASSERT (hcl, xtn->read_path == HCL_NULL); + HCL_ASSERT (hcl, xtn->scan_path == HCL_NULL); HCL_ASSERT (hcl, xtn->print_path == HCL_NULL); xtn->read_path = hcl_duputobcstr(hcl, read_file, HCL_NULL); if (HCL_UNLIKELY(!xtn->read_path)) return -1; - xtn->print_path = hcl_duputobcstr(hcl, print_file, HCL_NULL); - if (HCL_UNLIKELY(!xtn->print_path)) + xtn->scan_path = hcl_duputobcstr(hcl, scan_file, HCL_NULL); + if (HCL_UNLIKELY(!xtn->scan_path)) { hcl_freemem (hcl, xtn->read_path); xtn->read_path = HCL_NULL; return -1; } - n = hcl_attachio(hcl, read_handler, HCL_NULL, print_handler); + xtn->print_path = hcl_duputobcstr(hcl, print_file, HCL_NULL); + if (HCL_UNLIKELY(!xtn->print_path)) + { + hcl_freemem (hcl, xtn->scan_path); + hcl_freemem (hcl, xtn->read_path); + xtn->scan_path = HCL_NULL; + xtn->read_path = HCL_NULL; + return -1; + } + + n = hcl_attachio(hcl, read_handler, scan_handler, print_handler); hcl_freemem (hcl, xtn->read_path); + hcl_freemem (hcl, xtn->scan_path); hcl_freemem (hcl, xtn->print_path); xtn->read_path = HCL_NULL; + xtn->scan_path = HCL_NULL; xtn->print_path = HCL_NULL; return n; @@ -3550,4 +3702,3 @@ int hcl_isstdreadertty (hcl_t* hcl) xtn_t* xtn = GET_XTN(hcl); return xtn->reader_istty; } -