syscalls: support generic system calls
authorDmitry Selyutin <ghostmansd@gmail.com>
Wed, 20 Sep 2023 22:44:31 +0000 (01:44 +0300)
committerDmitry Selyutin <ghostmansd@gmail.com>
Wed, 20 Sep 2023 22:44:31 +0000 (01:44 +0300)
src/openpower/syscalls/__main__.py

index 716c9c0d417c42d12b645a842210976262cdd54f..0375d36fdcb1b244a287bf79d67fb1eb28e4c462 100644 (file)
@@ -7,9 +7,83 @@ import re
 
 
 def collect_sysnums(tree):
+    whitespace = re.compile(r"\s+")
+
+    number = r"[0-9]+"
+    name = r"[A-Za-z0-9_]+"
+    identifier = rf"__NR(?:3264)?_{name}"
+
+    def transform(macro_nr_args):
+        (macro, nr_args) = macro_nr_args
+        args = r",\s*\\*\s*".join([f"({name})"] * nr_args)
+        return rf"(?:({macro})\(({identifier}),\s*\\*\s*{args}\))"
+
+    pattern0 = re.compile(rf"^#define\s+({identifier})\s+({number})$", re.M)
+    pattern1 = re.compile("|".join(map(transform, {
+        "__SC_COMP_3264": 3,
+        "__SC_3264": 2,
+        "__SC_COMP": 2,
+        "__SYSCALL": 1,
+    }.items())))
+
+    path = (tree / "include/uapi/asm-generic/unistd.h")
+    with open(path, mode="r", encoding="UTF-8") as stream:
+        identifiers = {}
+        data = stream.read()
+
+        for match in pattern0.finditer(data):
+            identifier = match.group(1)
+            number = int(match.group(2))
+            identifiers[identifier] = number
+
+        for match in pattern1.finditer(data):
+            groups = (group for group in match.groups() if group is not None)
+            (category, identifier, *entries) = groups
+            number = identifiers[identifier]
+            identifiers[identifier] = (category, number, tuple(entries))
+
+    for identifier in ("__NR_arch_specific_syscall", "__NR_syscalls"):
+        del identifiers[identifier]
+
+    table = {
+        "arch32": collections.defaultdict(),
+        "arch64": collections.defaultdict(),
+    }
+    for (identifier, (category, number, entries)) in identifiers.items():
+        name = identifier.replace("__NR3264_", "").replace("__NR_", "")
+        (entry, entry32, entry64, compat) = ([None] * 4)
+        if category == "__SC_COMP_3264":
+            (entry32, entry64, compat) = entries
+        elif category == "__SC_3264":
+            (entry32, entry64) = entries
+        elif category == "__SC_COMP":
+            (entry, compat) = entries
+        else:
+            (entry,) = entries
+
+        for abi in table:
+            table[abi][number] = (name, [])
+            table[abi][name] = number
+
+        if entry32 is not None:
+            table["arch32"][number][1].append(entry32)
+        if entry64 is not None:
+            table["arch64"][number][1].append(entry64)
+        if compat is not None:
+            table["arch64"][number][1].append(compat)
+        if entry is not None:
+            table["arch32"][number][1].append(entry)
+            table["arch64"][number][1].append(entry)
+
+        for abi in dict(table):
+            if not table[abi][number][1]:
+                del table[abi][number]
+                del table[abi][name]
+
+        yield ("generic", table)
+
     def parse(path):
         table = collections.defaultdict(dict)
-        whitespace = re.compile(r"\s+")
         with open(path, mode="r", encoding="UTF-8") as stream:
             lines = filter(lambda line: not line.strip().startswith("#"), stream)
             for line in filter(bool, map(str.strip, lines)):