[APISETS] Stubplement versioned forwarders
[reactos.git] / dll / apisets / update.py
index 0591553..adad66c 100644 (file)
@@ -17,7 +17,7 @@ SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
 NL_CHAR = '\n'
 
 IGNORE_OPTIONS = ('-norelay', '-ret16', '-ret64', '-register', '-private',
-                  '-noname', '-ordinal', '-i386', '-arch=', '-stub')
+                  '-noname', '-ordinal', '-i386', '-arch=', '-stub', '-version=')
 
 # Figure these out later
 FUNCTION_BLACKLIST = [
@@ -34,6 +34,16 @@ SPEC_HEADER = [
     '\n'
 ]
 
+ALIAS_DLL = {
+    'ucrtbase': 'msvcrt',
+    'kernelbase': 'kernel32',
+    'shcore': 'shlwapi',
+    'combase': 'ole32',
+
+    # These modules cannot be linked against in ROS, so forward it
+    'cfgmgr32': 'setupapi', # Forward everything
+    'wmi': 'advapi32',      # Forward everything
+}
 
 class InvalidSpecError(Exception):
     def __init__(self, message):
@@ -102,16 +112,20 @@ class Arch(object):
     def __ne__(self, other):
         return not self.__eq__(other)
 
-ALIAS_DLL = {
-    'ucrtbase': 'msvcrt',
-    'kernelbase': 'kernel32',
-    'shcore': 'shlwapi',
-    'combase': 'ole32',
 
-    # These modules cannot be linked against in ROS, so forward it
-    'cfgmgr32': 'setupapi', # Forward everything
-    'wmi': 'advapi32',      # Forward everything
-}
+class VersionExpr(object):
+    def __init__(self, text):
+        self.text = text
+        self.parse()
+
+    def parse(self):
+        pass
+
+    def to_str(self):
+        if self.text:
+            return '-version={}'.format(self.text)
+        return ''
+
 
 class SpecEntry(object):
     def __init__(self, text, spec):
@@ -120,6 +134,7 @@ class SpecEntry(object):
         self.callconv = None
         self.name = None
         self.arch = Arch()
+        self.version = None
         self._forwarder = None
         self.init(text)
         self.noname = False
@@ -148,6 +163,8 @@ class SpecEntry(object):
         while self.name.startswith(IGNORE_OPTIONS):
             if self.name.startswith('-arch='):
                 self.arch.add(self.name[6:])
+            elif self.name.startswith('-version='):
+                self.version = VersionExpr(self.name[9:])
             elif self.name == '-i386':
                 self.arch.add('i386')
             self.name = tokens.pop(0)
@@ -185,10 +202,12 @@ class SpecEntry(object):
             module = module_lookup[module_name]
             fwd_arch = module.find_arch(self.name)
             callconv = module.find_callconv(self.name)
+            version = module.find_version(self.name)
             if fwd_arch:
                 self.arch = fwd_arch
                 self._forwarder = [module_name, self.name]
                 self.callconv = callconv
+                self.version = version
                 return 1
         return 0
 
@@ -214,6 +233,7 @@ class SpecEntry(object):
             mod = module_lookup[mod]
             self.arch = mod.find_arch(self.name)
             self.callconv = mod.find_callconv(self.name)
+            self.version = mod.find_version(self.name)
             return 1
         return 0
 
@@ -232,6 +252,8 @@ class SpecEntry(object):
         estimate_size = 0
         if self.noname:
             opts = '{} -noname'.format(opts)
+        if self.version:
+            opts = '{} {}'.format(opts, self.version.to_str())
         if self.name == '@':
             assert self._ord != '@'
             name = 'Ordinal' + self._ord
@@ -310,6 +332,18 @@ class SpecFile(object):
                     callconv = func.callconv
         return callconv
 
+    def find_version(self, name):
+        functions = self.find(name)
+        version = None
+        if functions:
+            for func in functions:
+                if not func.version:
+                    continue
+                if version:
+                    assert version.text == func.version.text
+                version = func.version
+        return version
+
     def resolve_forwarders(self, module_lookup):
         modules = self.forwarder_modules()
         total = 0