Commit 60d95258 authored by Ryan Hunt's avatar Ryan Hunt

Add item renaming, prefixing, force including, and excluding

parent 1ae43fea
......@@ -97,6 +97,19 @@ exclude = ["libc"]
# parsing to expand any macros
expand = ["euclid"]
[export]
# A list of additional items not used by exported functions to include in
# the generated bindings
include = ["Foo", "Bar"]
# A list of items to not include in the generated bindings
exclude = ["Bad"]
# A prefix to add before the name of every item
prefix = "CAPI_"
# Table of name conversions to apply to item names
[export.rename]
"Struct" = "CAPI_Struct"
[fn]
# An optional prefix to put before every function declaration
prefix = "string"
......
......@@ -115,6 +115,30 @@ impl Builder {
self
}
#[allow(unused)]
pub fn include_item<S: AsRef<str>>(mut self, item_name: S) -> Builder {
self.config.export.include.push(String::from(item_name.as_ref()));
self
}
#[allow(unused)]
pub fn exclude_item<S: AsRef<str>>(mut self, item_name: S) -> Builder {
self.config.export.exclude.push(String::from(item_name.as_ref()));
self
}
#[allow(unused)]
pub fn rename_item<S: AsRef<str>>(mut self, from: S, to: S) -> Builder {
self.config.export.rename.insert(String::from(from.as_ref()), String::from(to.as_ref()));
self
}
#[allow(unused)]
pub fn with_item_prefix<S: AsRef<str>>(mut self, prefix: S) -> Builder {
self.config.export.prefix = Some(String::from(prefix.as_ref()));
self
}
#[allow(unused)]
pub fn with_parse_deps(mut self, parse_deps: bool) -> Builder {
self.config.parse.parse_deps = parse_deps;
......
......@@ -95,6 +95,45 @@ impl FromStr for Layout {
deserialize_enum_str!(Layout);
/// Settings to apply when exporting items.
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "snake_case")]
#[serde(deny_unknown_fields)]
#[serde(default)]
pub struct ExportConfig {
/// A list of additional items not used by exported functions to include in
/// the generated bindings
pub include: Vec<String>,
/// A list of items to not include in the generated bindings
pub exclude: Vec<String>,
/// Table of name conversions to apply to item names
pub rename: HashMap<String, String>,
/// A prefix to add before the name of every item
pub prefix: Option<String>,
}
impl Default for ExportConfig {
fn default() -> ExportConfig {
ExportConfig {
include: Vec::new(),
exclude: Vec::new(),
rename: HashMap::new(),
prefix: None,
}
}
}
impl ExportConfig {
pub(crate) fn rename(&self, item_name: &mut String) {
if let Some(name) = self.rename.get(item_name) {
*item_name = name.clone();
}
if let Some(ref prefix) = self.prefix {
item_name.insert_str(0, &prefix);
}
}
}
/// Settings to apply to generated functions.
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "snake_case")]
......@@ -333,6 +372,8 @@ pub struct Config {
pub language: Language,
/// The configuration options for parsing
pub parse: ParseConfig,
/// The configuration options for exporting
pub export: ExportConfig,
/// The configuration options for functions
#[serde(rename = "fn")]
pub function: FunctionConfig,
......@@ -368,6 +409,7 @@ impl Default for Config {
tab_width: 2,
language: Language::Cxx,
parse: ParseConfig::default(),
export: ExportConfig::default(),
function: FunctionConfig::default(),
structure: StructConfig::default(),
enumeration: EnumConfig::default(),
......
......@@ -110,6 +110,10 @@ impl Item for Constant {
fn container(&self) -> ItemContainer {
ItemContainer::Constant(self.clone())
}
fn rename_for_config(&mut self, config: &Config) {
config.export.rename(&mut self.name);
}
}
impl Source for Constant {
......
......@@ -109,6 +109,8 @@ impl Item for Enum {
}
fn rename_for_config(&mut self, config: &Config) {
config.export.rename(&mut self.name);
if config.language == Language::C
&& (config.enumeration.prefix_with_name
|| self.annotations.bool("prefix-with-name").unwrap_or(false))
......
......@@ -78,6 +78,11 @@ impl Function {
}
pub fn rename_for_config(&mut self, config: &Config) {
self.ret.rename_for_config(config);
for &mut (_, ref mut ty) in &mut self.args {
ty.rename_for_config(config);
}
let rules = [
self.annotations.parse_atom::<RenameRule>("rename-all"),
config.function.rename_args,
......
......@@ -75,6 +75,10 @@ impl Item for Static {
ItemContainer::Static(self.clone())
}
fn rename_for_config(&mut self, config: &Config) {
self.ty.rename_for_config(config);
}
fn add_dependencies(&self, library: &Library, out: &mut Dependencies) {
self.ty.add_dependencies(library, out);
}
......
......@@ -76,6 +76,11 @@ impl<T: Item + Clone> ItemMap<T> {
}
}
pub fn rebuild(&mut self) {
let old = mem::replace(self, ItemMap::new());
old.for_all_items(|x| { self.try_insert(x.clone()); });
}
pub fn try_insert(&mut self, item: T) -> bool {
match (item.cfg().is_some(), self.data.get_mut(item.name())) {
(true, Some(&mut ItemValue::Cfg(ref mut items))) => {
......
......@@ -62,6 +62,10 @@ impl Item for OpaqueItem {
ItemContainer::OpaqueItem(self.clone())
}
fn rename_for_config(&mut self, config: &Config) {
config.export.rename(&mut self.name);
}
fn add_dependencies(&self, _: &Library, _: &mut Dependencies) {}
fn instantiate_monomorph(
......
......@@ -121,7 +121,12 @@ impl Item for Struct {
}
fn rename_for_config(&mut self, config: &Config) {
let rules = [
config.export.rename(&mut self.name);
for &mut (_, ref mut ty, _) in &mut self.fields {
ty.rename_for_config(config);
}
let field_rules = [
self.annotations.parse_atom::<RenameRule>("rename-all"),
config.structure.rename_fields,
];
......@@ -138,7 +143,7 @@ impl Item for Struct {
}
self.fields = overriden_fields;
} else if let Some(r) = find_first_some(&rules) {
} else if let Some(r) = find_first_some(&field_rules) {
self.fields = self.fields
.iter()
.map(|x| {
......
......@@ -443,6 +443,33 @@ impl Type {
}
}
pub fn rename_for_config(&mut self, config: &Config) {
match self {
&mut Type::ConstPtr(ref mut ty) => {
ty.rename_for_config(config);
}
&mut Type::Ptr(ref mut ty) => {
ty.rename_for_config(config);
}
&mut Type::Path(ref mut path) => {
for generic in &mut path.generics {
generic.rename_for_config(config);
}
config.export.rename(&mut path.name);
}
&mut Type::Primitive(_) => {}
&mut Type::Array(ref mut ty, _) => {
ty.rename_for_config(config);
}
&mut Type::FuncPtr(ref mut ret, ref mut args) => {
ret.rename_for_config(config);
for arg in args {
arg.rename_for_config(config);
}
}
}
}
pub fn mangle_paths(&mut self, monomorphs: &Monomorphs) {
match self {
&mut Type::ConstPtr(ref mut ty) => {
......
......@@ -115,6 +115,11 @@ impl Item for Typedef {
ItemContainer::Typedef(self.clone())
}
fn rename_for_config(&mut self, config: &Config) {
config.export.rename(&mut self.name);
self.aliased.rename_for_config(config);
}
fn add_dependencies(&self, library: &Library, out: &mut Dependencies) {
self.aliased
.add_dependencies_ignoring_generics(&self.generic_params, library, out);
......
......@@ -122,6 +122,11 @@ impl Item for Union {
}
fn rename_for_config(&mut self, config: &Config) {
config.export.rename(&mut self.name);
for &mut (_, ref mut ty, _) in &mut self.fields {
ty.rename_for_config(config);
}
let rules = [
self.annotations.parse_atom::<RenameRule>("rename-all"),
config.structure.rename_fields,
......
......@@ -52,8 +52,8 @@ impl Library {
}
pub fn generate(mut self) -> Result<Bindings, Error> {
self.remove_excluded();
self.functions.sort_by(|x, y| x.name.cmp(&y.name));
self.transfer_annotations();
self.rename_items();
self.simplify_option_to_ptr();
......@@ -70,6 +70,20 @@ impl Library {
self.globals.for_all_items(|global| {
global.add_dependencies(&self, &mut dependencies);
});
for name in &self.config.export.include {
if let Some(items) = self.get_items(name) {
if !dependencies.items.contains(name) {
dependencies.items.insert(name.clone());
for item in &items {
item.deref().add_dependencies(&self, &mut dependencies);
}
for item in items {
dependencies.order.push(item);
}
}
}
}
dependencies.sort();
......@@ -107,6 +121,18 @@ impl Library {
None
}
fn remove_excluded(&mut self) {
let config = &self.config;
self.functions.retain(|x| !config.export.exclude.contains(&x.name));
self.enums.filter(|x| config.export.exclude.contains(&x.name));
self.structs.filter(|x| config.export.exclude.contains(&x.name));
self.unions.filter(|x| config.export.exclude.contains(&x.name));
self.opaque_items.filter(|x| config.export.exclude.contains(&x.name));
self.typedefs.filter(|x| config.export.exclude.contains(&x.name));
self.globals.filter(|x| config.export.exclude.contains(&x.name));
self.constants.filter(|x| config.export.exclude.contains(&x.name));
}
fn transfer_annotations(&mut self) {
let mut annotations = HashMap::new();
......@@ -198,12 +224,34 @@ impl Library {
fn rename_items(&mut self) {
let config = &self.config;
self.globals
.for_all_items_mut(|x| x.rename_for_config(config));
self.globals.rebuild();
self.constants
.for_all_items_mut(|x| x.rename_for_config(config));
self.constants.rebuild();
self.structs
.for_all_items_mut(|x| x.rename_for_config(config));
self.structs.rebuild();
self.unions
.for_all_items_mut(|x| x.rename_for_config(config));
self.unions.rebuild();
self.enums
.for_all_items_mut(|x| x.rename_for_config(config));
self.enums.rebuild();
self.opaque_items
.for_all_items_mut(|x| x.rename_for_config(config));
self.opaque_items.rebuild();
self.typedefs
.for_all_items_mut(|x| x.rename_for_config(config));
self.typedefs.rebuild();
for item in &mut self.functions {
item.rename_for_config(&self.config);
......
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct {
int32_t x;
float y;
} A;
typedef struct {
A data;
} B;
#include <cstdint>
#include <cstdlib>
struct A {
int32_t x;
float y;
};
struct B {
A data;
};
extern "C" {
} // extern "C"
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#define C_H 10
enum C_E {
x = 0,
y = 1,
};
typedef uint8_t C_E;
typedef struct C_A C_A;
typedef struct C_C C_C;
typedef struct {
int32_t x;
float y;
} C_AwesomeB;
typedef union {
int32_t x;
float y;
} C_D;
typedef C_A C_F;
extern const int32_t G;
void root(const C_A *a, C_AwesomeB b, C_C c, C_D d, C_E e, C_F f);
#include <cstdint>
#include <cstdlib>
static const int32_t C_H = 10;
enum class C_E : uint8_t {
x = 0,
y = 1,
};
struct C_A;
struct C_C;
struct C_AwesomeB {
int32_t x;
float y;
};
union C_D {
int32_t x;
float y;
};
using C_F = C_A;
extern "C" {
extern const int32_t G;
void root(const C_A *a, C_AwesomeB b, C_C c, C_D d, C_E e, C_F f);
} // extern "C"
#[repr(C)]
struct A {
x: i32,
y: f32,
}
#[repr(C)]
struct B {
data: A,
}
[export]
include = ["B"]
struct A {
x: i32,
y: f32,
}
#[repr(C)]
struct B {
x: i32,
y: f32,
}
union C {
x: i32,
y: f32,
}
#[repr(C)]
union D {
x: i32,
y: f32,
}
#[repr(u8)]
enum E {
x = 0,
y = 1,
}
type F = A;
#[no_mangle]
pub static G: i32 = 10;
const H: i32 = 10;
#[no_mangle]
pub extern "C" fn root(
a: *const A,
b: B,
c: C,
d: D,
e: E,
f: F,
) { }
[export]
prefix = "C_"
[export.rename]
"B" = "AwesomeB"
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment