Fix a few more things for persistent undo.
diff --git a/src/misc2.c b/src/misc2.c
index 03af4cc..470bc2f 100644
--- a/src/misc2.c
+++ b/src/misc2.c
@@ -6125,3 +6125,165 @@
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
index 9b27b7e..a688147 100644
--- a/src/proto/misc2.pro
+++ b/src/proto/misc2.pro
@@ -100,4 +100,11 @@
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
index 1c3fd0f..fbf5c91 100644
--- a/src/spell.c
+++ b/src/spell.c
@@ -854,9 +854,7 @@
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 @@
break;
case SN_SUGFILE:
- lp->sl_sugtime = get8c(fd); /* <timestamp> */
+ lp->sl_sugtime = get8ctime(fd); /* <timestamp> */
break;
case SN_NOSPLITSUGS:
@@ -2983,66 +2981,6 @@
}
/*
- * 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 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 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 @@
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 @@
/* 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 @@
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 @@
/* 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"),
diff --git a/src/undo.c b/src/undo.c
index c5ea47c..bac8ec7 100644
--- a/src/undo.c
+++ b/src/undo.c
@@ -110,7 +110,7 @@
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 @@
# 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 @@
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 @@
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 @@
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 @@
/* 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 @@
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 @@
*/
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 @@
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 @@
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)