From 73cb88cfce73b448a4f64c8286def3272c5b4fdc Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Tue, 10 Sep 2024 12:30:26 +0900 Subject: [PATCH] updated the go wrapper to print compatible error messages with the main implementation --- configure | 68 ++++++++++++++++++++-------------------- configure.ac | 64 +++++++++++++++++++------------------- go/hcl.go | 87 ++++++++++++++++++++++++++++++++++++++++++++-------- lib/err.c | 1 - main.go | 21 +++++++------ 5 files changed, 151 insertions(+), 90 deletions(-) diff --git a/configure b/configure index b48f212..4de90eb 100755 --- a/configure +++ b/configure @@ -18575,12 +18575,12 @@ printf "%s\n" "#define HCL_ENDIAN_UNKNOWN /**/" >>confdefs.h # Check whether --enable-debug was given. if test ${enable_debug+y} then : - enableval=$enable_debug; enable_debug_is=$enableval + enableval=$enable_debug; enable_debug=$enableval else $as_nop - enable_debug_is=no + enable_debug=no fi -if test "$enable_debug_is" = "yes" +if test "x$enable_debug" = "xyes" then CFLAGS="$CFLAGS -g -D_DEBUG -UNDEBUG -U_FORTIFY_SOURCE" @@ -18665,24 +18665,24 @@ fi # Check whether --enable-dynamic-module was given. if test ${enable_dynamic_module+y} then : - enableval=$enable_dynamic_module; enable_dynamic_module_is=$enableval + enableval=$enable_dynamic_module; enable_dynamic_modules=$enableval else $as_nop - enable_dynamic_module_is=yes + enable_dynamic_modules=yes fi if test "x${enable_shared}" = "xno" then - enable_dynamic_module_is="no" + enable_dynamic_module="no" fi -if test "x${enable_dynamic_module_is}" = "xyes" +if test "x${enable_dynamic_module}" = "xyes" then printf "%s\n" "#define HCL_ENABLE_DYNAMIC_MODULE 1" >>confdefs.h fi - if test "x${enable_dynamic_module_is}" = "xyes"; then + if test "x${enable_dynamic_module}" = "xyes"; then ENABLE_DYNAMIC_MODULE_TRUE= ENABLE_DYNAMIC_MODULE_FALSE='#' else @@ -18694,25 +18694,25 @@ fi # Check whether --enable-static-module was given. if test ${enable_static_module+y} then : - enableval=$enable_static_module; enable_static_module_is=$enableval + enableval=$enable_static_module; enable_static_module=$enableval else $as_nop - enable_static_module_is=no + enable_static_module=no fi if test "x${enable_shared}" = "xno" -a "x${enable_static}" = "xyes" then - enable_static_module_is="yes" + enable_static_module="yes" fi -if test "x${enable_static_module_is}" = "xyes" +if test "x${enable_static_module}" = "xyes" then printf "%s\n" "#define HCL_ENABLE_STATIC_MODULE 1" >>confdefs.h fi - if test "x${enable_static_module_is}" = "xyes"; then + if test "x${enable_static_module}" = "xyes"; then ENABLE_STATIC_MODULE_TRUE= ENABLE_STATIC_MODULE_FALSE='#' else @@ -18722,7 +18722,7 @@ fi - if test "x${enable_static_is}" = "xyes"; then + if test "x${enable_static}" = "xyes"; then ENABLE_STATIC_TRUE= ENABLE_STATIC_FALSE='#' else @@ -18730,7 +18730,7 @@ else ENABLE_STATIC_FALSE= fi - if test "x${enable_shared_is}" = "xyes"; then + if test "x${enable_shared}" = "xyes"; then ENABLE_SHARED_TRUE= ENABLE_SHARED_FALSE='#' else @@ -18742,13 +18742,13 @@ fi # Check whether --enable-libltdl was given. if test ${enable_libltdl+y} then : - enableval=$enable_libltdl; enable_libltdl_is=$enableval + enableval=$enable_libltdl; enable_libltdl=$enableval else $as_nop - enable_libltdl_is=no + enable_libltdl=no fi -if test "x${enable_libltdl_is}" = "xyes" +if test "x${enable_libltdl}" = "xyes" then if test "x${ac_cv_header_ltdl_h}" = "xyes" -a "${LTDL_LIBS}" != "" then @@ -18756,10 +18756,10 @@ then printf "%s\n" "#define HCL_ENABLE_LIBLTDL /**/" >>confdefs.h else - enable_libltdl_is="no" + enable_libltdl="no" fi fi - if test "x${enable_libltdl_is}" = "xyes"; then + if test "x${enable_libltdl}" = "xyes"; then ENABLE_LIBLTDL_TRUE= ENABLE_LIBLTDL_FALSE='#' else @@ -18771,13 +18771,13 @@ fi # Check whether --enable-libunwind was given. if test ${enable_libunwind+y} then : - enableval=$enable_libunwind; enable_libunwind_is=$enableval + enableval=$enable_libunwind; enable_libunwind=$enableval else $as_nop - enable_libunwind_is=no + enable_libunwind=no fi -if test "x${enable_libunwind_is}" = "xyes" +if test "x${enable_libunwind}" = "xyes" then if test "x${ac_cv_header_libunwind_h}" = "xyes" -a "${UNWIND_LIBS}" != "" then @@ -18785,10 +18785,10 @@ then printf "%s\n" "#define HCL_ENABLE_LIBUNWIND /**/" >>confdefs.h else - enable_libunwind_is="no" + enable_libunwind="no" fi fi - if test "x${enable_libunwind_is}" = "xyes"; then + if test "x${enable_libunwind}" = "xyes"; then ENABLE_LIBUNWIND_TRUE= ENABLE_LIBUNWIND_FALSE='#' else @@ -18800,12 +18800,12 @@ fi # Check whether --enable-pthread-flags was given. if test ${enable_pthread_flags+y} then : - enableval=$enable_pthread_flags; enable_pthread_flags_is=$enableval + enableval=$enable_pthread_flags; enable_pthread_flags=$enableval else $as_nop - enable_pthread_flags_is=yes + enable_pthread_flags=yes fi -if test "$enable_pthread_flags_is" = "yes" +if test "$enable_pthread_flags" = "yes" then CFLAGS="$CFLAGS $PTHREAD_CFLAGS" LIBS="$LIBS $PTHREAD_LIBS" @@ -18814,13 +18814,13 @@ fi # Check whether --enable-hclx was given. if test ${enable_hclx+y} then : - enableval=$enable_hclx; enable_hclx_is=$enableval + enableval=$enable_hclx; enable_hclx=$enableval else $as_nop - enable_hclx_is=no + enable_hclx=no fi - if test "x${enable_hclx_is}" = "xyes"; then + if test "x${enable_hclx}" = "xyes"; then ENABLE_HCLX_TRUE= ENABLE_HCLX_FALSE='#' else @@ -18832,13 +18832,13 @@ fi # Check whether --enable-hclgo was given. if test ${enable_hclgo+y} then : - enableval=$enable_hclgo; enable_hclgo_is=$enableval + enableval=$enable_hclgo; enable_hclgo=$enableval else $as_nop - enable_hclgo_is=no + enable_hclgo=no fi - if test "x${enable_hclgo_is}" = "xyes"; then + if test "x${enable_hclgo}" = "xyes"; then ENABLE_HCLGO_TRUE= ENABLE_HCLGO_FALSE='#' else diff --git a/configure.ac b/configure.ac index 4673911..3ed30bd 100644 --- a/configure.ac +++ b/configure.ac @@ -533,8 +533,8 @@ AC_C_BIGENDIAN( [AC_DEFINE([HCL_ENDIAN_UNKNOWN],[],[Unknown Endian])]) AC_ARG_ENABLE([debug], [AS_HELP_STRING([--enable-debug],[build the library in the debug mode (default. no)])], - enable_debug_is=$enableval,enable_debug_is=no) -if test "$enable_debug_is" = "yes" + enable_debug=$enableval,enable_debug=no) +if test "x$enable_debug" = "xyes" then [CFLAGS="$CFLAGS -g -D_DEBUG -UNDEBUG -U_FORTIFY_SOURCE"] AC_DEFINE([HCL_BUILD_DEBUG],[1],[build release/debug]) @@ -585,83 +585,83 @@ fi dnl ===== enable-dynamic-module ===== AC_ARG_ENABLE([dynamic-module], [AS_HELP_STRING([--enable-dynamic-module],[enable dynamic module capability(default. yes)])], - enable_dynamic_module_is=$enableval, - enable_dynamic_module_is=yes + enable_dynamic_modules=$enableval, + enable_dynamic_modules=yes ) if test "x${enable_shared}" = "xno" then - enable_dynamic_module_is="no" + enable_dynamic_module="no" fi -if test "x${enable_dynamic_module_is}" = "xyes" +if test "x${enable_dynamic_module}" = "xyes" then AC_DEFINE([HCL_ENABLE_DYNAMIC_MODULE],[1],[enable dynamic module capability]) fi -AM_CONDITIONAL(ENABLE_DYNAMIC_MODULE, test "x${enable_dynamic_module_is}" = "xyes") +AM_CONDITIONAL(ENABLE_DYNAMIC_MODULE, test "x${enable_dynamic_module}" = "xyes") dnl ===== enable-static-module ===== AC_ARG_ENABLE([static-module], [AS_HELP_STRING([--enable-static-module],[build modules statically into the main library(default. no)])], - enable_static_module_is=$enableval, - enable_static_module_is=no + enable_static_module=$enableval, + enable_static_module=no ) if test "x${enable_shared}" = "xno" -a "x${enable_static}" = "xyes" then - enable_static_module_is="yes" + enable_static_module="yes" fi -if test "x${enable_static_module_is}" = "xyes" +if test "x${enable_static_module}" = "xyes" then AC_DEFINE([HCL_ENABLE_STATIC_MODULE],[1],[link modules statically into the main library]) fi -AM_CONDITIONAL(ENABLE_STATIC_MODULE, test "x${enable_static_module_is}" = "xyes") +AM_CONDITIONAL(ENABLE_STATIC_MODULE, test "x${enable_static_module}" = "xyes") dnl ===== conditionals - ENABLE_STATIC and ENABLE_SHARED ===== -AM_CONDITIONAL(ENABLE_STATIC, test "x${enable_static_is}" = "xyes") -AM_CONDITIONAL(ENABLE_SHARED, test "x${enable_shared_is}" = "xyes") +AM_CONDITIONAL(ENABLE_STATIC, test "x${enable_static}" = "xyes") +AM_CONDITIONAL(ENABLE_SHARED, test "x${enable_shared}" = "xyes") dnl ===== enable-libltdl ===== AC_ARG_ENABLE([libltdl], [AS_HELP_STRING([--enable-libltdl],[use libltdl(default. no)])], - enable_libltdl_is=$enableval, - enable_libltdl_is=no + enable_libltdl=$enableval, + enable_libltdl=no ) -if test "x${enable_libltdl_is}" = "xyes" +if test "x${enable_libltdl}" = "xyes" then if test "x${ac_cv_header_ltdl_h}" = "xyes" -a "${LTDL_LIBS}" != "" then AC_DEFINE([HCL_ENABLE_LIBLTDL],[],[use libltdl when loading a dynamic module]) else - enable_libltdl_is="no" + enable_libltdl="no" fi fi -AM_CONDITIONAL(ENABLE_LIBLTDL, test "x${enable_libltdl_is}" = "xyes") +AM_CONDITIONAL(ENABLE_LIBLTDL, test "x${enable_libltdl}" = "xyes") dnl ===== enable-libunwind ===== AC_ARG_ENABLE([libunwind], [AS_HELP_STRING([--enable-libunwind],[use libunwind(default. no)])], - enable_libunwind_is=$enableval, - enable_libunwind_is=no + enable_libunwind=$enableval, + enable_libunwind=no ) -if test "x${enable_libunwind_is}" = "xyes" +if test "x${enable_libunwind}" = "xyes" then if test "x${ac_cv_header_libunwind_h}" = "xyes" -a "${UNWIND_LIBS}" != "" then AC_DEFINE([HCL_ENABLE_LIBUNWIND],[],[use libunwind for backtracing stack frames]) else - enable_libunwind_is="no" + enable_libunwind="no" fi fi -AM_CONDITIONAL(ENABLE_LIBUNWIND, test "x${enable_libunwind_is}" = "xyes") +AM_CONDITIONAL(ENABLE_LIBUNWIND, test "x${enable_libunwind}" = "xyes") dnl ==== include pthread options to the default flags ==== dnl keep this as the last option as it changes the default compile flags. dnl otherwise, other tests may get affected if this option is on. AC_ARG_ENABLE([pthread-flags], [AS_HELP_STRING([--enable-pthread-flags],[add thread flags to CFLAGS, LIBS(default. yes)])], - enable_pthread_flags_is=$enableval,enable_pthread_flags_is=yes) -if test "$enable_pthread_flags_is" = "yes" + enable_pthread_flags=$enableval,enable_pthread_flags=yes) +if test "$enable_pthread_flags" = "yes" then [CFLAGS="$CFLAGS $PTHREAD_CFLAGS"] [LIBS="$LIBS $PTHREAD_LIBS"] @@ -670,18 +670,18 @@ fi dnl ===== enable-hclx ===== AC_ARG_ENABLE([hclx], [AS_HELP_STRING([--enable-hclx],[build libhclx(default. no)])], - enable_hclx_is=$enableval, - enable_hclx_is=no + enable_hclx=$enableval, + enable_hclx=no ) -AM_CONDITIONAL(ENABLE_HCLX, test "x${enable_hclx_is}" = "xyes") +AM_CONDITIONAL(ENABLE_HCLX, test "x${enable_hclx}" = "xyes") dnl ===== enable-hclgo ===== AC_ARG_ENABLE([hclgo], [AS_HELP_STRING([--enable-hclgo],[build the go wrapper(default. no)])], - enable_hclgo_is=$enableval, - enable_hclgo_is=no + enable_hclgo=$enableval, + enable_hclgo=no ) -AM_CONDITIONAL(ENABLE_HCLGO, test "x${enable_hclgo_is}" = "xyes") +AM_CONDITIONAL(ENABLE_HCLGO, test "x${enable_hclgo}" = "xyes") dnl ==== subsititution of some key items ==== diff --git a/go/hcl.go b/go/hcl.go index 65de131..e5280ea 100644 --- a/go/hcl.go +++ b/go/hcl.go @@ -65,6 +65,14 @@ type Ext struct { inst_no int } +type Err struct { + Line uint + Colm uint + File string + Msg string + Tgt string +} + type BitMask C.hcl_bitmask_t const TRAIT_LANG_ENABLE_EOL BitMask = C.HCL_TRAIT_LANG_ENABLE_EOL @@ -111,6 +119,34 @@ func (hcl *HCL) Close() { deregister_instance(hcl) } +func (hcl *HCL) make_errinfo() *Err { + var loc C.hcl_loc_t + var err Err + var errnum C.hcl_errnum_t + + err.Msg = hcl.get_errmsg() + + errnum = C.hcl_geterrnum(hcl.c) + if errnum == C.HCL_ESYNERR { + var synerr C.hcl_synerr_t + C.hcl_getsynerr(hcl.c, &synerr) + loc = synerr.loc + + err.Tgt = string(uchars_to_rune_slice(&synerr.tgt.val[0], uintptr(synerr.tgt.len))) + } else { + C.hcl_geterrloc(hcl.c, &loc) + } + + err.Line = uint(loc.line) + err.Colm = uint(loc.colm) + if loc.file != nil { + err.File = string(ucstr_to_rune_slice(loc.file)) + } else { + err.File = hcl.io.cci_main + } + return &err +} + func (hcl *HCL) GetTrait() BitMask { var x C.int var log_mask BitMask = 0 @@ -189,7 +225,8 @@ func (hcl *HCL) Ignite(memsize uintptr) error { x = C.hcl_ignite(hcl.c, C.hcl_oow_t(memsize)) if x <= -1 { - return fmt.Errorf("unable to ignite - %s", hcl.get_errmsg()) + //return fmt.Errorf("unable to ignite - %s", hcl.get_errmsg()) + return hcl.make_errinfo() } return nil @@ -200,7 +237,8 @@ func (hcl *HCL) AddBuiltinPrims() error { x = C.hcl_addbuiltinprims(hcl.c) if x <= -1 { - return fmt.Errorf("unable to add built-in primitives - %s", hcl.get_errmsg()) + //return fmt.Errorf("unable to add built-in primitives - %s", hcl.get_errmsg()) + return hcl.make_errinfo() } return nil } @@ -225,7 +263,8 @@ func (hcl *HCL) AttachCCIO(cci CciImpl, main_cci_name string) error { // restore the io handler set due to attachment failure hcl.io.cci_main = old_cci_name hcl.io.cci = old_cci - return fmt.Errorf("unable to attach source input stream handler - %s", hcl.get_errmsg()) + //return fmt.Errorf("unable to attach source input stream handler - %s", hcl.get_errmsg()) + return hcl.make_errinfo() } return nil } @@ -248,7 +287,8 @@ func (hcl *HCL) AttachUDIO(udi UdiImpl, udo UdoImpl) error { //restore the io handlers set due to attachment failure hcl.io.udi = os hcl.io.udo = op - return fmt.Errorf("unable to attach user data stream handlers - %s", hcl.get_errmsg()) + //return fmt.Errorf("unable to attach user data stream handlers - %s", hcl.get_errmsg()) + return hcl.make_errinfo() } return nil } @@ -258,7 +298,8 @@ func (hcl *HCL) BeginFeed() error { x = C.hcl_beginfeed(hcl.c, nil) if x <= -1 { - return fmt.Errorf("unable to begin feeding - %s", hcl.get_errmsg()) + //return fmt.Errorf("unable to begin feeding - %s", hcl.get_errmsg()) + return hcl.make_errinfo() } return nil @@ -269,7 +310,8 @@ func (hcl *HCL) EndFeed() error { x = C.hcl_endfeed(hcl.c) if x <= -1 { - return fmt.Errorf("unable to end feeding - %s", hcl.get_errmsg()) + //return fmt.Errorf("unable to end feeding - %s", hcl.get_errmsg()) + return hcl.make_errinfo() } return nil @@ -282,7 +324,8 @@ func (hcl *HCL) FeedString(str string) error { q = string_to_uchars(str) x = C.hcl_feed(hcl.c, &q[0], C.hcl_oow_t(len(q))) if x <= -1 { - return fmt.Errorf("unable to feed string - %s", hcl.get_errmsg()) + //return fmt.Errorf("unable to feed string - %s", hcl.get_errmsg()) + return hcl.make_errinfo() } return nil } @@ -294,7 +337,8 @@ func (hcl *HCL) FeedRunes(str []rune) error { q = rune_slice_to_uchars(str) x = C.hcl_feed(hcl.c, &q[0], C.hcl_oow_t(len(q))) if x <= -1 { - return fmt.Errorf("unable to feed runes - %s", hcl.get_errmsg()) + //return fmt.Errorf("unable to feed runes - %s", hcl.get_errmsg()) + return hcl.make_errinfo() } return nil } @@ -310,12 +354,14 @@ func (hcl *HCL) FeedFromReader(rdr io.Reader) error { if err == io.EOF { break } else if err != nil { - return fmt.Errorf("unable to read bytes - %s", err.Error()) + //return fmt.Errorf("unable to read bytes - %s", err.Error()) + return &Err{File: hcl.io.cci_main, Msg: 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 fmt.Errorf("unable to feed bytes - %s", hcl.get_errmsg()) + return hcl.make_errinfo() } } @@ -328,7 +374,8 @@ func (hcl *HCL) FeedFromFile(file string) error { f, err = os.Open(file) if err != nil { - return fmt.Errorf("unable to open %s - %s", file, err.Error()) + //return fmt.Errorf("unable to open %s - %s", file, err.Error()) + return &Err{File: file, Msg: err.Error()} } defer f.Close() @@ -340,7 +387,8 @@ func (hcl *HCL) Execute() error { x = C.hcl_execute(hcl.c) if x == nil { - return fmt.Errorf("unable to execute - %s", hcl.get_errmsg()) + //return fmt.Errorf("unable to execute - %s", hcl.get_errmsg()) + return hcl.make_errinfo() } // TODO: wrap C.hcl_oop_t in a go type @@ -353,7 +401,8 @@ func (hcl *HCL) Decode() error { x = C.hcl_decode(hcl.c, C.hcl_getcode(hcl.c), 0, C.hcl_getbclen(hcl.c)) if x <= -1 { - return fmt.Errorf("unable to decode byte codes - %s", hcl.get_errmsg()) + //return fmt.Errorf("unable to decode byte codes - %s", hcl.get_errmsg()) + return hcl.make_errinfo() } return nil @@ -370,6 +419,8 @@ func (hcl *HCL) set_errmsg(num C.hcl_errnum_t, msg string) { C.hcl_seterrbmsg(hcl.c, num, ptr) } +// ----------------------------------------------------------- + func ucstr_to_rune_slice(str *C.hcl_uch_t) []rune { return uchars_to_rune_slice(str, uintptr(C.hcl_count_ucstr(str))) } @@ -424,3 +475,13 @@ func c_to_go(c *C.hcl_t) *HCL { inst = inst_table.slot_to_instance(ext.inst_no) return inst.g } + +// ----------------------------------------------------------- + +func (err* Err) Error() string { + if err.Tgt == "" { + return fmt.Sprintf("%s[%d,%d] %s", err.File, err.Line, err.Colm, err.Msg) + } else { + } + return fmt.Sprintf("%s[%d,%d] %s - %s", err.File, err.Line, err.Colm, err.Msg, err.Tgt) +} diff --git a/lib/err.c b/lib/err.c index a3baa1a..4a60245 100644 --- a/lib/err.c +++ b/lib/err.c @@ -317,7 +317,6 @@ void hcl_seterrumsg (hcl_t* hcl, hcl_errnum_t errnum, const hcl_uch_t* errmsg) hcl_seterrbfmt(hcl, errnum, "%ls", errmsg); } - static int err_bcs (hcl_t* hcl, hcl_fmtout_t* fmtout, const hcl_bch_t* ptr, hcl_oow_t len) { hcl_oow_t max; diff --git a/main.go b/main.go index a729820..b9012af 100644 --- a/main.go +++ b/main.go @@ -106,14 +106,14 @@ func main() { err = handle_arguments(¶m) if err != nil { - fmt.Printf("Error: %s\n", err.Error()) + fmt.Printf("ERROR: %s\n", err.Error()) param.fs_usage() os.Exit(1) } x, err = hcl.New() if err != nil { - fmt.Printf("Error: failed to instantiate hcl - %s\n", err.Error()) + fmt.Printf("ERROR: failed to instantiate hcl - %s\n", err.Error()) os.Exit(1) } @@ -126,30 +126,30 @@ func main() { err = x.Ignite(1000000) if err != nil { - fmt.Printf("Error: failed to ignite - %s\n", err.Error()) + fmt.Printf("ERROR: failed to ignite - %s\n", err.Error()) goto oops } err = x.AddBuiltinPrims() if err != nil { - fmt.Printf("Error: failed to add builtin primitives - %s\n", err.Error()) + fmt.Printf("ERROR: failed to add builtin primitives - %s\n", err.Error()) goto oops } err = x.AttachCCIO(&rfh, param.input_file) if err != nil { - fmt.Printf("Error: %s\n", err.Error()) + fmt.Printf("ERROR: failed to attach input file handler - %s\n", err.Error()) goto oops } err = x.AttachUDIO(&sfh, &pfh) if err != nil { - fmt.Printf("Error: %s\n", err.Error()) + fmt.Printf("ERROR: failed to attach the user I/O handler - %s\n", err.Error()) goto oops } err = x.BeginFeed() if err != nil { - fmt.Printf("Error: %s\n", err.Error()) + fmt.Printf("ERROR: %s\n", err.Error()) goto oops } @@ -159,13 +159,13 @@ func main() { // #include "a.hcl" // (printf ">>>>>>>>> [%d]\n" (+ 20 455))`) if err != nil { - fmt.Printf("Error: %s\n", err.Error()) + fmt.Printf("ERROR: %s\n", err.Error()) goto oops } err = x.EndFeed() if err != nil { - fmt.Printf("Error: %s\n", err.Error()) + fmt.Printf("ERROR: %s\n", err.Error()) goto oops } @@ -174,7 +174,8 @@ func main() { err = x.Execute() if err != nil { - fmt.Printf("Error: %s\n", err.Error()) + //fmt.Printf("ERROR: %s[%d:%d] - %s\n", herr.File, herr.Line, herr.Colm, herr.Msg) + fmt.Printf("ERROR: %s\n", err.Error()) goto oops }