浏览代码

Add def_alias, alias shares handle with target (#153)

rw-vanc 2 年之前
父节点
当前提交
b48a085040
共有 3 个文件被更改,包括 72 次插入1 次删除
  1. 47 0
      aml/src/namespace.rs
  2. 1 0
      aml/src/opcode.rs
  3. 24 1
      aml/src/term_object.rs

+ 47 - 0
aml/src/namespace.rs

@@ -157,6 +157,26 @@ impl Namespace {
         self.add_value(path.resolve(scope)?, value)
     }
 
+    /// Add an alias for an existing name. The alias will refer to the same value as the original,
+    /// and the fact that the alias exists is forgotten.
+    pub fn add_alias_at_resolved_path(
+        &mut self,
+        path: AmlName,
+        scope: &AmlName,
+        target: AmlName
+    ) -> Result<AmlHandle, AmlError> {
+        let path = path.resolve(scope)?;
+        let target = target.resolve(scope)?;
+
+        let handle = self.get_handle(&target)?;
+        
+        let (level, last_seg) = self.get_level_for_path_mut(&path)?;
+        match level.values.insert(last_seg, handle) {
+            None => Ok(handle),
+            Some(_) => Err(AmlError::NameCollision(path)),
+        }
+    }
+
     pub fn get(&self, handle: AmlHandle) -> Result<&AmlValue, AmlError> {
         Ok(self.object_map.get(&handle).unwrap())
     }
@@ -722,6 +742,33 @@ mod tests {
         }
     }
 
+    #[test]
+    fn test_alias() {
+        let mut namespace = Namespace::new();
+
+        assert_eq!(namespace.add_level((AmlName::from_str("\\FOO")).unwrap(), LevelType::Scope), Ok(()));
+
+        assert!(
+            namespace.add_value_at_resolved_path(
+            AmlName::from_str("BAR").unwrap(),
+            &AmlName::from_str("\\FOO").unwrap(),
+            AmlValue::Integer(100))
+            .is_ok()
+        );
+        assert!(
+            namespace.add_alias_at_resolved_path(
+                AmlName::from_str("BARA").unwrap(),
+                &AmlName::from_str("\\FOO").unwrap(),
+                AmlName::from_str("BAR").unwrap())
+                .is_ok()
+        );
+        assert!(namespace.get_by_path(&AmlName::from_str("\\FOO.BARA").unwrap()).is_ok());
+        assert_eq!(
+            namespace.get_handle(&AmlName::from_str("\\FOO.BARA").unwrap()),
+            namespace.get_handle(&AmlName::from_str("\\FOO.BAR").unwrap())
+        );
+    }
+
     #[test]
     fn test_get_level_for_path() {
         let mut namespace = Namespace::new();

+ 1 - 0
aml/src/opcode.rs

@@ -20,6 +20,7 @@ pub const DWORD_CONST: u8 = 0x0c;
 pub const STRING_PREFIX: u8 = 0x0d;
 pub const QWORD_CONST: u8 = 0x0e;
 
+pub const DEF_ALIAS_OP: u8 = 0x06;
 pub const DEF_NAME_OP: u8 = 0x08;
 pub const DEF_SCOPE_OP: u8 = 0x10;
 pub const DEF_BUFFER_OP: u8 = 0x11;

+ 24 - 1
aml/src/term_object.rs

@@ -77,7 +77,7 @@ where
     /*
      * NamespaceModifierObj := DefAlias | DefName | DefScope
      */
-    choice!(def_name(), def_scope())
+    choice!(def_alias(), def_name(), def_scope())
 }
 
 pub fn named_obj<'a, 'c>() -> impl Parser<'a, 'c, ()>
@@ -137,6 +137,29 @@ where
         .discard_result()
 }
 
+pub fn def_alias<'a, 'c>() -> impl Parser<'a, 'c, ()>
+where
+    'c: 'a,
+{
+    /*
+     * DefAlias := 0x06 NameString NameString
+     * The second name refers to the same object as the first
+     */
+    opcode(opcode::DEF_ALIAS_OP)
+        .then(comment_scope(
+            DebugVerbosity::Scopes,
+            "DefAlias",
+            name_string().then(name_string()).map_with_context(|(target, alias), context| {
+                try_with_context!(
+                    context,
+                    context.namespace.add_alias_at_resolved_path(alias, &context.current_scope, target)
+                );
+                (Ok(()), context)
+            }),
+        ))
+        .discard_result()
+}
+
 pub fn def_scope<'a, 'c>() -> impl Parser<'a, 'c, ()>
 where
     'c: 'a,