Bram, When do_source() is called with a FIFO (or other file types for which lseek(2) errors), the first 3 bytes of the file are discarded due to the BOM check. The attached patch reads the entire first line to do the BOM check and then passes it on to do_cmdline later on.
A similar problem will occur in get_one_sourceline() if the line doesn't end on a '\n' and has a '\r' (lines 3478-3492 in the patched code, 3475-3489 in 7.2.084). I wasn't sure how to approach this occurrence. This came up on the #vim IRC channel yesterday as a user was trying to automate running with Vim with generated text for the vimrc. A simple, although not very useful, example making use of bash/zsh's process substitution would be: vim -u <(cat ~/.vimrc) -- James GPG Key: 1024D/61326D40 2003-09-02 James Vega <james...@jamessan.com>
diff --git a/src/ex_cmds2.c b/src/ex_cmds2.c index 2c0f80d..33fdf1c 100644 --- a/src/ex_cmds2.c +++ b/src/ex_cmds2.c @@ -2842,6 +2842,7 @@ do_source(fname, check_other, is_vimrc) linenr_T save_sourcing_lnum; char_u *p; char_u *fname_exp; + char_u *firstline = NULL; int retval = FAIL; #ifdef FEAT_EVAL scid_T save_current_SID; @@ -2995,18 +2996,18 @@ do_source(fname, check_other, is_vimrc) #ifdef FEAT_MBYTE cookie.conv.vc_type = CONV_NONE; /* no conversion */ - /* Try reading the first few bytes to check for a UTF-8 BOM. */ + /* Read the first line so we can check for a UTF-8 BOM. */ + firstline = getsourceline(0, (void*)&cookie, 0); + if (firstline != NULL && strlen(firstline) >= 3 + &&firstline[0] == 0xef && firstline[1] == 0xbb && firstline[2] == 0xbf) { - char_u buf[3]; - - if (fread((char *)buf, sizeof(char_u), (size_t)3, cookie.fp) - == (size_t)3 - && buf[0] == 0xef && buf[1] == 0xbb && buf[2] == 0xbf) - /* Found BOM, setup conversion and skip over it. */ - convert_setup(&cookie.conv, (char_u *)"utf-8", p_enc); - else - /* No BOM found, rewind. */ - fseek(cookie.fp, 0L, SEEK_SET); + char_u *buf; + /* Found BOM; setup conversion, skip over BOM and recode the line. */ + convert_setup(&cookie.conv, (char_u *)"utf-8", p_enc); + firstline = firstline + 3; + buf = string_convert(&cookie.conv, firstline, NULL); + if (buf != NULL) + firstline = buf; } #endif @@ -3111,8 +3112,10 @@ do_source(fname, check_other, is_vimrc) /* * Call do_cmdline, which will call getsourceline() to get the lines. */ - do_cmdline(NULL, getsourceline, (void *)&cookie, + do_cmdline(firstline, getsourceline, (void *)&cookie, DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_REPEAT); + if (firstline) + vim_free(firstline); retval = OK;
signature.asc
Description: Digital signature