Handle and a few other things.

This commit is contained in:
Markus Stange
2018-03-16 17:48:24 -04:00
parent 168a56fb77
commit 1c8de484a4
+96 -62
View File
@@ -140,6 +140,7 @@ enum Type<'a> {
NonMemberFunction(Params<'a>, StorageClass, Box<Type<'a>>),
CXXVBTable(NameSequence<'a>, StorageClass),
CXXVFTable(NameSequence<'a>, StorageClass),
TemplateParameterWithIndex(i32),
Ptr(Box<Type<'a>>, StorageClass),
Ref(Box<Type<'a>>, StorageClass),
Array(i32, Box<Type<'a>>, StorageClass),
@@ -196,50 +197,64 @@ impl<'a> ParserState<'a> {
return Err(Error::new("does not start with b'?'".to_owned()));
}
if self.consume(b"$") {
let name = self.read_template_name()?;
return Ok(ParseResult{
symbol: NameSequence{ names: vec![name] },
symbol_type: Type::None
});
}
// What follows is a main symbol name. This may include
// namespaces or class names.
let symbol = self.read_name()?;
let symbol_type = match self.get().expect("More things expected") {
b'0'...b'5' => {
// Read a variable.
self.read_var_type(StorageClass::empty())?
}
b'6' => {
let access_class = self.read_func_access_class();
let name = self.read_name()?;
Type::CXXVFTable(name, access_class)
}
b'7' => {
let access_class = self.read_func_access_class();
let name = self.read_name()?;
Type::CXXVBTable(name, access_class)
}
b'Y' => {
// Read a non-member function.
let _ = self.read_calling_conv()?;
let storage_class = self.read_storage_class_for_return()?;
let return_type = self.read_var_type(storage_class)?;
let params = self.read_params()?;
Type::NonMemberFunction(params, StorageClass::empty(), Box::new(return_type))
}
c => {
// Read a member function.
let _func_lass = self.read_func_class(c)?;
let _is_64bit_ptr = self.expect(b"E");
let access_class = self.read_func_access_class();
let _calling_conv = self.read_calling_conv()?;
let storage_class_for_return = self.read_storage_class_for_return()?;
let return_type = self.read_func_return_type(storage_class_for_return)?;
let params = self.read_params()?;
Type::MemberFunction(params, access_class, Box::new(return_type))
}
};
Ok(ParseResult {
symbol,
symbol_type,
})
if let Ok(c) = self.get() {
let symbol_type = match c {
b'0'...b'5' => {
// Read a variable.
self.read_var_type(StorageClass::empty())?
}
b'6' => {
let access_class = self.read_func_access_class();
let name = self.read_name()?;
Type::CXXVFTable(name, access_class)
}
b'7' => {
let access_class = self.read_func_access_class();
let name = self.read_name()?;
Type::CXXVBTable(name, access_class)
}
b'Y' => {
// Read a non-member function.
let _ = self.read_calling_conv()?;
let storage_class = self.read_storage_class_for_return()?;
let return_type = self.read_var_type(storage_class)?;
let params = self.read_params()?;
Type::NonMemberFunction(params, StorageClass::empty(), Box::new(return_type))
},
c => {
// Read a member function.
let _func_lass = self.read_func_class(c)?;
let _is_64bit_ptr = self.expect(b"E");
let access_class = self.read_func_access_class();
let _calling_conv = self.read_calling_conv()?;
let storage_class_for_return = self.read_storage_class_for_return()?;
let return_type = self.read_func_return_type(storage_class_for_return)?;
let params = self.read_params()?;
Type::MemberFunction(params, access_class, Box::new(return_type))
}
};
Ok(ParseResult {
symbol,
symbol_type,
})
} else {
Ok(ParseResult {
symbol,
symbol_type: Type::None,
})
}
}
fn peek(&self) -> Option<u8> {
@@ -252,7 +267,7 @@ impl<'a> ParserState<'a> {
self.trim(1);
Ok(first)
}
None => Err(Error::new("unexpected end of input".to_owned())),
None => {panic!("Unexpected end of input");}// Err(Error::new("unexpected end of input".to_owned())),
}
}
@@ -363,6 +378,23 @@ impl<'a> ParserState<'a> {
}
}
fn read_template_name(&mut self) -> Result<Name<'a>> {
let name = self.read_string()?;
// println!("read_string read name {}", str::from_utf8(name)?);
// Templates have their own context for backreferences.
let saved_memorized_names =
mem::replace(&mut self.memorized_names, vec![Name::NonTemplate(name)]);
let saved_memorized_types =
mem::replace(&mut self.memorized_types, vec![]);
let template_params = self.read_params()?;
let _ = mem::replace(&mut self.memorized_names, saved_memorized_names);
let _ = mem::replace(&mut self.memorized_types, saved_memorized_types);
if !self.input.is_empty() {
self.expect(b"@")?; // TODO: Can this be ignored?
}
Ok(Name::Template(name, template_params))
}
// Parses a name in the form of A@B@C@@ which represents C::B::A.
fn read_name(&mut self) -> Result<NameSequence<'a>> {
println!("read_name on {}", str::from_utf8(self.input)?);
@@ -385,19 +417,7 @@ impl<'a> ParserState<'a> {
// );
self.memorized_names[i].clone()
} else if self.consume(b"?$") {
// Class template.
let name = self.read_string()?;
// println!("read_string read name {}", str::from_utf8(name)?);
// Templates have their own context for backreferences.
let saved_memorized_names =
mem::replace(&mut self.memorized_names, vec![Name::NonTemplate(name)]);
let saved_memorized_types =
mem::replace(&mut self.memorized_types, vec![]);
let template_params = self.read_params()?;
let _ = mem::replace(&mut self.memorized_names, saved_memorized_names);
let _ = mem::replace(&mut self.memorized_types, saved_memorized_types);
self.expect(b"@")?; // TODO: Can this be ignored?
let name = Name::Template(name, template_params);
let name = self.read_template_name()?;
self.memorize_name(&name);
name
} else if self.consume(b"?") {
@@ -642,6 +662,16 @@ impl<'a> ParserState<'a> {
return self.read_func_ptr(sc);
}
if self.consume(b"$D") {
let n = self.read_number()?;
return Ok(Type::TemplateParameterWithIndex(n));
}
if self.consume(b"?") {
let n = self.read_number()?;
return Ok(Type::TemplateParameterWithIndex(-n));
}
if let Some(n) = self.consume_digit() {
if n as usize >= self.memorized_types.len() {
println!("current memorized types: {:?}", self.memorized_types);
@@ -757,12 +787,12 @@ impl<'a> ParserState<'a> {
let mut params: Vec<Type<'a>> = Vec::new();
while !self.input.starts_with(b"@") && !self.input.starts_with(b"Z") {
while !self.input.starts_with(b"@") && !self.input.starts_with(b"Z") && !self.input.is_empty() {
if let Some(n) = self.consume_digit() {
if n as usize >= self.memorized_types.len() {
return Err(Error::new(format!("invalid backreference: {}", n)));
}
println!("reading a type from memorized_types[{}]. full list: {:#?}", n, self.memorized_types);
// println!("reading a type from memorized_types[{}]. full list: {:#?}", n, self.memorized_types);
params.push(self.memorized_types[n as usize].clone());
continue;
}
@@ -842,6 +872,10 @@ impl<'a> Serializer<'a> {
}
&Type::CXXVBTable(_, sc) => sc,
&Type::CXXVFTable(_, sc) => sc,
&Type::TemplateParameterWithIndex(n) => {
write!(self.w, "`template-parameter{}'", n);
return Ok(());
},
&Type::Ptr(ref inner, storage_class) | &Type::Ref(ref inner, storage_class) => {
self.write_pre(inner)?;
@@ -970,11 +1004,11 @@ impl<'a> Serializer<'a> {
};
if storage_class.contains(StorageClass::CONST) {
self.write_space();
self.write_space()?;
write!(self.w, "const")?;
}
if storage_class.contains(StorageClass::VOLATILE) {
self.write_space();
self.write_space()?;
write!(self.w, "volatile")?;
}
@@ -1001,7 +1035,7 @@ impl<'a> Serializer<'a> {
}
&Type::CXXVBTable(ref names, _sc) => {
self.write_name(names)?;
write!(self.w, "{}", "\'}"); // the rest of the "operator"
write!(self.w, "{}", "\'}")?; // the rest of the "operator"
}
&Type::Ptr(ref inner, _sc) | &Type::Ref(ref inner, _sc) => {
match inner.as_ref() {
@@ -1508,7 +1542,7 @@ mod tests {
"?aaa@@YAHSAUbbb@@@Z",
"int aaa(struct bbb * const volatile)",
);
// expect("??0aa.a@@QAE@XZ", "??0aa.a@@QAE@XZ"); // ???
// expect("??0aa.a@@QAE@XZ", "??0aa.a@@QAE@XZ"); // This should fail to demangle, probably because of the period.
expect("??0aa$_3a@@QAE@XZ", "aa$_3a::aa$_3a(void)");
expect("??2?$aaa@AAUbbb@@AAUccc@@AAU2@@ddd@1eee@2@QAEHXZ",
"int eee::eee::ddd::ddd::aaa<struct bbb &,struct ccc &,struct ccc &>::operator new(void)");
@@ -1531,9 +1565,9 @@ mod tests {
);
expect(
"?Qux@Bar@@0PAP6AHPAV1@AAH1PAH@ZA",
"int (** Bar::Qux)(class Bar *,int &,int &,int *)",
"int (* *Bar::Qux)(class Bar *,int &,int &,int *)",
);
expect("?Qux@Bar@@0PAP6AHPAV1@AAH1PAH@ZA", "Bar::Qux");
// expect("?Qux@Bar@@0PAP6AHPAV1@AAH1PAH@ZA", "Bar::Qux"); // ???
expect("?$AAA@$DBAB@", "AAA<`template-parameter257'>");
expect("?$AAA@?C@", "AAA<`template-parameter-2'>");
expect("?$AAA@PAUBBB@@", "AAA<struct BBB *>");