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#include <google/protobuf/compiler/cpp/cpp_file.h>
36#include <google/protobuf/compiler/cpp/cpp_enum.h>
37#include <google/protobuf/compiler/cpp/cpp_service.h>
38#include <google/protobuf/compiler/cpp/cpp_extension.h>
39#include <google/protobuf/compiler/cpp/cpp_helpers.h>
40#include <google/protobuf/compiler/cpp/cpp_message.h>
41#include <google/protobuf/compiler/cpp/cpp_field.h>
42#include <google/protobuf/io/printer.h>
43#include <google/protobuf/descriptor.pb.h>
44#include <google/protobuf/stubs/strutil.h>
45
46namespace google {
47namespace protobuf {
48namespace compiler {
49namespace cpp {
50
51// ===================================================================
52
53FileGenerator::FileGenerator(const FileDescriptor* file,
54                             const string& dllexport_decl)
55  : file_(file),
56    message_generators_(
57      new scoped_ptr<MessageGenerator>[file->message_type_count()]),
58    enum_generators_(
59      new scoped_ptr<EnumGenerator>[file->enum_type_count()]),
60    service_generators_(
61      new scoped_ptr<ServiceGenerator>[file->service_count()]),
62    extension_generators_(
63      new scoped_ptr<ExtensionGenerator>[file->extension_count()]),
64    dllexport_decl_(dllexport_decl) {
65
66  for (int i = 0; i < file->message_type_count(); i++) {
67    message_generators_[i].reset(
68      new MessageGenerator(file->message_type(i), dllexport_decl));
69  }
70
71  for (int i = 0; i < file->enum_type_count(); i++) {
72    enum_generators_[i].reset(
73      new EnumGenerator(file->enum_type(i), dllexport_decl));
74  }
75
76  for (int i = 0; i < file->service_count(); i++) {
77    service_generators_[i].reset(
78      new ServiceGenerator(file->service(i), dllexport_decl));
79  }
80
81  for (int i = 0; i < file->extension_count(); i++) {
82    extension_generators_[i].reset(
83      new ExtensionGenerator(file->extension(i), dllexport_decl));
84  }
85
86  SplitStringUsing(file_->package(), ".", &package_parts_);
87}
88
89FileGenerator::~FileGenerator() {}
90
91void FileGenerator::GenerateHeader(io::Printer* printer) {
92  string filename_identifier = FilenameIdentifier(file_->name());
93
94  // Generate top of header.
95  printer->Print(
96    "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
97    "// source: $filename$\n"
98    "\n"
99    "#ifndef PROTOBUF_$filename_identifier$__INCLUDED\n"
100    "#define PROTOBUF_$filename_identifier$__INCLUDED\n"
101    "\n"
102    "#include <string>\n"
103    "\n",
104    "filename", file_->name(),
105    "filename_identifier", filename_identifier);
106
107  printer->Print(
108    "#include <google/protobuf/stubs/common.h>\n"
109    "\n");
110
111  // Verify the protobuf library header version is compatible with the protoc
112  // version before going any further.
113  printer->Print(
114    "#if GOOGLE_PROTOBUF_VERSION < $min_header_version$\n"
115    "#error This file was generated by a newer version of protoc which is\n"
116    "#error incompatible with your Protocol Buffer headers.  Please update\n"
117    "#error your headers.\n"
118    "#endif\n"
119    "#if $protoc_version$ < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION\n"
120    "#error This file was generated by an older version of protoc which is\n"
121    "#error incompatible with your Protocol Buffer headers.  Please\n"
122    "#error regenerate this file with a newer version of protoc.\n"
123    "#endif\n"
124    "\n",
125    "min_header_version",
126      SimpleItoa(protobuf::internal::kMinHeaderVersionForProtoc),
127    "protoc_version", SimpleItoa(GOOGLE_PROTOBUF_VERSION));
128
129  // OK, it's now safe to #include other files.
130  printer->Print(
131    "#include <google/protobuf/generated_message_util.h>\n"
132    "#include <google/protobuf/repeated_field.h>\n"
133    "#include <google/protobuf/extension_set.h>\n");
134
135  if (HasDescriptorMethods(file_)) {
136    printer->Print(
137      "#include <google/protobuf/generated_message_reflection.h>\n");
138  }
139
140  if (HasGenericServices(file_)) {
141    printer->Print(
142      "#include <google/protobuf/service.h>\n");
143  }
144
145
146  for (int i = 0; i < file_->dependency_count(); i++) {
147    printer->Print(
148      "#include \"$dependency$.pb.h\"\n",
149      "dependency", StripProto(file_->dependency(i)->name()));
150  }
151
152  printer->Print(
153    "// @@protoc_insertion_point(includes)\n");
154
155  // Open namespace.
156  GenerateNamespaceOpeners(printer);
157
158  // Forward-declare the AddDescriptors, AssignDescriptors, and ShutdownFile
159  // functions, so that we can declare them to be friends of each class.
160  printer->Print(
161    "\n"
162    "// Internal implementation detail -- do not call these.\n"
163    "void $dllexport_decl$ $adddescriptorsname$();\n",
164    "adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
165    "dllexport_decl", dllexport_decl_);
166
167  printer->Print(
168    // Note that we don't put dllexport_decl on these because they are only
169    // called by the .pb.cc file in which they are defined.
170    "void $assigndescriptorsname$();\n"
171    "void $shutdownfilename$();\n"
172    "\n",
173    "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()),
174    "shutdownfilename", GlobalShutdownFileName(file_->name()));
175
176  // Generate forward declarations of classes.
177  for (int i = 0; i < file_->message_type_count(); i++) {
178    message_generators_[i]->GenerateForwardDeclaration(printer);
179  }
180
181  printer->Print("\n");
182
183  // Generate enum definitions.
184  for (int i = 0; i < file_->message_type_count(); i++) {
185    message_generators_[i]->GenerateEnumDefinitions(printer);
186  }
187  for (int i = 0; i < file_->enum_type_count(); i++) {
188    enum_generators_[i]->GenerateDefinition(printer);
189  }
190
191  printer->Print(kThickSeparator);
192  printer->Print("\n");
193
194  // Generate class definitions.
195  for (int i = 0; i < file_->message_type_count(); i++) {
196    if (i > 0) {
197      printer->Print("\n");
198      printer->Print(kThinSeparator);
199      printer->Print("\n");
200    }
201    message_generators_[i]->GenerateClassDefinition(printer);
202  }
203
204  printer->Print("\n");
205  printer->Print(kThickSeparator);
206  printer->Print("\n");
207
208  if (HasGenericServices(file_)) {
209    // Generate service definitions.
210    for (int i = 0; i < file_->service_count(); i++) {
211      if (i > 0) {
212        printer->Print("\n");
213        printer->Print(kThinSeparator);
214        printer->Print("\n");
215      }
216      service_generators_[i]->GenerateDeclarations(printer);
217    }
218
219    printer->Print("\n");
220    printer->Print(kThickSeparator);
221    printer->Print("\n");
222  }
223
224  // Declare extension identifiers.
225  for (int i = 0; i < file_->extension_count(); i++) {
226    extension_generators_[i]->GenerateDeclaration(printer);
227  }
228
229  printer->Print("\n");
230  printer->Print(kThickSeparator);
231  printer->Print("\n");
232
233  // Generate class inline methods.
234  for (int i = 0; i < file_->message_type_count(); i++) {
235    if (i > 0) {
236      printer->Print(kThinSeparator);
237      printer->Print("\n");
238    }
239    message_generators_[i]->GenerateInlineMethods(printer);
240  }
241
242  printer->Print(
243    "\n"
244    "// @@protoc_insertion_point(namespace_scope)\n");
245
246  // Close up namespace.
247  GenerateNamespaceClosers(printer);
248
249  // Emit GetEnumDescriptor specializations into google::protobuf namespace:
250  if (HasDescriptorMethods(file_)) {
251    // The SWIG conditional is to avoid a null-pointer dereference
252    // (bug 1984964) in swig-1.3.21 resulting from the following syntax:
253    //   namespace X { void Y<Z::W>(); }
254    // which appears in GetEnumDescriptor() specializations.
255    printer->Print(
256        "\n"
257        "#ifndef SWIG\n"
258        "namespace google {\nnamespace protobuf {\n"
259        "\n");
260    for (int i = 0; i < file_->message_type_count(); i++) {
261      message_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
262    }
263    for (int i = 0; i < file_->enum_type_count(); i++) {
264      enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
265    }
266    printer->Print(
267        "\n"
268        "}  // namespace google\n}  // namespace protobuf\n"
269        "#endif  // SWIG\n");
270  }
271
272  printer->Print(
273    "\n"
274    "// @@protoc_insertion_point(global_scope)\n"
275    "\n");
276
277  printer->Print(
278    "#endif  // PROTOBUF_$filename_identifier$__INCLUDED\n",
279    "filename_identifier", filename_identifier);
280}
281
282void FileGenerator::GenerateSource(io::Printer* printer) {
283  printer->Print(
284    "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
285    "\n"
286    // The generated code calls accessors that might be deprecated. We don't
287    // want the compiler to warn in generated code.
288    "#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION\n"
289    "#include \"$basename$.pb.h\"\n"
290
291    "#include <google/protobuf/stubs/once.h>\n"
292    "#include <google/protobuf/io/coded_stream.h>\n"
293    "#include <google/protobuf/wire_format_lite_inl.h>\n",
294    "basename", StripProto(file_->name()));
295
296  if (HasDescriptorMethods(file_)) {
297    printer->Print(
298      "#include <google/protobuf/descriptor.h>\n"
299      "#include <google/protobuf/reflection_ops.h>\n"
300      "#include <google/protobuf/wire_format.h>\n");
301  }
302
303  printer->Print(
304    "// @@protoc_insertion_point(includes)\n");
305
306  GenerateNamespaceOpeners(printer);
307
308  if (HasDescriptorMethods(file_)) {
309    printer->Print(
310      "\n"
311      "namespace {\n"
312      "\n");
313    for (int i = 0; i < file_->message_type_count(); i++) {
314      message_generators_[i]->GenerateDescriptorDeclarations(printer);
315    }
316    for (int i = 0; i < file_->enum_type_count(); i++) {
317      printer->Print(
318        "const ::google::protobuf::EnumDescriptor* $name$_descriptor_ = NULL;\n",
319        "name", ClassName(file_->enum_type(i), false));
320    }
321
322    if (HasGenericServices(file_)) {
323      for (int i = 0; i < file_->service_count(); i++) {
324        printer->Print(
325          "const ::google::protobuf::ServiceDescriptor* $name$_descriptor_ = NULL;\n",
326          "name", file_->service(i)->name());
327      }
328    }
329
330    printer->Print(
331      "\n"
332      "}  // namespace\n"
333      "\n");
334  }
335
336  // Define our externally-visible BuildDescriptors() function.  (For the lite
337  // library, all this does is initialize default instances.)
338  GenerateBuildDescriptors(printer);
339
340  // Generate enums.
341  for (int i = 0; i < file_->enum_type_count(); i++) {
342    enum_generators_[i]->GenerateMethods(printer);
343  }
344
345  // Generate classes.
346  for (int i = 0; i < file_->message_type_count(); i++) {
347    printer->Print("\n");
348    printer->Print(kThickSeparator);
349    printer->Print("\n");
350    message_generators_[i]->GenerateClassMethods(printer);
351  }
352
353  if (HasGenericServices(file_)) {
354    // Generate services.
355    for (int i = 0; i < file_->service_count(); i++) {
356      if (i == 0) printer->Print("\n");
357      printer->Print(kThickSeparator);
358      printer->Print("\n");
359      service_generators_[i]->GenerateImplementation(printer);
360    }
361  }
362
363  // Define extensions.
364  for (int i = 0; i < file_->extension_count(); i++) {
365    extension_generators_[i]->GenerateDefinition(printer);
366  }
367
368  printer->Print(
369    "\n"
370    "// @@protoc_insertion_point(namespace_scope)\n");
371
372  GenerateNamespaceClosers(printer);
373
374  printer->Print(
375    "\n"
376    "// @@protoc_insertion_point(global_scope)\n");
377}
378
379void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
380  // AddDescriptors() is a file-level procedure which adds the encoded
381  // FileDescriptorProto for this .proto file to the global DescriptorPool
382  // for generated files (DescriptorPool::generated_pool()).  It always runs
383  // at static initialization time, so all files will be registered before
384  // main() starts.  This procedure also constructs default instances and
385  // registers extensions.
386  //
387  // Its sibling, AssignDescriptors(), actually pulls the compiled
388  // FileDescriptor from the DescriptorPool and uses it to populate all of
389  // the global variables which store pointers to the descriptor objects.
390  // It also constructs the reflection objects.  It is called the first time
391  // anyone calls descriptor() or GetReflection() on one of the types defined
392  // in the file.
393
394  // In optimize_for = LITE_RUNTIME mode, we don't generate AssignDescriptors()
395  // and we only use AddDescriptors() to allocate default instances.
396  if (HasDescriptorMethods(file_)) {
397    printer->Print(
398      "\n"
399      "void $assigndescriptorsname$() {\n",
400      "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
401    printer->Indent();
402
403    // Make sure the file has found its way into the pool.  If a descriptor
404    // is requested *during* static init then AddDescriptors() may not have
405    // been called yet, so we call it manually.  Note that it's fine if
406    // AddDescriptors() is called multiple times.
407    printer->Print(
408      "$adddescriptorsname$();\n",
409      "adddescriptorsname", GlobalAddDescriptorsName(file_->name()));
410
411    // Get the file's descriptor from the pool.
412    printer->Print(
413      "const ::google::protobuf::FileDescriptor* file =\n"
414      "  ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(\n"
415      "    \"$filename$\");\n"
416      // Note that this GOOGLE_CHECK is necessary to prevent a warning about "file"
417      // being unused when compiling an empty .proto file.
418      "GOOGLE_CHECK(file != NULL);\n",
419      "filename", file_->name());
420
421    // Go through all the stuff defined in this file and generated code to
422    // assign the global descriptor pointers based on the file descriptor.
423    for (int i = 0; i < file_->message_type_count(); i++) {
424      message_generators_[i]->GenerateDescriptorInitializer(printer, i);
425    }
426    for (int i = 0; i < file_->enum_type_count(); i++) {
427      enum_generators_[i]->GenerateDescriptorInitializer(printer, i);
428    }
429    if (HasGenericServices(file_)) {
430      for (int i = 0; i < file_->service_count(); i++) {
431        service_generators_[i]->GenerateDescriptorInitializer(printer, i);
432      }
433    }
434
435    printer->Outdent();
436    printer->Print(
437      "}\n"
438      "\n");
439
440    // ---------------------------------------------------------------
441
442    // protobuf_AssignDescriptorsOnce():  The first time it is called, calls
443    // AssignDescriptors().  All later times, waits for the first call to
444    // complete and then returns.
445    printer->Print(
446      "namespace {\n"
447      "\n"
448      "GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);\n"
449      "inline void protobuf_AssignDescriptorsOnce() {\n"
450      "  ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,\n"
451      "                 &$assigndescriptorsname$);\n"
452      "}\n"
453      "\n",
454      "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
455
456    // protobuf_RegisterTypes():  Calls
457    // MessageFactory::InternalRegisterGeneratedType() for each message type.
458    printer->Print(
459      "void protobuf_RegisterTypes(const ::std::string&) {\n"
460      "  protobuf_AssignDescriptorsOnce();\n");
461    printer->Indent();
462
463    for (int i = 0; i < file_->message_type_count(); i++) {
464      message_generators_[i]->GenerateTypeRegistrations(printer);
465    }
466
467    printer->Outdent();
468    printer->Print(
469      "}\n"
470      "\n"
471      "}  // namespace\n");
472  }
473
474  // -----------------------------------------------------------------
475
476  // ShutdownFile():  Deletes descriptors, default instances, etc. on shutdown.
477  printer->Print(
478    "\n"
479    "void $shutdownfilename$() {\n",
480    "shutdownfilename", GlobalShutdownFileName(file_->name()));
481  printer->Indent();
482
483  for (int i = 0; i < file_->message_type_count(); i++) {
484    message_generators_[i]->GenerateShutdownCode(printer);
485  }
486
487  printer->Outdent();
488  printer->Print(
489    "}\n");
490
491  // -----------------------------------------------------------------
492
493  // Now generate the AddDescriptors() function.
494  printer->Print(
495    "\n"
496    "void $adddescriptorsname$() {\n"
497    // We don't need any special synchronization here because this code is
498    // called at static init time before any threads exist.
499    "  static bool already_here = false;\n"
500    "  if (already_here) return;\n"
501    "  already_here = true;\n"
502    "  GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
503    "\n",
504    "adddescriptorsname", GlobalAddDescriptorsName(file_->name()));
505  printer->Indent();
506
507  // Call the AddDescriptors() methods for all of our dependencies, to make
508  // sure they get added first.
509  for (int i = 0; i < file_->dependency_count(); i++) {
510    const FileDescriptor* dependency = file_->dependency(i);
511    // Print the namespace prefix for the dependency.
512    vector<string> dependency_package_parts;
513    SplitStringUsing(dependency->package(), ".", &dependency_package_parts);
514    printer->Print("::");
515    for (int i = 0; i < dependency_package_parts.size(); i++) {
516      printer->Print("$name$::",
517                     "name", dependency_package_parts[i]);
518    }
519    // Call its AddDescriptors function.
520    printer->Print(
521      "$name$();\n",
522      "name", GlobalAddDescriptorsName(dependency->name()));
523  }
524
525  if (HasDescriptorMethods(file_)) {
526    // Embed the descriptor.  We simply serialize the entire FileDescriptorProto
527    // and embed it as a string literal, which is parsed and built into real
528    // descriptors at initialization time.
529    FileDescriptorProto file_proto;
530    file_->CopyTo(&file_proto);
531    string file_data;
532    file_proto.SerializeToString(&file_data);
533
534    printer->Print(
535      "::google::protobuf::DescriptorPool::InternalAddGeneratedFile(");
536
537    // Only write 40 bytes per line.
538    static const int kBytesPerLine = 40;
539    for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
540      printer->Print("\n  \"$data$\"",
541        "data", CEscape(file_data.substr(i, kBytesPerLine)));
542    }
543    printer->Print(
544      ", $size$);\n",
545      "size", SimpleItoa(file_data.size()));
546
547    // Call MessageFactory::InternalRegisterGeneratedFile().
548    printer->Print(
549      "::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(\n"
550      "  \"$filename$\", &protobuf_RegisterTypes);\n",
551      "filename", file_->name());
552  }
553
554  // Allocate and initialize default instances.  This can't be done lazily
555  // since default instances are returned by simple accessors and are used with
556  // extensions.  Speaking of which, we also register extensions at this time.
557  for (int i = 0; i < file_->message_type_count(); i++) {
558    message_generators_[i]->GenerateDefaultInstanceAllocator(printer);
559  }
560  for (int i = 0; i < file_->extension_count(); i++) {
561    extension_generators_[i]->GenerateRegistration(printer);
562  }
563  for (int i = 0; i < file_->message_type_count(); i++) {
564    message_generators_[i]->GenerateDefaultInstanceInitializer(printer);
565  }
566
567  printer->Print(
568    "::google::protobuf::internal::OnShutdown(&$shutdownfilename$);\n",
569    "shutdownfilename", GlobalShutdownFileName(file_->name()));
570
571  printer->Outdent();
572
573  printer->Print(
574    "}\n"
575    "\n"
576    "// Force AddDescriptors() to be called at static initialization time.\n"
577    "struct StaticDescriptorInitializer_$filename$ {\n"
578    "  StaticDescriptorInitializer_$filename$() {\n"
579    "    $adddescriptorsname$();\n"
580    "  }\n"
581    "} static_descriptor_initializer_$filename$_;\n"
582    "\n",
583    "adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
584    "filename", FilenameIdentifier(file_->name()));
585}
586
587void FileGenerator::GenerateNamespaceOpeners(io::Printer* printer) {
588  if (package_parts_.size() > 0) printer->Print("\n");
589
590  for (int i = 0; i < package_parts_.size(); i++) {
591    printer->Print("namespace $part$ {\n",
592                   "part", package_parts_[i]);
593  }
594}
595
596void FileGenerator::GenerateNamespaceClosers(io::Printer* printer) {
597  if (package_parts_.size() > 0) printer->Print("\n");
598
599  for (int i = package_parts_.size() - 1; i >= 0; i--) {
600    printer->Print("}  // namespace $part$\n",
601                   "part", package_parts_[i]);
602  }
603}
604
605}  // namespace cpp
606}  // namespace compiler
607}  // namespace protobuf
608}  // namespace google
609