diff --git a/go/hcl.go b/go/hcl.go index 7cfa610..b06d065 100644 --- a/go/hcl.go +++ b/go/hcl.go @@ -22,7 +22,10 @@ int hcl_print_handler_for_go (hcl_t hcl, hcl_iocmd_t cmd, void* arg) { import "C" import ( + "bufio" "fmt" + "io" + "os" "runtime" "unsafe" ) @@ -199,6 +202,28 @@ func (hcl *HCL) AttachIO(r IOReadImpl, s IOScanImpl, p IOPrintImpl) error { return nil } +func (hcl *HCL) BeginFeed() error { + var x C.int + + x = C.hcl_beginfeed(hcl.c, nil) + if x <= -1 { + return fmt.Errorf("unable to begin feeding - %s", hcl.get_errmsg()) + } + + return nil +} + +func (hcl *HCL) EndFeed() error { + var x C.int + + x = C.hcl_endfeed(hcl.c) + if x <= -1 { + return fmt.Errorf("unable to end feeding - %s", hcl.get_errmsg()) + } + + return nil +} + func (hcl *HCL) FeedString(str string) error { var x C.int var q []C.hcl_uch_t @@ -223,26 +248,40 @@ func (hcl *HCL) FeedRunes(str []rune) error { return nil } -func (hcl *HCL) BeginFeed() error { +func (hcl *HCL) FeedFromReader(rdr io.Reader) error { + var err error + var n int var x C.int + var buf [1024]byte - x = C.hcl_beginfeed(hcl.c, nil) - if x <= -1 { - return fmt.Errorf("unable to begin feeding - %s", hcl.get_errmsg()) + for { + n, err = rdr.Read(buf[:]) + if err == io.EOF { + break + } else if err != nil { + return fmt.Errorf("unable to read bytes - %s", err.Error()) + } + + x = C.hcl_feedbchars(hcl.c, (*C.hcl_bch_t)(unsafe.Pointer(&buf[0])), C.hcl_oow_t(n)); + if x <= -1 { + return fmt.Errorf("unable to feed bytes - %s", hcl.get_errmsg()) + } } return nil } -func (hcl *HCL) EndFeed() error { - var x C.int +func (hcl *HCL) FeedFromFile (file string) error { + var f *os.File + var err error - x = C.hcl_endfeed(hcl.c) - if x <= -1 { - return fmt.Errorf("unable to end feeding - %s", hcl.get_errmsg()) + f, err = os.Open(file); + if err != nil { + return fmt.Errorf("unable to open %s - %s", file, err.Error()) } - return nil + defer f.Close() + return hcl.FeedFromReader(bufio.NewReader(f)) } func (hcl *HCL) Execute() error { diff --git a/lib/hcl-prv.h b/lib/hcl-prv.h index dd81a2e..5106fef 100644 --- a/lib/hcl-prv.h +++ b/lib/hcl-prv.h @@ -684,6 +684,15 @@ struct hcl_compiler_t struct { + #if defined(HCL_OOCH_IS_UCH) + struct + { + hcl_bch_t buf[HCL_BCSIZE_MAX]; + hcl_oow_t len; + int no_check; + } rsd; /* residue - incomplete sequence at the end of the last data fed by hcl_feedbchars() */ + #endif + struct { hcl_flx_state_t state; diff --git a/lib/hcl.h b/lib/hcl.h index 91053d1..64cd8d4 100644 --- a/lib/hcl.h +++ b/lib/hcl.h @@ -2310,6 +2310,18 @@ HCL_EXPORT int hcl_feed ( hcl_oow_t len ); +HCL_EXPORT int hcl_feeduchars ( + hcl_t* hcl, + const hcl_uch_t* data, + hcl_oow_t len +); + +HCL_EXPORT int hcl_feedbchars ( + hcl_t* hcl, + const hcl_bch_t* data, + hcl_oow_t len +); + HCL_EXPORT int hcl_endfeed ( hcl_t* hcl ); diff --git a/lib/read.c b/lib/read.c index 27823b8..b0ec907 100644 --- a/lib/read.c +++ b/lib/read.c @@ -2436,6 +2436,15 @@ int hcl_feed (hcl_t* hcl, const hcl_ooch_t* data, hcl_oow_t len) int x; HCL_ASSERT (hcl, hcl->c != HCL_NULL); + +#if defined(HCL_OOCH_IS_UCH) + if (hcl->c->feed.rsd.len > 0 && !hcl->c->feed.rsd.no_check) + { + hcl_seterrbfmt (hcl, HCL_EPERM, "feed disallowed for incomplete sequence pending more feeding"); + return -1; + } +#endif + if (data) { for (i = 0; i < len; ) @@ -2504,6 +2513,138 @@ oops: return -1; } +int hcl_feedbchars (hcl_t* hcl, const hcl_bch_t* data, hcl_oow_t len) +{ +#if defined(HCL_OOCH_IS_UCH) + hcl_uch_t outbuf[128]; + hcl_oow_t inlen, outlen, inpos, brwlen; + int n; + + HCL_ASSERT (hcl, hcl->c != HCL_NULL); + + inpos = 0; + + if (hcl->c->feed.rsd.len > 0) + { + hcl_oow_t rsdlen; + + /* handle the residue bytes from the previous feeding */ + rsdlen = hcl->c->feed.rsd.len; /* original residue length*/ + brwlen = HCL_COUNTOF(hcl->c->feed.rsd.buf) - rsdlen; + if (len < brwlen) brwlen = len; + HCL_MEMCPY(&hcl->c->feed.rsd.buf[rsdlen], data, brwlen); + hcl->c->feed.rsd.len += brwlen; + + inlen = hcl->c->feed.rsd.len; + outlen = 1; /* ensure that it can only convert 1 character */ + n = hcl_conv_bchars_to_uchars_with_cmgr(hcl->c->feed.rsd.buf, &inlen, outbuf, &outlen, hcl_getcmgr(hcl), 0); + + if (outlen > 0) + { + int x; + hcl->c->feed.rsd.no_check = 1; + x = hcl_feed(hcl, outbuf, outlen); + hcl->c->feed.rsd.no_check = 0; + if (x <= -1) return -1; + } + + if (n <= -1) + { + if (n == -3 || (n == -2 && outlen > 0)) + { + /* n == -3. invalid sequence. more feeding is required */ + /* n == -2. there were extra bytes for the second character in the input */ + HCL_ASSERT (hcl, (n == -3 && inlen == 0 && outlen == 0) || (n == -2 && inlen > 0)); + /* nothing to do. carry on */ + } + else + { + hcl_seterrnum (hcl, (n == -2)? HCL_EBUFFULL: HCL_EECERR); + return -1; + } + } + + /* + * | rsdlen | brwlen | + * | inlen | + */ + if (inlen < rsdlen) + { + HCL_ASSERT (hcl, inlen == 0); + HCL_ASSERT (hcl, brwlen == len); + /* brwlen needs no change */ + /* hcl->c->feed.rsd.len nees no change */ + } + else + { + HCL_ASSERT (hcl, inlen > rsdlen); + brwlen = inlen - rsdlen; /* actual bytes borrowed and converted */ + hcl->c->feed.rsd.len = 0; + } + inpos += brwlen; + len -= brwlen; + } + + while (len > 0) + { + inlen = len; + outlen = HCL_COUNTOF(outbuf); + + /* hcl_convbtouchars() does not differentiate between illegal charcter and incomplete sequence. + * use a lower-level function that hcl_convbtouchars() uses */ + n = hcl_conv_bchars_to_uchars_with_cmgr(&data[inpos], &inlen, outbuf, &outlen, hcl_getcmgr(hcl), 0); + if (outlen > 0 && hcl_feed(hcl, outbuf, outlen) <= -1) return -1; + + if (n <= -1) + { + if (n == -2 || n == -3) + { + hcl_oow_t rsdlen; + + HCL_ASSERT (hcl, len > inlen); + rsdlen = len - inlen; + HCL_ASSERT (hcl, rsdlen <= HCL_COUNTOF(hcl->c->feed.rsd.buf)); + HCL_MEMCPY (hcl->c->feed.rsd.buf, &data[inpos + inlen], rsdlen); + hcl->c->feed.rsd.len = len - inlen; + break; + } + + hcl_seterrnum (hcl, HCL_EECERR); + return -1; + } + + inpos += inlen; + len -= inlen; + } + + return 0; +#else + return hcl_feed(hcl, data, len); +#endif +} + +int hcl_feeduchars (hcl_t* hcl, const hcl_uch_t* data, hcl_oow_t len) +{ +#if defined(HCL_OOCH_IS_UCH) + return hcl_feed(hcl, data, len); +#else + hcl_bch_t outbuf[HCL_BCSIZE_MAX * 128]; + hcl_oow_t inlen, outlen, inpos; + + inpos = 0; + while (len > 0) + { + inlen = len; + outlen = HCL_COUNTOF(outbuf); + n = hcl_convutobchars(hcl, &data[inpos], &inlen, outbuf, &outlen); + if (outlen > 0 && hcl_feed(hcl, outbuf, outlen) <= -1) return -1; + inpos += inlen; + len -= inlen; + if (n <= -1) return -1 + } + return 0; +#endif +} /* hcl_setopt (ON_EXPRESSION CALLBACK??? ); @@ -2598,7 +2739,6 @@ static void fini_compiler_cb (hcl_t* hcl) } } - static void fini_compiler (hcl_t* hcl) { /* unlike fini_compiler_cb(), this is to be used in some error handling diff --git a/lib/utl.c b/lib/utl.c index f47891f..950f89f 100644 --- a/lib/utl.c +++ b/lib/utl.c @@ -589,7 +589,7 @@ HCL_INLINE int hcl_conv_bchars_to_uchars_with_cmgr (const hcl_bch_t* bcs, hcl_oo break; } - n = cmgr->bctouc (p, mlen, q); + n = cmgr->bctouc(p, mlen, q); if (n == 0) { /* invalid sequence */ @@ -645,7 +645,7 @@ HCL_INLINE int hcl_conv_bchars_to_uchars_with_cmgr (const hcl_bch_t* bcs, hcl_oo { hcl_oow_t n; - n = cmgr->bctouc (p, mlen, &w); + n = cmgr->bctouc(p, mlen, &w); if (n == 0) { /* invalid sequence */ @@ -720,7 +720,7 @@ HCL_INLINE int hcl_conv_uchars_to_bchars_with_cmgr (const hcl_uch_t* ucs, hcl_oo break; } - n = cmgr->uctobc (*p, bcs, rem); + n = cmgr->uctobc(*p, bcs, rem); if (n == 0) { ret = -1; @@ -745,7 +745,7 @@ HCL_INLINE int hcl_conv_uchars_to_bchars_with_cmgr (const hcl_uch_t* ucs, hcl_oo { hcl_oow_t n; - n = cmgr->uctobc (*p, bcsbuf, HCL_COUNTOF(bcsbuf)); + n = cmgr->uctobc(*p, bcsbuf, HCL_COUNTOF(bcsbuf)); if (n == 0) { ret = -1; @@ -786,7 +786,7 @@ HCL_INLINE int hcl_conv_ucstr_to_bcstr_with_cmgr (const hcl_uch_t* ucs, hcl_oow_ break; } - n = cmgr->uctobc (*p, bcs, rem); + n = cmgr->uctobc(*p, bcs, rem); if (n == 0) { ret = -1; @@ -824,7 +824,7 @@ HCL_INLINE int hcl_conv_ucstr_to_bcstr_with_cmgr (const hcl_uch_t* ucs, hcl_oow_ { hcl_oow_t n; - n = cmgr->uctobc (*p, bcsbuf, HCL_COUNTOF(bcsbuf)); + n = cmgr->uctobc(*p, bcsbuf, HCL_COUNTOF(bcsbuf)); if (n == 0) { ret = -1; diff --git a/main.go b/main.go index ed76065..247f823 100644 --- a/main.go +++ b/main.go @@ -4,6 +4,7 @@ import ( _ "cfg" "fmt" "os" + "strings" hcl "code.miflux.com/hyung-hwan/hcl/go" ) @@ -17,23 +18,63 @@ import ( (printf ">>>>>>>>> [%d]\n" (+ 20 455)) `)) */ + +type Param struct { + log_file string + input_file string +} + +func handle_arguments(param *Param) error { + var nargs int = len(os.Args) + var i int + + for i = 1; i < nargs; i++ { + if strings.HasPrefix(os.Args[i], "--log=") { + param.log_file = os.Args[i][6:] + } else if (os.Args[i] == "--log") { + i++ + param.log_file = os.Args[i] + } else if strings.HasPrefix(os.Args[i], "--") || strings.HasPrefix(os.Args[i], "-") { + return fmt.Errorf("unknown option - %s", os.Args[i]) + } else { + break + } + } + + if i >= nargs { + return fmt.Errorf("no input file specified") + } + + param.input_file = os.Args[i] + return nil +} + func main() { var x *hcl.HCL = nil var err error = nil + var param Param var rfh hcl.ReadFileHandler var sfh hcl.ScanFileHandler var pfh hcl.PrintFileHandler + err = handle_arguments(¶m); + if err != nil { + fmt.Printf("Error: %s\n", err.Error()) + os.Exit(1) + } + x, err = hcl.New() if err != nil { fmt.Printf("Error: failed to instantiate hcl - %s\n", err.Error()) os.Exit(1) } - x.SetLogMask (^hcl.BitMask(0)) - x.SetLogTarget ("/dev/stderr") + if param.log_file != "" { + x.SetLogMask (^hcl.BitMask(0)) + x.SetLogTarget ("/dev/stderr") + } err = x.Ignite(1000000) if err != nil { @@ -52,10 +93,17 @@ func main() { goto oops } - err = x.FeedString(`(printf ">>>>>>>>> [%d]\n" (+ 30 455)) - (printf ">>>>>>>>> [%d]\n" (+ 11 455)) - #include "a.hcl" - (printf ">>>>>>>>> [%d]\n" (+ 20 455))`) + err = x.BeginFeed(); + if err != nil { + fmt.Printf("Error: %s\n", err.Error()) + goto oops + } + + err = x.FeedFromFile(param.input_file) + //err = x.FeedString(`(printf ">>>>>>>>> [%d]\n" (+ 30 455)) + // (printf ">>>>>>>>> [%d]\n" (+ 11 455)) + // #include "a.hcl" + // (printf ">>>>>>>>> [%d]\n" (+ 20 455))`) if err != nil { fmt.Printf("Error: %s\n", err.Error()) goto oops