forked from elliotchance/c2go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
function_definition.go
152 lines (128 loc) · 4.61 KB
/
function_definition.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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
package main
import (
"regexp"
"strings"
)
// FunctionDefinition contains the prototype definition for a function.
type FunctionDefinition struct {
// The name of the function, like "printf".
Name string
// The C return type, like "int".
ReturnType string
// The C argument types, like ["bool", "int"]. There is currently no way
// to represent a varargs.
ArgumentTypes []string
// If this is not empty then this function name should be used instead
// of the Name. Many low level functions have an exact match with a Go
// function. For example, "sin()".
Substitution string
}
var functionDefinitions = map[string]FunctionDefinition{}
var builtInFunctionDefinitionsHaveBeenLoaded = false
// Each of the predefined function have a syntax that allows them to be easy to
// read (and maintain). For example:
//
// double __builtin_fabs(double) -> darwin.Fabs
//
// Declares the prototype of __builtin_fabs (a low level function implemented
// only on Mac) with a specific substitution provided. This means that it should
// replace any instance of __builtin_fabs with:
//
// github.com/elliotchance/c2go/darwin.Fabs
//
// THe substitution is optional.
var builtInFunctionDefinitions = []string{
// darwin/assert.h
"int __builtin_expect(int, int) -> darwin.BuiltinExpect",
"bool __assert_rtn(const char*, const char*, int, const char*) -> darwin.AssertRtn",
// darwin/ctype.h
"uint32 __istype(__darwin_ct_rune_t, uint32)",
"__darwin_ct_rune_t __isctype(__darwin_ct_rune_t, uint32)",
"__darwin_ct_rune_t __tolower(__darwin_ct_rune_t)",
"__darwin_ct_rune_t __toupper(__darwin_ct_rune_t)",
"uint32 __maskrune(__darwin_ct_rune_t, uint32)",
// darwin/math.h
"double __builtin_fabs(double) -> darwin.Fabs",
"float __builtin_fabsf(float) -> darwin.Fabsf",
"double __builtin_fabsl(double) -> darwin.Fabsl",
"double __builtin_inf() -> darwin.Inf",
"float __builtin_inff() -> darwin.Inff",
"double __builtin_infl() -> darwin.Infl",
"Double2 __sincospi_stret(double) -> darwin.SincospiStret",
"Float2 __sincospif_stret(float) -> darwin.SincospifStret",
"Double2 __sincos_stret(double) -> darwin.SincosStret",
"Float2 __sincosf_stret(float) -> darwin.SincosfStret",
// linux/assert.h
"bool __assert_fail(const char*, const char*, unsigned int, const char*) -> linux.AssertFail",
// math.h
"double acos(double) -> math.Acos",
"double asin(double) -> math.Asin",
"double atan(double) -> math.Atan",
"double atan2(double) -> math.Atan2",
"double ceil(double) -> math.Ceil",
"double cos(double) -> math.Cos",
"double cosh(double) -> math.Cosh",
"double exp(double) -> math.Exp",
"double fabs(double) -> math.Abs",
"double floor(double) -> math.Floor",
"double fmod(double) -> math.Mod",
"double ldexp(double) -> math.Ldexp",
"double log(double) -> math.Log",
"double log10(double) -> math.Log10",
"double pow(double) -> math.Pow",
"double sin(double) -> math.Sin",
"double sinh(double) -> math.Sinh",
"double sqrt(double) -> math.Sqrt",
"double tan(double) -> math.Tan",
"double tanh(double) -> math.Tanh",
// stdio.h
"int printf() -> fmt.Printf",
"int scanf() -> fmt.Scanf",
}
// getFunctionDefinition will return nil if the function does not exist (is not
// registered).
func getFunctionDefinition(functionName string) FunctionDefinition {
loadFunctionDefinitions()
//fmt.Printf("%#v", functionDefinitions)
return functionDefinitions[functionName]
}
// addFunctionDefinition registers a function definition. If the definition
// already exists it will be replaced.
func addFunctionDefinition(f FunctionDefinition) {
loadFunctionDefinitions()
functionDefinitions[f.Name] = f
}
func loadFunctionDefinitions() {
if builtInFunctionDefinitionsHaveBeenLoaded {
return
}
builtInFunctionDefinitionsHaveBeenLoaded = true
for _, f := range builtInFunctionDefinitions {
match := regexp.MustCompile(`^(.+) (.+)\((.*)\)( -> .*)?$`).
FindStringSubmatch(f)
// Unpack argument types.
argumentTypes := strings.Split(match[3], ",")
for i := range argumentTypes {
argumentTypes[i] = strings.TrimSpace(argumentTypes[i])
}
if len(argumentTypes) == 1 && argumentTypes[0] == "" {
argumentTypes = []string{}
}
// Substitution rules.
substitution := match[4]
if substitution != "" {
substitution = strings.TrimLeft(substitution, " ->")
}
if strings.HasPrefix(substitution, "darwin.") ||
strings.HasPrefix(substitution, "linux.") ||
strings.HasPrefix(substitution, "noarch.") {
substitution = "github.com/elliotchance/c2go/" + substitution
}
addFunctionDefinition(FunctionDefinition{
Name: match[2],
ReturnType: match[1],
ArgumentTypes: argumentTypes,
Substitution: substitution,
})
}
}