1extern crate object;
2
3use object::Object;
4
5mod parser;
6use parser::{ parse, LittleEndian, BigEndian };
7
8use std::collections::BTreeMap;
9use std::fmt;
10use std::fmt::Write;
11
12pub struct Symbols {
13 pub functions: BTreeMap<String, Function>
14}
15
16#[derive(Clone)]
17pub struct Function {
18 pub name: Option<String>,
19 pub typed: Typed,
20 pub parameters: Parameters
21}
22
23#[derive(Clone)]
24pub struct Parameter {
25 pub name: Option<String>,
26 pub typed: Typed
27}
28pub type Parameters = Vec<Parameter>;
29pub type Member = Parameter;
30pub type Members = Vec<Member>;
31
32#[derive(Clone)]
33pub struct Typed {
34 pub name: String,
35 pub value: TypedValue,
36 pub modifiers: Modifiers
37}
38
39#[derive(Clone)]
40#[derive(Debug)]
41pub enum TypedValue {
42 Base,
43 Enum,
44 Typedef(Box<Typed>),
45 Function(Box<Function>),
46 Struct(Members),
47 Union(Members),
48 Array(Box<Typed>, u16),
49 Circular
50}
51
52#[derive(Clone)]
53pub enum Modifier {
54 Pointer,
55 Reference,
56 Const,
57 Volatile,
58 Restrict
59}
60pub type Modifiers = Vec<Modifier>;
61
62impl Symbols {
63 pub fn from(file: object::File) -> Symbols {
64 if file.is_little_endian() {
65 parse::<LittleEndian>(file)
66 } else {
67 parse::<BigEndian>(file)
68 }
69 }
70
71 fn new() -> Symbols {
72 Symbols {
73 functions: BTreeMap::new()
74 }
75 }
76}
77
78impl fmt::Debug for Function {
79 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
80 let typeds = self.parameters.iter().fold(format!("\n{:?}", self.typed), |mut s, p| {
81 let _ = write!(s, "\n{:?}", p);
82 s
83 });
84 write!(f, "{}{}", self, typeds)
85 }
86}
87
88impl fmt::Display for Function {
89 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
90 let parameters = self.parameters.iter().fold(String::new(), |mut s, p| {
92 let _ = if s.is_empty() {
93 write!(s, "{}", p)
94 } else {
95 write!(s, ", {}", p)
96 };
97 s
98 });
99
100 match self.name {
101 Some(ref name) => write!(f, "{} {}({})", name, self.typed, parameters),
102 None => write!(f, "{}({})", self.typed, parameters)
103 }
104 }
105}
106
107impl fmt::Debug for Parameter {
108 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
109 let name = match self.name {
110 Some(ref name) => format!("name: {}\t", name),
111 None => String::new()
112 };
113 write!(f, "{}{:?}", name, self.typed)
114 }
115}
116
117impl fmt::Display for Parameter {
118 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
119 match self.typed.value {
120 TypedValue::Function(ref function) => {
121 let mut function_ptr = (*function).clone();
122 function_ptr.name = Some(match self.name {
123 Some(ref name) => format!("(*{})", name),
124 None => String::from("(*)")
125 });
126 write!(f, "{}", function_ptr)
127 },
128 _ => {
129 match self.name {
130 Some(ref name) => write!(f, "{} {}", self.typed, name),
131 None => write!(f, "{}", self.typed)
132 }
133 }
134 }
135 }
136}
137
138impl fmt::Debug for Typed {
139 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
140 write!(f, "{} {:#?}", self, self.value)
141 }
142}
143
144impl fmt::Display for Typed {
145 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
146 let specifier = self.modifiers.iter().fold(self.name.clone(), |s, m| {
147 match m {
148 &Modifier::Pointer => s + "*",
149 &Modifier::Reference => s + "&",
150 &Modifier::Const => s + " const",
151 &Modifier::Volatile => s + " volatile",
152 &Modifier::Restrict => s + " restrict"
153 }
154 });
155 write!(f, "{}", specifier)
156 }
157}