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