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