summaryrefslogtreecommitdiff
path: root/tools/protoc-c
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2023-06-09 13:01:10 +0300
committerGeorge Hazan <ghazan@miranda.im>2023-06-09 13:01:10 +0300
commitb24c724f3342d0238f4dee37569638e73eaf8a3e (patch)
tree7f4fc833d1fde8aa73bfbb488bad470584b7c190 /tools/protoc-c
parent6eca44b20b08364d18cbec8c5e4a3973deff572d (diff)
Saving modified protoc-c used to generate a code from Miranda .proto files
Diffstat (limited to 'tools/protoc-c')
-rw-r--r--tools/protoc-c/c_file.cc284
-rw-r--r--tools/protoc-c/c_message.cc611
-rw-r--r--tools/protoc-c/readme.txt2
3 files changed, 897 insertions, 0 deletions
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 <protoc-c/c_file.h>
+#include <protoc-c/c_enum.h>
+#include <protoc-c/c_service.h>
+#include <protoc-c/c_extension.h>
+#include <protoc-c/c_helpers.h>
+#include <protoc-c/c_message.h>
+#include <google/protobuf/io/printer.h>
+#include <protobuf-c/protobuf-c.pb.h>
+
+#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<MessageGenerator>[file->message_type_count()]),
+ enum_generators_(
+ new std::unique_ptr<EnumGenerator>[file->enum_type_count()]),
+ service_generators_(
+ new std::unique_ptr<ServiceGenerator>[file->service_count()]),
+ extension_generators_(
+ new std::unique_ptr<ExtensionGenerator>[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 <protobuf-c/protobuf-c.h>\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 <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
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