Publishing nanopb-0.3.3
[apps/agl-service-can-low-level.git] / generator / nanopb_generator.py
index 7ee0652..364a22c 100755 (executable)
@@ -1,9 +1,10 @@
 #!/usr/bin/python
 
 '''Generate header file for nanopb from a ProtoBuf FileDescriptorSet.'''
-nanopb_version = "nanopb-0.3.3-dev"
+nanopb_version = "nanopb-0.3.3"
 
 import sys
+import re
 
 try:
     # Add some dummy imports to keep packaging tools happy.
@@ -164,6 +165,13 @@ class Enum:
         result = 'typedef enum _%s {\n' % self.names
         result += ',\n'.join(["    %s = %d" % x for x in self.values])
         result += '\n} %s;' % self.names
+        
+        if not self.options.long_names:
+            # Define the long names always so that enum value references
+            # from other files work properly.
+            for i, x in enumerate(self.values):
+                result += '\n#define %s %s' % (self.value_longnames[i], x[0])
+        
         return result
 
 class Field:
@@ -667,6 +675,9 @@ class Message:
         self.oneofs = {}
         no_unions = []
 
+        if message_options.msgid:
+            self.msgid = message_options.msgid
+
         if hasattr(desc, 'oneof_decl'):
             for i, f in enumerate(desc.oneof_decl):
                 oneof_options = get_nanopb_suboptions(desc, message_options, self.name + f.name)
@@ -854,7 +865,7 @@ def parse_file(fdesc, file_options):
         
         if message_options.skip_message:
             continue
-        
+   
         messages.append(Message(names, message, message_options))
         for enum in message.enum_type:
             enum_options = get_nanopb_suboptions(enum, message_options, names + enum.name)
@@ -1001,7 +1012,35 @@ def generate_header(dependencies, headername, enums, messages, extensions, optio
             identifier = '%s_size' % msg.name
             yield '#define %-40s %s\n' % (identifier, msize)
     yield '\n'
+
+    yield '/* Message IDs (where set with "msgid" option) */\n'
     
+    yield '#ifdef PB_MSGID\n'
+    for msg in messages:
+        if hasattr(msg,'msgid'):
+            yield '#define PB_MSG_%d %s\n' % (msg.msgid, msg.name)
+    yield '\n'
+
+    symbol = make_identifier(headername.split('.')[0])
+    yield '#define %s_MESSAGES \\\n' % symbol
+
+    for msg in messages:
+        m = "-1"
+        msize = msg.encoded_size(messages)
+        if msize is not None:
+            m = msize
+        if hasattr(msg,'msgid'):
+            yield '\tPB_MSG(%d,%s,%s) \\\n' % (msg.msgid, m, msg.name)
+    yield '\n'
+
+    for msg in messages:
+        if hasattr(msg,'msgid'):
+            yield '#define %s_msgid %d\n' % (msg.name, msg.msgid)
+    yield '\n'
+
+    yield '#endif\n\n'
+
+
     yield '#ifdef __cplusplus\n'
     yield '} /* extern "C" */\n'
     yield '#endif\n'
@@ -1126,14 +1165,32 @@ def read_options_file(infile):
         [(namemask, options), ...]
     '''
     results = []
-    for line in infile:
+    data = infile.read()
+    data = re.sub('/\*.*?\*/', '', data, flags = re.MULTILINE)
+    data = re.sub('//.*?$', '', data, flags = re.MULTILINE)
+    data = re.sub('#.*?$', '', data, flags = re.MULTILINE)
+    for i, line in enumerate(data.split('\n')):
         line = line.strip()
-        if not line or line.startswith('//') or line.startswith('#'):
+        if not line:
             continue
         
         parts = line.split(None, 1)
+        
+        if len(parts) < 2:
+            sys.stderr.write("%s:%d: " % (infile.name, i + 1) +
+                             "Option lines should have space between field name and options. " +
+                             "Skipping line: '%s'\n" % line)
+            continue
+        
         opts = nanopb_pb2.NanoPBOptions()
-        text_format.Merge(parts[1], opts)
+        
+        try:
+            text_format.Merge(parts[1], opts)
+        except Exception, e:
+            sys.stderr.write("%s:%d: " % (infile.name, i + 1) +
+                             "Unparseable option line: '%s'. " % line +
+                             "Error: %s\n" % str(e))
+            continue
         results.append((parts[0], opts))
 
     return results
@@ -1327,8 +1384,15 @@ def main_plugin():
     data = sys.stdin.read()
     request = plugin_pb2.CodeGeneratorRequest.FromString(data)
     
+    try:
+        # Versions of Python prior to 2.7.3 do not support unicode
+        # input to shlex.split(). Try to convert to str if possible.
+        params = str(request.parameter)
+    except UnicodeEncodeError:
+        params = request.parameter
+    
     import shlex
-    args = shlex.split(request.parameter)
+    args = shlex.split(params)
     options, dummy = optparser.parse_args(args)
     
     Globals.verbose_options = options.verbose