diff --git a/generator/src/main.rs b/generator/src/main.rs index 8012ebe5..999d534e 100644 --- a/generator/src/main.rs +++ b/generator/src/main.rs @@ -171,7 +171,7 @@ impl Parser { match self.reader.next().expect("failed to parse XML") { StartElement { name, .. } => match &name.local_name[..] { "require" => { - self.parse_feature_required(); + self.parse_required(None, None); } _ => { eprintln!("unimplemented feature element: {}", name.local_name); @@ -192,7 +192,85 @@ impl Parser { } } - fn parse_feature_required(&mut self) { + fn parse_extensions(&mut self) { + loop { + use XmlEvent::*; + match self.reader.next().expect("failed to parse XML") { + StartElement { + name, attributes, .. + } => match &name.local_name[..] { + "extension" => { + if let StartElement { name, .. } = + self.reader.next().expect("failed to parse XML") + { + if name.local_name == "require" { + self.parse_extension_required(&attributes); + } else { + eprintln!("unexpected extension element: {}", name.local_name); + } + } else { + eprintln!("unexpected extension event"); + } + self.finish_element(); + } + _ => { + eprintln!("unimplemented extensions element: {}", name.local_name); + self.finish_element(); + } + }, + EndElement { name } => { + if name.local_name == "extensions" { + break; + } + eprintln!("unexpected end element: {}", name); + } + EndDocument => { + panic!("unexpected end of document"); + } + _ => {} + } + } + } + + fn parse_extension_required(&mut self, attrs: &[OwnedAttribute]) { + let ext_name = Rc::::from(attr(attrs, "name").unwrap()); + let ext_number = attr(attrs, "number").unwrap().parse::().unwrap(); + let (ext_version, commands) = self.parse_required(Some(&ext_name), Some(ext_number)); + if attr(attrs, "supported").map_or(false, |x| x == "disabled") { + self.disabled_exts.insert(ext_name); + } else { + let provisional = attr(attrs, "provisional").map_or(false, |x| x == "true"); + + let (tag_name, _) = split_ext_tag(&ext_name); + let ext = Extension { + name: ext_name.clone(), + version: ext_version.unwrap(), + commands, + }; + + if let Some(tag) = self.extensions.get_mut(tag_name) { + tag.extensions.push(ext); + } else if provisional { + self.extensions.insert( + tag_name.into(), + Tag { + extensions: vec![ext], + }, + ); + } else { + eprintln!("ignoring extension with unlisted tag: {}", ext_name); + } + } + } + + fn parse_required( + &mut self, + ext_name: Option<&Rc>, + ext_number: Option, + ) -> (Option, Vec) { + assert_eq!(ext_name.is_some(), ext_number.is_some()); + let mut ext_version = None; + let mut commands = Vec::new(); loop { use XmlEvent::*; match self.reader.next().expect("failed to parse XML") { @@ -200,8 +278,13 @@ impl Parser { name, attributes, .. } => match &name.local_name[..] { "command" => { - let _name = attr(&attributes, "name").unwrap(); - let _comment = attr(&attributes, "comment"); + let cmd = attr(&attributes, "name").unwrap(); + if let Some(ext_name) = ext_name { + if let Some(command) = self.commands.get_mut(cmd) { + command.extension = Some(ext_name.clone()); + } + } + commands.push(cmd.into()); self.finish_element(); } "enum" => { @@ -209,10 +292,12 @@ impl Parser { 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 ext_number = ext_number.unwrap_or_else(|| { + attr(&attributes, "extnumber") + .unwrap() + .parse::() + .unwrap() + }); let value = if let Some(offset) = attr(&attributes, "offset") { let offset = offset.parse::().unwrap(); @@ -256,6 +341,12 @@ impl Parser { } } else if let Some(alias) = attr(&attributes, "alias") { self.api_aliases.push((name.into(), alias.into())); + } else if name.ends_with("SPEC_VERSION") { + let value = attr(&attributes, "value").unwrap(); + ext_version = Some(value.parse().unwrap()); + } else if name.ends_with("EXTENSION_NAME") { + let value = attr(&attributes, "value").unwrap(); + assert_eq!(&ext_name.unwrap()[..], &value[1..value.len() - 1]); } else if let Some(value) = attr(&attributes, "value") { self.api_constants .push((name.into(), value.parse().unwrap())); @@ -263,163 +354,21 @@ impl Parser { 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::*; - match self.reader.next().expect("failed to parse XML") { - StartElement { - name, attributes, .. - } => match &name.local_name[..] { - "extension" => { - if let StartElement { name, .. } = - self.reader.next().expect("failed to parse XML") - { - if name.local_name == "require" { - self.parse_extension_required(&attributes); - } else { - eprintln!("unexpected extension element: {}", name.local_name); + if let Some(ext_name) = ext_name { + let ty = attr(&attributes, "name").unwrap(); + if let Some(s) = self.structs.get_mut(ty) { + s.extension = Some(ext_name.clone()); } + self.finish_element(); } else { - eprintln!("unexpected extension event"); + self.parse_type(&attributes); } - self.finish_element(); } _ => { - eprintln!("unimplemented extensions element: {}", name.local_name); + eprintln!("unimplemented require element: {}", name.local_name); self.finish_element(); } }, - EndElement { name } => { - if name.local_name == "extensions" { - break; - } - eprintln!("unexpected end element: {}", name); - } - EndDocument => { - panic!("unexpected end of document"); - } - _ => {} - } - } - } - - fn parse_extension_required(&mut self, attrs: &[OwnedAttribute]) { - let ext_name = Rc::::from(attr(attrs, "name").unwrap()); - let ext_number = attr(attrs, "number").unwrap().parse::().unwrap(); - let mut ext_version = None; - let mut commands = Vec::new(); - loop { - use XmlEvent::*; - match self.reader.next().expect("failed to parse XML") { - StartElement { - name, attributes, .. - } => { - match &name.local_name[..] { - "command" => { - let cmd = attr(&attributes, "name").unwrap(); - if let Some(command) = self.commands.get_mut(cmd) { - command.extension = Some(ext_name.clone()); - } - commands.push(cmd.into()); - } - "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 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 name.ends_with("SPEC_VERSION") { - let value = attr(&attributes, "value").unwrap(); - ext_version = Some(value.parse().unwrap()); - } else if name.ends_with("EXTENSION_NAME") { - let value = attr(&attributes, "value").unwrap(); - assert_eq!(&ext_name[..], &value[1..value.len() - 1]); - } else { - let value = attr(&attributes, "value").unwrap(); - self.api_constants - .push((name.into(), value.parse().unwrap())); - } - } - "type" => { - let ty = attr(&attributes, "name").unwrap(); - if let Some(s) = self.structs.get_mut(ty) { - s.extension = Some(ext_name.clone()); - } - } - _ => { - eprintln!("unimplemented extension element: {}", name.local_name); - } - } - self.finish_element(); - } EndElement { name } => { if name.local_name == "require" { break; @@ -432,31 +381,7 @@ impl Parser { _ => {} } } - if attr(attrs, "supported").map_or(false, |x| x == "disabled") { - self.disabled_exts.insert(ext_name); - } else { - let provisional = attr(attrs, "provisional").map_or(false, |x| x == "true"); - - let (tag_name, _) = split_ext_tag(&ext_name); - let ext = Extension { - name: ext_name.clone(), - version: ext_version.unwrap(), - commands, - }; - - if let Some(tag) = self.extensions.get_mut(tag_name) { - tag.extensions.push(ext); - } else if provisional { - self.extensions.insert( - tag_name.into(), - Tag { - extensions: vec![ext], - }, - ); - } else { - eprintln!("ignoring extension with unlisted tag: {}", ext_name); - } - } + (ext_version, commands) } fn parse_commands(&mut self) {