From 1c8de484a4057fbcf162b98456b124689a0442f6 Mon Sep 17 00:00:00 2001 From: Markus Stange Date: Fri, 16 Mar 2018 17:48:24 -0400 Subject: [PATCH] Handle and a few other things. --- src/main.rs | 158 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 96 insertions(+), 62 deletions(-) diff --git a/src/main.rs b/src/main.rs index 2a52901..2754b29 100644 --- a/src/main.rs +++ b/src/main.rs @@ -140,6 +140,7 @@ enum Type<'a> { NonMemberFunction(Params<'a>, StorageClass, Box>), CXXVBTable(NameSequence<'a>, StorageClass), CXXVFTable(NameSequence<'a>, StorageClass), + TemplateParameterWithIndex(i32), Ptr(Box>, StorageClass), Ref(Box>, StorageClass), Array(i32, Box>, 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 { @@ -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> { + 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> { 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> = 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::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");