Compare commits
9
Commits
e2d648fbba
..
xstack
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
158865a866 | ||
|
|
d516cd2e4b | ||
|
|
79296debb1 | ||
|
|
6999c3ac37 | ||
|
|
c3e4fd8457 | ||
|
|
7f7893d4d1 | ||
|
|
e9f55d259f | ||
|
|
55f8b4f611 | ||
|
|
c5f35799a5 |
@@ -101,17 +101,6 @@ static void init_rtx_xtn_ecb (rtx_xtn_t* xtn)
|
||||
xtn->rtx_ecb.sigset = rtx_on_sigset;
|
||||
}
|
||||
|
||||
// -----------------------------------------------
|
||||
static hawk_uintptr_t val_arr_itr_elem(hawk_val_arr_itr_t* itr)
|
||||
{
|
||||
return (hawk_uintptr_t)itr->elem;
|
||||
}
|
||||
|
||||
static hawk_uintptr_t val_map_itr_val(hawk_val_map_itr_t* itr)
|
||||
{
|
||||
return (hawk_uintptr_t)HAWK_VAL_MAP_ITR_VAL(itr);
|
||||
}
|
||||
|
||||
// -----------------------------------------------
|
||||
|
||||
extern int hawk_mod_go_fnc_gc(rtx_xtn_t* rtx_xtn);
|
||||
@@ -239,14 +228,8 @@ type Rtx struct {
|
||||
val_tail *Val
|
||||
}
|
||||
|
||||
type CPtrVal uintptr
|
||||
|
||||
type Val struct {
|
||||
// storing a raw C pointer in the go memory is usually OK.
|
||||
// but the hawk encodes immediate values using tag in a pointer.
|
||||
// such values are not valid C pointers and go GC triggered pointer check error.
|
||||
//c *C.hawk_val_t
|
||||
c CPtrVal // use a numeric type that can store the pointer
|
||||
c *C.hawk_val_t
|
||||
rtx *Rtx
|
||||
next *Val
|
||||
prev *Val
|
||||
@@ -270,9 +253,7 @@ const (
|
||||
)
|
||||
|
||||
type ValArrayItr struct {
|
||||
//c C.hawk_val_arr_itr_t
|
||||
_ [0]uintptr // for alignment
|
||||
c [C.sizeof_hawk_val_arr_itr_t]byte
|
||||
c C.hawk_val_arr_itr_t
|
||||
}
|
||||
|
||||
type ValMapItr struct {
|
||||
@@ -673,7 +654,7 @@ func (rtx *Rtx) GetErrInfo() *Err {
|
||||
}
|
||||
|
||||
func (rtx *Rtx) SetGlobal(idx int, val *Val) error {
|
||||
if C.hawk_rtx_setgbl(rtx.c, C.int(idx), (*C.hawk_val_t)(unsafe.Pointer(val.c))) <= -1 {
|
||||
if C.hawk_rtx_setgbl(rtx.c, C.int(idx), val.c) <= -1 {
|
||||
return rtx.make_errinfo()
|
||||
}
|
||||
return nil
|
||||
@@ -695,7 +676,7 @@ func (rtx *Rtx) OnSigset(f RtxSigsetHandler) {
|
||||
}
|
||||
|
||||
func (rtx *Rtx) Exec(args []string) (*Val, error) {
|
||||
var val CPtrVal
|
||||
var val *C.hawk_val_t
|
||||
var cargs []*C.hawk_bch_t
|
||||
var idx int
|
||||
var count int
|
||||
@@ -707,35 +688,35 @@ func (rtx *Rtx) Exec(args []string) (*Val, error) {
|
||||
}
|
||||
|
||||
if count > 0 {
|
||||
val = CPtrVal(unsafe.Pointer(C.hawk_rtx_execwithbcstrarr(rtx.c, &cargs[0], C.hawk_oow_t(count))))
|
||||
val = C.hawk_rtx_execwithbcstrarr(rtx.c, &cargs[0], C.hawk_oow_t(count))
|
||||
} else {
|
||||
val = CPtrVal(unsafe.Pointer(C.hawk_rtx_execwithbcstrarr(rtx.c, (**C.hawk_bch_t)(nil), C.hawk_oow_t(count))))
|
||||
val = C.hawk_rtx_execwithbcstrarr(rtx.c, (**C.hawk_bch_t)(nil), C.hawk_oow_t(count))
|
||||
}
|
||||
|
||||
for idx = 0; idx < count; idx++ {
|
||||
C.free(unsafe.Pointer(cargs[idx]))
|
||||
}
|
||||
if val == 0 { return nil, rtx.make_errinfo() }
|
||||
if val == nil { return nil, rtx.make_errinfo() }
|
||||
|
||||
// hawk_rtx_exec...() returns a value with the reference count incremented.
|
||||
// create a value without going through rtx.make_val()
|
||||
return rtx.fix_val_with_raw(val), nil
|
||||
//return rtx.make_val(func() CPtrVal { return val })
|
||||
//return rtx.make_val(func() *C.hawk_val_t { return val })aAAA
|
||||
}
|
||||
|
||||
func (rtx *Rtx) Loop() (*Val, error) {
|
||||
var val CPtrVal
|
||||
val = CPtrVal(unsafe.Pointer(C.hawk_rtx_loop(rtx.c)))
|
||||
if val == 0 { return nil, rtx.make_errinfo() }
|
||||
var val *C.hawk_val_t
|
||||
val = C.hawk_rtx_loop(rtx.c)
|
||||
if val == nil { return nil, rtx.make_errinfo() }
|
||||
// hawk_rtx_loop() returns a value with the reference count incremented.
|
||||
// create a value without going through rtx.make_val()
|
||||
return rtx.fix_val_with_raw(val), nil
|
||||
//return rtx.make_val(func() *C.hawk_val_t { return val })
|
||||
//return rtx.make_val(func() *C.hawk_val_t { return val })aAAA
|
||||
}
|
||||
|
||||
func (rtx *Rtx) Call(name string, args ...*Val) (*Val, error) {
|
||||
var fun *C.hawk_fun_t
|
||||
var val CPtrVal
|
||||
var val *C.hawk_val_t
|
||||
var cv *C.hawk_bch_t
|
||||
var nargs int
|
||||
|
||||
@@ -746,21 +727,21 @@ func (rtx *Rtx) Call(name string, args ...*Val) (*Val, error) {
|
||||
|
||||
nargs = len(args)
|
||||
if nargs > 0 {
|
||||
var argv []CPtrVal
|
||||
var argv []*C.hawk_val_t
|
||||
var v *Val
|
||||
var i int
|
||||
argv = make([]CPtrVal, nargs)
|
||||
argv = make([]*C.hawk_val_t, nargs)
|
||||
for i, v = range args { argv[i] = v.c }
|
||||
val = CPtrVal(unsafe.Pointer(C.hawk_rtx_callfun(rtx.c, fun, (**C.hawk_val_t)(unsafe.Pointer(&argv[0])), C.hawk_oow_t(nargs))))
|
||||
val = C.hawk_rtx_callfun(rtx.c, fun, &argv[0], C.hawk_oow_t(nargs))
|
||||
} else {
|
||||
val = CPtrVal(unsafe.Pointer(C.hawk_rtx_callfun(rtx.c, fun, nil, 0)))
|
||||
val = C.hawk_rtx_callfun(rtx.c, fun, nil, 0)
|
||||
}
|
||||
if val == 0 { return nil, rtx.make_errinfo() }
|
||||
if val == nil { return nil, rtx.make_errinfo() }
|
||||
|
||||
// hawk_rtx_callfun() returns a value with the reference count incremented.
|
||||
// i create a Val object without incrementing the reference count of val.
|
||||
return rtx.fix_val_with_raw(val), nil
|
||||
//return rtx.make_val(func() CPtrVal { return val })
|
||||
//return rtx.make_val(func() *C.hawk_val_t { return val })aAAA
|
||||
}
|
||||
|
||||
func (rtx *Rtx) ValCount() int {
|
||||
@@ -814,74 +795,63 @@ func (rtx *Rtx) GetFuncArgCount() int {
|
||||
}
|
||||
|
||||
func (rtx *Rtx) GetFuncArg(idx int) (*Val, error) {
|
||||
return rtx.make_val(func() CPtrVal {
|
||||
return CPtrVal(unsafe.Pointer(C.hawk_rtx_getarg(rtx.c, C.hawk_oow_t(idx))))
|
||||
return rtx.make_val(func() *C.hawk_val_t {
|
||||
return C.hawk_rtx_getarg(rtx.c, C.hawk_oow_t(idx))
|
||||
})
|
||||
}
|
||||
|
||||
func (rtx *Rtx) SetFuncRet(v *Val) {
|
||||
C.hawk_rtx_setretval(rtx.c, (*C.hawk_val_t)(unsafe.Pointer(v.c)))
|
||||
C.hawk_rtx_setretval(rtx.c, v.c)
|
||||
}
|
||||
|
||||
func (rtx *Rtx) SetFuncRetWithInt(v int) error {
|
||||
//var vv *C.hawk_val_t
|
||||
//vv = C.hawk_rtx_makeintval(rtx.c, C.hawk_int_t(v))
|
||||
//if vv == nil { return rtx.make_errinfo() }
|
||||
|
||||
var vv CPtrVal
|
||||
vv = CPtrVal(unsafe.Pointer(C.hawk_rtx_makeintval(rtx.c, C.hawk_int_t(v))))
|
||||
if vv == 0 { return rtx.make_errinfo() }
|
||||
|
||||
C.hawk_rtx_refupval(rtx.c, (*C.hawk_val_t)(unsafe.Pointer(vv)))
|
||||
C.hawk_rtx_setretval(rtx.c, (*C.hawk_val_t)(unsafe.Pointer(vv)))
|
||||
C.hawk_rtx_refdownval(rtx.c, (*C.hawk_val_t)(unsafe.Pointer(vv)))
|
||||
var vv *C.hawk_val_t
|
||||
vv = C.hawk_rtx_makeintval(rtx.c, C.hawk_int_t(v))
|
||||
if vv == nil { return rtx.make_errinfo() }
|
||||
C.hawk_rtx_refupval(rtx.c, vv)
|
||||
C.hawk_rtx_setretval(rtx.c, vv)
|
||||
C.hawk_rtx_refdownval(rtx.c, vv)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rtx *Rtx) SetFuncRetWithFlt(v float64) error {
|
||||
//var vv *C.hawk_val_t
|
||||
//vv = C.make_flt_val(rtx.c, C.double(v))
|
||||
//if vv == nil { return rtx.make_errinfo() }
|
||||
|
||||
var vv CPtrVal
|
||||
vv = CPtrVal(unsafe.Pointer(C.make_flt_val(rtx.c, C.double(v))))
|
||||
if vv == 0 { return rtx.make_errinfo() }
|
||||
|
||||
C.hawk_rtx_refupval(rtx.c, (*C.hawk_val_t)(unsafe.Pointer(vv)))
|
||||
C.hawk_rtx_setretval(rtx.c, (*C.hawk_val_t)(unsafe.Pointer(vv)))
|
||||
C.hawk_rtx_refdownval(rtx.c, (*C.hawk_val_t)(unsafe.Pointer(vv)))
|
||||
var vv *C.hawk_val_t
|
||||
vv = C.make_flt_val(rtx.c, C.double(v))
|
||||
if vv == nil { return rtx.make_errinfo() }
|
||||
C.hawk_rtx_refupval(rtx.c, vv)
|
||||
C.hawk_rtx_setretval(rtx.c, vv)
|
||||
C.hawk_rtx_refdownval(rtx.c, vv)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rtx *Rtx) SetFuncRetWithStr(v string) error {
|
||||
//var vv *C.hawk_val_t
|
||||
var vv CPtrVal
|
||||
var vv *C.hawk_val_t
|
||||
var cv *C.hawk_bch_t
|
||||
cv = C.CString(v)
|
||||
//vv = C.hawk_rtx_makestrvalwithbchars(rtx.c, cv, C.hawk_oow_t(len(v)))
|
||||
vv = CPtrVal(unsafe.Pointer(C.hawk_rtx_makestrvalwithbchars(rtx.c, cv, C.hawk_oow_t(len(v)))))
|
||||
vv = C.hawk_rtx_makestrvalwithbchars(rtx.c, cv, C.hawk_oow_t(len(v)))
|
||||
C.free(unsafe.Pointer(cv))
|
||||
//if vv == nil { return rtx.make_errinfo() }
|
||||
if vv == 0 { return rtx.make_errinfo() }
|
||||
C.hawk_rtx_refupval(rtx.c, (*C.hawk_val_t)(unsafe.Pointer(vv)))
|
||||
C.hawk_rtx_setretval(rtx.c, (*C.hawk_val_t)(unsafe.Pointer(vv)))
|
||||
C.hawk_rtx_refdownval(rtx.c, (*C.hawk_val_t)(unsafe.Pointer(vv)))
|
||||
if vv == nil { return rtx.make_errinfo() }
|
||||
C.hawk_rtx_refupval(rtx.c, vv)
|
||||
C.hawk_rtx_setretval(rtx.c, vv)
|
||||
C.hawk_rtx_refdownval(rtx.c, vv)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rtx *Rtx) GetNamedVars(vars map[string]*Val) {
|
||||
var itr C.hawk_rtx_nv_itr_t
|
||||
var val CPtrVal
|
||||
var val *C.hawk_val_t
|
||||
var k string
|
||||
var err error
|
||||
|
||||
C.hawk_init_rtx_nv_itr(&itr)
|
||||
val = CPtrVal(unsafe.Pointer(C.hawk_rtx_getfirstnv(rtx.c, &itr)))
|
||||
for val != 0 {
|
||||
val = C.hawk_rtx_getfirstnv(rtx.c, &itr)
|
||||
for val != nil {
|
||||
k = string(uchars_to_rune_slice((*C.hawk_uch_t)(itr.name.ptr), uintptr(itr.name.len)))
|
||||
vars[k], err = rtx.make_val(func() CPtrVal { return val })
|
||||
if err != nil { return }
|
||||
val = CPtrVal(unsafe.Pointer(C.hawk_rtx_getnextnv(rtx.c, &itr)))
|
||||
vars[k], err = rtx.make_val(func() *C.hawk_val_t { return val })
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
val = C.hawk_rtx_getnextnv(rtx.c, &itr)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1066,97 +1036,96 @@ func (rtx *Rtx) NewVal(v interface{}) (*Val, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func (rtx* Rtx) make_val(vmaker func() CPtrVal) (*Val, error) {
|
||||
var c CPtrVal
|
||||
func (rtx* Rtx) make_val(vmaker func() *C.hawk_val_t) (*Val, error) {
|
||||
var c *C.hawk_val_t
|
||||
var vv *Val
|
||||
|
||||
c = vmaker()
|
||||
if c == 0 { return nil, rtx.make_errinfo() }
|
||||
if c == nil { return nil, rtx.make_errinfo() }
|
||||
|
||||
C.hawk_rtx_refupval(rtx.c, (*C.hawk_val_t)(unsafe.Pointer(c)))
|
||||
C.hawk_rtx_refupval(rtx.c, c)
|
||||
vv = &Val{rtx: rtx, c: c}
|
||||
rtx.chain_val(vv)
|
||||
return vv, nil
|
||||
}
|
||||
|
||||
func (rtx* Rtx) fix_val_with_raw(val CPtrVal) *Val {
|
||||
func (rtx* Rtx) fix_val_with_raw(val *C.hawk_val_t) *Val {
|
||||
// this function assumes val has the non-zero reference count
|
||||
// the caller must ensure that the reference count has been incremented properly
|
||||
var vv *Val
|
||||
// immediate values or static pointer values must no check the reference count.
|
||||
if C.hawk_rtx_isimmorstaticval(rtx.c, (*C.hawk_val_t)(unsafe.Pointer(val))) == 0 && ((*C.hawk_val_t)(unsafe.Pointer(val))).v_refs <= 0 { panic("invalid reference count") }
|
||||
if val.v_refs <= 0 && C.hawk_rtx_isstaticval(rtx.c, val) == 0 { panic("invalid reference count") }
|
||||
vv = &Val{rtx: rtx, c: val}
|
||||
rtx.chain_val(vv)
|
||||
return vv
|
||||
}
|
||||
|
||||
func (rtx *Rtx) NewByteVal(v byte) (*Val, error) {
|
||||
return rtx.make_val(func() CPtrVal {
|
||||
return CPtrVal(unsafe.Pointer(C.hawk_rtx_makebchrval(rtx.c, C.hawk_bch_t(v))))
|
||||
return rtx.make_val(func() *C.hawk_val_t {
|
||||
return C.hawk_rtx_makebchrval(rtx.c, C.hawk_bch_t(v))
|
||||
})
|
||||
}
|
||||
|
||||
func (rtx *Rtx) NewCharVal(v rune) (*Val, error) {
|
||||
return rtx.make_val(func() CPtrVal {
|
||||
return CPtrVal(unsafe.Pointer(C.hawk_rtx_makecharval(rtx.c, C.hawk_ooch_t(v))))
|
||||
return rtx.make_val(func() *C.hawk_val_t {
|
||||
return C.hawk_rtx_makecharval(rtx.c, C.hawk_ooch_t(v))
|
||||
})
|
||||
}
|
||||
|
||||
func (rtx *Rtx) NewIntVal(v int) (*Val, error) {
|
||||
return rtx.make_val(func() CPtrVal {
|
||||
return CPtrVal(unsafe.Pointer(C.hawk_rtx_makeintval(rtx.c, C.hawk_int_t(v))))
|
||||
return rtx.make_val(func() *C.hawk_val_t {
|
||||
return C.hawk_rtx_makeintval(rtx.c, C.hawk_int_t(v))
|
||||
})
|
||||
}
|
||||
|
||||
func (rtx *Rtx) NewFltVal(v float64) (*Val, error) {
|
||||
return rtx.make_val(func() CPtrVal {
|
||||
return CPtrVal(unsafe.Pointer(C.make_flt_val(rtx.c, C.double(v))))
|
||||
return rtx.make_val(func() *C.hawk_val_t {
|
||||
return C.make_flt_val(rtx.c, C.double(v))
|
||||
})
|
||||
}
|
||||
|
||||
func (rtx *Rtx) NewStrVal(v string) (*Val, error) {
|
||||
return rtx.make_val(func() CPtrVal {
|
||||
var vv CPtrVal
|
||||
return rtx.make_val(func() *C.hawk_val_t {
|
||||
var vv *C.hawk_val_t
|
||||
var cv *C.hawk_bch_t
|
||||
cv = C.CString(v)
|
||||
vv = CPtrVal(unsafe.Pointer(C.hawk_rtx_makestrvalwithbchars(rtx.c, cv, C.hawk_oow_t(len(v)))))
|
||||
vv = C.hawk_rtx_makestrvalwithbchars(rtx.c, cv, C.hawk_oow_t(len(v)))
|
||||
C.free(unsafe.Pointer(cv))
|
||||
return vv
|
||||
})
|
||||
}
|
||||
|
||||
func (rtx *Rtx) NewNumOrStrVal(v string, mode int) (*Val, error) {
|
||||
return rtx.make_val(func() CPtrVal {
|
||||
var vv CPtrVal
|
||||
return rtx.make_val(func() *C.hawk_val_t {
|
||||
var vv *C.hawk_val_t
|
||||
var cv *C.hawk_bch_t
|
||||
cv = C.CString(v)
|
||||
vv = CPtrVal(unsafe.Pointer(C.hawk_rtx_makenumorstrvalwithbchars(rtx.c, cv, C.hawk_oow_t(len(v)), C.int(mode))))
|
||||
vv = C.hawk_rtx_makenumorstrvalwithbchars(rtx.c, cv, C.hawk_oow_t(len(v)), C.int(mode))
|
||||
C.free(unsafe.Pointer(cv))
|
||||
return vv
|
||||
})
|
||||
}
|
||||
|
||||
func (rtx *Rtx) NewByteArrVal(v []byte) (*Val, error) {
|
||||
return rtx.make_val(func() CPtrVal {
|
||||
return CPtrVal(unsafe.Pointer(C.hawk_rtx_makembsvalwithbchars(rtx.c, (*C.hawk_bch_t)(unsafe.Pointer(&v[0])), C.hawk_oow_t(len(v)))))
|
||||
return rtx.make_val(func() *C.hawk_val_t {
|
||||
return C.hawk_rtx_makembsvalwithbchars(rtx.c, (*C.hawk_bch_t)(unsafe.Pointer(&v[0])), C.hawk_oow_t(len(v)))
|
||||
})
|
||||
}
|
||||
|
||||
func (rtx *Rtx) NewBobVal(v []byte) (*Val, error) {
|
||||
return rtx.make_val(func() CPtrVal {
|
||||
return CPtrVal(unsafe.Pointer(C.hawk_rtx_makebobval(rtx.c, unsafe.Pointer(&v[0]), C.hawk_oow_t(len(v)))))
|
||||
return rtx.make_val(func() *C.hawk_val_t {
|
||||
return C.hawk_rtx_makebobval(rtx.c, unsafe.Pointer(&v[0]), C.hawk_oow_t(len(v)))
|
||||
})
|
||||
}
|
||||
|
||||
func (rtx *Rtx) NewMapVal() (*Val, error) {
|
||||
return rtx.make_val(func() CPtrVal {
|
||||
return CPtrVal(unsafe.Pointer(C.hawk_rtx_makemapval(rtx.c)))
|
||||
return rtx.make_val(func() *C.hawk_val_t {
|
||||
return C.hawk_rtx_makemapval(rtx.c)
|
||||
})
|
||||
}
|
||||
|
||||
func (rtx *Rtx) NewArrVal(init_capa int) (*Val, error) {
|
||||
return rtx.make_val(func() CPtrVal {
|
||||
return CPtrVal(unsafe.Pointer(C.hawk_rtx_makearrval(rtx.c, C.hawk_ooi_t(init_capa))))
|
||||
return rtx.make_val(func() *C.hawk_val_t {
|
||||
return C.hawk_rtx_makearrval(rtx.c, C.hawk_ooi_t(init_capa))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1167,13 +1136,13 @@ func (val *Val) Close() {
|
||||
var rtx *C.hawk_rtx_t
|
||||
rtx = val.rtx.c // store this field as unchain_val() resets it to nil
|
||||
val.rtx.unchain_val(val)
|
||||
C.hawk_rtx_refdownval(rtx, (*C.hawk_val_t)(unsafe.Pointer(val.c)))
|
||||
C.hawk_rtx_refdownval(rtx, val.c)
|
||||
}
|
||||
}
|
||||
|
||||
func (val *Val) Type() ValType {
|
||||
var x C.int
|
||||
x = C.hawk_rtx_getvaltype(val.rtx.c, (*C.hawk_val_t)(unsafe.Pointer(val.c)))
|
||||
x = C.hawk_rtx_getvaltype(val.rtx.c, val.c)
|
||||
return ValType(x)
|
||||
}
|
||||
|
||||
@@ -1187,7 +1156,7 @@ func (val *Val) ToInt() (int, error) {
|
||||
var v C.hawk_int_t
|
||||
var x C.int
|
||||
|
||||
x = C.hawk_rtx_valtoint(val.rtx.c, (*C.hawk_val_t)(unsafe.Pointer(val.c)), &v)
|
||||
x = C.hawk_rtx_valtoint(val.rtx.c, val.c, &v)
|
||||
if x <= -1 { return 0, val.rtx.make_errinfo() }
|
||||
|
||||
return int(v), nil
|
||||
@@ -1198,7 +1167,7 @@ func (val *Val) ToFlt() (float64, error) {
|
||||
var x C.int
|
||||
|
||||
//x = C.hawk_rtx_valtoflt(val.rtx.c, val.c, &v)
|
||||
x = C.val_to_flt(val.rtx.c, (*C.hawk_val_t)(unsafe.Pointer(val.c)), (*C.double)(&v))
|
||||
x = C.val_to_flt(val.rtx.c, val.c, (*C.double)(&v))
|
||||
if x <= -1 { return 0, val.rtx.make_errinfo() }
|
||||
|
||||
return v, nil
|
||||
@@ -1212,7 +1181,7 @@ func (val *Val) ToStr() (string, error) {
|
||||
var x C.int
|
||||
|
||||
out._type = C.HAWK_RTX_VALTOSTR_CPLDUP
|
||||
x = C.hawk_rtx_valtostr(val.rtx.c, (*C.hawk_val_t)(unsafe.Pointer(val.c)), &out)
|
||||
x = C.hawk_rtx_valtostr(val.rtx.c, val.c, &out)
|
||||
if x <= -1 { return "", val.rtx.make_errinfo() }
|
||||
|
||||
ptr = C.valtostr_out_cpldup(&out, &len)
|
||||
@@ -1227,7 +1196,7 @@ func (val *Val) ToByteArr() ([]byte, error) {
|
||||
var len C.hawk_oow_t
|
||||
var v []byte
|
||||
|
||||
ptr = C.hawk_rtx_valtobcstrdupwithcmgr(val.rtx.c, (*C.hawk_val_t)(unsafe.Pointer(val.c)), &len, C.hawk_rtx_getcmgr(val.rtx.c))
|
||||
ptr = C.hawk_rtx_valtobcstrdupwithcmgr(val.rtx.c, val.c, &len, C.hawk_rtx_getcmgr(val.rtx.c))
|
||||
if ptr == nil { return nil, val.rtx.make_errinfo() }
|
||||
|
||||
v = C.GoBytes(unsafe.Pointer(ptr), C.int(len))
|
||||
@@ -1239,212 +1208,149 @@ func (val *Val) ToByteArr() ([]byte, error) {
|
||||
func (val *Val) ArrayTally() int {
|
||||
var v C.hawk_ooi_t
|
||||
// TODO: if not array .. panic or return -1 or 0?
|
||||
v = C.hawk_rtx_getarrvaltally(val.rtx.c, (*C.hawk_val_t)(unsafe.Pointer(val.c)))
|
||||
v = C.hawk_rtx_getarrvaltally(val.rtx.c, val.c)
|
||||
return int(v)
|
||||
}
|
||||
|
||||
// TODO: function to get the first index and last index or the capacity
|
||||
// function to traverse?
|
||||
func (val *Val) GetArrayField(index int) (*Val, error) {
|
||||
var v CPtrVal
|
||||
v = CPtrVal(unsafe.Pointer(C.hawk_rtx_getarrvalfld(val.rtx.c, (*C.hawk_val_t)(unsafe.Pointer(val.c)), C.hawk_ooi_t(index))))
|
||||
if v == 0 { return nil, val.rtx.make_errinfo() }
|
||||
return val.rtx.make_val(func() CPtrVal { return v })
|
||||
var v *C.hawk_val_t
|
||||
v = C.hawk_rtx_getarrvalfld(val.rtx.c, val.c, C.hawk_ooi_t(index))
|
||||
if v == nil { return nil, val.rtx.make_errinfo() }
|
||||
return val.rtx.make_val(func() *C.hawk_val_t { return v })
|
||||
}
|
||||
|
||||
func (val *Val) SetArrayField(index int, v *Val) error {
|
||||
var vv CPtrVal
|
||||
vv = CPtrVal(unsafe.Pointer(C.hawk_rtx_setarrvalfld(
|
||||
val.rtx.c,
|
||||
(*C.hawk_val_t)(unsafe.Pointer(val.c)),
|
||||
C.hawk_ooi_t(index),
|
||||
(*C.hawk_val_t)(unsafe.Pointer(v.c)))))
|
||||
if vv == 0 { return val.rtx.make_errinfo() }
|
||||
var vv *C.hawk_val_t
|
||||
vv = C.hawk_rtx_setarrvalfld(val.rtx.c, val.c, C.hawk_ooi_t(index), v.c)
|
||||
if vv == nil { return val.rtx.make_errinfo() }
|
||||
return nil
|
||||
}
|
||||
|
||||
func (val *Val) SetArrayFieldWithInt(index int, v int) error {
|
||||
var vv CPtrVal
|
||||
var ww CPtrVal
|
||||
vv = CPtrVal(unsafe.Pointer(C.hawk_rtx_makeintval(val.rtx.c, C.hawk_int_t(v))))
|
||||
if vv == 0 { return val.rtx.make_errinfo() }
|
||||
C.hawk_rtx_refupval(val.rtx.c, (*C.hawk_val_t)(unsafe.Pointer(vv)))
|
||||
ww = CPtrVal(unsafe.Pointer(C.hawk_rtx_setarrvalfld(
|
||||
val.rtx.c,
|
||||
(*C.hawk_val_t)(unsafe.Pointer(val.c)),
|
||||
C.hawk_ooi_t(index),
|
||||
(*C.hawk_val_t)(unsafe.Pointer(vv)))))
|
||||
C.hawk_rtx_refdownval(val.rtx.c, (*C.hawk_val_t)(unsafe.Pointer(vv)))
|
||||
if ww == 0 { return val.rtx.make_errinfo() }
|
||||
var vv *C.hawk_val_t
|
||||
var ww *C.hawk_val_t
|
||||
vv = C.hawk_rtx_makeintval(val.rtx.c, C.hawk_int_t(v))
|
||||
if vv == nil { return val.rtx.make_errinfo() }
|
||||
C.hawk_rtx_refupval(val.rtx.c, vv)
|
||||
ww = C.hawk_rtx_setarrvalfld(val.rtx.c, val.c, C.hawk_ooi_t(index), vv)
|
||||
C.hawk_rtx_refdownval(val.rtx.c, vv)
|
||||
if ww == nil { return val.rtx.make_errinfo() }
|
||||
return nil
|
||||
}
|
||||
|
||||
func (val *Val) SetArrayFieldWithFlt(index int, v float64) error {
|
||||
var vv CPtrVal
|
||||
var ww CPtrVal
|
||||
vv = CPtrVal(unsafe.Pointer(C.make_flt_val(val.rtx.c, C.double(v))))
|
||||
if vv == 0 { return val.rtx.make_errinfo() }
|
||||
C.hawk_rtx_refupval(val.rtx.c, (*C.hawk_val_t)(unsafe.Pointer(vv)))
|
||||
ww = CPtrVal(unsafe.Pointer(C.hawk_rtx_setarrvalfld(
|
||||
val.rtx.c,
|
||||
(*C.hawk_val_t)(unsafe.Pointer(val.c)),
|
||||
C.hawk_ooi_t(index),
|
||||
(*C.hawk_val_t)(unsafe.Pointer(vv)))))
|
||||
C.hawk_rtx_refdownval(val.rtx.c, (*C.hawk_val_t)(unsafe.Pointer(vv)))
|
||||
if ww == 0 { return val.rtx.make_errinfo() }
|
||||
var vv *C.hawk_val_t
|
||||
vv = C.make_flt_val(val.rtx.c, C.double(v))
|
||||
if vv == nil { return val.rtx.make_errinfo() }
|
||||
C.hawk_rtx_refupval(val.rtx.c, vv)
|
||||
vv = C.hawk_rtx_setarrvalfld(val.rtx.c, val.c, C.hawk_ooi_t(index), vv)
|
||||
C.hawk_rtx_refdownval(val.rtx.c, vv)
|
||||
if vv == nil { return val.rtx.make_errinfo() }
|
||||
return nil
|
||||
}
|
||||
|
||||
func (val *Val) SetArrayFieldWithStr(index int, v string) error {
|
||||
var vv CPtrVal
|
||||
var ww CPtrVal
|
||||
var vv *C.hawk_val_t
|
||||
var cv *C.hawk_bch_t
|
||||
cv = C.CString(v)
|
||||
vv = CPtrVal(unsafe.Pointer(C.hawk_rtx_makestrvalwithbchars(val.rtx.c, cv, C.hawk_oow_t(len(v)))))
|
||||
vv = C.hawk_rtx_makestrvalwithbchars(val.rtx.c, cv, C.hawk_oow_t(len(v)))
|
||||
C.free(unsafe.Pointer(cv))
|
||||
if vv == 0 { return val.rtx.make_errinfo() }
|
||||
C.hawk_rtx_refupval(val.rtx.c, (*C.hawk_val_t)(unsafe.Pointer(vv)))
|
||||
ww = CPtrVal(unsafe.Pointer(C.hawk_rtx_setarrvalfld(
|
||||
val.rtx.c,
|
||||
(*C.hawk_val_t)(unsafe.Pointer(val.c)),
|
||||
C.hawk_ooi_t(index),
|
||||
(*C.hawk_val_t)(unsafe.Pointer(vv)))))
|
||||
C.hawk_rtx_refdownval(val.rtx.c, (*C.hawk_val_t)(unsafe.Pointer(vv)))
|
||||
if ww == 0 { return val.rtx.make_errinfo() }
|
||||
if vv == nil { return val.rtx.make_errinfo() }
|
||||
C.hawk_rtx_refupval(val.rtx.c, vv)
|
||||
vv = C.hawk_rtx_setarrvalfld(val.rtx.c, val.c, C.hawk_ooi_t(index), vv)
|
||||
C.hawk_rtx_refdownval(val.rtx.c, vv)
|
||||
if vv == nil { return val.rtx.make_errinfo() }
|
||||
return nil
|
||||
}
|
||||
|
||||
func (itr *ValArrayItr) cptr() *C.hawk_val_arr_itr_t {
|
||||
return (*C.hawk_val_arr_itr_t)(unsafe.Pointer(&itr.c[0]))
|
||||
}
|
||||
|
||||
func (val *Val) GetFirstArrayField(itr *ValArrayItr) (int, *Val) {
|
||||
//var i *C.hawk_val_arr_itr_t
|
||||
var i uintptr
|
||||
var i *C.hawk_val_arr_itr_t
|
||||
var v *Val
|
||||
var err error
|
||||
|
||||
i = uintptr(unsafe.Pointer(C.hawk_rtx_getfirstarrvalitr(
|
||||
val.rtx.c,
|
||||
(*C.hawk_val_t)(unsafe.Pointer(val.c)),
|
||||
itr.cptr())))
|
||||
if i == 0 { return -1, nil }
|
||||
|
||||
v, err = val.rtx.make_val(func() CPtrVal {
|
||||
return CPtrVal(C.val_arr_itr_elem(itr.cptr()))
|
||||
})
|
||||
i = C.hawk_rtx_getfirstarrvalitr(val.rtx.c, val.c, &itr.c)
|
||||
if i == nil { return -1, nil }
|
||||
v, err = val.rtx.make_val(func() *C.hawk_val_t { return itr.c.elem })
|
||||
if err != nil { return -1, nil }
|
||||
return int(itr.cptr().itr.idx), v;
|
||||
return int(itr.c.itr.idx), v;
|
||||
}
|
||||
|
||||
func (val *Val) GetNextArrayField(itr *ValArrayItr) (int, *Val) {
|
||||
//var i *C.hawk_val_arr_itr_t
|
||||
var i uintptr
|
||||
var i *C.hawk_val_arr_itr_t
|
||||
var v *Val
|
||||
var err error
|
||||
|
||||
i = uintptr(unsafe.Pointer(C.hawk_rtx_getnextarrvalitr(
|
||||
val.rtx.c,
|
||||
(*C.hawk_val_t)(unsafe.Pointer(val.c)),
|
||||
itr.cptr())))
|
||||
if i == 0 { return -1, nil }
|
||||
|
||||
v, err = val.rtx.make_val(func() CPtrVal {
|
||||
return CPtrVal(C.val_arr_itr_elem(itr.cptr()))
|
||||
})
|
||||
i = C.hawk_rtx_getnextarrvalitr(val.rtx.c, val.c, &itr.c)
|
||||
if i == nil { return -1, nil }
|
||||
v, err = val.rtx.make_val(func() *C.hawk_val_t { return itr.c.elem })
|
||||
if err != nil { return -1, nil }
|
||||
return int(itr.cptr().itr.idx), v;
|
||||
return int(itr.c.itr.idx), v;
|
||||
}
|
||||
|
||||
func (val *Val) GetMapField(key string) (*Val, error) {
|
||||
var v CPtrVal
|
||||
var v *C.hawk_val_t
|
||||
var uc []C.hawk_uch_t
|
||||
|
||||
uc = string_to_uchars(key)
|
||||
v = (CPtrVal)(unsafe.Pointer(C.hawk_rtx_getmapvalfld(
|
||||
val.rtx.c,
|
||||
(*C.hawk_val_t)(unsafe.Pointer(val.c)),
|
||||
&uc[0],
|
||||
C.hawk_oow_t(len(uc)))))
|
||||
if v == 0 { return nil, val.rtx.make_errinfo() }
|
||||
return val.rtx.make_val(func() CPtrVal { return v })
|
||||
v = C.hawk_rtx_getmapvalfld(val.rtx.c, val.c, &uc[0], C.hawk_oow_t(len(uc)))
|
||||
if v == nil { return nil, val.rtx.make_errinfo() }
|
||||
return val.rtx.make_val(func() *C.hawk_val_t { return v })
|
||||
}
|
||||
|
||||
func (val *Val) SetMapField(key string, v *Val) error {
|
||||
var vv CPtrVal
|
||||
var vv *C.hawk_val_t
|
||||
var kk []C.hawk_uch_t
|
||||
|
||||
kk = string_to_uchars(key)
|
||||
vv = (CPtrVal)(unsafe.Pointer(C.hawk_rtx_setmapvalfld(
|
||||
val.rtx.c,
|
||||
(*C.hawk_val_t)(unsafe.Pointer(val.c)),
|
||||
&kk[0],
|
||||
C.hawk_oow_t(len(kk)),
|
||||
(*C.hawk_val_t)(unsafe.Pointer(v.c)))))
|
||||
if vv == 0 { return val.rtx.make_errinfo() }
|
||||
vv = C.hawk_rtx_setmapvalfld(val.rtx.c, val.c, &kk[0], C.hawk_oow_t(len(kk)), v.c)
|
||||
if vv == nil { return val.rtx.make_errinfo() }
|
||||
return nil
|
||||
}
|
||||
|
||||
func (val *Val) SetMapFieldWithInt(key string, v int) error {
|
||||
var kk []C.hawk_uch_t
|
||||
var vv CPtrVal
|
||||
var ww CPtrVal
|
||||
var vv *C.hawk_val_t
|
||||
var ww *C.hawk_val_t
|
||||
|
||||
kk = string_to_uchars(key)
|
||||
vv = CPtrVal(unsafe.Pointer(C.hawk_rtx_makeintval(val.rtx.c, C.hawk_int_t(v))))
|
||||
if vv == 0 { return val.rtx.make_errinfo() }
|
||||
C.hawk_rtx_refupval(val.rtx.c, (*C.hawk_val_t)(unsafe.Pointer(vv)))
|
||||
ww = CPtrVal(unsafe.Pointer(C.hawk_rtx_setmapvalfld(
|
||||
val.rtx.c,
|
||||
(*C.hawk_val_t)(unsafe.Pointer(val.c)),
|
||||
&kk[0],
|
||||
C.hawk_oow_t(len(kk)),
|
||||
(*C.hawk_val_t)(unsafe.Pointer(vv)))))
|
||||
C.hawk_rtx_refdownval(val.rtx.c, (*C.hawk_val_t)(unsafe.Pointer(vv)))
|
||||
if ww == 0 { return val.rtx.make_errinfo() }
|
||||
vv = C.hawk_rtx_makeintval(val.rtx.c, C.hawk_int_t(v))
|
||||
if vv == nil { return val.rtx.make_errinfo() }
|
||||
C.hawk_rtx_refupval(val.rtx.c, vv)
|
||||
ww = C.hawk_rtx_setmapvalfld(val.rtx.c, val.c, &kk[0], C.hawk_oow_t(len(kk)), vv)
|
||||
C.hawk_rtx_refdownval(val.rtx.c, vv)
|
||||
if ww == nil { return val.rtx.make_errinfo() }
|
||||
return nil
|
||||
}
|
||||
|
||||
func (val *Val) SetMapFieldWithFlt(key string, v float64) error {
|
||||
var kk []C.hawk_uch_t
|
||||
var vv CPtrVal
|
||||
var ww CPtrVal
|
||||
var vv *C.hawk_val_t
|
||||
var ww *C.hawk_val_t
|
||||
|
||||
kk = string_to_uchars(key)
|
||||
vv = CPtrVal(unsafe.Pointer(C.make_flt_val(val.rtx.c, C.double(v))))
|
||||
if vv == 0 { return val.rtx.make_errinfo() }
|
||||
C.hawk_rtx_refupval(val.rtx.c, (*C.hawk_val_t)(unsafe.Pointer(vv)))
|
||||
ww = CPtrVal(unsafe.Pointer(C.hawk_rtx_setmapvalfld(
|
||||
val.rtx.c,
|
||||
(*C.hawk_val_t)(unsafe.Pointer(val.c)),
|
||||
&kk[0],
|
||||
C.hawk_oow_t(len(kk)),
|
||||
(*C.hawk_val_t)(unsafe.Pointer(vv)))))
|
||||
C.hawk_rtx_refdownval(val.rtx.c, (*C.hawk_val_t)(unsafe.Pointer(vv)))
|
||||
if ww == 0 { return val.rtx.make_errinfo() }
|
||||
vv = C.make_flt_val(val.rtx.c, C.double(v))
|
||||
if vv == nil { return val.rtx.make_errinfo() }
|
||||
C.hawk_rtx_refupval(val.rtx.c, vv)
|
||||
ww = C.hawk_rtx_setmapvalfld(val.rtx.c, val.c, &kk[0], C.hawk_oow_t(len(kk)), vv)
|
||||
C.hawk_rtx_refdownval(val.rtx.c, vv)
|
||||
if ww == nil { return val.rtx.make_errinfo() }
|
||||
return nil
|
||||
}
|
||||
|
||||
func (val *Val) SetMapFieldWithStr(key string, v string) error {
|
||||
var kk []C.hawk_uch_t
|
||||
var vv CPtrVal
|
||||
var ww CPtrVal
|
||||
var vv *C.hawk_val_t
|
||||
var ww *C.hawk_val_t
|
||||
var cv *C.hawk_bch_t
|
||||
|
||||
kk = string_to_uchars(key)
|
||||
cv = C.CString(v)
|
||||
vv = CPtrVal(unsafe.Pointer(C.hawk_rtx_makestrvalwithbchars(val.rtx.c, cv, C.hawk_oow_t(len(v)))))
|
||||
vv = C.hawk_rtx_makestrvalwithbchars(val.rtx.c, cv, C.hawk_oow_t(len(v)))
|
||||
C.free(unsafe.Pointer(cv))
|
||||
if vv == 0 { return val.rtx.make_errinfo() }
|
||||
C.hawk_rtx_refupval(val.rtx.c, (*C.hawk_val_t)(unsafe.Pointer(vv)))
|
||||
ww = CPtrVal(unsafe.Pointer(C.hawk_rtx_setmapvalfld(
|
||||
val.rtx.c,
|
||||
(*C.hawk_val_t)(unsafe.Pointer(val.c)),
|
||||
&kk[0],
|
||||
C.hawk_oow_t(len(kk)),
|
||||
(*C.hawk_val_t)(unsafe.Pointer(vv)))))
|
||||
C.hawk_rtx_refdownval(val.rtx.c, (*C.hawk_val_t)(unsafe.Pointer(vv)))
|
||||
if ww == 0 { return val.rtx.make_errinfo() }
|
||||
if vv == nil { return val.rtx.make_errinfo() }
|
||||
C.hawk_rtx_refupval(val.rtx.c, vv)
|
||||
ww = C.hawk_rtx_setmapvalfld(val.rtx.c, val.c, &kk[0], C.hawk_oow_t(len(kk)), vv)
|
||||
C.hawk_rtx_refdownval(val.rtx.c, vv)
|
||||
if ww == nil { return val.rtx.make_errinfo() }
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1453,14 +1359,10 @@ func (val *Val) GetFirstMapField(itr *ValMapItr) (string, *Val) {
|
||||
var k string
|
||||
var v *Val
|
||||
var err error
|
||||
|
||||
i = C.hawk_rtx_getfirstmapvalitr(val.rtx.c, (*C.hawk_val_t)(unsafe.Pointer(val.c)), &itr.c)
|
||||
i = C.hawk_rtx_getfirstmapvalitr(val.rtx.c, val.c, &itr.c)
|
||||
if i == nil { return "", nil }
|
||||
|
||||
k = string(uchars_to_rune_slice((*C.hawk_uch_t)(itr.c.pair.key.ptr), uintptr(itr.c.pair.key.len)))
|
||||
v, err = val.rtx.make_val(func() CPtrVal {
|
||||
return CPtrVal(C.val_map_itr_val(&itr.c))
|
||||
})
|
||||
v, err = val.rtx.make_val(func() *C.hawk_val_t { return (*C.hawk_val_t)(itr.c.pair.val.ptr) })
|
||||
if err != nil { return "", nil }
|
||||
return k, v;
|
||||
}
|
||||
@@ -1470,14 +1372,10 @@ func (val *Val) GetNextMapField(itr *ValMapItr) (string, *Val) {
|
||||
var k string
|
||||
var v *Val
|
||||
var err error
|
||||
|
||||
i = C.hawk_rtx_getnextmapvalitr(val.rtx.c, (*C.hawk_val_t)(unsafe.Pointer(val.c)), &itr.c)
|
||||
i = C.hawk_rtx_getnextmapvalitr(val.rtx.c, val.c, &itr.c)
|
||||
if i == nil { return "", nil }
|
||||
|
||||
k = string(uchars_to_rune_slice((*C.hawk_uch_t)(itr.c.pair.key.ptr), uintptr(itr.c.pair.key.len)))
|
||||
v, err = val.rtx.make_val(func() CPtrVal {
|
||||
return CPtrVal(C.val_map_itr_val(&itr.c))
|
||||
})
|
||||
v, err = val.rtx.make_val(func() *C.hawk_val_t { return (*C.hawk_val_t)(itr.c.pair.val.ptr) })
|
||||
if err != nil { return "", nil }
|
||||
return k, v;
|
||||
}
|
||||
|
||||
+5
-307
@@ -19,9 +19,7 @@ func make_hawk(script string) (*hawk.Hawk, error) {
|
||||
var err error
|
||||
|
||||
h, err = hawk.New()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err != nil { return nil, err }
|
||||
|
||||
err = h.ParseText(script)
|
||||
if err != nil {
|
||||
@@ -57,9 +55,7 @@ func make_hawk_extended(script string) (*hawk.Hawk, error) {
|
||||
var err error
|
||||
|
||||
h, err = hawk.New()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err != nil { return nil, err }
|
||||
|
||||
h.AddFunc("enbase64", 1, 10, "", enbase64)
|
||||
h.AddFunc("debase64", 1, 1, "", debase64)
|
||||
@@ -73,155 +69,6 @@ func make_hawk_extended(script string) (*hawk.Hawk, error) {
|
||||
return h, nil
|
||||
}
|
||||
|
||||
func echoint(rtx *hawk.Rtx) error {
|
||||
var v *hawk.Val
|
||||
var i int
|
||||
var err error
|
||||
|
||||
v, err = rtx.GetFuncArg(0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
i, err = v.ToInt()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return rtx.SetFuncRetWithInt(i)
|
||||
}
|
||||
|
||||
func force_gc() {
|
||||
runtime.GC()
|
||||
runtime.Gosched()
|
||||
}
|
||||
|
||||
func expect_int_val(t *testing.T, v *hawk.Val, want int, msg string) {
|
||||
var got int
|
||||
var s string
|
||||
var err error
|
||||
|
||||
t.Helper()
|
||||
|
||||
got, err = v.ToInt()
|
||||
if err != nil {
|
||||
t.Fatalf("%s: failed to convert to int - %s", msg, err.Error())
|
||||
}
|
||||
if got != want {
|
||||
t.Fatalf("%s: expected %d but got %d", msg, want, got)
|
||||
}
|
||||
|
||||
s, err = v.ToStr()
|
||||
if err != nil {
|
||||
t.Fatalf("%s: failed to convert to string - %s", msg, err.Error())
|
||||
}
|
||||
if s != fmt.Sprintf("%d", want) {
|
||||
t.Fatalf("%s: expected string %q but got %q", msg, fmt.Sprintf("%d", want), s)
|
||||
}
|
||||
}
|
||||
|
||||
func expect_map_ints(t *testing.T, v *hawk.Val, want map[string]int) {
|
||||
var key string
|
||||
var f *hawk.Val
|
||||
var got map[string]int
|
||||
var itr hawk.ValMapItr
|
||||
var err error
|
||||
|
||||
t.Helper()
|
||||
|
||||
if v.Type() != hawk.VAL_MAP {
|
||||
t.Fatalf("expected a map but got %s", v.Type().String())
|
||||
}
|
||||
|
||||
for key = range want {
|
||||
force_gc()
|
||||
f, err = v.GetMapField(key)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to get map field %q - %s", key, err.Error())
|
||||
}
|
||||
expect_int_val(t, f, want[key], fmt.Sprintf("map field %q", key))
|
||||
}
|
||||
|
||||
got = make(map[string]int)
|
||||
key, f = v.GetFirstMapField(&itr)
|
||||
for f != nil {
|
||||
var iv int
|
||||
|
||||
force_gc()
|
||||
iv, err = f.ToInt()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to convert iterated map value for key %q - %s", key, err.Error())
|
||||
}
|
||||
got[key] = iv
|
||||
|
||||
force_gc()
|
||||
key, f = v.GetNextMapField(&itr)
|
||||
}
|
||||
|
||||
if len(got) != len(want) {
|
||||
t.Fatalf("expected %d iterated map entries but got %d", len(want), len(got))
|
||||
}
|
||||
|
||||
for key = range want {
|
||||
if got[key] != want[key] {
|
||||
t.Fatalf("iterated map field %q: expected %d but got %d", key, want[key], got[key])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func expect_array_ints(t *testing.T, v *hawk.Val, want map[int]int) {
|
||||
var idx int
|
||||
var f *hawk.Val
|
||||
var got map[int]int
|
||||
var itr hawk.ValArrayItr
|
||||
var err error
|
||||
|
||||
t.Helper()
|
||||
|
||||
if v.Type() != hawk.VAL_ARR {
|
||||
t.Fatalf("expected an array but got %s", v.Type().String())
|
||||
}
|
||||
|
||||
if v.ArrayTally() != len(want) {
|
||||
t.Fatalf("expected %d array elements but got %d", len(want), v.ArrayTally())
|
||||
}
|
||||
|
||||
for idx = range want {
|
||||
force_gc()
|
||||
f, err = v.GetArrayField(idx)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to get array field %d - %s", idx, err.Error())
|
||||
}
|
||||
expect_int_val(t, f, want[idx], fmt.Sprintf("array field %d", idx))
|
||||
}
|
||||
|
||||
got = make(map[int]int)
|
||||
idx, f = v.GetFirstArrayField(&itr)
|
||||
for f != nil {
|
||||
var iv int
|
||||
|
||||
force_gc()
|
||||
iv, err = f.ToInt()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to convert iterated array value at %d - %s", idx, err.Error())
|
||||
}
|
||||
got[idx] = iv
|
||||
|
||||
force_gc()
|
||||
idx, f = v.GetNextArrayField(&itr)
|
||||
}
|
||||
|
||||
if len(got) != len(want) {
|
||||
t.Fatalf("expected %d iterated array entries but got %d", len(want), len(got))
|
||||
}
|
||||
|
||||
for idx = range want {
|
||||
if got[idx] != want[idx] {
|
||||
t.Fatalf("iterated array field %d: expected %d but got %d", idx, want[idx], got[idx])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func run_hawk(h *hawk.Hawk, id int, t *testing.T, wg *sync.WaitGroup) {
|
||||
var rtx *hawk.Rtx
|
||||
var v *hawk.Val
|
||||
@@ -258,17 +105,13 @@ func run_hawk(h *hawk.Hawk, id int, t *testing.T, wg *sync.WaitGroup) {
|
||||
|
||||
// check if ValCount() returns the right number of values created. 3 explicitly and 1 return value
|
||||
i = rtx.ValCount()
|
||||
if i != 4 {
|
||||
t.Errorf("the number of val objects for rtx id[%d] must be 4. but %d was returned", id, i)
|
||||
}
|
||||
if i != 4 { t.Errorf("the number of val objects for rtx id[%d] must be 4. but %d was returned", id, i) }
|
||||
|
||||
rtx.Close()
|
||||
|
||||
// it's safe to all ValCount() after Close() has been called.
|
||||
i = rtx.ValCount()
|
||||
if i != 0 {
|
||||
t.Errorf("the number of val objects for rtx id[%d] must be 0. but %d was returned", id, i)
|
||||
}
|
||||
if i != 0 { t.Errorf("the number of val objects for rtx id[%d] must be 0. but %d was returned", id, i) }
|
||||
}
|
||||
|
||||
func Test1(t *testing.T) {
|
||||
@@ -300,9 +143,7 @@ return 1.9923;
|
||||
|
||||
// when rtx objects are all closed, the counter must drop to 0
|
||||
i = h.RtxCount()
|
||||
if i != 0 {
|
||||
t.Errorf("the number of rtx objects must be 0. but %d was returned", i)
|
||||
}
|
||||
if i != 0 { t.Errorf("the number of rtx objects must be 0. but %d was returned", i) }
|
||||
|
||||
h.Close()
|
||||
|
||||
@@ -491,146 +332,3 @@ return x
|
||||
time.Sleep(1000 * time.Millisecond) // give finalizer time to print
|
||||
}
|
||||
|
||||
func Test4(t *testing.T) {
|
||||
var h *hawk.Hawk
|
||||
var rtx *hawk.Rtx
|
||||
var v *hawk.Val
|
||||
var gm *hawk.Val
|
||||
var ga *hawk.Val
|
||||
var err error
|
||||
var round int
|
||||
|
||||
debug.SetGCPercent(100)
|
||||
|
||||
h, err = hawk.New()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to make hawk - %s", err.Error())
|
||||
}
|
||||
|
||||
h.AddFunc("echoint", 1, 1, "", echoint)
|
||||
|
||||
err = h.ParseText(`function ret_zero() { return 0; }
|
||||
function ret_one() { return 1; }
|
||||
function ret_neg() { return -1; }
|
||||
function call_echo_zero() { return echoint(0); }
|
||||
function call_echo_neg() { return echoint(-1); }
|
||||
function make_int_map() {
|
||||
@local x;
|
||||
x["zero"] = 0;
|
||||
x["one"] = 1;
|
||||
x["neg"] = -1;
|
||||
return x;
|
||||
}
|
||||
function make_int_arr() {
|
||||
@local x;
|
||||
x = hawk::array(0, 1, -1);
|
||||
return x;
|
||||
}`)
|
||||
if err != nil {
|
||||
h.Close()
|
||||
t.Fatalf("Failed to parse hawk script - %s", err.Error())
|
||||
}
|
||||
|
||||
rtx, err = h.NewRtx("test4", nil, nil)
|
||||
if err != nil {
|
||||
h.Close()
|
||||
t.Fatalf("failed to create rtx - %s", err.Error())
|
||||
}
|
||||
|
||||
for round = 0; round < 32; round++ {
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
want int
|
||||
}{
|
||||
{"ret_zero", 0},
|
||||
{"ret_one", 1},
|
||||
{"ret_neg", -1},
|
||||
{"call_echo_zero", 0},
|
||||
{"call_echo_neg", -1},
|
||||
} {
|
||||
force_gc()
|
||||
v, err = rtx.Call(tc.name)
|
||||
if err != nil {
|
||||
rtx.Close()
|
||||
h.Close()
|
||||
t.Fatalf("failed to call %s - %s", tc.name, err.Error())
|
||||
}
|
||||
force_gc()
|
||||
expect_int_val(t, v, tc.want, tc.name)
|
||||
}
|
||||
}
|
||||
|
||||
v, err = rtx.Call("make_int_map")
|
||||
if err != nil {
|
||||
rtx.Close()
|
||||
h.Close()
|
||||
t.Fatalf("failed to call make_int_map - %s", err.Error())
|
||||
}
|
||||
expect_map_ints(t, v, map[string]int{
|
||||
"zero": 0,
|
||||
"one": 1,
|
||||
"neg": -1,
|
||||
})
|
||||
|
||||
v, err = rtx.Call("make_int_arr")
|
||||
if err != nil {
|
||||
rtx.Close()
|
||||
h.Close()
|
||||
t.Fatalf("failed to call make_int_arr - %s", err.Error())
|
||||
}
|
||||
expect_array_ints(t, v, map[int]int{
|
||||
1: 0,
|
||||
2: 1,
|
||||
3: -1,
|
||||
})
|
||||
|
||||
gm = hawk.Must(rtx.NewMapVal())
|
||||
if err = gm.SetMapFieldWithInt("zero", 0); err != nil {
|
||||
rtx.Close()
|
||||
h.Close()
|
||||
t.Fatalf("failed to set zero map field - %s", err.Error())
|
||||
}
|
||||
if err = gm.SetMapFieldWithInt("one", 1); err != nil {
|
||||
rtx.Close()
|
||||
h.Close()
|
||||
t.Fatalf("failed to set one map field - %s", err.Error())
|
||||
}
|
||||
if err = gm.SetMapFieldWithInt("neg", -1); err != nil {
|
||||
rtx.Close()
|
||||
h.Close()
|
||||
t.Fatalf("failed to set neg map field - %s", err.Error())
|
||||
}
|
||||
expect_map_ints(t, gm, map[string]int{
|
||||
"zero": 0,
|
||||
"one": 1,
|
||||
"neg": -1,
|
||||
})
|
||||
|
||||
ga = hawk.Must(rtx.NewArrVal(0))
|
||||
if err = ga.SetArrayFieldWithInt(1, 0); err != nil {
|
||||
rtx.Close()
|
||||
h.Close()
|
||||
t.Fatalf("failed to set array field 1 - %s", err.Error())
|
||||
}
|
||||
if err = ga.SetArrayFieldWithInt(2, 1); err != nil {
|
||||
rtx.Close()
|
||||
h.Close()
|
||||
t.Fatalf("failed to set array field 2 - %s", err.Error())
|
||||
}
|
||||
if err = ga.SetArrayFieldWithInt(3, -1); err != nil {
|
||||
rtx.Close()
|
||||
h.Close()
|
||||
t.Fatalf("failed to set array field 3 - %s", err.Error())
|
||||
}
|
||||
expect_array_ints(t, ga, map[int]int{
|
||||
1: 0,
|
||||
2: 1,
|
||||
3: -1,
|
||||
})
|
||||
|
||||
rtx.Close()
|
||||
h.Close()
|
||||
|
||||
force_gc()
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
|
||||
@@ -69,6 +69,20 @@ typedef struct hawk_tree_t hawk_tree_t;
|
||||
#define HAWK_ENABLE_ATOMIC_SIG
|
||||
#endif
|
||||
|
||||
/* this part is kept for preservation of experiment only.
|
||||
#if defined(HAVE_UCONTEXT_H)
|
||||
#include <ucontext.h>
|
||||
#define HAWK_ENABLE_UCONTEXT
|
||||
#endif
|
||||
*/
|
||||
|
||||
/* Use iterative (heap-stack) expression evaluation instead of C recursion.
|
||||
* eval_expression, eval_expression0, and hawk_rtx_evalcall automatically
|
||||
* route through the xstack variants when this is defined. Comment out to
|
||||
* revert to the purely recursive implementation. */
|
||||
/*#define HAWK_ENABLE_XSTACK_EVAL*/
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
/* private headers. some files are affected by feature macros above */
|
||||
@@ -448,6 +462,49 @@ struct hawk_exec_stack_t
|
||||
|
||||
typedef struct hawk_exec_stack_t hawk_exec_stack_t;
|
||||
|
||||
/* expression frame states for eval_expression0_xstack */
|
||||
enum hawk_ef_state_t
|
||||
{
|
||||
HAWK_EF_EVAL = 0, /* dispatch on nde->type */
|
||||
HAWK_EF_BIN_LEFT, /* binary: awaiting left result */
|
||||
HAWK_EF_BIN_RIGHT, /* binary: left done (val=left refupped), awaiting right */
|
||||
HAWK_EF_UNARY, /* unary: awaiting operand result */
|
||||
HAWK_EF_CND, /* conditional: awaiting test result */
|
||||
HAWK_EF_ASS_RHS, /* assignment: awaiting RHS result */
|
||||
HAWK_EF_ASS_LHS, /* compound assign: RHS in val (refupped), awaiting LHS */
|
||||
HAWK_EF_LAND_LEFT, /* logical AND: awaiting left result */
|
||||
HAWK_EF_LAND_RIGHT, /* logical AND: left done and true (val=left), awaiting right */
|
||||
HAWK_EF_LOR_LEFT, /* logical OR: awaiting left result */
|
||||
HAWK_EF_LOR_RIGHT, /* logical OR: left done and false (val=left), awaiting right */
|
||||
#if defined(HAWK_ENABLE_XSTACK_EVAL)
|
||||
HAWK_EF_FNCALL_FUN_AWAIT /* user fn body executing on exec_stack; aux=exec_body_base */
|
||||
#endif
|
||||
};
|
||||
typedef enum hawk_ef_state_t hawk_ef_state_t;
|
||||
|
||||
struct hawk_eframe_t
|
||||
{
|
||||
hawk_ef_state_t state;
|
||||
hawk_nde_t* nde; /* composite node being processed */
|
||||
hawk_val_t* val; /* intermediate value (refcount incremented) */
|
||||
hawk_oow_t aux; /* FNCALL_FUN_AWAIT: exec_stack size when body frames were pushed */
|
||||
};
|
||||
typedef struct hawk_eframe_t hawk_eframe_t;
|
||||
|
||||
#if defined(HAWK_ENABLE_XSTACK_EVAL)
|
||||
/* call frame: saves context for a user-defined function call made from within
|
||||
* expression evaluation. stored in the call_stack. */
|
||||
struct hawk_call_frame_t
|
||||
{
|
||||
hawk_nde_fncall_t* call; /* call-site node */
|
||||
hawk_fun_t* fun; /* resolved function */
|
||||
hawk_oow_t saved_stack_top; /* rtx->stack_top before the call */
|
||||
hawk_oow_t saved_stack_base;/* rtx->stack_base before the call */
|
||||
hawk_oow_t nargs; /* actual argument count pushed */
|
||||
};
|
||||
typedef struct hawk_call_frame_t hawk_call_frame_t;
|
||||
#endif
|
||||
|
||||
struct hawk_rtx_t
|
||||
{
|
||||
HAWK_RTX_HDR;
|
||||
@@ -467,6 +524,36 @@ struct hawk_rtx_t
|
||||
hawk_oow_t exec_stack_size;
|
||||
hawk_oow_t exec_stack_limit;
|
||||
|
||||
/* heap-based stack for iterative expression evaluation (xstack variant) */
|
||||
hawk_eframe_t* eframe_stack;
|
||||
hawk_oow_t eframe_stack_size;
|
||||
hawk_oow_t eframe_stack_limit;
|
||||
|
||||
#if defined(HAWK_ENABLE_XSTACK_EVAL)
|
||||
/* heap-based call frame stack: user-defined function calls from eframe evaluation */
|
||||
hawk_call_frame_t* call_stack;
|
||||
hawk_oow_t call_stack_size;
|
||||
hawk_oow_t call_stack_limit;
|
||||
/* result register: eframe eval result delivered to exec AFTER_EVAL frames */
|
||||
hawk_val_t* driver_eval_result;
|
||||
#endif
|
||||
|
||||
#if defined(HAWK_ENABLE_UCONTEXT)
|
||||
/* pool of reusable C stacks for coroutine-based function calls */
|
||||
struct
|
||||
{
|
||||
char* pool[16];
|
||||
hawk_oow_t pool_size;
|
||||
/* arguments for the next coroutine invocation */
|
||||
hawk_nde_blk_t* pending_body;
|
||||
int* pending_result;
|
||||
/* depth at which the current C stack segment started */
|
||||
hawk_oow_t stack_base;
|
||||
/* nonzero when executing on a heap-allocated coroutine stack */
|
||||
int in_coroutine;
|
||||
} co;
|
||||
#endif
|
||||
|
||||
int exit_level;
|
||||
int init_called;
|
||||
|
||||
|
||||
+4
-14
@@ -1922,12 +1922,14 @@ static HAWK_INLINE void hawk_geterruinf (hawk_t* hawk, hawk_erruinf_t* errinf) {
|
||||
* it automatically formatted.
|
||||
*/
|
||||
#if defined(HAWK_HAVE_INLINE)
|
||||
static HAWK_INLINE void hawk_clrerror (hawk_t* hawk) { hawk_gem_seterrnum(hawk_getgem(hawk), HAWK_NULL, HAWK_ENOERR); }
|
||||
static HAWK_INLINE void hawk_seterrnum (hawk_t* hawk, const hawk_loc_t* errloc, hawk_errnum_t errnum) { hawk_gem_seterrnum(hawk_getgem(hawk), errloc, errnum); }
|
||||
static HAWK_INLINE void hawk_seterrinf (hawk_t* hawk, const hawk_errinf_t* errinf) { hawk_gem_seterrinf(hawk_getgem(hawk), errinf); }
|
||||
static HAWK_INLINE void hawk_seterror (hawk_t* hawk, const hawk_loc_t* errloc, hawk_errnum_t errnum, const hawk_oocs_t* errarg) { hawk_gem_seterror(hawk_getgem(hawk), errloc, errnum, errarg); }
|
||||
static HAWK_INLINE const hawk_ooch_t* hawk_backuperrmsg (hawk_t* hawk) { return hawk_gem_backuperrmsg(hawk_getgem(hawk)); }
|
||||
static HAWK_INLINE void hawk_geterror (hawk_t* hawk, hawk_errnum_t* errnum, const hawk_ooch_t** errmsg, hawk_loc_t* errloc) { return hawk_gem_geterror(hawk_getgem(hawk), errnum, errmsg, errloc); }
|
||||
#else
|
||||
#define hawk_clrerror(hawk) hawk_gem_seterrnum(hawk_getgem(hawk), HAWK_NULL, HAWK_ENOERR)
|
||||
#define hawk_seterrnum(hawk, errloc, errnum) hawk_gem_seterrnum(hawk_getgem(hawk), errloc, errnum)
|
||||
#define hawk_seterrinf(hawk, errinf) hawk_gem_seterrinf(hawk_getgem(hawk), errinf)
|
||||
#define hawk_seterror(hawk, errloc, errnum, errarg) hawk_gem_seterror(hawk_getgem(hawk), errloc, errnum, errarg)
|
||||
@@ -3119,11 +3121,13 @@ static HAWK_INLINE void hawk_rtx_geterror (hawk_rtx_t* rtx, hawk_errnum_t* errnu
|
||||
* The hawk_rtx_seterrinf() function sets error information.
|
||||
*/
|
||||
#if defined(HAWK_HAVE_INLINE)
|
||||
static HAWK_INLINE void hawk_rtx_clrerror (hawk_rtx_t* rtx) { hawk_gem_seterrnum(hawk_rtx_getgem(rtx), HAWK_NULL, HAWK_ENOERR); }
|
||||
static HAWK_INLINE void hawk_rtx_seterrnum (hawk_rtx_t* rtx, const hawk_loc_t* errloc, hawk_errnum_t errnum) { hawk_gem_seterrnum (hawk_rtx_getgem(rtx), errloc, errnum); }
|
||||
static HAWK_INLINE void hawk_rtx_seterrinf (hawk_rtx_t* rtx, const hawk_errinf_t* errinf) { hawk_gem_seterrinf (hawk_rtx_getgem(rtx), errinf); }
|
||||
static HAWK_INLINE void hawk_rtx_seterror (hawk_rtx_t* rtx, const hawk_loc_t* errloc, hawk_errnum_t errnum, const hawk_oocs_t* errarg) { hawk_gem_seterror(hawk_rtx_getgem(rtx), errloc, errnum, errarg); }
|
||||
static HAWK_INLINE const hawk_ooch_t* hawk_rtx_backuperrmsg (hawk_rtx_t* rtx) { return hawk_gem_backuperrmsg(hawk_rtx_getgem(rtx)); }
|
||||
#else
|
||||
#define hawk_rtx_clrerror(rtx) hawk_gem_seterrnum(hawk_rtx_getgem(rtx), HAWK_NULL, HAWK_ENOERR)
|
||||
#define hawk_rtx_seterrnum(rtx, errloc, errnum) hawk_gem_seterrnum(hawk_rtx_getgem(rtx), errloc, errnum)
|
||||
#define hawk_rtx_seterrinf(rtx, errinf) hawk_gem_seterrinf(hawk_rtx_getgem(rtx), errinf)
|
||||
#define hawk_rtx_seterror(rtx, errloc, errnum, errarg) hawk_gem_seterror(hawk_rtx_getgem(rtx), errloc, errnum, errarg)
|
||||
@@ -3653,20 +3657,6 @@ HAWK_EXPORT int hawk_rtx_isstaticval (
|
||||
const hawk_val_t* val /**< value to check */
|
||||
);
|
||||
|
||||
/**
|
||||
* The hawk_rtx_isimmval() function determines if a value is a immediate value
|
||||
* encoded using pointer tagging.
|
||||
*/
|
||||
HAWK_EXPORT int hawk_rtx_isimmval (
|
||||
hawk_rtx_t* rtx, /**< runtime context */
|
||||
const hawk_val_t* val /**< value to check */
|
||||
);
|
||||
|
||||
HAWK_EXPORT int hawk_rtx_isimmorstaticval (
|
||||
hawk_rtx_t* rtx, /**< runtime context */
|
||||
const hawk_val_t* val /**< value to check */
|
||||
);
|
||||
|
||||
HAWK_EXPORT int hawk_rtx_getvaltype (
|
||||
hawk_rtx_t* rtx,
|
||||
const hawk_val_t* val
|
||||
|
||||
+9
-4
@@ -22,6 +22,15 @@
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <hawk-cfg.h>
|
||||
#if defined(HAVE_ACCEPT4)
|
||||
/* the runtime library has accept4. but accept4 is usually visiable
|
||||
* if _GNU_SOURCE is defined */
|
||||
# if !defined(_GNU_SOURCE)
|
||||
# define _GNU_SOURCE
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include "mod-sys.h"
|
||||
#include "hawk-prv.h"
|
||||
#include <hawk-pio.h>
|
||||
@@ -42,10 +51,6 @@
|
||||
#elif defined(__DOS__)
|
||||
# include <dos.h>
|
||||
#else
|
||||
# if !defined(_GNU_SOURCE)
|
||||
# define _GNU_SOURCE
|
||||
# endif
|
||||
|
||||
# include "syscall.h"
|
||||
# include <sys/utsname.h>
|
||||
# if defined(HAVE_SYS_EPOLL_H)
|
||||
|
||||
@@ -601,17 +601,9 @@ static hawk_pio_pid_t standard_fork_and_exec (hawk_pio_t* pio, int pipes[], para
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(__DOS__)
|
||||
/* not needed on DOS: hawk_pio_init() bails out with HAWK_ENOIMPL there before
|
||||
* any pipe is ever created, so there is no call site for this. */
|
||||
static int set_pipe_nonblock (hawk_pio_t* pio, hawk_pio_hnd_t fd, int enabled)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
/* anonymous pipes created by CreatePipe() cannot be switched to
|
||||
* non-blocking mode. */
|
||||
hawk_gem_seterrnum(pio->gem, HAWK_NULL, HAWK_ENOIMPL);
|
||||
return -1;
|
||||
#elif defined(O_NONBLOCK)
|
||||
#if defined(O_NONBLOCK)
|
||||
int flag = HAWK_FCNTL(fd, F_GETFL, 0);
|
||||
if (flag >= 0) flag = HAWK_FCNTL(fd, F_SETFL, (enabled? (flag | O_NONBLOCK): (flag & ~O_NONBLOCK)));
|
||||
if (flag <= -1) hawk_gem_seterrnum(pio->gem, HAWK_NULL, hawk_syserr_to_errnum(errno));
|
||||
@@ -621,7 +613,6 @@ static int set_pipe_nonblock (hawk_pio_t* pio, hawk_pio_hnd_t fd, int enabled)
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int hawk_pio_init (hawk_pio_t* pio, hawk_gem_t* gem, const hawk_ooch_t* cmd, int flags, hawk_pio_env_mk_t env_mk, void* env_ctx)
|
||||
@@ -734,12 +725,6 @@ int hawk_pio_init (hawk_pio_t* pio, hawk_gem_t* gem, const hawk_ooch_t* cmd, int
|
||||
}
|
||||
}
|
||||
|
||||
/* handle[1] is the parent's end and is never inherited by the child,
|
||||
* so switching it here - before the child exists - is equivalent to
|
||||
* doing it afterwards, and keeps this failure out of the window in
|
||||
* which a spawned child would have to be cleaned up. */
|
||||
if ((flags & HAWK_PIO_INNOBLOCK) && set_pipe_nonblock(pio, handle[1], 1) <= -1) goto oops;
|
||||
|
||||
minidx = 0; maxidx = 1;
|
||||
}
|
||||
|
||||
@@ -765,8 +750,6 @@ int hawk_pio_init (hawk_pio_t* pio, hawk_gem_t* gem, const hawk_ooch_t* cmd, int
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags & HAWK_PIO_OUTNOBLOCK) && set_pipe_nonblock(pio, handle[2], 1) <= -1) goto oops;
|
||||
|
||||
if (minidx == -1) minidx = 2;
|
||||
maxidx = 3;
|
||||
}
|
||||
@@ -793,8 +776,6 @@ int hawk_pio_init (hawk_pio_t* pio, hawk_gem_t* gem, const hawk_ooch_t* cmd, int
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags & HAWK_PIO_ERRNOBLOCK) && set_pipe_nonblock(pio, handle[4], 1) <= -1) goto oops;
|
||||
|
||||
if (minidx == -1) minidx = 4;
|
||||
maxidx = 5;
|
||||
}
|
||||
@@ -832,7 +813,7 @@ int hawk_pio_init (hawk_pio_t* pio, hawk_gem_t* gem, const hawk_ooch_t* cmd, int
|
||||
|
||||
startup.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
|
||||
startup.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
startup.hStdError = GetStdHandle(STD_ERROR_HANDLE);
|
||||
startup.hStdOutput = GetStdHandle(STD_ERROR_HANDLE);
|
||||
if (startup.hStdInput == INVALID_HANDLE_VALUE ||
|
||||
startup.hStdOutput == INVALID_HANDLE_VALUE ||
|
||||
startup.hStdError == INVALID_HANDLE_VALUE)
|
||||
@@ -1032,12 +1013,6 @@ create_process:
|
||||
DosQueryFHState (handle[1], &state);
|
||||
DosSetFHState (handle[1], state | OPEN_FLAGS_NOINHERIT); */
|
||||
|
||||
/* handle[1] is the parent's end and is marked NOINHERIT above, so
|
||||
* switching it before the child exists is equivalent to doing it
|
||||
* afterwards, and keeps this failure out of the window in which a
|
||||
* spawned child would have to be cleaned up. */
|
||||
if ((flags & HAWK_PIO_INNOBLOCK) && set_pipe_nonblock(pio, handle[1], 1) <= -1) goto oops;
|
||||
|
||||
minidx = 0; maxidx = 1;
|
||||
}
|
||||
|
||||
@@ -1060,8 +1035,6 @@ create_process:
|
||||
goto oops;
|
||||
}
|
||||
|
||||
if ((flags & HAWK_PIO_OUTNOBLOCK) && set_pipe_nonblock(pio, handle[2], 1) <= -1) goto oops;
|
||||
|
||||
if (minidx == -1) minidx = 2;
|
||||
maxidx = 3;
|
||||
}
|
||||
@@ -1085,8 +1058,6 @@ create_process:
|
||||
goto oops;
|
||||
}
|
||||
|
||||
if ((flags & HAWK_PIO_ERRNOBLOCK) && set_pipe_nonblock(pio, handle[4], 1) <= -1) goto oops;
|
||||
|
||||
if (minidx == -1) minidx = 4;
|
||||
maxidx = 5;
|
||||
}
|
||||
@@ -1332,15 +1303,6 @@ create_process:
|
||||
hawk_gem_seterrnum(pio->gem, HAWK_NULL, hawk_syserr_to_errnum(errno));
|
||||
goto oops;
|
||||
}
|
||||
|
||||
/* O_NONBLOCK belongs to the open file description, and handle[1] is
|
||||
* the parent's end - a different description from the handle[0] the
|
||||
* child inherits, and one the child closes anyway. so switching it
|
||||
* here, before the child exists, is equivalent to doing it after the
|
||||
* spawn, and keeps this failure out of the window in which a spawned
|
||||
* child would have to be cleaned up. */
|
||||
if ((flags & HAWK_PIO_INNOBLOCK) && set_pipe_nonblock(pio, handle[1], 1) <= -1) goto oops;
|
||||
|
||||
minidx = 0; maxidx = 1;
|
||||
}
|
||||
|
||||
@@ -1351,9 +1313,6 @@ create_process:
|
||||
hawk_gem_seterrnum(pio->gem, HAWK_NULL, hawk_syserr_to_errnum(errno));
|
||||
goto oops;
|
||||
}
|
||||
|
||||
if ((flags & HAWK_PIO_OUTNOBLOCK) && set_pipe_nonblock(pio, handle[2], 1) <= -1) goto oops;
|
||||
|
||||
if (minidx == -1) minidx = 2;
|
||||
maxidx = 3;
|
||||
}
|
||||
@@ -1365,9 +1324,6 @@ create_process:
|
||||
hawk_gem_seterrnum(pio->gem, HAWK_NULL, hawk_syserr_to_errnum(errno));
|
||||
goto oops;
|
||||
}
|
||||
|
||||
if ((flags & HAWK_PIO_ERRNOBLOCK) && set_pipe_nonblock(pio, handle[4], 1) <= -1) goto oops;
|
||||
|
||||
if (minidx == -1) minidx = 4;
|
||||
maxidx = 5;
|
||||
}
|
||||
@@ -1805,6 +1761,13 @@ create_process:
|
||||
}
|
||||
#endif
|
||||
|
||||
if (((flags & HAWK_PIO_INNOBLOCK) && set_pipe_nonblock(pio, handle[1], 1) <= -1) ||
|
||||
((flags & HAWK_PIO_OUTNOBLOCK) && set_pipe_nonblock(pio, handle[2], 1) <= -1) ||
|
||||
((flags & HAWK_PIO_ERRNOBLOCK) && set_pipe_nonblock(pio, handle[4], 1) <= -1))
|
||||
{
|
||||
goto oops;
|
||||
}
|
||||
|
||||
/* store back references */
|
||||
pio->pin[HAWK_PIO_IN].self = pio;
|
||||
pio->pin[HAWK_PIO_OUT].self = pio;
|
||||
@@ -1815,6 +1778,7 @@ create_process:
|
||||
pio->pin[HAWK_PIO_OUT].handle = handle[2];
|
||||
pio->pin[HAWK_PIO_ERR].handle = handle[4];
|
||||
|
||||
|
||||
if (flags & HAWK_PIO_TEXT)
|
||||
{
|
||||
int topt = 0;
|
||||
@@ -1827,9 +1791,6 @@ create_process:
|
||||
{
|
||||
int r;
|
||||
|
||||
/* NOTE: the child process has already been spawned.
|
||||
* jumping to oops for failure below will trigger forced kill of
|
||||
* a child process at the beginning of the oops part */
|
||||
tio[i] = hawk_tio_open(pio->gem, HAWK_SIZEOF(&pio->pin[i]), topt);
|
||||
if (HAWK_UNLIKELY(!tio[i])) goto oops;
|
||||
|
||||
@@ -1847,26 +1808,6 @@ create_process:
|
||||
return 0;
|
||||
|
||||
oops:
|
||||
/* if the child has already been spawned, a failure in a later step must
|
||||
* not leave it behind: the caller is about to get -1 and will never have
|
||||
* a handle to reap it with. */
|
||||
if (pio->child != HAWK_PIO_PID_NIL)
|
||||
{
|
||||
hawk_errnum_t err = hawk_gem_geterrnum(pio->gem);
|
||||
|
||||
/* SIGKILL, not a bare wait: the child may be long-running, or blocked
|
||||
* writing to a pipe we still hold - either would hang us here. */
|
||||
hawk_pio_kill(pio);
|
||||
|
||||
/* the caller's WAITNOBLOCK/WAITNORETRY must not stop us reaping */
|
||||
pio->flags &= ~HAWK_PIO_WAITNOBLOCK;
|
||||
pio->flags &= ~HAWK_PIO_WAITNORETRY;
|
||||
hawk_pio_wait(pio); /* reaps and resets child to PID_NIL */
|
||||
|
||||
/* kill()/wait() set errnum themselves - restore the real cause */
|
||||
hawk_gem_seterrnum (pio->gem, HAWK_NULL, err);
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
if (windevnul != INVALID_HANDLE_VALUE) CloseHandle(windevnul);
|
||||
|
||||
@@ -1896,21 +1837,12 @@ oops:
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
if (minidx >= 0)
|
||||
{
|
||||
for (i = minidx; i <= maxidx; i++)
|
||||
{
|
||||
if (handle[i] != HAWK_PIO_HND_NIL) CloseHandle(handle[i]);
|
||||
}
|
||||
}
|
||||
for (i = minidx; i < maxidx; i++) CloseHandle(handle[i]);
|
||||
#elif defined(__OS2__)
|
||||
if (minidx >= 0)
|
||||
{
|
||||
for (i = minidx; i <= maxidx; i++)
|
||||
for (i = minidx; i < maxidx; i++)
|
||||
{
|
||||
if (handle[i] != HAWK_PIO_HND_NIL) DosClose(handle[i]);
|
||||
}
|
||||
}
|
||||
#elif defined(__DOS__)
|
||||
|
||||
/* DOS not multi-processed. can't support pio */
|
||||
@@ -1920,29 +1852,20 @@ oops:
|
||||
posix_spawn_file_actions_destroy (&fa);
|
||||
fa_inited = 0;
|
||||
}
|
||||
if (i >= 0)
|
||||
{
|
||||
for (i = minidx; i <= maxidx; i++)
|
||||
for (i = minidx; i < maxidx; i++)
|
||||
{
|
||||
if (handle[i] != HAWK_PIO_HND_NIL) HAWK_CLOSE(handle[i]);
|
||||
}
|
||||
}
|
||||
#elif defined(HAWK_SYSCALL0) && defined(SYS_vfork)
|
||||
if (i >= 0)
|
||||
{
|
||||
for (i = minidx; i <= maxidx; i++)
|
||||
for (i = minidx; i < maxidx; i++)
|
||||
{
|
||||
if (handle[i] != HAWK_PIO_HND_NIL) HAWK_CLOSE(handle[i]);
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (i >= 0)
|
||||
{
|
||||
for (i = minidx; i <= maxidx; i++)
|
||||
for (i = minidx; i < maxidx; i++)
|
||||
{
|
||||
if (handle[i] != HAWK_PIO_HND_NIL) HAWK_CLOSE(handle[i]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return -1;
|
||||
|
||||
@@ -30,6 +30,7 @@ enum hawk_assop_type_t
|
||||
/* if you change this, you have to change assop_str in tree.c.
|
||||
* synchronize it wit:
|
||||
* - binop_func in eval_assignment of run.c
|
||||
* - binop_func in eval_expression0_xstack in run.c
|
||||
* - assop in assing_to_opcode of parse.c
|
||||
* - TOK_XXX_ASSN in tok_t in parse.c
|
||||
* - assop_str in tree.c
|
||||
@@ -149,6 +150,18 @@ hawk_val_t* hawk_rtx_evalcall (
|
||||
void* eharg
|
||||
);
|
||||
|
||||
#if 0
|
||||
hawk_val_t* hawk_rtx_evalcall_xstack (
|
||||
hawk_rtx_t* rtx,
|
||||
hawk_nde_fncall_t* call,
|
||||
hawk_fun_t* fun,
|
||||
hawk_oow_t(*argpusher)(hawk_rtx_t*,const hawk_loc_t* loc,void*),
|
||||
void* apdata,
|
||||
void(*errhandler)(void*),
|
||||
void* eharg
|
||||
);
|
||||
#endif
|
||||
|
||||
int hawk_rtx_setsighandler (
|
||||
hawk_rtx_t* rtx,
|
||||
int sig,
|
||||
|
||||
@@ -215,6 +215,18 @@ void hawk_rtx_freevalchunk (
|
||||
);
|
||||
|
||||
#if defined(HAWK_HAVE_INLINE)
|
||||
/* the nocheck versions are defined in case you already know the value
|
||||
* is a pointer and not a static value */
|
||||
static HAWK_INLINE_ALWAYS void hawk_rtx_refupval_nocheck_inline (hawk_rtx_t* rtx, hawk_val_t* val)
|
||||
{
|
||||
#if defined(HAWK_USE_ATOMIC_REFCNT) && defined(HAWK_ATOMIC_FETCH_ADD)
|
||||
HAWK_ATOMIC_FETCH_ADD(&val->v_refs, 1, HAWK_ATOMIC_RELAXED);
|
||||
#else
|
||||
val->v_refs++;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* regular refup with pointer check */
|
||||
static HAWK_INLINE_ALWAYS void hawk_rtx_refupval_inline (hawk_rtx_t* rtx, hawk_val_t* val)
|
||||
{
|
||||
if (HAWK_VTR_IS_POINTER(val) && !HAWK_IS_STATICVAL(val))
|
||||
@@ -226,13 +238,22 @@ static HAWK_INLINE_ALWAYS void hawk_rtx_refupval_inline (hawk_rtx_t* rtx, hawk_v
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(HAWK_USE_ATOMIC_REFCNT) && defined(HAWK_ATOMIC_FETCH_ADD)
|
||||
|
||||
#define hawk_rtx_refupval_nocheck_inline(rtx, val) do { \
|
||||
HAWK_ATOMIC_FETCH_ADD(&(val)->v_refs, 1, HAWK_ATOMIC_RELAXED); \
|
||||
} while(0)
|
||||
|
||||
#define hawk_rtx_refupval_inline(rtx, val) do { \
|
||||
if (HAWK_VTR_IS_POINTER(val) && !HAWK_IS_STATICVAL(val)) { \
|
||||
HAWK_ATOMIC_FETCH_ADD(&(val)->v_refs, 1, HAWK_ATOMIC_RELAXED); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#else
|
||||
#define hawk_rtx_refupval_nocheck_inline(rtx, val) do { (val)->v_refs++; } while(0)
|
||||
|
||||
#define hawk_rtx_refupval_inline(rtx, val) do { \
|
||||
if (HAWK_VTR_IS_POINTER(val) && !HAWK_IS_STATICVAL(val)) (val)->v_refs++; \
|
||||
} while(0)
|
||||
|
||||
@@ -1572,21 +1572,11 @@ hawk_val_t* hawk_rtx_makebobval (hawk_rtx_t* rtx, const void* ptr, hawk_oow_t le
|
||||
return (hawk_val_t*)val;
|
||||
}
|
||||
|
||||
int hawk_rtx_isstaticval (hawk_rtx_t* rtx, const hawk_val_t* val)
|
||||
int HAWK_INLINE hawk_rtx_isstaticval (hawk_rtx_t* rtx, const hawk_val_t* val)
|
||||
{
|
||||
return HAWK_VTR_IS_POINTER(val) && HAWK_IS_STATICVAL(val);
|
||||
}
|
||||
|
||||
int hawk_rtx_isimmval (hawk_rtx_t* rtx, const hawk_val_t* val)
|
||||
{
|
||||
return !HAWK_VTR_IS_POINTER(val);
|
||||
}
|
||||
|
||||
int hawk_rtx_isimmorstaticval (hawk_rtx_t* rtx, const hawk_val_t* val)
|
||||
{
|
||||
return !HAWK_VTR_IS_POINTER(val) || HAWK_IS_STATICVAL(val);
|
||||
}
|
||||
|
||||
int hawk_rtx_getvaltype (hawk_rtx_t* rtx, const hawk_val_t* val)
|
||||
{
|
||||
return HAWK_RTX_GETVALTYPE(rtx, val);
|
||||
|
||||
Reference in New Issue
Block a user