# HG changeset patch # User Bram Moolenaar # Date 1275138707 -7200 # Node ID d45902a5c61c055489e900e4098a73315780b036 # Parent f5bd6753cdc40733c903090cef1cff033942dcf7 Fix a few more things for persistent undo. diff --git a/runtime/doc/todo.txt b/runtime/doc/todo.txt --- 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? diff --git a/runtime/syntax/forth.vim b/runtime/syntax/forth.vim --- 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 -" 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 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 diff --git a/src/misc2.c b/src/misc2.c --- 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 diff --git a/src/proto/misc2.pro b/src/proto/misc2.pro --- 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 : */ diff --git a/src/spell.c b/src/spell.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); /* */ + lp->sl_sugtime = get8ctime(fd); /* */ 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: ... * 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); /* */ + put_time(fd, spin->si_sugtime); /* */ } /* SN_NOSPLITSUGS: nothing @@ -9106,7 +8955,7 @@ sug_write(spin, fname) putc(VIMSUGVERSION, fd); /* */ /* Write si_sugtime to the file. */ - put_sugtime(spin, fd); /* */ + put_time(fd, spin->si_sugtime); /* */ /* * @@ -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 = get8ctime(fd); /* */ if (timestamp != slang->sl_sugtime) { EMSG2(_("E781: .sug file doesn't match .spl file: %s"), diff --git a/src/undo.c b/src/undo.c --- 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)