Go support for protocol buffers.

Consists of a compiler plugin and the support library, all written in Go.

This is a complete implementation except for:
  - Extensions in the plugin
    - coming soon
    - support is already in the library
  - Services (RPC)
    - needs an external definition to honor before supporting.
  - Insertion points in the plugin
    - may come

R=rsc, dsymonds1, ken2
CC=golang-dev
http://codereview.appspot.com/676041
diff --git a/compiler/Makefile b/compiler/Makefile
new file mode 100644
index 0000000..ad85973
--- /dev/null
+++ b/compiler/Makefile
@@ -0,0 +1,44 @@
+# Go support for Protocol Buffers - Google's data interchange format
+#
+# Copyright 2010 Google Inc.  All rights reserved.
+# http://code.google.com/p/goprotobuf/
+#
+# 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.
+
+
+include $(GOROOT)/src/Make.$(GOARCH)
+
+TARG=protoc-gen-go
+GOFILES=\
+	main.go\
+
+DEPS=descriptor plugin
+
+include $(GOROOT)/src/Make.cmd
+
+test:
+	cd testdata && make test
diff --git a/compiler/descriptor/Makefile b/compiler/descriptor/Makefile
new file mode 100644
index 0000000..cd2add9
--- /dev/null
+++ b/compiler/descriptor/Makefile
@@ -0,0 +1,53 @@
+# Go support for Protocol Buffers - Google's data interchange format
+#
+# Copyright 2010 Google Inc.  All rights reserved.
+# http://code.google.com/p/goprotobuf/
+#
+# 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.
+
+include $(GOROOT)/src/Make.$(GOARCH)
+
+TARG=goprotobuf.googlecode.com/hg/compiler/descriptor
+GOFILES=\
+	descriptor.pb.go\
+
+include $(GOROOT)/src/Make.pkg
+
+# Not stored here, but descriptor.proto is in http://code.google.com/p/protobuf
+# at protobuf-2.3.0/src/google/protobuf/descriptor.proto
+# Also we need to fix an import.
+regenerate:
+	echo WARNING! THIS RULE IS PROBABLY NOT RIGHT FOR YOUR INSTALLATION
+	cd $(HOME)/protobuf-2.3.0/src && \
+	protoc --go_out=. ./google/protobuf/descriptor.proto && \
+	cp ./google/protobuf/descriptor.pb.go $(GOROOT)/src/pkg/goprotobuf.googlecode.com/hg/compiler/descriptor/descriptor.pb.go
+
+restore:
+	cp descriptor.pb.golden descriptor.pb.go
+
+preserve:
+	cp descriptor.pb.go descriptor.pb.golden
diff --git a/compiler/descriptor/descriptor.pb.go b/compiler/descriptor/descriptor.pb.go
new file mode 100644
index 0000000..dc7e4a6
--- /dev/null
+++ b/compiler/descriptor/descriptor.pb.go
@@ -0,0 +1,398 @@
+// Code generated by protoc-gen-go from "google/protobuf/descriptor.proto"
+// DO NOT EDIT!
+
+package google_protobuf
+
+import "goprotobuf.googlecode.com/hg/proto"
+
+type FieldDescriptorProto_Type int32
+const (
+	FieldDescriptorProto_TYPE_DOUBLE = 1
+	FieldDescriptorProto_TYPE_FLOAT = 2
+	FieldDescriptorProto_TYPE_INT64 = 3
+	FieldDescriptorProto_TYPE_UINT64 = 4
+	FieldDescriptorProto_TYPE_INT32 = 5
+	FieldDescriptorProto_TYPE_FIXED64 = 6
+	FieldDescriptorProto_TYPE_FIXED32 = 7
+	FieldDescriptorProto_TYPE_BOOL = 8
+	FieldDescriptorProto_TYPE_STRING = 9
+	FieldDescriptorProto_TYPE_GROUP = 10
+	FieldDescriptorProto_TYPE_MESSAGE = 11
+	FieldDescriptorProto_TYPE_BYTES = 12
+	FieldDescriptorProto_TYPE_UINT32 = 13
+	FieldDescriptorProto_TYPE_ENUM = 14
+	FieldDescriptorProto_TYPE_SFIXED32 = 15
+	FieldDescriptorProto_TYPE_SFIXED64 = 16
+	FieldDescriptorProto_TYPE_SINT32 = 17
+	FieldDescriptorProto_TYPE_SINT64 = 18
+)
+var FieldDescriptorProto_Type_name = map[int32] string {
+	1: "TYPE_DOUBLE",
+	2: "TYPE_FLOAT",
+	3: "TYPE_INT64",
+	4: "TYPE_UINT64",
+	5: "TYPE_INT32",
+	6: "TYPE_FIXED64",
+	7: "TYPE_FIXED32",
+	8: "TYPE_BOOL",
+	9: "TYPE_STRING",
+	10: "TYPE_GROUP",
+	11: "TYPE_MESSAGE",
+	12: "TYPE_BYTES",
+	13: "TYPE_UINT32",
+	14: "TYPE_ENUM",
+	15: "TYPE_SFIXED32",
+	16: "TYPE_SFIXED64",
+	17: "TYPE_SINT32",
+	18: "TYPE_SINT64",
+}
+var FieldDescriptorProto_Type_value = map[string] int32 {
+	"TYPE_DOUBLE": 1,
+	"TYPE_FLOAT": 2,
+	"TYPE_INT64": 3,
+	"TYPE_UINT64": 4,
+	"TYPE_INT32": 5,
+	"TYPE_FIXED64": 6,
+	"TYPE_FIXED32": 7,
+	"TYPE_BOOL": 8,
+	"TYPE_STRING": 9,
+	"TYPE_GROUP": 10,
+	"TYPE_MESSAGE": 11,
+	"TYPE_BYTES": 12,
+	"TYPE_UINT32": 13,
+	"TYPE_ENUM": 14,
+	"TYPE_SFIXED32": 15,
+	"TYPE_SFIXED64": 16,
+	"TYPE_SINT32": 17,
+	"TYPE_SINT64": 18,
+}
+func NewFieldDescriptorProto_Type(x int32) *FieldDescriptorProto_Type {
+	e := FieldDescriptorProto_Type(x)
+	return &e
+}
+
+type FieldDescriptorProto_Label int32
+const (
+	FieldDescriptorProto_LABEL_OPTIONAL = 1
+	FieldDescriptorProto_LABEL_REQUIRED = 2
+	FieldDescriptorProto_LABEL_REPEATED = 3
+)
+var FieldDescriptorProto_Label_name = map[int32] string {
+	1: "LABEL_OPTIONAL",
+	2: "LABEL_REQUIRED",
+	3: "LABEL_REPEATED",
+}
+var FieldDescriptorProto_Label_value = map[string] int32 {
+	"LABEL_OPTIONAL": 1,
+	"LABEL_REQUIRED": 2,
+	"LABEL_REPEATED": 3,
+}
+func NewFieldDescriptorProto_Label(x int32) *FieldDescriptorProto_Label {
+	e := FieldDescriptorProto_Label(x)
+	return &e
+}
+
+type FileOptions_OptimizeMode int32
+const (
+	FileOptions_SPEED = 1
+	FileOptions_CODE_SIZE = 2
+	FileOptions_LITE_RUNTIME = 3
+)
+var FileOptions_OptimizeMode_name = map[int32] string {
+	1: "SPEED",
+	2: "CODE_SIZE",
+	3: "LITE_RUNTIME",
+}
+var FileOptions_OptimizeMode_value = map[string] int32 {
+	"SPEED": 1,
+	"CODE_SIZE": 2,
+	"LITE_RUNTIME": 3,
+}
+func NewFileOptions_OptimizeMode(x int32) *FileOptions_OptimizeMode {
+	e := FileOptions_OptimizeMode(x)
+	return &e
+}
+
+type FieldOptions_CType int32
+const (
+	FieldOptions_STRING = 0
+	FieldOptions_CORD = 1
+	FieldOptions_STRING_PIECE = 2
+)
+var FieldOptions_CType_name = map[int32] string {
+	0: "STRING",
+	1: "CORD",
+	2: "STRING_PIECE",
+}
+var FieldOptions_CType_value = map[string] int32 {
+	"STRING": 0,
+	"CORD": 1,
+	"STRING_PIECE": 2,
+}
+func NewFieldOptions_CType(x int32) *FieldOptions_CType {
+	e := FieldOptions_CType(x)
+	return &e
+}
+
+type FileDescriptorSet struct {
+	File	[]*FileDescriptorProto	"PB(bytes,1,rep,name=file)"
+	XXX_unrecognized	[]byte
+}
+func (this *FileDescriptorSet) Reset() {
+	*this = FileDescriptorSet{}
+}
+func NewFileDescriptorSet() *FileDescriptorSet {
+	return new(FileDescriptorSet)
+}
+
+type FileDescriptorProto struct {
+	Name	*string	"PB(bytes,1,opt,name=name)"
+	Package	*string	"PB(bytes,2,opt,name=package)"
+	Dependency	[]string	"PB(bytes,3,rep,name=dependency)"
+	MessageType	[]*DescriptorProto	"PB(bytes,4,rep,name=message_type)"
+	EnumType	[]*EnumDescriptorProto	"PB(bytes,5,rep,name=enum_type)"
+	Service	[]*ServiceDescriptorProto	"PB(bytes,6,rep,name=service)"
+	Extension	[]*FieldDescriptorProto	"PB(bytes,7,rep,name=extension)"
+	Options	*FileOptions	"PB(bytes,8,opt,name=options)"
+	XXX_unrecognized	[]byte
+}
+func (this *FileDescriptorProto) Reset() {
+	*this = FileDescriptorProto{}
+}
+func NewFileDescriptorProto() *FileDescriptorProto {
+	return new(FileDescriptorProto)
+}
+
+type DescriptorProto struct {
+	Name	*string	"PB(bytes,1,opt,name=name)"
+	Field	[]*FieldDescriptorProto	"PB(bytes,2,rep,name=field)"
+	Extension	[]*FieldDescriptorProto	"PB(bytes,6,rep,name=extension)"
+	NestedType	[]*DescriptorProto	"PB(bytes,3,rep,name=nested_type)"
+	EnumType	[]*EnumDescriptorProto	"PB(bytes,4,rep,name=enum_type)"
+	ExtensionRange	[]*DescriptorProto_ExtensionRange	"PB(bytes,5,rep,name=extension_range)"
+	Options	*MessageOptions	"PB(bytes,7,opt,name=options)"
+	XXX_unrecognized	[]byte
+}
+func (this *DescriptorProto) Reset() {
+	*this = DescriptorProto{}
+}
+func NewDescriptorProto() *DescriptorProto {
+	return new(DescriptorProto)
+}
+
+type DescriptorProto_ExtensionRange struct {
+	Start	*int32	"PB(varint,1,opt,name=start)"
+	End	*int32	"PB(varint,2,opt,name=end)"
+	XXX_unrecognized	[]byte
+}
+func (this *DescriptorProto_ExtensionRange) Reset() {
+	*this = DescriptorProto_ExtensionRange{}
+}
+func NewDescriptorProto_ExtensionRange() *DescriptorProto_ExtensionRange {
+	return new(DescriptorProto_ExtensionRange)
+}
+
+type FieldDescriptorProto struct {
+	Name	*string	"PB(bytes,1,opt,name=name)"
+	Number	*int32	"PB(varint,3,opt,name=number)"
+	Label	*FieldDescriptorProto_Label	"PB(varint,4,opt,name=label,enum=google_protobuf.FieldDescriptorProto_Label)"
+	Type	*FieldDescriptorProto_Type	"PB(varint,5,opt,name=type,enum=google_protobuf.FieldDescriptorProto_Type)"
+	TypeName	*string	"PB(bytes,6,opt,name=type_name)"
+	Extendee	*string	"PB(bytes,2,opt,name=extendee)"
+	DefaultValue	*string	"PB(bytes,7,opt,name=default_value)"
+	Options	*FieldOptions	"PB(bytes,8,opt,name=options)"
+	XXX_unrecognized	[]byte
+}
+func (this *FieldDescriptorProto) Reset() {
+	*this = FieldDescriptorProto{}
+}
+func NewFieldDescriptorProto() *FieldDescriptorProto {
+	return new(FieldDescriptorProto)
+}
+
+type EnumDescriptorProto struct {
+	Name	*string	"PB(bytes,1,opt,name=name)"
+	Value	[]*EnumValueDescriptorProto	"PB(bytes,2,rep,name=value)"
+	Options	*EnumOptions	"PB(bytes,3,opt,name=options)"
+	XXX_unrecognized	[]byte
+}
+func (this *EnumDescriptorProto) Reset() {
+	*this = EnumDescriptorProto{}
+}
+func NewEnumDescriptorProto() *EnumDescriptorProto {
+	return new(EnumDescriptorProto)
+}
+
+type EnumValueDescriptorProto struct {
+	Name	*string	"PB(bytes,1,opt,name=name)"
+	Number	*int32	"PB(varint,2,opt,name=number)"
+	Options	*EnumValueOptions	"PB(bytes,3,opt,name=options)"
+	XXX_unrecognized	[]byte
+}
+func (this *EnumValueDescriptorProto) Reset() {
+	*this = EnumValueDescriptorProto{}
+}
+func NewEnumValueDescriptorProto() *EnumValueDescriptorProto {
+	return new(EnumValueDescriptorProto)
+}
+
+type ServiceDescriptorProto struct {
+	Name	*string	"PB(bytes,1,opt,name=name)"
+	Method	[]*MethodDescriptorProto	"PB(bytes,2,rep,name=method)"
+	Options	*ServiceOptions	"PB(bytes,3,opt,name=options)"
+	XXX_unrecognized	[]byte
+}
+func (this *ServiceDescriptorProto) Reset() {
+	*this = ServiceDescriptorProto{}
+}
+func NewServiceDescriptorProto() *ServiceDescriptorProto {
+	return new(ServiceDescriptorProto)
+}
+
+type MethodDescriptorProto struct {
+	Name	*string	"PB(bytes,1,opt,name=name)"
+	InputType	*string	"PB(bytes,2,opt,name=input_type)"
+	OutputType	*string	"PB(bytes,3,opt,name=output_type)"
+	Options	*MethodOptions	"PB(bytes,4,opt,name=options)"
+	XXX_unrecognized	[]byte
+}
+func (this *MethodDescriptorProto) Reset() {
+	*this = MethodDescriptorProto{}
+}
+func NewMethodDescriptorProto() *MethodDescriptorProto {
+	return new(MethodDescriptorProto)
+}
+
+type FileOptions struct {
+	JavaPackage	*string	"PB(bytes,1,opt,name=java_package)"
+	JavaOuterClassname	*string	"PB(bytes,8,opt,name=java_outer_classname)"
+	JavaMultipleFiles	*bool	"PB(varint,10,opt,name=java_multiple_files,def=0)"
+	OptimizeFor	*FileOptions_OptimizeMode	"PB(varint,9,opt,name=optimize_for,enum=google_protobuf.FileOptions_OptimizeMode,def=1)"
+	CcGenericServices	*bool	"PB(varint,16,opt,name=cc_generic_services,def=1)"
+	JavaGenericServices	*bool	"PB(varint,17,opt,name=java_generic_services,def=1)"
+	PyGenericServices	*bool	"PB(varint,18,opt,name=py_generic_services,def=1)"
+	UninterpretedOption	[]*UninterpretedOption	"PB(bytes,999,rep,name=uninterpreted_option)"
+	XXX_unrecognized	[]byte
+}
+func (this *FileOptions) Reset() {
+	*this = FileOptions{}
+}
+func NewFileOptions() *FileOptions {
+	return new(FileOptions)
+}
+const Default_FileOptions_JavaMultipleFiles bool = false
+const Default_FileOptions_OptimizeFor FileOptions_OptimizeMode = FileOptions_SPEED
+const Default_FileOptions_CcGenericServices bool = true
+const Default_FileOptions_JavaGenericServices bool = true
+const Default_FileOptions_PyGenericServices bool = true
+
+type MessageOptions struct {
+	MessageSetWireFormat	*bool	"PB(varint,1,opt,name=message_set_wire_format,def=0)"
+	NoStandardDescriptorAccessor	*bool	"PB(varint,2,opt,name=no_standard_descriptor_accessor,def=0)"
+	UninterpretedOption	[]*UninterpretedOption	"PB(bytes,999,rep,name=uninterpreted_option)"
+	XXX_unrecognized	[]byte
+}
+func (this *MessageOptions) Reset() {
+	*this = MessageOptions{}
+}
+func NewMessageOptions() *MessageOptions {
+	return new(MessageOptions)
+}
+const Default_MessageOptions_MessageSetWireFormat bool = false
+const Default_MessageOptions_NoStandardDescriptorAccessor bool = false
+
+type FieldOptions struct {
+	Ctype	*FieldOptions_CType	"PB(varint,1,opt,name=ctype,enum=google_protobuf.FieldOptions_CType,def=0)"
+	Packed	*bool	"PB(varint,2,opt,name=packed)"
+	Deprecated	*bool	"PB(varint,3,opt,name=deprecated,def=0)"
+	ExperimentalMapKey	*string	"PB(bytes,9,opt,name=experimental_map_key)"
+	UninterpretedOption	[]*UninterpretedOption	"PB(bytes,999,rep,name=uninterpreted_option)"
+	XXX_unrecognized	[]byte
+}
+func (this *FieldOptions) Reset() {
+	*this = FieldOptions{}
+}
+func NewFieldOptions() *FieldOptions {
+	return new(FieldOptions)
+}
+const Default_FieldOptions_Ctype FieldOptions_CType = FieldOptions_STRING
+const Default_FieldOptions_Deprecated bool = false
+
+type EnumOptions struct {
+	UninterpretedOption	[]*UninterpretedOption	"PB(bytes,999,rep,name=uninterpreted_option)"
+	XXX_unrecognized	[]byte
+}
+func (this *EnumOptions) Reset() {
+	*this = EnumOptions{}
+}
+func NewEnumOptions() *EnumOptions {
+	return new(EnumOptions)
+}
+
+type EnumValueOptions struct {
+	UninterpretedOption	[]*UninterpretedOption	"PB(bytes,999,rep,name=uninterpreted_option)"
+	XXX_unrecognized	[]byte
+}
+func (this *EnumValueOptions) Reset() {
+	*this = EnumValueOptions{}
+}
+func NewEnumValueOptions() *EnumValueOptions {
+	return new(EnumValueOptions)
+}
+
+type ServiceOptions struct {
+	UninterpretedOption	[]*UninterpretedOption	"PB(bytes,999,rep,name=uninterpreted_option)"
+	XXX_unrecognized	[]byte
+}
+func (this *ServiceOptions) Reset() {
+	*this = ServiceOptions{}
+}
+func NewServiceOptions() *ServiceOptions {
+	return new(ServiceOptions)
+}
+
+type MethodOptions struct {
+	UninterpretedOption	[]*UninterpretedOption	"PB(bytes,999,rep,name=uninterpreted_option)"
+	XXX_unrecognized	[]byte
+}
+func (this *MethodOptions) Reset() {
+	*this = MethodOptions{}
+}
+func NewMethodOptions() *MethodOptions {
+	return new(MethodOptions)
+}
+
+type UninterpretedOption struct {
+	Name	[]*UninterpretedOption_NamePart	"PB(bytes,2,rep,name=name)"
+	IdentifierValue	*string	"PB(bytes,3,opt,name=identifier_value)"
+	PositiveIntValue	*uint64	"PB(varint,4,opt,name=positive_int_value)"
+	NegativeIntValue	*int64	"PB(varint,5,opt,name=negative_int_value)"
+	DoubleValue	*float64	"PB(fixed64,6,opt,name=double_value)"
+	StringValue	[]byte	"PB(bytes,7,opt,name=string_value)"
+	XXX_unrecognized	[]byte
+}
+func (this *UninterpretedOption) Reset() {
+	*this = UninterpretedOption{}
+}
+func NewUninterpretedOption() *UninterpretedOption {
+	return new(UninterpretedOption)
+}
+
+type UninterpretedOption_NamePart struct {
+	NamePart	*string	"PB(bytes,1,req,name=name_part)"
+	IsExtension	*bool	"PB(varint,2,req,name=is_extension)"
+	XXX_unrecognized	[]byte
+}
+func (this *UninterpretedOption_NamePart) Reset() {
+	*this = UninterpretedOption_NamePart{}
+}
+func NewUninterpretedOption_NamePart() *UninterpretedOption_NamePart {
+	return new(UninterpretedOption_NamePart)
+}
+
+func init() {
+	proto.RegisterEnum("google_protobuf.FieldDescriptorProto_Type", FieldDescriptorProto_Type_name, FieldDescriptorProto_Type_value)
+	proto.RegisterEnum("google_protobuf.FieldDescriptorProto_Label", FieldDescriptorProto_Label_name, FieldDescriptorProto_Label_value)
+	proto.RegisterEnum("google_protobuf.FileOptions_OptimizeMode", FileOptions_OptimizeMode_name, FileOptions_OptimizeMode_value)
+	proto.RegisterEnum("google_protobuf.FieldOptions_CType", FieldOptions_CType_name, FieldOptions_CType_value)
+}
diff --git a/compiler/descriptor/descriptor.pb.golden b/compiler/descriptor/descriptor.pb.golden
new file mode 100644
index 0000000..dc7e4a6
--- /dev/null
+++ b/compiler/descriptor/descriptor.pb.golden
@@ -0,0 +1,398 @@
+// Code generated by protoc-gen-go from "google/protobuf/descriptor.proto"
+// DO NOT EDIT!
+
+package google_protobuf
+
+import "goprotobuf.googlecode.com/hg/proto"
+
+type FieldDescriptorProto_Type int32
+const (
+	FieldDescriptorProto_TYPE_DOUBLE = 1
+	FieldDescriptorProto_TYPE_FLOAT = 2
+	FieldDescriptorProto_TYPE_INT64 = 3
+	FieldDescriptorProto_TYPE_UINT64 = 4
+	FieldDescriptorProto_TYPE_INT32 = 5
+	FieldDescriptorProto_TYPE_FIXED64 = 6
+	FieldDescriptorProto_TYPE_FIXED32 = 7
+	FieldDescriptorProto_TYPE_BOOL = 8
+	FieldDescriptorProto_TYPE_STRING = 9
+	FieldDescriptorProto_TYPE_GROUP = 10
+	FieldDescriptorProto_TYPE_MESSAGE = 11
+	FieldDescriptorProto_TYPE_BYTES = 12
+	FieldDescriptorProto_TYPE_UINT32 = 13
+	FieldDescriptorProto_TYPE_ENUM = 14
+	FieldDescriptorProto_TYPE_SFIXED32 = 15
+	FieldDescriptorProto_TYPE_SFIXED64 = 16
+	FieldDescriptorProto_TYPE_SINT32 = 17
+	FieldDescriptorProto_TYPE_SINT64 = 18
+)
+var FieldDescriptorProto_Type_name = map[int32] string {
+	1: "TYPE_DOUBLE",
+	2: "TYPE_FLOAT",
+	3: "TYPE_INT64",
+	4: "TYPE_UINT64",
+	5: "TYPE_INT32",
+	6: "TYPE_FIXED64",
+	7: "TYPE_FIXED32",
+	8: "TYPE_BOOL",
+	9: "TYPE_STRING",
+	10: "TYPE_GROUP",
+	11: "TYPE_MESSAGE",
+	12: "TYPE_BYTES",
+	13: "TYPE_UINT32",
+	14: "TYPE_ENUM",
+	15: "TYPE_SFIXED32",
+	16: "TYPE_SFIXED64",
+	17: "TYPE_SINT32",
+	18: "TYPE_SINT64",
+}
+var FieldDescriptorProto_Type_value = map[string] int32 {
+	"TYPE_DOUBLE": 1,
+	"TYPE_FLOAT": 2,
+	"TYPE_INT64": 3,
+	"TYPE_UINT64": 4,
+	"TYPE_INT32": 5,
+	"TYPE_FIXED64": 6,
+	"TYPE_FIXED32": 7,
+	"TYPE_BOOL": 8,
+	"TYPE_STRING": 9,
+	"TYPE_GROUP": 10,
+	"TYPE_MESSAGE": 11,
+	"TYPE_BYTES": 12,
+	"TYPE_UINT32": 13,
+	"TYPE_ENUM": 14,
+	"TYPE_SFIXED32": 15,
+	"TYPE_SFIXED64": 16,
+	"TYPE_SINT32": 17,
+	"TYPE_SINT64": 18,
+}
+func NewFieldDescriptorProto_Type(x int32) *FieldDescriptorProto_Type {
+	e := FieldDescriptorProto_Type(x)
+	return &e
+}
+
+type FieldDescriptorProto_Label int32
+const (
+	FieldDescriptorProto_LABEL_OPTIONAL = 1
+	FieldDescriptorProto_LABEL_REQUIRED = 2
+	FieldDescriptorProto_LABEL_REPEATED = 3
+)
+var FieldDescriptorProto_Label_name = map[int32] string {
+	1: "LABEL_OPTIONAL",
+	2: "LABEL_REQUIRED",
+	3: "LABEL_REPEATED",
+}
+var FieldDescriptorProto_Label_value = map[string] int32 {
+	"LABEL_OPTIONAL": 1,
+	"LABEL_REQUIRED": 2,
+	"LABEL_REPEATED": 3,
+}
+func NewFieldDescriptorProto_Label(x int32) *FieldDescriptorProto_Label {
+	e := FieldDescriptorProto_Label(x)
+	return &e
+}
+
+type FileOptions_OptimizeMode int32
+const (
+	FileOptions_SPEED = 1
+	FileOptions_CODE_SIZE = 2
+	FileOptions_LITE_RUNTIME = 3
+)
+var FileOptions_OptimizeMode_name = map[int32] string {
+	1: "SPEED",
+	2: "CODE_SIZE",
+	3: "LITE_RUNTIME",
+}
+var FileOptions_OptimizeMode_value = map[string] int32 {
+	"SPEED": 1,
+	"CODE_SIZE": 2,
+	"LITE_RUNTIME": 3,
+}
+func NewFileOptions_OptimizeMode(x int32) *FileOptions_OptimizeMode {
+	e := FileOptions_OptimizeMode(x)
+	return &e
+}
+
+type FieldOptions_CType int32
+const (
+	FieldOptions_STRING = 0
+	FieldOptions_CORD = 1
+	FieldOptions_STRING_PIECE = 2
+)
+var FieldOptions_CType_name = map[int32] string {
+	0: "STRING",
+	1: "CORD",
+	2: "STRING_PIECE",
+}
+var FieldOptions_CType_value = map[string] int32 {
+	"STRING": 0,
+	"CORD": 1,
+	"STRING_PIECE": 2,
+}
+func NewFieldOptions_CType(x int32) *FieldOptions_CType {
+	e := FieldOptions_CType(x)
+	return &e
+}
+
+type FileDescriptorSet struct {
+	File	[]*FileDescriptorProto	"PB(bytes,1,rep,name=file)"
+	XXX_unrecognized	[]byte
+}
+func (this *FileDescriptorSet) Reset() {
+	*this = FileDescriptorSet{}
+}
+func NewFileDescriptorSet() *FileDescriptorSet {
+	return new(FileDescriptorSet)
+}
+
+type FileDescriptorProto struct {
+	Name	*string	"PB(bytes,1,opt,name=name)"
+	Package	*string	"PB(bytes,2,opt,name=package)"
+	Dependency	[]string	"PB(bytes,3,rep,name=dependency)"
+	MessageType	[]*DescriptorProto	"PB(bytes,4,rep,name=message_type)"
+	EnumType	[]*EnumDescriptorProto	"PB(bytes,5,rep,name=enum_type)"
+	Service	[]*ServiceDescriptorProto	"PB(bytes,6,rep,name=service)"
+	Extension	[]*FieldDescriptorProto	"PB(bytes,7,rep,name=extension)"
+	Options	*FileOptions	"PB(bytes,8,opt,name=options)"
+	XXX_unrecognized	[]byte
+}
+func (this *FileDescriptorProto) Reset() {
+	*this = FileDescriptorProto{}
+}
+func NewFileDescriptorProto() *FileDescriptorProto {
+	return new(FileDescriptorProto)
+}
+
+type DescriptorProto struct {
+	Name	*string	"PB(bytes,1,opt,name=name)"
+	Field	[]*FieldDescriptorProto	"PB(bytes,2,rep,name=field)"
+	Extension	[]*FieldDescriptorProto	"PB(bytes,6,rep,name=extension)"
+	NestedType	[]*DescriptorProto	"PB(bytes,3,rep,name=nested_type)"
+	EnumType	[]*EnumDescriptorProto	"PB(bytes,4,rep,name=enum_type)"
+	ExtensionRange	[]*DescriptorProto_ExtensionRange	"PB(bytes,5,rep,name=extension_range)"
+	Options	*MessageOptions	"PB(bytes,7,opt,name=options)"
+	XXX_unrecognized	[]byte
+}
+func (this *DescriptorProto) Reset() {
+	*this = DescriptorProto{}
+}
+func NewDescriptorProto() *DescriptorProto {
+	return new(DescriptorProto)
+}
+
+type DescriptorProto_ExtensionRange struct {
+	Start	*int32	"PB(varint,1,opt,name=start)"
+	End	*int32	"PB(varint,2,opt,name=end)"
+	XXX_unrecognized	[]byte
+}
+func (this *DescriptorProto_ExtensionRange) Reset() {
+	*this = DescriptorProto_ExtensionRange{}
+}
+func NewDescriptorProto_ExtensionRange() *DescriptorProto_ExtensionRange {
+	return new(DescriptorProto_ExtensionRange)
+}
+
+type FieldDescriptorProto struct {
+	Name	*string	"PB(bytes,1,opt,name=name)"
+	Number	*int32	"PB(varint,3,opt,name=number)"
+	Label	*FieldDescriptorProto_Label	"PB(varint,4,opt,name=label,enum=google_protobuf.FieldDescriptorProto_Label)"
+	Type	*FieldDescriptorProto_Type	"PB(varint,5,opt,name=type,enum=google_protobuf.FieldDescriptorProto_Type)"
+	TypeName	*string	"PB(bytes,6,opt,name=type_name)"
+	Extendee	*string	"PB(bytes,2,opt,name=extendee)"
+	DefaultValue	*string	"PB(bytes,7,opt,name=default_value)"
+	Options	*FieldOptions	"PB(bytes,8,opt,name=options)"
+	XXX_unrecognized	[]byte
+}
+func (this *FieldDescriptorProto) Reset() {
+	*this = FieldDescriptorProto{}
+}
+func NewFieldDescriptorProto() *FieldDescriptorProto {
+	return new(FieldDescriptorProto)
+}
+
+type EnumDescriptorProto struct {
+	Name	*string	"PB(bytes,1,opt,name=name)"
+	Value	[]*EnumValueDescriptorProto	"PB(bytes,2,rep,name=value)"
+	Options	*EnumOptions	"PB(bytes,3,opt,name=options)"
+	XXX_unrecognized	[]byte
+}
+func (this *EnumDescriptorProto) Reset() {
+	*this = EnumDescriptorProto{}
+}
+func NewEnumDescriptorProto() *EnumDescriptorProto {
+	return new(EnumDescriptorProto)
+}
+
+type EnumValueDescriptorProto struct {
+	Name	*string	"PB(bytes,1,opt,name=name)"
+	Number	*int32	"PB(varint,2,opt,name=number)"
+	Options	*EnumValueOptions	"PB(bytes,3,opt,name=options)"
+	XXX_unrecognized	[]byte
+}
+func (this *EnumValueDescriptorProto) Reset() {
+	*this = EnumValueDescriptorProto{}
+}
+func NewEnumValueDescriptorProto() *EnumValueDescriptorProto {
+	return new(EnumValueDescriptorProto)
+}
+
+type ServiceDescriptorProto struct {
+	Name	*string	"PB(bytes,1,opt,name=name)"
+	Method	[]*MethodDescriptorProto	"PB(bytes,2,rep,name=method)"
+	Options	*ServiceOptions	"PB(bytes,3,opt,name=options)"
+	XXX_unrecognized	[]byte
+}
+func (this *ServiceDescriptorProto) Reset() {
+	*this = ServiceDescriptorProto{}
+}
+func NewServiceDescriptorProto() *ServiceDescriptorProto {
+	return new(ServiceDescriptorProto)
+}
+
+type MethodDescriptorProto struct {
+	Name	*string	"PB(bytes,1,opt,name=name)"
+	InputType	*string	"PB(bytes,2,opt,name=input_type)"
+	OutputType	*string	"PB(bytes,3,opt,name=output_type)"
+	Options	*MethodOptions	"PB(bytes,4,opt,name=options)"
+	XXX_unrecognized	[]byte
+}
+func (this *MethodDescriptorProto) Reset() {
+	*this = MethodDescriptorProto{}
+}
+func NewMethodDescriptorProto() *MethodDescriptorProto {
+	return new(MethodDescriptorProto)
+}
+
+type FileOptions struct {
+	JavaPackage	*string	"PB(bytes,1,opt,name=java_package)"
+	JavaOuterClassname	*string	"PB(bytes,8,opt,name=java_outer_classname)"
+	JavaMultipleFiles	*bool	"PB(varint,10,opt,name=java_multiple_files,def=0)"
+	OptimizeFor	*FileOptions_OptimizeMode	"PB(varint,9,opt,name=optimize_for,enum=google_protobuf.FileOptions_OptimizeMode,def=1)"
+	CcGenericServices	*bool	"PB(varint,16,opt,name=cc_generic_services,def=1)"
+	JavaGenericServices	*bool	"PB(varint,17,opt,name=java_generic_services,def=1)"
+	PyGenericServices	*bool	"PB(varint,18,opt,name=py_generic_services,def=1)"
+	UninterpretedOption	[]*UninterpretedOption	"PB(bytes,999,rep,name=uninterpreted_option)"
+	XXX_unrecognized	[]byte
+}
+func (this *FileOptions) Reset() {
+	*this = FileOptions{}
+}
+func NewFileOptions() *FileOptions {
+	return new(FileOptions)
+}
+const Default_FileOptions_JavaMultipleFiles bool = false
+const Default_FileOptions_OptimizeFor FileOptions_OptimizeMode = FileOptions_SPEED
+const Default_FileOptions_CcGenericServices bool = true
+const Default_FileOptions_JavaGenericServices bool = true
+const Default_FileOptions_PyGenericServices bool = true
+
+type MessageOptions struct {
+	MessageSetWireFormat	*bool	"PB(varint,1,opt,name=message_set_wire_format,def=0)"
+	NoStandardDescriptorAccessor	*bool	"PB(varint,2,opt,name=no_standard_descriptor_accessor,def=0)"
+	UninterpretedOption	[]*UninterpretedOption	"PB(bytes,999,rep,name=uninterpreted_option)"
+	XXX_unrecognized	[]byte
+}
+func (this *MessageOptions) Reset() {
+	*this = MessageOptions{}
+}
+func NewMessageOptions() *MessageOptions {
+	return new(MessageOptions)
+}
+const Default_MessageOptions_MessageSetWireFormat bool = false
+const Default_MessageOptions_NoStandardDescriptorAccessor bool = false
+
+type FieldOptions struct {
+	Ctype	*FieldOptions_CType	"PB(varint,1,opt,name=ctype,enum=google_protobuf.FieldOptions_CType,def=0)"
+	Packed	*bool	"PB(varint,2,opt,name=packed)"
+	Deprecated	*bool	"PB(varint,3,opt,name=deprecated,def=0)"
+	ExperimentalMapKey	*string	"PB(bytes,9,opt,name=experimental_map_key)"
+	UninterpretedOption	[]*UninterpretedOption	"PB(bytes,999,rep,name=uninterpreted_option)"
+	XXX_unrecognized	[]byte
+}
+func (this *FieldOptions) Reset() {
+	*this = FieldOptions{}
+}
+func NewFieldOptions() *FieldOptions {
+	return new(FieldOptions)
+}
+const Default_FieldOptions_Ctype FieldOptions_CType = FieldOptions_STRING
+const Default_FieldOptions_Deprecated bool = false
+
+type EnumOptions struct {
+	UninterpretedOption	[]*UninterpretedOption	"PB(bytes,999,rep,name=uninterpreted_option)"
+	XXX_unrecognized	[]byte
+}
+func (this *EnumOptions) Reset() {
+	*this = EnumOptions{}
+}
+func NewEnumOptions() *EnumOptions {
+	return new(EnumOptions)
+}
+
+type EnumValueOptions struct {
+	UninterpretedOption	[]*UninterpretedOption	"PB(bytes,999,rep,name=uninterpreted_option)"
+	XXX_unrecognized	[]byte
+}
+func (this *EnumValueOptions) Reset() {
+	*this = EnumValueOptions{}
+}
+func NewEnumValueOptions() *EnumValueOptions {
+	return new(EnumValueOptions)
+}
+
+type ServiceOptions struct {
+	UninterpretedOption	[]*UninterpretedOption	"PB(bytes,999,rep,name=uninterpreted_option)"
+	XXX_unrecognized	[]byte
+}
+func (this *ServiceOptions) Reset() {
+	*this = ServiceOptions{}
+}
+func NewServiceOptions() *ServiceOptions {
+	return new(ServiceOptions)
+}
+
+type MethodOptions struct {
+	UninterpretedOption	[]*UninterpretedOption	"PB(bytes,999,rep,name=uninterpreted_option)"
+	XXX_unrecognized	[]byte
+}
+func (this *MethodOptions) Reset() {
+	*this = MethodOptions{}
+}
+func NewMethodOptions() *MethodOptions {
+	return new(MethodOptions)
+}
+
+type UninterpretedOption struct {
+	Name	[]*UninterpretedOption_NamePart	"PB(bytes,2,rep,name=name)"
+	IdentifierValue	*string	"PB(bytes,3,opt,name=identifier_value)"
+	PositiveIntValue	*uint64	"PB(varint,4,opt,name=positive_int_value)"
+	NegativeIntValue	*int64	"PB(varint,5,opt,name=negative_int_value)"
+	DoubleValue	*float64	"PB(fixed64,6,opt,name=double_value)"
+	StringValue	[]byte	"PB(bytes,7,opt,name=string_value)"
+	XXX_unrecognized	[]byte
+}
+func (this *UninterpretedOption) Reset() {
+	*this = UninterpretedOption{}
+}
+func NewUninterpretedOption() *UninterpretedOption {
+	return new(UninterpretedOption)
+}
+
+type UninterpretedOption_NamePart struct {
+	NamePart	*string	"PB(bytes,1,req,name=name_part)"
+	IsExtension	*bool	"PB(varint,2,req,name=is_extension)"
+	XXX_unrecognized	[]byte
+}
+func (this *UninterpretedOption_NamePart) Reset() {
+	*this = UninterpretedOption_NamePart{}
+}
+func NewUninterpretedOption_NamePart() *UninterpretedOption_NamePart {
+	return new(UninterpretedOption_NamePart)
+}
+
+func init() {
+	proto.RegisterEnum("google_protobuf.FieldDescriptorProto_Type", FieldDescriptorProto_Type_name, FieldDescriptorProto_Type_value)
+	proto.RegisterEnum("google_protobuf.FieldDescriptorProto_Label", FieldDescriptorProto_Label_name, FieldDescriptorProto_Label_value)
+	proto.RegisterEnum("google_protobuf.FileOptions_OptimizeMode", FileOptions_OptimizeMode_name, FileOptions_OptimizeMode_value)
+	proto.RegisterEnum("google_protobuf.FieldOptions_CType", FieldOptions_CType_name, FieldOptions_CType_value)
+}
diff --git a/compiler/doc.go b/compiler/doc.go
new file mode 100644
index 0000000..f84ff8e
--- /dev/null
+++ b/compiler/doc.go
@@ -0,0 +1,51 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2010 Google Inc.  All rights reserved.
+// http://code.google.com/p/goprotobuf/
+//
+// 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.
+
+/*
+	A plugin for the Google protocol buffer compiler to generate Go code.
+	Run it by building this program and putting it in your path with the name
+		protoc-gen-go
+	That word 'go' at the end becomes part of the option string set for the
+	protocol compiler, so once the protocol compiler (protoc) is installed
+	you can run
+		protoc --go_out=output_directory input_directory/file.proto
+	to generate Go bindings for the protocol defined by file.proto.
+	With that input, the output will be written to
+		output_directory/file.pb.go
+
+	The generated code is documented in the package comment for
+	the library.
+
+	See the README and documentation for protocol buffers to learn more:
+		http://code.google.com/p/protobuf/
+
+*/
+package documentation
diff --git a/compiler/main.go b/compiler/main.go
new file mode 100644
index 0000000..88bb4c5
--- /dev/null
+++ b/compiler/main.go
@@ -0,0 +1,903 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2010 Google Inc.  All rights reserved.
+// http://code.google.com/p/goprotobuf/
+//
+// 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.
+
+/*
+	A plugin for the Google protocol buffer compiler to generate Go code.
+
+	This plugin takes no options and the protocol buffer file syntax does
+	not yet define any options for Go, so program does no option evaluation.
+	That may change.
+
+	Not supported yet:
+		Extensions
+		Services
+*/
+
+package main
+
+import (
+	"bytes"
+	"fmt"
+	"io/ioutil"
+	"log"
+	"os"
+	"strings"
+	"unicode"
+
+	"goprotobuf.googlecode.com/hg/proto"
+	plugin "goprotobuf.googlecode.com/hg/compiler/plugin"
+	descriptor "goprotobuf.googlecode.com/hg/compiler/descriptor"
+)
+
+func main() {
+	// Begin by allocating a generator. The request and response structures are stored there
+	// so we can do error handling easily - the response structure contains the field to
+	// report failure.
+	g := NewGenerator()
+
+	data, err := ioutil.ReadAll(os.Stdin)
+	if err != nil {
+		g.error(err, "reading input")
+	}
+
+	if err := proto.Unmarshal(data, g.request); err != nil {
+		g.error(err, "parsing input proto")
+	}
+
+	if len(g.request.FileToGenerate) == 0 {
+		g.fail("no files to generate")
+	}
+
+	// Create a wrapped version of the Descriptors and EnumDescriptors that
+	// point to the file that defines them.
+	g.WrapTypes()
+
+	g.SetPackageNames()
+	g.BuildTypeNameMap()
+
+	g.GenerateAllFiles()
+
+	// Send back the results.
+	data, err = proto.Marshal(g.response)
+	if err != nil {
+		g.error(err, "failed to marshal output proto")
+	}
+	_, err = os.Stdout.Write(data)
+	if err != nil {
+		g.error(err, "failed to write output proto")
+	}
+}
+
+// Each type we import as a protocol buffer (other than FileDescriptorProto) needs
+// a pointer to the FileDescriptorProto that represents it.  These types achieve that
+// wrapping by placing each Proto inside a struct with the pointer to its File. The
+// structs have the same names as their contents, with "Proto" removed.
+// FileDescriptor is used to store the things that it points to.
+
+// The file and package name method are common to messages and enums.
+type common struct {
+	file *descriptor.FileDescriptorProto // File this object comes from.
+}
+
+// The package name we will produce in our output.
+func (c *common) packageName() string { return uniquePackageOf(c.file) }
+
+// A message (struct).
+type Descriptor struct {
+	common
+	*descriptor.DescriptorProto
+	parent   *Descriptor   // The containing message, if any.
+	nested   []*Descriptor // Inner messages, if any.
+	typename []string      // Cached typename vector.
+}
+
+// Return the elements of the dotted type name.  The package name is not part
+// of this name.
+func (d *Descriptor) typeName() []string {
+	if d.typename != nil {
+		return d.typename
+	}
+	n := 0
+	for parent := d; parent != nil; parent = parent.parent {
+		n++
+	}
+	s := make([]string, n, n)
+	for parent := d; parent != nil; parent = parent.parent {
+		n--
+		s[n] = proto.GetString(parent.Name)
+	}
+	d.typename = s
+	return s
+}
+
+// An enum. If it's at top level, its parent will be nil. Otherwise it will be
+// the descriptor of the message in which it is defined.
+type EnumDescriptor struct {
+	common
+	*descriptor.EnumDescriptorProto
+	parent   *Descriptor // The containing message, if any.
+	typename []string    // Cached typename vector.
+}
+
+// Return the elements of the dotted type name.
+func (e *EnumDescriptor) typeName() (s []string) {
+	if e.typename != nil {
+		return e.typename
+	}
+	name := proto.GetString(e.Name)
+	if e.parent == nil {
+		s = make([]string, 1)
+	} else {
+		pname := e.parent.typeName()
+		s = make([]string, len(pname)+1)
+		copy(s, pname)
+	}
+	s[len(s)-1] = name
+	e.typename = s
+	return s
+}
+
+// Everything but the last element of the full type name, CamelCased.
+// The values of type Foo.Bar are call Foo_value1... not Foo_Bar_value1... .
+func (e *EnumDescriptor) prefix() string {
+	typeName := e.typeName()
+	ccPrefix := CamelCaseSlice(typeName[0:len(typeName)-1]) + "_"
+	if e.parent == nil {
+		// If the enum is not part of a message, the prefix is just the type name.
+		ccPrefix = CamelCase(*e.Name) + "_"
+	}
+	return ccPrefix
+}
+
+// The integer value of the named constant in this enumerated type.
+func (e *EnumDescriptor) integerValueAsString(name string) string {
+	for _, c := range e.Value {
+		if proto.GetString(c.Name) == name {
+			return fmt.Sprint(proto.GetInt32(c.Number))
+		}
+	}
+	log.Exit("cannot find value for enum constant")
+	return ""
+}
+
+// A file. Includes slices of all the messages and enums defined within it.
+// Those slices are constructed by WrapTypes.
+type FileDescriptor struct {
+	*descriptor.FileDescriptorProto
+	desc []*Descriptor     // All the messages defined in this file.
+	enum []*EnumDescriptor // All the enums defined in this file.
+}
+
+// The package name we'll use in the generated code to refer to this file.
+func (d *FileDescriptor) packageName() string { return uniquePackageOf(d.FileDescriptorProto) }
+
+// The package named defined in the input for this file, possibly dotted.
+func (d *FileDescriptor) originalPackageName() string {
+	return proto.GetString(d.Package)
+}
+
+// Simplify some things by abstracting the abilities shared by enums and messages.
+type Object interface {
+	packageName() string // The name we use in our output (a_b_c), possibly renamed for uniqueness.
+	typeName() []string
+}
+
+// Each package name we generate must be unique. The package we're generating
+// gets its own name but every other package must have a unqiue name that does
+// not conflict in the code we generate.  These names are chosen globally (although
+// they don't have to be, it simplifies things to do them globally).
+func uniquePackageOf(fd *descriptor.FileDescriptorProto) string {
+	s, ok := uniquePackageName[fd]
+	if !ok {
+		log.Exit("internal error: no package name defined for", proto.GetString(fd.Name))
+	}
+	return s
+}
+
+// The type whose methods generate the output, stored in the associated response structure.
+type Generator struct {
+	bytes.Buffer
+
+	request  *plugin.CodeGeneratorRequest  // The input.
+	response *plugin.CodeGeneratorResponse // The output.
+
+	packageName      string            // What we're calling ourselves.
+	allFiles         []*FileDescriptor // All files in the tree
+	genFiles         []*FileDescriptor // Those files we will generate output for.
+	file             *FileDescriptor   // The file we are compiling now.
+	typeNameToObject map[string]Object // Key is a fully-qualified name in input syntax.
+	indent           string
+}
+
+// Create a new generator and allocate the request and response protobufs.
+func NewGenerator() *Generator {
+	g := new(Generator)
+	g.request = plugin.NewCodeGeneratorRequest()
+	g.response = plugin.NewCodeGeneratorResponse()
+	return g
+}
+
+// Report problem, including an os.Error, and fail.
+func (g *Generator) error(err os.Error, msgs ...string) {
+	s := strings.Join(msgs, " ") + ":" + err.String()
+	log.Stderr("protoc-gen-go: error: ", s)
+	g.response.Error = proto.String(s)
+	os.Exit(1)
+}
+
+// Report problem and fail.
+func (g *Generator) fail(msgs ...string) {
+	s := strings.Join(msgs, " ")
+	log.Stderr("protoc-gen-go: error: ", s)
+	g.response.Error = proto.String(s)
+	os.Exit(1)
+}
+
+// If this file is in a different package, return the package name we're using for this file, plus ".".
+// Otherwise return the empty string.
+func (g *Generator) DefaultPackageName(obj Object) string {
+	pkg := obj.packageName()
+	if pkg == g.packageName {
+		return ""
+	}
+	return pkg + "."
+}
+
+// For each input file, the unique package name to use, underscored.
+var uniquePackageName = make(map[*descriptor.FileDescriptorProto]string)
+
+// Set the package name for this run.  It must agree across all files being generated.
+// Also define unique package names for all imported files.
+func (g *Generator) SetPackageNames() {
+	inUse := make(map[string]bool)
+	pkg := proto.GetString(g.genFiles[0].Package)
+	g.packageName = strings.Map(DotToUnderscore, pkg)
+	inUse[pkg] = true
+	for _, f := range g.genFiles {
+		thisPkg := proto.GetString(f.Package)
+		if thisPkg != pkg {
+			g.fail("inconsistent package names:", thisPkg, pkg)
+		}
+	}
+AllFiles:
+	for _, f := range g.allFiles {
+		for _, genf := range g.genFiles {
+			if f == genf {
+				// In this package already.
+				uniquePackageName[f.FileDescriptorProto] = g.packageName
+				continue AllFiles
+			}
+		}
+		truePkg := proto.GetString(f.Package)
+		pkg := truePkg
+		for {
+			_, present := inUse[pkg]
+			if present {
+				// It's a duplicate; must rename.
+				pkg += "X"
+				continue
+			}
+			break
+		}
+		// Install it.
+		if pkg != truePkg {
+			log.Stderr("renaming duplicate imported package named", truePkg, "to", pkg)
+		}
+		inUse[pkg] = true
+		uniquePackageName[f.FileDescriptorProto] = strings.Map(DotToUnderscore, pkg)
+	}
+}
+
+// Walk the incoming data, wrapping DescriptorProtos and EnumDescriptorProtos
+// into file-referenced objects within the Generator.  Also create the list of files
+// to generate
+func (g *Generator) WrapTypes() {
+	g.allFiles = make([]*FileDescriptor, len(g.request.ProtoFile))
+	for i, f := range g.request.ProtoFile {
+		pkg := proto.GetString(f.Package)
+		if pkg == "" {
+			g.fail(proto.GetString(f.Name), "is missing a package declaration")
+		}
+		// We must wrap the descriptors before we wrap the enums
+		descs := WrapDescriptors(f)
+		g.BuildNestedDescriptors(descs)
+		enums := WrapEnumDescriptors(f, descs)
+		g.allFiles[i] = &FileDescriptor{
+			FileDescriptorProto: f,
+			desc:                descs,
+			enum:                enums,
+		}
+	}
+
+	g.genFiles = make([]*FileDescriptor, len(g.request.FileToGenerate))
+FindFiles:
+	for i, fileName := range g.request.FileToGenerate {
+		// Search the list.  This algorithm is n^2 but n is tiny.
+		for _, file := range g.allFiles {
+			if fileName == proto.GetString(file.Name) {
+				g.genFiles[i] = file
+				continue FindFiles
+			}
+		}
+		g.fail("could not find file named", fileName)
+	}
+	g.response.File = make([]*plugin.CodeGeneratorResponse_File, len(g.genFiles))
+}
+
+// Scan the descriptors in this file.  For each one, build the slice of nested descriptors
+func (g *Generator) BuildNestedDescriptors(descs []*Descriptor) {
+	for _, desc := range descs {
+		if len(desc.NestedType) != 0 {
+			desc.nested = make([]*Descriptor, len(desc.NestedType))
+			n := 0
+			for _, nest := range descs {
+				if nest.parent == desc {
+					desc.nested[n] = nest
+					n++
+				}
+			}
+			if n != len(desc.NestedType) {
+				g.fail("internal error: nesting failure for", proto.GetString(desc.Name))
+			}
+		}
+	}
+}
+
+// Construct the Descriptor and add it to the slice
+func AddDescriptor(sl []*Descriptor, desc *descriptor.DescriptorProto, parent *Descriptor, file *descriptor.FileDescriptorProto) []*Descriptor {
+	if len(sl) == cap(sl) {
+		nsl := make([]*Descriptor, len(sl), 2*len(sl))
+		copy(nsl, sl)
+		sl = nsl
+	}
+	sl = sl[0 : len(sl)+1]
+	sl[len(sl)-1] = &Descriptor{common{file: file}, desc, parent, nil, nil}
+	return sl
+}
+
+// Return a slice of all the Descriptors defined within this file
+func WrapDescriptors(file *descriptor.FileDescriptorProto) []*Descriptor {
+	sl := make([]*Descriptor, 0, len(file.MessageType)+10)
+	for _, desc := range file.MessageType {
+		sl = WrapThisDescriptor(sl, desc, nil, file)
+	}
+	return sl
+}
+
+// Wrap this Descriptor, recursively
+func WrapThisDescriptor(sl []*Descriptor, desc *descriptor.DescriptorProto, parent *Descriptor, file *descriptor.FileDescriptorProto) []*Descriptor {
+	sl = AddDescriptor(sl, desc, parent, file)
+	me := sl[len(sl)-1]
+	for _, nested := range desc.NestedType {
+		sl = WrapThisDescriptor(sl, nested, me, file)
+	}
+	return sl
+}
+
+// Construct the EnumDescriptor and add it to the slice
+func AddEnumDescriptor(sl []*EnumDescriptor, desc *descriptor.EnumDescriptorProto, parent *Descriptor, file *descriptor.FileDescriptorProto) []*EnumDescriptor {
+	if len(sl) == cap(sl) {
+		nsl := make([]*EnumDescriptor, len(sl), 2*len(sl))
+		copy(nsl, sl)
+		sl = nsl
+	}
+	sl = sl[0 : len(sl)+1]
+	sl[len(sl)-1] = &EnumDescriptor{common{file: file}, desc, parent, nil}
+	return sl
+}
+
+// Return a slice of all the EnumDescriptors defined within this file
+func WrapEnumDescriptors(file *descriptor.FileDescriptorProto, descs []*Descriptor) []*EnumDescriptor {
+	sl := make([]*EnumDescriptor, 0, len(file.EnumType)+10)
+	for _, enum := range file.EnumType {
+		sl = AddEnumDescriptor(sl, enum, nil, file)
+	}
+	for _, nested := range descs {
+		sl = WrapEnumDescriptorsInMessage(sl, nested, file)
+	}
+	return sl
+}
+
+// Wrap this EnumDescriptor, recursively
+func WrapEnumDescriptorsInMessage(sl []*EnumDescriptor, desc *Descriptor, file *descriptor.FileDescriptorProto) []*EnumDescriptor {
+	for _, enum := range desc.EnumType {
+		sl = AddEnumDescriptor(sl, enum, desc, file)
+	}
+	for _, nested := range desc.nested {
+		sl = WrapEnumDescriptorsInMessage(sl, nested, file)
+	}
+	return sl
+}
+
+// Build the map from fully qualified type names to objects.  The key for the map
+// comes from the input data, which puts a period at the beginning.
+func (g *Generator) BuildTypeNameMap() {
+	g.typeNameToObject = make(map[string]Object)
+	for _, f := range g.allFiles {
+		dottedPkg := "." + f.originalPackageName() + "."
+		for _, enum := range f.enum {
+			name := dottedPkg + DottedSlice(enum.typeName())
+			g.typeNameToObject[name] = enum
+		}
+		for _, desc := range f.desc {
+			name := dottedPkg + DottedSlice(desc.typeName())
+			g.typeNameToObject[name] = desc
+		}
+	}
+}
+
+// Given a fully-qualified input type name, return the descriptor for the message or enum with that type.
+func (g *Generator) objectNamed(typeName string) Object {
+	f, ok := g.typeNameToObject[typeName]
+	if !ok {
+panicln()
+		g.fail("can't find object with type", typeName)
+	}
+	return f
+}
+
+// Print the arguments, handling indirections because they may be *string, etc.
+func (g *Generator) p(str ...interface{}) {
+	g.WriteString(g.indent)
+	for _, v := range str {
+		switch s := v.(type) {
+		case string:
+			g.WriteString(s)
+		case *string:
+			g.WriteString(*s)
+		case *int32:
+			g.WriteString(fmt.Sprintf("%d", *s))
+		default:
+			g.fail(fmt.Sprintf("unknown type in printer: %T", v))
+		}
+	}
+	g.WriteByte('\n')
+}
+
+// Indent the output one tab stop.
+func (g *Generator) in() { g.indent += "\t" }
+
+// Unindent the output one tab stop.
+func (g *Generator) out() {
+	if len(g.indent) > 0 {
+		g.indent = g.indent[1:]
+	}
+}
+
+// Generate the output for all the files we're generating output for.
+func (g *Generator) GenerateAllFiles() {
+	for i, file := range g.genFiles {
+		g.Reset()
+		g.Generate(file)
+		g.response.File[i] = plugin.NewCodeGeneratorResponse_File()
+		g.response.File[i].Name = proto.String(GoName(*file.Name))
+		g.response.File[i].Content = proto.String(g.String())
+	}
+}
+
+// Return the FileDescriptor for this FileDescriptorProto
+func (g *Generator) FileOf(fd *descriptor.FileDescriptorProto) *FileDescriptor {
+	for _, file := range g.allFiles {
+		if file.FileDescriptorProto == fd {
+			return file
+		}
+	}
+	g.fail("could not find file in table:", proto.GetString(fd.Name))
+	return nil
+}
+
+// Fill the response protocol buffer with the generated output for all the files we're
+// supposed to generate.
+func (g *Generator) Generate(file *FileDescriptor) {
+	g.file = g.FileOf(file.FileDescriptorProto)
+	g.GenerateHeader()
+	g.GenerateImports()
+	for _, enum := range g.file.enum {
+		g.GenerateEnum(enum)
+	}
+	for _, desc := range g.file.desc {
+		g.GenerateMessage(desc)
+	}
+	g.GenerateInitFunction()
+}
+
+// Generate the header, including package definition and imports
+func (g *Generator) GenerateHeader() {
+	g.p("// Code generated by protoc-gen-go from ", Quote(*g.file.Name))
+	g.p("// DO NOT EDIT!")
+	g.p()
+	g.p("package ", g.file.packageName())
+	g.p()
+}
+
+// Generate the header, including package definition and imports
+func (g *Generator) GenerateImports() {
+	if len(g.file.enum) > 0 {
+		g.p(`import "goprotobuf.googlecode.com/hg/proto"`)
+	}
+	for _, s := range g.file.Dependency {
+		// Need to find the descriptor for this file
+		for _, fd := range g.allFiles {
+			if proto.GetString(fd.Name) == s {
+				filename := GoName(s)
+				if strings.HasSuffix(filename, ".go") {
+					filename = filename[0:len(filename)-3]
+				}
+				g.p("import ", fd.packageName(), " ", Quote(filename))
+				break
+			}
+		}
+	}
+	g.p()
+}
+
+// Generate the enum definitions for this EnumDescriptor.
+func (g *Generator) GenerateEnum(enum *EnumDescriptor) {
+	// The full type name
+	typeName := enum.typeName()
+	// The full type name, CamelCased.
+	ccTypeName := CamelCaseSlice(typeName)
+	ccPrefix := enum.prefix()
+	g.p("type ", ccTypeName, " int32")
+	g.p("const (")
+	g.in()
+	for _, e := range enum.Value {
+		g.p(ccPrefix+*e.Name, " = ", e.Number)
+	}
+	g.out()
+	g.p(")")
+	g.p("var ", ccTypeName, "_name = map[int32] string {")
+	g.in()
+	generated := make(map[int32] bool)	// avoid duplicate values
+	for _, e := range enum.Value {
+		duplicate := ""
+		if _, present := generated[*e.Number]; present {
+			duplicate = "// Duplicate value: "
+		}
+		g.p(duplicate, e.Number, ": ", Quote(*e.Name), ",")
+		generated[*e.Number] = true
+	}
+	g.out()
+	g.p("}")
+	g.p("var ", ccTypeName, "_value = map[string] int32 {")
+	g.in()
+	for _, e := range enum.Value {
+		g.p(Quote(*e.Name), ": ", e.Number, ",")
+	}
+	g.out()
+	g.p("}")
+	g.p("func New", ccTypeName, "(x int32) *", ccTypeName, " {")
+	g.in()
+	g.p("e := ", ccTypeName, "(x)")
+	g.p("return &e")
+	g.out()
+	g.p("}")
+	g.p()
+}
+
+// The tag is a string like "PB(varint,2,opt,name=fieldname,def=7)" that
+// identifies details of the field for the protocol buffer marshaling and unmarshaling
+// code.  The fields are:
+//	wire encoding
+//	protocol tag number
+//	opt,req,rep for optional, required, or repeated
+//	name= the original declared name
+//	enum= the name of the enum type if it is an enum-typed field.
+//	def= string representation of the default value, if any.
+// The default value must be in a representation that can be used at run-time
+// to generate the default value. Thus bools become 0 and 1, for instance.
+func (g *Generator) GoTag(field *descriptor.FieldDescriptorProto, wiretype string) string {
+	optrepreq := ""
+	switch {
+	case IsOptional(field):
+		optrepreq = "opt"
+	case IsRequired(field):
+		optrepreq = "req"
+	case IsRepeated(field):
+		optrepreq = "rep"
+	}
+	defaultValue := proto.GetString(field.DefaultValue)
+	if defaultValue != "" {
+		switch *field.Type {
+		case descriptor.FieldDescriptorProto_TYPE_BOOL:
+			if defaultValue == "true" {
+				defaultValue = "1"
+			} else {
+				defaultValue = "0"
+			}
+		case descriptor.FieldDescriptorProto_TYPE_STRING,
+			descriptor.FieldDescriptorProto_TYPE_BYTES:
+			// Protect frogs.
+			defaultValue = Quote(defaultValue)
+			// Don't need the quotes
+			defaultValue = defaultValue[1 : len(defaultValue)-1]
+		case descriptor.FieldDescriptorProto_TYPE_ENUM:
+			// For enums we need to provide the integer constant.
+			obj := g.objectNamed(proto.GetString(field.TypeName))
+			enum, ok := obj.(*EnumDescriptor)
+			if !ok {
+				g.fail("enum type inconsistent for", CamelCaseSlice(obj.typeName()))
+			}
+			defaultValue = enum.integerValueAsString(defaultValue)
+		}
+		defaultValue = ",def=" + defaultValue
+	}
+	enum := ""
+	if *field.Type == descriptor.FieldDescriptorProto_TYPE_ENUM {
+		obj := g.objectNamed(proto.GetString(field.TypeName))
+		enum = ",enum=" + obj.packageName() + "." + CamelCaseSlice(obj.typeName())
+	}
+	name := proto.GetString(field.Name)
+	if name == CamelCase(name) {
+		name = ""
+	} else {
+		name = ",name=" + name
+	}
+	return Quote(fmt.Sprintf("PB(%s,%d,%s%s%s%s)",
+		wiretype,
+		proto.GetInt32(field.Number),
+		optrepreq,
+		name,
+		enum,
+		defaultValue))
+}
+
+func NeedsStar(typ descriptor.FieldDescriptorProto_Type) bool {
+	switch typ {
+	case descriptor.FieldDescriptorProto_TYPE_GROUP:
+		return false
+	case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
+		return false
+	case descriptor.FieldDescriptorProto_TYPE_BYTES:
+		return false
+	}
+	return true
+}
+
+// The type name appropriate for an item. If it's in the current file,
+// drop the package name and underscore the rest.
+// Otherwise it's from another package; use the underscored package name
+// followed by the field name.  The result has an initial capital.
+func (g *Generator) TypeName(obj Object) string {
+	return g.DefaultPackageName(obj) + CamelCaseSlice(obj.typeName())
+}
+
+// Like TypeName, but always includes the package name even if it's our own package.
+func (g *Generator) TypeNameWithPackage(obj Object) string {
+	return obj.packageName() + CamelCaseSlice(obj.typeName())
+}
+
+// Returns a string representing the type name, and the wire type
+func (g *Generator) GoType(message *Descriptor, field *descriptor.FieldDescriptorProto) (typ string, wire string) {
+	// TODO: Options.
+	switch *field.Type {
+	case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
+		typ, wire = "float64", "fixed64"
+	case descriptor.FieldDescriptorProto_TYPE_FLOAT:
+		typ, wire = "float32", "fixed32"
+	case descriptor.FieldDescriptorProto_TYPE_INT64:
+		typ, wire = "int64", "varint"
+	case descriptor.FieldDescriptorProto_TYPE_UINT64:
+		typ, wire = "uint64", "varint"
+	case descriptor.FieldDescriptorProto_TYPE_INT32:
+		typ, wire = "int32", "varint"
+	case descriptor.FieldDescriptorProto_TYPE_UINT32:
+		typ, wire = "uint32", "varint"
+	case descriptor.FieldDescriptorProto_TYPE_FIXED64:
+		typ, wire = "uint64", "fixed64"
+	case descriptor.FieldDescriptorProto_TYPE_FIXED32:
+		typ, wire = "uint32", "fixed32"
+	case descriptor.FieldDescriptorProto_TYPE_BOOL:
+		typ, wire = "bool", "varint"
+	case descriptor.FieldDescriptorProto_TYPE_STRING:
+		typ, wire = "string", "bytes"
+	case descriptor.FieldDescriptorProto_TYPE_GROUP:
+		desc := g.objectNamed(proto.GetString(field.TypeName))
+		typ, wire = "*"+g.TypeName(desc), "group"
+	case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
+		desc := g.objectNamed(proto.GetString(field.TypeName))
+		typ, wire = "*"+g.TypeName(desc), "bytes"
+	case descriptor.FieldDescriptorProto_TYPE_BYTES:
+		typ, wire = "[]byte", "bytes"
+	case descriptor.FieldDescriptorProto_TYPE_ENUM:
+		desc := g.objectNamed(proto.GetString(field.TypeName))
+		typ, wire = g.TypeName(desc), "varint"
+	case descriptor.FieldDescriptorProto_TYPE_SFIXED32:
+		typ, wire = "int32", "fixed32"
+	case descriptor.FieldDescriptorProto_TYPE_SFIXED64:
+		typ, wire = "int64", "fixed64"
+	case descriptor.FieldDescriptorProto_TYPE_SINT32:
+		typ, wire = "int32", "zigzag32"
+	case descriptor.FieldDescriptorProto_TYPE_SINT64:
+		typ, wire = "int64", "zigzag64"
+	default:
+		g.fail("unknown type for", proto.GetString(field.Name))
+	}
+	if IsRepeated(field) {
+		typ = "[]" + typ
+	} else if NeedsStar(*field.Type) {
+		typ = "*" + typ
+	}
+	return
+}
+
+// Generate the type and default constant definitions for this Descriptor.
+func (g *Generator) GenerateMessage(message *Descriptor) {
+	// The full type name
+	typeName := message.typeName()
+	// The full type name, CamelCased.
+	ccTypeName := CamelCaseSlice(typeName)
+
+	g.p("type ", ccTypeName, " struct {")
+	g.in()
+	for _, field := range message.Field {
+		fieldname := CamelCase(*field.Name)
+		typename, wiretype := g.GoType(message, field)
+		tag := g.GoTag(field, wiretype)
+		g.p(fieldname, "\t", typename, "\t", tag)
+	}
+	g.p("XXX_unrecognized\t[]byte")
+	g.out()
+	g.p("}")
+
+	// Reset and New functions
+	g.p("func (this *", ccTypeName, ") Reset() {")
+	g.in()
+	g.p("*this = ", ccTypeName, "{}")
+	g.out()
+	g.p("}")
+	g.p("func New", ccTypeName, "() *", ccTypeName, " {")
+	g.in()
+	g.p("return new(", ccTypeName, ")")
+	g.out()
+	g.p("}")
+
+	// Default constants
+	for _, field := range message.Field {
+		def := proto.GetString(field.DefaultValue)
+		if def == "" {
+			continue
+		}
+		fieldname := "Default_" + ccTypeName + "_" + CamelCase(*field.Name)
+		typename, _ := g.GoType(message, field)
+		if typename[0] == '*' {
+			typename = typename[1:]
+		}
+		kind := "const "
+		switch {
+		case typename == "bool":
+		case typename == "string":
+			def = Quote(def)
+		case typename == "[]byte":
+			def = "[]byte(" + Quote(def) + ")"
+			kind = "var "
+		case 	*field.Type == descriptor.FieldDescriptorProto_TYPE_ENUM:
+			// Must be an enum.  Need to construct the prefixed name.
+			obj := g.objectNamed(proto.GetString(field.TypeName))
+			enum, ok := obj.(*EnumDescriptor)
+			if !ok {
+				log.Stderr("don't know how to generate constant for", fieldname)
+				continue
+			}
+			def = enum.prefix() + def
+		}
+		g.p(kind, fieldname, " ", typename, " = ", def)
+	}
+	g.p()
+}
+
+func (g *Generator) GenerateInitFunction() {
+	g.p("func init() {")
+	g.in()
+	for _, enum := range g.file.enum {
+		g.GenerateEnumRegistration(enum)
+	}
+	g.out()
+	g.p("}")
+}
+
+func (g *Generator) GenerateEnumRegistration(enum *EnumDescriptor) {
+	pkg := g.packageName + "." // We always print the full package name here.
+	// The full type name
+	typeName := enum.typeName()
+	// The full type name, CamelCased.
+	ccTypeName := CamelCaseSlice(typeName)
+	g.p("proto.RegisterEnum(", Quote(pkg+ccTypeName), ", ", ccTypeName+"_name, ", ccTypeName+"_value)")
+}
+
+// And now lots of helper functions.
+
+// Return change foo_bar_Baz to FooBar_Baz.
+func CamelCase(name string) string {
+	elems := strings.Split(name, "_", 0)
+	for i, e := range elems {
+		if e == "" {
+			elems[i] = "_"
+			continue
+		}
+		runes := []int(e)
+		if unicode.IsLower(runes[0]) {
+			runes[0] = unicode.ToUpper(runes[0])
+			elems[i] = string(runes)
+		} else {
+			if i > 0 {
+				elems[i] = "_" + e
+			}
+		}
+	}
+	s := strings.Join(elems, "")
+	// Name must not begin with an underscore.
+	if len(s) > 0 && s[0] == '_' {
+		s = "X" + s[1:]
+	}
+	return s
+}
+
+// Like CamelCase, but the argument is a slice of strings to
+// be concatenated with "_"
+func CamelCaseSlice(elem []string) string { return CamelCase(strings.Join(elem, "_")) }
+
+// Turn a sliced name into a dotted name
+func DottedSlice(elem []string) string { return strings.Join(elem, ".") }
+
+// Return a Go-source quoted string representation of s.
+func Quote(s string) string { return fmt.Sprintf("%q", s) }
+
+// Given a .proto file name, return the output name for the generated Go program.
+func GoName(name string) string {
+	if strings.HasSuffix(name, ".proto") {
+		name = name[0 : len(name)-6]
+	}
+	return name + ".pb.go"
+}
+
+// Is this field optional?
+func IsOptional(field *descriptor.FieldDescriptorProto) bool {
+	return field.Label != nil && *field.Label == descriptor.FieldDescriptorProto_LABEL_OPTIONAL
+}
+
+// Is this field required?
+func IsRequired(field *descriptor.FieldDescriptorProto) bool {
+	return field.Label != nil && *field.Label == descriptor.FieldDescriptorProto_LABEL_REQUIRED
+}
+
+// Is this field repeated?
+func IsRepeated(field *descriptor.FieldDescriptorProto) bool {
+	return field.Label != nil && *field.Label == descriptor.FieldDescriptorProto_LABEL_REPEATED
+}
+
+// Mapping function used to generate Go names from package names, which can be dotted.
+func DotToUnderscore(rune int) int {
+	if rune == '.' {
+		return '_'
+	}
+	return rune
+}
diff --git a/compiler/plugin/Makefile b/compiler/plugin/Makefile
new file mode 100644
index 0000000..08be77f
--- /dev/null
+++ b/compiler/plugin/Makefile
@@ -0,0 +1,54 @@
+# Go support for Protocol Buffers - Google's data interchange format
+#
+# Copyright 2010 Google Inc.  All rights reserved.
+# http://code.google.com/p/goprotobuf/
+#
+# 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.
+
+include $(GOROOT)/src/Make.$(GOARCH)
+
+TARG=goprotobuf.googlecode.com/hg/compiler/plugin
+GOFILES=\
+	plugin.pb.go\
+
+include $(GOROOT)/src/Make.pkg
+
+# Not stored here, but plugin.proto is in http://code.google.com/p/protobuf
+# at protobuf-2.3.0/src/google/protobuf/compiler/plugin.proto
+# Also we need to fix an import.
+regenerate:
+	echo WARNING! THIS RULE IS PROBABLY NOT RIGHT FOR YOUR INSTALLATION
+	cd $(HOME)/protobuf-2.3.0/src && \
+	protoc --go_out=. ./google/protobuf/compiler/plugin.proto && \
+	cat ./google/protobuf/compiler/plugin.pb.go | \
+		sed '/^import/s;google/protobuf/descriptor.pb;goprotobuf.googlecode.com/hg/compiler/descriptor;' >$(GOROOT)/src/pkg/goprotobuf.googlecode.com/hg/compiler/plugin/plugin.pb.go
+
+restore:
+	cp plugin.pb.golden plugin.pb.go
+
+preserve:
+	cp plugin.pb.go plugin.pb.golden
diff --git a/compiler/plugin/plugin.pb.go b/compiler/plugin/plugin.pb.go
new file mode 100644
index 0000000..1c11686
--- /dev/null
+++ b/compiler/plugin/plugin.pb.go
@@ -0,0 +1,47 @@
+// Code generated by protoc-gen-go from "google/protobuf/compiler/plugin.proto"
+// DO NOT EDIT!
+
+package google_protobuf_compiler
+
+import google_protobuf "goprotobuf.googlecode.com/hg/compiler/descriptor"
+
+type CodeGeneratorRequest struct {
+	FileToGenerate	[]string	"PB(bytes,1,rep,name=file_to_generate)"
+	Parameter	*string	"PB(bytes,2,opt,name=parameter)"
+	ProtoFile	[]*google_protobuf.FileDescriptorProto	"PB(bytes,15,rep,name=proto_file)"
+	XXX_unrecognized	[]byte
+}
+func (this *CodeGeneratorRequest) Reset() {
+	*this = CodeGeneratorRequest{}
+}
+func NewCodeGeneratorRequest() *CodeGeneratorRequest {
+	return new(CodeGeneratorRequest)
+}
+
+type CodeGeneratorResponse struct {
+	Error	*string	"PB(bytes,1,opt,name=error)"
+	File	[]*CodeGeneratorResponse_File	"PB(bytes,15,rep,name=file)"
+	XXX_unrecognized	[]byte
+}
+func (this *CodeGeneratorResponse) Reset() {
+	*this = CodeGeneratorResponse{}
+}
+func NewCodeGeneratorResponse() *CodeGeneratorResponse {
+	return new(CodeGeneratorResponse)
+}
+
+type CodeGeneratorResponse_File struct {
+	Name	*string	"PB(bytes,1,opt,name=name)"
+	InsertionPoint	*string	"PB(bytes,2,opt,name=insertion_point)"
+	Content	*string	"PB(bytes,15,opt,name=content)"
+	XXX_unrecognized	[]byte
+}
+func (this *CodeGeneratorResponse_File) Reset() {
+	*this = CodeGeneratorResponse_File{}
+}
+func NewCodeGeneratorResponse_File() *CodeGeneratorResponse_File {
+	return new(CodeGeneratorResponse_File)
+}
+
+func init() {
+}
diff --git a/compiler/plugin/plugin.pb.golden b/compiler/plugin/plugin.pb.golden
new file mode 100644
index 0000000..1c11686
--- /dev/null
+++ b/compiler/plugin/plugin.pb.golden
@@ -0,0 +1,47 @@
+// Code generated by protoc-gen-go from "google/protobuf/compiler/plugin.proto"
+// DO NOT EDIT!
+
+package google_protobuf_compiler
+
+import google_protobuf "goprotobuf.googlecode.com/hg/compiler/descriptor"
+
+type CodeGeneratorRequest struct {
+	FileToGenerate	[]string	"PB(bytes,1,rep,name=file_to_generate)"
+	Parameter	*string	"PB(bytes,2,opt,name=parameter)"
+	ProtoFile	[]*google_protobuf.FileDescriptorProto	"PB(bytes,15,rep,name=proto_file)"
+	XXX_unrecognized	[]byte
+}
+func (this *CodeGeneratorRequest) Reset() {
+	*this = CodeGeneratorRequest{}
+}
+func NewCodeGeneratorRequest() *CodeGeneratorRequest {
+	return new(CodeGeneratorRequest)
+}
+
+type CodeGeneratorResponse struct {
+	Error	*string	"PB(bytes,1,opt,name=error)"
+	File	[]*CodeGeneratorResponse_File	"PB(bytes,15,rep,name=file)"
+	XXX_unrecognized	[]byte
+}
+func (this *CodeGeneratorResponse) Reset() {
+	*this = CodeGeneratorResponse{}
+}
+func NewCodeGeneratorResponse() *CodeGeneratorResponse {
+	return new(CodeGeneratorResponse)
+}
+
+type CodeGeneratorResponse_File struct {
+	Name	*string	"PB(bytes,1,opt,name=name)"
+	InsertionPoint	*string	"PB(bytes,2,opt,name=insertion_point)"
+	Content	*string	"PB(bytes,15,opt,name=content)"
+	XXX_unrecognized	[]byte
+}
+func (this *CodeGeneratorResponse_File) Reset() {
+	*this = CodeGeneratorResponse_File{}
+}
+func NewCodeGeneratorResponse_File() *CodeGeneratorResponse_File {
+	return new(CodeGeneratorResponse_File)
+}
+
+func init() {
+}
diff --git a/compiler/testdata/Makefile b/compiler/testdata/Makefile
new file mode 100644
index 0000000..0cc9ad1
--- /dev/null
+++ b/compiler/testdata/Makefile
@@ -0,0 +1,63 @@
+# Go support for Protocol Buffers - Google's data interchange format
+#
+# Copyright 2010 Google Inc.  All rights reserved.
+# http://code.google.com/p/goprotobuf/
+#
+# 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.
+
+include $(GOROOT)/src/Make.$(GOARCH)
+
+all:
+	@echo run make test
+
+include $(GOROOT)/src/Make.common
+include $(GOROOT)/src/pkg/goprotobuf.googlecode.com/hg/Make.protobuf
+
+CLEANFILES+=*.pb.go
+
+test:	golden testbuild
+	@echo PASS
+
+golden:
+	$(QUOTED_GOBIN)/gomake -B test.pb.go
+	diff test.pb.go test.pb.go.golden
+
+nuke:	clean
+
+testbuild:	main.$O
+	$(LD) -L. main.$O
+
+multi.a: multi3.pb.$O multi2.pb.$O multi1.pb.$O
+	rm -f multi.a
+	$(QUOTED_GOBIN)/gopack grc $@ $<
+
+%.$O:	%.go
+	$(QUOTED_GOBIN)/$(GC) -I . -o $@ $<
+
+test.pb.go:	imp.pb.go
+multi1.pb.go:	multi2.pb.go multi3.pb.go
+main.$O: imp.pb.$O test.pb.$O multi.a
diff --git a/compiler/testdata/imp.proto b/compiler/testdata/imp.proto
new file mode 100644
index 0000000..beb6805
--- /dev/null
+++ b/compiler/testdata/imp.proto
@@ -0,0 +1,41 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2010 Google Inc.  All rights reserved.
+// http://code.google.com/p/goprotobuf/
+//
+// 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.
+
+package imp;
+
+message ImportedMessage {
+  required int64 field = 1;
+
+  enum Owner {
+    DAVE = 1;
+    MIKE = 2;
+  }
+}
diff --git a/compiler/testdata/main.go b/compiler/testdata/main.go
new file mode 100644
index 0000000..29100be
--- /dev/null
+++ b/compiler/testdata/main.go
@@ -0,0 +1,44 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2010 Google Inc.  All rights reserved.
+// http://code.google.com/p/goprotobuf/
+//
+// 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.
+
+// A simple binary to link together the protocol buffers in this test.
+
+package main
+
+import (
+	"./test.pb"
+	"./multi1.pb"
+)
+
+func main() {
+	_ = my_test.NewRequest()
+	_ = multitest.NewMulti1()
+}
diff --git a/compiler/testdata/multi1.proto b/compiler/testdata/multi1.proto
new file mode 100644
index 0000000..47a4d2f
--- /dev/null
+++ b/compiler/testdata/multi1.proto
@@ -0,0 +1,42 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2010 Google Inc.  All rights reserved.
+// http://code.google.com/p/goprotobuf/
+//
+// 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.
+
+import "multi2.proto";
+import "multi3.proto";
+
+package multitest;
+
+message Multi1 {
+  required Multi2 multi2 = 1;
+  optional Multi2.Color color = 2;
+  optional Multi3.HatType hat_type = 3;
+}
+
diff --git a/compiler/testdata/multi2.proto b/compiler/testdata/multi2.proto
new file mode 100644
index 0000000..6bb76f9
--- /dev/null
+++ b/compiler/testdata/multi2.proto
@@ -0,0 +1,44 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2010 Google Inc.  All rights reserved.
+// http://code.google.com/p/goprotobuf/
+//
+// 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.
+
+package multitest;
+
+message Multi2 {
+  required int32 required_value = 1;
+
+  enum Color {
+    BLUE = 1;
+    GREEN = 2;
+    RED = 3;
+  };
+  optional Color color = 2;
+}
+
diff --git a/compiler/testdata/multi3.proto b/compiler/testdata/multi3.proto
new file mode 100644
index 0000000..191fefd
--- /dev/null
+++ b/compiler/testdata/multi3.proto
@@ -0,0 +1,41 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2010 Google Inc.  All rights reserved.
+// http://code.google.com/p/goprotobuf/
+//
+// 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.
+
+package multitest;
+
+message Multi3 {
+  enum HatType {
+    FEDORA = 1;
+    FEZ = 2;
+  };
+  optional HatType hat_type = 1;
+}
+
diff --git a/compiler/testdata/test.pb.go.golden b/compiler/testdata/test.pb.go.golden
new file mode 100644
index 0000000..0d7a7cb
--- /dev/null
+++ b/compiler/testdata/test.pb.go.golden
@@ -0,0 +1,124 @@
+// Code generated by protoc-gen-go from "test.proto"
+// DO NOT EDIT!
+
+package my_test
+
+import "goprotobuf.googlecode.com/hg/proto"
+import imp "imp.pb"
+
+type HatType int32
+const (
+	HatType_FEDORA = 1
+	HatType_FEZ = 2
+)
+var HatType_name = map[int32] string {
+	1: "FEDORA",
+	2: "FEZ",
+}
+var HatType_value = map[string] int32 {
+	"FEDORA": 1,
+	"FEZ": 2,
+}
+func NewHatType(x int32) *HatType {
+	e := HatType(x)
+	return &e
+}
+
+type Days int32
+const (
+	Days_MONDAY = 1
+	Days_TUESDAY = 2
+	Days_LUNDI = 1
+)
+var Days_name = map[int32] string {
+	1: "MONDAY",
+	2: "TUESDAY",
+	// Duplicate value: 1: "LUNDI",
+}
+var Days_value = map[string] int32 {
+	"MONDAY": 1,
+	"TUESDAY": 2,
+	"LUNDI": 1,
+}
+func NewDays(x int32) *Days {
+	e := Days(x)
+	return &e
+}
+
+type Request_Color int32
+const (
+	Request_RED = 0
+	Request_GREEN = 1
+	Request_BLUE = 2
+)
+var Request_Color_name = map[int32] string {
+	0: "RED",
+	1: "GREEN",
+	2: "BLUE",
+}
+var Request_Color_value = map[string] int32 {
+	"RED": 0,
+	"GREEN": 1,
+	"BLUE": 2,
+}
+func NewRequest_Color(x int32) *Request_Color {
+	e := Request_Color(x)
+	return &e
+}
+
+type Request struct {
+	Key	[]int64	"PB(varint,1,rep,name=key)"
+	ImportedMessage	*imp.ImportedMessage	"PB(bytes,2,opt,name=imported_message)"
+	Hue	*Request_Color	"PB(varint,3,opt,name=hue,enum=my_test.Request_Color)"
+	Hat	*HatType	"PB(varint,4,opt,name=hat,enum=my_test.HatType,def=1)"
+	Owner	*imp.ImportedMessage_Owner	"PB(varint,6,opt,name=owner,enum=imp.ImportedMessage_Owner)"
+	XXX_unrecognized	[]byte
+}
+func (this *Request) Reset() {
+	*this = Request{}
+}
+func NewRequest() *Request {
+	return new(Request)
+}
+const Default_Request_Hat HatType = HatType_FEDORA
+
+type Reply struct {
+	Found	[]*Reply_Entry	"PB(bytes,1,rep,name=found)"
+	XXX_unrecognized	[]byte
+}
+func (this *Reply) Reset() {
+	*this = Reply{}
+}
+func NewReply() *Reply {
+	return new(Reply)
+}
+
+type Reply_Entry struct {
+	KeyThatNeeds_1234camel_CasIng	*int64	"PB(varint,1,req,name=key_that_needs_1234camel_CasIng)"
+	Value	*int64	"PB(varint,2,opt,name=value,def=7)"
+	XMyFieldName_2	*int64	"PB(varint,3,opt,name=_my_field_name_2)"
+	XXX_unrecognized	[]byte
+}
+func (this *Reply_Entry) Reset() {
+	*this = Reply_Entry{}
+}
+func NewReply_Entry() *Reply_Entry {
+	return new(Reply_Entry)
+}
+const Default_Reply_Entry_Value int64 = 7
+
+type ReplyExtensions struct {
+	XXX_unrecognized	[]byte
+}
+func (this *ReplyExtensions) Reset() {
+	*this = ReplyExtensions{}
+}
+func NewReplyExtensions() *ReplyExtensions {
+	return new(ReplyExtensions)
+}
+
+func init() {
+	proto.RegisterEnum("my_test.HatType", HatType_name, HatType_value)
+	proto.RegisterEnum("my_test.Days", Days_name, Days_value)
+	proto.RegisterEnum("my_test.Request_Color", Request_Color_name, Request_Color_value)
+}
diff --git a/compiler/testdata/test.proto b/compiler/testdata/test.proto
new file mode 100644
index 0000000..f7e7a3d
--- /dev/null
+++ b/compiler/testdata/test.proto
@@ -0,0 +1,75 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2010 Google Inc.  All rights reserved.
+// http://code.google.com/p/goprotobuf/
+//
+// 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.
+
+package my.test;  // dotted package name
+
+import "imp.proto";
+
+enum HatType {
+  // deliberately skipping 0
+  FEDORA = 1;
+  FEZ = 2;
+}
+
+enum Days {
+  MONDAY = 1;
+  TUESDAY = 2;
+  LUNDI = 1;  // same value as MONDAY
+}
+
+message Request {
+  enum Color {
+    RED = 0;
+    GREEN = 1;
+    BLUE = 2;
+  }
+  repeated int64 key = 1;
+  optional imp.ImportedMessage imported_message = 2;
+  optional Color hue = 3;
+  optional HatType hat = 4 [default=FEDORA];
+  optional imp.ImportedMessage.Owner owner = 6;
+}
+
+message Reply {
+  message Entry {
+    required int64 key_that_needs_1234camel_CasIng = 1;
+    optional int64 value = 2 [default=7];
+    optional int64 _my_field_name_2 = 3;
+  }
+  repeated Entry found = 1;
+  extensions 100 to max;
+}
+
+message ReplyExtensions {
+  extend Reply {
+    optional double time = 101;
+  }
+}