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;
 

Attachment: signature.asc
Description: Digital signature

Raspunde prin e-mail lui