-
Notifications
You must be signed in to change notification settings - Fork 4
/
wrappers.pl
144 lines (125 loc) · 3.71 KB
/
wrappers.pl
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
# We build a colelction of cpp function factories here that'll help reduce
# boilerplate and pointer mistakes when wrapping libgit2 functions.
@valargs = ( [0,1], [0,2], [0,3] );
@ptrargs = ( [1,0], [1,1], [1,2] );
# @valargs = ( "v","vv","vvv" );
# @ptrargs = ( "p", "pv","pvv","pvvv" );
# Escape all lines in a #define after removing // comments
sub slashn {
my ($_) = @_; chomp;
s/\/\/[^\n]*\n/\n/g;
s/\n/ \\\n/g;
return $_ .= "\n\n";
}
sub alt_set_wrap_args {
return unless @_;
$argdsc = $_[0];
$paramc = length $argdsc;
die "CAMLparam$paramc does not exist!" if ($paramc > 5);
sub argdsc_map(%) { my %f = @_; map { $_ = 1+pos; &{$f{$1}}; } ($argdsc =~ /([pv])/); }
$params = join(",", argdsc_map( p => sub{"p$_"}, v => sub{"v$_"} ));
$defargs = join(",", argdsc_map( p => sub {"TYPE$_"}, v => sub {"CONVERSION$_"} ));
$funargs = join(",", argdsc_map( p => sub {"value p$_"}, v => sub {"value v$_"} ));
$lines = join(",\n", argdsc_map(
p => { "\t\t*(TYPE$_ **)Data_custom_val(p$_)" },
v => { "\t\tCONVERSION$_(v$_)" }
));
} # eww, global variables! ;)
sub set_wrap_args {
return unless @_;
($ptr_cnt,$val_cnt) = @_;
$argdsc = ($ptr_cnt ? "_ptr$ptr_cnt" : "") . ($val_cnt ? "_val$val_cnt" : "");
$defargs = join( ",",
(map { "TYPE$_"; } (1..$ptr_cnt)),
(map { "CONVERSION$_"; } (1..$val_cnt)) );
$funargs = join( ",",
(map { "value p$_"; } (1..$ptr_cnt)),
(map { "value v$_"; } (1..$val_cnt)) );
$params = join( ",", (map { "p$_"; } (1..$ptr_cnt)), (map { "v$_"; } (1..$val_cnt)) );
$paramc = $ptr_cnt + $val_cnt;
die "CAMLparam$paramc does not exist!" if ($paramc > 5);
$lines = join( ",\n",
(map { "\t\t*(TYPE$_ **)Data_custom_val(p$_)" } (1..$ptr_cnt)),
(map { "\t\tCONVERSION$_(v$_)" } (1..$val_cnt)) );
} # eww, global variables! ;)
sub wrap_retunit {
set_wrap_args(@_);
print slashn( <<__EoC__ );
#define wrap_retunit$argdsc(FUNCTION,$defargs)
CAMLprim value ocaml_##FUNCTION($funargs) {
CAMLparam$paramc($params);
FUNCTION(
$lines
);
CAMLreturn(Val_unit);
}
__EoC__
}
wrap_retunit(1,0);
wrap_retunit(1,1);
sub wrap_retunit_exn {
set_wrap_args(@_);
print slashn( <<__EoC__ );
#define wrap_retunit_exn$argdsc(FUNCTION,ERROR,EXN,$defargs)
CAMLprim value ocaml_##FUNCTION($funargs) {
CAMLparam$paramc($params);
pass_git_exceptions(
FUNCTION(
$lines
), ERROR, EXN );
CAMLreturn(Val_unit);
}
__EoC__
}
map { wrap_retunit_exn(@$_); } @ptrargs;
wrap_retunit_exn(2,0);
sub wrap_retval {
set_wrap_args(@_);
print slashn( <<__EoC__ );
#define wrap_retval$argdsc(FUNCTION,RETURN_CONVERSION,$defargs)
CAMLprim value ocaml_##FUNCTION($funargs) {
CAMLparam$paramc($params);
CAMLreturn( RETURN_CONVERSION( FUNCTION(
$lines
) ) );
}
__EoC__
}
map { wrap_retval(@$_); } (@valargs, @ptrargs);
sub wrap_retptr {
set_wrap_args(@_);
print slashn( <<__EoC__ );
#define wrap_retptr$argdsc(FUNCTION,NEWTYPE,ERROR,$defargs)
CAMLprim value ocaml_##FUNCTION($funargs) {
CAMLparam$paramc($params);
CAMLlocal1(r);
r = caml_alloc_git_ptr(NEWTYPE);
*(NEWTYPE **)Data_custom_val(r) =
FUNCTION(
$lines
);
if( *(NEWTYPE **)Data_custom_val(r) == NULL )
caml_invalid_argument( #ERROR " : " #FUNCTION " returned null." );
CAMLreturn(r);
}
__EoC__
}
# Afaik, all are invalid_argument.
map { wrap_retptr(@$_); } (@valargs, @ptrargs);
sub wrap_setptr {
set_wrap_args(@_);
print slashn( <<__EoC__ );
#define wrap_setptr$argdsc(FUNCTION,NEWTYPE,ERROR,EXN,$defargs)
CAMLprim value ocaml_##FUNCTION($funargs) {
CAMLparam$paramc($params);
CAMLlocal1(r);
r = caml_alloc_git_ptr(NEWTYPE);
pass_git_exceptions(
FUNCTION( (NEWTYPE **)Data_custom_val(r),
$lines
), ERROR, EXN );
CAMLreturn(r);
}
__EoC__
} # We support both invalid_argument and failwith
map { wrap_setptr(@$_); } (@valargs, [0,3], [0,4], @ptrargs, [1,3]);