changeset 2229:d45902a5c61c vim73

Fix a few more things for persistent undo.
author Bram Moolenaar <bram@vim.org>
date Sat, 29 May 2010 15:11:47 +0200
parents f5bd6753cdc4
children 290ee42cae85
files runtime/doc/todo.txt runtime/syntax/forth.vim src/misc2.c src/proto/misc2.pro src/spell.c src/undo.c
diffstat 6 files changed, 222 insertions(+), 191 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/todo.txt
+++ b/runtime/doc/todo.txt
@@ -30,11 +30,6 @@ be worked on, but only if you sponsor Vi
 							*known-bugs*
 -------------------- Known bugs and current work -----------------------
 
-Patch for invalid mem access in completion. (Dominique Pelle, 2010 May 26)
-
-Invalid memory access when deleting funcref variable.  Patch by Lech Lorens,
-2010 May 25.
-
 Fixes for broken URLs:
     Benjamin Haskell, 2010 May 25
     Christian Brabandt, 2010 May 26, two messages
@@ -1095,26 +1090,29 @@ restored. (Luc St-Louis)
 
 Vim 7.3:
 - Win32 DOS and Win32 console version: test69 fails.
-- Win32 binary: vim -r fails. (Antonio Colombo)  Also on Unix.
 - using NSIS 2.46: install on Windows 7 works, but no "Edit with Vim" menu.
    Use register_shell_extension()? (George Reilly, 2010 May 26)
    Ron's version: http://dev.ronware.org/p/vim/finfo?name=gvim.nsi
-Patches to include:
 - Persistent undo bugs / fixes:
+    - Memory leak reproduced by Dominique Pelle, 2010 May 28.
+    - Compiling without FEAT_SPELL fails, functions used in undo code:
+	get2c, get4c, put_bytes (Ralf Schandl)
     - binary distributed: ":wundo" always fails.
-    - Patch not to allocate extra byte in U_ALLOC_LINE() (Dominique, 2010 May
-      25)
+    - Patch not to allocate extra byte in U_ALLOC_LINE() (Dominique Pelle,
+      2010 May 25)
     - Remove the old code when U_USE_MALLOC is not defined?
     - When there is no undo info (undolevels negative), delete the undo file.
     - Need to check all values for evil manipulation.
     - Add undofile(name): get undo file name for buffer "name".
-- Extend test62 for gettabvar() and settabvar(). (Yegappan Lakshmanan, 2010
-  May 23)
 - Also crypt the undo file.
 - Also crypt the swap file, each block separately.  Change mf_write() and
     mf_read().  How to get b_p_key to these functions?
 - Do profiling on sha256 code to find obvious bottlenecks.
 - Do profiling on crypt code to find obvious bottlenecks.
+- Make 'clipboard' global-local, for "html"?  Christian J. Robinson.
+Patches to include:
+- Extend test62 for gettabvar() and settabvar(). (Yegappan Lakshmanan, 2010
+  May 23)
 - Use off_t instead of long for bytes in a buffer. (James Vega, 2010 May 22,
   update next day)
 - Include conceal patch?
--- a/runtime/syntax/forth.vim
+++ b/runtime/syntax/forth.vim
@@ -1,11 +1,11 @@
 " Vim syntax file
 " Language:    FORTH
 " Maintainer:  Christian V. J. Brüssow <cvjb@cvjb.de>
-" Last Change: Sa 09 Feb 2008 13:27:29 CET
+" Last Change: Di 07 Jul 2009 21:38:45 CEST
 " Filenames:   *.fs,*.ft
 " URL:	       http://www.cvjb.de/comp/vim/forth.vim
 
-" $Id: forth.vim,v 1.11 2008/02/09 13:17:01 bruessow Exp $
+" $Id: forth.vim,v 1.12 2008/07/07 21:39:12 bruessow Exp $
 
 " The list of keywords is incomplete, compared with the offical ANS
 " wordlist. If you use this language, please improve it, and send me
@@ -17,6 +17,11 @@
 
 " Many Thanks to...
 "
+" 2009-06-28:
+" Josh Grams send a patch to allow the parenthesis comments at the
+" beginning of a line. That patch also fixed a typo in one of the
+" comments.
+"
 " 2008-02-09:
 " Shawn K. Quinn <sjquinn at speakeasy dot net> send a big patch with
 " new words commonly used in Forth programs or defined by GNU Forth.
@@ -209,7 +214,7 @@ syn keyword forthConversion <<# <# # #> 
 syn keyword forthConversion D>S DIGIT DPL F>D HLD HOLD NUMBER S>D SIGN >NUMBER
 syn keyword forthConversion F>S S>F
 
-" interptreter, wordbook, compiler
+" interpreter, wordbook, compiler
 syn keyword forthForth (LOCAL) BYE COLD ABORT >BODY >NEXT >LINK CFA >VIEW HERE
 syn keyword forthForth PAD WORDS VIEW VIEW> N>LINK NAME> LINK> L>NAME FORGET
 syn keyword forthForth BODY> ASSERT( ASSERT0( ASSERT1( ASSERT2( ASSERT3( )
@@ -258,7 +263,7 @@ syn region forthString start=+c\"+ end=+
 syn match forthComment '\\\s.*$' contains=forthTodo,forthSpaceError
 syn region forthComment start='\\S\s' end='.*' contains=forthTodo,forthSpaceError
 syn match forthComment '\.(\s[^)]*)' contains=forthTodo,forthSpaceError
-syn region forthComment start='\s(\s' skip='\\)' end=')' contains=forthTodo,forthSpaceError
+syn region forthComment start='\(^\|\s\)\zs(\s' skip='\\)' end=')' contains=forthTodo,forthSpaceError
 syn region forthComment start='/\*' end='\*/' contains=forthTodo,forthSpaceError
 
 " Include files
--- a/src/misc2.c
+++ b/src/misc2.c
@@ -6125,3 +6125,165 @@ emsgn(s, n)
     vim_snprintf((char *)IObuff, IOSIZE, (char *)s, n);
     return emsg(IObuff);
 }
+
+#if defined(FEAT_SPELL) || defined(FEAT_PERSISTENT_UNDO) || defined(PROTO)
+/*
+ * Read 2 bytes from "fd" and turn them into an int, MSB first.
+ */
+    int
+get2c(fd)
+    FILE	*fd;
+{
+    long	n;
+
+    n = getc(fd);
+    n = (n << 8) + getc(fd);
+    return n;
+}
+
+/*
+ * Read 3 bytes from "fd" and turn them into an int, MSB first.
+ */
+    int
+get3c(fd)
+    FILE	*fd;
+{
+    long	n;
+
+    n = getc(fd);
+    n = (n << 8) + getc(fd);
+    n = (n << 8) + getc(fd);
+    return n;
+}
+
+/*
+ * Read 4 bytes from "fd" and turn them into an int, MSB first.
+ */
+    int
+get4c(fd)
+    FILE	*fd;
+{
+    long	n;
+
+    n = getc(fd);
+    n = (n << 8) + getc(fd);
+    n = (n << 8) + getc(fd);
+    n = (n << 8) + getc(fd);
+    return n;
+}
+
+/*
+ * Read 8 bytes from "fd" and turn them into a time_t, MSB first.
+ */
+    time_t
+get8ctime(fd)
+    FILE	*fd;
+{
+    time_t	n = 0;
+    int		i;
+
+    for (i = 0; i < 8; ++i)
+	n = (n << 8) + getc(fd);
+    return n;
+}
+
+/*
+ * Read a string of length "cnt" from "fd" into allocated memory.
+ * Returns NULL when out of memory or unable to read that many bytes.
+ */
+    char_u *
+read_string(fd, cnt)
+    FILE	*fd;
+    int		cnt;
+{
+    char_u	*str;
+    int		i;
+    int		c;
+
+    /* allocate memory */
+    str = alloc((unsigned)cnt + 1);
+    if (str != NULL)
+    {
+	/* Read the string.  Quit when running into the EOF. */
+	for (i = 0; i < cnt; ++i)
+	{
+	    c = getc(fd);
+	    if (c == EOF)
+	    {
+		vim_free(str);
+		return NULL;
+	    }
+	    str[i] = c;
+	}
+	str[i] = NUL;
+    }
+    return str;
+}
+
+/*
+ * Write a number to file "fd", MSB first, in "len" bytes.
+ */
+    int
+put_bytes(fd, nr, len)
+    FILE    *fd;
+    long_u  nr;
+    int	    len;
+{
+    int	    i;
+
+    for (i = len - 1; i >= 0; --i)
+	if (putc((int)(nr >> (i * 8)), fd) == EOF)
+	    return FAIL;
+    return OK;
+}
+
+#ifdef _MSC_VER
+# if (_MSC_VER <= 1200)
+/* This line is required for VC6 without the service pack.  Also see the
+ * matching #pragma below. */
+ #  pragma optimize("", off)
+# endif
+#endif
+
+/*
+ * Write time_t to file "fd" in 8 bytes.
+ */
+    void
+put_time(fd, the_time)
+    FILE	*fd;
+    time_t	the_time;
+{
+    int		c;
+    int		i;
+    time_t	wtime = the_time;
+
+    /* time_t can be up to 8 bytes in size, more than long_u, thus we
+     * can't use put_bytes() here.
+     * Another problem is that ">>" may do an arithmetic shift that keeps the
+     * sign.  A cast to long_u may truncate if time_t is 8 bytes.  So only use
+     * a cast when it is 4 bytes, it's safe to assume that long_u is 4 bytes
+     * or more and when using 8 bytes the top bit won't be set. */
+    for (i = 7; i >= 0; --i)
+    {
+	if (i + 1 > (int)sizeof(time_t))
+	    /* ">>" doesn't work well when shifting more bits than avail */
+	    putc(0, fd);
+	else
+	{
+	    /* use "i" in condition to avoid compiler warning */
+	    if (i >= 0 && sizeof(time_t) > 4)
+		c = wtime >> (i * 8);
+	    else
+		c = (long_u)wtime >> (i * 8);
+	    putc(c, fd);
+	}
+    }
+}
+
+#ifdef _MSC_VER
+# if (_MSC_VER <= 1200)
+ #  pragma optimize("", on)
+# endif
+#endif
+
+#endif
--- a/src/proto/misc2.pro
+++ b/src/proto/misc2.pro
@@ -100,4 +100,11 @@ int pathcmp __ARGS((const char *p, const
 int filewritable __ARGS((char_u *fname));
 int emsg3 __ARGS((char_u *s, char_u *a1, char_u *a2));
 int emsgn __ARGS((char_u *s, long n));
+int get2c __ARGS((FILE *fd));
+int get3c __ARGS((FILE *fd));
+int get4c __ARGS((FILE *fd));
+time_t get8ctime __ARGS((FILE *fd));
+char_u *read_string __ARGS((FILE *fd, int cnt));
+int put_bytes __ARGS((FILE *fd, long_u nr, int len));
+void put_time __ARGS((FILE *fd, time_t the_time));
 /* vim: set ft=c : */
--- a/src/spell.c
+++ b/src/spell.c
@@ -854,9 +854,7 @@ static char_u *spell_enc __ARGS((void));
 static void int_wordlist_spl __ARGS((char_u *fname));
 static void spell_load_cb __ARGS((char_u *fname, void *cookie));
 static slang_T *spell_load_file __ARGS((char_u *fname, char_u *lang, slang_T *old_lp, int silent));
-static time_t get8c __ARGS((FILE *fd));
 static char_u *read_cnt_string __ARGS((FILE *fd, int cnt_bytes, int *lenp));
-static char_u *read_string __ARGS((FILE *fd, int cnt));
 static int read_region_section __ARGS((FILE *fd, slang_T *slang, int len));
 static int read_charflags_section __ARGS((FILE *fd));
 static int read_prefcond_section __ARGS((FILE *fd, slang_T *lp));
@@ -2888,7 +2886,7 @@ spell_load_file(fname, lang, old_lp, sil
 		break;
 
 	    case SN_SUGFILE:
-		lp->sl_sugtime = get8c(fd);		/* <timestamp> */
+		lp->sl_sugtime = get8ctime(fd);		/* <timestamp> */
 		break;
 
 	    case SN_NOSPLITSUGS:
@@ -2983,66 +2981,6 @@ endOK:
 }
 
 /*
- * Read 2 bytes from "fd" and turn them into an int, MSB first.
- */
-    int
-get2c(fd)
-    FILE	*fd;
-{
-    long	n;
-
-    n = getc(fd);
-    n = (n << 8) + getc(fd);
-    return n;
-}
-
-/*
- * Read 3 bytes from "fd" and turn them into an int, MSB first.
- */
-    int
-get3c(fd)
-    FILE	*fd;
-{
-    long	n;
-
-    n = getc(fd);
-    n = (n << 8) + getc(fd);
-    n = (n << 8) + getc(fd);
-    return n;
-}
-
-/*
- * Read 4 bytes from "fd" and turn them into an int, MSB first.
- */
-    int
-get4c(fd)
-    FILE	*fd;
-{
-    long	n;
-
-    n = getc(fd);
-    n = (n << 8) + getc(fd);
-    n = (n << 8) + getc(fd);
-    n = (n << 8) + getc(fd);
-    return n;
-}
-
-/*
- * Read 8 bytes from "fd" and turn them into a time_t, MSB first.
- */
-    static time_t
-get8c(fd)
-    FILE	*fd;
-{
-    time_t	n = 0;
-    int		i;
-
-    for (i = 0; i < 8; ++i)
-	n = (n << 8) + getc(fd);
-    return n;
-}
-
-/*
  * Read a length field from "fd" in "cnt_bytes" bytes.
  * Allocate memory, read the string into it and add a NUL at the end.
  * Returns NULL when the count is zero.
@@ -3078,39 +3016,6 @@ read_cnt_string(fd, cnt_bytes, cntp)
 }
 
 /*
- * Read a string of length "cnt" from "fd" into allocated memory.
- * Returns NULL when out of memory or unable to read that many bytes.
- */
-    static char_u *
-read_string(fd, cnt)
-    FILE	*fd;
-    int		cnt;
-{
-    char_u	*str;
-    int		i;
-    int		c;
-
-    /* allocate memory */
-    str = alloc((unsigned)cnt + 1);
-    if (str != NULL)
-    {
-	/* Read the string.  Quit when running into the EOF. */
-	for (i = 0; i < cnt; ++i)
-	{
-	    c = getc(fd);
-	    if (c == EOF)
-	    {
-		vim_free(str);
-		return NULL;
-	    }
-	    str[i] = c;
-	}
-	str[i] = NUL;
-    }
-    return str;
-}
-
-/*
  * Read SN_REGION: <regionname> ...
  * Return SP_*ERROR flags.
  */
@@ -5113,7 +5018,6 @@ static void free_wordnode __ARGS((spelli
 static void wordtree_compress __ARGS((spellinfo_T *spin, wordnode_T *root));
 static int node_compress __ARGS((spellinfo_T *spin, wordnode_T *node, hashtab_T *ht, int *tot));
 static int node_equal __ARGS((wordnode_T *n1, wordnode_T *n2));
-static void put_sugtime __ARGS((spellinfo_T *spin, FILE *fd));
 static int write_vim_spell __ARGS((spellinfo_T *spin, char_u *fname));
 static void clear_node __ARGS((wordnode_T *node));
 static int put_node __ARGS((FILE *fd, wordnode_T *node, int idx, int regionmask, int prefixtree));
@@ -8012,61 +7916,6 @@ node_equal(n1, n2)
     return p1 == NULL && p2 == NULL;
 }
 
-/*
- * Write a number to file "fd", MSB first, in "len" bytes.
- */
-    int
-put_bytes(fd, nr, len)
-    FILE    *fd;
-    long_u  nr;
-    int	    len;
-{
-    int	    i;
-
-    for (i = len - 1; i >= 0; --i)
-	if (putc((int)(nr >> (i * 8)), fd) == EOF)
-	    return FAIL;
-    return OK;
-}
-
-#ifdef _MSC_VER
-# if (_MSC_VER <= 1200)
-/* This line is required for VC6 without the service pack.  Also see the
- * matching #pragma below. */
- #  pragma optimize("", off)
-# endif
-#endif
-
-/*
- * Write spin->si_sugtime to file "fd".
- */
-    static void
-put_sugtime(spin, fd)
-    spellinfo_T *spin;
-    FILE	*fd;
-{
-    int		c;
-    int		i;
-
-    /* time_t can be up to 8 bytes in size, more than long_u, thus we
-     * can't use put_bytes() here. */
-    for (i = 7; i >= 0; --i)
-	if (i + 1 > (int)sizeof(time_t))
-	    /* ">>" doesn't work well when shifting more bits than avail */
-	    putc(0, fd);
-	else
-	{
-	    c = (unsigned)spin->si_sugtime >> (i * 8);
-	    putc(c, fd);
-	}
-}
-
-#ifdef _MSC_VER
-# if (_MSC_VER <= 1200)
- #  pragma optimize("", on)
-# endif
-#endif
-
 static int
 #ifdef __BORLANDC__
 _RTLENTRYF
@@ -8384,7 +8233,7 @@ write_vim_spell(spin, fname)
 
 	/* Set si_sugtime and write it to the file. */
 	spin->si_sugtime = time(NULL);
-	put_sugtime(spin, fd);				/* <timestamp> */
+	put_time(fd, spin->si_sugtime);			/* <timestamp> */
     }
 
     /* SN_NOSPLITSUGS: nothing
@@ -9106,7 +8955,7 @@ sug_write(spin, fname)
     putc(VIMSUGVERSION, fd);				/* <versionnr> */
 
     /* Write si_sugtime to the file. */
-    put_sugtime(spin, fd);				/* <timestamp> */
+    put_time(fd, spin->si_sugtime);			/* <timestamp> */
 
     /*
      * <SUGWORDTREE>
@@ -11059,7 +10908,7 @@ suggest_load_files()
 
 	    /* Check the timestamp, it must be exactly the same as the one in
 	     * the .spl file.  Otherwise the word numbers won't match. */
-	    timestamp = get8c(fd);			/* <timestamp> */
+	    timestamp = get8ctime(fd);			/* <timestamp> */
 	    if (timestamp != slang->sl_sugtime)
 	    {
 		EMSG2(_("E781: .sug file doesn't match .spl file: %s"),
--- a/src/undo.c
+++ b/src/undo.c
@@ -110,7 +110,7 @@ static char_u *u_get_undo_file_name __AR
 static void u_free_uhp __ARGS((u_header_T *uhp));
 static int serialize_uep __ARGS((u_entry_T *uep, FILE *fp));
 static void serialize_pos __ARGS((pos_T pos, FILE *fp));
-static void serialize_visualinfo __ARGS((visualinfo_T info, FILE *fp));
+static void serialize_visualinfo __ARGS((visualinfo_T *info, FILE *fp));
 #endif
 
 #ifdef U_USE_MALLOC
@@ -675,6 +675,9 @@ nomem:
 # define UF_END_MAGIC	    0xe7aa	/* magic after last header */
 # define UF_VERSION	    1		/* 2-byte undofile version number */
 
+static char_u e_not_open[] = N_("E828: Cannot open undo file for writing: %s");
+static char_u e_corrupted[] = N_("E823: Corrupted undo file: %s");
+
 /*
  * Compute the hash for the current buffer text into hash[UNDO_HASH_SIZE].
  */
@@ -866,7 +869,7 @@ u_read_undo(name, hash)
     magic = get2c(fp);
     if (magic != UF_START_MAGIC)
     {
-        EMSG2(_("E823: Corrupted undo file: %s"), file_name);
+        EMSG2(_(e_corrupted), file_name);
         goto error;
     }
     version = get2c(fp);
@@ -876,7 +879,11 @@ u_read_undo(name, hash)
         goto error;
     }
 
-    fread(read_hash, UNDO_HASH_SIZE, 1, fp);
+    if (fread(read_hash, UNDO_HASH_SIZE, 1, fp) != 1)
+    {
+        EMSG2(_(e_corrupted), file_name);
+        goto error;
+    }
     line_count = (linenr_T)get4c(fp);
     if (memcmp(hash, read_hash, UNDO_HASH_SIZE) != 0
 				  || line_count != curbuf->b_ml.ml_line_count)
@@ -912,7 +919,7 @@ u_read_undo(name, hash)
     num_head = get4c(fp);
     seq_last = get4c(fp);
     seq_cur = get4c(fp);
-    seq_time = get4c(fp);
+    seq_time = get8ctime(fp);
 
     if (num_head < 0)
 	num_head = 0;
@@ -942,10 +949,10 @@ u_read_undo(name, hash)
         /* We're not actually trying to store pointers here. We're just storing
          * IDs so we can swizzle them into pointers later - hence the type
 	 * cast. */
-        uhp->uh_next = (u_header_T *)get4c(fp);
-        uhp->uh_prev = (u_header_T *)get4c(fp);
-        uhp->uh_alt_next = (u_header_T *)get4c(fp);
-        uhp->uh_alt_prev = (u_header_T *)get4c(fp);
+        uhp->uh_next = (u_header_T *)(long_u)get4c(fp);
+        uhp->uh_prev = (u_header_T *)(long_u)get4c(fp);
+        uhp->uh_alt_next = (u_header_T *)(long_u)get4c(fp);
+        uhp->uh_alt_prev = (u_header_T *)(long_u)get4c(fp);
         uhp->uh_seq = get4c(fp);
         if (uhp->uh_seq <= 0)
         {
@@ -972,7 +979,7 @@ u_read_undo(name, hash)
 	    unserialize_visualinfo(&info, fp);
 	}
 #endif
-        uhp->uh_time = get4c(fp);
+        uhp->uh_time = get8ctime(fp);
 
         /* Unserialize uep list. The first 4 bytes is the length of the
          * entire uep in bytes minus the length of the strings within.
@@ -1220,17 +1227,15 @@ serialize_pos(pos, fp)
  */
     static void
 serialize_visualinfo(info, fp)
-    visualinfo_T    info;
+    visualinfo_T    *info;
     FILE	    *fp;
 {
-    serialize_pos(info.vi_start, fp);
-    serialize_pos(info.vi_end, fp);
-    put_bytes(fp, (long_u)info.vi_mode, 4);
-    put_bytes(fp, (long_u)info.vi_curswant, 4);
+    serialize_pos(info->vi_start, fp);
+    serialize_pos(info->vi_end, fp);
+    put_bytes(fp, (long_u)info->vi_mode, 4);
+    put_bytes(fp, (long_u)info->vi_curswant, 4);
 }
 
-static char_u e_not_open[] = N_("E828: Cannot open undo file for writing: %s");
-
 /*
  * Write the undo tree in an undo file.
  * When "name" is not NULL, use it as the name of the undo file.
@@ -1398,7 +1403,7 @@ u_write_undo(name, forceit, buf, hash)
     put_bytes(fp, (long_u)buf->b_u_numhead, 4);
     put_bytes(fp, (long_u)buf->b_u_seq_last, 4);
     put_bytes(fp, (long_u)buf->b_u_seq_cur, 4);
-    put_bytes(fp, (long_u)buf->b_u_seq_time, 4);
+    put_time(fp, buf->b_u_seq_time);
 
     /* Iteratively serialize UHPs and their UEPs from the top down.  */
     mark = ++lastmark;
@@ -1429,13 +1434,18 @@ u_write_undo(name, forceit, buf, hash)
             put_bytes(fp, (long_u)uhp->uh_flags, 2);
             /* Assume NMARKS will stay the same. */
             for (i = 0; i < NMARKS; ++i)
-            {
                 serialize_pos(uhp->uh_namedm[i], fp);
-            }
 #ifdef FEAT_VISUAL
-            serialize_visualinfo(uhp->uh_visual, fp);
+            serialize_visualinfo(&uhp->uh_visual, fp);
+#else
+	    {
+		visualinfo_T info;
+
+		memset(&info, 0, sizeof(visualinfo_T));
+		serialize_visualinfo(&info, fp);
+	    }
 #endif
-            put_bytes(fp, (long_u)uhp->uh_time, 4);
+            put_time(fp, uhp->uh_time);
 
             uep = uhp->uh_entry;
             while (uep != NULL)