mirror of
https://github.com/encounter/msvc-demangler-rust.git
synced 2026-07-10 12:18:38 -07:00
Handle and a few other things.
This commit is contained in:
+96
-62
@@ -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 *>");
|
||||
|
||||
Reference in New Issue
Block a user