diff --git a/generator/src/main.rs b/generator/src/main.rs index c6a74395..25a173ee 100644 --- a/generator/src/main.rs +++ b/generator/src/main.rs @@ -110,6 +110,9 @@ impl Parser { "commands" => { self.parse_commands(); } + "feature" => { + self.parse_feature(); + } "extensions" => { self.parse_extensions(); } @@ -162,6 +165,125 @@ impl Parser { } } + fn parse_feature(&mut self) { + loop { + use XmlEvent::*; + match self.reader.next().expect("failed to parse XML") { + StartElement { name, .. } => match &name.local_name[..] { + "require" => { + self.parse_feature_required(); + } + _ => { + eprintln!("unimplemented feature element: {}", name.local_name); + self.finish_element(); + } + }, + EndElement { name } => { + if name.local_name == "feature" { + break; + } + eprintln!("unexpected end element: {}", name); + } + EndDocument => { + panic!("unexpected end of document"); + } + _ => {} + } + } + } + + fn parse_feature_required(&mut self) { + loop { + use XmlEvent::*; + match self.reader.next().expect("failed to parse XML") { + StartElement { + name, attributes, .. + } => match &name.local_name[..] { + "command" => { + let _name = attr(&attributes, "name").unwrap(); + let _comment = attr(&attributes, "comment"); + self.finish_element(); + } + "enum" => { + let name = attr(&attributes, "name").unwrap(); + if let Some(extends) = attr(&attributes, "extends") { + const EXT_BASE: i32 = 1_000_000_000; + const EXT_BLOCK_SIZE: i32 = 1000; + let ext_number = attr(&attributes, "extnumber") + .unwrap() + .parse::() + .unwrap(); + + let value = if let Some(offset) = attr(&attributes, "offset") { + let offset = offset.parse::().unwrap(); + let sign = if attr(&attributes, "dir").map_or(false, |x| x == "-") { + -1 + } else { + 1 + }; + ConstantValue::Literal( + sign * (EXT_BASE + (ext_number - 1) * EXT_BLOCK_SIZE + offset), + ) + } else if let Some(bitpos) = attr(&attributes, "bitpos") { + ConstantValue::Literal(bitpos.parse::().unwrap()) + } else { + ConstantValue::Alias(attr(&attributes, "alias").unwrap().into()) + }; + let bitmasks = &mut self.bitmasks; + if let Some(e) = self.enums.get_mut(extends) { + e.values.push(Constant { + name: name.into(), + value, + comment: attr(&attributes, "comment").and_then(tidy_comment), + }); + } else if let Some(e) = self + .bitvalues + .get(extends) + .and_then(|x| bitmasks.get_mut(x)) + { + e.values.push(Constant { + name: name.into(), + value: match value { + ConstantValue::Literal(x) => { + ConstantValue::Literal(x as u64) + } + ConstantValue::Alias(x) => ConstantValue::Alias(x), + }, + comment: attr(&attributes, "comment").and_then(tidy_comment), + }); + } else { + eprintln!("extension to unrecognized type {}", extends); + } + } else if let Some(alias) = attr(&attributes, "alias") { + self.api_aliases.push((name.into(), alias.into())); + } else if let Some(value) = attr(&attributes, "value") { + self.api_constants + .push((name.into(), value.parse().unwrap())); + } + self.finish_element(); + } + "type" => { + self.parse_type(&attributes); + } + _ => { + eprintln!("unimplemented feature require element: {}", name.local_name); + self.finish_element(); + } + }, + EndElement { name } => { + if name.local_name == "require" { + break; + } + eprintln!("unexpected end element: {}", name); + } + EndDocument => { + panic!("unexpected end of document"); + } + _ => {} + } + } + } + fn parse_extensions(&mut self) { loop { use XmlEvent::*;