1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // http://code.google.com/p/protobuf/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 // Author: kenton@google.com (Kenton Varda)
32 // Based on original Protocol Buffers design by
33 // Sanjay Ghemawat, Jeff Dean, and others.
34
35 // Copyright (c) 2008-2014, Dave Benson and the protobuf-c authors.
36 // All rights reserved.
37 //
38 // Redistribution and use in source and binary forms, with or without
39 // modification, are permitted provided that the following conditions are
40 // met:
41 //
42 // * Redistributions of source code must retain the above copyright
43 // notice, this list of conditions and the following disclaimer.
44 //
45 // * Redistributions in binary form must reproduce the above
46 // copyright notice, this list of conditions and the following disclaimer
47 // in the documentation and/or other materials provided with the
48 // distribution.
49 //
50 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
51 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
52 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
53 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
54 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
55 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
56 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
57 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
58 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
59 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
60 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
61
62 // Modified to implement C code by Dave Benson.
63
64 #include <protoc-c/c_file.h>
65 #include <protoc-c/c_enum.h>
66 #include <protoc-c/c_service.h>
67 #include <protoc-c/c_extension.h>
68 #include <protoc-c/c_helpers.h>
69 #include <protoc-c/c_message.h>
70 #include <google/protobuf/io/printer.h>
71 #include <protobuf-c/protobuf-c.pb.h>
72
73 #include "protobuf-c.h"
74
75 namespace google {
76 namespace protobuf {
77 namespace compiler {
78 namespace c {
79
80 // ===================================================================
81
FileGenerator(const FileDescriptor * file,const std::string & dllexport_decl)82 FileGenerator::FileGenerator(const FileDescriptor* file,
83 const std::string& dllexport_decl)
84 : file_(file),
85 message_generators_(
86 new std::unique_ptr<MessageGenerator>[file->message_type_count()]),
87 enum_generators_(
88 new std::unique_ptr<EnumGenerator>[file->enum_type_count()]),
89 service_generators_(
90 new std::unique_ptr<ServiceGenerator>[file->service_count()]),
91 extension_generators_(
92 new std::unique_ptr<ExtensionGenerator>[file->extension_count()]) {
93
94 for (int i = 0; i < file->message_type_count(); i++) {
95 message_generators_[i].reset(
96 new MessageGenerator(file->message_type(i), dllexport_decl));
97 }
98
99 for (int i = 0; i < file->enum_type_count(); i++) {
100 enum_generators_[i].reset(
101 new EnumGenerator(file->enum_type(i), dllexport_decl));
102 }
103
104 for (int i = 0; i < file->service_count(); i++) {
105 service_generators_[i].reset(
106 new ServiceGenerator(file->service(i), dllexport_decl));
107 }
108
109 for (int i = 0; i < file->extension_count(); i++) {
110 extension_generators_[i].reset(
111 new ExtensionGenerator(file->extension(i), dllexport_decl));
112 }
113 }
114
~FileGenerator()115 FileGenerator::~FileGenerator() {}
116
GenerateHeader(io::Printer * printer)117 void FileGenerator::GenerateHeader(io::Printer* printer) {
118 std::string filename_identifier = FilenameIdentifier(file_->name());
119
120 int min_header_version = 1000000;
121 #if defined(HAVE_PROTO3)
122 if (file_->syntax() == FileDescriptor::SYNTAX_PROTO3) {
123 min_header_version = 1003000;
124 }
125 #endif
126
127 // Generate top of header.
128 printer->Print(
129 "/* Generated by the protocol buffer compiler. DO NOT EDIT! */\n"
130 "/* Generated from: $filename$ */\n"
131 "\n"
132 "#ifndef PROTOBUF_C_$filename_identifier$__INCLUDED\n"
133 "#define PROTOBUF_C_$filename_identifier$__INCLUDED\n"
134 "\n"
135 "#include <protobuf-c/protobuf-c.h>\n"
136 "\n"
137 "PROTOBUF_C__BEGIN_DECLS\n"
138 "\n",
139 "filename", file_->name(),
140 "filename_identifier", filename_identifier);
141
142 // Verify the protobuf-c library header version is compatible with the
143 // protoc-c version before going any further.
144 printer->Print(
145 "#if PROTOBUF_C_VERSION_NUMBER < $min_header_version$\n"
146 "# error This file was generated by a newer version of protoc-c which is "
147 "incompatible with your libprotobuf-c headers. Please update your headers.\n"
148 "#elif $protoc_version$ < PROTOBUF_C_MIN_COMPILER_VERSION\n"
149 "# error This file was generated by an older version of protoc-c which is "
150 "incompatible with your libprotobuf-c headers. Please regenerate this file "
151 "with a newer version of protoc-c.\n"
152 "#endif\n"
153 "\n",
154 "min_header_version", SimpleItoa(min_header_version),
155 "protoc_version", SimpleItoa(PROTOBUF_C_VERSION_NUMBER));
156
157 for (int i = 0; i < file_->dependency_count(); i++) {
158 const ProtobufCFileOptions opt =
159 file_->dependency(i)->options().GetExtension(pb_c_file);
160 if (!opt.no_generate()) {
161 printer->Print(
162 "#include \"$dependency$.pb-c.h\"\n",
163 "dependency", StripProto(file_->dependency(i)->name()));
164 }
165 }
166
167 printer->Print("\n");
168
169 // Generate forward declarations of classes.
170 for (int i = 0; i < file_->message_type_count(); i++) {
171 message_generators_[i]->GenerateStructTypedef(printer);
172 }
173
174 printer->Print("\n");
175
176 // Generate enum definitions.
177 printer->Print("\n/* --- enums --- */\n\n");
178 for (int i = 0; i < file_->message_type_count(); i++) {
179 message_generators_[i]->GenerateEnumDefinitions(printer);
180 }
181 for (int i = 0; i < file_->enum_type_count(); i++) {
182 enum_generators_[i]->GenerateDefinition(printer);
183 }
184
185 // Generate class definitions.
186 printer->Print("\n/* --- messages --- */\n\n");
187 for (int i = 0; i < file_->message_type_count(); i++) {
188 message_generators_[i]->GenerateStructDefinition(printer);
189 }
190
191 for (int i = 0; i < file_->message_type_count(); i++) {
192 const ProtobufCFileOptions opt = file_->options().GetExtension(pb_c_file);
193
194 message_generators_[i]->GenerateHelperFunctionDeclarations(
195 printer,
196 opt.has_gen_pack_helpers(),
197 opt.gen_pack_helpers(),
198 opt.gen_init_helpers());
199 }
200
201 printer->Print("/* --- per-message closures --- */\n\n");
202 for (int i = 0; i < file_->message_type_count(); i++) {
203 message_generators_[i]->GenerateClosureTypedef(printer);
204 }
205
206 // Generate service definitions.
207 printer->Print("\n/* --- services --- */\n\n");
208 for (int i = 0; i < file_->service_count(); i++) {
209 service_generators_[i]->GenerateMainHFile(printer);
210 }
211
212 // Declare extension identifiers.
213 for (int i = 0; i < file_->extension_count(); i++) {
214 extension_generators_[i]->GenerateDeclaration(printer);
215 }
216
217 printer->Print("\n/* --- descriptors --- */\n\n");
218 for (int i = 0; i < file_->enum_type_count(); i++) {
219 enum_generators_[i]->GenerateDescriptorDeclarations(printer);
220 }
221 for (int i = 0; i < file_->message_type_count(); i++) {
222 message_generators_[i]->GenerateDescriptorDeclarations(printer);
223 }
224 for (int i = 0; i < file_->service_count(); i++) {
225 service_generators_[i]->GenerateDescriptorDeclarations(printer);
226 }
227
228 printer->Print(
229 "\n"
230 "PROTOBUF_C__END_DECLS\n"
231 "\n\n#endif /* PROTOBUF_C_$filename_identifier$__INCLUDED */\n",
232 "filename_identifier", filename_identifier);
233 }
234
GenerateSource(io::Printer * printer)235 void FileGenerator::GenerateSource(io::Printer* printer) {
236 printer->Print(
237 "/* Generated by the protocol buffer compiler. DO NOT EDIT! */\n"
238 "/* Generated from: $filename$ */\n"
239 "\n"
240 "/* Do not generate deprecated warnings for self */\n"
241 "#ifndef PROTOBUF_C__NO_DEPRECATED\n"
242 "#define PROTOBUF_C__NO_DEPRECATED\n"
243 "#endif\n"
244 "\n"
245 "#include \"$basename$.pb-c.h\"\n",
246 "filename", file_->name(),
247 "basename", StripProto(file_->name()));
248
249 const ProtobufCFileOptions opt = file_->options().GetExtension(pb_c_file);
250
251 for (int i = 0; i < file_->message_type_count(); i++) {
252 message_generators_[i]->GenerateHelperFunctionDefinitions(
253 printer,
254 opt.has_gen_pack_helpers(),
255 opt.gen_pack_helpers(),
256 opt.gen_init_helpers());
257 }
258 for (int i = 0; i < file_->message_type_count(); i++) {
259 message_generators_[i]->GenerateMessageDescriptor(printer,
260 opt.gen_init_helpers());
261 }
262 for (int i = 0; i < file_->enum_type_count(); i++) {
263 enum_generators_[i]->GenerateEnumDescriptor(printer);
264 }
265 for (int i = 0; i < file_->service_count(); i++) {
266 service_generators_[i]->GenerateCFile(printer);
267 }
268
269 }
270
271 } // namespace c
272 } // namespace compiler
273 } // namespace protobuf
274 } // namespace google
275