Introduce declaration styles on C structs and enums
Allow structs, enums and unions to be declared as: struct Name {}; typedef struct {} Name; typedef struct Name {} Name; Opaque enums will be declared as: struct Name; typedef struct Name Name;
This commit is contained in:
parent
1693519e39
commit
608a67b4b2
@ -85,6 +85,8 @@ line_length = 80
|
||||
tab_width = 2
|
||||
# The language to output bindings in
|
||||
language = "[C|C++]"
|
||||
# A rule to use to select style of declaration in C, tagname vs typedef
|
||||
style = "[Both|Type|Tag]"
|
||||
|
||||
[parse]
|
||||
# Whether to parse dependent crates and include their types in the generated
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
use std::io::Write;
|
||||
|
||||
use bindgen::declarationtyperesolver::DeclarationType;
|
||||
use bindgen::ir::{Function, Type};
|
||||
use bindgen::writer::{ListType, SourceWriter};
|
||||
|
||||
@ -32,6 +33,7 @@ struct CDecl {
|
||||
type_name: String,
|
||||
type_generic_args: Vec<Type>,
|
||||
declarators: Vec<CDeclarator>,
|
||||
type_ctype: Option<DeclarationType>,
|
||||
}
|
||||
|
||||
impl CDecl {
|
||||
@ -41,6 +43,7 @@ impl CDecl {
|
||||
type_name: String::new(),
|
||||
type_generic_args: Vec::new(),
|
||||
declarators: Vec::new(),
|
||||
type_ctype: None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -77,6 +80,7 @@ impl CDecl {
|
||||
self.type_name = path.name.clone();
|
||||
assert!(self.type_generic_args.len() == 0, "error generating cdecl for {:?}", t);
|
||||
self.type_generic_args = path.generics.clone();
|
||||
self.type_ctype = path.ctype;
|
||||
}
|
||||
&Type::Primitive(ref p) => {
|
||||
if is_const {
|
||||
@ -117,10 +121,14 @@ impl CDecl {
|
||||
) {
|
||||
// Write the type-specifier and type-qualifier first
|
||||
if self.type_qualifers.len() != 0 {
|
||||
write!(out, "{} {}", self.type_qualifers, self.type_name);
|
||||
} else {
|
||||
write!(out, "{}", self.type_name);
|
||||
};
|
||||
write!(out, "{} ", self.type_qualifers);
|
||||
}
|
||||
|
||||
if let Some(ref ctype) = self.type_ctype {
|
||||
write!(out, "{} ", ctype.to_str());
|
||||
}
|
||||
|
||||
write!(out, "{}", self.type_name);
|
||||
|
||||
if !self.type_generic_args.is_empty() {
|
||||
out.write("<");
|
||||
|
@ -95,6 +95,50 @@ impl FromStr for Layout {
|
||||
|
||||
deserialize_enum_str!(Layout);
|
||||
|
||||
/// A style of Style to use when generating structs and enums.
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum Style {
|
||||
Both,
|
||||
Tag,
|
||||
Type,
|
||||
}
|
||||
|
||||
impl Style {
|
||||
pub fn generate_tag(&self) -> bool {
|
||||
match self {
|
||||
&Style::Both => true,
|
||||
&Style::Tag => true,
|
||||
&Style::Type => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate_typedef(&self) -> bool {
|
||||
match self {
|
||||
&Style::Both => true,
|
||||
&Style::Tag => false,
|
||||
&Style::Type => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Style {
|
||||
type Err = String;
|
||||
|
||||
fn from_str(s: &str) -> Result<Style, Self::Err> {
|
||||
match s {
|
||||
"Both" => Ok(Style::Both),
|
||||
"both" => Ok(Style::Both),
|
||||
"Tag" => Ok(Style::Tag),
|
||||
"tag" => Ok(Style::Tag),
|
||||
"Type" => Ok(Style::Type),
|
||||
"type" => Ok(Style::Type),
|
||||
_ => Err(format!("Unrecognized Style: '{}'.", s)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deserialize_enum_str!(Style);
|
||||
|
||||
/// Settings to apply when exporting items.
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
@ -380,6 +424,8 @@ pub struct Config {
|
||||
pub tab_width: usize,
|
||||
/// The language to output bindings for
|
||||
pub language: Language,
|
||||
/// The style to declare structs, enums and unions in for C
|
||||
pub style: Style,
|
||||
/// The configuration options for parsing
|
||||
pub parse: ParseConfig,
|
||||
/// The configuration options for exporting
|
||||
@ -418,6 +464,7 @@ impl Default for Config {
|
||||
line_length: 100,
|
||||
tab_width: 2,
|
||||
language: Language::Cxx,
|
||||
style: Style::Type,
|
||||
parse: ParseConfig::default(),
|
||||
export: ExportConfig::default(),
|
||||
function: FunctionConfig::default(),
|
||||
|
62
src/bindgen/declarationtyperesolver.rs
Normal file
62
src/bindgen/declarationtyperesolver.rs
Normal file
@ -0,0 +1,62 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use std::collections::HashSet;
|
||||
|
||||
pub struct DeclarationTypeResolver {
|
||||
structs: HashSet<String>,
|
||||
enums: HashSet<String>,
|
||||
unions: HashSet<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
|
||||
pub enum DeclarationType {
|
||||
Struct,
|
||||
Enum,
|
||||
Union,
|
||||
}
|
||||
|
||||
impl DeclarationType {
|
||||
pub fn to_str(&self) -> &'static str {
|
||||
match self {
|
||||
&DeclarationType::Struct => "struct",
|
||||
&DeclarationType::Enum => "enum",
|
||||
&DeclarationType::Union => "union",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DeclarationTypeResolver {
|
||||
pub fn new() -> DeclarationTypeResolver {
|
||||
DeclarationTypeResolver {
|
||||
structs: HashSet::new(),
|
||||
enums: HashSet::new(),
|
||||
unions: HashSet::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_enum(&mut self, name: &str) {
|
||||
self.enums.insert(name.to_owned());
|
||||
}
|
||||
|
||||
pub fn add_struct(&mut self, name: &str) {
|
||||
self.structs.insert(name.to_owned());
|
||||
}
|
||||
|
||||
pub fn add_union(&mut self, name: &str) {
|
||||
self.unions.insert(name.to_owned());
|
||||
}
|
||||
|
||||
pub fn type_for(&self, name: &str) -> Option<DeclarationType> {
|
||||
if self.structs.contains(name) {
|
||||
Some(DeclarationType::Struct)
|
||||
} else if self.enums.contains(name) {
|
||||
Some(DeclarationType::Enum)
|
||||
} else if self.unions.contains(name) {
|
||||
Some(DeclarationType::Union)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
@ -9,6 +9,7 @@ use syn;
|
||||
|
||||
use bindgen::config::{Config, Language};
|
||||
use bindgen::ir::{AnnotationSet, Cfg, CfgWrite, Documentation, Item, ItemContainer, Type};
|
||||
use bindgen::declarationtyperesolver::DeclarationTypeResolver;
|
||||
use bindgen::writer::{Source, SourceWriter};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@ -128,6 +129,10 @@ impl Item for Constant {
|
||||
fn rename_for_config(&mut self, config: &Config) {
|
||||
config.export.rename(&mut self.name);
|
||||
}
|
||||
|
||||
fn resolve_declaration_types(&mut self, resolver: &DeclarationTypeResolver) {
|
||||
self.ty.resolve_declaration_types(resolver);
|
||||
}
|
||||
}
|
||||
|
||||
impl Source for Constant {
|
||||
|
@ -7,6 +7,7 @@ use std::io::Write;
|
||||
use syn;
|
||||
|
||||
use bindgen::config::{Config, Language};
|
||||
use bindgen::declarationtyperesolver::DeclarationTypeResolver;
|
||||
use bindgen::dependencies::Dependencies;
|
||||
use bindgen::library::Library;
|
||||
use bindgen::ir::{AnnotationSet, Cfg, CfgWrite, Documentation, GenericParams, GenericPath, Item,
|
||||
@ -55,6 +56,7 @@ impl EnumVariant {
|
||||
Type::Path(GenericPath {
|
||||
name: "Tag".to_string(),
|
||||
generics: vec![],
|
||||
ctype: None,
|
||||
}),
|
||||
Documentation::none(),
|
||||
));
|
||||
@ -119,6 +121,12 @@ impl EnumVariant {
|
||||
item.add_dependencies(library, out);
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_declaration_types(&mut self, resolver: &DeclarationTypeResolver) {
|
||||
if let Some((_, ref mut ty)) = self.body {
|
||||
ty.resolve_declaration_types(resolver);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Source for EnumVariant {
|
||||
@ -209,6 +217,22 @@ impl Item for Enum {
|
||||
ItemContainer::Enum(self.clone())
|
||||
}
|
||||
|
||||
fn collect_declaration_types(&self, resolver: &mut DeclarationTypeResolver) {
|
||||
if self.tag.is_some() && self.repr.style == ReprStyle::C {
|
||||
resolver.add_struct(&self.name);
|
||||
} else if self.tag.is_some() && self.repr.style != ReprStyle::C {
|
||||
resolver.add_union(&self.name);
|
||||
} else if self.repr.style == ReprStyle::C {
|
||||
resolver.add_enum(&self.name);
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_declaration_types(&mut self, resolver: &DeclarationTypeResolver) {
|
||||
for &mut ref mut var in &mut self.variants {
|
||||
var.resolve_declaration_types(resolver);
|
||||
}
|
||||
}
|
||||
|
||||
fn rename_for_config(&mut self, config: &Config) {
|
||||
config.export.rename(&mut self.name);
|
||||
|
||||
@ -221,6 +245,7 @@ impl Item for Enum {
|
||||
body.fields[0].1 = Type::Path(GenericPath {
|
||||
name: new_tag.clone(),
|
||||
generics: vec![],
|
||||
ctype: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -308,12 +333,16 @@ impl Source for Enum {
|
||||
};
|
||||
|
||||
if config.language == Language::C {
|
||||
if size.is_none() {
|
||||
out.write("typedef enum");
|
||||
} else {
|
||||
write!(out, "enum {}", enum_name);
|
||||
if size.is_none() && config.style.generate_typedef() {
|
||||
out.write("typedef ");
|
||||
}
|
||||
} else {
|
||||
|
||||
out.write("enum");
|
||||
|
||||
if !size.is_none() || config.style.generate_tag() {
|
||||
write!(out, " {}", enum_name);
|
||||
}
|
||||
} else {
|
||||
if let Some(prim) = size {
|
||||
write!(out, "enum class {} : {}", enum_name, prim);
|
||||
} else {
|
||||
@ -333,7 +362,7 @@ impl Source for Enum {
|
||||
out.write("Sentinel /* this must be last for serialization purposes. */");
|
||||
}
|
||||
|
||||
if config.language == Language::C && size.is_none() {
|
||||
if config.language == Language::C && size.is_none() && config.style.generate_typedef() {
|
||||
out.close_brace(false);
|
||||
write!(out, " {};", enum_name);
|
||||
} else {
|
||||
@ -361,11 +390,16 @@ impl Source for Enum {
|
||||
out.new_line();
|
||||
|
||||
if config.language == Language::C {
|
||||
write!(
|
||||
out,
|
||||
"typedef {}",
|
||||
if separate_tag { "struct" } else { "union" }
|
||||
);
|
||||
if config.style.generate_typedef() {
|
||||
out.write("typedef ");
|
||||
}
|
||||
|
||||
out.write(if separate_tag { "struct" } else { "union" });
|
||||
|
||||
if config.style.generate_tag() {
|
||||
write!(out, " {}", self.name);
|
||||
}
|
||||
|
||||
out.open_brace();
|
||||
}
|
||||
|
||||
@ -378,6 +412,10 @@ impl Source for Enum {
|
||||
out.open_brace();
|
||||
}
|
||||
|
||||
if config.language == Language::C && !config.style.generate_typedef() {
|
||||
out.write("enum ");
|
||||
}
|
||||
|
||||
write!(out, "{} tag;", enum_name);
|
||||
|
||||
if wrap_tag {
|
||||
@ -399,7 +437,11 @@ impl Source for Enum {
|
||||
if i != 0 {
|
||||
out.new_line();
|
||||
}
|
||||
write!(out, "{} {};", body.name, field_name);
|
||||
if config.style.generate_typedef() {
|
||||
write!(out, "{} {};", body.name, field_name);
|
||||
} else {
|
||||
write!(out, "struct {} {};", body.name, field_name);
|
||||
}
|
||||
}
|
||||
|
||||
if separate_tag {
|
||||
@ -407,8 +449,12 @@ impl Source for Enum {
|
||||
}
|
||||
|
||||
if config.language == Language::C {
|
||||
out.close_brace(false);
|
||||
write!(out, " {};", self.name);
|
||||
if config.style.generate_typedef() {
|
||||
out.close_brace(false);
|
||||
write!(out, " {};", self.name);
|
||||
} else {
|
||||
out.close_brace(true);
|
||||
}
|
||||
} else {
|
||||
out.close_brace(true);
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ use syn;
|
||||
|
||||
use bindgen::cdecl;
|
||||
use bindgen::config::{Config, Language, Layout};
|
||||
use bindgen::declarationtyperesolver::DeclarationTypeResolver;
|
||||
use bindgen::dependencies::Dependencies;
|
||||
use bindgen::ir::{AnnotationSet, Cfg, CfgWrite, Documentation, PrimitiveType, Type};
|
||||
use bindgen::library::Library;
|
||||
@ -86,6 +87,13 @@ impl Function {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_declaration_types(&mut self, resolver: &DeclarationTypeResolver) {
|
||||
self.ret.resolve_declaration_types(resolver);
|
||||
for &mut (_, ref mut ty) in &mut self.args {
|
||||
ty.resolve_declaration_types(resolver);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rename_for_config(&mut self, config: &Config) {
|
||||
self.ret.rename_for_config(config);
|
||||
for &mut (_, ref mut ty) in &mut self.args {
|
||||
|
@ -7,6 +7,7 @@ use std::io::Write;
|
||||
use syn;
|
||||
|
||||
use bindgen::config::Config;
|
||||
use bindgen::declarationtyperesolver::DeclarationTypeResolver;
|
||||
use bindgen::dependencies::Dependencies;
|
||||
use bindgen::ir::{AnnotationSet, Cfg, Documentation, Item, ItemContainer, Type};
|
||||
use bindgen::library::Library;
|
||||
@ -70,6 +71,10 @@ impl Item for Static {
|
||||
self.ty.rename_for_config(config);
|
||||
}
|
||||
|
||||
fn resolve_declaration_types(&mut self, resolver: &DeclarationTypeResolver) {
|
||||
self.ty.resolve_declaration_types(resolver);
|
||||
}
|
||||
|
||||
fn add_dependencies(&self, library: &Library, out: &mut Dependencies) {
|
||||
self.ty.add_dependencies(library, out);
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ use std::collections::BTreeMap;
|
||||
use std::mem;
|
||||
|
||||
use bindgen::config::Config;
|
||||
use bindgen::declarationtyperesolver::DeclarationTypeResolver;
|
||||
use bindgen::dependencies::Dependencies;
|
||||
use bindgen::ir::{AnnotationSet, Cfg, Constant, Enum, OpaqueItem, Static, Struct, Type, Typedef,
|
||||
Union};
|
||||
@ -21,6 +22,8 @@ pub trait Item {
|
||||
|
||||
fn container(&self) -> ItemContainer;
|
||||
|
||||
fn collect_declaration_types(&self, _resolver: &mut DeclarationTypeResolver) { unimplemented!() }
|
||||
fn resolve_declaration_types(&mut self, _resolver: &DeclarationTypeResolver) { unimplemented!() }
|
||||
fn rename_for_config(&mut self, _config: &Config) {}
|
||||
fn add_dependencies(&self, _library: &Library, _out: &mut Dependencies) {}
|
||||
fn instantiate_monomorph(
|
||||
|
@ -7,6 +7,7 @@ use std::io::Write;
|
||||
use syn;
|
||||
|
||||
use bindgen::config::{Config, Language};
|
||||
use bindgen::declarationtyperesolver::DeclarationTypeResolver;
|
||||
use bindgen::dependencies::Dependencies;
|
||||
use bindgen::ir::{AnnotationSet, Cfg, CfgWrite, Documentation, GenericParams, Item, ItemContainer,
|
||||
Path, Type};
|
||||
@ -62,6 +63,10 @@ impl Item for OpaqueItem {
|
||||
ItemContainer::OpaqueItem(self.clone())
|
||||
}
|
||||
|
||||
fn collect_declaration_types(&self, resolver: &mut DeclarationTypeResolver) {
|
||||
resolver.add_struct(&self.name);
|
||||
}
|
||||
|
||||
fn rename_for_config(&mut self, config: &Config) {
|
||||
config.export.rename(&mut self.name);
|
||||
}
|
||||
@ -101,7 +106,8 @@ impl Source for OpaqueItem {
|
||||
|
||||
self.generic_params.write(config, out);
|
||||
|
||||
if config.language == Language::C {
|
||||
if config.style.generate_typedef() &&
|
||||
config.language == Language::C {
|
||||
write!(out, "typedef struct {} {};", self.name, self.name);
|
||||
} else {
|
||||
write!(out, "struct {};", self.name);
|
||||
|
@ -5,6 +5,7 @@
|
||||
use syn;
|
||||
|
||||
use bindgen::ir::Type;
|
||||
use bindgen::declarationtyperesolver::{DeclarationType, DeclarationTypeResolver};
|
||||
use bindgen::utilities::IterHelpers;
|
||||
|
||||
pub type Path = String;
|
||||
@ -13,6 +14,7 @@ pub type Path = String;
|
||||
pub struct GenericPath {
|
||||
pub name: String,
|
||||
pub generics: Vec<Type>,
|
||||
pub ctype: Option<DeclarationType>,
|
||||
}
|
||||
|
||||
impl GenericPath {
|
||||
@ -20,9 +22,14 @@ impl GenericPath {
|
||||
GenericPath {
|
||||
name: name,
|
||||
generics: generics,
|
||||
ctype: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_declaration_types(&mut self, resolver: &DeclarationTypeResolver) {
|
||||
self.ctype = resolver.type_for(&self.name);
|
||||
}
|
||||
|
||||
pub fn load(path: &syn::Path) -> Result<GenericPath, String> {
|
||||
assert!(path.segments.len() > 0, "{:?} doesn't have any segments", path);
|
||||
let last_segment_token = path.segments.last().unwrap();
|
||||
|
@ -7,9 +7,10 @@ use std::io::Write;
|
||||
use syn;
|
||||
|
||||
use bindgen::config::{Config, Language};
|
||||
use bindgen::declarationtyperesolver::DeclarationTypeResolver;
|
||||
use bindgen::dependencies::Dependencies;
|
||||
use bindgen::ir::{AnnotationSet, Cfg, CfgWrite, Documentation, GenericParams, Item, ItemContainer,
|
||||
Repr, Type};
|
||||
use bindgen::ir::{AnnotationSet, Cfg, CfgWrite, Documentation, GenericParams, Item,
|
||||
ItemContainer, Repr, Type};
|
||||
use bindgen::library::Library;
|
||||
use bindgen::mangle;
|
||||
use bindgen::monomorph::Monomorphs;
|
||||
@ -116,6 +117,16 @@ impl Item for Struct {
|
||||
ItemContainer::Struct(self.clone())
|
||||
}
|
||||
|
||||
fn collect_declaration_types(&self, resolver: &mut DeclarationTypeResolver) {
|
||||
resolver.add_struct(&self.name);
|
||||
}
|
||||
|
||||
fn resolve_declaration_types(&mut self, resolver: &DeclarationTypeResolver) {
|
||||
for &mut (_, ref mut ty, _) in &mut self.fields {
|
||||
ty.resolve_declaration_types(resolver);
|
||||
}
|
||||
}
|
||||
|
||||
fn rename_for_config(&mut self, config: &Config) {
|
||||
config.export.rename(&mut self.name);
|
||||
for &mut (_, ref mut ty, _) in &mut self.fields {
|
||||
@ -217,11 +228,23 @@ impl Source for Struct {
|
||||
|
||||
self.generic_params.write(config, out);
|
||||
|
||||
if config.language == Language::C {
|
||||
out.write("typedef struct");
|
||||
} else {
|
||||
write!(out, "struct {}", self.name);
|
||||
// The following results in
|
||||
// C++ or C with Tag as style:
|
||||
// struct Name {
|
||||
// C with Type only style:
|
||||
// typedef struct {
|
||||
// C with Both as style:
|
||||
// typedef struct Name {
|
||||
if config.language == Language::C && config.style.generate_typedef() {
|
||||
out.write("typedef ");
|
||||
}
|
||||
|
||||
out.write("struct");
|
||||
|
||||
if config.language == Language::Cxx || config.style.generate_tag() {
|
||||
write!(out, " {}", self.name);
|
||||
}
|
||||
|
||||
out.open_brace();
|
||||
|
||||
if config.documentation {
|
||||
@ -345,7 +368,7 @@ impl Source for Struct {
|
||||
}
|
||||
}
|
||||
|
||||
if config.language == Language::C {
|
||||
if config.language == Language::C && config.style.generate_typedef() {
|
||||
out.close_brace(false);
|
||||
write!(out, " {};", self.name);
|
||||
} else {
|
||||
|
@ -9,6 +9,7 @@ use syn;
|
||||
|
||||
use bindgen::cdecl;
|
||||
use bindgen::config::Config;
|
||||
use bindgen::declarationtyperesolver::DeclarationTypeResolver;
|
||||
use bindgen::dependencies::Dependencies;
|
||||
use bindgen::ir::{Documentation, GenericParams, GenericPath, Path};
|
||||
use bindgen::library::Library;
|
||||
@ -491,6 +492,30 @@ impl Type {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_declaration_types(&mut self, resolver: &DeclarationTypeResolver) {
|
||||
match self {
|
||||
&mut Type::ConstPtr(ref mut ty) => {
|
||||
ty.resolve_declaration_types(resolver);
|
||||
}
|
||||
&mut Type::Ptr(ref mut ty) => {
|
||||
ty.resolve_declaration_types(resolver);
|
||||
}
|
||||
&mut Type::Path(ref mut path) => {
|
||||
path.resolve_declaration_types(resolver);
|
||||
}
|
||||
&mut Type::Primitive(_) => {}
|
||||
&mut Type::Array(ref mut ty, _) => {
|
||||
ty.resolve_declaration_types(resolver);
|
||||
}
|
||||
&mut Type::FuncPtr(ref mut ret, ref mut args) => {
|
||||
ret.resolve_declaration_types(resolver);
|
||||
for arg in args {
|
||||
arg.resolve_declaration_types(resolver);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mangle_paths(&mut self, monomorphs: &Monomorphs) {
|
||||
match self {
|
||||
&mut Type::ConstPtr(ref mut ty) => {
|
||||
|
@ -8,6 +8,7 @@ use std::io::Write;
|
||||
use syn;
|
||||
|
||||
use bindgen::config::{Config, Language};
|
||||
use bindgen::declarationtyperesolver::DeclarationTypeResolver;
|
||||
use bindgen::dependencies::Dependencies;
|
||||
use bindgen::ir::{AnnotationSet, Cfg, CfgWrite, Documentation, GenericParams, Item, ItemContainer,
|
||||
Path, Type};
|
||||
@ -114,6 +115,10 @@ impl Item for Typedef {
|
||||
self.aliased.rename_for_config(config);
|
||||
}
|
||||
|
||||
fn resolve_declaration_types(&mut self, resolver: &DeclarationTypeResolver) {
|
||||
self.aliased.resolve_declaration_types(resolver);
|
||||
}
|
||||
|
||||
fn add_dependencies(&self, library: &Library, out: &mut Dependencies) {
|
||||
self.aliased
|
||||
.add_dependencies_ignoring_generics(&self.generic_params, library, out);
|
||||
|
@ -7,6 +7,7 @@ use std::io::Write;
|
||||
use syn;
|
||||
|
||||
use bindgen::config::{Config, Language};
|
||||
use bindgen::declarationtyperesolver::DeclarationTypeResolver;
|
||||
use bindgen::dependencies::Dependencies;
|
||||
use bindgen::ir::{AnnotationSet, Cfg, CfgWrite, Documentation, GenericParams, Item, ItemContainer,
|
||||
Repr, Type};
|
||||
@ -104,6 +105,16 @@ impl Item for Union {
|
||||
ItemContainer::Union(self.clone())
|
||||
}
|
||||
|
||||
fn collect_declaration_types(&self, resolver: &mut DeclarationTypeResolver) {
|
||||
resolver.add_union(&self.name);
|
||||
}
|
||||
|
||||
fn resolve_declaration_types(&mut self, resolver: &DeclarationTypeResolver) {
|
||||
for &mut (_, ref mut ty, _) in &mut self.fields {
|
||||
ty.resolve_declaration_types(resolver);
|
||||
}
|
||||
}
|
||||
|
||||
fn rename_for_config(&mut self, config: &Config) {
|
||||
config.export.rename(&mut self.name);
|
||||
for &mut (_, ref mut ty, _) in &mut self.fields {
|
||||
@ -205,11 +216,23 @@ impl Source for Union {
|
||||
|
||||
self.generic_params.write(config, out);
|
||||
|
||||
if config.language == Language::C {
|
||||
out.write("typedef union");
|
||||
} else {
|
||||
write!(out, "union {}", self.name);
|
||||
// The following results in
|
||||
// C++ or C with Tag as style:
|
||||
// union Name {
|
||||
// C with Type only style:
|
||||
// typedef union {
|
||||
// C with Both as style:
|
||||
// typedef union Name {
|
||||
if config.language == Language::C && config.style.generate_typedef() {
|
||||
out.write("typedef ");
|
||||
}
|
||||
|
||||
out.write("union");
|
||||
|
||||
if config.language == Language::Cxx || config.style.generate_tag() {
|
||||
write!(out, " {}", self.name);
|
||||
}
|
||||
|
||||
out.open_brace();
|
||||
|
||||
if config.documentation {
|
||||
@ -224,7 +247,7 @@ impl Source for Union {
|
||||
);
|
||||
}
|
||||
|
||||
if config.language == Language::C {
|
||||
if config.language == Language::C && config.style.generate_typedef() {
|
||||
out.close_brace(false);
|
||||
write!(out, " {};", self.name);
|
||||
} else {
|
||||
|
@ -7,6 +7,7 @@ use std::mem;
|
||||
|
||||
use bindgen::bindings::Bindings;
|
||||
use bindgen::config::{Config, Language};
|
||||
use bindgen::declarationtyperesolver::DeclarationTypeResolver;
|
||||
use bindgen::dependencies::Dependencies;
|
||||
use bindgen::error::Error;
|
||||
use bindgen::ir::{Constant, Enum, Function, Item, ItemContainer, ItemMap};
|
||||
@ -60,6 +61,8 @@ impl Library {
|
||||
|
||||
if self.config.language == Language::C {
|
||||
self.instantiate_monomorphs();
|
||||
|
||||
self.resolve_declaration_types();
|
||||
}
|
||||
|
||||
let mut dependencies = Dependencies::new();
|
||||
@ -266,6 +269,49 @@ impl Library {
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_declaration_types(&mut self) {
|
||||
if self.config.style.generate_typedef() {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut resolver = DeclarationTypeResolver::new();
|
||||
|
||||
self.structs.for_all_items(|x| {
|
||||
x.collect_declaration_types(&mut resolver);
|
||||
});
|
||||
|
||||
self.opaque_items.for_all_items(|x| {
|
||||
x.collect_declaration_types(&mut resolver);
|
||||
});
|
||||
|
||||
self.enums.for_all_items(|x| {
|
||||
x.collect_declaration_types(&mut resolver);
|
||||
});
|
||||
|
||||
self.unions.for_all_items(|x| {
|
||||
x.collect_declaration_types(&mut resolver);
|
||||
});
|
||||
|
||||
self.enums
|
||||
.for_all_items_mut(|x| x.resolve_declaration_types(&resolver));
|
||||
|
||||
self.structs
|
||||
.for_all_items_mut(|x| x.resolve_declaration_types(&resolver));
|
||||
|
||||
self.unions
|
||||
.for_all_items_mut(|x| x.resolve_declaration_types(&resolver));
|
||||
|
||||
self.typedefs
|
||||
.for_all_items_mut(|x| x.resolve_declaration_types(&resolver));
|
||||
|
||||
self.globals
|
||||
.for_all_items_mut(|x| x.resolve_declaration_types(&resolver));
|
||||
|
||||
for item in &mut self.functions {
|
||||
item.resolve_declaration_types(&resolver);
|
||||
}
|
||||
}
|
||||
|
||||
fn simplify_option_to_ptr(&mut self) {
|
||||
self.structs.for_all_items_mut(|x| {
|
||||
x.simplify_option_to_ptr();
|
||||
|
@ -39,6 +39,7 @@ mod builder;
|
||||
mod cargo;
|
||||
mod cdecl;
|
||||
mod config;
|
||||
mod declarationtyperesolver;
|
||||
mod dependencies;
|
||||
mod error;
|
||||
mod ir;
|
||||
|
25
src/main.rs
25
src/main.rs
@ -20,7 +20,7 @@ use clap::{App, Arg, ArgMatches};
|
||||
mod logging;
|
||||
mod bindgen;
|
||||
|
||||
use bindgen::{Bindings, Builder, Cargo, Config, Error, Language};
|
||||
use bindgen::{Bindings, Builder, Cargo, Config, Error, Language, Style};
|
||||
|
||||
fn apply_config_overrides<'a>(config: &mut Config, matches: &ArgMatches<'a>) {
|
||||
// We allow specifying a language to override the config default. This is
|
||||
@ -38,6 +38,21 @@ fn apply_config_overrides<'a>(config: &mut Config, matches: &ArgMatches<'a>) {
|
||||
};
|
||||
}
|
||||
|
||||
if let Some(style) = matches.value_of("style") {
|
||||
config.style = match style {
|
||||
"Both" => Style::Both,
|
||||
"both" => Style::Both,
|
||||
"Tag" => Style::Tag,
|
||||
"tag" => Style::Tag,
|
||||
"Type" => Style::Type,
|
||||
"type" => Style::Type,
|
||||
_ => {
|
||||
error!("Unknown style specified.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if matches.is_present("d") {
|
||||
config.parse.parse_deps = true;
|
||||
}
|
||||
@ -111,6 +126,14 @@ fn main() {
|
||||
.help("Specify the language to output bindings in")
|
||||
.possible_values(&["c++", "C++", "c", "C"]),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("style")
|
||||
.short("s")
|
||||
.long("style")
|
||||
.value_name("STYLE")
|
||||
.help("Specify the declaration style to use for bindings")
|
||||
.possible_values(&["Both", "both", "Tag", "tag", "Type", "type"]),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("d")
|
||||
.short("d")
|
||||
|
Loading…
x
Reference in New Issue
Block a user