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