1 use bindgen::{
2 builder, AliasVariation, Builder, CodegenConfig, EnumVariation, RustTarget,
3 RUST_TARGET_STRINGS,
4 };
5 use clap::{App, Arg};
6 use std::fs::File;
7 use std::io::{self, stderr, Error, ErrorKind, Write};
8 use std::path::PathBuf;
9 use std::str::FromStr;
10
11 /// Construct a new [`Builder`](./struct.Builder.html) from command line flags.
builder_from_flags<I>( args: I, ) -> Result<(Builder, Box<dyn io::Write>, bool), io::Error> where I: Iterator<Item = String>,12 pub fn builder_from_flags<I>(
13 args: I,
14 ) -> Result<(Builder, Box<dyn io::Write>, bool), io::Error>
15 where
16 I: Iterator<Item = String>,
17 {
18 let rust_target_help = format!(
19 "Version of the Rust compiler to target. Valid options are: {:?}. Defaults to {:?}.",
20 RUST_TARGET_STRINGS,
21 String::from(RustTarget::default())
22 );
23
24 let matches = App::new("bindgen")
25 .version(option_env!("CARGO_PKG_VERSION").unwrap_or("unknown"))
26 .about("Generates Rust bindings from C/C++ headers.")
27 .usage("bindgen [FLAGS] [OPTIONS] <header> -- <clang-args>...")
28 .args(&[
29 Arg::with_name("header")
30 .help("C or C++ header file")
31 .required(true),
32 Arg::with_name("default-enum-style")
33 .long("default-enum-style")
34 .help("The default style of code used to generate enums.")
35 .value_name("variant")
36 .default_value("consts")
37 .possible_values(&[
38 "consts",
39 "moduleconsts",
40 "bitfield",
41 "newtype",
42 "rust",
43 "rust_non_exhaustive",
44 ])
45 .multiple(false),
46 Arg::with_name("bitfield-enum")
47 .long("bitfield-enum")
48 .help(
49 "Mark any enum whose name matches <regex> as a set of \
50 bitfield flags.",
51 )
52 .value_name("regex")
53 .takes_value(true)
54 .multiple(true)
55 .number_of_values(1),
56 Arg::with_name("newtype-enum")
57 .long("newtype-enum")
58 .help("Mark any enum whose name matches <regex> as a newtype.")
59 .value_name("regex")
60 .takes_value(true)
61 .multiple(true)
62 .number_of_values(1),
63 Arg::with_name("rustified-enum")
64 .long("rustified-enum")
65 .help("Mark any enum whose name matches <regex> as a Rust enum.")
66 .value_name("regex")
67 .takes_value(true)
68 .multiple(true)
69 .number_of_values(1),
70 Arg::with_name("constified-enum")
71 .long("constified-enum")
72 .help(
73 "Mark any enum whose name matches <regex> as a series of \
74 constants.",
75 )
76 .value_name("regex")
77 .takes_value(true)
78 .multiple(true)
79 .number_of_values(1),
80 Arg::with_name("constified-enum-module")
81 .long("constified-enum-module")
82 .help(
83 "Mark any enum whose name matches <regex> as a module of \
84 constants.",
85 )
86 .value_name("regex")
87 .takes_value(true)
88 .multiple(true)
89 .number_of_values(1),
90 Arg::with_name("default-alias-style")
91 .long("default-alias-style")
92 .help("The default style of code used to generate typedefs.")
93 .value_name("variant")
94 .default_value("type_alias")
95 .possible_values(&[
96 "type_alias",
97 "new_type",
98 "new_type_deref",
99 ])
100 .multiple(false),
101 Arg::with_name("normal-alias")
102 .long("normal-alias")
103 .help(
104 "Mark any typedef alias whose name matches <regex> to use \
105 normal type aliasing.",
106 )
107 .value_name("regex")
108 .takes_value(true)
109 .multiple(true)
110 .number_of_values(1),
111 Arg::with_name("new-type-alias")
112 .long("new-type-alias")
113 .help(
114 "Mark any typedef alias whose name matches <regex> to have \
115 a new type generated for it.",
116 )
117 .value_name("regex")
118 .takes_value(true)
119 .multiple(true)
120 .number_of_values(1),
121 Arg::with_name("new-type-alias-deref")
122 .long("new-type-alias-deref")
123 .help(
124 "Mark any typedef alias whose name matches <regex> to have \
125 a new type with Deref and DerefMut to the inner type.",
126 )
127 .value_name("regex")
128 .takes_value(true)
129 .multiple(true)
130 .number_of_values(1),
131 Arg::with_name("blacklist-type")
132 .long("blacklist-type")
133 .help("Mark <type> as hidden.")
134 .value_name("type")
135 .takes_value(true)
136 .multiple(true)
137 .number_of_values(1),
138 Arg::with_name("blacklist-function")
139 .long("blacklist-function")
140 .help("Mark <function> as hidden.")
141 .value_name("function")
142 .takes_value(true)
143 .multiple(true)
144 .number_of_values(1),
145 Arg::with_name("blacklist-item")
146 .long("blacklist-item")
147 .help("Mark <item> as hidden.")
148 .value_name("item")
149 .takes_value(true)
150 .multiple(true)
151 .number_of_values(1),
152 Arg::with_name("no-layout-tests")
153 .long("no-layout-tests")
154 .help("Avoid generating layout tests for any type."),
155 Arg::with_name("no-derive-copy")
156 .long("no-derive-copy")
157 .help("Avoid deriving Copy on any type."),
158 Arg::with_name("no-derive-debug")
159 .long("no-derive-debug")
160 .help("Avoid deriving Debug on any type."),
161 Arg::with_name("no-derive-default")
162 .long("no-derive-default")
163 .hidden(true)
164 .help("Avoid deriving Default on any type."),
165 Arg::with_name("impl-debug").long("impl-debug").help(
166 "Create Debug implementation, if it can not be derived \
167 automatically.",
168 ),
169 Arg::with_name("impl-partialeq")
170 .long("impl-partialeq")
171 .help(
172 "Create PartialEq implementation, if it can not be derived \
173 automatically.",
174 ),
175 Arg::with_name("with-derive-default")
176 .long("with-derive-default")
177 .help("Derive Default on any type."),
178 Arg::with_name("with-derive-hash")
179 .long("with-derive-hash")
180 .help("Derive hash on any type."),
181 Arg::with_name("with-derive-partialeq")
182 .long("with-derive-partialeq")
183 .help("Derive partialeq on any type."),
184 Arg::with_name("with-derive-partialord")
185 .long("with-derive-partialord")
186 .help("Derive partialord on any type."),
187 Arg::with_name("with-derive-eq")
188 .long("with-derive-eq")
189 .help(
190 "Derive eq on any type. Enable this option also \
191 enables --with-derive-partialeq",
192 ),
193 Arg::with_name("with-derive-ord")
194 .long("with-derive-ord")
195 .help(
196 "Derive ord on any type. Enable this option also \
197 enables --with-derive-partialord",
198 ),
199 Arg::with_name("no-doc-comments")
200 .long("no-doc-comments")
201 .help(
202 "Avoid including doc comments in the output, see: \
203 https://github.com/rust-lang/rust-bindgen/issues/426",
204 ),
205 Arg::with_name("no-recursive-whitelist")
206 .long("no-recursive-whitelist")
207 .help(
208 "Disable whitelisting types recursively. This will cause \
209 bindgen to emit Rust code that won't compile! See the \
210 `bindgen::Builder::whitelist_recursively` method's \
211 documentation for details.",
212 ),
213 Arg::with_name("objc-extern-crate")
214 .long("objc-extern-crate")
215 .help("Use extern crate instead of use for objc."),
216 Arg::with_name("generate-block")
217 .long("generate-block")
218 .help("Generate block signatures instead of void pointers."),
219 Arg::with_name("block-extern-crate")
220 .long("block-extern-crate")
221 .help("Use extern crate instead of use for block."),
222 Arg::with_name("distrust-clang-mangling")
223 .long("distrust-clang-mangling")
224 .help("Do not trust the libclang-provided mangling"),
225 Arg::with_name("builtins").long("builtins").help(
226 "Output bindings for builtin definitions, e.g. \
227 __builtin_va_list.",
228 ),
229 Arg::with_name("ctypes-prefix")
230 .long("ctypes-prefix")
231 .help(
232 "Use the given prefix before raw types instead of \
233 ::std::os::raw.",
234 )
235 .value_name("prefix")
236 .takes_value(true),
237 Arg::with_name("time-phases")
238 .long("time-phases")
239 .help("Time the different bindgen phases and print to stderr"),
240 // All positional arguments after the end of options marker, `--`
241 Arg::with_name("clang-args").last(true).multiple(true),
242 Arg::with_name("emit-clang-ast")
243 .long("emit-clang-ast")
244 .help("Output the Clang AST for debugging purposes."),
245 Arg::with_name("emit-ir")
246 .long("emit-ir")
247 .help("Output our internal IR for debugging purposes."),
248 Arg::with_name("emit-ir-graphviz")
249 .long("emit-ir-graphviz")
250 .help("Dump graphviz dot file.")
251 .value_name("path")
252 .takes_value(true),
253 Arg::with_name("enable-cxx-namespaces")
254 .long("enable-cxx-namespaces")
255 .help("Enable support for C++ namespaces."),
256 Arg::with_name("disable-name-namespacing")
257 .long("disable-name-namespacing")
258 .help(
259 "Disable namespacing via mangling, causing bindgen to \
260 generate names like \"Baz\" instead of \"foo_bar_Baz\" \
261 for an input name \"foo::bar::Baz\".",
262 ),
263 Arg::with_name("disable-nested-struct-naming")
264 .long("disable-nested-struct-naming")
265 .help(
266 "Disable nested struct naming, causing bindgen to generate \
267 names like \"bar\" instead of \"foo_bar\" for a nested \
268 definition \"struct foo { struct bar { } b; };\"."
269 ),
270 Arg::with_name("disable-untagged-union")
271 .long("disable-untagged-union")
272 .help(
273 "Disable support for native Rust unions.",
274 ),
275 Arg::with_name("ignore-functions")
276 .long("ignore-functions")
277 .help(
278 "Do not generate bindings for functions or methods. This \
279 is useful when you only care about struct layouts.",
280 ),
281 Arg::with_name("generate")
282 .long("generate")
283 .help(
284 "Generate only given items, split by commas. \
285 Valid values are \"functions\",\"types\", \"vars\", \
286 \"methods\", \"constructors\" and \"destructors\".",
287 )
288 .takes_value(true),
289 Arg::with_name("ignore-methods")
290 .long("ignore-methods")
291 .help("Do not generate bindings for methods."),
292 Arg::with_name("no-convert-floats")
293 .long("no-convert-floats")
294 .help("Do not automatically convert floats to f32/f64."),
295 Arg::with_name("no-prepend-enum-name")
296 .long("no-prepend-enum-name")
297 .help("Do not prepend the enum name to constant or newtype variants."),
298 Arg::with_name("no-include-path-detection")
299 .long("no-include-path-detection")
300 .help("Do not try to detect default include paths"),
301 Arg::with_name("unstable-rust")
302 .long("unstable-rust")
303 .help("Generate unstable Rust code (deprecated; use --rust-target instead).")
304 .multiple(true), // FIXME: Pass legacy test suite
305 Arg::with_name("opaque-type")
306 .long("opaque-type")
307 .help("Mark <type> as opaque.")
308 .value_name("type")
309 .takes_value(true)
310 .multiple(true)
311 .number_of_values(1),
312 Arg::with_name("output")
313 .short("o")
314 .long("output")
315 .help("Write Rust bindings to <output>.")
316 .takes_value(true),
317 Arg::with_name("raw-line")
318 .long("raw-line")
319 .help("Add a raw line of Rust code at the beginning of output.")
320 .takes_value(true)
321 .multiple(true)
322 .number_of_values(1),
323 Arg::with_name("rust-target")
324 .long("rust-target")
325 .help(&rust_target_help)
326 .takes_value(true),
327 Arg::with_name("use-core")
328 .long("use-core")
329 .help("Use types from Rust core instead of std."),
330 Arg::with_name("conservative-inline-namespaces")
331 .long("conservative-inline-namespaces")
332 .help(
333 "Conservatively generate inline namespaces to avoid name \
334 conflicts.",
335 ),
336 Arg::with_name("use-msvc-mangling")
337 .long("use-msvc-mangling")
338 .help("MSVC C++ ABI mangling. DEPRECATED: Has no effect."),
339 Arg::with_name("whitelist-function")
340 .long("whitelist-function")
341 .help(
342 "Whitelist all the free-standing functions matching \
343 <regex>. Other non-whitelisted functions will not be \
344 generated.",
345 )
346 .value_name("regex")
347 .takes_value(true)
348 .multiple(true)
349 .number_of_values(1),
350 Arg::with_name("generate-inline-functions")
351 .long("generate-inline-functions")
352 .help("Generate inline functions."),
353 Arg::with_name("whitelist-type")
354 .long("whitelist-type")
355 .help(
356 "Only generate types matching <regex>. Other non-whitelisted types will \
357 not be generated.",
358 )
359 .value_name("regex")
360 .takes_value(true)
361 .multiple(true)
362 .number_of_values(1),
363 Arg::with_name("whitelist-var")
364 .long("whitelist-var")
365 .help(
366 "Whitelist all the free-standing variables matching \
367 <regex>. Other non-whitelisted variables will not be \
368 generated.",
369 )
370 .value_name("regex")
371 .takes_value(true)
372 .multiple(true)
373 .number_of_values(1),
374 Arg::with_name("verbose")
375 .long("verbose")
376 .help("Print verbose error messages."),
377 Arg::with_name("dump-preprocessed-input")
378 .long("dump-preprocessed-input")
379 .help(
380 "Preprocess and dump the input header files to disk. \
381 Useful when debugging bindgen, using C-Reduce, or when \
382 filing issues. The resulting file will be named \
383 something like `__bindgen.i` or `__bindgen.ii`.",
384 ),
385 Arg::with_name("no-record-matches")
386 .long("no-record-matches")
387 .help(
388 "Do not record matching items in the regex sets. \
389 This disables reporting of unused items.",
390 ),
391 Arg::with_name("size_t-is-usize")
392 .long("size_t-is-usize")
393 .help("Translate size_t to usize."),
394 Arg::with_name("no-rustfmt-bindings")
395 .long("no-rustfmt-bindings")
396 .help("Do not format the generated bindings with rustfmt."),
397 Arg::with_name("rustfmt-bindings")
398 .long("rustfmt-bindings")
399 .help(
400 "Format the generated bindings with rustfmt. DEPRECATED: \
401 --rustfmt-bindings is now enabled by default. Disable \
402 with --no-rustfmt-bindings.",
403 ),
404 Arg::with_name("rustfmt-configuration-file")
405 .long("rustfmt-configuration-file")
406 .help(
407 "The absolute path to the rustfmt configuration file. \
408 The configuration file will be used for formatting the bindings. \
409 This parameter is incompatible with --no-rustfmt-bindings.",
410 )
411 .value_name("path")
412 .takes_value(true)
413 .multiple(false)
414 .number_of_values(1),
415 Arg::with_name("no-partialeq")
416 .long("no-partialeq")
417 .help("Avoid deriving PartialEq for types matching <regex>.")
418 .value_name("regex")
419 .takes_value(true)
420 .multiple(true)
421 .number_of_values(1),
422 Arg::with_name("no-copy")
423 .long("no-copy")
424 .help("Avoid deriving Copy for types matching <regex>.")
425 .value_name("regex")
426 .takes_value(true)
427 .multiple(true)
428 .number_of_values(1),
429 Arg::with_name("no-hash")
430 .long("no-hash")
431 .help("Avoid deriving Hash for types matching <regex>.")
432 .value_name("regex")
433 .takes_value(true)
434 .multiple(true)
435 .number_of_values(1),
436 Arg::with_name("enable-function-attribute-detection")
437 .long("enable-function-attribute-detection")
438 .help(
439 "Enables detecting unexposed attributes in functions (slow).
440 Used to generate #[must_use] annotations.",
441 ),
442 Arg::with_name("use-array-pointers-in-arguments")
443 .long("use-array-pointers-in-arguments")
444 .help("Use `*const [T; size]` instead of `*const T` for C arrays"),
445 Arg::with_name("wasm-import-module-name")
446 .long("wasm-import-module-name")
447 .value_name("name")
448 .takes_value(true)
449 .help("The name to be used in a #[link(wasm_import_module = ...)] statement")
450 ]) // .args()
451 .get_matches_from(args);
452
453 let mut builder = builder();
454
455 if let Some(header) = matches.value_of("header") {
456 builder = builder.header(header);
457 } else {
458 return Err(Error::new(ErrorKind::Other, "Header not found"));
459 }
460
461 if matches.is_present("unstable-rust") {
462 builder = builder.rust_target(RustTarget::Nightly);
463 writeln!(
464 &mut stderr(),
465 "warning: the `--unstable-rust` option is deprecated"
466 )
467 .expect("Unable to write error message");
468 }
469
470 if let Some(rust_target) = matches.value_of("rust-target") {
471 builder = builder.rust_target(RustTarget::from_str(rust_target)?);
472 }
473
474 if let Some(variant) = matches.value_of("default-enum-style") {
475 builder = builder.default_enum_style(EnumVariation::from_str(variant)?)
476 }
477
478 if let Some(bitfields) = matches.values_of("bitfield-enum") {
479 for regex in bitfields {
480 builder = builder.bitfield_enum(regex);
481 }
482 }
483
484 if let Some(newtypes) = matches.values_of("newtype-enum") {
485 for regex in newtypes {
486 builder = builder.newtype_enum(regex);
487 }
488 }
489
490 if let Some(rustifieds) = matches.values_of("rustified-enum") {
491 for regex in rustifieds {
492 builder = builder.rustified_enum(regex);
493 }
494 }
495
496 if let Some(const_enums) = matches.values_of("constified-enum") {
497 for regex in const_enums {
498 builder = builder.constified_enum(regex);
499 }
500 }
501
502 if let Some(constified_mods) = matches.values_of("constified-enum-module") {
503 for regex in constified_mods {
504 builder = builder.constified_enum_module(regex);
505 }
506 }
507
508 if let Some(variant) = matches.value_of("default-alias-style") {
509 builder =
510 builder.default_alias_style(AliasVariation::from_str(variant)?);
511 }
512
513 if let Some(type_alias) = matches.values_of("normal-alias") {
514 for regex in type_alias {
515 builder = builder.type_alias(regex);
516 }
517 }
518
519 if let Some(new_type) = matches.values_of("new-type-alias") {
520 for regex in new_type {
521 builder = builder.new_type_alias(regex);
522 }
523 }
524
525 if let Some(new_type_deref) = matches.values_of("new-type-alias-deref") {
526 for regex in new_type_deref {
527 builder = builder.new_type_alias_deref(regex);
528 }
529 }
530
531 if let Some(hidden_types) = matches.values_of("blacklist-type") {
532 for ty in hidden_types {
533 builder = builder.blacklist_type(ty);
534 }
535 }
536
537 if let Some(hidden_functions) = matches.values_of("blacklist-function") {
538 for fun in hidden_functions {
539 builder = builder.blacklist_function(fun);
540 }
541 }
542
543 if let Some(hidden_identifiers) = matches.values_of("blacklist-item") {
544 for id in hidden_identifiers {
545 builder = builder.blacklist_item(id);
546 }
547 }
548
549 if matches.is_present("builtins") {
550 builder = builder.emit_builtins();
551 }
552
553 if matches.is_present("no-layout-tests") {
554 builder = builder.layout_tests(false);
555 }
556
557 if matches.is_present("no-derive-copy") {
558 builder = builder.derive_copy(false);
559 }
560
561 if matches.is_present("no-derive-debug") {
562 builder = builder.derive_debug(false);
563 }
564
565 if matches.is_present("impl-debug") {
566 builder = builder.impl_debug(true);
567 }
568
569 if matches.is_present("impl-partialeq") {
570 builder = builder.impl_partialeq(true);
571 }
572
573 if matches.is_present("with-derive-default") {
574 builder = builder.derive_default(true);
575 }
576
577 if matches.is_present("with-derive-hash") {
578 builder = builder.derive_hash(true);
579 }
580
581 if matches.is_present("with-derive-partialeq") {
582 builder = builder.derive_partialeq(true);
583 }
584
585 if matches.is_present("with-derive-partialord") {
586 builder = builder.derive_partialord(true);
587 }
588
589 if matches.is_present("with-derive-eq") {
590 builder = builder.derive_eq(true);
591 }
592
593 if matches.is_present("with-derive-ord") {
594 builder = builder.derive_ord(true);
595 }
596
597 if matches.is_present("no-derive-default") {
598 builder = builder.derive_default(false);
599 }
600
601 if matches.is_present("no-prepend-enum-name") {
602 builder = builder.prepend_enum_name(false);
603 }
604
605 if matches.is_present("no-include-path-detection") {
606 builder = builder.detect_include_paths(false);
607 }
608
609 if matches.is_present("time-phases") {
610 builder = builder.time_phases(true);
611 }
612
613 if matches.is_present("use-array-pointers-in-arguments") {
614 builder = builder.array_pointers_in_arguments(true);
615 }
616
617 if let Some(wasm_import_name) = matches.value_of("wasm-import-module-name")
618 {
619 builder = builder.wasm_import_module_name(wasm_import_name);
620 }
621
622 if let Some(prefix) = matches.value_of("ctypes-prefix") {
623 builder = builder.ctypes_prefix(prefix);
624 }
625
626 if let Some(what_to_generate) = matches.value_of("generate") {
627 let mut config = CodegenConfig::empty();
628 for what in what_to_generate.split(",") {
629 match what {
630 "functions" => config.insert(CodegenConfig::FUNCTIONS),
631 "types" => config.insert(CodegenConfig::TYPES),
632 "vars" => config.insert(CodegenConfig::VARS),
633 "methods" => config.insert(CodegenConfig::METHODS),
634 "constructors" => config.insert(CodegenConfig::CONSTRUCTORS),
635 "destructors" => config.insert(CodegenConfig::DESTRUCTORS),
636 otherwise => {
637 return Err(Error::new(
638 ErrorKind::Other,
639 format!("Unknown generate item: {}", otherwise),
640 ));
641 }
642 }
643 }
644 builder = builder.with_codegen_config(config);
645 }
646
647 if matches.is_present("emit-clang-ast") {
648 builder = builder.emit_clang_ast();
649 }
650
651 if matches.is_present("emit-ir") {
652 builder = builder.emit_ir();
653 }
654
655 if let Some(path) = matches.value_of("emit-ir-graphviz") {
656 builder = builder.emit_ir_graphviz(path);
657 }
658
659 if matches.is_present("enable-cxx-namespaces") {
660 builder = builder.enable_cxx_namespaces();
661 }
662
663 if matches.is_present("enable-function-attribute-detection") {
664 builder = builder.enable_function_attribute_detection();
665 }
666
667 if matches.is_present("disable-name-namespacing") {
668 builder = builder.disable_name_namespacing();
669 }
670
671 if matches.is_present("disable-nested-struct-naming") {
672 builder = builder.disable_nested_struct_naming();
673 }
674
675 if matches.is_present("disable-untagged-union") {
676 builder = builder.disable_untagged_union();
677 }
678
679 if matches.is_present("ignore-functions") {
680 builder = builder.ignore_functions();
681 }
682
683 if matches.is_present("ignore-methods") {
684 builder = builder.ignore_methods();
685 }
686
687 if matches.is_present("no-convert-floats") {
688 builder = builder.no_convert_floats();
689 }
690
691 if matches.is_present("no-doc-comments") {
692 builder = builder.generate_comments(false);
693 }
694
695 if matches.is_present("no-recursive-whitelist") {
696 builder = builder.whitelist_recursively(false);
697 }
698
699 if matches.is_present("objc-extern-crate") {
700 builder = builder.objc_extern_crate(true);
701 }
702
703 if matches.is_present("generate-block") {
704 builder = builder.generate_block(true);
705 }
706
707 if matches.is_present("block-extern-crate") {
708 builder = builder.block_extern_crate(true);
709 }
710
711 if let Some(opaque_types) = matches.values_of("opaque-type") {
712 for ty in opaque_types {
713 builder = builder.opaque_type(ty);
714 }
715 }
716
717 if let Some(lines) = matches.values_of("raw-line") {
718 for line in lines {
719 builder = builder.raw_line(line);
720 }
721 }
722
723 if matches.is_present("use-core") {
724 builder = builder.use_core();
725 }
726
727 if matches.is_present("distrust-clang-mangling") {
728 builder = builder.trust_clang_mangling(false);
729 }
730
731 if matches.is_present("conservative-inline-namespaces") {
732 builder = builder.conservative_inline_namespaces();
733 }
734
735 if matches.is_present("generate-inline-functions") {
736 builder = builder.generate_inline_functions(true);
737 }
738
739 if let Some(whitelist) = matches.values_of("whitelist-function") {
740 for regex in whitelist {
741 builder = builder.whitelist_function(regex);
742 }
743 }
744
745 if let Some(whitelist) = matches.values_of("whitelist-type") {
746 for regex in whitelist {
747 builder = builder.whitelist_type(regex);
748 }
749 }
750
751 if let Some(whitelist) = matches.values_of("whitelist-var") {
752 for regex in whitelist {
753 builder = builder.whitelist_var(regex);
754 }
755 }
756
757 if let Some(args) = matches.values_of("clang-args") {
758 for arg in args {
759 builder = builder.clang_arg(arg);
760 }
761 }
762
763 let output = if let Some(path) = matches.value_of("output") {
764 let file = File::create(path)?;
765 Box::new(io::BufWriter::new(file)) as Box<dyn io::Write>
766 } else {
767 Box::new(io::BufWriter::new(io::stdout())) as Box<dyn io::Write>
768 };
769
770 if matches.is_present("dump-preprocessed-input") {
771 builder.dump_preprocessed_input()?;
772 }
773
774 if matches.is_present("no-record-matches") {
775 builder = builder.record_matches(false);
776 }
777
778 if matches.is_present("size_t-is-usize") {
779 builder = builder.size_t_is_usize(true);
780 }
781
782 let no_rustfmt_bindings = matches.is_present("no-rustfmt-bindings");
783 if no_rustfmt_bindings {
784 builder = builder.rustfmt_bindings(false);
785 }
786
787 if let Some(path_str) = matches.value_of("rustfmt-configuration-file") {
788 let path = PathBuf::from(path_str);
789
790 if no_rustfmt_bindings {
791 return Err(Error::new(
792 ErrorKind::Other,
793 "Cannot supply both --rustfmt-configuration-file and --no-rustfmt-bindings",
794 ));
795 }
796
797 if !path.is_absolute() {
798 return Err(Error::new(
799 ErrorKind::Other,
800 "--rustfmt-configuration--file needs to be an absolute path!",
801 ));
802 }
803
804 if path.to_str().is_none() {
805 return Err(Error::new(
806 ErrorKind::Other,
807 "--rustfmt-configuration-file contains non-valid UTF8 characters.",
808 ));
809 }
810
811 builder = builder.rustfmt_configuration_file(Some(path));
812 }
813
814 if let Some(no_partialeq) = matches.values_of("no-partialeq") {
815 for regex in no_partialeq {
816 builder = builder.no_partialeq(regex);
817 }
818 }
819
820 if let Some(no_copy) = matches.values_of("no-copy") {
821 for regex in no_copy {
822 builder = builder.no_copy(regex);
823 }
824 }
825
826 if let Some(no_hash) = matches.values_of("no-hash") {
827 for regex in no_hash {
828 builder = builder.no_hash(regex);
829 }
830 }
831
832 let verbose = matches.is_present("verbose");
833
834 Ok((builder, output, verbose))
835 }
836