changed the free list implementation in hawk-inst.go
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
added go wrapper functions to manipulate return value and arguments
This commit is contained in:
76
hawk-inst.go
76
hawk-inst.go
@@ -4,65 +4,75 @@ package hawk
|
||||
#include <hawk.h>
|
||||
*/
|
||||
import "C"
|
||||
import "fmt"
|
||||
import "sync"
|
||||
import "weak"
|
||||
|
||||
type Instance struct {
|
||||
c *C.hawk_t // c object
|
||||
g weak.Pointer[Hawk] // go object
|
||||
type CPtr interface {
|
||||
//~*C.hawk_t | ~*C.hawk_rtx_t
|
||||
*C.hawk_t | *C.hawk_rtx_t
|
||||
}
|
||||
|
||||
type InstanceTable struct {
|
||||
type Instance[CT CPtr, GT interface{}] struct {
|
||||
c CT // c object
|
||||
g weak.Pointer[GT] // go object
|
||||
next_free int
|
||||
}
|
||||
|
||||
type InstanceTable[CT CPtr, GT interface{}] struct {
|
||||
name string
|
||||
mtx sync.Mutex
|
||||
insts []Instance
|
||||
free_slots []int
|
||||
next int
|
||||
insts []Instance[CT, GT]
|
||||
next_free int
|
||||
}
|
||||
|
||||
var inst_table InstanceTable
|
||||
type HawkInstance = Instance[*C.hawk_t, Hawk]
|
||||
type HawkInstanceTable = InstanceTable[*C.hawk_t, Hawk]
|
||||
|
||||
func (itab *InstanceTable) add_instance(c *C.hawk_t, g *Hawk) int {
|
||||
var n int
|
||||
type RtxInstance = Instance[*C.hawk_rtx_t, Rtx]
|
||||
type RtxInstanceTable = InstanceTable[*C.hawk_rtx_t, Rtx]
|
||||
|
||||
var inst_table HawkInstanceTable = HawkInstanceTable{ name: "hawk", next_free: -1 }
|
||||
var rtx_inst_table RtxInstanceTable = RtxInstanceTable{ name: "rtx", next_free: -1 }
|
||||
|
||||
func (itab *InstanceTable[CT, GT]) add_instance(c CT, g *GT) int {
|
||||
itab.mtx.Lock()
|
||||
defer itab.mtx.Unlock()
|
||||
|
||||
n = len(itab.free_slots)
|
||||
if n <= 0 { // no free slots
|
||||
itab.insts = append(itab.insts, Instance{c: c, g: weak.Make(g)})
|
||||
return len(itab.insts) - 1
|
||||
} else {
|
||||
if itab.next_free >= 0 {
|
||||
var slot int
|
||||
n--
|
||||
slot = itab.free_slots[n]
|
||||
itab.free_slots = itab.free_slots[:n]
|
||||
slot = itab.next_free
|
||||
if slot >= 0 { itab.next_free = itab.insts[slot].next_free }
|
||||
itab.insts[slot].c = c
|
||||
itab.insts[slot].g = weak.Make(g)
|
||||
itab.insts[slot].next_free = -1
|
||||
return slot
|
||||
} else { // no free slots
|
||||
itab.insts = append(itab.insts, Instance[CT, GT]{c: c, g: weak.Make(g), next_free: -1})
|
||||
return len(itab.insts) - 1
|
||||
}
|
||||
}
|
||||
|
||||
func (itab *InstanceTable) delete_instance(slot int) Instance {
|
||||
var h Instance
|
||||
var n int
|
||||
|
||||
func (itab *InstanceTable[CT, GT]) delete_instance(slot int) error {
|
||||
itab.mtx.Lock()
|
||||
defer itab.mtx.Unlock()
|
||||
|
||||
h = itab.insts[slot]
|
||||
itab.insts[slot].c = nil
|
||||
itab.insts[slot].g = weak.Make((*Hawk)(nil)) // this may not even be necessary as it's a weak pointer
|
||||
|
||||
n = len(itab.insts)
|
||||
if slot == n - 1 {
|
||||
itab.insts = itab.insts[:n - 1]
|
||||
} else {
|
||||
itab.free_slots = append(itab.free_slots, slot)
|
||||
if slot >= len(itab.insts) || slot < 0 {
|
||||
return fmt.Errorf("index %d out of range", slot)
|
||||
}
|
||||
if itab.insts[slot].next_free >= 0 {
|
||||
return fmt.Errorf("no instance at index %d", slot)
|
||||
}
|
||||
|
||||
return h
|
||||
itab.insts[slot].c = CT(nil)
|
||||
itab.insts[slot].g = weak.Make((*GT)(nil)) // this may not even be necessary as it's a weak pointer
|
||||
itab.insts[slot].next_free = itab.next_free
|
||||
itab.next_free = slot
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (itab *InstanceTable) slot_to_instance(slot int) Instance {
|
||||
func (itab *InstanceTable[CT, GT]) slot_to_instance(slot int) Instance[CT, GT] {
|
||||
itab.mtx.Lock()
|
||||
defer itab.mtx.Unlock()
|
||||
return itab.insts[slot]
|
||||
|
||||
224
hawk.go
224
hawk.go
@@ -3,6 +3,15 @@ package hawk
|
||||
/*
|
||||
#include <hawk.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
struct rtx_xtn_t
|
||||
{
|
||||
hawk_oow_t inst_no;
|
||||
hawk_oow_t rtx_inst_no;
|
||||
};
|
||||
|
||||
typedef struct rtx_xtn_t rtx_xtn_t;
|
||||
|
||||
static void init_parsestd_for_text_in(hawk_parsestd_t* in, hawk_bch_t* ptr, hawk_oow_t len)
|
||||
{
|
||||
@@ -36,6 +45,50 @@ static int val_to_flt(hawk_rtx_t* rtx, hawk_val_t* v, double* ret) {
|
||||
*ret = (double)fv;
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern int hawk_go_fnc_handler(rtx_xtn_t* rtx_xtn, hawk_bch_t* name, hawk_oow_t len);
|
||||
|
||||
static int hawk_fnc_handler_for_go(hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
|
||||
{
|
||||
int n;
|
||||
hawk_oow_t namelen;
|
||||
hawk_bch_t* name;
|
||||
rtx_xtn_t* xtn;
|
||||
|
||||
name = hawk_rtx_duputobchars(rtx, fi->name.ptr, fi->name.len, &namelen);
|
||||
if (!name)
|
||||
{
|
||||
// TODO: set error information
|
||||
return -1;
|
||||
}
|
||||
|
||||
xtn = hawk_rtx_getxtn(rtx);
|
||||
n = hawk_go_fnc_handler(xtn, name, namelen);
|
||||
hawk_rtx_freemem(rtx, name);
|
||||
return n;
|
||||
}
|
||||
|
||||
static hawk_fnc_t* add_fnc_with_bcstr(hawk_t* hawk, const hawk_bch_t* name, hawk_oow_t min_args, hawk_oow_t max_args, const hawk_bch_t* arg_spec)
|
||||
{
|
||||
hawk_fnc_bspec_t spec;
|
||||
memset(&spec, 0, HAWK_SIZEOF(spec));
|
||||
spec.arg.min = min_args;
|
||||
spec.arg.max = max_args;
|
||||
spec.arg.spec = arg_spec;
|
||||
spec.impl = hawk_fnc_handler_for_go;
|
||||
spec.trait = 0;
|
||||
return hawk_addfncwithbcstr(hawk, name, &spec);
|
||||
}
|
||||
|
||||
static void set_errmsg(hawk_t* hawk, hawk_errnum_t errnum, const hawk_bch_t* msg)
|
||||
{
|
||||
hawk_seterrbfmt(hawk, HAWK_NULL, errnum, "%hs", msg);
|
||||
}
|
||||
|
||||
static void set_rtx_errmsg(hawk_rtx_t* rtx, hawk_errnum_t errnum, const hawk_bch_t* msg)
|
||||
{
|
||||
hawk_rtx_seterrbfmt(rtx, HAWK_NULL, errnum, "%hs", msg);
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
@@ -45,19 +98,7 @@ import "runtime"
|
||||
import "sync"
|
||||
import "unsafe"
|
||||
|
||||
type Hawk struct {
|
||||
c *C.hawk_t
|
||||
inst_no int
|
||||
|
||||
rtx_mtx sync.Mutex
|
||||
rtx_count int
|
||||
rtx_head *Rtx
|
||||
rtx_tail *Rtx
|
||||
}
|
||||
|
||||
type Ext struct {
|
||||
inst_no int
|
||||
}
|
||||
type Fnc func(rtx *Rtx) error
|
||||
|
||||
type Err struct {
|
||||
Line uint
|
||||
@@ -66,8 +107,24 @@ type Err struct {
|
||||
Msg string
|
||||
}
|
||||
|
||||
type Hawk struct {
|
||||
c *C.hawk_t
|
||||
inst_no int
|
||||
fnctab map[string]Fnc
|
||||
|
||||
rtx_mtx sync.Mutex
|
||||
rtx_count int
|
||||
rtx_head *Rtx
|
||||
rtx_tail *Rtx
|
||||
}
|
||||
|
||||
type HawkExt struct {
|
||||
inst_no int
|
||||
}
|
||||
|
||||
type Rtx struct {
|
||||
c *C.hawk_rtx_t
|
||||
inst_no int
|
||||
h *Hawk
|
||||
|
||||
next *Rtx
|
||||
@@ -137,7 +194,7 @@ func deregister_instance(h *Hawk) {
|
||||
func New() (*Hawk, error) {
|
||||
var c *C.hawk_t
|
||||
var g *Hawk
|
||||
var ext *Ext
|
||||
var ext *HawkExt
|
||||
var errinf C.hawk_errinf_t
|
||||
|
||||
c = C.hawk_openstd(C.hawk_oow_t(unsafe.Sizeof(*ext)), &errinf)
|
||||
@@ -147,10 +204,11 @@ func New() (*Hawk, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ext = (*Ext)(unsafe.Pointer(C.hawk_getxtn(c)))
|
||||
ext = (*HawkExt)(unsafe.Pointer(C.hawk_getxtn(c)))
|
||||
|
||||
g = &Hawk{c: c, inst_no: -1}
|
||||
|
||||
g.fnctab = make(map[string]Fnc)
|
||||
g.rtx_count = 0
|
||||
g.rtx_head = nil
|
||||
g.rtx_tail = nil
|
||||
@@ -256,6 +314,46 @@ func (hawk *Hawk) AddGlobal(name string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
//export hawk_go_fnc_handler
|
||||
func hawk_go_fnc_handler(rtx_xtn *C.rtx_xtn_t, name *C.hawk_bch_t, namelen C.hawk_oow_t) C.int {
|
||||
var fn Fnc
|
||||
var inst HawkInstance
|
||||
var rtx_inst RtxInstance
|
||||
var rtx *Rtx
|
||||
var fnname string
|
||||
var ok bool
|
||||
var err error
|
||||
|
||||
inst = inst_table.slot_to_instance(int(rtx_xtn.inst_no))
|
||||
rtx_inst = rtx_inst_table.slot_to_instance(int(rtx_xtn.rtx_inst_no))
|
||||
rtx = rtx_inst.g.Value()
|
||||
|
||||
fnname = C.GoStringN(name, C.int(namelen))
|
||||
fn, ok = inst.g.Value().fnctab[fnname]
|
||||
if !ok {
|
||||
rtx.set_errmsg(C.HAWK_ENOENT, fmt.Sprintf("function '%s' not found", fnname))
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = fn(rtx_inst.g.Value())
|
||||
if err != nil {
|
||||
rtx.set_errmsg(C.HAWK_EOTHER, fmt.Sprintf("function '%s' failure - %s", fnname, err.Error()))
|
||||
return -1
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func (hawk *Hawk) AddFunc(name string, min_args uint, max_args uint, spec string, fn Fnc) error {
|
||||
var fnc *C.hawk_fnc_t
|
||||
|
||||
fnc = C.add_fnc_with_bcstr(hawk.c, C.CString(name), C.hawk_oow_t(min_args), C.hawk_oow_t(max_args), C.CString(spec));
|
||||
if fnc == nil { return hawk.make_errinfo() }
|
||||
|
||||
hawk.fnctab[name] = fn;
|
||||
return nil
|
||||
}
|
||||
|
||||
func (hawk *Hawk) ParseFile(text string) error {
|
||||
var x C.int
|
||||
var in [2]C.hawk_parsestd_t
|
||||
@@ -322,26 +420,7 @@ func (hawk *Hawk) unchain_rtx(rtx *Rtx) {
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------
|
||||
|
||||
func (hawk *Hawk) NewRtx(id string) (*Rtx, error) {
|
||||
var rtx *C.hawk_rtx_t
|
||||
var g *Rtx
|
||||
|
||||
rtx = C.hawk_rtx_openstdwithbcstr(hawk.c, 0, C.CString(id), nil, nil, nil)
|
||||
if rtx == nil { return nil, hawk.make_errinfo() }
|
||||
|
||||
g = &Rtx{c: rtx}
|
||||
hawk.chain_rtx(g)
|
||||
|
||||
// [NOTE]
|
||||
// if the owning hawk is not garbaged-collected, this rtx is never
|
||||
// garbaged collected as a strong pointer to a rtx object is maintained
|
||||
// in the owner. i never set the runtime finalizer on this rtx object.
|
||||
|
||||
return g, nil
|
||||
}
|
||||
|
||||
func (rtx* Rtx) Close() {
|
||||
func deregister_rtx_instance(rtx *Rtx) {
|
||||
if rtx.h != nil {
|
||||
//fmt.Printf("RTX CLOSING UNCHAIN %p\n", rtx)
|
||||
rtx.h.unchain_rtx(rtx)
|
||||
@@ -354,6 +433,41 @@ func (rtx* Rtx) Close() {
|
||||
C.hawk_rtx_close(rtx.c)
|
||||
//fmt.Printf("RTX CLOSING %p\n", rtx)
|
||||
}
|
||||
|
||||
if rtx.inst_no >= 0 {
|
||||
rtx_inst_table.delete_instance(rtx.inst_no)
|
||||
rtx.inst_no = -1
|
||||
}
|
||||
}
|
||||
|
||||
func (hawk *Hawk) NewRtx(id string) (*Rtx, error) {
|
||||
var rtx *C.hawk_rtx_t
|
||||
var g *Rtx
|
||||
var xtn *C.rtx_xtn_t
|
||||
|
||||
rtx = C.hawk_rtx_openstdwithbcstr(hawk.c, C.hawk_oow_t(unsafe.Sizeof(*xtn)), C.CString(id), nil, nil, nil)
|
||||
if rtx == nil { return nil, hawk.make_errinfo() }
|
||||
|
||||
g = &Rtx{c: rtx}
|
||||
hawk.chain_rtx(g)
|
||||
|
||||
// [NOTE]
|
||||
// if the owning hawk is not garbaged-collected, this rtx is never
|
||||
// garbaged collected as a strong pointer to a rtx object is maintained
|
||||
// in the owner.
|
||||
|
||||
runtime.SetFinalizer(g, deregister_rtx_instance)
|
||||
g.inst_no = rtx_inst_table.add_instance(rtx, g)
|
||||
|
||||
xtn = (*C.rtx_xtn_t)(unsafe.Pointer(C.hawk_rtx_getxtn(rtx)))
|
||||
xtn.inst_no = C.hawk_oow_t(hawk.inst_no)
|
||||
xtn.rtx_inst_no = C.hawk_oow_t(g.inst_no)
|
||||
|
||||
return g, nil
|
||||
}
|
||||
|
||||
func (rtx* Rtx) Close() {
|
||||
deregister_rtx_instance(rtx)
|
||||
}
|
||||
|
||||
func (rtx *Rtx) make_errinfo() *Err {
|
||||
@@ -446,6 +560,22 @@ func (rtx *Rtx) unchain_val(val *Val) {
|
||||
rtx.val_mtx.Unlock()
|
||||
}
|
||||
|
||||
func (rtx *Rtx) GetFuncArgCount() int {
|
||||
var nargs C.hawk_oow_t
|
||||
nargs = C.hawk_rtx_getnargs(rtx.c)
|
||||
return int(nargs)
|
||||
}
|
||||
|
||||
func (rtx *Rtx) GetFuncArg(idx int) (*Val, error) {
|
||||
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, v.c)
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------
|
||||
|
||||
func (hawk *Hawk) get_errmsg() string {
|
||||
@@ -456,13 +586,20 @@ func (hawk *Hawk) set_errmsg(num C.hawk_errnum_t, msg string) {
|
||||
var ptr *C.char
|
||||
ptr = C.CString(msg)
|
||||
defer C.free(unsafe.Pointer(ptr))
|
||||
C.hawk_seterrbmsg(hawk.c, nil, num, ptr)
|
||||
C.set_errmsg(hawk.c, num, ptr)
|
||||
}
|
||||
|
||||
func (rtx *Rtx) get_errmsg() string {
|
||||
return C.GoString(C.hawk_rtx_geterrbmsg(rtx.c))
|
||||
}
|
||||
|
||||
func (rtx *Rtx) set_errmsg(num C.hawk_errnum_t, msg string) {
|
||||
var ptr *C.char
|
||||
ptr = C.CString(msg)
|
||||
defer C.free(unsafe.Pointer(ptr))
|
||||
C.set_rtx_errmsg(rtx.c, num, ptr)
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------
|
||||
|
||||
func (err* Err) Error() string {
|
||||
@@ -807,14 +944,23 @@ func rune_slice_to_uchars(r []rune) []C.hawk_uch_t {
|
||||
}
|
||||
|
||||
func c_to_go(c *C.hawk_t) *Hawk {
|
||||
var ext *Ext
|
||||
var inst Instance
|
||||
var ext *HawkExt
|
||||
var inst HawkInstance
|
||||
|
||||
ext = (*Ext)(unsafe.Pointer(C.hawk_getxtn(c)))
|
||||
ext = (*HawkExt)(unsafe.Pointer(C.hawk_getxtn(c)))
|
||||
inst = inst_table.slot_to_instance(ext.inst_no)
|
||||
return inst.g.Value()
|
||||
}
|
||||
|
||||
func rtx_to_go(rtx *C.hawk_rtx_t) *Rtx {
|
||||
var xtn *C.rtx_xtn_t
|
||||
var inst RtxInstance
|
||||
|
||||
xtn = (*C.rtx_xtn_t)(unsafe.Pointer(C.hawk_rtx_getxtn(rtx)))
|
||||
inst = rtx_inst_table.slot_to_instance(int(xtn.rtx_inst_no))
|
||||
return inst.g.Value()
|
||||
}
|
||||
|
||||
func Must[T any](v T, err error) T {
|
||||
if err != nil { panic(err) }
|
||||
return v
|
||||
|
||||
83
hawk_test.go
83
hawk_test.go
@@ -30,6 +30,45 @@ func make_hawk(script string) (*hawk.Hawk, error) {
|
||||
return h, nil
|
||||
}
|
||||
|
||||
func enbase64(rtx *hawk.Rtx) error {
|
||||
fmt.Printf ("*** ENABLE64 RTX %p\n", rtx) // << this is 0 from time to time.. TODO: fix it..
|
||||
fmt.Printf("****ENBASE64 [%d]\n", rtx.GetFuncArgCount())
|
||||
|
||||
var a0 *hawk.Val = hawk.Must(rtx.GetFuncArg(0))
|
||||
var a1 *hawk.Val = hawk.Must(rtx.GetFuncArg(1))
|
||||
var a2 *hawk.Val = hawk.Must(rtx.GetFuncArg(2))
|
||||
|
||||
fmt.Printf("[%s] [%s] [%s]\n", a0.String(), a1.String(), a2.String())
|
||||
rtx.SetFuncRet(hawk.Must(rtx.NewValFromStr("ENBASE64-OUTPUT")))
|
||||
return nil
|
||||
}
|
||||
|
||||
func debase64(rtx *hawk.Rtx) error {
|
||||
fmt.Printf("****DEBASE64 [%d]\n", rtx.GetFuncArgCount())
|
||||
rtx.SetFuncRet(hawk.Must(rtx.NewValFromFlt(-999.1111)))
|
||||
return nil
|
||||
//return fmt.Errorf("what the hell.....")
|
||||
}
|
||||
|
||||
func make_hawk_extended(script string) (*hawk.Hawk, error) {
|
||||
var h *hawk.Hawk
|
||||
var err error
|
||||
|
||||
h, err = hawk.New()
|
||||
if err != nil { return nil, err }
|
||||
|
||||
h.AddFunc("enbase64", 1, 10, "", enbase64)
|
||||
h.AddFunc("debase64", 1, 1, "", debase64)
|
||||
|
||||
err = h.ParseText(script)
|
||||
if err != nil {
|
||||
h.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return h, nil
|
||||
}
|
||||
|
||||
func run_hawk(h *hawk.Hawk, id int, t *testing.T, wg *sync.WaitGroup) {
|
||||
var rtx *hawk.Rtx
|
||||
var v *hawk.Val
|
||||
@@ -109,7 +148,7 @@ return 1.9923;
|
||||
h.Close()
|
||||
|
||||
h = nil
|
||||
fmt.Printf ("== END of run ==\n")
|
||||
fmt.Printf ("== END of Test1 ==\n")
|
||||
runtime.GC()
|
||||
runtime.Gosched()
|
||||
time.Sleep(1000 * time.Millisecond) // give finalizer time to print
|
||||
@@ -239,6 +278,7 @@ return x;
|
||||
fmt.Printf("index=[%d] value=[%v]\n", i, ff.String())
|
||||
i, ff = v.ArrayNextField(&itr)
|
||||
}
|
||||
fmt.Printf("== END OF ARRAY DUMP ==\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -251,3 +291,44 @@ return x;
|
||||
time.Sleep(1000 * time.Millisecond) // give finalizer time to print
|
||||
}
|
||||
|
||||
func Test3(t *testing.T) {
|
||||
var h *hawk.Hawk
|
||||
var rtx *hawk.Rtx
|
||||
var err error
|
||||
|
||||
debug.SetGCPercent(100) // enable normal GC
|
||||
|
||||
fmt.Printf ("BEGINNING OF TEST3\n")
|
||||
|
||||
h, err = make_hawk_extended(`function main(s) {
|
||||
print enbase64(s, "hello", 1.289);
|
||||
print debase64(s);
|
||||
return x
|
||||
}`)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to make hawk - %s", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
rtx, err = h.NewRtx("test3")
|
||||
if err != nil {
|
||||
t.Errorf("failed to create rtx - %s", err.Error())
|
||||
} else {
|
||||
var v *hawk.Val
|
||||
|
||||
v, err = rtx.Call("main", hawk.Must(rtx.NewValFromStr("this is a test3 string")))
|
||||
if err != nil {
|
||||
t.Errorf("failed to call main - %s", err.Error())
|
||||
} else {
|
||||
fmt.Printf("V=>[%v]\n", v.String())
|
||||
}
|
||||
}
|
||||
|
||||
h.Close()
|
||||
fmt.Printf ("END OF TEST3\n")
|
||||
|
||||
runtime.GC()
|
||||
runtime.Gosched()
|
||||
time.Sleep(1000 * time.Millisecond) // give finalizer time to print
|
||||
}
|
||||
|
||||
|
||||
@@ -2550,7 +2550,7 @@ int Hawk::addFunction (
|
||||
{
|
||||
HAWK_ASSERT(this->hawk != HAWK_NULL);
|
||||
|
||||
hawk_fnc_mspec_t spec;
|
||||
hawk_fnc_bspec_t spec;
|
||||
|
||||
HAWK_MEMSET (&spec, 0, HAWK_SIZEOF(spec));
|
||||
spec.arg.min = minArgs;
|
||||
@@ -2601,7 +2601,7 @@ int Hawk::addFunction (
|
||||
{
|
||||
HAWK_ASSERT(this->hawk != HAWK_NULL);
|
||||
|
||||
hawk_fnc_wspec_t spec;
|
||||
hawk_fnc_uspec_t spec;
|
||||
|
||||
HAWK_MEMSET (&spec, 0, HAWK_SIZEOF(spec));
|
||||
spec.arg.min = minArgs;
|
||||
|
||||
32
lib/fnc.c
32
lib/fnc.c
@@ -146,66 +146,66 @@ static hawk_fnc_t* add_fnc (hawk_t* hawk, const hawk_ooch_t* name, const hawk_fn
|
||||
return fnc;
|
||||
}
|
||||
|
||||
hawk_fnc_t* hawk_addfncwithbcstr (hawk_t* hawk, const hawk_bch_t* name, const hawk_fnc_mspec_t* spec)
|
||||
hawk_fnc_t* hawk_addfncwithbcstr (hawk_t* hawk, const hawk_bch_t* name, const hawk_fnc_bspec_t* spec)
|
||||
{
|
||||
#if defined(HAWK_OOCH_IS_BCH)
|
||||
return add_fnc(hawk, name, spec);
|
||||
#else
|
||||
hawk_ucs_t wcs;
|
||||
hawk_fnc_t* fnc;
|
||||
hawk_fnc_spec_t wspec;
|
||||
hawk_fnc_spec_t uspec;
|
||||
|
||||
HAWK_STATIC_ASSERT (HAWK_SIZEOF(*spec) == HAWK_SIZEOF(wspec));
|
||||
HAWK_STATIC_ASSERT (HAWK_SIZEOF(*spec) == HAWK_SIZEOF(uspec));
|
||||
|
||||
HAWK_MEMCPY (&wspec, spec, HAWK_SIZEOF(wspec));
|
||||
HAWK_MEMCPY (&uspec, spec, HAWK_SIZEOF(uspec));
|
||||
if (spec->arg.spec)
|
||||
{
|
||||
wcs.ptr = hawk_dupbtoucstr(hawk, spec->arg.spec, &wcs.len, 0);
|
||||
if (HAWK_UNLIKELY(!wcs.ptr)) return HAWK_NULL;
|
||||
wspec.arg.spec = wcs.ptr;
|
||||
uspec.arg.spec = wcs.ptr;
|
||||
}
|
||||
|
||||
wcs.ptr = hawk_dupbtoucstr(hawk, name, &wcs.len, 0);
|
||||
if (HAWK_UNLIKELY(!wcs.ptr))
|
||||
{
|
||||
if (wspec.arg.spec) hawk_freemem(hawk, (hawk_uch_t*)wspec.arg.spec);
|
||||
if (uspec.arg.spec) hawk_freemem(hawk, (hawk_uch_t*)uspec.arg.spec);
|
||||
return HAWK_NULL;
|
||||
}
|
||||
|
||||
fnc = add_fnc(hawk, wcs.ptr, &wspec);
|
||||
fnc = add_fnc(hawk, wcs.ptr, &uspec);
|
||||
hawk_freemem(hawk, wcs.ptr);
|
||||
if (wspec.arg.spec) hawk_freemem(hawk, (hawk_uch_t*)wspec.arg.spec);
|
||||
if (uspec.arg.spec) hawk_freemem(hawk, (hawk_uch_t*)uspec.arg.spec);
|
||||
return fnc;
|
||||
#endif
|
||||
}
|
||||
|
||||
hawk_fnc_t* hawk_addfncwithucstr (hawk_t* hawk, const hawk_uch_t* name, const hawk_fnc_wspec_t* spec)
|
||||
hawk_fnc_t* hawk_addfncwithucstr (hawk_t* hawk, const hawk_uch_t* name, const hawk_fnc_uspec_t* spec)
|
||||
{
|
||||
#if defined(HAWK_OOCH_IS_BCH)
|
||||
hawk_bcs_t mbs;
|
||||
hawk_fnc_t* fnc;
|
||||
hawk_fnc_spec_t mspec;
|
||||
hawk_fnc_spec_t bspec;
|
||||
|
||||
HAWK_STATIC_ASSERT (HAWK_SIZEOF(*spec) == HAWK_SIZEOF(mspec));
|
||||
HAWK_STATIC_ASSERT (HAWK_SIZEOF(*spec) == HAWK_SIZEOF(bspec));
|
||||
|
||||
HAWK_MEMCPY (&mspec, spec, HAWK_SIZEOF(mspec));
|
||||
HAWK_MEMCPY (&bspec, spec, HAWK_SIZEOF(bspec));
|
||||
if (spec->arg.spec)
|
||||
{
|
||||
mbs.ptr = hawk_duputobcstr(hawk, spec->arg.spec, &mbs.len);
|
||||
if (HAWK_UNLIKELY(!mbs.ptr)) return HAWK_NULL;
|
||||
mspec.arg.spec = mbs.ptr;
|
||||
bspec.arg.spec = mbs.ptr;
|
||||
}
|
||||
|
||||
mbs.ptr = hawk_duputobcstr(hawk, name, &mbs.len);
|
||||
if (HAWK_UNLIKELY(!mbs.ptr))
|
||||
{
|
||||
if (mspec.arg.spec) hawk_freemem(hawk, (hawk_bch_t*)mspec.arg.spec);
|
||||
if (bspec.arg.spec) hawk_freemem(hawk, (hawk_bch_t*)bspec.arg.spec);
|
||||
return HAWK_NULL;
|
||||
}
|
||||
|
||||
fnc = add_fnc(hawk, mbs.ptr, &mspec);
|
||||
fnc = add_fnc(hawk, mbs.ptr, &bspec);
|
||||
hawk_freemem(hawk, mbs.ptr);
|
||||
if (mspec.arg.spec) hawk_freemem(hawk, (hawk_bch_t*)mspec.arg.spec);
|
||||
if (bspec.arg.spec) hawk_freemem(hawk, (hawk_bch_t*)bspec.arg.spec);
|
||||
return fnc;
|
||||
#else
|
||||
return add_fnc(hawk, name, spec);
|
||||
|
||||
42
lib/hawk.h
42
lib/hawk.h
@@ -916,10 +916,10 @@ typedef int (*hawk_fnc_impl_t) (
|
||||
);
|
||||
|
||||
/**
|
||||
* The hawk_fnc_marg_t type defines a structure to describe arguments
|
||||
* The hawk_fnc_barg_t type defines a structure to describe arguments
|
||||
* to an implicit function.
|
||||
*/
|
||||
struct hawk_fnc_marg_t
|
||||
struct hawk_fnc_barg_t
|
||||
{
|
||||
/** minimum numbers of argument for a function */
|
||||
hawk_oow_t min;
|
||||
@@ -939,28 +939,28 @@ struct hawk_fnc_marg_t
|
||||
*/
|
||||
const hawk_bch_t* spec;
|
||||
};
|
||||
typedef struct hawk_fnc_marg_t hawk_fnc_marg_t;
|
||||
typedef struct hawk_fnc_barg_t hawk_fnc_barg_t;
|
||||
|
||||
/**
|
||||
* The hawk_fnc_warg_t type defines a structure to describe arguments
|
||||
* The hawk_fnc_uarg_t type defines a structure to describe arguments
|
||||
* to an implicit function.
|
||||
*/
|
||||
struct hawk_fnc_warg_t
|
||||
struct hawk_fnc_uarg_t
|
||||
{
|
||||
hawk_oow_t min;
|
||||
hawk_oow_t max;
|
||||
const hawk_uch_t* spec;
|
||||
};
|
||||
typedef struct hawk_fnc_warg_t hawk_fnc_warg_t;
|
||||
typedef struct hawk_fnc_uarg_t hawk_fnc_uarg_t;
|
||||
|
||||
/**
|
||||
* The hawk_fnc_mspec_t type defines a structure to hold the specification
|
||||
* The hawk_fnc_bspec_t type defines a structure to hold the specification
|
||||
* of an intrinsic function or a module function.
|
||||
*/
|
||||
struct hawk_fnc_mspec_t
|
||||
struct hawk_fnc_bspec_t
|
||||
{
|
||||
/** argument descriptor */
|
||||
hawk_fnc_marg_t arg;
|
||||
hawk_fnc_barg_t arg;
|
||||
|
||||
/** pointer to the function implementing this function */
|
||||
hawk_fnc_impl_t impl;
|
||||
@@ -975,16 +975,16 @@ struct hawk_fnc_mspec_t
|
||||
*/
|
||||
int trait;
|
||||
};
|
||||
typedef struct hawk_fnc_mspec_t hawk_fnc_mspec_t;
|
||||
typedef struct hawk_fnc_bspec_t hawk_fnc_bspec_t;
|
||||
|
||||
/**
|
||||
* The hawk_fnc_wspec_t type defines a structure to hold the specification
|
||||
* The hawk_fnc_uspec_t type defines a structure to hold the specification
|
||||
* of an intrinsic function or a module function.
|
||||
*/
|
||||
struct hawk_fnc_wspec_t
|
||||
struct hawk_fnc_uspec_t
|
||||
{
|
||||
/** argument descriptor */
|
||||
hawk_fnc_warg_t arg;
|
||||
hawk_fnc_uarg_t arg;
|
||||
|
||||
/** pointer to the function implementing this function */
|
||||
hawk_fnc_impl_t impl;
|
||||
@@ -999,14 +999,14 @@ struct hawk_fnc_wspec_t
|
||||
*/
|
||||
int trait;
|
||||
};
|
||||
typedef struct hawk_fnc_wspec_t hawk_fnc_wspec_t;
|
||||
typedef struct hawk_fnc_uspec_t hawk_fnc_uspec_t;
|
||||
|
||||
#if defined(HAWK_OOCH_IS_BCH)
|
||||
typedef hawk_fnc_marg_t hawk_fnc_arg_t;
|
||||
typedef hawk_fnc_mspec_t hawk_fnc_spec_t;
|
||||
typedef hawk_fnc_barg_t hawk_fnc_arg_t;
|
||||
typedef hawk_fnc_bspec_t hawk_fnc_spec_t;
|
||||
#else
|
||||
typedef hawk_fnc_warg_t hawk_fnc_arg_t;
|
||||
typedef hawk_fnc_wspec_t hawk_fnc_spec_t;
|
||||
typedef hawk_fnc_uarg_t hawk_fnc_arg_t;
|
||||
typedef hawk_fnc_uspec_t hawk_fnc_spec_t;
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
@@ -2002,7 +2002,7 @@ HAWK_EXPORT int hawk_findgblwithucstr (
|
||||
HAWK_EXPORT hawk_fnc_t* hawk_addfncwithbcstr (
|
||||
hawk_t* hawk,
|
||||
const hawk_bch_t* name,
|
||||
const hawk_fnc_mspec_t* spec
|
||||
const hawk_fnc_bspec_t* spec
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -2011,7 +2011,7 @@ HAWK_EXPORT hawk_fnc_t* hawk_addfncwithbcstr (
|
||||
HAWK_EXPORT hawk_fnc_t* hawk_addfncwithucstr (
|
||||
hawk_t* hawk,
|
||||
const hawk_uch_t* name,
|
||||
const hawk_fnc_wspec_t* spec
|
||||
const hawk_fnc_uspec_t* spec
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -2737,7 +2737,7 @@ HAWK_EXPORT hawk_oow_t hawk_rtx_getnargs (
|
||||
*/
|
||||
HAWK_EXPORT hawk_val_t* hawk_rtx_getarg (
|
||||
hawk_rtx_t* rtx,
|
||||
hawk_oow_t idx
|
||||
hawk_oow_t idx
|
||||
);
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user