From b24c724f3342d0238f4dee37569638e73eaf8a3e Mon Sep 17 00:00:00 2001 From: George Hazan Date: Fri, 9 Jun 2023 13:01:10 +0300 Subject: Saving modified protoc-c used to generate a code from Miranda .proto files --- tools/protoc-c/c_file.cc | 284 ++++++++++++++++++++ tools/protoc-c/c_message.cc | 611 ++++++++++++++++++++++++++++++++++++++++++++ tools/protoc-c/readme.txt | 2 + 3 files changed, 897 insertions(+) create mode 100644 tools/protoc-c/c_file.cc create mode 100644 tools/protoc-c/c_message.cc create mode 100644 tools/protoc-c/readme.txt (limited to 'tools/protoc-c') diff --git a/tools/protoc-c/c_file.cc b/tools/protoc-c/c_file.cc new file mode 100644 index 0000000000..a07a2b3e60 --- /dev/null +++ b/tools/protoc-c/c_file.cc @@ -0,0 +1,284 @@ +// 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-2014, Dave Benson and the protobuf-c authors. +// 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 +#include +#include +#include +#include +#include +#include +#include + +#include "protobuf-c.h" + +namespace google { +namespace protobuf { +namespace compiler { +namespace c { + +// =================================================================== + +FileGenerator::FileGenerator(const FileDescriptor* file, + const std::string& dllexport_decl) + : file_(file), + message_generators_( + new std::unique_ptr[file->message_type_count()]), + enum_generators_( + new std::unique_ptr[file->enum_type_count()]), + service_generators_( + new std::unique_ptr[file->service_count()]), + extension_generators_( + new std::unique_ptr[file->extension_count()]) { + + for (int i = 0; i < file->message_type_count(); i++) { + message_generators_[i].reset( + new MessageGenerator(file->message_type(i), dllexport_decl)); + } + + for (int i = 0; i < file->enum_type_count(); i++) { + enum_generators_[i].reset( + new EnumGenerator(file->enum_type(i), dllexport_decl)); + } + + for (int i = 0; i < file->service_count(); i++) { + service_generators_[i].reset( + new ServiceGenerator(file->service(i), dllexport_decl)); + } + + for (int i = 0; i < file->extension_count(); i++) { + extension_generators_[i].reset( + new ExtensionGenerator(file->extension(i), dllexport_decl)); + } +} + +FileGenerator::~FileGenerator() {} + +void FileGenerator::GenerateHeader(io::Printer* printer) { + std::string filename_identifier = FilenameIdentifier(file_->name()); + + int min_header_version = 1000000; +#if defined(HAVE_PROTO3) + if (file_->syntax() == FileDescriptor::SYNTAX_PROTO3) { + min_header_version = 1003000; + } +#endif + + // Generate top of header. + printer->Print( + "/* Generated by the protocol buffer compiler. DO NOT EDIT! */\n" + "/* Generated from: $filename$ */\n" + "\n" + "#ifndef PROTOBUF_C_$filename_identifier$__INCLUDED\n" + "#define PROTOBUF_C_$filename_identifier$__INCLUDED\n" + "\n" + "#include \n" + "\n" + "PROTOBUF_C__BEGIN_DECLS\n" + "\n", + "filename", file_->name(), + "filename_identifier", filename_identifier); + + // Verify the protobuf-c library header version is compatible with the + // protoc-c version before going any further. + printer->Print( + "#if PROTOBUF_C_VERSION_NUMBER < $min_header_version$\n" + "# error This file was generated by a newer version of protoc-c which is " + "incompatible with your libprotobuf-c headers. Please update your headers.\n" + "#elif $protoc_version$ < PROTOBUF_C_MIN_COMPILER_VERSION\n" + "# error This file was generated by an older version of protoc-c which is " + "incompatible with your libprotobuf-c headers. Please regenerate this file " + "with a newer version of protoc-c.\n" + "#endif\n" + "\n", + "min_header_version", SimpleItoa(min_header_version), + "protoc_version", SimpleItoa(PROTOBUF_C_VERSION_NUMBER)); + + for (int i = 0; i < file_->dependency_count(); i++) { + const ProtobufCFileOptions opt = + file_->dependency(i)->options().GetExtension(pb_c_file); + if (!opt.no_generate()) { + printer->Print( + "#include \"$dependency$.pb-c.h\"\n", + "dependency", StripProto(file_->dependency(i)->name())); + } + } + + printer->Print("\n"); + + // Generate forward declarations of classes. + for (int i = 0; i < file_->message_type_count(); i++) { + message_generators_[i]->GenerateStructTypedef(printer); + } + + printer->Print("\n"); + + // Generate enum definitions. + printer->Print("\n/* --- enums --- */\n\n"); + for (int i = 0; i < file_->message_type_count(); i++) { + message_generators_[i]->GenerateEnumDefinitions(printer); + } + for (int i = 0; i < file_->enum_type_count(); i++) { + enum_generators_[i]->GenerateDefinition(printer); + } + + // Generate descriptors. + printer->Print("\n/* --- descriptors --- */\n\n"); + for (int i = 0; i < file_->enum_type_count(); i++) { + enum_generators_[i]->GenerateDescriptorDeclarations(printer); + } + for (int i = 0; i < file_->message_type_count(); i++) { + message_generators_[i]->GenerateDescriptorDeclarations(printer); + } + for (int i = 0; i < file_->service_count(); i++) { + service_generators_[i]->GenerateDescriptorDeclarations(printer); + } + + // Generate class definitions. + printer->Print("\n/* --- messages --- */\n\n"); + printer->Print("extern \"C\" void message_init_generic(const ProtobufCMessageDescriptor * desc, ProtobufCMessage * message);\n\n" + "struct ProtobufCppMessage : public ProtobufCMessage\n" + "{\n" + " ProtobufCppMessage(const ProtobufCMessageDescriptor &descr)\n" + " {\n" + " message_init_generic(&descr, this);\n" + " }\n" + "};\n\n"); + + for (int i = 0; i < file_->message_type_count(); i++) { + message_generators_[i]->GenerateStructDefinition(printer); + } + + for (int i = 0; i < file_->message_type_count(); i++) { + const ProtobufCFileOptions opt = file_->options().GetExtension(pb_c_file); + + message_generators_[i]->GenerateHelperFunctionDeclarations( + printer, + opt.has_gen_pack_helpers(), + opt.gen_pack_helpers(), + false); + } + + printer->Print("/* --- per-message closures --- */\n\n"); + for (int i = 0; i < file_->message_type_count(); i++) { + message_generators_[i]->GenerateClosureTypedef(printer); + } + + // Generate service definitions. + printer->Print("\n/* --- services --- */\n\n"); + for (int i = 0; i < file_->service_count(); i++) { + service_generators_[i]->GenerateMainHFile(printer); + } + + // Declare extension identifiers. + for (int i = 0; i < file_->extension_count(); i++) { + extension_generators_[i]->GenerateDeclaration(printer); + } + + printer->Print( + "\n" + "PROTOBUF_C__END_DECLS\n" + "\n\n#endif /* PROTOBUF_C_$filename_identifier$__INCLUDED */\n", + "filename_identifier", filename_identifier); +} + +void FileGenerator::GenerateSource(io::Printer* printer) { + printer->Print( + "/* Generated by the protocol buffer compiler. DO NOT EDIT! */\n" + "/* Generated from: $filename$ */\n" + "\n" + "/* Do not generate deprecated warnings for self */\n" + "#ifndef PROTOBUF_C__NO_DEPRECATED\n" + "#define PROTOBUF_C__NO_DEPRECATED\n" + "#endif\n" + "\n" + "#include \"$basename$.pb-c.h\"\n", + "filename", file_->name(), + "basename", StripProto(file_->name())); + + const ProtobufCFileOptions opt = file_->options().GetExtension(pb_c_file); + + for (int i = 0; i < file_->message_type_count(); i++) { + message_generators_[i]->GenerateHelperFunctionDefinitions( + printer, + opt.has_gen_pack_helpers(), + opt.gen_pack_helpers(), + false); + } + for (int i = 0; i < file_->message_type_count(); i++) { + message_generators_[i]->GenerateMessageDescriptor(printer, + false); + } + for (int i = 0; i < file_->enum_type_count(); i++) { + enum_generators_[i]->GenerateEnumDescriptor(printer); + } + for (int i = 0; i < file_->service_count(); i++) { + service_generators_[i]->GenerateCFile(printer); + } + +} + +} // namespace c +} // namespace compiler +} // namespace protobuf +} // namespace google 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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[ + descriptor->nested_type_count()]), + enum_generators_(new std::unique_ptr[ + descriptor->enum_type_count()]), + extension_generators_(new std::unique_ptr[ + 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 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 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 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 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 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 diff --git a/tools/protoc-c/readme.txt b/tools/protoc-c/readme.txt new file mode 100644 index 0000000000..96719bfa29 --- /dev/null +++ b/tools/protoc-c/readme.txt @@ -0,0 +1,2 @@ +1. Retrieve standard protobuf-c compiler from https://github.com/protobuf-c/protobuf-c.git +2. Replace those two files in it \ No newline at end of file -- cgit v1.2.3