-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathmodule.go
104 lines (84 loc) · 2.37 KB
/
module.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/* module.go - Go wrapper for Emacs module API.
Copyright (C) 2016 Yann Hodique <yann.hodique@gmail.com>.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package emacs
/*
#include "include/wrapper.h"
*/
import "C"
import "unsafe"
var initFuncs = make([]func(Environment), 0)
// InitFunction is the type for functions to be called at module initialization
type InitFunction func(Environment)
// Register makes sure a function will be called at module initialization
func Register(init InitFunction) {
initFuncs = append(initFuncs, init)
}
//export emacsModuleInit
func emacsModuleInit(e *C.struct_emacs_runtime) C.int {
env := &emacsEnv{
env: C.GetEnvironment(e),
}
for _, f := range initFuncs {
f(env)
}
return 0
}
//export emacsCallFunction
func emacsCallFunction(
env *C.emacs_env, nargs C.ptrdiff_t,
args *C.emacs_value, idx C.ptrdiff_t) C.emacs_value {
e := &emacsEnv{
env: env,
}
n := int(nargs)
pargs := (*[1 << 30]C.emacs_value)(unsafe.Pointer(args))
arguments := make([]Value, n)
for i := 0; i < n; i++ {
arguments[i] = baseValue{
env: e,
val: pargs[i],
}
}
entry := funcReg.Lookup(int64(idx))
res, err := entry.f(
&emacsCallContext{
e,
arguments,
entry.data,
},
)
if err == nil {
if res == nil {
return e.intern("nil")
}
return res.getVal()
}
if isSignal(err) {
s := err.(signal)
C.NonLocalExitSignal(env, s.Symbol().getVal(), s.Value().getVal())
} else if isThrow(err) {
t := err.(throw)
C.NonLocalExitThrow(env, t.Symbol().getVal(), t.Value().getVal())
} else {
msg := err.Error()
C.NonLocalExitThrow(env, e.intern("error"), e.stringVal(msg))
}
return e.intern("nil")
}
//export emacsFinalizeFunction
func emacsFinalizeFunction(idx C.ptrdiff_t) {
index := int64(idx)
defer ptrReg.Unregister(index)
entry := ptrReg.Lookup(index)
entry.Finalize()
}