API: Add support for type aliases
[vpp.git] / src / tools / vppapigen / vppapigen.py
index 5cedfb2..3f882c4 100755 (executable)
@@ -151,6 +151,25 @@ class Typedef():
         return self.name + str(self.flags) + str(self.block)
 
 
+class Using():
+    def __init__(self, name, alias):
+        global global_crc
+        self.name = name
+
+        if isinstance(alias, Array):
+            a = { 'type': alias.fieldtype,
+                  'length': alias.length }
+        else:
+            a = { 'type': alias.fieldtype }
+        self.alias = a
+        self.crc = binascii.crc32(str(alias)) & 0xffffffff
+        global_crc = binascii.crc32(str(alias), global_crc)
+        global_type_add(name)
+
+    def __repr__(self):
+        return self.name + str(self.alias)
+
+
 class Union():
     def __init__(self, name, block):
         self.type = 'Union'
@@ -457,6 +476,10 @@ class VPPAPIParser(object):
         '''typedef : TYPEDEF ID '{' block_statements_opt '}' ';' '''
         p[0] = Typedef(p[2], [], p[4])
 
+    def p_typedef_alias(self, p):
+        '''typedef : TYPEDEF declaration '''
+        p[0] = Using(p[2].fieldname, p[2])
+
     def p_block_statements_opt(self, p):
         '''block_statements_opt : block_statements '''
         p[0] = p[1]
@@ -594,6 +617,7 @@ class VPPAPI(object):
         s['Service'] = []
         s['types'] = []
         s['Import'] = []
+        s['Alias'] = {}
         for o in objs:
             tname = o.__class__.__name__
             if isinstance(o, Define):
@@ -608,6 +632,8 @@ class VPPAPI(object):
                         s['Service'].append(o2)
             elif isinstance(o, Enum) or isinstance(o, Typedef) or isinstance(o, Union):
                 s['types'].append(o)
+            elif isinstance(o, Using):
+                s['Alias'][o.name] = o.alias
             else:
                 if tname not in s:
                     raise ValueError('Unknown class type: {} {}'.format(tname, o))
@@ -685,12 +711,14 @@ class VPPAPI(object):
             # Only allow the following object types from imported file
             if in_import and not (isinstance(o, Enum) or
                                   isinstance(o, Union) or
-                                  isinstance(o, Typedef)):
+                                  isinstance(o, Typedef) or
+                                  isinstance(o, Import) or
+                                  isinstance(o, Using)):
                 continue
-            result.append(o)
-
             if isinstance(o, Import):
                 self.process_imports(o.result, True, result)
+            else:
+                result.append(o)
 
 # Add message ids to each message.
 def add_msg_id(s):
@@ -764,7 +792,7 @@ def main():
     # Debug
     if args.debug:
         import pprint
-        pp = pprint.PrettyPrinter(indent=4)
+        pp = pprint.PrettyPrinter(indent=4, stream=sys.stderr)
         for t in s['Define']:
             pp.pprint([t.name, t.flags, t.block])
         for t in s['types']:
@@ -784,14 +812,14 @@ def main():
                     '/../share/vpp/')
         for c in cand:
             c += '/'
-            if os.path.isfile(c + args.output_module + '.py'):
+            if os.path.isfile('{}vppapigen_{}.py'.format(c, args.output_module.lower())):
                 pluginpath = c
                 break
     else:
         pluginpath = args.pluginpath + '/'
     if pluginpath == '':
         raise Exception('Output plugin not found')
-    module_path = pluginpath + args.output_module + '.py'
+    module_path = '{}vppapigen_{}.py'.format(pluginpath, args.output_module.lower())
 
     try:
         plugin = imp.load_source(args.output_module, module_path)