4
4
extern crate bindgen;
5
5
extern crate env_logger;
6
6
#[ macro_use]
7
- extern crate docopt;
8
- #[ macro_use]
9
7
extern crate log;
10
8
extern crate clang_sys;
11
9
extern crate rustc_serialize;
12
10
13
11
use bindgen:: { Bindings , BindgenOptions , LinkType } ;
12
+ use std:: default:: Default ;
14
13
use std:: io;
15
14
use std:: path;
15
+ use std:: process;
16
16
use std:: env;
17
- use std:: default:: Default ;
18
17
use std:: fs;
19
18
20
19
const USAGE : & ' static str = "
23
22
[--link=<lib>...] \
24
23
[--static-link=<lib>...] \
25
24
[--framework-link=<framework>...] \
26
- [--match=<name>...] \
27
25
[--raw-line=<raw>...] \
28
- [--dtor-attr=<attr>...] \
29
26
[--opaque-type=<type>...] \
30
27
[--blacklist-type=<type>...] \
31
28
[--whitelist-type=<type>...] \
@@ -50,18 +47,15 @@ Options:
50
47
-o=<output-rust-file> Write bindings to <output-rust-file>
51
48
(defaults to stdout)
52
49
53
- --match=<name> Only output bindings for definitions from
54
- files whose name contains <name>. If multiple
55
- match options are provided, files matching any
56
- rule are bound to.
57
-
58
50
--builtins Output bindings for builtin definitions (for
59
51
example __builtin_va_list)
60
52
61
53
--ignore-functions Don't generate bindings for functions and
62
54
methods. This is useful when you only care
63
55
about struct layouts.
64
56
57
+ --ignore-methods Avoid generating all kind of methods.
58
+
65
59
--enable-cxx-namespaces Enable support for C++ namespaces.
66
60
67
61
--no-type-renaming Don't rename types.
@@ -74,25 +68,9 @@ Options:
74
68
--use-msvc-mangling Handle MSVC C++ ABI mangling; requires that
75
69
target be set to (i686|x86_64)-pc-win32
76
70
77
- --override-enum-type=<type> Override enum type, type name could be
78
- uchar
79
- schar
80
- ushort
81
- sshort
82
- uint
83
- sint
84
- ulong
85
- slong
86
- ulonglong
87
- slonglong
88
-
89
71
--raw-line=<raw> Add a raw line at the beginning of the output.
90
- --dtor-attr=<attr> Attributes to add to structures with destructor.
91
- --no-class-constants Avoid generating class constants.
92
72
--no-unstable-rust Avoid generating unstable rust.
93
- --no-namespaced-constants Avoid generating constants right under namespaces.
94
73
--no-bitfield-methods Avoid generating methods for bitfield access.
95
- --ignore-methods Avoid generating all kind of methods.
96
74
--opaque-type=<type> Mark a type as opaque.
97
75
--blacklist-type=<type> Mark a type as hidden.
98
76
--whitelist-type=<type> Whitelist the type. If this set or any other
@@ -110,91 +88,119 @@ Options:
110
88
directly through to clang.
111
89
" ;
112
90
113
- #[ derive( Debug , RustcDecodable ) ]
114
- struct Args {
115
- arg_input_header : String ,
116
- flag_link : Vec < String > ,
117
- flag_static_link : Vec < String > ,
118
- flag_framework_link : Vec < String > ,
119
- flag_o : Option < String > ,
120
- flag_match : Vec < String > ,
121
- flag_builtins : bool ,
122
- flag_ignore_functions : bool ,
123
- flag_enable_cxx_namespaces : bool ,
124
- flag_no_type_renaming : bool ,
125
- flag_allow_unknown_types : bool ,
126
- flag_emit_clang_ast : bool ,
127
- flag_use_msvc_mangling : bool ,
128
- flag_override_enum_type : String ,
129
- flag_raw_line : Vec < String > ,
130
- flag_dtor_attr : Vec < String > ,
131
- flag_no_class_constants : bool ,
132
- flag_no_unstable_rust : bool ,
133
- flag_no_namespaced_constants : bool ,
134
- flag_no_bitfield_methods : bool ,
135
- flag_ignore_methods : bool ,
136
- flag_opaque_type : Vec < String > ,
137
- flag_blacklist_type : Vec < String > ,
138
- flag_whitelist_type : Vec < String > ,
139
- flag_whitelist_function : Vec < String > ,
140
- flag_whitelist_var : Vec < String > ,
141
- arg_clang_args : Vec < String > ,
142
- }
143
-
144
- type ParseResult < T > = Result < T , String > ;
145
-
146
- impl Into < ParseResult < ( BindgenOptions , Box < io:: Write > ) > > for Args {
147
- fn into ( mut self ) -> Result < ( BindgenOptions , Box < io:: Write > ) , String > {
148
- let mut options: BindgenOptions = Default :: default ( ) ;
149
-
150
- for lib in self . flag_link . drain ( ..) {
151
- options. links . push ( ( lib, LinkType :: Default ) ) ;
152
- }
91
+ // FIXME(emilio): Replace this with docopt if/when they fix their exponential
92
+ // algorithm for argument parsing.
93
+ fn parse_args_or_exit ( args : Vec < String > ) -> ( BindgenOptions , Box < io:: Write > ) {
94
+ let mut options = BindgenOptions :: default ( ) ;
95
+ let mut dest_file = None ;
96
+ let mut source_file = None ;
97
+
98
+ let mut iter = args. into_iter ( ) . skip ( 1 ) ;
99
+ loop {
100
+ let next = match iter. next ( ) {
101
+ Some ( arg) => arg,
102
+ _ => break ,
103
+ } ;
153
104
154
- for lib in self . flag_static_link . drain ( ..) {
155
- options. links . push ( ( lib, LinkType :: Static ) ) ;
105
+ match & * next {
106
+ "-h" | "--help" => {
107
+ println ! ( "{}" , USAGE ) ;
108
+ process:: exit ( 0 ) ;
109
+ }
110
+ "-l" | "--link" => {
111
+ let lib = iter. next ( ) . expect ( "--link needs an argument" ) ;
112
+ options. links . push ( ( lib, LinkType :: Default ) ) ;
113
+ }
114
+ "--static-link" => {
115
+ let lib = iter. next ( ) . expect ( "--static-link needs an argument" ) ;
116
+ options. links . push ( ( lib, LinkType :: Static ) ) ;
117
+ }
118
+ "--framework-link" => {
119
+ let lib = iter. next ( ) . expect ( "--framework-link needs an argument" ) ;
120
+ options. links . push ( ( lib, LinkType :: Framework ) ) ;
121
+ }
122
+ "--raw-line" => {
123
+ let line = iter. next ( ) . expect ( "--raw-line needs an argument" ) ;
124
+ options. raw_lines . push ( line) ;
125
+ }
126
+ "--opaque-type" => {
127
+ let ty_canonical_name = iter. next ( ) . expect ( "--opaque-type expects a type" ) ;
128
+ options. opaque_types . insert ( ty_canonical_name) ;
129
+ }
130
+ "--blacklist-type" => {
131
+ let ty_canonical_name = iter. next ( ) . expect ( "--blacklist-type expects a type" ) ;
132
+ options. hidden_types . insert ( ty_canonical_name) ;
133
+ }
134
+ "--whitelist-type" => {
135
+ let ty_pat = iter. next ( ) . expect ( "--whitelist-type expects a type pattern" ) ;
136
+ options. whitelisted_types . insert ( & ty_pat) ;
137
+ }
138
+ "--whitelist-function" => {
139
+ let function_pat = iter. next ( ) . expect ( "--whitelist-function expects a pattern" ) ;
140
+ options. whitelisted_functions . insert ( & function_pat) ;
141
+ }
142
+ "--whitelist-var" => {
143
+ let var_pat = iter. next ( ) . expect ( "--whitelist-var expects a pattern" ) ;
144
+ options. whitelisted_vars . insert ( & var_pat) ;
145
+ }
146
+ "--" => {
147
+ while let Some ( clang_arg) = iter. next ( ) {
148
+ options. clang_args . push ( clang_arg) ;
149
+ }
150
+ }
151
+ "--output" | "-o" => {
152
+ let out_name = iter. next ( ) . expect ( "-o expects a file name" ) ;
153
+ dest_file = Some ( out_name) ;
154
+ }
155
+ "--builtins" => {
156
+ options. builtins = true ;
157
+ }
158
+ "--ignore-functions" => {
159
+ options. ignore_functions = true ;
160
+ }
161
+ "--no-bitfield-methods" => {
162
+ options. gen_bitfield_methods = false ;
163
+ }
164
+ "--ignore-methods" => {
165
+ options. ignore_methods = true ;
166
+ }
167
+ "--enable-cxx-namespaces" => {
168
+ options. enable_cxx_namespaces = true ;
169
+ }
170
+ "--no-type-renaming" => {
171
+ options. rename_types = false ;
172
+ }
173
+ "--no-unstable-rust" => {
174
+ options. unstable_rust = false ;
175
+ }
176
+ "--emit-clang-ast" => {
177
+ options. emit_ast = true ;
178
+ }
179
+ "--use-msvc-mangling" => {
180
+ options. msvc_mangling = true ;
181
+ }
182
+ other if source_file. is_none ( ) => {
183
+ source_file = Some ( other. into ( ) ) ;
184
+ }
185
+ other => {
186
+ panic ! ( "Unknown option: \" {}\" " , other) ;
187
+ }
156
188
}
189
+ }
157
190
158
- for lib in self . flag_framework_link . drain ( .. ) {
159
- options. links . push ( ( lib , LinkType :: Framework ) ) ;
160
- }
191
+ if let Some ( source_file ) = source_file . take ( ) {
192
+ options. clang_args . push ( source_file ) ;
193
+ }
161
194
162
- let out = if let Some ( ref path_name) = self . flag_o {
163
- let path = path:: Path :: new ( path_name) ;
164
- let file = try!( fs:: File :: create ( path) . map_err ( |_| {
165
- format ! ( "Opening {} failed" , path_name)
166
- } ) ) ;
167
- Box :: new ( io:: BufWriter :: new ( file) ) as Box < io:: Write >
168
- } else {
169
- Box :: new ( io:: BufWriter :: new ( io:: stdout ( ) ) ) as Box < io:: Write >
170
- } ;
195
+ let out = if let Some ( ref path_name) = dest_file {
196
+ let path = path:: Path :: new ( path_name) ;
197
+ let file = fs:: File :: create ( path) . expect ( "Opening out file failed" ) ;
198
+ Box :: new ( io:: BufWriter :: new ( file) ) as Box < io:: Write >
199
+ } else {
200
+ Box :: new ( io:: BufWriter :: new ( io:: stdout ( ) ) ) as Box < io:: Write >
201
+ } ;
171
202
172
- options. match_pat . extend ( self . flag_match . drain ( ..) ) ;
173
- options. builtins = self . flag_builtins ;
174
- options. ignore_functions = self . flag_ignore_functions ;
175
- options. enable_cxx_namespaces = self . flag_enable_cxx_namespaces ;
176
- options. rename_types = !self . flag_no_type_renaming ;
177
- options. fail_on_unknown_type = !self . flag_allow_unknown_types ;
178
- options. emit_ast = self . flag_emit_clang_ast ;
179
- options. msvc_mangling = self . flag_use_msvc_mangling ;
180
- options. override_enum_ty = self . flag_override_enum_type ;
181
- options. raw_lines . extend ( self . flag_raw_line . drain ( ..) ) ;
182
- options. dtor_attrs . extend ( self . flag_dtor_attr . drain ( ..) ) ;
183
- options. class_constants = !self . flag_no_class_constants ;
184
- options. unstable_rust = !self . flag_no_unstable_rust ;
185
- options. namespaced_constants = !self . flag_no_namespaced_constants ;
186
- options. gen_bitfield_methods = !self . flag_no_bitfield_methods ;
187
- options. ignore_methods = self . flag_ignore_methods ;
188
- options. opaque_types . extend ( self . flag_opaque_type . drain ( ..) ) ;
189
- options. hidden_types . extend ( self . flag_blacklist_type . drain ( ..) ) ;
190
- options. whitelisted_types . extend ( self . flag_whitelist_type . drain ( ..) ) ;
191
- options. whitelisted_functions . extend ( self . flag_whitelist_function . drain ( ..) ) ;
192
- options. whitelisted_vars . extend ( self . flag_whitelist_var . drain ( ..) ) ;
193
- options. clang_args . extend ( self . arg_clang_args . drain ( ..) ) ;
194
- options. clang_args . push ( self . arg_input_header ) ;
195
-
196
- Ok ( ( options, out) )
197
- }
203
+ ( options, out)
198
204
}
199
205
200
206
pub fn main ( ) {
@@ -227,17 +233,11 @@ pub fn main() {
227
233
}
228
234
}
229
235
230
- let args: Args = docopt:: Docopt :: new ( USAGE )
231
- . and_then ( |d| d. argv ( bind_args. iter ( ) ) . decode ( ) )
232
- . unwrap_or_else ( |e| e. exit ( ) ) ;
233
-
234
- let result: ParseResult < _ > = args. into ( ) ;
235
- let ( options, out) = result. unwrap_or_else ( |msg| {
236
- panic ! ( "Failed to generate_bindings: {:?}" , msg) ;
237
- } ) ;
236
+ let ( options, out) = parse_args_or_exit ( bind_args) ;
238
237
239
238
let bindings = Bindings :: generate ( options, None )
240
239
. expect ( "Unable to generate bindings" ) ;
240
+
241
241
bindings. write ( out)
242
242
. expect ( "Unable to write bindings to file." ) ;
243
243
}
0 commit comments