syscalls: refactor calls chain
authorDmitry Selyutin <ghostmansd@gmail.com>
Mon, 18 Sep 2023 20:24:27 +0000 (23:24 +0300)
committerDmitry Selyutin <ghostmansd@gmail.com>
Mon, 18 Sep 2023 20:24:27 +0000 (23:24 +0300)
src/openpower/syscalls/__init__.py

index abb06db172c92020c6cef4cfb0b6b3331334b953..3879822059ac4fac9b7664cff10412a732f01aff 100644 (file)
@@ -54,44 +54,53 @@ class Dispatcher:
 
         return super().__init__()
 
-    def __getattr__(self, identifier):
-        return functools.partial(self.__call__, identifier)
+    def __getattr__(self, entry):
+        if entry.startswith("compat_sys_"):
+            identifier = entry[len("compat_sys_"):]
+        elif entry.startswith("sys_"):
+            identifier = entry[len("sys_"):]
+        else:
+            raise AttributeError(entry)
+
+        if entry not in self.__parameters:
+            raise AttributeError(entry)
+
+        if identifier not in self.__guest:
+            raise AttributeError(entry)
+        identifier = int(self.__guest[identifier])
+
+        def syscall(identifier, *arguments):
+            parameters = tuple(self.__parameters[entry].items())
+            if len(arguments) != len(parameters):
+                raise ValueError("conflict between arguments and parameters")
 
-    def __call__(self, identifier, *arguments):
-        if isinstance(identifier, int):
             identifier = str(identifier)
-            if identifier not in self.__guest:
-                raise KeyError(identifier)
-            entry = self.__guest[identifier][1][0]
             identifier = self.__guest[identifier][0]
-        else:
-            if not isinstance(identifier, str):
-                raise ValueError(identifier)
-            entry = identifier
-            if not entry.startswith(("compat_sys_", "sys_")):
-                entry = f"sys_{entry}"
-
-        if ((identifier not in self.__guest) or
-                (identifier not in self.__host)):
-            raise KeyError(identifier)
-
-        parameters = tuple(self.__parameters[entry].items())
-        if len(arguments) != len(parameters):
-            raise ValueError("conflict between arguments and parameters")
-
-        guest = int(self.__guest[identifier])
-        host = int(self.__host[identifier])
-        self.__logger(f"{identifier} {guest} => {host}")
-        for index in range(len(arguments)):
-            value = arguments[index]
-            if not isinstance(value, int):
-                raise ValueError("integer argument expected")
-            name = parameters[index][0]
-            ctype = parameters[index][1]
-            self.__logger(f"    0x{value:016x} {name} ({ctype})")
-
-        syscall = self.__libc.syscall
-        syscall.restype = ctypes.c_long
-        syscall.argtypes = ([ctypes.c_long] * len(arguments))
-
-        return int(syscall(ctypes.c_ulong(host)))
+            guest = int(self.__guest[identifier])
+            host = int(self.__host[identifier])
+            self.__logger(f"{identifier} {guest} => {host}")
+            for index in range(len(arguments)):
+                value = arguments[index]
+                if not isinstance(value, int):
+                    raise ValueError("integer argument expected")
+                name = parameters[index][0]
+                ctype = parameters[index][1]
+                self.__logger(f"    0x{value:016x} {name} ({ctype})")
+
+            syscall = self.__libc.syscall
+            syscall.restype = ctypes.c_long
+            syscall.argtypes = ([ctypes.c_long] * len(arguments))
+
+            return int(syscall(ctypes.c_ulong(host)))
+
+        return functools.partial(syscall, identifier)
+
+    def __call__(self, identifier, *arguments):
+        if not isinstance(identifier, int):
+            raise ValueError(identifier)
+
+        identifier = str(identifier)
+        entry = self.__guest[identifier][1][0]
+        syscall = getattr(self, entry)
+
+        return syscall(*arguments)