X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=generator%2Fnanopb_generator.py;h=bffdb353c7daff7b9a27d2ec085d3a9996f0be85;hb=bb5dc04584f4e147cf3c892ab004ecd36ba7642b;hp=860f3742d4d84760fe8790543532e62a7f1b9d04;hpb=0ee4bb96b1e53d16a29869864eff87c8934894ae;p=apps%2Fagl-service-can-low-level.git diff --git a/generator/nanopb_generator.py b/generator/nanopb_generator.py index 860f3742..bffdb353 100644 --- a/generator/nanopb_generator.py +++ b/generator/nanopb_generator.py @@ -1,4 +1,5 @@ '''Generate header file for nanopb from a ProtoBuf FileDescriptorSet.''' +nanopb_version = "nanopb-0.1.9-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] != '.': @@ -81,8 +85,16 @@ def names_from_type_name(type_name): class Enum: def __init__(self, names, desc, enum_options): '''desc is EnumDescriptorProto''' + + self.options = enum_options self.names = names + desc.name - self.values = [(self.names + x.name, x.number) for x in desc.value] + + if enum_options.long_names: + self.values = [(self.names + x.name, x.number) for x in desc.value] + else: + self.values = [(names + x.name, x.number) for x in desc.value] + + self.value_longnames = [self.names + x.name for x in desc.value] def __str__(self): result = 'typedef enum _%s {\n' % self.names @@ -376,13 +388,24 @@ def parse_file(fdesc, file_options): base_name = Names() for enum in fdesc.enum_type: - enums.append(Enum(base_name, enum, file_options)) + enum_options = get_nanopb_suboptions(enum, file_options) + enums.append(Enum(base_name, enum, enum_options)) for names, message in iterate_messages(fdesc, base_name): message_options = get_nanopb_suboptions(message, file_options) messages.append(Message(names, message, message_options)) for enum in message.enum_type: - enums.append(Enum(names, enum, message_options)) + enum_options = get_nanopb_suboptions(enum, message_options) + enums.append(Enum(names, enum, enum_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 @@ -423,6 +446,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 @@ -432,7 +456,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: @@ -466,7 +493,9 @@ def generate_header(dependencies, headername, enums, messages): worst = 0 worst_field = '' checks = [] + checks_msgnames = [] for msg in messages: + checks_msgnames.append(msg.name) for field in msg.fields: status = field.largest_field_value() if isinstance(status, (str, unicode)): @@ -484,7 +513,8 @@ def generate_header(dependencies, headername, enums, messages): yield '#error Field descriptor for %s is too large. Define PB_FIELD_16BIT to fix this.\n' % worst_field else: assertion = ' && '.join(str(c) + ' < 256' for c in checks) - yield 'STATIC_ASSERT((%s), YOU_MUST_DEFINE_PB_FIELD_16BIT)\n' % assertion + msgs = '_'.join(str(n) for n in checks_msgnames) + yield 'STATIC_ASSERT((%s), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_%s)\n'%(assertion,msgs) yield '#endif\n\n' if worst > 65535 or checks: @@ -493,9 +523,14 @@ def generate_header(dependencies, headername, enums, messages): yield '#error Field descriptor for %s is too large. Define PB_FIELD_32BIT to fix this.\n' % worst_field else: assertion = ' && '.join(str(c) + ' < 65536' for c in checks) - yield 'STATIC_ASSERT((%s), YOU_MUST_DEFINE_PB_FIELD_32BIT)\n' % assertion + msgs = '_'.join(str(n) for n in checks_msgnames) + yield 'STATIC_ASSERT((%s), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_%s)\n'%(assertion,msgs) yield '#endif\n' + yield '\n#ifdef __cplusplus\n' + yield '} /* extern "C" */\n' + yield '#endif\n' + # End of header yield '\n#endif\n' @@ -503,6 +538,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: @@ -548,6 +584,8 @@ def get_nanopb_suboptions(subdesc, options): ext_type = nanopb_pb2.nanopb_fileopt elif isinstance(subdesc.options, descriptor.MessageOptions): ext_type = nanopb_pb2.nanopb_msgopt + elif isinstance(subdesc.options, descriptor.EnumOptions): + ext_type = nanopb_pb2.nanopb_enumopt else: raise Exception("Unknown options type")