Fix naming of enums when long_names=false.
[apps/agl-service-can-low-level.git] / generator / nanopb_generator.py
index 2267238..68cc800 100644 (file)
@@ -1,4 +1,5 @@
 '''Generate header file for nanopb from a ProtoBuf FileDescriptorSet.'''
+nanopb_version = "nanopb-0.1.8-dev"
 
 try:
     import google.protobuf.descriptor_pb2 as descriptor
@@ -31,7 +32,7 @@ except:
 #                     Generation of single fields
 # ---------------------------------------------------------------------------
 
-
+import time
 import os.path
 
 # Values are tuple (c type, pb ltype)
@@ -72,6 +73,9 @@ class Names:
         else:
             raise ValueError("Name parts should be of type str")
     
+    def __eq__(self, other):
+        return isinstance(other, Names) and self.parts == other.parts
+    
 def names_from_type_name(type_name):
     '''Parse Names() from FieldDescriptorProto type_name'''
     if type_name[0] != '.':
@@ -82,12 +86,15 @@ class Enum:
     def __init__(self, names, desc, enum_options):
         '''desc is EnumDescriptorProto'''
         
+        self.options = enum_options
+        self.names = names + desc.name
+        
         if enum_options.long_names:
-            self.names = names + desc.name
+            self.values = [(self.names + x.name, x.number) for x in desc.value]            
         else:
-            self.names = names
+            self.values = [(x.name, x.number) for x in desc.value] 
         
-        self.values = [(self.names + x.name, x.number) for x in desc.value]
+        self.value_longnames = [names + desc.name + x.name for x in desc.value]
     
     def __str__(self):
         result = 'typedef enum _%s {\n' % self.names
@@ -390,6 +397,15 @@ def parse_file(fdesc, file_options):
         for enum in message.enum_type:
             enums.append(Enum(names, enum, message_options))
     
+    # Fix field default values where enum short names are used.
+    for enum in enums:
+        if not enum.options.long_names:
+            for message in messages:
+                for field in message.fields:
+                    if field.default in enum.value_longnames:
+                        idx = enum.value_longnames.index(field.default)
+                        field.default = enum.values[idx][0]
+    
     return enums, messages
 
 def toposort2(data):
@@ -429,6 +445,7 @@ def generate_header(dependencies, headername, enums, messages):
     '''
     
     yield '/* Automatically generated nanopb header */\n'
+    yield '/* Generated by %s at %s. */\n\n' % (nanopb_version, time.asctime())
     
     symbol = headername.replace('.', '_').upper()
     yield '#ifndef _PB_%s_\n' % symbol
@@ -438,7 +455,10 @@ def generate_header(dependencies, headername, enums, messages):
     for dependency in dependencies:
         noext = os.path.splitext(dependency)[0]
         yield '#include "%s.pb.h"\n' % noext
-    yield '\n'
+    
+    yield '#ifdef __cplusplus\n'
+    yield 'extern "C" {\n'
+    yield '#endif\n\n'
     
     yield '/* Enum definitions */\n'
     for enum in enums:
@@ -502,6 +522,10 @@ def generate_header(dependencies, headername, enums, messages):
                 yield 'STATIC_ASSERT((%s), YOU_MUST_DEFINE_PB_FIELD_32BIT)\n' % assertion
             yield '#endif\n'
     
+    yield '\n#ifdef __cplusplus\n'
+    yield '} /* extern "C" */\n'
+    yield '#endif\n'
+    
     # End of header
     yield '\n#endif\n'
 
@@ -509,6 +533,7 @@ def generate_source(headername, enums, messages):
     '''Generate content for a source file.'''
     
     yield '/* Automatically generated nanopb constant definitions */\n'
+    yield '/* Generated by %s at %s. */\n\n' % (nanopb_version, time.asctime())
     yield '#include "%s"\n\n' % headername
     
     for msg in messages: