diff options
Diffstat (limited to 'tools/protoc-c/c_message.cc')
-rw-r--r-- | tools/protoc-c/c_message.cc | 611 |
1 files changed, 611 insertions, 0 deletions
diff --git a/tools/protoc-c/c_message.cc b/tools/protoc-c/c_message.cc new file mode 100644 index 0000000000..3ba76817ae --- /dev/null +++ b/tools/protoc-c/c_message.cc @@ -0,0 +1,611 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +// Copyright (c) 2008-2013, Dave Benson. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Modified to implement C code by Dave Benson. + +#include <algorithm> +#include <map> +#include <memory> +#include <protoc-c/c_message.h> +#include <protoc-c/c_enum.h> +#include <protoc-c/c_extension.h> +#include <protoc-c/c_helpers.h> +#include <google/protobuf/io/printer.h> +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/wire_format.h> +#include <protobuf-c/protobuf-c.pb.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace c { + +// =================================================================== + +MessageGenerator::MessageGenerator(const Descriptor* descriptor, + const std::string& dllexport_decl) + : descriptor_(descriptor), + dllexport_decl_(dllexport_decl), + field_generators_(descriptor), + nested_generators_(new std::unique_ptr<MessageGenerator>[ + descriptor->nested_type_count()]), + enum_generators_(new std::unique_ptr<EnumGenerator>[ + descriptor->enum_type_count()]), + extension_generators_(new std::unique_ptr<ExtensionGenerator>[ + descriptor->extension_count()]) { + + for (int i = 0; i < descriptor->nested_type_count(); i++) { + nested_generators_[i].reset( + new MessageGenerator(descriptor->nested_type(i), dllexport_decl)); + } + + for (int i = 0; i < descriptor->enum_type_count(); i++) { + enum_generators_[i].reset( + new EnumGenerator(descriptor->enum_type(i), dllexport_decl)); + } + + for (int i = 0; i < descriptor->extension_count(); i++) { + extension_generators_[i].reset( + new ExtensionGenerator(descriptor->extension(i), dllexport_decl)); + } +} + +MessageGenerator::~MessageGenerator() {} + +void MessageGenerator:: +GenerateStructTypedef(io::Printer* printer) { + printer->Print("struct $classname$;\n", + "classname", FullNameToC(descriptor_->full_name(), descriptor_->file())); + + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + nested_generators_[i]->GenerateStructTypedef(printer); + } +} + +void MessageGenerator:: +GenerateEnumDefinitions(io::Printer* printer) { + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + nested_generators_[i]->GenerateEnumDefinitions(printer); + } + + for (int i = 0; i < descriptor_->enum_type_count(); i++) { + enum_generators_[i]->GenerateDefinition(printer); + } +} + + +void MessageGenerator:: +GenerateStructDefinition(io::Printer* printer) { + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + nested_generators_[i]->GenerateStructDefinition(printer); + } + + std::map<std::string, std::string> vars; + vars["classname"] = FullNameToC(descriptor_->full_name(), descriptor_->file()); + vars["lcclassname"] = FullNameToLower(descriptor_->full_name(), descriptor_->file()); + vars["ucclassname"] = FullNameToUpper(descriptor_->full_name(), descriptor_->file()); + vars["field_count"] = SimpleItoa(descriptor_->field_count()); + if (dllexport_decl_.empty()) { + vars["dllexport"] = ""; + } else { + vars["dllexport"] = dllexport_decl_ + " "; + } + + // Generate the case enums for unions + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + const OneofDescriptor *oneof = descriptor_->oneof_decl(i); + vars["opt_comma"] = ","; + + vars["oneofname"] = CamelToUpper(oneof->name()); + vars["foneofname"] = FullNameToC(oneof->full_name(), oneof->file()); + + printer->Print("typedef enum {\n"); + printer->Indent(); + printer->Print(vars, "$ucclassname$__$oneofname$__NOT_SET = 0,\n"); + for (int j = 0; j < oneof->field_count(); j++) { + const FieldDescriptor *field = oneof->field(j); + vars["fieldname"] = CamelToUpper(field->name()); + vars["fieldnum"] = SimpleItoa(field->number()); + bool isLast = j == oneof->field_count() - 1; + if (isLast) { + vars["opt_comma"] = ""; + } + printer->Print(vars, "$ucclassname$__$oneofname$_$fieldname$ = $fieldnum$$opt_comma$\n"); + } + printer->Print(vars, " PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE($ucclassname$__$oneofname$__CASE)\n"); + printer->Outdent(); + printer->Print(vars, "} $foneofname$Case;\n\n"); + } + + SourceLocation msgSourceLoc; + descriptor_->GetSourceLocation(&msgSourceLoc); + PrintComment (printer, msgSourceLoc.leading_comments); + + const ProtobufCMessageOptions opt = + descriptor_->options().GetExtension(pb_c_msg); + vars["base"] = opt.base_field_name(); + + printer->Print(vars, + "struct $classname$ : public ProtobufCppMessage\n" + "{\n"); + + // Generate fields. + printer->Indent(); + + printer->Print(vars, + "$classname$() :\n" + " ProtobufCppMessage($lcclassname$__descriptor)\n" + "{}\n\n"); + + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor *field = descriptor_->field(i); + if (field->containing_oneof() == NULL) { + SourceLocation fieldSourceLoc; + field->GetSourceLocation(&fieldSourceLoc); + + PrintComment (printer, fieldSourceLoc.leading_comments); + PrintComment (printer, fieldSourceLoc.trailing_comments); + field_generators_.get(field).GenerateStructMembers(printer); + } + } + + // Generate unions from oneofs. + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + const OneofDescriptor *oneof = descriptor_->oneof_decl(i); + vars["oneofname"] = CamelToLower(oneof->name()); + vars["foneofname"] = FullNameToC(oneof->full_name(), oneof->file()); + + printer->Print(vars, "$foneofname$Case $oneofname$_case;\n"); + + printer->Print("union {\n"); + printer->Indent(); + for (int j = 0; j < oneof->field_count(); j++) { + const FieldDescriptor *field = oneof->field(j); + SourceLocation fieldSourceLoc; + field->GetSourceLocation(&fieldSourceLoc); + + PrintComment (printer, fieldSourceLoc.leading_comments); + PrintComment (printer, fieldSourceLoc.trailing_comments); + field_generators_.get(field).GenerateStructMembers(printer); + } + printer->Outdent(); + printer->Print(vars, "};\n"); + } + printer->Outdent(); + + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor *field = descriptor_->field(i); + if (field->has_default_value()) { + field_generators_.get(field).GenerateDefaultValueDeclarations(printer); + } + } + + printer->Print("};\n\n"); +} + +void MessageGenerator:: +GenerateHelperFunctionDeclarations(io::Printer* printer, + bool is_pack_deep, + bool gen_pack, + bool gen_init) +{ + const ProtobufCMessageOptions opt = + descriptor_->options().GetExtension(pb_c_msg); + + // Override parent settings, if needed + if (opt.has_gen_pack_helpers()) + gen_pack = opt.gen_pack_helpers(); + if (opt.has_gen_init_helpers()) + gen_init = opt.gen_init_helpers(); + + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + bool nested_pack = !is_pack_deep ? opt.gen_pack_helpers() : gen_pack; + nested_generators_[i]->GenerateHelperFunctionDeclarations(printer, true, + nested_pack, + gen_init); + } + + std::map<std::string, std::string> vars; + vars["classname"] = FullNameToC(descriptor_->full_name(), descriptor_->file()); + vars["lcclassname"] = FullNameToLower(descriptor_->full_name(), descriptor_->file()); + if (gen_init) { + printer->Print(vars, + "/* $classname$ methods */\n" + "void $lcclassname$__init\n" + " ($classname$ *message);\n" + ); + } + if (gen_pack) { + printer->Print(vars, + "size_t $lcclassname$__get_packed_size\n" + " (const $classname$ *message);\n" + "size_t $lcclassname$__pack\n" + " (const $classname$ *message,\n" + " uint8_t *out);\n" + "size_t $lcclassname$__pack_to_buffer\n" + " (const $classname$ *message,\n" + " ProtobufCBuffer *buffer);\n" + "$classname$ *\n" + " $lcclassname$__unpack\n" + " (ProtobufCAllocator *allocator,\n" + " size_t len,\n" + " const uint8_t *data);\n" + "void $lcclassname$__free_unpacked\n" + " ($classname$ *message,\n" + " ProtobufCAllocator *allocator);\n" + ); + } +} + +void MessageGenerator:: +GenerateDescriptorDeclarations(io::Printer* printer) { + printer->Print("extern const ProtobufCMessageDescriptor $name$__descriptor;\n", + "name", FullNameToLower(descriptor_->full_name(), descriptor_->file())); + + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + nested_generators_[i]->GenerateDescriptorDeclarations(printer); + } + + for (int i = 0; i < descriptor_->enum_type_count(); i++) { + enum_generators_[i]->GenerateDescriptorDeclarations(printer); + } +} +void MessageGenerator::GenerateClosureTypedef(io::Printer* printer) +{ + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + nested_generators_[i]->GenerateClosureTypedef(printer); + } + std::map<std::string, std::string> vars; + vars["name"] = FullNameToC(descriptor_->full_name(), descriptor_->file()); + printer->Print(vars, + "typedef void (*$name$_Closure)\n" + " (const $name$ *message,\n" + " void *closure_data);\n"); +} + +static int +compare_pfields_by_number (const void *a, const void *b) +{ + const FieldDescriptor *pa = *(const FieldDescriptor **)a; + const FieldDescriptor *pb = *(const FieldDescriptor **)b; + if (pa->number() < pb->number()) return -1; + if (pa->number() > pb->number()) return +1; + return 0; +} + +void MessageGenerator:: +GenerateHelperFunctionDefinitions(io::Printer* printer, + bool is_pack_deep, + bool gen_pack, + bool gen_init) +{ + const ProtobufCMessageOptions opt = + descriptor_->options().GetExtension(pb_c_msg); + + // Override parent settings, if needed + if (opt.has_gen_pack_helpers()) + gen_pack = opt.gen_pack_helpers(); + if (opt.has_gen_init_helpers()) + gen_init = opt.gen_init_helpers(); + + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + bool nested_pack = !is_pack_deep ? opt.gen_pack_helpers() : gen_pack; + nested_generators_[i]->GenerateHelperFunctionDefinitions(printer, true, + nested_pack, + gen_init); + } + + std::map<std::string, std::string> vars; + vars["classname"] = FullNameToC(descriptor_->full_name(), descriptor_->file()); + vars["lcclassname"] = FullNameToLower(descriptor_->full_name(), descriptor_->file()); + vars["ucclassname"] = FullNameToUpper(descriptor_->full_name(), descriptor_->file()); + vars["base"] = opt.base_field_name(); + if (gen_init) { + printer->Print(vars, + "void $lcclassname$__init\n" + " ($classname$ *message)\n" + "{\n" + " static const $classname$ init_value = $ucclassname$__INIT;\n" + " *message = init_value;\n" + "}\n"); + } + if (gen_pack) { + printer->Print(vars, + "size_t $lcclassname$__get_packed_size\n" + " (const $classname$ *message)\n" + "{\n" + " assert(message->descriptor == &$lcclassname$__descriptor);\n" + " return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));\n" + "}\n" + "size_t $lcclassname$__pack\n" + " (const $classname$ *message,\n" + " uint8_t *out)\n" + "{\n" + " assert(message->descriptor == &$lcclassname$__descriptor);\n" + " return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);\n" + "}\n" + "size_t $lcclassname$__pack_to_buffer\n" + " (const $classname$ *message,\n" + " ProtobufCBuffer *buffer)\n" + "{\n" + " assert(message->descriptor == &$lcclassname$__descriptor);\n" + " return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);\n" + "}\n" + "$classname$ *\n" + " $lcclassname$__unpack\n" + " (ProtobufCAllocator *allocator,\n" + " size_t len,\n" + " const uint8_t *data)\n" + "{\n" + " return ($classname$ *)\n" + " protobuf_c_message_unpack (&$lcclassname$__descriptor,\n" + " allocator, len, data);\n" + "}\n" + "void $lcclassname$__free_unpacked\n" + " ($classname$ *message,\n" + " ProtobufCAllocator *allocator)\n" + "{\n" + " if(!message)\n" + " return;\n" + " assert(message->descriptor == &$lcclassname$__descriptor);\n" + " protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);\n" + "}\n\n" + ); + } +} + +void MessageGenerator:: +GenerateMessageDescriptor(io::Printer* printer, bool gen_init) { + std::map<std::string, std::string> vars; + vars["fullname"] = descriptor_->full_name(); + vars["classname"] = FullNameToC(descriptor_->full_name(), descriptor_->file()); + vars["lcclassname"] = FullNameToLower(descriptor_->full_name(), descriptor_->file()); + vars["shortname"] = ToCamel(descriptor_->name()); + vars["n_fields"] = SimpleItoa(descriptor_->field_count()); + vars["packagename"] = descriptor_->file()->package(); + + bool optimize_code_size = descriptor_->file()->options().has_optimize_for() && + descriptor_->file()->options().optimize_for() == + FileOptions_OptimizeMode_CODE_SIZE; + + const ProtobufCMessageOptions opt = + descriptor_->options().GetExtension(pb_c_msg); + // Override parent settings, if needed + if (opt.has_gen_init_helpers()) + gen_init = opt.gen_init_helpers(); + + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + nested_generators_[i]->GenerateMessageDescriptor(printer, gen_init); + } + + for (int i = 0; i < descriptor_->enum_type_count(); i++) { + enum_generators_[i]->GenerateEnumDescriptor(printer); + } + + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor *fd = descriptor_->field(i); + if (fd->has_default_value()) { + field_generators_.get(fd).GenerateDefaultValueImplementations(printer); + } + } + + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor *fd = descriptor_->field(i); + const ProtobufCFieldOptions opt = fd->options().GetExtension(pb_c_field); + if (fd->has_default_value()) { + + bool already_defined = false; + vars["name"] = fd->name(); + vars["lcname"] = CamelToLower(fd->name()); + vars["maybe_static"] = "static "; + vars["field_dv_ctype_suffix"] = ""; + vars["default_value"] = field_generators_.get(fd).GetDefaultValue(); + switch (fd->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: + vars["field_dv_ctype"] = "int32_t"; + break; + case FieldDescriptor::CPPTYPE_INT64: + vars["field_dv_ctype"] = "int64_t"; + break; + case FieldDescriptor::CPPTYPE_UINT32: + vars["field_dv_ctype"] = "uint32_t"; + break; + case FieldDescriptor::CPPTYPE_UINT64: + vars["field_dv_ctype"] = "uint64_t"; + break; + case FieldDescriptor::CPPTYPE_FLOAT: + vars["field_dv_ctype"] = "float"; + break; + case FieldDescriptor::CPPTYPE_DOUBLE: + vars["field_dv_ctype"] = "double"; + break; + case FieldDescriptor::CPPTYPE_BOOL: + vars["field_dv_ctype"] = "protobuf_c_boolean"; + break; + + case FieldDescriptor::CPPTYPE_MESSAGE: + // NOTE: not supported by protobuf + vars["maybe_static"] = ""; + vars["field_dv_ctype"] = "{ ... }"; + GOOGLE_LOG(DFATAL) << "Messages can't have default values!"; + break; + case FieldDescriptor::CPPTYPE_STRING: + if (fd->type() == FieldDescriptor::TYPE_BYTES || opt.string_as_bytes()) + { + vars["field_dv_ctype"] = "ProtobufCBinaryData"; + } + else /* STRING type */ + { + already_defined = true; + vars["maybe_static"] = ""; + vars["field_dv_ctype"] = "char"; + vars["field_dv_ctype_suffix"] = "[]"; + } + break; + case FieldDescriptor::CPPTYPE_ENUM: + { + const EnumValueDescriptor *vd = fd->default_value_enum(); + vars["field_dv_ctype"] = FullNameToC(vd->type()->full_name(), vd->type()->file()); + break; + } + default: + GOOGLE_LOG(DFATAL) << "Unknown CPPTYPE"; + break; + } + if (!already_defined) + printer->Print(vars, "$maybe_static$const $field_dv_ctype$ $lcclassname$__$lcname$__default_value$field_dv_ctype_suffix$ = $default_value$;\n"); + } + } + + if ( descriptor_->field_count() ) { + printer->Print(vars, + "static const ProtobufCFieldDescriptor $lcclassname$__field_descriptors[$n_fields$] =\n" + "{\n"); + printer->Indent(); + const FieldDescriptor **sorted_fields = new const FieldDescriptor *[descriptor_->field_count()]; + for (int i = 0; i < descriptor_->field_count(); i++) { + sorted_fields[i] = descriptor_->field(i); + } + qsort (sorted_fields, descriptor_->field_count(), + sizeof (const FieldDescriptor *), + compare_pfields_by_number); + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor *field = sorted_fields[i]; + field_generators_.get(field).GenerateDescriptorInitializer(printer); + } + printer->Outdent(); + printer->Print(vars, "};\n"); + + if (!optimize_code_size) { + NameIndex *field_indices = new NameIndex [descriptor_->field_count()]; + for (int i = 0; i < descriptor_->field_count(); i++) { + field_indices[i].name = sorted_fields[i]->name().c_str(); + field_indices[i].index = i; + } + qsort (field_indices, descriptor_->field_count(), sizeof (NameIndex), + compare_name_indices_by_name); + printer->Print(vars, "static const unsigned $lcclassname$__field_indices_by_name[] = {\n"); + for (int i = 0; i < descriptor_->field_count(); i++) { + vars["index"] = SimpleItoa(field_indices[i].index); + vars["name"] = field_indices[i].name; + printer->Print(vars, " $index$, /* field[$index$] = $name$ */\n"); + } + printer->Print("};\n"); + delete[] field_indices; + } + + // create range initializers + int *values = new int[descriptor_->field_count()]; + for (int i = 0; i < descriptor_->field_count(); i++) { + values[i] = sorted_fields[i]->number(); + } + int n_ranges = WriteIntRanges(printer, + descriptor_->field_count(), values, + vars["lcclassname"] + "__number_ranges"); + delete [] values; + delete [] sorted_fields; + + vars["n_ranges"] = SimpleItoa(n_ranges); + } else { + /* MS compiler can't handle arrays with zero size and empty + * initialization list. Furthermore it is an extension of GCC only but + * not a standard. */ + vars["n_ranges"] = "0"; + printer->Print(vars, + "#define $lcclassname$__field_descriptors NULL\n" + "#define $lcclassname$__field_indices_by_name NULL\n" + "#define $lcclassname$__number_ranges NULL\n"); + } + + printer->Print(vars, + "const ProtobufCMessageDescriptor $lcclassname$__descriptor =\n" + "{\n" + " PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,\n"); + if (optimize_code_size) { + printer->Print(" NULL,NULL,NULL,NULL, /* CODE_SIZE */\n"); + } else { + printer->Print(vars, + " \"$fullname$\",\n" + " \"$shortname$\",\n" + " \"$classname$\",\n" + " \"$packagename$\",\n"); + } + printer->Print(vars, + " sizeof($classname$),\n" + " $n_fields$,\n" + " $lcclassname$__field_descriptors,\n"); + if (optimize_code_size) { + printer->Print(" NULL, /* CODE_SIZE */\n"); + } else { + printer->Print(vars, + " $lcclassname$__field_indices_by_name,\n"); + } + printer->Print(vars, + " $n_ranges$," + " $lcclassname$__number_ranges,\n"); + printer->Print(vars, + " NULL,NULL,NULL,NULL /* reserved[123] */\n" + "};\n"); +} + +} // namespace c +} // namespace compiler +} // namespace protobuf +} // namespace google |