patch 8.0.0420: text garbled when the system encoding differs from 'encoding'

Problem:    When running :make the output may be in the system encoding,
            different from 'encoding'.
Solution:   Add the 'makeencoding' option. (Ken Takata)
diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak
index 513fd89..e1ce151 100644
--- a/src/testdir/Make_all.mak
+++ b/src/testdir/Make_all.mak
@@ -170,6 +170,7 @@
 	    test_listlbr.res \
 	    test_listlbr_utf8.res \
 	    test_lua.res \
+	    test_makeencoding.res \
 	    test_man.res \
 	    test_marks.res \
 	    test_matchadd_conceal.res \
diff --git a/src/testdir/test_makeencoding.py b/src/testdir/test_makeencoding.py
new file mode 100644
index 0000000..041edad
--- /dev/null
+++ b/src/testdir/test_makeencoding.py
@@ -0,0 +1,67 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Test program for :make, :grep and :cgetfile.
+
+from __future__ import print_function, unicode_literals
+import locale
+import io
+import sys
+
+def set_output_encoding(enc=None):
+    """Set the encoding of stdout and stderr
+
+    arguments:
+      enc -- Encoding name.
+             If omitted, locale.getpreferredencoding() is used.
+    """
+    if enc is None:
+        enc = locale.getpreferredencoding()
+
+    def get_text_writer(fo, **kwargs):
+        kw = dict(kwargs)
+        kw.setdefault('errors', 'backslashreplace') # use \uXXXX style
+        kw.setdefault('closefd', False)
+
+        if sys.version_info[0] < 3:
+            # Work around for Python 2.x
+            # New line conversion isn't needed here. Done in somewhere else.
+            writer = io.open(fo.fileno(), mode='w', newline='', **kw)
+            write = writer.write    # save the original write() function
+            enc = locale.getpreferredencoding()
+            def convwrite(s):
+                if isinstance(s, bytes):
+                    write(s.decode(enc))    # convert to unistr
+                else:
+                    write(s)
+                try:
+                    writer.flush()  # needed on Windows
+                except IOError:
+                    pass
+            writer.write = convwrite
+        else:
+            writer = io.open(fo.fileno(), mode='w', **kw)
+        return writer
+
+    sys.stdout = get_text_writer(sys.stdout, encoding=enc)
+    sys.stderr = get_text_writer(sys.stderr, encoding=enc)
+
+
+def main():
+    enc = 'utf-8'
+    if len(sys.argv) > 1:
+        enc = sys.argv[1]
+    set_output_encoding(enc)
+
+    message_tbl = {
+            'utf-8': 'ÀÈÌÒÙ こんにちは 你好',
+            'latin1': 'ÀÈÌÒÙ',
+            'cp932': 'こんにちは',
+            'cp936': '你好',
+            }
+
+    print('Xfoobar.c(10) : %s (%s)' % (message_tbl[enc], enc))
+
+
+if __name__ == "__main__":
+    main()
diff --git a/src/testdir/test_makeencoding.vim b/src/testdir/test_makeencoding.vim
new file mode 100644
index 0000000..a3d5538
--- /dev/null
+++ b/src/testdir/test_makeencoding.vim
@@ -0,0 +1,106 @@
+" Tests for 'makeencoding'.
+if !has('multi_byte')
+  finish
+endif
+
+source shared.vim
+
+let s:python = PythonProg()
+if s:python == ''
+  " Can't run this test.
+  finish
+endif
+
+let s:script = 'test_makeencoding.py'
+
+let s:message_tbl = {
+      \ 'utf-8': 'ÀÈÌÒÙ こんにちは 你好',
+      \ 'latin1': 'ÀÈÌÒÙ',
+      \ 'cp932': 'こんにちは',
+      \ 'cp936': '你好',
+      \}
+
+
+" Tests for :cgetfile and :lgetfile.
+func Test_getfile()
+  set errorfile=Xerror.txt
+  set errorformat=%f(%l)\ :\ %m
+
+  " :cgetfile
+  for enc in keys(s:message_tbl)
+    let &makeencoding = enc
+    exec "silent !" . s:python . " " . s:script . " " . enc . " > " . &errorfile
+    cgetfile
+    copen
+    call assert_equal("Xfoobar.c|10| " . s:message_tbl[enc] . " (" . enc . ")",
+          \ getline('.'))
+    cclose
+  endfor
+
+  " :lgetfile
+  for enc in keys(s:message_tbl)
+    let &makeencoding = enc
+    exec "silent !" . s:python . " " . s:script . " " . enc . " > " . &errorfile
+    lgetfile
+    lopen
+    call assert_equal("Xfoobar.c|10| " . s:message_tbl[enc] . " (" . enc . ")",
+          \ getline('.'))
+    lclose
+  endfor
+
+  call delete(&errorfile)
+endfunc
+
+
+" Tests for :grep and :lgrep.
+func Test_grep()
+  let &grepprg = s:python
+  set grepformat=%f(%l)\ :\ %m
+
+  " :grep
+  for enc in keys(s:message_tbl)
+    let &makeencoding = enc
+    exec "silent grep! " . s:script . " " . enc
+    copen
+    call assert_equal("Xfoobar.c|10| " . s:message_tbl[enc] . " (" . enc . ")",
+          \ getline('.'))
+    cclose
+  endfor
+
+  " :lgrep
+  for enc in keys(s:message_tbl)
+    let &makeencoding = enc
+    exec "silent lgrep! " . s:script . " " . enc
+    lopen
+    call assert_equal("Xfoobar.c|10| " . s:message_tbl[enc] . " (" . enc . ")",
+          \ getline('.'))
+    lclose
+  endfor
+endfunc
+
+
+" Tests for :make and :lmake.
+func Test_make()
+  let &makeprg = s:python
+  set errorformat=%f(%l)\ :\ %m
+
+  " :make
+  for enc in keys(s:message_tbl)
+    let &makeencoding = enc
+    exec "silent make! " . s:script . " " . enc
+    copen
+    call assert_equal("Xfoobar.c|10| " . s:message_tbl[enc] . " (" . enc . ")",
+          \ getline('.'))
+    cclose
+  endfor
+
+  " :lmake
+  for enc in keys(s:message_tbl)
+    let &makeencoding = enc
+    exec "silent lmake! " . s:script . " " . enc
+    lopen
+    call assert_equal("Xfoobar.c|10| " . s:message_tbl[enc] . " (" . enc . ")",
+          \ getline('.'))
+    lclose
+  endfor
+endfunc