aboutsummaryrefslogtreecommitdiff
path: root/src/google
diff options
context:
space:
mode:
Diffstat (limited to 'src/google')
-rwxr-xr-xsrc/google/protobuf/compiler/js/js_generator.cc289
-rwxr-xr-xsrc/google/protobuf/compiler/js/js_generator.h18
-rw-r--r--src/google/protobuf/compiler/main.cc2
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc17
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_enum_field.h12
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_field.cc60
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_field.h28
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_file.cc10
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_file.h4
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_generator.cc20
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_helpers.cc48
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_helpers.h10
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_map_field.cc51
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_map_field.h8
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_message.cc14
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_message.h4
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_message_field.cc20
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_message_field.h15
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc27
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h19
-rw-r--r--src/google/protobuf/stubs/atomicops.h2
-rw-r--r--src/google/protobuf/stubs/atomicops_internals_ppc_gcc.h155
-rw-r--r--src/google/protobuf/stubs/platform_macros.h3
23 files changed, 647 insertions, 189 deletions
diff --git a/src/google/protobuf/compiler/js/js_generator.cc b/src/google/protobuf/compiler/js/js_generator.cc
index e6c3b36a..0de7e2c6 100755
--- a/src/google/protobuf/compiler/js/js_generator.cc
+++ b/src/google/protobuf/compiler/js/js_generator.cc
@@ -134,12 +134,51 @@ bool IsReserved(const string& ident) {
// Returns a copy of |filename| with any trailing ".protodevel" or ".proto
// suffix stripped.
+// TODO(robinson): Unify with copy in compiler/cpp/internal/helpers.cc.
string StripProto(const string& filename) {
const char* suffix = HasSuffixString(filename, ".protodevel")
? ".protodevel" : ".proto";
return StripSuffixString(filename, suffix);
}
+// Given a filename like foo/bar/baz.proto, returns the correspoding JavaScript
+// file foo/bar/baz.js.
+string GetJSFilename(const string& filename) {
+ const char* suffix = HasSuffixString(filename, ".protodevel")
+ ? ".protodevel" : ".proto";
+ return StripSuffixString(filename, suffix) + "_pb.js";
+}
+
+// Given a filename like foo/bar/baz.proto, returns the root directory
+// path ../../
+string GetRootPath(const string& filename) {
+ size_t slashes = std::count(filename.begin(), filename.end(), '/');
+ if (slashes == 0) {
+ return "./";
+ }
+ string result = "";
+ for (size_t i = 0; i < slashes; i++) {
+ result += "../";
+ }
+ return result;
+}
+
+// Returns the alias we assign to the module of the given .proto filename
+// when importing.
+string ModuleAlias(const string& filename) {
+ // This scheme could technically cause problems if a file includes any 2 of:
+ // foo/bar_baz.proto
+ // foo_bar_baz.proto
+ // foo_bar/baz.proto
+ //
+ // We'll worry about this problem if/when we actually see it. This name isn't
+ // exposed to users so we can change it later if we need to.
+ string basename = StripProto(filename);
+ StripString(&basename, "-", '$');
+ StripString(&basename, "/", '_');
+ return basename + "_pb";
+}
+
// Returns the fully normalized JavaScript path for the given
// file descriptor's package.
string GetPath(const GeneratorOptions& options,
@@ -215,6 +254,26 @@ string GetPath(const GeneratorOptions& options,
value_descriptor->type()) + "." + value_descriptor->name();
}
+string MaybeCrossFileRef(const GeneratorOptions& options,
+ const FileDescriptor* from_file,
+ const Descriptor* to_message) {
+ if (options.import_style == GeneratorOptions::IMPORT_COMMONJS &&
+ from_file != to_message->file()) {
+ // Cross-file ref in CommonJS needs to use the module alias instead of
+ // the global name.
+ return ModuleAlias(to_message->file()->name()) + "." + to_message->name();
+ } else {
+ // Within a single file we use a full name.
+ return GetPath(options, to_message);
+ }
+}
+
+string SubmessageTypeRef(const GeneratorOptions& options,
+ const FieldDescriptor* field) {
+ GOOGLE_CHECK(field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE);
+ return MaybeCrossFileRef(options, field->file(), field->message_type());
+}
+
// - Object field name: LOWER_UNDERSCORE -> LOWER_CAMEL, except for group fields
// (UPPER_CAMEL -> LOWER_CAMEL), with "List" (or "Map") appended if appropriate,
// and with reserved words triggering a "pb_" prefix.
@@ -952,11 +1011,13 @@ string RelativeTypeName(const FieldDescriptor* field) {
}
string JSExtensionsObjectName(const GeneratorOptions& options,
+ const FileDescriptor* from_file,
const Descriptor* desc) {
if (desc->full_name() == "google.protobuf.bridge.MessageSet") {
+ // TODO(haberman): fix this for the IMPORT_COMMONJS case.
return "jspb.Message.messageSetExtensions";
} else {
- return GetPath(options, desc) + ".extensions";
+ return MaybeCrossFileRef(options, from_file, desc) + ".extensions";
}
}
@@ -1113,19 +1174,24 @@ void Generator::GenerateHeader(const GeneratorOptions& options,
"\n");
}
+void Generator::FindProvidesForFile(const GeneratorOptions& options,
+ io::Printer* printer,
+ const FileDescriptor* file,
+ std::set<string>* provided) const {
+ for (int i = 0; i < file->message_type_count(); i++) {
+ FindProvidesForMessage(options, printer, file->message_type(i), provided);
+ }
+ for (int i = 0; i < file->enum_type_count(); i++) {
+ FindProvidesForEnum(options, printer, file->enum_type(i), provided);
+ }
+}
+
void Generator::FindProvides(const GeneratorOptions& options,
io::Printer* printer,
const vector<const FileDescriptor*>& files,
std::set<string>* provided) const {
for (int i = 0; i < files.size(); i++) {
- for (int j = 0; j < files[i]->message_type_count(); j++) {
- FindProvidesForMessage(options, printer, files[i]->message_type(j),
- provided);
- }
- for (int j = 0; j < files[i]->enum_type_count(); j++) {
- FindProvidesForEnum(options, printer, files[i]->enum_type(j),
- provided);
- }
+ FindProvidesForFile(options, printer, files[i], provided);
}
printer->Print("\n");
@@ -1204,38 +1270,45 @@ void Generator::GenerateRequires(const GeneratorOptions& options,
io::Printer* printer,
const vector<const FileDescriptor*>& files,
std::set<string>* provided) const {
- std::set<string> required;
- std::set<string> forwards;
- bool have_extensions = false;
- bool have_message = false;
-
- for (int i = 0; i < files.size(); i++) {
- for (int j = 0; j < files[i]->message_type_count(); j++) {
- FindRequiresForMessage(options,
- files[i]->message_type(j),
- &required, &forwards, &have_message);
- }
- if (!have_extensions && HasExtensions(files[i])) {
- have_extensions = true;
- }
+ if (options.import_style == GeneratorOptions::IMPORT_BROWSER) {
+ return;
+ } else if (options.import_style == GeneratorOptions::IMPORT_CLOSURE) {
+ // For Closure imports we need to import every message type individually.
+ std::set<string> required;
+ std::set<string> forwards;
+ bool have_extensions = false;
+ bool have_message = false;
- for (int j = 0; j < files[i]->extension_count(); j++) {
- const FieldDescriptor* extension = files[i]->extension(j);
- if (IgnoreField(extension)) {
- continue;
+ for (int i = 0; i < files.size(); i++) {
+ for (int j = 0; j < files[i]->message_type_count(); j++) {
+ FindRequiresForMessage(options,
+ files[i]->message_type(j),
+ &required, &forwards, &have_message);
}
- if (extension->containing_type()->full_name() !=
- "google.protobuf.bridge.MessageSet") {
- required.insert(GetPath(options, extension->containing_type()));
+ if (!have_extensions && HasExtensions(files[i])) {
+ have_extensions = true;
+ }
+
+ for (int j = 0; j < files[i]->extension_count(); j++) {
+ const FieldDescriptor* extension = files[i]->extension(j);
+ if (IgnoreField(extension)) {
+ continue;
+ }
+ if (extension->containing_type()->full_name() !=
+ "google.protobuf.bridge.MessageSet") {
+ required.insert(GetPath(options, extension->containing_type()));
+ }
+ FindRequiresForField(options, extension, &required, &forwards);
+ have_extensions = true;
}
- FindRequiresForField(options, extension, &required, &forwards);
- have_extensions = true;
}
- }
- GenerateRequiresImpl(options, printer, &required, &forwards, provided,
- /* require_jspb = */ have_message,
- /* require_extension = */ have_extensions);
+ GenerateRequiresImpl(options, printer, &required, &forwards, provided,
+ /* require_jspb = */ have_message,
+ /* require_extension = */ have_extensions);
+ } else if (options.import_style == GeneratorOptions::IMPORT_COMMONJS) {
+ // CommonJS imports are based on files
+ }
}
void Generator::GenerateRequires(const GeneratorOptions& options,
@@ -1406,6 +1479,12 @@ void Generator::GenerateClass(const GeneratorOptions& options,
if (IsExtendable(desc) && desc->full_name() != "google.protobuf.bridge.MessageSet") {
GenerateClassExtensionFieldInfo(options, printer, desc);
}
+
+ if (options.import_style != GeneratorOptions:: IMPORT_CLOSURE) {
+ for (int i = 0; i < desc->extension_count(); i++) {
+ GenerateExtension(options, printer, desc->extension(i));
+ }
+ }
}
// Recurse on nested types.
@@ -1623,7 +1702,7 @@ void Generator::GenerateClassToObject(const GeneratorOptions& options,
"obj,\n"
" $extObject$, $class$.prototype.getExtension,\n"
" includeInstance);\n",
- "extObject", JSExtensionsObjectName(options, desc),
+ "extObject", JSExtensionsObjectName(options, desc->file(), desc),
"class", GetPath(options, desc));
}
@@ -1652,13 +1731,13 @@ void Generator::GenerateClassFieldToObject(const GeneratorOptions& options,
printer->Print("jspb.Message.toObjectList(msg.get$getter$(),\n"
" $type$.toObject, includeInstance)",
"getter", JSGetterName(field),
- "type", GetPath(options, field->message_type()));
+ "type", SubmessageTypeRef(options, field));
}
} else {
printer->Print("(f = msg.get$getter$()) && "
"$type$.toObject(includeInstance, f)",
"getter", JSGetterName(field),
- "type", GetPath(options, field->message_type()));
+ "type", SubmessageTypeRef(options, field));
}
} else {
// Simple field (singular or repeated).
@@ -1723,7 +1802,7 @@ void Generator::GenerateClassFieldFromObject(
" }));\n",
"name", JSObjectFieldName(field),
"index", JSFieldIndex(field),
- "fieldclass", GetPath(options, field->message_type()));
+ "fieldclass", SubmessageTypeRef(options, field));
}
} else {
printer->Print(
@@ -1731,7 +1810,7 @@ void Generator::GenerateClassFieldFromObject(
" msg, $index$, $fieldclass$.fromObject(obj.$name$));\n",
"name", JSObjectFieldName(field),
"index", JSFieldIndex(field),
- "fieldclass", GetPath(options, field->message_type()));
+ "fieldclass", SubmessageTypeRef(options, field));
}
} else {
// Simple (primitive) field.
@@ -1815,7 +1894,7 @@ void Generator::GenerateClassField(const GeneratorOptions& options,
/* always_singular = */ false),
"rpt", (field->is_repeated() ? "Repeated" : ""),
"index", JSFieldIndex(field),
- "wrapperclass", GetPath(options, field->message_type()),
+ "wrapperclass", SubmessageTypeRef(options, field),
"required", (field->label() == FieldDescriptor::LABEL_REQUIRED ?
", 1" : ""));
printer->Print(
@@ -2043,7 +2122,7 @@ void Generator::GenerateClassDeserializeBinary(const GeneratorOptions& options,
" $class$.prototype.getExtension,\n"
" $class$.prototype.setExtension);\n"
" break;\n",
- "extobj", JSExtensionsObjectName(options, desc),
+ "extobj", JSExtensionsObjectName(options, desc->file(), desc),
"class", GetPath(options, desc));
} else {
printer->Print(
@@ -2073,7 +2152,7 @@ void Generator::GenerateClassDeserializeBinaryField(
" var value = new $fieldclass$;\n"
" reader.read$msgOrGroup$($grpfield$value,"
"$fieldclass$.deserializeBinaryFromReader);\n",
- "fieldclass", GetPath(options, field->message_type()),
+ "fieldclass", SubmessageTypeRef(options, field),
"msgOrGroup", (field->type() == FieldDescriptor::TYPE_GROUP) ?
"Group" : "Message",
"grpfield", (field->type() == FieldDescriptor::TYPE_GROUP) ?
@@ -2149,7 +2228,7 @@ void Generator::GenerateClassSerializeBinary(const GeneratorOptions& options,
printer->Print(
" jspb.Message.serializeBinaryExtensions(this, writer, $extobj$,\n"
" $class$.prototype.getExtension);\n",
- "extobj", JSExtensionsObjectName(options, desc),
+ "extobj", JSExtensionsObjectName(options, desc->file(), desc),
"class", GetPath(options, desc));
}
@@ -2222,7 +2301,7 @@ void Generator::GenerateClassSerializeBinaryField(
printer->Print(
",\n"
" $submsg$.serializeBinaryToWriter\n",
- "submsg", GetPath(options, field->message_type()));
+ "submsg", SubmessageTypeRef(options, field));
} else {
printer->Print("\n");
}
@@ -2290,9 +2369,9 @@ void Generator::GenerateExtension(const GeneratorOptions& options,
"index", SimpleItoa(field->number()),
"name", JSObjectFieldName(field),
"ctor", (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ?
- GetPath(options, field->message_type()) : string("null")),
+ SubmessageTypeRef(options, field) : string("null")),
"toObject", (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ?
- (GetPath(options, field->message_type()) + ".toObject") :
+ (SubmessageTypeRef(options, field) + ".toObject") :
string("null")),
"repeated", (field->is_repeated() ? "1" : "0"));
@@ -2308,11 +2387,11 @@ void Generator::GenerateExtension(const GeneratorOptions& options,
"binaryWriterFn", JSBinaryWriterMethodName(field),
"binaryMessageSerializeFn",
(field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) ?
- (GetPath(options, field->message_type()) +
+ (SubmessageTypeRef(options, field) +
".serializeBinaryToWriter") : "null",
"binaryMessageDeserializeFn",
(field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) ?
- (GetPath(options, field->message_type()) +
+ (SubmessageTypeRef(options, field) +
".deserializeBinaryFromReader") : "null",
"isPacked", (field->is_packed() ? "true" : "false"));
} else {
@@ -2324,7 +2403,8 @@ void Generator::GenerateExtension(const GeneratorOptions& options,
"// toObject() will function correctly.\n"
"$extendName$[$index$] = $class$.$name$;\n"
"\n",
- "extendName", JSExtensionsObjectName(options, field->containing_type()),
+ "extendName", JSExtensionsObjectName(options, field->file(),
+ field->containing_type()),
"index", SimpleItoa(field->number()),
"class", extension_scope,
"name", JSObjectFieldName(field));
@@ -2364,6 +2444,19 @@ bool GeneratorOptions::ParseFromOptions(
namespace_prefix = options[i].second;
} else if (options[i].first == "library") {
library = options[i].second;
+ } else if (options[i].first == "import_style") {
+ if (options[i].second == "closure") {
+ import_style = IMPORT_CLOSURE;
+ } else if (options[i].second == "commonjs") {
+ import_style = IMPORT_COMMONJS;
+ } else if (options[i].second == "browser") {
+ import_style = IMPORT_BROWSER;
+ } else if (options[i].second == "es6") {
+ import_style = IMPORT_ES6;
+ } else {
+ *error = "Unknown import style " + options[i].second + ", expected " +
+ "one of: closure, commonjs, browser, es6.";
+ }
} else {
// Assume any other option is an output directory, as long as it is a bare
// `key` rather than a `key=value` option.
@@ -2375,6 +2468,11 @@ bool GeneratorOptions::ParseFromOptions(
}
}
+ if (!library.empty() && import_style != IMPORT_CLOSURE) {
+ *error = "The library option should only be used for "
+ "import_style=closure";
+ }
+
return true;
}
@@ -2418,6 +2516,63 @@ void Generator::GenerateFileAndDeps(
}
}
+void Generator::GenerateFile(const GeneratorOptions& options,
+ io::Printer* printer,
+ const FileDescriptor* file) const {
+ GenerateHeader(options, printer);
+
+ // Generate "require" statements.
+ if (options.import_style == GeneratorOptions::IMPORT_COMMONJS) {
+ printer->Print("var jspb = require('google-protobuf');\n");
+ printer->Print("var goog = jspb;\n");
+ printer->Print("var global = Function('return this')();\n\n");
+
+ for (int i = 0; i < file->dependency_count(); i++) {
+ const std::string& name = file->dependency(i)->name();
+ printer->Print(
+ "var $alias$ = require('$file$');\n",
+ "alias", ModuleAlias(name),
+ "file", GetRootPath(file->name()) + GetJSFilename(name));
+ }
+ }
+
+ // We aren't using Closure's import system, but we use goog.exportSymbol()
+ // to construct the expected tree of objects, eg.
+ //
+ // goog.exportSymbol('foo.bar.Baz', null, this);
+ //
+ // // Later generated code expects foo.bar = {} to exist:
+ // foo.bar.Baz = function() { /* ... */ }
+ std::set<std::string> provided;
+
+ // Cover the case where this file declares extensions but no messages.
+ // This will ensure that the file-level object will be declared to hold
+ // the extensions.
+ for (int i = 0; i < file->extension_count(); i++) {
+ provided.insert(file->extension(i)->full_name());
+ }
+
+ FindProvidesForFile(options, printer, file, &provided);
+ for (std::set<string>::iterator it = provided.begin();
+ it != provided.end(); ++it) {
+ printer->Print("goog.exportSymbol('$name$', null, global);\n",
+ "name", *it);
+ }
+
+ GenerateClassesAndEnums(options, printer, file);
+
+ // Extensions nested inside messages are emitted inside
+ // GenerateClassesAndEnums().
+ for (int i = 0; i < file->extension_count(); i++) {
+ GenerateExtension(options, printer, file->extension(i));
+ }
+
+ if (options.import_style == GeneratorOptions::IMPORT_COMMONJS) {
+ printer->Print("goog.object.extend(exports, $package$);\n",
+ "package", GetPath(options, file));
+ }
+}
+
bool Generator::GenerateAll(const vector<const FileDescriptor*>& files,
const string& parameter,
GeneratorContext* context,
@@ -2430,10 +2585,14 @@ bool Generator::GenerateAll(const vector<const FileDescriptor*>& files,
}
- // We're either generating a single library file with definitions for message
- // and enum types in *all* FileDescriptor inputs, or we're generating a single
- // file for each type.
- if (options.library != "") {
+ // There are three schemes for where output files go:
+ //
+ // - import_style = IMPORT_CLOSURE, library non-empty: all output in one file
+ // - import_style = IMPORT_CLOSURE, library empty: one output file per type
+ // - import_style != IMPORT_CLOSURE: one output file per .proto file
+ if (options.import_style == GeneratorOptions::IMPORT_CLOSURE &&
+ options.library != "") {
+ // All output should go in a single file.
string filename = options.output_dir + "/" + options.library + ".js";
google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
GOOGLE_CHECK(output.get());
@@ -2469,7 +2628,7 @@ bool Generator::GenerateAll(const vector<const FileDescriptor*>& files,
if (printer.failed()) {
return false;
}
- } else {
+ } else if (options.import_style == GeneratorOptions::IMPORT_CLOSURE) {
// Collect all types, and print each type to a separate file. Pull out
// free-floating extensions while we make this pass.
map< string, vector<const FieldDescriptor*> > extensions_by_namespace;
@@ -2611,6 +2770,24 @@ bool Generator::GenerateAll(const vector<const FileDescriptor*>& files,
}
}
}
+ } else {
+ // Generate one output file per input (.proto) file.
+
+ for (int i = 0; i < files.size(); i++) {
+ const google::protobuf::FileDescriptor* file = files[i];
+
+ string filename = options.output_dir + "/" + GetJSFilename(file->name());
+ google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
+ context->Open(filename));
+ GOOGLE_CHECK(output.get());
+ io::Printer printer(output.get(), '$');
+
+ GenerateFile(options, &printer, file);
+
+ if (printer.failed()) {
+ return false;
+ }
+ }
}
return true;
diff --git a/src/google/protobuf/compiler/js/js_generator.h b/src/google/protobuf/compiler/js/js_generator.h
index db2dceb3..db9178d3 100755
--- a/src/google/protobuf/compiler/js/js_generator.h
+++ b/src/google/protobuf/compiler/js/js_generator.h
@@ -67,6 +67,13 @@ struct GeneratorOptions {
bool error_on_name_conflict;
// Enable binary-format support?
bool binary;
+ // What style of imports should be used.
+ enum ImportStyle {
+ IMPORT_CLOSURE, // goog.require()
+ IMPORT_COMMONJS, // require()
+ IMPORT_BROWSER, // no import statements
+ IMPORT_ES6, // import { member } from ''
+ } import_style;
GeneratorOptions()
: add_require_for_enums(false),
@@ -75,7 +82,8 @@ struct GeneratorOptions {
namespace_prefix(""),
library(""),
error_on_name_conflict(false),
- binary(false) {}
+ binary(false),
+ import_style(IMPORT_CLOSURE) {}
bool ParseFromOptions(
const vector< pair< string, string > >& options,
@@ -111,6 +119,10 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator {
io::Printer* printer,
const vector<const FileDescriptor*>& file,
std::set<string>* provided) const;
+ void FindProvidesForFile(const GeneratorOptions& options,
+ io::Printer* printer,
+ const FileDescriptor* file,
+ std::set<string>* provided) const;
void FindProvidesForMessage(const GeneratorOptions& options,
io::Printer* printer,
const Descriptor* desc,
@@ -168,6 +180,10 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator {
std::set<string>* required,
std::set<string>* forwards) const;
+ void GenerateFile(const GeneratorOptions& options,
+ io::Printer* printer,
+ const FileDescriptor* file) const;
+
// Generate definitions for all message classes and enums in all files,
// processing the files in dependence order.
void GenerateFilesInDepOrder(const GeneratorOptions& options,
diff --git a/src/google/protobuf/compiler/main.cc b/src/google/protobuf/compiler/main.cc
index 97df536e..66ad13b7 100644
--- a/src/google/protobuf/compiler/main.cc
+++ b/src/google/protobuf/compiler/main.cc
@@ -78,7 +78,7 @@ int main(int argc, char* argv[]) {
// Objective C
google::protobuf::compiler::objectivec::ObjectiveCGenerator objc_generator;
- cli.RegisterGenerator("--objc_out", &objc_generator,
+ cli.RegisterGenerator("--objc_out", "--objc_opt", &objc_generator,
"Generate Objective C header and source.");
// JavaScript
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc
index 30a13ddb..ecc77f6b 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc
@@ -44,6 +44,7 @@ namespace compiler {
namespace objectivec {
namespace {
+
void SetEnumVariables(const FieldDescriptor* descriptor,
map<string, string>* variables) {
string type = EnumName(descriptor->enum_type());
@@ -63,8 +64,9 @@ void SetEnumVariables(const FieldDescriptor* descriptor,
}
} // namespace
-EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor)
- : SingleFieldGenerator(descriptor) {
+EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options)
+ : SingleFieldGenerator(descriptor, options) {
SetEnumVariables(descriptor, &variables_);
}
@@ -112,6 +114,7 @@ void EnumFieldGenerator::GenerateCFunctionImplementations(
void EnumFieldGenerator::DetermineForwardDeclarations(
set<string>* fwd_decls) const {
+ SingleFieldGenerator::DetermineForwardDeclarations(fwd_decls);
// If it is an enum defined in a different file, then we'll need a forward
// declaration for it. When it is in our file, all the enums are output
// before the message, so it will be declared before it is needed.
@@ -123,14 +126,20 @@ void EnumFieldGenerator::DetermineForwardDeclarations(
}
RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator(
- const FieldDescriptor* descriptor)
- : RepeatedFieldGenerator(descriptor) {
+ const FieldDescriptor* descriptor, const Options& options)
+ : RepeatedFieldGenerator(descriptor, options) {
SetEnumVariables(descriptor, &variables_);
variables_["array_storage_type"] = "GPBEnumArray";
}
RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
+void RepeatedEnumFieldGenerator::FinishInitialization(void) {
+ RepeatedFieldGenerator::FinishInitialization();
+ variables_["array_comment"] =
+ "// |" + variables_["name"] + "| contains |" + variables_["storage_type"] + "|\n";
+}
+
void RepeatedEnumFieldGenerator::GenerateFieldDescriptionTypeSpecific(
io::Printer* printer) const {
printer->Print(
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h
index b629eae8..ae2f57e3 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h
@@ -41,7 +41,8 @@ namespace compiler {
namespace objectivec {
class EnumFieldGenerator : public SingleFieldGenerator {
- friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field);
+ friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
+ const Options& options);
public:
virtual void GenerateFieldDescriptionTypeSpecific(io::Printer* printer) const;
@@ -50,7 +51,7 @@ class EnumFieldGenerator : public SingleFieldGenerator {
virtual void DetermineForwardDeclarations(set<string>* fwd_decls) const;
protected:
- explicit EnumFieldGenerator(const FieldDescriptor* descriptor);
+ EnumFieldGenerator(const FieldDescriptor* descriptor, const Options& options);
virtual ~EnumFieldGenerator();
private:
@@ -58,13 +59,16 @@ class EnumFieldGenerator : public SingleFieldGenerator {
};
class RepeatedEnumFieldGenerator : public RepeatedFieldGenerator {
- friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field);
+ friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
+ const Options& options);
public:
+ virtual void FinishInitialization();
virtual void GenerateFieldDescriptionTypeSpecific(io::Printer* printer) const;
protected:
- RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor);
+ RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
virtual ~RepeatedEnumFieldGenerator();
private:
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_field.cc
index cf5d8cfb..09341820 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_field.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_field.cc
@@ -45,6 +45,7 @@ namespace compiler {
namespace objectivec {
namespace {
+
void SetCommonFieldVariables(const FieldDescriptor* descriptor,
map<string, string>* variables) {
string camel_case_name = FieldName(descriptor);
@@ -117,39 +118,40 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor,
} // namespace
-FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field) {
+FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
+ const Options& options) {
FieldGenerator* result = NULL;
if (field->is_repeated()) {
switch (GetObjectiveCType(field)) {
case OBJECTIVECTYPE_MESSAGE: {
if (field->is_map()) {
- result = new MapFieldGenerator(field);
+ result = new MapFieldGenerator(field, options);
} else {
- result = new RepeatedMessageFieldGenerator(field);
+ result = new RepeatedMessageFieldGenerator(field, options);
}
break;
}
case OBJECTIVECTYPE_ENUM:
- result = new RepeatedEnumFieldGenerator(field);
+ result = new RepeatedEnumFieldGenerator(field, options);
break;
default:
- result = new RepeatedPrimitiveFieldGenerator(field);
+ result = new RepeatedPrimitiveFieldGenerator(field, options);
break;
}
} else {
switch (GetObjectiveCType(field)) {
case OBJECTIVECTYPE_MESSAGE: {
- result = new MessageFieldGenerator(field);
+ result = new MessageFieldGenerator(field, options);
break;
}
case OBJECTIVECTYPE_ENUM:
- result = new EnumFieldGenerator(field);
+ result = new EnumFieldGenerator(field, options);
break;
default:
if (IsReferenceType(field)) {
- result = new PrimitiveObjFieldGenerator(field);
+ result = new PrimitiveObjFieldGenerator(field, options);
} else {
- result = new PrimitiveFieldGenerator(field);
+ result = new PrimitiveFieldGenerator(field, options);
}
break;
}
@@ -158,8 +160,8 @@ FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field) {
return result;
}
-
-FieldGenerator::FieldGenerator(const FieldDescriptor* descriptor)
+FieldGenerator::FieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options)
: descriptor_(descriptor) {
SetCommonFieldVariables(descriptor, &variables_);
}
@@ -252,9 +254,9 @@ void FieldGenerator::FinishInitialization(void) {
}
}
-SingleFieldGenerator::SingleFieldGenerator(
- const FieldDescriptor* descriptor)
- : FieldGenerator(descriptor) {
+SingleFieldGenerator::SingleFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options)
+ : FieldGenerator(descriptor, options) {
// Nothing
}
@@ -300,9 +302,9 @@ bool SingleFieldGenerator::WantsHasProperty(void) const {
return false;
}
-ObjCObjFieldGenerator::ObjCObjFieldGenerator(
- const FieldDescriptor* descriptor)
- : SingleFieldGenerator(descriptor) {
+ObjCObjFieldGenerator::ObjCObjFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options)
+ : SingleFieldGenerator(descriptor, options) {
variables_["property_storage_attribute"] = "strong";
if (IsRetainedName(variables_["name"])) {
variables_["storage_attribute"] = " NS_RETURNS_NOT_RETAINED";
@@ -342,18 +344,21 @@ void ObjCObjFieldGenerator::GeneratePropertyDeclaration(
}
RepeatedFieldGenerator::RepeatedFieldGenerator(
- const FieldDescriptor* descriptor)
- : ObjCObjFieldGenerator(descriptor) {
+ const FieldDescriptor* descriptor, const Options& options)
+ : ObjCObjFieldGenerator(descriptor, options) {
// Repeated fields don't use the has index.
variables_["has_index"] = "GPBNoHasBit";
+ // Default to no comment and let the cases needing it fill it in.
+ variables_["array_comment"] = "";
}
RepeatedFieldGenerator::~RepeatedFieldGenerator() {}
void RepeatedFieldGenerator::FinishInitialization(void) {
FieldGenerator::FinishInitialization();
- variables_["array_comment"] =
- "// |" + variables_["name"] + "| contains |" + variables_["storage_type"] + "|\n";
+ if (variables_.find("array_property_type") == variables_.end()) {
+ variables_["array_property_type"] = variable("array_storage_type");
+ }
}
void RepeatedFieldGenerator::GenerateFieldStorageDeclaration(
@@ -379,13 +384,13 @@ void RepeatedFieldGenerator::GeneratePropertyDeclaration(
variables_,
"$comments$"
"$array_comment$"
- "@property(nonatomic, readwrite, strong, null_resettable) $array_storage_type$ *$name$$storage_attribute$;\n"
+ "@property(nonatomic, readwrite, strong, null_resettable) $array_property_type$ *$name$$storage_attribute$;\n"
"@property(nonatomic, readonly) NSUInteger $name$_Count;\n");
if (IsInitName(variables_.find("name")->second)) {
// If property name starts with init we need to annotate it to get past ARC.
// http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227
printer->Print(variables_,
- "- ($array_storage_type$ *)$name$ GPB_METHOD_FAMILY_NONE;\n");
+ "- ($array_property_type$ *)$name$ GPB_METHOD_FAMILY_NONE;\n");
}
printer->Print("\n");
}
@@ -395,7 +400,8 @@ bool RepeatedFieldGenerator::WantsHasProperty(void) const {
return false;
}
-FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor)
+FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor,
+ const Options& options)
: descriptor_(descriptor),
field_generators_(
new scoped_ptr<FieldGenerator>[descriptor->field_count()]),
@@ -403,10 +409,12 @@ FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor)
new scoped_ptr<FieldGenerator>[descriptor->extension_count()]) {
// Construct all the FieldGenerators.
for (int i = 0; i < descriptor->field_count(); i++) {
- field_generators_[i].reset(FieldGenerator::Make(descriptor->field(i)));
+ field_generators_[i].reset(
+ FieldGenerator::Make(descriptor->field(i), options));
}
for (int i = 0; i < descriptor->extension_count(); i++) {
- extension_generators_[i].reset(FieldGenerator::Make(descriptor->extension(i)));
+ extension_generators_[i].reset(
+ FieldGenerator::Make(descriptor->extension(i), options));
}
}
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_field.h b/src/google/protobuf/compiler/objectivec/objectivec_field.h
index 130a52dd..e8a20a72 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_field.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_field.h
@@ -49,24 +49,31 @@ namespace objectivec {
class FieldGenerator {
public:
- static FieldGenerator* Make(const FieldDescriptor* field);
+ static FieldGenerator* Make(const FieldDescriptor* field,
+ const Options& options);
virtual ~FieldGenerator();
+ // Exposed for subclasses to fill in.
virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const = 0;
virtual void GeneratePropertyDeclaration(io::Printer* printer) const = 0;
-
virtual void GeneratePropertyImplementation(io::Printer* printer) const = 0;
- virtual void GenerateFieldDescription(io::Printer* printer) const;
+ // Called by GenerateFieldDescription, exposed for classes that need custom
+ // generation.
virtual void GenerateFieldDescriptionTypeSpecific(io::Printer* printer) const;
- virtual void GenerateFieldNumberConstant(io::Printer* printer) const;
+ // Exposed for subclasses to extend, base does nothing.
virtual void GenerateCFunctionDeclarations(io::Printer* printer) const;
virtual void GenerateCFunctionImplementations(io::Printer* printer) const;
+ // Exposed for subclasses, should always call it on the parent class also.
virtual void DetermineForwardDeclarations(set<string>* fwd_decls) const;
+ // Used during generation, not intended to be extended by subclasses.
+ void GenerateFieldDescription(io::Printer* printer) const;
+ void GenerateFieldNumberConstant(io::Printer* printer) const;
+
void SetOneofIndexBase(int index_base);
string variable(const char* key) const {
@@ -81,7 +88,7 @@ class FieldGenerator {
string raw_field_name() const { return variable("raw_field_name"); }
protected:
- explicit FieldGenerator(const FieldDescriptor* descriptor);
+ FieldGenerator(const FieldDescriptor* descriptor, const Options& options);
virtual void FinishInitialization(void);
virtual bool WantsHasProperty(void) const = 0;
@@ -103,7 +110,8 @@ class SingleFieldGenerator : public FieldGenerator {
virtual void GeneratePropertyImplementation(io::Printer* printer) const;
protected:
- explicit SingleFieldGenerator(const FieldDescriptor* descriptor);
+ SingleFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
virtual bool WantsHasProperty(void) const;
private:
@@ -119,7 +127,8 @@ class ObjCObjFieldGenerator : public SingleFieldGenerator {
virtual void GeneratePropertyDeclaration(io::Printer* printer) const;
protected:
- explicit ObjCObjFieldGenerator(const FieldDescriptor* descriptor);
+ ObjCObjFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjCObjFieldGenerator);
@@ -135,7 +144,8 @@ class RepeatedFieldGenerator : public ObjCObjFieldGenerator {
virtual void GeneratePropertyImplementation(io::Printer* printer) const;
protected:
- explicit RepeatedFieldGenerator(const FieldDescriptor* descriptor);
+ RepeatedFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
virtual void FinishInitialization(void);
virtual bool WantsHasProperty(void) const;
@@ -146,7 +156,7 @@ class RepeatedFieldGenerator : public ObjCObjFieldGenerator {
// Convenience class which constructs FieldGenerators for a Descriptor.
class FieldGeneratorMap {
public:
- explicit FieldGeneratorMap(const Descriptor* descriptor);
+ FieldGeneratorMap(const Descriptor* descriptor, const Options& options);
~FieldGeneratorMap();
const FieldGenerator& get(const FieldDescriptor* field) const;
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.cc b/src/google/protobuf/compiler/objectivec/objectivec_file.cc
index 228c66f0..cdf9ebbc 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_file.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_file.cc
@@ -50,17 +50,18 @@ const int32 GOOGLE_PROTOBUF_OBJC_GEN_VERSION = 30000;
namespace compiler {
namespace objectivec {
-FileGenerator::FileGenerator(const FileDescriptor *file)
+FileGenerator::FileGenerator(const FileDescriptor *file, const Options& options)
: file_(file),
root_class_name_(FileClassName(file)),
- is_public_dep_(false) {
+ is_public_dep_(false),
+ options_(options) {
for (int i = 0; i < file_->enum_type_count(); i++) {
EnumGenerator *generator = new EnumGenerator(file_->enum_type(i));
enum_generators_.push_back(generator);
}
for (int i = 0; i < file_->message_type_count(); i++) {
MessageGenerator *generator =
- new MessageGenerator(root_class_name_, file_->message_type(i));
+ new MessageGenerator(root_class_name_, file_->message_type(i), options_);
message_generators_.push_back(generator);
}
for (int i = 0; i < file_->extension_count(); i++) {
@@ -352,7 +353,8 @@ const vector<FileGenerator *> &FileGenerator::DependencyGenerators() {
public_import_names.insert(file_->public_dependency(i)->name());
}
for (int i = 0; i < file_->dependency_count(); i++) {
- FileGenerator *generator = new FileGenerator(file_->dependency(i));
+ FileGenerator *generator =
+ new FileGenerator(file_->dependency(i), options_);
const string& name = file_->dependency(i)->name();
bool public_import = (public_import_names.count(name) != 0);
generator->SetIsPublicDependency(public_import);
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.h b/src/google/protobuf/compiler/objectivec/objectivec_file.h
index 1bb4f0ea..4c0fcd3f 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_file.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_file.h
@@ -55,7 +55,7 @@ class MessageGenerator;
class FileGenerator {
public:
- explicit FileGenerator(const FileDescriptor* file);
+ FileGenerator(const FileDescriptor* file, const Options& options);
~FileGenerator();
void GenerateSource(io::Printer* printer);
@@ -84,6 +84,8 @@ class FileGenerator {
vector<ExtensionGenerator*> extension_generators_;
bool is_public_dep_;
+ const Options options_;
+
const vector<FileGenerator*>& DependencyGenerators();
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator);
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_generator.cc b/src/google/protobuf/compiler/objectivec/objectivec_generator.cc
index 375b4e0f..72e295de 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_generator.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_generator.cc
@@ -49,21 +49,31 @@ bool ObjectiveCGenerator::Generate(const FileDescriptor* file,
const string& parameter,
OutputDirectory* output_directory,
string* error) const {
- // ObjC doesn't have any options at the moment, error if passed one.
+ // -----------------------------------------------------------------
+ // Parse generator options.
+
+ Options generation_options;
+
vector<pair<string, string> > options;
ParseGeneratorParameter(parameter, &options);
for (int i = 0; i < options.size(); i++) {
- *error = "error:: Unknown generator option: " + options[i].first;
- return false;
+ if (options[i].first == "expected_prefixes_path") {
+ generation_options.expected_prefixes_path = options[i].second;
+ } else {
+ *error = "error: Unknown generator option: " + options[i].first;
+ return false;
+ }
}
+ // -----------------------------------------------------------------
+
// Validate the objc prefix/package pairing.
- if (!ValidateObjCClassPrefix(file, error)) {
+ if (!ValidateObjCClassPrefix(file, generation_options, error)) {
// *error will have been filled in.
return false;
}
- FileGenerator file_generator(file);
+ FileGenerator file_generator(file, generation_options);
string filepath = FilePath(file);
// Generate header.
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
index 8527b74b..77a378c8 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
@@ -58,6 +58,14 @@ namespace protobuf {
namespace compiler {
namespace objectivec {
+Options::Options() {
+ // Default is the value of the env for the package prefixes.
+ const char* file_path = getenv("GPB_OBJC_EXPECTED_PACKAGE_PREFIXES");
+ if (file_path) {
+ expected_prefixes_path = file_path;
+ }
+}
+
namespace {
hash_set<string> MakeWordsMap(const char* const words[], size_t num_words) {
@@ -890,26 +898,26 @@ bool Parser::ParseLoop() {
return true;
}
-bool LoadExpectedPackagePrefixes(map<string, string>* prefix_map,
- string* out_expect_file_path,
+bool LoadExpectedPackagePrefixes(const Options &generation_options,
+ map<string, string>* prefix_map,
string* out_error) {
- const char* file_path = getenv("GPB_OBJC_EXPECTED_PACKAGE_PREFIXES");
- if (file_path == NULL) {
+ if (generation_options.expected_prefixes_path.empty()) {
return true;
}
int fd;
do {
- fd = open(file_path, O_RDONLY);
+ fd = open(generation_options.expected_prefixes_path.c_str(), O_RDONLY);
} while (fd < 0 && errno == EINTR);
if (fd < 0) {
*out_error =
- string(file_path) + ":0:0: error: Unable to open." + strerror(errno);
+ string("error: Unable to open \"") +
+ generation_options.expected_prefixes_path +
+ "\", " + strerror(errno);
return false;
}
io::FileInputStream file_stream(fd);
file_stream.SetCloseOnDelete(true);
- *out_expect_file_path = file_path;
Parser parser(prefix_map);
const void* buf;
@@ -920,8 +928,9 @@ bool LoadExpectedPackagePrefixes(map<string, string>* prefix_map,
}
if (!parser.ParseChunk(StringPiece(static_cast<const char*>(buf), buf_len))) {
- *out_error = string(file_path) + ":" + SimpleItoa(parser.last_line()) +
- ":0: error: " + parser.error_str();
+ *out_error =
+ string("error: ") + generation_options.expected_prefixes_path +
+ " Line " + SimpleItoa(parser.last_line()) + ", " + parser.error_str();
return false;
}
}
@@ -930,7 +939,9 @@ bool LoadExpectedPackagePrefixes(map<string, string>* prefix_map,
} // namespace
-bool ValidateObjCClassPrefix(const FileDescriptor* file, string* out_error) {
+bool ValidateObjCClassPrefix(const FileDescriptor* file,
+ const Options& generation_options,
+ string* out_error) {
const string prefix = file->options().objc_class_prefix();
const string package = file->package();
@@ -939,11 +950,10 @@ bool ValidateObjCClassPrefix(const FileDescriptor* file, string* out_error) {
// Load any expected package prefixes to validate against those.
map<string, string> expected_package_prefixes;
- string expect_file_path;
- if (!LoadExpectedPackagePrefixes(&expected_package_prefixes,
- &expect_file_path, out_error)) {
- // Any error, clear the entries that were read.
- expected_package_prefixes.clear();
+ if (!LoadExpectedPackagePrefixes(generation_options,
+ &expected_package_prefixes,
+ out_error)) {
+ return false;
}
// Check: Error - See if there was an expected prefix for the package and
@@ -957,7 +967,7 @@ bool ValidateObjCClassPrefix(const FileDescriptor* file, string* out_error) {
return true;
} else {
// ...it didn't match!
- *out_error = "protoc:0: error: Expected 'option objc_class_prefix = \"" +
+ *out_error = "error: Expected 'option objc_class_prefix = \"" +
package_match->second + "\";' in '" + file->name() + "'";
if (prefix.length()) {
*out_error += "; but found '" + prefix + "' instead";
@@ -980,11 +990,11 @@ bool ValidateObjCClassPrefix(const FileDescriptor* file, string* out_error) {
i != expected_package_prefixes.end(); ++i) {
if (i->second == prefix) {
*out_error =
- "protoc:0: error: Found 'option objc_class_prefix = \"" + prefix +
+ "error: Found 'option objc_class_prefix = \"" + prefix +
"\";' in '" + file->name() +
"'; that prefix is already used for 'package " + i->first +
";'. It can only be reused by listing it in the expected file (" +
- expect_file_path + ").";
+ generation_options.expected_prefixes_path + ").";
return false; // Only report first usage of the prefix.
}
}
@@ -1017,7 +1027,7 @@ bool ValidateObjCClassPrefix(const FileDescriptor* file, string* out_error) {
<< "protoc:0: warning: Found unexpected 'option objc_class_prefix = \""
<< prefix << "\";' in '" << file->name() << "';"
<< " consider adding it to the expected prefixes file ("
- << expect_file_path << ")." << endl;
+ << generation_options.expected_prefixes_path << ")." << endl;
cerr.flush();
}
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h
index 85744862..5b2dd190 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h
@@ -42,6 +42,12 @@ namespace protobuf {
namespace compiler {
namespace objectivec {
+// Generator options (see objectivec_generator.cc for a description of each):
+struct Options {
+ Options();
+ string expected_prefixes_path;
+};
+
// Strips ".proto" or ".protodevel" from the end of a filename.
string StripProto(const string& filename);
@@ -145,7 +151,9 @@ string BuildCommentsString(const SourceLocation& location);
// Checks the prefix for a given file and outputs any warnings needed, if
// there are flat out errors, then out_error is filled in and the result is
// false.
-bool ValidateObjCClassPrefix(const FileDescriptor* file, string *out_error);
+bool ValidateObjCClassPrefix(const FileDescriptor* file,
+ const Options& generation_options,
+ string* out_error);
// Generate decode data needed for ObjC's GPBDecodeTextFormatName() to transform
// the input into the expected output.
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc
index 2987f3db..2751e936 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc
@@ -84,13 +84,14 @@ const char* MapEntryTypeName(const FieldDescriptor* descriptor, bool isKey) {
} // namespace
-MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor)
- : RepeatedFieldGenerator(descriptor) {
+MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options)
+ : RepeatedFieldGenerator(descriptor, options) {
const FieldDescriptor* key_descriptor =
descriptor->message_type()->FindFieldByName("key");
const FieldDescriptor* value_descriptor =
descriptor->message_type()->FindFieldByName("value");
- value_field_generator_.reset(FieldGenerator::Make(value_descriptor));
+ value_field_generator_.reset(FieldGenerator::Make(value_descriptor, options));
// Pull over some variables_ from the value.
variables_["field_type"] = value_field_generator_->variable("field_type");
@@ -117,16 +118,27 @@ MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor)
variables_["fieldflags"] = BuildFlagsString(field_flags);
ObjectiveCType value_objc_type = GetObjectiveCType(value_descriptor);
- if ((GetObjectiveCType(key_descriptor) == OBJECTIVECTYPE_STRING) &&
+ const bool value_is_object_type =
((value_objc_type == OBJECTIVECTYPE_STRING) ||
(value_objc_type == OBJECTIVECTYPE_DATA) ||
- (value_objc_type == OBJECTIVECTYPE_MESSAGE))) {
+ (value_objc_type == OBJECTIVECTYPE_MESSAGE));
+ if ((GetObjectiveCType(key_descriptor) == OBJECTIVECTYPE_STRING) &&
+ value_is_object_type) {
variables_["array_storage_type"] = "NSMutableDictionary";
+ variables_["array_property_type"] =
+ "NSMutableDictionary<NSString*, " +
+ value_field_generator_->variable("storage_type") + "*>";
} else {
- string base_name = MapEntryTypeName(key_descriptor, true);
- base_name += MapEntryTypeName(value_descriptor, false);
- base_name += "Dictionary";
- variables_["array_storage_type"] = "GPB" + base_name;
+ string class_name("GPB");
+ class_name += MapEntryTypeName(key_descriptor, true);
+ class_name += MapEntryTypeName(value_descriptor, false);
+ class_name += "Dictionary";
+ variables_["array_storage_type"] = class_name;
+ if (value_is_object_type) {
+ variables_["array_property_type"] =
+ class_name + "<" +
+ value_field_generator_->variable("storage_type") + "*>";
+ }
}
}
@@ -138,15 +150,9 @@ void MapFieldGenerator::FinishInitialization(void) {
// values in the map are.
const FieldDescriptor* value_descriptor =
descriptor_->message_type()->FindFieldByName("value");
- ObjectiveCType value_objc_type = GetObjectiveCType(value_descriptor);
- if ((value_objc_type == OBJECTIVECTYPE_MESSAGE) ||
- (value_objc_type == OBJECTIVECTYPE_DATA) ||
- (value_objc_type == OBJECTIVECTYPE_STRING) ||
- (value_objc_type == OBJECTIVECTYPE_ENUM)) {
+ if (GetObjectiveCType(value_descriptor) == OBJECTIVECTYPE_ENUM) {
variables_["array_comment"] =
"// |" + variables_["name"] + "| values are |" + value_field_generator_->variable("storage_type") + "|\n";
- } else {
- variables_["array_comment"] = "";
}
}
@@ -157,6 +163,19 @@ void MapFieldGenerator::GenerateFieldDescriptionTypeSpecific(
value_field_generator_->GenerateFieldDescriptionTypeSpecific(printer);
}
+void MapFieldGenerator::DetermineForwardDeclarations(
+ set<string>* fwd_decls) const {
+ RepeatedFieldGenerator::DetermineForwardDeclarations(fwd_decls);
+ const FieldDescriptor* value_descriptor =
+ descriptor_->message_type()->FindFieldByName("value");
+ if (GetObjectiveCType(value_descriptor) == OBJECTIVECTYPE_MESSAGE) {
+ const string& value_storage_type =
+ value_field_generator_->variable("storage_type");
+ fwd_decls->insert("@class " + value_storage_type);
+ }
+}
+
+
} // namespace objectivec
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_map_field.h b/src/google/protobuf/compiler/objectivec/objectivec_map_field.h
index 173541f2..7351ea05 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_map_field.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_map_field.h
@@ -41,18 +41,22 @@ namespace compiler {
namespace objectivec {
class MapFieldGenerator : public RepeatedFieldGenerator {
- friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field);
+ friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
+ const Options& options);
public:
virtual void FinishInitialization(void);
virtual void GenerateFieldDescriptionTypeSpecific(io::Printer* printer) const;
protected:
- explicit MapFieldGenerator(const FieldDescriptor* descriptor);
+ MapFieldGenerator(const FieldDescriptor* descriptor, const Options& options);
virtual ~MapFieldGenerator();
+ virtual void DetermineForwardDeclarations(set<string>* fwd_decls) const;
+
private:
scoped_ptr<FieldGenerator> value_field_generator_;
+
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldGenerator);
};
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message.cc b/src/google/protobuf/compiler/objectivec/objectivec_message.cc
index 32671d42..e0ea8bd2 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_message.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_message.cc
@@ -174,10 +174,11 @@ const FieldDescriptor** SortFieldsByStorageSize(const Descriptor* descriptor) {
} // namespace
MessageGenerator::MessageGenerator(const string& root_classname,
- const Descriptor* descriptor)
+ const Descriptor* descriptor,
+ const Options& options)
: root_classname_(root_classname),
descriptor_(descriptor),
- field_generators_(descriptor),
+ field_generators_(descriptor, options),
class_name_(ClassName(descriptor_)) {
for (int i = 0; i < descriptor_->extension_count(); i++) {
extension_generators_.push_back(
@@ -196,7 +197,9 @@ MessageGenerator::MessageGenerator(const string& root_classname,
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
MessageGenerator* generator =
- new MessageGenerator(root_classname_, descriptor_->nested_type(i));
+ new MessageGenerator(root_classname_,
+ descriptor_->nested_type(i),
+ options);
nested_message_generators_.push_back(generator);
}
}
@@ -230,11 +233,6 @@ void MessageGenerator::DetermineForwardDeclarations(set<string>* fwd_decls) {
if (!IsMapEntryMessage(descriptor_)) {
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* fieldDescriptor = descriptor_->field(i);
- // If it is a the field is repeated, the type will be and *Array, and we
- // don't need any forward decl.
- if (fieldDescriptor->is_repeated()) {
- continue;
- }
field_generators_.get(fieldDescriptor)
.DetermineForwardDeclarations(fwd_decls);
}
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message.h b/src/google/protobuf/compiler/objectivec/objectivec_message.h
index 06b536ff..8565e76f 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_message.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_message.h
@@ -54,7 +54,9 @@ class EnumGenerator;
class MessageGenerator {
public:
- MessageGenerator(const string& root_classname, const Descriptor* descriptor);
+ MessageGenerator(const string& root_classname,
+ const Descriptor* descriptor,
+ const Options& options);
~MessageGenerator();
void GenerateStaticVariablesInitialization(io::Printer* printer);
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc
index f2ce4e5b..d6ccd6d1 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc
@@ -58,8 +58,9 @@ void SetMessageVariables(const FieldDescriptor* descriptor,
} // namespace
-MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor)
- : ObjCObjFieldGenerator(descriptor) {
+MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options)
+ : ObjCObjFieldGenerator(descriptor, options) {
SetMessageVariables(descriptor, &variables_);
}
@@ -67,6 +68,7 @@ MessageFieldGenerator::~MessageFieldGenerator() {}
void MessageFieldGenerator::DetermineForwardDeclarations(
set<string>* fwd_decls) const {
+ ObjCObjFieldGenerator::DetermineForwardDeclarations(fwd_decls);
// Class name is already in "storage_type".
fwd_decls->insert("@class " + variable("storage_type"));
}
@@ -82,14 +84,24 @@ bool MessageFieldGenerator::WantsHasProperty(void) const {
}
RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator(
- const FieldDescriptor* descriptor)
- : RepeatedFieldGenerator(descriptor) {
+ const FieldDescriptor* descriptor, const Options& options)
+ : RepeatedFieldGenerator(descriptor, options) {
SetMessageVariables(descriptor, &variables_);
variables_["array_storage_type"] = "NSMutableArray";
+ variables_["array_property_type"] =
+ "NSMutableArray<" + variables_["storage_type"] + "*>";
}
RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
+void RepeatedMessageFieldGenerator::DetermineForwardDeclarations(
+ set<string>* fwd_decls) const {
+ RepeatedFieldGenerator::DetermineForwardDeclarations(fwd_decls);
+ // Class name is already in "storage_type".
+ fwd_decls->insert("@class " + variable("storage_type"));
+}
+
+
} // namespace objectivec
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message_field.h b/src/google/protobuf/compiler/objectivec/objectivec_message_field.h
index 708ea566..d2dba153 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_message_field.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_message_field.h
@@ -41,10 +41,12 @@ namespace compiler {
namespace objectivec {
class MessageFieldGenerator : public ObjCObjFieldGenerator {
- friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field);
+ friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
+ const Options& options);
protected:
- explicit MessageFieldGenerator(const FieldDescriptor* descriptor);
+ MessageFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
virtual ~MessageFieldGenerator();
virtual bool WantsHasProperty(void) const;
@@ -56,12 +58,17 @@ class MessageFieldGenerator : public ObjCObjFieldGenerator {
};
class RepeatedMessageFieldGenerator : public RepeatedFieldGenerator {
- friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field);
+ friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
+ const Options& options);
protected:
- explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor);
+ RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
virtual ~RepeatedMessageFieldGenerator();
+ public:
+ virtual void DetermineForwardDeclarations(set<string>* fwd_decls) const;
+
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator);
};
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc
index c185b66d..ea7f1b91 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc
@@ -74,7 +74,7 @@ const char* PrimitiveTypeName(const FieldDescriptor* descriptor) {
case OBJECTIVECTYPE_ENUM:
return "int32_t";
case OBJECTIVECTYPE_MESSAGE:
- return NULL;
+ return NULL; // Messages go through objectivec_message_field.cc|h.
}
// Some compilers report reaching end of function even though all cases of
@@ -107,7 +107,8 @@ const char* PrimitiveArrayTypeName(const FieldDescriptor* descriptor) {
case OBJECTIVECTYPE_ENUM:
return "Enum";
case OBJECTIVECTYPE_MESSAGE:
- return ""; // Want NSArray
+ // Want NSArray (but goes through objectivec_message_field.cc|h).
+ return "";
}
// Some compilers report reaching end of function even though all cases of
@@ -126,16 +127,16 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
} // namespace
PrimitiveFieldGenerator::PrimitiveFieldGenerator(
- const FieldDescriptor* descriptor)
- : SingleFieldGenerator(descriptor) {
+ const FieldDescriptor* descriptor, const Options& options)
+ : SingleFieldGenerator(descriptor, options) {
SetPrimitiveVariables(descriptor, &variables_);
}
PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
PrimitiveObjFieldGenerator::PrimitiveObjFieldGenerator(
- const FieldDescriptor* descriptor)
- : ObjCObjFieldGenerator(descriptor) {
+ const FieldDescriptor* descriptor, const Options& options)
+ : ObjCObjFieldGenerator(descriptor, options) {
SetPrimitiveVariables(descriptor, &variables_);
variables_["property_storage_attribute"] = "copy";
}
@@ -143,8 +144,8 @@ PrimitiveObjFieldGenerator::PrimitiveObjFieldGenerator(
PrimitiveObjFieldGenerator::~PrimitiveObjFieldGenerator() {}
RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
- const FieldDescriptor* descriptor)
- : RepeatedFieldGenerator(descriptor) {
+ const FieldDescriptor* descriptor, const Options& options)
+ : RepeatedFieldGenerator(descriptor, options) {
SetPrimitiveVariables(descriptor, &variables_);
string base_name = PrimitiveArrayTypeName(descriptor);
@@ -152,19 +153,13 @@ RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
variables_["array_storage_type"] = "GPB" + base_name + "Array";
} else {
variables_["array_storage_type"] = "NSMutableArray";
+ variables_["array_property_type"] =
+ "NSMutableArray<" + variables_["storage_type"] + "*>";
}
}
RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
-void RepeatedPrimitiveFieldGenerator::FinishInitialization(void) {
- RepeatedFieldGenerator::FinishInitialization();
- if (IsPrimitiveType(descriptor_)) {
- // No comment needed for primitive types.
- variables_["array_comment"] = "";
- }
-}
-
} // namespace objectivec
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h
index 9bb79343..87139afb 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h
@@ -41,10 +41,12 @@ namespace compiler {
namespace objectivec {
class PrimitiveFieldGenerator : public SingleFieldGenerator {
- friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field);
+ friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
+ const Options& options);
protected:
- explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor);
+ PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
virtual ~PrimitiveFieldGenerator();
private:
@@ -52,10 +54,12 @@ class PrimitiveFieldGenerator : public SingleFieldGenerator {
};
class PrimitiveObjFieldGenerator : public ObjCObjFieldGenerator {
- friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field);
+ friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
+ const Options& options);
protected:
- explicit PrimitiveObjFieldGenerator(const FieldDescriptor* descriptor);
+ PrimitiveObjFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
virtual ~PrimitiveObjFieldGenerator();
private:
@@ -63,12 +67,13 @@ class PrimitiveObjFieldGenerator : public ObjCObjFieldGenerator {
};
class RepeatedPrimitiveFieldGenerator : public RepeatedFieldGenerator {
- friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field);
+ friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field,
+ const Options& options);
protected:
- explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor);
+ RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
virtual ~RepeatedPrimitiveFieldGenerator();
- virtual void FinishInitialization(void);
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator);
diff --git a/src/google/protobuf/stubs/atomicops.h b/src/google/protobuf/stubs/atomicops.h
index cb93227f..9b3d1e6b 100644
--- a/src/google/protobuf/stubs/atomicops.h
+++ b/src/google/protobuf/stubs/atomicops.h
@@ -214,6 +214,8 @@ Atomic64 Release_Load(volatile const Atomic64* ptr);
#include <google/protobuf/stubs/atomicops_internals_power.h>
#elif defined(__native_client__)
#include <google/protobuf/stubs/atomicops_internals_pnacl.h>
+#elif defined(GOOGLE_PROTOBUF_ARCH_PPC)
+#include <google/protobuf/stubs/atomicops_internals_ppc_gcc.h>
#elif (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4))
#include <google/protobuf/stubs/atomicops_internals_generic_gcc.h>
#elif defined(__clang__)
diff --git a/src/google/protobuf/stubs/atomicops_internals_ppc_gcc.h b/src/google/protobuf/stubs/atomicops_internals_ppc_gcc.h
new file mode 100644
index 00000000..8231a578
--- /dev/null
+++ b/src/google/protobuf/stubs/atomicops_internals_ppc_gcc.h
@@ -0,0 +1,155 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: ogabbay@advaoptical.com (Oded Gabbay)
+// Cleaned up by: bsilver16384@gmail.com (Brian Silverman)
+//
+// This file is an internal atomic implementation, use atomicops.h instead.
+
+#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_PPC_GCC_H_
+#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_PPC_GCC_H_
+
+#define ATOMICOPS_COMPILER_BARRIER() __asm__ __volatile__("" : : : "memory")
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32 *ptr,
+ Atomic32 old_value,
+ Atomic32 new_value) {
+ Atomic32 prev;
+
+ __asm__ __volatile__(
+ "0: \n\t"
+ "lwarx %[prev],0,%[ptr] \n\t"
+ "cmpw 0,%[prev],%[old_value] \n\t"
+ "bne- 1f \n\t"
+ "stwcx. %[new_value],0,%[ptr] \n\t"
+ "bne- 0b \n\t"
+ "1: \n\t"
+ : [prev] "=&r"(prev), "+m"(*ptr)
+ : [ptr] "r"(ptr), [old_value] "r"(old_value), [new_value] "r"(new_value)
+ : "cc", "memory");
+
+ return prev;
+}
+
+inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32 *ptr,
+ Atomic32 new_value) {
+ Atomic32 old;
+
+ __asm__ __volatile__(
+ "0: \n\t"
+ "lwarx %[old],0,%[ptr] \n\t"
+ "stwcx. %[new_value],0,%[ptr] \n\t"
+ "bne- 0b \n\t"
+ : [old] "=&r"(old), "+m"(*ptr)
+ : [ptr] "r"(ptr), [new_value] "r"(new_value)
+ : "cc", "memory");
+
+ return old;
+}
+
+inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32 *ptr,
+ Atomic32 increment) {
+ Atomic32 temp;
+
+ __asm__ __volatile__(
+ "0: \n\t"
+ "lwarx %[temp],0,%[ptr] \n\t"
+ "add %[temp],%[increment],%[temp] \n\t"
+ "stwcx. %[temp],0,%[ptr] \n\t"
+ "bne- 0b \n\t"
+ : [temp] "=&r"(temp)
+ : [increment] "r"(increment), [ptr] "r"(ptr)
+ : "cc", "memory");
+
+ return temp;
+}
+
+inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32 *ptr,
+ Atomic32 increment) {
+ MemoryBarrier();
+ Atomic32 res = NoBarrier_AtomicIncrement(ptr, increment);
+ MemoryBarrier();
+ return res;
+}
+
+inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32 *ptr,
+ Atomic32 old_value, Atomic32 new_value) {
+ Atomic32 res = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+ MemoryBarrier();
+ return res;
+}
+
+inline Atomic32 Release_CompareAndSwap(volatile Atomic32 *ptr,
+ Atomic32 old_value, Atomic32 new_value) {
+ MemoryBarrier();
+ Atomic32 res = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+ return res;
+}
+
+inline void NoBarrier_Store(volatile Atomic32 *ptr, Atomic32 value) {
+ *ptr = value;
+}
+
+inline void MemoryBarrier() { __asm__ __volatile__("sync" : : : "memory"); }
+
+inline void Acquire_Store(volatile Atomic32 *ptr, Atomic32 value) {
+ *ptr = value;
+ MemoryBarrier();
+}
+
+inline void Release_Store(volatile Atomic32 *ptr, Atomic32 value) {
+ MemoryBarrier();
+ *ptr = value;
+}
+
+inline Atomic32 NoBarrier_Load(volatile const Atomic32 *ptr) { return *ptr; }
+
+inline Atomic32 Acquire_Load(volatile const Atomic32 *ptr) {
+ Atomic32 value = *ptr;
+ MemoryBarrier();
+ return value;
+}
+
+inline Atomic32 Release_Load(volatile const Atomic32 *ptr) {
+ MemoryBarrier();
+ return *ptr;
+}
+
+} // namespace internal
+} // namespace protobuf
+} // namespace google
+
+#undef ATOMICOPS_COMPILER_BARRIER
+
+#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_PPC_GCC_H_
diff --git a/src/google/protobuf/stubs/platform_macros.h b/src/google/protobuf/stubs/platform_macros.h
index 22b35723..4ba4b348 100644
--- a/src/google/protobuf/stubs/platform_macros.h
+++ b/src/google/protobuf/stubs/platform_macros.h
@@ -73,6 +73,9 @@
#elif defined(_POWER) || defined(__powerpc64__) || defined(__PPC64__)
#define GOOGLE_PROTOBUF_ARCH_POWER 1
#define GOOGLE_PROTOBUF_ARCH_64_BIT 1
+#elif defined(__PPC__)
+#define GOOGLE_PROTOBUF_ARCH_PPC 1
+#define GOOGLE_PROTOBUF_ARCH_32_BIT 1
#elif defined(__GNUC__)
# if (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4))
// We fallback to the generic Clang/GCC >= 4.7 implementation in atomicops.h