Skip to content

Commit f71d7b9

Browse files
committed
patch 7.4.2189
Problem: Cannot detect encoding in a fifo. Solution: Extend the stdin way of detecting encoding to fifo. Add a test for detecting encoding on stdin and fifo. (Ken Takata)
1 parent c9fb77c commit f71d7b9

7 files changed

Lines changed: 168 additions & 47 deletions

File tree

src/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2114,6 +2114,7 @@ test_arglist \
21142114
test_signs \
21152115
test_sort \
21162116
test_startup \
2117+
test_startup_utf8 \
21172118
test_stat \
21182119
test_statusline \
21192120
test_syn_attr \

src/buffer.c

Lines changed: 89 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,64 @@ static char *e_auabort = N_("E855: Autocommands caused command to abort");
7070
/* Number of times free_buffer() was called. */
7171
static int buf_free_count = 0;
7272

73+
/* Read data from buffer for retrying. */
74+
static int
75+
read_buffer(
76+
int read_stdin, /* read file from stdin, otherwise fifo */
77+
exarg_T *eap, /* for forced 'ff' and 'fenc' or NULL */
78+
int flags) /* extra flags for readfile() */
79+
{
80+
int retval = OK;
81+
linenr_T line_count;
82+
83+
/*
84+
* Read from the buffer which the text is already filled in and append at
85+
* the end. This makes it possible to retry when 'fileformat' or
86+
* 'fileencoding' was guessed wrong.
87+
*/
88+
line_count = curbuf->b_ml.ml_line_count;
89+
retval = readfile(
90+
read_stdin ? NULL : curbuf->b_ffname,
91+
read_stdin ? NULL : curbuf->b_fname,
92+
(linenr_T)line_count, (linenr_T)0, (linenr_T)MAXLNUM, eap,
93+
flags | READ_BUFFER);
94+
if (retval == OK)
95+
{
96+
/* Delete the binary lines. */
97+
while (--line_count >= 0)
98+
ml_delete((linenr_T)1, FALSE);
99+
}
100+
else
101+
{
102+
/* Delete the converted lines. */
103+
while (curbuf->b_ml.ml_line_count > line_count)
104+
ml_delete(line_count, FALSE);
105+
}
106+
/* Put the cursor on the first line. */
107+
curwin->w_cursor.lnum = 1;
108+
curwin->w_cursor.col = 0;
109+
110+
if (read_stdin)
111+
{
112+
/* Set or reset 'modified' before executing autocommands, so that
113+
* it can be changed there. */
114+
if (!readonlymode && !bufempty())
115+
changed();
116+
else if (retval != FAIL)
117+
unchanged(curbuf, FALSE);
118+
119+
#ifdef FEAT_AUTOCMD
120+
# ifdef FEAT_EVAL
121+
apply_autocmds_retval(EVENT_STDINREADPOST, NULL, NULL, FALSE,
122+
curbuf, &retval);
123+
# else
124+
apply_autocmds(EVENT_STDINREADPOST, NULL, NULL, FALSE, curbuf);
125+
# endif
126+
#endif
127+
}
128+
return retval;
129+
}
130+
73131
/*
74132
* Open current buffer, that is: open the memfile and read the file into
75133
* memory.
@@ -88,6 +146,7 @@ open_buffer(
88146
#ifdef FEAT_SYN_HL
89147
long old_tw = curbuf->b_p_tw;
90148
#endif
149+
int read_fifo = FALSE;
91150

92151
/*
93152
* The 'readonly' flag is only set when BF_NEVERLOADED is being reset.
@@ -143,17 +202,42 @@ open_buffer(
143202
)
144203
{
145204
int old_msg_silent = msg_silent;
146-
205+
#ifdef UNIX
206+
int save_bin = curbuf->b_p_bin;
207+
int perm;
208+
#endif
147209
#ifdef FEAT_NETBEANS_INTG
148210
int oldFire = netbeansFireChanges;
149211

150212
netbeansFireChanges = 0;
213+
#endif
214+
#ifdef UNIX
215+
perm = mch_getperm(curbuf->b_ffname);
216+
if (perm >= 0 && (0
217+
# ifdef S_ISFIFO
218+
|| S_ISFIFO(perm)
219+
# endif
220+
# ifdef S_ISSOCK
221+
|| S_ISSOCK(perm)
222+
# endif
223+
))
224+
read_fifo = TRUE;
225+
if (read_fifo)
226+
curbuf->b_p_bin = TRUE;
151227
#endif
152228
if (shortmess(SHM_FILEINFO))
153229
msg_silent = 1;
154230
retval = readfile(curbuf->b_ffname, curbuf->b_fname,
155231
(linenr_T)0, (linenr_T)0, (linenr_T)MAXLNUM, eap,
156-
flags | READ_NEW);
232+
flags | READ_NEW | (read_fifo ? READ_FIFO : 0));
233+
#ifdef UNIX
234+
if (read_fifo)
235+
{
236+
curbuf->b_p_bin = save_bin;
237+
if (retval == OK)
238+
retval = read_buffer(FALSE, eap, flags);
239+
}
240+
#endif
157241
msg_silent = old_msg_silent;
158242
#ifdef FEAT_NETBEANS_INTG
159243
netbeansFireChanges = oldFire;
@@ -164,8 +248,7 @@ open_buffer(
164248
}
165249
else if (read_stdin)
166250
{
167-
int save_bin = curbuf->b_p_bin;
168-
linenr_T line_count;
251+
int save_bin = curbuf->b_p_bin;
169252

170253
/*
171254
* First read the text in binary mode into the buffer.
@@ -179,42 +262,7 @@ open_buffer(
179262
flags | (READ_NEW + READ_STDIN));
180263
curbuf->b_p_bin = save_bin;
181264
if (retval == OK)
182-
{
183-
line_count = curbuf->b_ml.ml_line_count;
184-
retval = readfile(NULL, NULL, (linenr_T)line_count,
185-
(linenr_T)0, (linenr_T)MAXLNUM, eap,
186-
flags | READ_BUFFER);
187-
if (retval == OK)
188-
{
189-
/* Delete the binary lines. */
190-
while (--line_count >= 0)
191-
ml_delete((linenr_T)1, FALSE);
192-
}
193-
else
194-
{
195-
/* Delete the converted lines. */
196-
while (curbuf->b_ml.ml_line_count > line_count)
197-
ml_delete(line_count, FALSE);
198-
}
199-
/* Put the cursor on the first line. */
200-
curwin->w_cursor.lnum = 1;
201-
curwin->w_cursor.col = 0;
202-
203-
/* Set or reset 'modified' before executing autocommands, so that
204-
* it can be changed there. */
205-
if (!readonlymode && !bufempty())
206-
changed();
207-
else if (retval != FAIL)
208-
unchanged(curbuf, FALSE);
209-
#ifdef FEAT_AUTOCMD
210-
# ifdef FEAT_EVAL
211-
apply_autocmds_retval(EVENT_STDINREADPOST, NULL, NULL, FALSE,
212-
curbuf, &retval);
213-
# else
214-
apply_autocmds(EVENT_STDINREADPOST, NULL, NULL, FALSE, curbuf);
215-
# endif
216-
#endif
217-
}
265+
retval = read_buffer(TRUE, eap, flags);
218266
}
219267

220268
/* if first time loading this buffer, init b_chartab[] */
@@ -243,7 +291,7 @@ open_buffer(
243291
#endif
244292
)
245293
changed();
246-
else if (retval != FAIL && !read_stdin)
294+
else if (retval != FAIL && !read_stdin && !read_fifo)
247295
unchanged(curbuf, FALSE);
248296
save_file_ff(curbuf); /* keep this fileformat */
249297

src/fileio.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ filemess(
212212
* stdin)
213213
* READ_DUMMY read into a dummy buffer (to check if file contents changed)
214214
* READ_KEEP_UNDO don't clear undo info or read it from a file
215+
* READ_FIFO read from fifo/socket instead of a file
215216
*
216217
* return FAIL for failure, OK otherwise
217218
*/
@@ -231,6 +232,7 @@ readfile(
231232
int filtering = (flags & READ_FILTER);
232233
int read_stdin = (flags & READ_STDIN);
233234
int read_buffer = (flags & READ_BUFFER);
235+
int read_fifo = (flags & READ_FIFO);
234236
int set_options = newfile || read_buffer
235237
|| (eap != NULL && eap->read_edit);
236238
linenr_T read_buf_lnum = 1; /* next line to read from curbuf */
@@ -431,7 +433,7 @@ readfile(
431433
}
432434
}
433435

434-
if (!read_stdin && !read_buffer)
436+
if (!read_stdin && !read_buffer && !read_fifo)
435437
{
436438
#ifdef UNIX
437439
/*
@@ -489,7 +491,7 @@ readfile(
489491
if (check_readonly && !readonlymode)
490492
curbuf->b_p_ro = FALSE;
491493

492-
if (newfile && !read_stdin && !read_buffer)
494+
if (newfile && !read_stdin && !read_buffer && !read_fifo)
493495
{
494496
/* Remember time of file. */
495497
if (mch_stat((char *)fname, &st) >= 0)
@@ -1101,6 +1103,7 @@ readfile(
11011103
* and we can't do it internally or with iconv().
11021104
*/
11031105
if (fio_flags == 0 && !read_stdin && !read_buffer && *p_ccv != NUL
1106+
&& !read_fifo
11041107
# ifdef USE_ICONV
11051108
&& iconv_fd == (iconv_t)-1
11061109
# endif
@@ -1149,7 +1152,7 @@ readfile(
11491152
/* Set "can_retry" when it's possible to rewind the file and try with
11501153
* another "fenc" value. It's FALSE when no other "fenc" to try, reading
11511154
* stdin or fixed at a specific encoding. */
1152-
can_retry = (*fenc != NUL && !read_stdin && !keep_dest_enc);
1155+
can_retry = (*fenc != NUL && !read_stdin && !read_fifo && !keep_dest_enc);
11531156
#endif
11541157

11551158
if (!skip_read)
@@ -1166,6 +1169,7 @@ readfile(
11661169
&& curbuf->b_ffname != NULL
11671170
&& curbuf->b_p_udf
11681171
&& !filtering
1172+
&& !read_fifo
11691173
&& !read_stdin
11701174
&& !read_buffer);
11711175
if (read_undo_file)
@@ -2666,7 +2670,7 @@ readfile(
26662670
#endif
26672671

26682672
#ifdef FEAT_AUTOCMD
2669-
if (!read_stdin && !read_buffer)
2673+
if (!read_stdin && !read_fifo && (!read_buffer || sfname != NULL))
26702674
{
26712675
int m = msg_scroll;
26722676
int n = msg_scrolled;
@@ -2685,7 +2689,7 @@ readfile(
26852689
if (filtering)
26862690
apply_autocmds_exarg(EVENT_FILTERREADPOST, NULL, sfname,
26872691
FALSE, curbuf, eap);
2688-
else if (newfile)
2692+
else if (newfile || (read_buffer && sfname != NULL))
26892693
{
26902694
apply_autocmds_exarg(EVENT_BUFREADPOST, NULL, sfname,
26912695
FALSE, curbuf, eap);

src/testdir/Make_all.mak

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ NEW_TESTS = test_arglist.res \
185185
test_ruby.res \
186186
test_signs.res \
187187
test_startup.res \
188+
test_startup_utf8.res \
188189
test_stat.res \
189190
test_syntax.res \
190191
test_textobjects.res \

src/testdir/test_startup_utf8.vim

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
" Tests for startup using utf-8.
2+
if !has('multi_byte')
3+
finish
4+
endif
5+
6+
source shared.vim
7+
8+
func Test_read_stdin_utf8()
9+
let linesin = ['テスト', '€ÀÈÌÒÙ']
10+
call writefile(linesin, 'Xtestin')
11+
let before = [
12+
\ 'set enc=utf-8',
13+
\ 'set fencs=cp932,utf-8',
14+
\ ]
15+
let after = [
16+
\ 'write ++enc=utf-8 Xtestout',
17+
\ 'quit!',
18+
\ ]
19+
if has('win32')
20+
let pipecmd = 'type Xtestin | '
21+
else
22+
let pipecmd = 'cat Xtestin | '
23+
endif
24+
if RunVimPiped(before, after, '-', pipecmd)
25+
let lines = readfile('Xtestout')
26+
call assert_equal(linesin, lines)
27+
else
28+
call assert_equal('', 'RunVimPiped failed.')
29+
endif
30+
call delete('Xtestout')
31+
call delete('Xtestin')
32+
endfunc
33+
34+
func Test_read_fifo_utf8()
35+
if !has('unix')
36+
return
37+
endif
38+
" Using bash/zsh's process substitution.
39+
if executable('bash')
40+
set shell=bash
41+
elseif executable('zsh')
42+
set shell=zsh
43+
else
44+
return
45+
endif
46+
let linesin = ['テスト', '€ÀÈÌÒÙ']
47+
call writefile(linesin, 'Xtestin')
48+
let before = [
49+
\ 'set enc=utf-8',
50+
\ 'set fencs=cp932,utf-8',
51+
\ ]
52+
let after = [
53+
\ 'write ++enc=utf-8 Xtestout',
54+
\ 'quit!',
55+
\ ]
56+
if RunVim(before, after, '<(cat Xtestin)')
57+
let lines = readfile('Xtestout')
58+
call assert_equal(linesin, lines)
59+
else
60+
call assert_equal('', 'RunVim failed.')
61+
endif
62+
call delete('Xtestout')
63+
call delete('Xtestin')
64+
endfunc

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -763,6 +763,8 @@ static char *(features[]) =
763763

764764
static int included_patches[] =
765765
{ /* Add new patch number below this line */
766+
/**/
767+
2189,
766768
/**/
767769
2188,
768770
/**/

src/vim.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -980,7 +980,8 @@ extern char *(*dyn_libintl_textdomain)(const char *domainname);
980980
#define READ_STDIN 0x04 /* read from stdin */
981981
#define READ_BUFFER 0x08 /* read from curbuf (converting stdin) */
982982
#define READ_DUMMY 0x10 /* reading into a dummy buffer */
983-
#define READ_KEEP_UNDO 0x20 /* keep undo info*/
983+
#define READ_KEEP_UNDO 0x20 /* keep undo info */
984+
#define READ_FIFO 0x40 /* read from fifo or socket */
984985

985986
/* Values for change_indent() */
986987
#define INDENT_SET 1 /* set indent */

0 commit comments

Comments
 (0)