Fix decoding of merge tags.

This addresses a number of related issues on how merge tags
were handled, most notably the case of nested mappings being
merged instead of the outermost value being used as-is.

Closes: #818 #826
diff --git a/decode.go b/decode.go
index df36e3a..c59dea4 100644
--- a/decode.go
+++ b/decode.go
@@ -320,6 +320,8 @@
 	decodeCount int
 	aliasCount  int
 	aliasDepth  int
+
+	mergedFields map[interface{}]bool
 }
 
 var (
@@ -808,6 +810,11 @@
 		}
 	}
 
+	mergedFields := d.mergedFields
+	d.mergedFields = nil
+
+	var mergeNode *Node
+
 	mapIsNew := false
 	if out.IsNil() {
 		out.Set(reflect.MakeMap(outt))
@@ -815,11 +822,18 @@
 	}
 	for i := 0; i < l; i += 2 {
 		if isMerge(n.Content[i]) {
-			d.merge(n.Content[i+1], out)
+			mergeNode = n.Content[i+1]
 			continue
 		}
 		k := reflect.New(kt).Elem()
 		if d.unmarshal(n.Content[i], k) {
+			if mergedFields != nil {
+				ki := k.Interface()
+				if mergedFields[ki] {
+					continue
+				}
+				mergedFields[ki] = true
+			}
 			kkind := k.Kind()
 			if kkind == reflect.Interface {
 				kkind = k.Elem().Kind()
@@ -833,6 +847,12 @@
 			}
 		}
 	}
+
+	d.mergedFields = mergedFields
+	if mergeNode != nil {
+		d.merge(n, mergeNode, out)
+	}
+
 	d.stringMapType = stringMapType
 	d.generalMapType = generalMapType
 	return true
@@ -844,7 +864,8 @@
 	}
 	l := len(n.Content)
 	for i := 0; i < l; i += 2 {
-		if n.Content[i].ShortTag() != strTag {
+		shortTag := n.Content[i].ShortTag()
+		if shortTag != strTag && shortTag != mergeTag {
 			return false
 		}
 	}
@@ -861,7 +882,6 @@
 	var elemType reflect.Type
 	if sinfo.InlineMap != -1 {
 		inlineMap = out.Field(sinfo.InlineMap)
-		inlineMap.Set(reflect.New(inlineMap.Type()).Elem())
 		elemType = inlineMap.Type().Elem()
 	}
 
@@ -870,6 +890,9 @@
 		d.prepare(n, field)
 	}
 
+	mergedFields := d.mergedFields
+	d.mergedFields = nil
+	var mergeNode *Node
 	var doneFields []bool
 	if d.uniqueKeys {
 		doneFields = make([]bool, len(sinfo.FieldsList))
@@ -879,13 +902,20 @@
 	for i := 0; i < l; i += 2 {
 		ni := n.Content[i]
 		if isMerge(ni) {
-			d.merge(n.Content[i+1], out)
+			mergeNode = n.Content[i+1]
 			continue
 		}
 		if !d.unmarshal(ni, name) {
 			continue
 		}
-		if info, ok := sinfo.FieldsMap[name.String()]; ok {
+		sname := name.String()
+		if mergedFields != nil {
+			if mergedFields[sname] {
+				continue
+			}
+			mergedFields[sname] = true
+		}
+		if info, ok := sinfo.FieldsMap[sname]; ok {
 			if d.uniqueKeys {
 				if doneFields[info.Id] {
 					d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s already set in type %s", ni.Line, name.String(), out.Type()))
@@ -911,6 +941,11 @@
 			d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s not found in type %s", ni.Line, name.String(), out.Type()))
 		}
 	}
+
+	d.mergedFields = mergedFields
+	if mergeNode != nil {
+		d.merge(n, mergeNode, out)
+	}
 	return true
 }
 
@@ -918,19 +953,29 @@
 	failf("map merge requires map or sequence of maps as the value")
 }
 
-func (d *decoder) merge(n *Node, out reflect.Value) {
-	switch n.Kind {
+func (d *decoder) merge(parent *Node, merge *Node, out reflect.Value) {
+	mergedFields := d.mergedFields
+	if mergedFields == nil {
+		d.mergedFields = make(map[interface{}]bool)
+		for i := 0; i < len(parent.Content); i += 2 {
+			k := reflect.New(ifaceType).Elem()
+			if d.unmarshal(parent.Content[i], k) {
+				d.mergedFields[k.Interface()] = true
+			}
+		}
+	}
+
+	switch merge.Kind {
 	case MappingNode:
-		d.unmarshal(n, out)
+		d.unmarshal(merge, out)
 	case AliasNode:
-		if n.Alias != nil && n.Alias.Kind != MappingNode {
+		if merge.Alias != nil && merge.Alias.Kind != MappingNode {
 			failWantMap()
 		}
-		d.unmarshal(n, out)
+		d.unmarshal(merge, out)
 	case SequenceNode:
-		// Step backwards as earlier nodes take precedence.
-		for i := len(n.Content) - 1; i >= 0; i-- {
-			ni := n.Content[i]
+		for i := 0; i < len(merge.Content); i++ {
+			ni := merge.Content[i]
 			if ni.Kind == AliasNode {
 				if ni.Alias != nil && ni.Alias.Kind != MappingNode {
 					failWantMap()
@@ -943,6 +988,8 @@
 	default:
 		failWantMap()
 	}
+
+	d.mergedFields = mergedFields
 }
 
 func isMerge(n *Node) bool {
diff --git a/decode_test.go b/decode_test.go
index 5ade550..5f65e43 100644
--- a/decode_test.go
+++ b/decode_test.go
@@ -767,7 +767,7 @@
 		M{"a": 123456e1},
 	}, {
 		"a: 123456E1\n",
-		M{"a": 123456E1},
+		M{"a": 123456e1},
 	},
 	// yaml-test-suite 3GZX: Spec Example 7.1. Alias Nodes
 	{
@@ -802,7 +802,6 @@
 			"c": []interface{}{"d", "e"},
 		},
 	},
-
 }
 
 type M map[string]interface{}
@@ -950,14 +949,14 @@
 	{"a: 1\nb: 2\nc 2\nd: 3\n", "^yaml: line 3: could not find expected ':'$"},
 	{
 		"a: &a [00,00,00,00,00,00,00,00,00]\n" +
-		"b: &b [*a,*a,*a,*a,*a,*a,*a,*a,*a]\n" +
-		"c: &c [*b,*b,*b,*b,*b,*b,*b,*b,*b]\n" +
-		"d: &d [*c,*c,*c,*c,*c,*c,*c,*c,*c]\n" +
-		"e: &e [*d,*d,*d,*d,*d,*d,*d,*d,*d]\n" +
-		"f: &f [*e,*e,*e,*e,*e,*e,*e,*e,*e]\n" +
-		"g: &g [*f,*f,*f,*f,*f,*f,*f,*f,*f]\n" +
-		"h: &h [*g,*g,*g,*g,*g,*g,*g,*g,*g]\n" +
-		"i: &i [*h,*h,*h,*h,*h,*h,*h,*h,*h]\n",
+			"b: &b [*a,*a,*a,*a,*a,*a,*a,*a,*a]\n" +
+			"c: &c [*b,*b,*b,*b,*b,*b,*b,*b,*b]\n" +
+			"d: &d [*c,*c,*c,*c,*c,*c,*c,*c,*c]\n" +
+			"e: &e [*d,*d,*d,*d,*d,*d,*d,*d,*d]\n" +
+			"f: &f [*e,*e,*e,*e,*e,*e,*e,*e,*e]\n" +
+			"g: &g [*f,*f,*f,*f,*f,*f,*f,*f,*f]\n" +
+			"h: &h [*g,*g,*g,*g,*g,*g,*g,*g,*g]\n" +
+			"i: &i [*h,*h,*h,*h,*h,*h,*h,*h,*h]\n",
 		"yaml: document contains excessive aliasing",
 	},
 }
@@ -1391,7 +1390,7 @@
 `
 
 func (s *S) TestMerge(c *C) {
-	var want = map[interface{}]interface{}{
+	var want = map[string]interface{}{
 		"x":     1,
 		"y":     2,
 		"r":     10,
@@ -1436,7 +1435,103 @@
 	}
 }
 
-var unmarshalNullTests = []struct{ input string; pristine, expected func() interface{} }{{
+var mergeTestsNested = `
+mergeouter1: &mergeouter1
+    d: 40
+    e: 50
+
+mergeouter2: &mergeouter2
+    e: 5
+    f: 6
+    g: 70
+
+mergeinner1: &mergeinner1
+    <<: *mergeouter1
+    inner:
+        a: 1
+        b: 2
+
+mergeinner2: &mergeinner2
+    <<: *mergeouter2
+    inner:
+        a: -1
+        b: -2
+
+outer:
+    <<: [*mergeinner1, *mergeinner2]
+    f: 60
+    inner:
+        a: 10
+`
+
+func (s *S) TestMergeNestedStruct(c *C) {
+	// Issue #818: Merging used to just unmarshal twice on the target
+	// value, which worked for maps as these were replaced by the new map,
+	// but not on struct values as these are preserved. This resulted in
+	// the nested data from the merged map to be mixed up with the data
+	// from the map being merged into.
+	//
+	// This test also prevents two potential bugs from showing up:
+	//
+	// 1) A simple implementation might just zero out the nested value
+	//    before unmarshaling the second time, but this would clobber previous
+	//    data that is usually respected ({C: 30} below).
+	//
+	// 2) A simple implementation might attempt to handle the key skipping
+	//    directly by iterating over the merging map without recursion, but
+	//    there are more complex cases that require recursion.
+	// 
+	// Quick summary of the fields:
+	//
+	// - A must come from outer and not overriden
+	// - B must not be set as its in the ignored merge
+	// - C should still be set as it's preset in the value
+	// - D should be set from the recursive merge
+	// - E should be set from the first recursive merge, ignored on the second
+	// - F should be set in the inlined map from outer, ignored later
+	// - G should be set in the inlined map from the second recursive merge
+	//
+
+	type Inner struct {
+		A, B, C int
+	}
+	type Outer struct {
+		D, E      int
+		Inner  Inner
+		Inline map[string]int `yaml:",inline"`
+	}
+	type Data struct {
+		Outer Outer
+	}
+
+	test := Data{Outer{0, 0, Inner{C: 30}, nil}}
+	want := Data{Outer{40, 50, Inner{A: 10, C: 30}, map[string]int{"f": 60, "g": 70}}}
+
+	err := yaml.Unmarshal([]byte(mergeTestsNested), &test)
+	c.Assert(err, IsNil)
+	c.Assert(test, DeepEquals, want)
+
+	// Repeat test with a map.
+
+	var testm map[string]interface{}
+	var wantm = map[string]interface {} {
+		"f":     60,
+		"inner": map[string]interface{}{
+		    "a": 10,
+		},
+		"d": 40,
+		"e": 50,
+		"g": 70,
+	}
+	err = yaml.Unmarshal([]byte(mergeTestsNested), &testm)
+	c.Assert(err, IsNil)
+	c.Assert(testm["outer"], DeepEquals, wantm)
+}
+
+var unmarshalNullTests = []struct {
+	input              string
+	pristine, expected func() interface{}
+}{{
 	"null",
 	func() interface{} { var v interface{}; v = "v"; return &v },
 	func() interface{} { var v interface{}; v = nil; return &v },
@@ -1487,7 +1582,7 @@
 func (s *S) TestUnmarshalPreservesData(c *C) {
 	var v struct {
 		A, B int
-		C int `yaml:"-"`
+		C    int `yaml:"-"`
 	}
 	v.A = 42
 	v.C = 88