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
#![allow(non_camel_case_types)]
extern crate libc;
extern crate serde_bytes;
extern crate serde_cbor;
use serde_cbor::{from_slice, Value};
use std::collections::HashMap;
use std::ffi::{CStr, CString};
use std::io::{Error, ErrorKind};
use std::path::Path;
use std::slice;
pub mod clang_ast;
pub fn get_clang_major_version() -> Option<u32> {
let s = unsafe { CStr::from_ptr(clang_version()) };
s.to_str()
.unwrap()
.split('.')
.next()
.unwrap()
.parse::<u32>()
.ok()
}
pub fn get_untyped_ast(
file_path: &Path,
cc_db: &Path,
extra_args: &[&str],
) -> Result<clang_ast::AstContext, Error> {
let cbors = get_ast_cbors(file_path, cc_db, extra_args);
let buffer = cbors.values().next().ok_or(Error::new(
ErrorKind::InvalidData,
"Could not parse input file",
))?;
let items: Value = from_slice(&buffer[..]).unwrap();
match clang_ast::process(items) {
Ok(cxt) => Ok(cxt),
Err(e) => Err(Error::new(ErrorKind::InvalidData, format!("{:}", e))),
}
}
fn get_ast_cbors(file_path: &Path, cc_db: &Path, extra_args: &[&str]) -> HashMap<String, Vec<u8>> {
let mut res = 0;
let mut args_owned = vec![CString::new("ast_exporter").unwrap()];
args_owned.push(CString::new(file_path.to_str().unwrap()).unwrap());
args_owned.push(CString::new("-p").unwrap());
args_owned.push(CString::new(cc_db.to_str().unwrap()).unwrap());
for &arg in extra_args {
args_owned.push(CString::new(["-extra-arg=", arg].join("")).unwrap())
}
let args_ptrs: Vec<*const libc::c_char> = args_owned.iter().map(|x| x.as_ptr()).collect();
let hashmap;
unsafe {
let ptr = ast_exporter(args_ptrs.len() as libc::c_int, args_ptrs.as_ptr(), &mut res);
hashmap = marshal_result(ptr);
drop_export_result(ptr);
}
hashmap
}
include!(concat!(env!("OUT_DIR"), "/cppbindings.rs"));
extern "C" {
#[no_mangle]
fn ast_exporter(
argc: libc::c_int,
argv: *const *const libc::c_char,
res: *mut libc::c_int,
) -> *mut ExportResult;
#[no_mangle]
fn drop_export_result(ptr: *mut ExportResult);
#[no_mangle]
fn clang_version() -> *const libc::c_char;
}
unsafe fn marshal_result(result: *const ExportResult) -> HashMap<String, Vec<u8>> {
let mut output = HashMap::new();
let n = (*result).entries as isize;
for i in 0..n {
let ref res = *result;
let cname = CStr::from_ptr(*res.names.offset(i));
let name = cname.to_str().unwrap().to_owned();
let csize = *res.sizes.offset(i);
let cbytes = *res.bytes.offset(i);
let bytes = slice::from_raw_parts(cbytes, csize);
let mut v = Vec::new();
v.extend_from_slice(bytes);
output.insert(name, v);
}
output
}