xref: /vim-8.2.3635/src/viminfo.c (revision ed7cb2df)
1 /* vi:set ts=8 sts=4 sw=4 noet:
2  *
3  * VIM - Vi IMproved	by Bram Moolenaar
4  *
5  * Do ":help uganda"  in Vim to read copying and usage conditions.
6  * Do ":help credits" in Vim to see a list of people who contributed.
7  * See README.txt for an overview of the Vim source code.
8  */
9 
10 /*
11  * viminfo.c: viminfo related functions
12  */
13 
14 #include "vim.h"
15 #include "version.h"
16 
17 /*
18  * Structure used for reading from the viminfo file.
19  */
20 typedef struct
21 {
22     char_u	*vir_line;	// text of the current line
23     FILE	*vir_fd;	// file descriptor
24     vimconv_T	vir_conv;	// encoding conversion
25     int		vir_version;	// viminfo version detected or -1
26     garray_T	vir_barlines;	// lines starting with |
27 } vir_T;
28 
29 typedef enum {
30     BVAL_NR,
31     BVAL_STRING,
32     BVAL_EMPTY
33 } btype_T;
34 
35 typedef struct {
36     btype_T	bv_type;
37     long	bv_nr;
38     char_u	*bv_string;
39     char_u	*bv_tofree;	// free later when not NULL
40     int		bv_len;		// length of bv_string
41     int		bv_allocated;	// bv_string was allocated
42 } bval_T;
43 
44 #if defined(FEAT_VIMINFO) || defined(PROTO)
45 
46 static int  viminfo_errcnt;
47 
48 /*
49  * Find the parameter represented by the given character (eg ''', ':', '"', or
50  * '/') in the 'viminfo' option and return a pointer to the string after it.
51  * Return NULL if the parameter is not specified in the string.
52  */
53     static char_u *
find_viminfo_parameter(int type)54 find_viminfo_parameter(int type)
55 {
56     char_u  *p;
57 
58     for (p = p_viminfo; *p; ++p)
59     {
60 	if (*p == type)
61 	    return p + 1;
62 	if (*p == 'n')		    // 'n' is always the last one
63 	    break;
64 	p = vim_strchr(p, ',');	    // skip until next ','
65 	if (p == NULL)		    // hit the end without finding parameter
66 	    break;
67     }
68     return NULL;
69 }
70 
71 /*
72  * Find the parameter represented by the given character (eg ', :, ", or /),
73  * and return its associated value in the 'viminfo' string.
74  * Only works for number parameters, not for 'r' or 'n'.
75  * If the parameter is not specified in the string or there is no following
76  * number, return -1.
77  */
78     int
get_viminfo_parameter(int type)79 get_viminfo_parameter(int type)
80 {
81     char_u  *p;
82 
83     p = find_viminfo_parameter(type);
84     if (p != NULL && VIM_ISDIGIT(*p))
85 	return atoi((char *)p);
86     return -1;
87 }
88 
89 /*
90  * Get the viminfo file name to use.
91  * If "file" is given and not empty, use it (has already been expanded by
92  * cmdline functions).
93  * Otherwise use "-i file_name", value from 'viminfo' or the default, and
94  * expand environment variables.
95  * Returns an allocated string.  NULL when out of memory.
96  */
97     static char_u *
viminfo_filename(char_u * file)98 viminfo_filename(char_u *file)
99 {
100     if (file == NULL || *file == NUL)
101     {
102 	if (*p_viminfofile != NUL)
103 	    file = p_viminfofile;
104 	else if ((file = find_viminfo_parameter('n')) == NULL || *file == NUL)
105 	{
106 #ifdef VIMINFO_FILE2
107 # ifdef VMS
108 	    if (mch_getenv((char_u *)"SYS$LOGIN") == NULL)
109 # else
110 #  ifdef MSWIN
111 	    // Use $VIM only if $HOME is the default "C:/".
112 	    if (STRCMP(vim_getenv((char_u *)"HOME", NULL), "C:/") == 0
113 		    && mch_getenv((char_u *)"HOME") == NULL)
114 #  else
115 	    if (mch_getenv((char_u *)"HOME") == NULL)
116 #  endif
117 # endif
118 	    {
119 		// don't use $VIM when not available.
120 		expand_env((char_u *)"$VIM", NameBuff, MAXPATHL);
121 		if (STRCMP("$VIM", NameBuff) != 0)  // $VIM was expanded
122 		    file = (char_u *)VIMINFO_FILE2;
123 		else
124 		    file = (char_u *)VIMINFO_FILE;
125 	    }
126 	    else
127 #endif
128 		file = (char_u *)VIMINFO_FILE;
129 	}
130 	expand_env(file, NameBuff, MAXPATHL);
131 	file = NameBuff;
132     }
133     return vim_strsave(file);
134 }
135 
136 /*
137  * write string to viminfo file
138  * - replace CTRL-V with CTRL-V CTRL-V
139  * - replace '\n'   with CTRL-V 'n'
140  * - add a '\n' at the end
141  *
142  * For a long line:
143  * - write " CTRL-V <length> \n " in first line
144  * - write " < <string> \n "	  in second line
145  */
146     static void
viminfo_writestring(FILE * fd,char_u * p)147 viminfo_writestring(FILE *fd, char_u *p)
148 {
149     int		c;
150     char_u	*s;
151     int		len = 0;
152 
153     for (s = p; *s != NUL; ++s)
154     {
155 	if (*s == Ctrl_V || *s == '\n')
156 	    ++len;
157 	++len;
158     }
159 
160     // If the string will be too long, write its length and put it in the next
161     // line.  Take into account that some room is needed for what comes before
162     // the string (e.g., variable name).  Add something to the length for the
163     // '<', NL and trailing NUL.
164     if (len > LSIZE / 2)
165 	fprintf(fd, IF_EB("\026%d\n<", CTRL_V_STR "%d\n<"), len + 3);
166 
167     while ((c = *p++) != NUL)
168     {
169 	if (c == Ctrl_V || c == '\n')
170 	{
171 	    putc(Ctrl_V, fd);
172 	    if (c == '\n')
173 		c = 'n';
174 	}
175 	putc(c, fd);
176     }
177     putc('\n', fd);
178 }
179 
180 /*
181  * Write a string in quotes that barline_parse() can read back.
182  * Breaks the line in less than LSIZE pieces when needed.
183  * Returns remaining characters in the line.
184  */
185     static int
barline_writestring(FILE * fd,char_u * s,int remaining_start)186 barline_writestring(FILE *fd, char_u *s, int remaining_start)
187 {
188     char_u *p;
189     int	    remaining = remaining_start;
190     int	    len = 2;
191 
192     // Count the number of characters produced, including quotes.
193     for (p = s; *p != NUL; ++p)
194     {
195 	if (*p == NL)
196 	    len += 2;
197 	else if (*p == '"' || *p == '\\')
198 	    len += 2;
199 	else
200 	    ++len;
201     }
202     if (len > remaining - 2)
203     {
204 	fprintf(fd, ">%d\n|<", len);
205 	remaining = LSIZE - 20;
206     }
207 
208     putc('"', fd);
209     for (p = s; *p != NUL; ++p)
210     {
211 	if (*p == NL)
212 	{
213 	    putc('\\', fd);
214 	    putc('n', fd);
215 	    --remaining;
216 	}
217 	else if (*p == '"' || *p == '\\')
218 	{
219 	    putc('\\', fd);
220 	    putc(*p, fd);
221 	    --remaining;
222 	}
223 	else
224 	    putc(*p, fd);
225 	--remaining;
226 
227 	if (remaining < 3)
228 	{
229 	    putc('\n', fd);
230 	    putc('|', fd);
231 	    putc('<', fd);
232 	    // Leave enough space for another continuation.
233 	    remaining = LSIZE - 20;
234 	}
235     }
236     putc('"', fd);
237     return remaining - 2;
238 }
239 
240 /*
241  * Check string read from viminfo file.
242  * Remove '\n' at the end of the line.
243  * - replace CTRL-V CTRL-V with CTRL-V
244  * - replace CTRL-V 'n'    with '\n'
245  *
246  * Check for a long line as written by viminfo_writestring().
247  *
248  * Return the string in allocated memory (NULL when out of memory).
249  */
250     static char_u *
viminfo_readstring(vir_T * virp,int off,int convert UNUSED)251 viminfo_readstring(
252     vir_T	*virp,
253     int		off,		    // offset for virp->vir_line
254     int		convert UNUSED)	    // convert the string
255 {
256     char_u	*retval = NULL;
257     char_u	*s, *d;
258     long	len;
259 
260     if (virp->vir_line[off] == Ctrl_V && vim_isdigit(virp->vir_line[off + 1]))
261     {
262 	len = atol((char *)virp->vir_line + off + 1);
263 	if (len > 0 && len < 1000000)
264 	    retval = lalloc(len, TRUE);
265 	if (retval == NULL)
266 	{
267 	    // Invalid length, line too long, out of memory?  Skip next line.
268 	    (void)vim_fgets(virp->vir_line, 10, virp->vir_fd);
269 	    return NULL;
270 	}
271 	(void)vim_fgets(retval, (int)len, virp->vir_fd);
272 	s = retval + 1;	    // Skip the leading '<'
273     }
274     else
275     {
276 	retval = vim_strsave(virp->vir_line + off);
277 	if (retval == NULL)
278 	    return NULL;
279 	s = retval;
280     }
281 
282     // Change CTRL-V CTRL-V to CTRL-V and CTRL-V n to \n in-place.
283     d = retval;
284     while (*s != NUL && *s != '\n')
285     {
286 	if (s[0] == Ctrl_V && s[1] != NUL)
287 	{
288 	    if (s[1] == 'n')
289 		*d++ = '\n';
290 	    else
291 		*d++ = Ctrl_V;
292 	    s += 2;
293 	}
294 	else
295 	    *d++ = *s++;
296     }
297     *d = NUL;
298 
299     if (convert && virp->vir_conv.vc_type != CONV_NONE && *retval != NUL)
300     {
301 	d = string_convert(&virp->vir_conv, retval, NULL);
302 	if (d != NULL)
303 	{
304 	    vim_free(retval);
305 	    retval = d;
306 	}
307     }
308 
309     return retval;
310 }
311 
312 /*
313  * Read a line from the viminfo file.
314  * Returns TRUE for end-of-file;
315  */
316     static int
viminfo_readline(vir_T * virp)317 viminfo_readline(vir_T *virp)
318 {
319     return vim_fgets(virp->vir_line, LSIZE, virp->vir_fd);
320 }
321 
322     static int
read_viminfo_bufferlist(vir_T * virp,int writing)323 read_viminfo_bufferlist(
324     vir_T	*virp,
325     int		writing)
326 {
327     char_u	*tab;
328     linenr_T	lnum;
329     colnr_T	col;
330     buf_T	*buf;
331     char_u	*sfname;
332     char_u	*xline;
333 
334     // Handle long line and escaped characters.
335     xline = viminfo_readstring(virp, 1, FALSE);
336 
337     // don't read in if there are files on the command-line or if writing:
338     if (xline != NULL && !writing && ARGCOUNT == 0
339 				       && find_viminfo_parameter('%') != NULL)
340     {
341 	// Format is: <fname> Tab <lnum> Tab <col>.
342 	// Watch out for a Tab in the file name, work from the end.
343 	lnum = 0;
344 	col = 0;
345 	tab = vim_strrchr(xline, '\t');
346 	if (tab != NULL)
347 	{
348 	    *tab++ = '\0';
349 	    col = (colnr_T)atoi((char *)tab);
350 	    tab = vim_strrchr(xline, '\t');
351 	    if (tab != NULL)
352 	    {
353 		*tab++ = '\0';
354 		lnum = atol((char *)tab);
355 	    }
356 	}
357 
358 	// Expand "~/" in the file name at "line + 1" to a full path.
359 	// Then try shortening it by comparing with the current directory
360 	expand_env(xline, NameBuff, MAXPATHL);
361 	sfname = shorten_fname1(NameBuff);
362 
363 	buf = buflist_new(NameBuff, sfname, (linenr_T)0, BLN_LISTED);
364 	if (buf != NULL)	// just in case...
365 	{
366 	    buf->b_last_cursor.lnum = lnum;
367 	    buf->b_last_cursor.col = col;
368 	    buflist_setfpos(buf, curwin, lnum, col, FALSE);
369 	}
370     }
371     vim_free(xline);
372 
373     return viminfo_readline(virp);
374 }
375 
376 /*
377  * Return TRUE if "name" is on removable media (depending on 'viminfo').
378  */
379     static int
removable(char_u * name)380 removable(char_u *name)
381 {
382     char_u  *p;
383     char_u  part[51];
384     int	    retval = FALSE;
385     size_t  n;
386 
387     name = home_replace_save(NULL, name);
388     if (name != NULL)
389     {
390 	for (p = p_viminfo; *p; )
391 	{
392 	    copy_option_part(&p, part, 51, ", ");
393 	    if (part[0] == 'r')
394 	    {
395 		n = STRLEN(part + 1);
396 		if (MB_STRNICMP(part + 1, name, n) == 0)
397 		{
398 		    retval = TRUE;
399 		    break;
400 		}
401 	    }
402 	}
403 	vim_free(name);
404     }
405     return retval;
406 }
407 
408     static void
write_viminfo_bufferlist(FILE * fp)409 write_viminfo_bufferlist(FILE *fp)
410 {
411     buf_T	*buf;
412     win_T	*win;
413     tabpage_T	*tp;
414     char_u	*line;
415     int		max_buffers;
416 
417     if (find_viminfo_parameter('%') == NULL)
418 	return;
419 
420     // Without a number -1 is returned: do all buffers.
421     max_buffers = get_viminfo_parameter('%');
422 
423     // Allocate room for the file name, lnum and col.
424 #define LINE_BUF_LEN (MAXPATHL + 40)
425     line = alloc(LINE_BUF_LEN);
426     if (line == NULL)
427 	return;
428 
429     FOR_ALL_TAB_WINDOWS(tp, win)
430 	set_last_cursor(win);
431 
432     fputs(_("\n# Buffer list:\n"), fp);
433     FOR_ALL_BUFFERS(buf)
434     {
435 	if (buf->b_fname == NULL
436 		|| !buf->b_p_bl
437 #ifdef FEAT_QUICKFIX
438 		|| bt_quickfix(buf)
439 #endif
440 #ifdef FEAT_TERMINAL
441 		|| bt_terminal(buf)
442 #endif
443 		|| removable(buf->b_ffname))
444 	    continue;
445 
446 	if (max_buffers-- == 0)
447 	    break;
448 	putc('%', fp);
449 	home_replace(NULL, buf->b_ffname, line, MAXPATHL, TRUE);
450 	vim_snprintf_add((char *)line, LINE_BUF_LEN, "\t%ld\t%d",
451 			(long)buf->b_last_cursor.lnum,
452 			buf->b_last_cursor.col);
453 	viminfo_writestring(fp, line);
454     }
455     vim_free(line);
456 }
457 
458 /*
459  * Buffers for history read from a viminfo file.  Only valid while reading.
460  */
461 static histentry_T *viminfo_history[HIST_COUNT] =
462 					       {NULL, NULL, NULL, NULL, NULL};
463 static int	viminfo_hisidx[HIST_COUNT] = {0, 0, 0, 0, 0};
464 static int	viminfo_hislen[HIST_COUNT] = {0, 0, 0, 0, 0};
465 static int	viminfo_add_at_front = FALSE;
466 
467 /*
468  * Translate a history type number to the associated character.
469  */
470     static int
hist_type2char(int type,int use_question)471 hist_type2char(
472     int	    type,
473     int	    use_question)	    // use '?' instead of '/'
474 {
475     if (type == HIST_CMD)
476 	return ':';
477     if (type == HIST_SEARCH)
478     {
479 	if (use_question)
480 	    return '?';
481 	else
482 	    return '/';
483     }
484     if (type == HIST_EXPR)
485 	return '=';
486     return '@';
487 }
488 
489 /*
490  * Prepare for reading the history from the viminfo file.
491  * This allocates history arrays to store the read history lines.
492  */
493     static void
prepare_viminfo_history(int asklen,int writing)494 prepare_viminfo_history(int asklen, int writing)
495 {
496     int	    i;
497     int	    num;
498     int	    type;
499     int	    len;
500     int	    hislen;
501 
502     init_history();
503     hislen = get_hislen();
504     viminfo_add_at_front = (asklen != 0 && !writing);
505     if (asklen > hislen)
506 	asklen = hislen;
507 
508     for (type = 0; type < HIST_COUNT; ++type)
509     {
510 	histentry_T *histentry = get_histentry(type);
511 
512 	// Count the number of empty spaces in the history list.  Entries read
513 	// from viminfo previously are also considered empty.  If there are
514 	// more spaces available than we request, then fill them up.
515 	for (i = 0, num = 0; i < hislen; i++)
516 	    if (histentry[i].hisstr == NULL || histentry[i].viminfo)
517 		num++;
518 	len = asklen;
519 	if (num > len)
520 	    len = num;
521 	if (len <= 0)
522 	    viminfo_history[type] = NULL;
523 	else
524 	    viminfo_history[type] = LALLOC_MULT(histentry_T, len);
525 	if (viminfo_history[type] == NULL)
526 	    len = 0;
527 	viminfo_hislen[type] = len;
528 	viminfo_hisidx[type] = 0;
529     }
530 }
531 
532 /*
533  * Accept a line from the viminfo, store it in the history array when it's
534  * new.
535  */
536     static int
read_viminfo_history(vir_T * virp,int writing)537 read_viminfo_history(vir_T *virp, int writing)
538 {
539     int		type;
540     long_u	len;
541     char_u	*val;
542     char_u	*p;
543 
544     type = hist_char2type(virp->vir_line[0]);
545     if (viminfo_hisidx[type] < viminfo_hislen[type])
546     {
547 	val = viminfo_readstring(virp, 1, TRUE);
548 	if (val != NULL && *val != NUL)
549 	{
550 	    int sep = (*val == ' ' ? NUL : *val);
551 
552 	    if (!in_history(type, val + (type == HIST_SEARCH),
553 					  viminfo_add_at_front, sep, writing))
554 	    {
555 		// Need to re-allocate to append the separator byte.
556 		len = STRLEN(val);
557 		p = alloc(len + 2);
558 		if (p != NULL)
559 		{
560 		    if (type == HIST_SEARCH)
561 		    {
562 			// Search entry: Move the separator from the first
563 			// column to after the NUL.
564 			mch_memmove(p, val + 1, (size_t)len);
565 			p[len] = sep;
566 		    }
567 		    else
568 		    {
569 			// Not a search entry: No separator in the viminfo
570 			// file, add a NUL separator.
571 			mch_memmove(p, val, (size_t)len + 1);
572 			p[len + 1] = NUL;
573 		    }
574 		    viminfo_history[type][viminfo_hisidx[type]].hisstr = p;
575 		    viminfo_history[type][viminfo_hisidx[type]].time_set = 0;
576 		    viminfo_history[type][viminfo_hisidx[type]].viminfo = TRUE;
577 		    viminfo_history[type][viminfo_hisidx[type]].hisnum = 0;
578 		    viminfo_hisidx[type]++;
579 		}
580 	    }
581 	}
582 	vim_free(val);
583     }
584     return viminfo_readline(virp);
585 }
586 
587 /*
588  * Accept a new style history line from the viminfo, store it in the history
589  * array when it's new.
590  */
591     static void
handle_viminfo_history(garray_T * values,int writing)592 handle_viminfo_history(
593 	garray_T    *values,
594 	int	    writing)
595 {
596     int		type;
597     long_u	len;
598     char_u	*val;
599     char_u	*p;
600     bval_T	*vp = (bval_T *)values->ga_data;
601 
602     // Check the format:
603     // |{bartype},{histtype},{timestamp},{separator},"text"
604     if (values->ga_len < 4
605 	    || vp[0].bv_type != BVAL_NR
606 	    || vp[1].bv_type != BVAL_NR
607 	    || (vp[2].bv_type != BVAL_NR && vp[2].bv_type != BVAL_EMPTY)
608 	    || vp[3].bv_type != BVAL_STRING)
609 	return;
610 
611     type = vp[0].bv_nr;
612     if (type >= HIST_COUNT)
613 	return;
614     if (viminfo_hisidx[type] < viminfo_hislen[type])
615     {
616 	val = vp[3].bv_string;
617 	if (val != NULL && *val != NUL)
618 	{
619 	    int sep = type == HIST_SEARCH && vp[2].bv_type == BVAL_NR
620 						      ? vp[2].bv_nr : NUL;
621 	    int idx;
622 	    int overwrite = FALSE;
623 
624 	    if (!in_history(type, val, viminfo_add_at_front, sep, writing))
625 	    {
626 		// If lines were written by an older Vim we need to avoid
627 		// getting duplicates. See if the entry already exists.
628 		for (idx = 0; idx < viminfo_hisidx[type]; ++idx)
629 		{
630 		    p = viminfo_history[type][idx].hisstr;
631 		    if (STRCMP(val, p) == 0
632 			  && (type != HIST_SEARCH || sep == p[STRLEN(p) + 1]))
633 		    {
634 			overwrite = TRUE;
635 			break;
636 		    }
637 		}
638 
639 		if (!overwrite)
640 		{
641 		    // Need to re-allocate to append the separator byte.
642 		    len = vp[3].bv_len;
643 		    p = alloc(len + 2);
644 		}
645 		else
646 		    len = 0; // for picky compilers
647 		if (p != NULL)
648 		{
649 		    viminfo_history[type][idx].time_set = vp[1].bv_nr;
650 		    if (!overwrite)
651 		    {
652 			mch_memmove(p, val, (size_t)len + 1);
653 			// Put the separator after the NUL.
654 			p[len + 1] = sep;
655 			viminfo_history[type][idx].hisstr = p;
656 			viminfo_history[type][idx].hisnum = 0;
657 			viminfo_history[type][idx].viminfo = TRUE;
658 			viminfo_hisidx[type]++;
659 		    }
660 		}
661 	    }
662 	}
663     }
664 }
665 
666 /*
667  * Concatenate history lines from viminfo after the lines typed in this Vim.
668  */
669     static void
concat_history(int type)670 concat_history(int type)
671 {
672     int		idx;
673     int		i;
674     int		hislen = get_hislen();
675     histentry_T *histentry = get_histentry(type);
676     int		*hisidx = get_hisidx(type);
677     int		*hisnum = get_hisnum(type);
678 
679     idx = *hisidx + viminfo_hisidx[type];
680     if (idx >= hislen)
681 	idx -= hislen;
682     else if (idx < 0)
683 	idx = hislen - 1;
684     if (viminfo_add_at_front)
685 	*hisidx = idx;
686     else
687     {
688 	if (*hisidx == -1)
689 	    *hisidx = hislen - 1;
690 	do
691 	{
692 	    if (histentry[idx].hisstr != NULL || histentry[idx].viminfo)
693 		break;
694 	    if (++idx == hislen)
695 		idx = 0;
696 	} while (idx != *hisidx);
697 	if (idx != *hisidx && --idx < 0)
698 	    idx = hislen - 1;
699     }
700     for (i = 0; i < viminfo_hisidx[type]; i++)
701     {
702 	vim_free(histentry[idx].hisstr);
703 	histentry[idx].hisstr = viminfo_history[type][i].hisstr;
704 	histentry[idx].viminfo = TRUE;
705 	histentry[idx].time_set = viminfo_history[type][i].time_set;
706 	if (--idx < 0)
707 	    idx = hislen - 1;
708     }
709     idx += 1;
710     idx %= hislen;
711     for (i = 0; i < viminfo_hisidx[type]; i++)
712     {
713 	histentry[idx++].hisnum = ++*hisnum;
714 	idx %= hislen;
715     }
716 }
717 
718     static int
sort_hist(const void * s1,const void * s2)719 sort_hist(const void *s1, const void *s2)
720 {
721     histentry_T *p1 = *(histentry_T **)s1;
722     histentry_T *p2 = *(histentry_T **)s2;
723 
724     if (p1->time_set < p2->time_set) return -1;
725     if (p1->time_set > p2->time_set) return 1;
726     return 0;
727 }
728 
729 /*
730  * Merge history lines from viminfo and lines typed in this Vim based on the
731  * timestamp;
732  */
733     static void
merge_history(int type)734 merge_history(int type)
735 {
736     int		max_len;
737     histentry_T **tot_hist;
738     histentry_T *new_hist;
739     int		i;
740     int		len;
741     int		hislen = get_hislen();
742     histentry_T *histentry = get_histentry(type);
743     int		*hisidx = get_hisidx(type);
744     int		*hisnum = get_hisnum(type);
745 
746     // Make one long list with all entries.
747     max_len = hislen + viminfo_hisidx[type];
748     tot_hist = ALLOC_MULT(histentry_T *, max_len);
749     new_hist = ALLOC_MULT(histentry_T, hislen);
750     if (tot_hist == NULL || new_hist == NULL)
751     {
752 	vim_free(tot_hist);
753 	vim_free(new_hist);
754 	return;
755     }
756     for (i = 0; i < viminfo_hisidx[type]; i++)
757 	tot_hist[i] = &viminfo_history[type][i];
758     len = i;
759     for (i = 0; i < hislen; i++)
760 	if (histentry[i].hisstr != NULL)
761 	    tot_hist[len++] = &histentry[i];
762 
763     // Sort the list on timestamp.
764     qsort((void *)tot_hist, (size_t)len, sizeof(histentry_T *), sort_hist);
765 
766     // Keep the newest ones.
767     for (i = 0; i < hislen; i++)
768     {
769 	if (i < len)
770 	{
771 	    new_hist[i] = *tot_hist[i];
772 	    tot_hist[i]->hisstr = NULL;
773 	    if (new_hist[i].hisnum == 0)
774 		new_hist[i].hisnum = ++*hisnum;
775 	}
776 	else
777 	    clear_hist_entry(&new_hist[i]);
778     }
779     *hisidx = (i < len ? i : len) - 1;
780 
781     // Free what is not kept.
782     for (i = 0; i < viminfo_hisidx[type]; i++)
783 	vim_free(viminfo_history[type][i].hisstr);
784     for (i = 0; i < hislen; i++)
785 	vim_free(histentry[i].hisstr);
786     vim_free(histentry);
787     set_histentry(type, new_hist);
788     vim_free(tot_hist);
789 }
790 
791 /*
792  * Finish reading history lines from viminfo.  Not used when writing viminfo.
793  */
794     static void
finish_viminfo_history(vir_T * virp)795 finish_viminfo_history(vir_T *virp)
796 {
797     int	type;
798     int merge = virp->vir_version >= VIMINFO_VERSION_WITH_HISTORY;
799 
800     for (type = 0; type < HIST_COUNT; ++type)
801     {
802 	if (get_histentry(type) == NULL)
803 	    continue;
804 
805 	if (merge)
806 	    merge_history(type);
807 	else
808 	    concat_history(type);
809 
810 	VIM_CLEAR(viminfo_history[type]);
811 	viminfo_hisidx[type] = 0;
812     }
813 }
814 
815 /*
816  * Write history to viminfo file in "fp".
817  * When "merge" is TRUE merge history lines with a previously read viminfo
818  * file, data is in viminfo_history[].
819  * When "merge" is FALSE just write all history lines.  Used for ":wviminfo!".
820  */
821     static void
write_viminfo_history(FILE * fp,int merge)822 write_viminfo_history(FILE *fp, int merge)
823 {
824     int	    i;
825     int	    type;
826     int	    num_saved;
827     int     round;
828     int	    hislen;
829 
830     init_history();
831     hislen = get_hislen();
832     if (hislen == 0)
833 	return;
834     for (type = 0; type < HIST_COUNT; ++type)
835     {
836 	histentry_T *histentry = get_histentry(type);
837 	int	    *hisidx = get_hisidx(type);
838 
839 	num_saved = get_viminfo_parameter(hist_type2char(type, FALSE));
840 	if (num_saved == 0)
841 	    continue;
842 	if (num_saved < 0)  // Use default
843 	    num_saved = hislen;
844 	fprintf(fp, _("\n# %s History (newest to oldest):\n"),
845 			    type == HIST_CMD ? _("Command Line") :
846 			    type == HIST_SEARCH ? _("Search String") :
847 			    type == HIST_EXPR ? _("Expression") :
848 			    type == HIST_INPUT ? _("Input Line") :
849 					_("Debug Line"));
850 	if (num_saved > hislen)
851 	    num_saved = hislen;
852 
853 	// Merge typed and viminfo history:
854 	// round 1: history of typed commands.
855 	// round 2: history from recently read viminfo.
856 	for (round = 1; round <= 2; ++round)
857 	{
858 	    if (round == 1)
859 		// start at newest entry, somewhere in the list
860 		i = *hisidx;
861 	    else if (viminfo_hisidx[type] > 0)
862 		// start at newest entry, first in the list
863 		i = 0;
864 	    else
865 		// empty list
866 		i = -1;
867 	    if (i >= 0)
868 		while (num_saved > 0
869 			&& !(round == 2 && i >= viminfo_hisidx[type]))
870 		{
871 		    char_u  *p;
872 		    time_t  timestamp;
873 		    int	    c = NUL;
874 
875 		    if (round == 1)
876 		    {
877 			p = histentry[i].hisstr;
878 			timestamp = histentry[i].time_set;
879 		    }
880 		    else
881 		    {
882 			p = viminfo_history[type] == NULL ? NULL
883 					    : viminfo_history[type][i].hisstr;
884 			timestamp = viminfo_history[type] == NULL ? 0
885 					  : viminfo_history[type][i].time_set;
886 		    }
887 
888 		    if (p != NULL && (round == 2
889 				       || !merge
890 				       || !histentry[i].viminfo))
891 		    {
892 			--num_saved;
893 			fputc(hist_type2char(type, TRUE), fp);
894 			// For the search history: put the separator in the
895 			// second column; use a space if there isn't one.
896 			if (type == HIST_SEARCH)
897 			{
898 			    c = p[STRLEN(p) + 1];
899 			    putc(c == NUL ? ' ' : c, fp);
900 			}
901 			viminfo_writestring(fp, p);
902 
903 			{
904 			    char    cbuf[NUMBUFLEN];
905 
906 			    // New style history with a bar line. Format:
907 			    // |{bartype},{histtype},{timestamp},{separator},"text"
908 			    if (c == NUL)
909 				cbuf[0] = NUL;
910 			    else
911 				sprintf(cbuf, "%d", c);
912 			    fprintf(fp, "|%d,%d,%ld,%s,", BARTYPE_HISTORY,
913 						 type, (long)timestamp, cbuf);
914 			    barline_writestring(fp, p, LSIZE - 20);
915 			    putc('\n', fp);
916 			}
917 		    }
918 		    if (round == 1)
919 		    {
920 			// Decrement index, loop around and stop when back at
921 			// the start.
922 			if (--i < 0)
923 			    i = hislen - 1;
924 			if (i == *hisidx)
925 			    break;
926 		    }
927 		    else
928 		    {
929 			// Increment index. Stop at the end in the while.
930 			++i;
931 		    }
932 		}
933 	}
934 	for (i = 0; i < viminfo_hisidx[type]; ++i)
935 	    if (viminfo_history[type] != NULL)
936 		vim_free(viminfo_history[type][i].hisstr);
937 	VIM_CLEAR(viminfo_history[type]);
938 	viminfo_hisidx[type] = 0;
939     }
940 }
941 
942     static void
write_viminfo_barlines(vir_T * virp,FILE * fp_out)943 write_viminfo_barlines(vir_T *virp, FILE *fp_out)
944 {
945     int		i;
946     garray_T	*gap = &virp->vir_barlines;
947     int		seen_useful = FALSE;
948     char	*line;
949 
950     if (gap->ga_len > 0)
951     {
952 	fputs(_("\n# Bar lines, copied verbatim:\n"), fp_out);
953 
954 	// Skip over continuation lines until seeing a useful line.
955 	for (i = 0; i < gap->ga_len; ++i)
956 	{
957 	    line = ((char **)(gap->ga_data))[i];
958 	    if (seen_useful || line[1] != '<')
959 	    {
960 		fputs(line, fp_out);
961 		seen_useful = TRUE;
962 	    }
963 	}
964     }
965 }
966 
967 /*
968  * Parse a viminfo line starting with '|'.
969  * Add each decoded value to "values".
970  * Returns TRUE if the next line is to be read after using the parsed values.
971  */
972     static int
barline_parse(vir_T * virp,char_u * text,garray_T * values)973 barline_parse(vir_T *virp, char_u *text, garray_T *values)
974 {
975     char_u  *p = text;
976     char_u  *nextp = NULL;
977     char_u  *buf = NULL;
978     bval_T  *value;
979     int	    i;
980     int	    allocated = FALSE;
981     int	    eof;
982     char_u  *sconv;
983     int	    converted;
984 
985     while (*p == ',')
986     {
987 	++p;
988 	if (ga_grow(values, 1) == FAIL)
989 	    break;
990 	value = (bval_T *)(values->ga_data) + values->ga_len;
991 
992 	if (*p == '>')
993 	{
994 	    // Need to read a continuation line.  Put strings in allocated
995 	    // memory, because virp->vir_line is overwritten.
996 	    if (!allocated)
997 	    {
998 		for (i = 0; i < values->ga_len; ++i)
999 		{
1000 		    bval_T  *vp = (bval_T *)(values->ga_data) + i;
1001 
1002 		    if (vp->bv_type == BVAL_STRING && !vp->bv_allocated)
1003 		    {
1004 			vp->bv_string = vim_strnsave(vp->bv_string, vp->bv_len);
1005 			vp->bv_allocated = TRUE;
1006 		    }
1007 		}
1008 		allocated = TRUE;
1009 	    }
1010 
1011 	    if (vim_isdigit(p[1]))
1012 	    {
1013 		size_t len;
1014 		size_t todo;
1015 		size_t n;
1016 
1017 		// String value was split into lines that are each shorter
1018 		// than LSIZE:
1019 		//     |{bartype},>{length of "{text}{text2}"}
1020 		//     |<"{text1}
1021 		//     |<{text2}",{value}
1022 		// Length includes the quotes.
1023 		++p;
1024 		len = getdigits(&p);
1025 		buf = alloc((int)(len + 1));
1026 		if (buf == NULL)
1027 		    return TRUE;
1028 		p = buf;
1029 		for (todo = len; todo > 0; todo -= n)
1030 		{
1031 		    eof = viminfo_readline(virp);
1032 		    if (eof || virp->vir_line[0] != '|'
1033 						  || virp->vir_line[1] != '<')
1034 		    {
1035 			// File was truncated or garbled. Read another line if
1036 			// this one starts with '|'.
1037 			vim_free(buf);
1038 			return eof || virp->vir_line[0] == '|';
1039 		    }
1040 		    // Get length of text, excluding |< and NL chars.
1041 		    n = STRLEN(virp->vir_line);
1042 		    while (n > 0 && (virp->vir_line[n - 1] == NL
1043 					     || virp->vir_line[n - 1] == CAR))
1044 			--n;
1045 		    n -= 2;
1046 		    if (n > todo)
1047 		    {
1048 			// more values follow after the string
1049 			nextp = virp->vir_line + 2 + todo;
1050 			n = todo;
1051 		    }
1052 		    mch_memmove(p, virp->vir_line + 2, n);
1053 		    p += n;
1054 		}
1055 		*p = NUL;
1056 		p = buf;
1057 	    }
1058 	    else
1059 	    {
1060 		// Line ending in ">" continues in the next line:
1061 		//     |{bartype},{lots of values},>
1062 		//     |<{value},{value}
1063 		eof = viminfo_readline(virp);
1064 		if (eof || virp->vir_line[0] != '|'
1065 					      || virp->vir_line[1] != '<')
1066 		    // File was truncated or garbled. Read another line if
1067 		    // this one starts with '|'.
1068 		    return eof || virp->vir_line[0] == '|';
1069 		p = virp->vir_line + 2;
1070 	    }
1071 	}
1072 
1073 	if (isdigit(*p))
1074 	{
1075 	    value->bv_type = BVAL_NR;
1076 	    value->bv_nr = getdigits(&p);
1077 	    ++values->ga_len;
1078 	}
1079 	else if (*p == '"')
1080 	{
1081 	    int	    len = 0;
1082 	    char_u  *s = p;
1083 
1084 	    // Unescape special characters in-place.
1085 	    ++p;
1086 	    while (*p != '"')
1087 	    {
1088 		if (*p == NL || *p == NUL)
1089 		    return TRUE;  // syntax error, drop the value
1090 		if (*p == '\\')
1091 		{
1092 		    ++p;
1093 		    if (*p == 'n')
1094 			s[len++] = '\n';
1095 		    else
1096 			s[len++] = *p;
1097 		    ++p;
1098 		}
1099 		else
1100 		    s[len++] = *p++;
1101 	    }
1102 	    ++p;
1103 	    s[len] = NUL;
1104 
1105 	    converted = FALSE;
1106 	    value->bv_tofree = NULL;
1107 	    if (virp->vir_conv.vc_type != CONV_NONE && *s != NUL)
1108 	    {
1109 		sconv = string_convert(&virp->vir_conv, s, NULL);
1110 		if (sconv != NULL)
1111 		{
1112 		    if (s == buf)
1113 			// the converted string is stored in bv_string and
1114 			// freed later, also need to free "buf" later
1115 			value->bv_tofree = buf;
1116 		    s = sconv;
1117 		    converted = TRUE;
1118 		}
1119 	    }
1120 
1121 	    // Need to copy in allocated memory if the string wasn't allocated
1122 	    // above and we did allocate before, thus vir_line may change.
1123 	    if (s != buf && allocated && !converted)
1124 		s = vim_strsave(s);
1125 	    value->bv_string = s;
1126 	    value->bv_type = BVAL_STRING;
1127 	    value->bv_len = len;
1128 	    value->bv_allocated = allocated || converted;
1129 	    ++values->ga_len;
1130 	    if (nextp != NULL)
1131 	    {
1132 		// values following a long string
1133 		p = nextp;
1134 		nextp = NULL;
1135 	    }
1136 	}
1137 	else if (*p == ',')
1138 	{
1139 	    value->bv_type = BVAL_EMPTY;
1140 	    ++values->ga_len;
1141 	}
1142 	else
1143 	    break;
1144     }
1145     return TRUE;
1146 }
1147 
1148     static void
write_viminfo_version(FILE * fp_out)1149 write_viminfo_version(FILE *fp_out)
1150 {
1151     fprintf(fp_out, "# Viminfo version\n|%d,%d\n\n",
1152 					    BARTYPE_VERSION, VIMINFO_VERSION);
1153 }
1154 
1155     static int
no_viminfo(void)1156 no_viminfo(void)
1157 {
1158     // "vim -i NONE" does not read or write a viminfo file
1159     return STRCMP(p_viminfofile, "NONE") == 0;
1160 }
1161 
1162 /*
1163  * Report an error for reading a viminfo file.
1164  * Count the number of errors.	When there are more than 10, return TRUE.
1165  */
1166     static int
viminfo_error(char * errnum,char * message,char_u * line)1167 viminfo_error(char *errnum, char *message, char_u *line)
1168 {
1169     vim_snprintf((char *)IObuff, IOSIZE, _("%sviminfo: %s in line: "),
1170 							     errnum, message);
1171     STRNCAT(IObuff, line, IOSIZE - STRLEN(IObuff) - 1);
1172     if (IObuff[STRLEN(IObuff) - 1] == '\n')
1173 	IObuff[STRLEN(IObuff) - 1] = NUL;
1174     emsg((char *)IObuff);
1175     if (++viminfo_errcnt >= 10)
1176     {
1177 	emsg(_("E136: viminfo: Too many errors, skipping rest of file"));
1178 	return TRUE;
1179     }
1180     return FALSE;
1181 }
1182 
1183 /*
1184  * Compare the 'encoding' value in the viminfo file with the current value of
1185  * 'encoding'.  If different and the 'c' flag is in 'viminfo', setup for
1186  * conversion of text with iconv() in viminfo_readstring().
1187  */
1188     static int
viminfo_encoding(vir_T * virp)1189 viminfo_encoding(vir_T *virp)
1190 {
1191     char_u	*p;
1192     int		i;
1193 
1194     if (get_viminfo_parameter('c') != 0)
1195     {
1196 	p = vim_strchr(virp->vir_line, '=');
1197 	if (p != NULL)
1198 	{
1199 	    // remove trailing newline
1200 	    ++p;
1201 	    for (i = 0; vim_isprintc(p[i]); ++i)
1202 		;
1203 	    p[i] = NUL;
1204 
1205 	    convert_setup(&virp->vir_conv, p, p_enc);
1206 	}
1207     }
1208     return viminfo_readline(virp);
1209 }
1210 
1211 #if defined(FEAT_EVAL) || defined(PROTO)
1212 /*
1213  * Restore global vars that start with a capital from the viminfo file
1214  */
1215     static int
read_viminfo_varlist(vir_T * virp,int writing)1216 read_viminfo_varlist(vir_T *virp, int writing)
1217 {
1218     char_u	*tab;
1219     int		type = VAR_NUMBER;
1220     typval_T	tv;
1221     funccal_entry_T funccal_entry;
1222 
1223     if (!writing && (find_viminfo_parameter('!') != NULL))
1224     {
1225 	tab = vim_strchr(virp->vir_line + 1, '\t');
1226 	if (tab != NULL)
1227 	{
1228 	    *tab++ = '\0';	// isolate the variable name
1229 	    switch (*tab)
1230 	    {
1231 		case 'S': type = VAR_STRING; break;
1232 #ifdef FEAT_FLOAT
1233 		case 'F': type = VAR_FLOAT; break;
1234 #endif
1235 		case 'D': type = VAR_DICT; break;
1236 		case 'L': type = VAR_LIST; break;
1237 		case 'B': type = VAR_BLOB; break;
1238 		case 'X': type = VAR_SPECIAL; break;
1239 	    }
1240 
1241 	    tab = vim_strchr(tab, '\t');
1242 	    if (tab != NULL)
1243 	    {
1244 		tv.v_type = type;
1245 		if (type == VAR_STRING || type == VAR_DICT
1246 			|| type == VAR_LIST || type == VAR_BLOB)
1247 		    tv.vval.v_string = viminfo_readstring(virp,
1248 				       (int)(tab - virp->vir_line + 1), TRUE);
1249 #ifdef FEAT_FLOAT
1250 		else if (type == VAR_FLOAT)
1251 		    (void)string2float(tab + 1, &tv.vval.v_float, FALSE);
1252 #endif
1253 		else
1254 		{
1255 		    tv.vval.v_number = atol((char *)tab + 1);
1256 		    if (type == VAR_SPECIAL && (tv.vval.v_number == VVAL_FALSE
1257 					     || tv.vval.v_number == VVAL_TRUE))
1258 			tv.v_type = VAR_BOOL;
1259 		}
1260 		if (type == VAR_DICT || type == VAR_LIST)
1261 		{
1262 		    typval_T *etv = eval_expr(tv.vval.v_string, NULL);
1263 
1264 		    if (etv == NULL)
1265 			// Failed to parse back the dict or list, use it as a
1266 			// string.
1267 			tv.v_type = VAR_STRING;
1268 		    else
1269 		    {
1270 			vim_free(tv.vval.v_string);
1271 			tv = *etv;
1272 			vim_free(etv);
1273 		    }
1274 		}
1275 		else if (type == VAR_BLOB)
1276 		{
1277 		    blob_T *blob = string2blob(tv.vval.v_string);
1278 
1279 		    if (blob == NULL)
1280 			// Failed to parse back the blob, use it as a string.
1281 			tv.v_type = VAR_STRING;
1282 		    else
1283 		    {
1284 			vim_free(tv.vval.v_string);
1285 			tv.v_type = VAR_BLOB;
1286 			tv.vval.v_blob = blob;
1287 		    }
1288 		}
1289 
1290 		// when in a function use global variables
1291 		save_funccal(&funccal_entry);
1292 		set_var(virp->vir_line + 1, &tv, FALSE);
1293 		restore_funccal();
1294 
1295 		if (tv.v_type == VAR_STRING)
1296 		    vim_free(tv.vval.v_string);
1297 		else if (tv.v_type == VAR_DICT || tv.v_type == VAR_LIST ||
1298 			tv.v_type == VAR_BLOB)
1299 		    clear_tv(&tv);
1300 	    }
1301 	}
1302     }
1303 
1304     return viminfo_readline(virp);
1305 }
1306 
1307 /*
1308  * Write global vars that start with a capital to the viminfo file
1309  */
1310     static void
write_viminfo_varlist(FILE * fp)1311 write_viminfo_varlist(FILE *fp)
1312 {
1313     hashtab_T	*gvht = get_globvar_ht();
1314     hashitem_T	*hi;
1315     dictitem_T	*this_var;
1316     int		todo;
1317     char	*s = "";
1318     char_u	*p;
1319     char_u	*tofree;
1320     char_u	numbuf[NUMBUFLEN];
1321 
1322     if (find_viminfo_parameter('!') == NULL)
1323 	return;
1324 
1325     fputs(_("\n# global variables:\n"), fp);
1326 
1327     todo = (int)gvht->ht_used;
1328     for (hi = gvht->ht_array; todo > 0; ++hi)
1329     {
1330 	if (!HASHITEM_EMPTY(hi))
1331 	{
1332 	    --todo;
1333 	    this_var = HI2DI(hi);
1334 	    if (var_flavour(this_var->di_key) == VAR_FLAVOUR_VIMINFO)
1335 	    {
1336 		switch (this_var->di_tv.v_type)
1337 		{
1338 		    case VAR_STRING:  s = "STR"; break;
1339 		    case VAR_NUMBER:  s = "NUM"; break;
1340 		    case VAR_FLOAT:   s = "FLO"; break;
1341 		    case VAR_DICT:
1342 			  {
1343 			      dict_T	*di = this_var->di_tv.vval.v_dict;
1344 			      int	copyID = get_copyID();
1345 
1346 			      s = "DIC";
1347 			      if (di != NULL && !set_ref_in_ht(
1348 						 &di->dv_hashtab, copyID, NULL)
1349 				      && di->dv_copyID == copyID)
1350 				  // has a circular reference, can't turn the
1351 				  // value into a string
1352 				  continue;
1353 			      break;
1354 			  }
1355 		    case VAR_LIST:
1356 			  {
1357 			      list_T	*l = this_var->di_tv.vval.v_list;
1358 			      int	copyID = get_copyID();
1359 
1360 			      s = "LIS";
1361 			      if (l != NULL && !set_ref_in_list_items(
1362 							       l, copyID, NULL)
1363 				      && l->lv_copyID == copyID)
1364 				  // has a circular reference, can't turn the
1365 				  // value into a string
1366 				  continue;
1367 			      break;
1368 			  }
1369 		    case VAR_BLOB:    s = "BLO"; break;
1370 		    case VAR_BOOL:    s = "XPL"; break;  // backwards compat.
1371 		    case VAR_SPECIAL: s = "XPL"; break;
1372 
1373 		    case VAR_UNKNOWN:
1374 		    case VAR_ANY:
1375 		    case VAR_VOID:
1376 		    case VAR_FUNC:
1377 		    case VAR_PARTIAL:
1378 		    case VAR_JOB:
1379 		    case VAR_CHANNEL:
1380 		    case VAR_INSTR:
1381 				     continue;
1382 		}
1383 		fprintf(fp, "!%s\t%s\t", this_var->di_key, s);
1384 		if (this_var->di_tv.v_type == VAR_BOOL
1385 				      || this_var->di_tv.v_type == VAR_SPECIAL)
1386 		{
1387 		    // do not use "v:true" but "1"
1388 		    sprintf((char *)numbuf, "%ld",
1389 					  (long)this_var->di_tv.vval.v_number);
1390 		    p = numbuf;
1391 		    tofree = NULL;
1392 		}
1393 		else
1394 		    p = echo_string(&this_var->di_tv, &tofree, numbuf, 0);
1395 		if (p != NULL)
1396 		    viminfo_writestring(fp, p);
1397 		vim_free(tofree);
1398 	    }
1399 	}
1400     }
1401 }
1402 #endif // FEAT_EVAL
1403 
1404     static int
read_viminfo_sub_string(vir_T * virp,int force)1405 read_viminfo_sub_string(vir_T *virp, int force)
1406 {
1407     if (force || get_old_sub() == NULL)
1408 	set_old_sub(viminfo_readstring(virp, 1, TRUE));
1409     return viminfo_readline(virp);
1410 }
1411 
1412     static void
write_viminfo_sub_string(FILE * fp)1413 write_viminfo_sub_string(FILE *fp)
1414 {
1415     char_u *old_sub = get_old_sub();
1416 
1417     if (get_viminfo_parameter('/') != 0 && old_sub != NULL)
1418     {
1419 	fputs(_("\n# Last Substitute String:\n$"), fp);
1420 	viminfo_writestring(fp, old_sub);
1421     }
1422 }
1423 
1424 /*
1425  * Functions relating to reading/writing the search pattern from viminfo
1426  */
1427 
1428     static int
read_viminfo_search_pattern(vir_T * virp,int force)1429 read_viminfo_search_pattern(vir_T *virp, int force)
1430 {
1431     char_u	*lp;
1432     int		idx = -1;
1433     int		magic = FALSE;
1434     int		no_scs = FALSE;
1435     int		off_line = FALSE;
1436     int		off_end = 0;
1437     long	off = 0;
1438     int		setlast = FALSE;
1439 #ifdef FEAT_SEARCH_EXTRA
1440     static int	hlsearch_on = FALSE;
1441 #endif
1442     char_u	*val;
1443     spat_T	*spat;
1444 
1445     // Old line types:
1446     // "/pat", "&pat": search/subst. pat
1447     // "~/pat", "~&pat": last used search/subst. pat
1448     // New line types:
1449     // "~h", "~H": hlsearch highlighting off/on
1450     // "~<magic><smartcase><line><end><off><last><which>pat"
1451     // <magic>: 'm' off, 'M' on
1452     // <smartcase>: 's' off, 'S' on
1453     // <line>: 'L' line offset, 'l' char offset
1454     // <end>: 'E' from end, 'e' from start
1455     // <off>: decimal, offset
1456     // <last>: '~' last used pattern
1457     // <which>: '/' search pat, '&' subst. pat
1458     lp = virp->vir_line;
1459     if (lp[0] == '~' && (lp[1] == 'm' || lp[1] == 'M'))	// new line type
1460     {
1461 	if (lp[1] == 'M')		// magic on
1462 	    magic = TRUE;
1463 	if (lp[2] == 's')
1464 	    no_scs = TRUE;
1465 	if (lp[3] == 'L')
1466 	    off_line = TRUE;
1467 	if (lp[4] == 'E')
1468 	    off_end = SEARCH_END;
1469 	lp += 5;
1470 	off = getdigits(&lp);
1471     }
1472     if (lp[0] == '~')		// use this pattern for last-used pattern
1473     {
1474 	setlast = TRUE;
1475 	lp++;
1476     }
1477     if (lp[0] == '/')
1478 	idx = RE_SEARCH;
1479     else if (lp[0] == '&')
1480 	idx = RE_SUBST;
1481 #ifdef FEAT_SEARCH_EXTRA
1482     else if (lp[0] == 'h')	// ~h: 'hlsearch' highlighting off
1483 	hlsearch_on = FALSE;
1484     else if (lp[0] == 'H')	// ~H: 'hlsearch' highlighting on
1485 	hlsearch_on = TRUE;
1486 #endif
1487     if (idx >= 0)
1488     {
1489 	spat = get_spat(idx);
1490 	if (force || spat->pat == NULL)
1491 	{
1492 	    val = viminfo_readstring(virp, (int)(lp - virp->vir_line + 1),
1493 									TRUE);
1494 	    if (val != NULL)
1495 	    {
1496 		set_last_search_pat(val, idx, magic, setlast);
1497 		vim_free(val);
1498 		spat->no_scs = no_scs;
1499 		spat->off.line = off_line;
1500 		spat->off.end = off_end;
1501 		spat->off.off = off;
1502 #ifdef FEAT_SEARCH_EXTRA
1503 		if (setlast)
1504 		    set_no_hlsearch(!hlsearch_on);
1505 #endif
1506 	    }
1507 	}
1508     }
1509     return viminfo_readline(virp);
1510 }
1511 
1512     static void
wvsp_one(FILE * fp,int idx,char * s,int sc)1513 wvsp_one(
1514     FILE	*fp,	// file to write to
1515     int		idx,	// spats[] index
1516     char	*s,	// search pat
1517     int		sc)	// dir char
1518 {
1519     spat_T	*spat = get_spat(idx);
1520     if (spat->pat != NULL)
1521     {
1522 	fprintf(fp, _("\n# Last %sSearch Pattern:\n~"), s);
1523 	// off.dir is not stored, it's reset to forward
1524 	fprintf(fp, "%c%c%c%c%ld%s%c",
1525 		spat->magic    ? 'M' : 'm',	// magic
1526 		spat->no_scs   ? 's' : 'S',	// smartcase
1527 		spat->off.line ? 'L' : 'l',	// line offset
1528 		spat->off.end  ? 'E' : 'e',	// offset from end
1529 		spat->off.off,			// offset
1530 		get_spat_last_idx() == idx ? "~" : "",	// last used pat
1531 		sc);
1532 	viminfo_writestring(fp, spat->pat);
1533     }
1534 }
1535 
1536     static void
write_viminfo_search_pattern(FILE * fp)1537 write_viminfo_search_pattern(FILE *fp)
1538 {
1539     if (get_viminfo_parameter('/') != 0)
1540     {
1541 #ifdef FEAT_SEARCH_EXTRA
1542 	fprintf(fp, "\n# hlsearch on (H) or off (h):\n~%c",
1543 	    (no_hlsearch || find_viminfo_parameter('h') != NULL) ? 'h' : 'H');
1544 #endif
1545 	wvsp_one(fp, RE_SEARCH, "", '/');
1546 	wvsp_one(fp, RE_SUBST, _("Substitute "), '&');
1547     }
1548 }
1549 
1550 /*
1551  * Functions relating to reading/writing registers from viminfo
1552  */
1553 
1554 static yankreg_T *y_read_regs = NULL;
1555 
1556 #define REG_PREVIOUS 1
1557 #define REG_EXEC 2
1558 
1559 /*
1560  * Prepare for reading viminfo registers when writing viminfo later.
1561  */
1562     static void
prepare_viminfo_registers(void)1563 prepare_viminfo_registers(void)
1564 {
1565      y_read_regs = ALLOC_CLEAR_MULT(yankreg_T, NUM_REGISTERS);
1566 }
1567 
1568     static void
finish_viminfo_registers(void)1569 finish_viminfo_registers(void)
1570 {
1571     int		i;
1572     int		j;
1573 
1574     if (y_read_regs != NULL)
1575     {
1576 	for (i = 0; i < NUM_REGISTERS; ++i)
1577 	    if (y_read_regs[i].y_array != NULL)
1578 	    {
1579 		for (j = 0; j < y_read_regs[i].y_size; j++)
1580 		    vim_free(y_read_regs[i].y_array[j]);
1581 		vim_free(y_read_regs[i].y_array);
1582 	    }
1583 	VIM_CLEAR(y_read_regs);
1584     }
1585 }
1586 
1587     static int
read_viminfo_register(vir_T * virp,int force)1588 read_viminfo_register(vir_T *virp, int force)
1589 {
1590     int		eof;
1591     int		do_it = TRUE;
1592     int		size;
1593     int		limit;
1594     int		i;
1595     int		set_prev = FALSE;
1596     char_u	*str;
1597     char_u	**array = NULL;
1598     int		new_type = MCHAR; // init to shut up compiler
1599     colnr_T	new_width = 0; // init to shut up compiler
1600     yankreg_T	*y_current_p;
1601 
1602     // We only get here (hopefully) if line[0] == '"'
1603     str = virp->vir_line + 1;
1604 
1605     // If the line starts with "" this is the y_previous register.
1606     if (*str == '"')
1607     {
1608 	set_prev = TRUE;
1609 	str++;
1610     }
1611 
1612     if (!ASCII_ISALNUM(*str) && *str != '-')
1613     {
1614 	if (viminfo_error("E577: ", _("Illegal register name"), virp->vir_line))
1615 	    return TRUE;	// too many errors, pretend end-of-file
1616 	do_it = FALSE;
1617     }
1618     get_yank_register(*str++, FALSE);
1619     y_current_p = get_y_current();
1620     if (!force && y_current_p->y_array != NULL)
1621 	do_it = FALSE;
1622 
1623     if (*str == '@')
1624     {
1625 	// "x@: register x used for @@
1626 	if (force || get_execreg_lastc() == NUL)
1627 	    set_execreg_lastc(str[-1]);
1628     }
1629 
1630     size = 0;
1631     limit = 100;	// Optimized for registers containing <= 100 lines
1632     if (do_it)
1633     {
1634 	// Build the new register in array[].
1635 	// y_array is kept as-is until done.
1636 	// The "do_it" flag is reset when something is wrong, in which case
1637 	// array[] needs to be freed.
1638 	if (set_prev)
1639 	    set_y_previous(y_current_p);
1640 	array = ALLOC_MULT(char_u *, limit);
1641 	str = skipwhite(skiptowhite(str));
1642 	if (STRNCMP(str, "CHAR", 4) == 0)
1643 	    new_type = MCHAR;
1644 	else if (STRNCMP(str, "BLOCK", 5) == 0)
1645 	    new_type = MBLOCK;
1646 	else
1647 	    new_type = MLINE;
1648 	// get the block width; if it's missing we get a zero, which is OK
1649 	str = skipwhite(skiptowhite(str));
1650 	new_width = getdigits(&str);
1651     }
1652 
1653     while (!(eof = viminfo_readline(virp))
1654 		    && (virp->vir_line[0] == TAB || virp->vir_line[0] == '<'))
1655     {
1656 	if (do_it)
1657 	{
1658 	    if (size == limit)
1659 	    {
1660 		char_u **new_array = (char_u **)
1661 					   alloc(limit * 2 * sizeof(char_u *));
1662 
1663 		if (new_array == NULL)
1664 		{
1665 		    do_it = FALSE;
1666 		    break;
1667 		}
1668 		for (i = 0; i < limit; i++)
1669 		    new_array[i] = array[i];
1670 		vim_free(array);
1671 		array = new_array;
1672 		limit *= 2;
1673 	    }
1674 	    str = viminfo_readstring(virp, 1, TRUE);
1675 	    if (str != NULL)
1676 		array[size++] = str;
1677 	    else
1678 		// error, don't store the result
1679 		do_it = FALSE;
1680 	}
1681     }
1682 
1683     if (do_it)
1684     {
1685 	// free y_array[]
1686 	for (i = 0; i < y_current_p->y_size; i++)
1687 	    vim_free(y_current_p->y_array[i]);
1688 	vim_free(y_current_p->y_array);
1689 
1690 	y_current_p->y_type = new_type;
1691 	y_current_p->y_width = new_width;
1692 	y_current_p->y_size = size;
1693 	y_current_p->y_time_set = 0;
1694 	if (size == 0)
1695 	{
1696 	    y_current_p->y_array = NULL;
1697 	}
1698 	else
1699 	{
1700 	    // Move the lines from array[] to y_array[].
1701 	    y_current_p->y_array = ALLOC_MULT(char_u *, size);
1702 	    for (i = 0; i < size; i++)
1703 	    {
1704 		if (y_current_p->y_array == NULL)
1705 		    vim_free(array[i]);
1706 		else
1707 		    y_current_p->y_array[i] = array[i];
1708 	    }
1709 	}
1710     }
1711     else
1712     {
1713 	// Free array[] if it was filled.
1714 	for (i = 0; i < size; i++)
1715 	    vim_free(array[i]);
1716     }
1717     vim_free(array);
1718 
1719     return eof;
1720 }
1721 
1722 /*
1723  * Accept a new style register line from the viminfo, store it when it's new.
1724  */
1725     static void
handle_viminfo_register(garray_T * values,int force)1726 handle_viminfo_register(garray_T *values, int force)
1727 {
1728     bval_T	*vp = (bval_T *)values->ga_data;
1729     int		flags;
1730     int		name;
1731     int		type;
1732     int		linecount;
1733     int		width;
1734     time_t	timestamp;
1735     yankreg_T	*y_ptr;
1736     yankreg_T	*y_regs_p = get_y_regs();
1737     int		i;
1738 
1739     // Check the format:
1740     // |{bartype},{flags},{name},{type},
1741     //      {linecount},{width},{timestamp},"line1","line2"
1742     if (values->ga_len < 6
1743 	    || vp[0].bv_type != BVAL_NR
1744 	    || vp[1].bv_type != BVAL_NR
1745 	    || vp[2].bv_type != BVAL_NR
1746 	    || vp[3].bv_type != BVAL_NR
1747 	    || vp[4].bv_type != BVAL_NR
1748 	    || vp[5].bv_type != BVAL_NR)
1749 	return;
1750     flags = vp[0].bv_nr;
1751     name = vp[1].bv_nr;
1752     if (name < 0 || name >= NUM_REGISTERS)
1753 	return;
1754     type = vp[2].bv_nr;
1755     if (type != MCHAR && type != MLINE && type != MBLOCK)
1756 	return;
1757     linecount = vp[3].bv_nr;
1758     if (values->ga_len < 6 + linecount)
1759 	return;
1760     width = vp[4].bv_nr;
1761     if (width < 0)
1762 	return;
1763 
1764     if (y_read_regs != NULL)
1765 	// Reading viminfo for merging and writing.  Store the register
1766 	// content, don't update the current registers.
1767 	y_ptr = &y_read_regs[name];
1768     else
1769 	y_ptr = &y_regs_p[name];
1770 
1771     // Do not overwrite unless forced or the timestamp is newer.
1772     timestamp = (time_t)vp[5].bv_nr;
1773     if (y_ptr->y_array != NULL && !force
1774 			 && (timestamp == 0 || y_ptr->y_time_set > timestamp))
1775 	return;
1776 
1777     if (y_ptr->y_array != NULL)
1778 	for (i = 0; i < y_ptr->y_size; i++)
1779 	    vim_free(y_ptr->y_array[i]);
1780     vim_free(y_ptr->y_array);
1781 
1782     if (y_read_regs == NULL)
1783     {
1784 	if (flags & REG_PREVIOUS)
1785 	    set_y_previous(y_ptr);
1786 	if ((flags & REG_EXEC) && (force || get_execreg_lastc() == NUL))
1787 	    set_execreg_lastc(get_register_name(name));
1788     }
1789     y_ptr->y_type = type;
1790     y_ptr->y_width = width;
1791     y_ptr->y_size = linecount;
1792     y_ptr->y_time_set = timestamp;
1793     if (linecount == 0)
1794     {
1795 	y_ptr->y_array = NULL;
1796 	return;
1797     }
1798     y_ptr->y_array = ALLOC_MULT(char_u *, linecount);
1799     if (y_ptr->y_array == NULL)
1800     {
1801 	y_ptr->y_size = 0; // ensure object state is consistent
1802 	return;
1803     }
1804     for (i = 0; i < linecount; i++)
1805     {
1806 	if (vp[i + 6].bv_allocated)
1807 	{
1808 	    y_ptr->y_array[i] = vp[i + 6].bv_string;
1809 	    vp[i + 6].bv_string = NULL;
1810 	}
1811 	else
1812 	    y_ptr->y_array[i] = vim_strsave(vp[i + 6].bv_string);
1813     }
1814 }
1815 
1816     static void
write_viminfo_registers(FILE * fp)1817 write_viminfo_registers(FILE *fp)
1818 {
1819     int		i, j;
1820     char_u	*type;
1821     char_u	c;
1822     int		num_lines;
1823     int		max_num_lines;
1824     int		max_kbyte;
1825     long	len;
1826     yankreg_T	*y_ptr;
1827     yankreg_T	*y_regs_p = get_y_regs();;
1828 
1829     fputs(_("\n# Registers:\n"), fp);
1830 
1831     // Get '<' value, use old '"' value if '<' is not found.
1832     max_num_lines = get_viminfo_parameter('<');
1833     if (max_num_lines < 0)
1834 	max_num_lines = get_viminfo_parameter('"');
1835     if (max_num_lines == 0)
1836 	return;
1837     max_kbyte = get_viminfo_parameter('s');
1838     if (max_kbyte == 0)
1839 	return;
1840 
1841     for (i = 0; i < NUM_REGISTERS; i++)
1842     {
1843 #ifdef FEAT_CLIPBOARD
1844 	// Skip '*'/'+' register, we don't want them back next time
1845 	if (i == STAR_REGISTER || i == PLUS_REGISTER)
1846 	    continue;
1847 #endif
1848 #ifdef FEAT_DND
1849 	// Neither do we want the '~' register
1850 	if (i == TILDE_REGISTER)
1851 	    continue;
1852 #endif
1853 	// When reading viminfo for merging and writing: Use the register from
1854 	// viminfo if it's newer.
1855 	if (y_read_regs != NULL
1856 		&& y_read_regs[i].y_array != NULL
1857 		&& (y_regs_p[i].y_array == NULL ||
1858 			    y_read_regs[i].y_time_set > y_regs_p[i].y_time_set))
1859 	    y_ptr = &y_read_regs[i];
1860 	else if (y_regs_p[i].y_array == NULL)
1861 	    continue;
1862 	else
1863 	    y_ptr = &y_regs_p[i];
1864 
1865 	// Skip empty registers.
1866 	num_lines = y_ptr->y_size;
1867 	if (num_lines == 0
1868 		|| (num_lines == 1 && y_ptr->y_type == MCHAR
1869 					&& *y_ptr->y_array[0] == NUL))
1870 	    continue;
1871 
1872 	if (max_kbyte > 0)
1873 	{
1874 	    // Skip register if there is more text than the maximum size.
1875 	    len = 0;
1876 	    for (j = 0; j < num_lines; j++)
1877 		len += (long)STRLEN(y_ptr->y_array[j]) + 1L;
1878 	    if (len > (long)max_kbyte * 1024L)
1879 		continue;
1880 	}
1881 
1882 	switch (y_ptr->y_type)
1883 	{
1884 	    case MLINE:
1885 		type = (char_u *)"LINE";
1886 		break;
1887 	    case MCHAR:
1888 		type = (char_u *)"CHAR";
1889 		break;
1890 	    case MBLOCK:
1891 		type = (char_u *)"BLOCK";
1892 		break;
1893 	    default:
1894 		semsg(_("E574: Unknown register type %d"), y_ptr->y_type);
1895 		type = (char_u *)"LINE";
1896 		break;
1897 	}
1898 	if (get_y_previous() == &y_regs_p[i])
1899 	    fprintf(fp, "\"");
1900 	c = get_register_name(i);
1901 	fprintf(fp, "\"%c", c);
1902 	if (c == get_execreg_lastc())
1903 	    fprintf(fp, "@");
1904 	fprintf(fp, "\t%s\t%d\n", type, (int)y_ptr->y_width);
1905 
1906 	// If max_num_lines < 0, then we save ALL the lines in the register
1907 	if (max_num_lines > 0 && num_lines > max_num_lines)
1908 	    num_lines = max_num_lines;
1909 	for (j = 0; j < num_lines; j++)
1910 	{
1911 	    putc('\t', fp);
1912 	    viminfo_writestring(fp, y_ptr->y_array[j]);
1913 	}
1914 
1915 	{
1916 	    int	    flags = 0;
1917 	    int	    remaining;
1918 
1919 	    // New style with a bar line. Format:
1920 	    // |{bartype},{flags},{name},{type},
1921 	    //      {linecount},{width},{timestamp},"line1","line2"
1922 	    // flags: REG_PREVIOUS - register is y_previous
1923 	    //	      REG_EXEC - used for @@
1924 	    if (get_y_previous() == &y_regs_p[i])
1925 		flags |= REG_PREVIOUS;
1926 	    if (c == get_execreg_lastc())
1927 		flags |= REG_EXEC;
1928 	    fprintf(fp, "|%d,%d,%d,%d,%d,%d,%ld", BARTYPE_REGISTER, flags,
1929 		    i, y_ptr->y_type, num_lines, (int)y_ptr->y_width,
1930 		    (long)y_ptr->y_time_set);
1931 	    // 11 chars for type/flags/name/type, 3 * 20 for numbers
1932 	    remaining = LSIZE - 71;
1933 	    for (j = 0; j < num_lines; j++)
1934 	    {
1935 		putc(',', fp);
1936 		--remaining;
1937 		remaining = barline_writestring(fp, y_ptr->y_array[j],
1938 								   remaining);
1939 	    }
1940 	    putc('\n', fp);
1941 	}
1942     }
1943 }
1944 
1945 /*
1946  * Functions relating to reading/writing marks from viminfo
1947  */
1948 
1949 static xfmark_T *vi_namedfm = NULL;
1950 #ifdef FEAT_JUMPLIST
1951 static xfmark_T *vi_jumplist = NULL;
1952 static int vi_jumplist_len = 0;
1953 #endif
1954 
1955     static void
write_one_mark(FILE * fp_out,int c,pos_T * pos)1956 write_one_mark(FILE *fp_out, int c, pos_T *pos)
1957 {
1958     if (pos->lnum != 0)
1959 	fprintf(fp_out, "\t%c\t%ld\t%d\n", c, (long)pos->lnum, (int)pos->col);
1960 }
1961 
1962     static void
write_buffer_marks(buf_T * buf,FILE * fp_out)1963 write_buffer_marks(buf_T *buf, FILE *fp_out)
1964 {
1965     int		i;
1966     pos_T	pos;
1967 
1968     home_replace(NULL, buf->b_ffname, IObuff, IOSIZE, TRUE);
1969     fprintf(fp_out, "\n> ");
1970     viminfo_writestring(fp_out, IObuff);
1971 
1972     // Write the last used timestamp as the lnum of the non-existing mark '*'.
1973     // Older Vims will ignore it and/or copy it.
1974     pos.lnum = (linenr_T)buf->b_last_used;
1975     pos.col = 0;
1976     write_one_mark(fp_out, '*', &pos);
1977 
1978     write_one_mark(fp_out, '"', &buf->b_last_cursor);
1979     write_one_mark(fp_out, '^', &buf->b_last_insert);
1980     write_one_mark(fp_out, '.', &buf->b_last_change);
1981 #ifdef FEAT_JUMPLIST
1982     // changelist positions are stored oldest first
1983     for (i = 0; i < buf->b_changelistlen; ++i)
1984     {
1985 	// skip duplicates
1986 	if (i == 0 || !EQUAL_POS(buf->b_changelist[i - 1],
1987 							 buf->b_changelist[i]))
1988 	    write_one_mark(fp_out, '+', &buf->b_changelist[i]);
1989     }
1990 #endif
1991     for (i = 0; i < NMARKS; i++)
1992 	write_one_mark(fp_out, 'a' + i, &buf->b_namedm[i]);
1993 }
1994 
1995 /*
1996  * Return TRUE if marks for "buf" should not be written.
1997  */
1998     static int
skip_for_viminfo(buf_T * buf)1999 skip_for_viminfo(buf_T *buf)
2000 {
2001     return
2002 #ifdef FEAT_TERMINAL
2003 	    bt_terminal(buf) ||
2004 #endif
2005 	    removable(buf->b_ffname);
2006 }
2007 
2008 /*
2009  * Write all the named marks for all buffers.
2010  * When "buflist" is not NULL fill it with the buffers for which marks are to
2011  * be written.
2012  */
2013     static void
write_viminfo_marks(FILE * fp_out,garray_T * buflist)2014 write_viminfo_marks(FILE *fp_out, garray_T *buflist)
2015 {
2016     buf_T	*buf;
2017     int		is_mark_set;
2018     int		i;
2019     win_T	*win;
2020     tabpage_T	*tp;
2021 
2022     // Set b_last_cursor for the all buffers that have a window.
2023     FOR_ALL_TAB_WINDOWS(tp, win)
2024 	set_last_cursor(win);
2025 
2026     fputs(_("\n# History of marks within files (newest to oldest):\n"), fp_out);
2027     FOR_ALL_BUFFERS(buf)
2028     {
2029 	// Only write something if buffer has been loaded and at least one
2030 	// mark is set.
2031 	if (buf->b_marks_read)
2032 	{
2033 	    if (buf->b_last_cursor.lnum != 0)
2034 		is_mark_set = TRUE;
2035 	    else
2036 	    {
2037 		is_mark_set = FALSE;
2038 		for (i = 0; i < NMARKS; i++)
2039 		    if (buf->b_namedm[i].lnum != 0)
2040 		    {
2041 			is_mark_set = TRUE;
2042 			break;
2043 		    }
2044 	    }
2045 	    if (is_mark_set && buf->b_ffname != NULL
2046 		      && buf->b_ffname[0] != NUL
2047 		      && !skip_for_viminfo(buf))
2048 	    {
2049 		if (buflist == NULL)
2050 		    write_buffer_marks(buf, fp_out);
2051 		else if (ga_grow(buflist, 1) == OK)
2052 		    ((buf_T **)buflist->ga_data)[buflist->ga_len++] = buf;
2053 	    }
2054 	}
2055     }
2056 }
2057 
2058     static void
write_one_filemark(FILE * fp,xfmark_T * fm,int c1,int c2)2059 write_one_filemark(
2060     FILE	*fp,
2061     xfmark_T	*fm,
2062     int		c1,
2063     int		c2)
2064 {
2065     char_u	*name;
2066 
2067     if (fm->fmark.mark.lnum == 0)	// not set
2068 	return;
2069 
2070     if (fm->fmark.fnum != 0)		// there is a buffer
2071 	name = buflist_nr2name(fm->fmark.fnum, TRUE, FALSE);
2072     else
2073 	name = fm->fname;		// use name from .viminfo
2074     if (name != NULL && *name != NUL)
2075     {
2076 	fprintf(fp, "%c%c  %ld  %ld  ", c1, c2, (long)fm->fmark.mark.lnum,
2077 						    (long)fm->fmark.mark.col);
2078 	viminfo_writestring(fp, name);
2079 
2080 	// Barline: |{bartype},{name},{lnum},{col},{timestamp},{filename}
2081 	// size up to filename: 8 + 3 * 20
2082 	fprintf(fp, "|%d,%d,%ld,%ld,%ld,", BARTYPE_MARK, c2,
2083 		(long)fm->fmark.mark.lnum, (long)fm->fmark.mark.col,
2084 		(long)fm->time_set);
2085 	barline_writestring(fp, name, LSIZE - 70);
2086 	putc('\n', fp);
2087     }
2088 
2089     if (fm->fmark.fnum != 0)
2090 	vim_free(name);
2091 }
2092 
2093     static void
write_viminfo_filemarks(FILE * fp)2094 write_viminfo_filemarks(FILE *fp)
2095 {
2096     int		i;
2097     char_u	*name;
2098     buf_T	*buf;
2099     xfmark_T	*namedfm_p = get_namedfm();
2100     xfmark_T	*fm;
2101     int		vi_idx;
2102     int		idx;
2103 
2104     if (get_viminfo_parameter('f') == 0)
2105 	return;
2106 
2107     fputs(_("\n# File marks:\n"), fp);
2108 
2109     // Write the filemarks 'A - 'Z
2110     for (i = 0; i < NMARKS; i++)
2111     {
2112 	if (vi_namedfm != NULL
2113 			&& (vi_namedfm[i].time_set > namedfm_p[i].time_set))
2114 	    fm = &vi_namedfm[i];
2115 	else
2116 	    fm = &namedfm_p[i];
2117 	write_one_filemark(fp, fm, '\'', i + 'A');
2118     }
2119 
2120     // Find a mark that is the same file and position as the cursor.
2121     // That one, or else the last one is deleted.
2122     // Move '0 to '1, '1 to '2, etc. until the matching one or '9
2123     // Set the '0 mark to current cursor position.
2124     if (curbuf->b_ffname != NULL && !skip_for_viminfo(curbuf))
2125     {
2126 	name = buflist_nr2name(curbuf->b_fnum, TRUE, FALSE);
2127 	for (i = NMARKS; i < NMARKS + EXTRA_MARKS - 1; ++i)
2128 	    if (namedfm_p[i].fmark.mark.lnum == curwin->w_cursor.lnum
2129 		    && (namedfm_p[i].fname == NULL
2130 			    ? namedfm_p[i].fmark.fnum == curbuf->b_fnum
2131 			    : (name != NULL
2132 				    && STRCMP(name, namedfm_p[i].fname) == 0)))
2133 		break;
2134 	vim_free(name);
2135 
2136 	vim_free(namedfm_p[i].fname);
2137 	for ( ; i > NMARKS; --i)
2138 	    namedfm_p[i] = namedfm_p[i - 1];
2139 	namedfm_p[NMARKS].fmark.mark = curwin->w_cursor;
2140 	namedfm_p[NMARKS].fmark.fnum = curbuf->b_fnum;
2141 	namedfm_p[NMARKS].fname = NULL;
2142 	namedfm_p[NMARKS].time_set = vim_time();
2143     }
2144 
2145     // Write the filemarks '0 - '9.  Newest (highest timestamp) first.
2146     vi_idx = NMARKS;
2147     idx = NMARKS;
2148     for (i = NMARKS; i < NMARKS + EXTRA_MARKS; i++)
2149     {
2150 	xfmark_T *vi_fm = vi_namedfm != NULL ? &vi_namedfm[vi_idx] : NULL;
2151 
2152 	if (vi_fm != NULL
2153 		&& vi_fm->fmark.mark.lnum != 0
2154 		&& (vi_fm->time_set > namedfm_p[idx].time_set
2155 		    || namedfm_p[idx].fmark.mark.lnum == 0))
2156 	{
2157 	    fm = vi_fm;
2158 	    ++vi_idx;
2159 	}
2160 	else
2161 	{
2162 	    fm = &namedfm_p[idx++];
2163 	    if (vi_fm != NULL
2164 		  && vi_fm->fmark.mark.lnum == fm->fmark.mark.lnum
2165 		  && vi_fm->time_set == fm->time_set
2166 		  && ((vi_fm->fmark.fnum != 0
2167 			  && vi_fm->fmark.fnum == fm->fmark.fnum)
2168 		      || (vi_fm->fname != NULL
2169 			  && fm->fname != NULL
2170 			  && STRCMP(vi_fm->fname, fm->fname) == 0)))
2171 		++vi_idx;  // skip duplicate
2172 	}
2173 	write_one_filemark(fp, fm, '\'', i - NMARKS + '0');
2174     }
2175 
2176 #ifdef FEAT_JUMPLIST
2177     // Write the jumplist with -'
2178     fputs(_("\n# Jumplist (newest first):\n"), fp);
2179     setpcmark();	// add current cursor position
2180     cleanup_jumplist(curwin, FALSE);
2181     vi_idx = 0;
2182     idx = curwin->w_jumplistlen - 1;
2183     for (i = 0; i < JUMPLISTSIZE; ++i)
2184     {
2185 	xfmark_T	*vi_fm;
2186 
2187 	fm = idx >= 0 ? &curwin->w_jumplist[idx] : NULL;
2188 	vi_fm = (vi_jumplist != NULL && vi_idx < vi_jumplist_len)
2189 					? &vi_jumplist[vi_idx] : NULL;
2190 	if (fm == NULL && vi_fm == NULL)
2191 	    break;
2192 	if (fm == NULL || (vi_fm != NULL && fm->time_set < vi_fm->time_set))
2193 	{
2194 	    fm = vi_fm;
2195 	    ++vi_idx;
2196 	}
2197 	else
2198 	    --idx;
2199 	if (fm->fmark.fnum == 0
2200 		|| ((buf = buflist_findnr(fm->fmark.fnum)) != NULL
2201 		    && !skip_for_viminfo(buf)))
2202 	    write_one_filemark(fp, fm, '-', '\'');
2203     }
2204 #endif
2205 }
2206 
2207 /*
2208  * Compare functions for qsort() below, that compares b_last_used.
2209  */
2210     int
buf_compare(const void * s1,const void * s2)2211 buf_compare(const void *s1, const void *s2)
2212 {
2213     buf_T *buf1 = *(buf_T **)s1;
2214     buf_T *buf2 = *(buf_T **)s2;
2215 
2216     if (buf1->b_last_used == buf2->b_last_used)
2217 	return 0;
2218     return buf1->b_last_used > buf2->b_last_used ? -1 : 1;
2219 }
2220 
2221 /*
2222  * Handle marks in the viminfo file:
2223  * fp_out != NULL: copy marks, in time order with buffers in "buflist".
2224  * fp_out == NULL && (flags & VIF_WANT_MARKS): read marks for curbuf
2225  * fp_out == NULL && (flags & VIF_ONLY_CURBUF): bail out after curbuf marks
2226  * fp_out == NULL && (flags & VIF_GET_OLDFILES | VIF_FORCEIT): fill v:oldfiles
2227  */
2228     static void
copy_viminfo_marks(vir_T * virp,FILE * fp_out,garray_T * buflist,int eof,int flags)2229 copy_viminfo_marks(
2230     vir_T	*virp,
2231     FILE	*fp_out,
2232     garray_T	*buflist,
2233     int		eof,
2234     int		flags)
2235 {
2236     char_u	*line = virp->vir_line;
2237     buf_T	*buf;
2238     int		num_marked_files;
2239     int		load_marks;
2240     int		copy_marks_out;
2241     char_u	*str;
2242     int		i;
2243     char_u	*p;
2244     char_u	*name_buf;
2245     pos_T	pos;
2246 #ifdef FEAT_EVAL
2247     list_T	*list = NULL;
2248 #endif
2249     int		count = 0;
2250     int		buflist_used = 0;
2251     buf_T	*buflist_buf = NULL;
2252 
2253     if ((name_buf = alloc(LSIZE)) == NULL)
2254 	return;
2255     *name_buf = NUL;
2256 
2257     if (fp_out != NULL && buflist->ga_len > 0)
2258     {
2259 	// Sort the list of buffers on b_last_used.
2260 	qsort(buflist->ga_data, (size_t)buflist->ga_len,
2261 						sizeof(buf_T *), buf_compare);
2262 	buflist_buf = ((buf_T **)buflist->ga_data)[0];
2263     }
2264 
2265 #ifdef FEAT_EVAL
2266     if (fp_out == NULL && (flags & (VIF_GET_OLDFILES | VIF_FORCEIT)))
2267     {
2268 	list = list_alloc();
2269 	if (list != NULL)
2270 	    set_vim_var_list(VV_OLDFILES, list);
2271     }
2272 #endif
2273 
2274     num_marked_files = get_viminfo_parameter('\'');
2275     while (!eof && (count < num_marked_files || fp_out == NULL))
2276     {
2277 	if (line[0] != '>')
2278 	{
2279 	    if (line[0] != '\n' && line[0] != '\r' && line[0] != '#')
2280 	    {
2281 		if (viminfo_error("E576: ", _("Missing '>'"), line))
2282 		    break;	// too many errors, return now
2283 	    }
2284 	    eof = vim_fgets(line, LSIZE, virp->vir_fd);
2285 	    continue;		// Skip this dud line
2286 	}
2287 
2288 	// Handle long line and translate escaped characters.
2289 	// Find file name, set str to start.
2290 	// Ignore leading and trailing white space.
2291 	str = skipwhite(line + 1);
2292 	str = viminfo_readstring(virp, (int)(str - virp->vir_line), FALSE);
2293 	if (str == NULL)
2294 	    continue;
2295 	p = str + STRLEN(str);
2296 	while (p != str && (*p == NUL || vim_isspace(*p)))
2297 	    p--;
2298 	if (*p)
2299 	    p++;
2300 	*p = NUL;
2301 
2302 #ifdef FEAT_EVAL
2303 	if (list != NULL)
2304 	    list_append_string(list, str, -1);
2305 #endif
2306 
2307 	// If fp_out == NULL, load marks for current buffer.
2308 	// If fp_out != NULL, copy marks for buffers not in buflist.
2309 	load_marks = copy_marks_out = FALSE;
2310 	if (fp_out == NULL)
2311 	{
2312 	    if ((flags & VIF_WANT_MARKS) && curbuf->b_ffname != NULL)
2313 	    {
2314 		if (*name_buf == NUL)	    // only need to do this once
2315 		    home_replace(NULL, curbuf->b_ffname, name_buf, LSIZE, TRUE);
2316 		if (fnamecmp(str, name_buf) == 0)
2317 		    load_marks = TRUE;
2318 	    }
2319 	}
2320 	else // fp_out != NULL
2321 	{
2322 	    // This is slow if there are many buffers!!
2323 	    FOR_ALL_BUFFERS(buf)
2324 		if (buf->b_ffname != NULL)
2325 		{
2326 		    home_replace(NULL, buf->b_ffname, name_buf, LSIZE, TRUE);
2327 		    if (fnamecmp(str, name_buf) == 0)
2328 			break;
2329 		}
2330 
2331 	    // Copy marks if the buffer has not been loaded.
2332 	    if (buf == NULL || !buf->b_marks_read)
2333 	    {
2334 		int	did_read_line = FALSE;
2335 
2336 		if (buflist_buf != NULL)
2337 		{
2338 		    // Read the next line.  If it has the "*" mark compare the
2339 		    // time stamps.  Write entries from "buflist" that are
2340 		    // newer.
2341 		    if (!(eof = viminfo_readline(virp)) && line[0] == TAB)
2342 		    {
2343 			did_read_line = TRUE;
2344 			if (line[1] == '*')
2345 			{
2346 			    long	ltime;
2347 
2348 			    sscanf((char *)line + 2, "%ld ", &ltime);
2349 			    while ((time_T)ltime < buflist_buf->b_last_used)
2350 			    {
2351 				write_buffer_marks(buflist_buf, fp_out);
2352 				if (++count >= num_marked_files)
2353 				    break;
2354 				if (++buflist_used == buflist->ga_len)
2355 				{
2356 				    buflist_buf = NULL;
2357 				    break;
2358 				}
2359 				buflist_buf =
2360 				   ((buf_T **)buflist->ga_data)[buflist_used];
2361 			    }
2362 			}
2363 			else
2364 			{
2365 			    // No timestamp, must be written by an older Vim.
2366 			    // Assume all remaining buffers are older than
2367 			    // ours.
2368 			    while (count < num_marked_files
2369 					    && buflist_used < buflist->ga_len)
2370 			    {
2371 				buflist_buf = ((buf_T **)buflist->ga_data)
2372 							     [buflist_used++];
2373 				write_buffer_marks(buflist_buf, fp_out);
2374 				++count;
2375 			    }
2376 			    buflist_buf = NULL;
2377 			}
2378 
2379 			if (count >= num_marked_files)
2380 			{
2381 			    vim_free(str);
2382 			    break;
2383 			}
2384 		    }
2385 		}
2386 
2387 		fputs("\n> ", fp_out);
2388 		viminfo_writestring(fp_out, str);
2389 		if (did_read_line)
2390 		    fputs((char *)line, fp_out);
2391 
2392 		count++;
2393 		copy_marks_out = TRUE;
2394 	    }
2395 	}
2396 	vim_free(str);
2397 
2398 	pos.coladd = 0;
2399 	while (!(eof = viminfo_readline(virp)) && line[0] == TAB)
2400 	{
2401 	    if (load_marks)
2402 	    {
2403 		if (line[1] != NUL)
2404 		{
2405 		    unsigned u;
2406 
2407 		    sscanf((char *)line + 2, "%ld %u", &pos.lnum, &u);
2408 		    pos.col = u;
2409 		    switch (line[1])
2410 		    {
2411 			case '"': curbuf->b_last_cursor = pos; break;
2412 			case '^': curbuf->b_last_insert = pos; break;
2413 			case '.': curbuf->b_last_change = pos; break;
2414 			case '+':
2415 #ifdef FEAT_JUMPLIST
2416 				  // changelist positions are stored oldest
2417 				  // first
2418 				  if (curbuf->b_changelistlen == JUMPLISTSIZE)
2419 				      // list is full, remove oldest entry
2420 				      mch_memmove(curbuf->b_changelist,
2421 					    curbuf->b_changelist + 1,
2422 					    sizeof(pos_T) * (JUMPLISTSIZE - 1));
2423 				  else
2424 				      ++curbuf->b_changelistlen;
2425 				  curbuf->b_changelist[
2426 					   curbuf->b_changelistlen - 1] = pos;
2427 #endif
2428 				  break;
2429 
2430 				  // Using the line number for the last-used
2431 				  // timestamp.
2432 			case '*': curbuf->b_last_used = pos.lnum; break;
2433 
2434 			default:  if ((i = line[1] - 'a') >= 0 && i < NMARKS)
2435 				      curbuf->b_namedm[i] = pos;
2436 		    }
2437 		}
2438 	    }
2439 	    else if (copy_marks_out)
2440 		fputs((char *)line, fp_out);
2441 	}
2442 
2443 	if (load_marks)
2444 	{
2445 #ifdef FEAT_JUMPLIST
2446 	    win_T	*wp;
2447 
2448 	    FOR_ALL_WINDOWS(wp)
2449 	    {
2450 		if (wp->w_buffer == curbuf)
2451 		    wp->w_changelistidx = curbuf->b_changelistlen;
2452 	    }
2453 #endif
2454 	    if (flags & VIF_ONLY_CURBUF)
2455 		break;
2456 	}
2457     }
2458 
2459     if (fp_out != NULL)
2460 	// Write any remaining entries from buflist.
2461 	while (count < num_marked_files && buflist_used < buflist->ga_len)
2462 	{
2463 	    buflist_buf = ((buf_T **)buflist->ga_data)[buflist_used++];
2464 	    write_buffer_marks(buflist_buf, fp_out);
2465 	    ++count;
2466 	}
2467 
2468     vim_free(name_buf);
2469 }
2470 
2471 /*
2472  * Read marks for the current buffer from the viminfo file, when we support
2473  * buffer marks and the buffer has a name.
2474  */
2475     void
check_marks_read(void)2476 check_marks_read(void)
2477 {
2478     if (!curbuf->b_marks_read && get_viminfo_parameter('\'') > 0
2479 						  && curbuf->b_ffname != NULL)
2480 	read_viminfo(NULL, VIF_WANT_MARKS | VIF_ONLY_CURBUF);
2481 
2482     // Always set b_marks_read; needed when 'viminfo' is changed to include
2483     // the ' parameter after opening a buffer.
2484     curbuf->b_marks_read = TRUE;
2485 }
2486 
2487     static int
read_viminfo_filemark(vir_T * virp,int force)2488 read_viminfo_filemark(vir_T *virp, int force)
2489 {
2490     char_u	*str;
2491     xfmark_T	*namedfm_p = get_namedfm();
2492     xfmark_T	*fm;
2493     int		i;
2494 
2495     // We only get here if line[0] == '\'' or '-'.
2496     // Illegal mark names are ignored (for future expansion).
2497     str = virp->vir_line + 1;
2498     if (
2499 #ifndef EBCDIC
2500 	    *str <= 127 &&
2501 #endif
2502 	    ((*virp->vir_line == '\'' && (VIM_ISDIGIT(*str) || isupper(*str)))
2503 	     || (*virp->vir_line == '-' && *str == '\'')))
2504     {
2505 	if (*str == '\'')
2506 	{
2507 #ifdef FEAT_JUMPLIST
2508 	    // If the jumplist isn't full insert fmark as oldest entry
2509 	    if (curwin->w_jumplistlen == JUMPLISTSIZE)
2510 		fm = NULL;
2511 	    else
2512 	    {
2513 		for (i = curwin->w_jumplistlen; i > 0; --i)
2514 		    curwin->w_jumplist[i] = curwin->w_jumplist[i - 1];
2515 		++curwin->w_jumplistidx;
2516 		++curwin->w_jumplistlen;
2517 		fm = &curwin->w_jumplist[0];
2518 		fm->fmark.mark.lnum = 0;
2519 		fm->fname = NULL;
2520 	    }
2521 #else
2522 	    fm = NULL;
2523 #endif
2524 	}
2525 	else if (VIM_ISDIGIT(*str))
2526 	    fm = &namedfm_p[*str - '0' + NMARKS];
2527 	else
2528 	    fm = &namedfm_p[*str - 'A'];
2529 	if (fm != NULL && (fm->fmark.mark.lnum == 0 || force))
2530 	{
2531 	    str = skipwhite(str + 1);
2532 	    fm->fmark.mark.lnum = getdigits(&str);
2533 	    str = skipwhite(str);
2534 	    fm->fmark.mark.col = getdigits(&str);
2535 	    fm->fmark.mark.coladd = 0;
2536 	    fm->fmark.fnum = 0;
2537 	    str = skipwhite(str);
2538 	    vim_free(fm->fname);
2539 	    fm->fname = viminfo_readstring(virp, (int)(str - virp->vir_line),
2540 								       FALSE);
2541 	    fm->time_set = 0;
2542 	}
2543     }
2544     return vim_fgets(virp->vir_line, LSIZE, virp->vir_fd);
2545 }
2546 
2547 /*
2548  * Prepare for reading viminfo marks when writing viminfo later.
2549  */
2550     static void
prepare_viminfo_marks(void)2551 prepare_viminfo_marks(void)
2552 {
2553     vi_namedfm = ALLOC_CLEAR_MULT(xfmark_T, NMARKS + EXTRA_MARKS);
2554 #ifdef FEAT_JUMPLIST
2555     vi_jumplist = ALLOC_CLEAR_MULT(xfmark_T, JUMPLISTSIZE);
2556     vi_jumplist_len = 0;
2557 #endif
2558 }
2559 
2560     static void
finish_viminfo_marks(void)2561 finish_viminfo_marks(void)
2562 {
2563     int		i;
2564 
2565     if (vi_namedfm != NULL)
2566     {
2567 	for (i = 0; i < NMARKS + EXTRA_MARKS; ++i)
2568 	    vim_free(vi_namedfm[i].fname);
2569 	VIM_CLEAR(vi_namedfm);
2570     }
2571 #ifdef FEAT_JUMPLIST
2572     if (vi_jumplist != NULL)
2573     {
2574 	for (i = 0; i < vi_jumplist_len; ++i)
2575 	    vim_free(vi_jumplist[i].fname);
2576 	VIM_CLEAR(vi_jumplist);
2577     }
2578 #endif
2579 }
2580 
2581 /*
2582  * Accept a new style mark line from the viminfo, store it when it's new.
2583  */
2584     static void
handle_viminfo_mark(garray_T * values,int force)2585 handle_viminfo_mark(garray_T *values, int force)
2586 {
2587     bval_T	*vp = (bval_T *)values->ga_data;
2588     int		name;
2589     linenr_T	lnum;
2590     colnr_T	col;
2591     time_t	timestamp;
2592     xfmark_T	*fm = NULL;
2593 
2594     // Check the format:
2595     // |{bartype},{name},{lnum},{col},{timestamp},{filename}
2596     if (values->ga_len < 5
2597 	    || vp[0].bv_type != BVAL_NR
2598 	    || vp[1].bv_type != BVAL_NR
2599 	    || vp[2].bv_type != BVAL_NR
2600 	    || vp[3].bv_type != BVAL_NR
2601 	    || vp[4].bv_type != BVAL_STRING)
2602 	return;
2603 
2604     name = vp[0].bv_nr;
2605     if (name != '\'' && !VIM_ISDIGIT(name) && !ASCII_ISUPPER(name))
2606 	return;
2607     lnum = vp[1].bv_nr;
2608     col = vp[2].bv_nr;
2609     if (lnum <= 0 || col < 0)
2610 	return;
2611     timestamp = (time_t)vp[3].bv_nr;
2612 
2613     if (name == '\'')
2614     {
2615 #ifdef FEAT_JUMPLIST
2616 	if (vi_jumplist != NULL)
2617 	{
2618 	    if (vi_jumplist_len < JUMPLISTSIZE)
2619 		fm = &vi_jumplist[vi_jumplist_len++];
2620 	}
2621 	else
2622 	{
2623 	    int idx;
2624 	    int i;
2625 
2626 	    // If we have a timestamp insert it in the right place.
2627 	    if (timestamp != 0)
2628 	    {
2629 		for (idx = curwin->w_jumplistlen - 1; idx >= 0; --idx)
2630 		    if (curwin->w_jumplist[idx].time_set < timestamp)
2631 		    {
2632 			++idx;
2633 			break;
2634 		    }
2635 		// idx cannot be zero now
2636 		if (idx < 0 && curwin->w_jumplistlen < JUMPLISTSIZE)
2637 		    // insert as the oldest entry
2638 		    idx = 0;
2639 	    }
2640 	    else if (curwin->w_jumplistlen < JUMPLISTSIZE)
2641 		// insert as oldest entry
2642 		idx = 0;
2643 	    else
2644 		idx = -1;
2645 
2646 	    if (idx >= 0)
2647 	    {
2648 		if (curwin->w_jumplistlen == JUMPLISTSIZE)
2649 		{
2650 		    // Drop the oldest entry.
2651 		    --idx;
2652 		    vim_free(curwin->w_jumplist[0].fname);
2653 		    for (i = 0; i < idx; ++i)
2654 			curwin->w_jumplist[i] = curwin->w_jumplist[i + 1];
2655 		}
2656 		else
2657 		{
2658 		    // Move newer entries forward.
2659 		    for (i = curwin->w_jumplistlen; i > idx; --i)
2660 			curwin->w_jumplist[i] = curwin->w_jumplist[i - 1];
2661 		    ++curwin->w_jumplistidx;
2662 		    ++curwin->w_jumplistlen;
2663 		}
2664 		fm = &curwin->w_jumplist[idx];
2665 		fm->fmark.mark.lnum = 0;
2666 		fm->fname = NULL;
2667 		fm->time_set = 0;
2668 	    }
2669 	}
2670 #endif
2671     }
2672     else
2673     {
2674 	int		idx;
2675 	xfmark_T	*namedfm_p = get_namedfm();
2676 
2677 	if (VIM_ISDIGIT(name))
2678 	{
2679 	    if (vi_namedfm != NULL)
2680 		idx = name - '0' + NMARKS;
2681 	    else
2682 	    {
2683 		int i;
2684 
2685 		// Do not use the name from the viminfo file, insert in time
2686 		// order.
2687 		for (idx = NMARKS; idx < NMARKS + EXTRA_MARKS; ++idx)
2688 		    if (namedfm_p[idx].time_set < timestamp)
2689 			break;
2690 		if (idx == NMARKS + EXTRA_MARKS)
2691 		    // All existing entries are newer.
2692 		    return;
2693 		i = NMARKS + EXTRA_MARKS - 1;
2694 
2695 		vim_free(namedfm_p[i].fname);
2696 		for ( ; i > idx; --i)
2697 		    namedfm_p[i] = namedfm_p[i - 1];
2698 		namedfm_p[idx].fname = NULL;
2699 	    }
2700 	}
2701 	else
2702 	    idx = name - 'A';
2703 	if (vi_namedfm != NULL)
2704 	    fm = &vi_namedfm[idx];
2705 	else
2706 	    fm = &namedfm_p[idx];
2707     }
2708 
2709     if (fm != NULL)
2710     {
2711 	if (vi_namedfm != NULL || fm->fmark.mark.lnum == 0
2712 					  || fm->time_set < timestamp || force)
2713 	{
2714 	    fm->fmark.mark.lnum = lnum;
2715 	    fm->fmark.mark.col = col;
2716 	    fm->fmark.mark.coladd = 0;
2717 	    fm->fmark.fnum = 0;
2718 	    vim_free(fm->fname);
2719 	    if (vp[4].bv_allocated)
2720 	    {
2721 		fm->fname = vp[4].bv_string;
2722 		vp[4].bv_string = NULL;
2723 	    }
2724 	    else
2725 		fm->fname = vim_strsave(vp[4].bv_string);
2726 	    fm->time_set = timestamp;
2727 	}
2728     }
2729 }
2730 
2731     static int
read_viminfo_barline(vir_T * virp,int got_encoding,int force,int writing)2732 read_viminfo_barline(vir_T *virp, int got_encoding, int force, int writing)
2733 {
2734     char_u	*p = virp->vir_line + 1;
2735     int		bartype;
2736     garray_T	values;
2737     bval_T	*vp;
2738     int		i;
2739     int		read_next = TRUE;
2740 
2741     // The format is: |{bartype},{value},...
2742     // For a very long string:
2743     //     |{bartype},>{length of "{text}{text2}"}
2744     //     |<{text1}
2745     //     |<{text2},{value}
2746     // For a long line not using a string
2747     //     |{bartype},{lots of values},>
2748     //     |<{value},{value}
2749     if (*p == '<')
2750     {
2751 	// Continuation line of an unrecognized item.
2752 	if (writing)
2753 	    ga_add_string(&virp->vir_barlines, virp->vir_line);
2754     }
2755     else
2756     {
2757 	ga_init2(&values, sizeof(bval_T), 20);
2758 	bartype = getdigits(&p);
2759 	switch (bartype)
2760 	{
2761 	    case BARTYPE_VERSION:
2762 		// Only use the version when it comes before the encoding.
2763 		// If it comes later it was copied by a Vim version that
2764 		// doesn't understand the version.
2765 		if (!got_encoding)
2766 		{
2767 		    read_next = barline_parse(virp, p, &values);
2768 		    vp = (bval_T *)values.ga_data;
2769 		    if (values.ga_len > 0 && vp->bv_type == BVAL_NR)
2770 			virp->vir_version = vp->bv_nr;
2771 		}
2772 		break;
2773 
2774 	    case BARTYPE_HISTORY:
2775 		read_next = barline_parse(virp, p, &values);
2776 		handle_viminfo_history(&values, writing);
2777 		break;
2778 
2779 	    case BARTYPE_REGISTER:
2780 		read_next = barline_parse(virp, p, &values);
2781 		handle_viminfo_register(&values, force);
2782 		break;
2783 
2784 	    case BARTYPE_MARK:
2785 		read_next = barline_parse(virp, p, &values);
2786 		handle_viminfo_mark(&values, force);
2787 		break;
2788 
2789 	    default:
2790 		// copy unrecognized line (for future use)
2791 		if (writing)
2792 		    ga_add_string(&virp->vir_barlines, virp->vir_line);
2793 	}
2794 	for (i = 0; i < values.ga_len; ++i)
2795 	{
2796 	    vp = (bval_T *)values.ga_data + i;
2797 	    if (vp->bv_type == BVAL_STRING && vp->bv_allocated)
2798 		vim_free(vp->bv_string);
2799 	    vim_free(vp->bv_tofree);
2800 	}
2801 	ga_clear(&values);
2802     }
2803 
2804     if (read_next)
2805 	return viminfo_readline(virp);
2806     return FALSE;
2807 }
2808 
2809 /*
2810  * read_viminfo_up_to_marks() -- Only called from do_viminfo().  Reads in the
2811  * first part of the viminfo file which contains everything but the marks that
2812  * are local to a file.  Returns TRUE when end-of-file is reached. -- webb
2813  */
2814     static int
read_viminfo_up_to_marks(vir_T * virp,int forceit,int writing)2815 read_viminfo_up_to_marks(
2816     vir_T	*virp,
2817     int		forceit,
2818     int		writing)
2819 {
2820     int		eof;
2821     buf_T	*buf;
2822     int		got_encoding = FALSE;
2823 
2824     prepare_viminfo_history(forceit ? 9999 : 0, writing);
2825 
2826     eof = viminfo_readline(virp);
2827     while (!eof && virp->vir_line[0] != '>')
2828     {
2829 	switch (virp->vir_line[0])
2830 	{
2831 		// Characters reserved for future expansion, ignored now
2832 	    case '+': // "+40 /path/dir file", for running vim without args
2833 	    case '^': // to be defined
2834 	    case '<': // long line - ignored
2835 		// A comment or empty line.
2836 	    case NUL:
2837 	    case '\r':
2838 	    case '\n':
2839 	    case '#':
2840 		eof = viminfo_readline(virp);
2841 		break;
2842 	    case '|':
2843 		eof = read_viminfo_barline(virp, got_encoding,
2844 							    forceit, writing);
2845 		break;
2846 	    case '*': // "*encoding=value"
2847 		got_encoding = TRUE;
2848 		eof = viminfo_encoding(virp);
2849 		break;
2850 	    case '!': // global variable
2851 #ifdef FEAT_EVAL
2852 		eof = read_viminfo_varlist(virp, writing);
2853 #else
2854 		eof = viminfo_readline(virp);
2855 #endif
2856 		break;
2857 	    case '%': // entry for buffer list
2858 		eof = read_viminfo_bufferlist(virp, writing);
2859 		break;
2860 	    case '"':
2861 		// When registers are in bar lines skip the old style register
2862 		// lines.
2863 		if (virp->vir_version < VIMINFO_VERSION_WITH_REGISTERS)
2864 		    eof = read_viminfo_register(virp, forceit);
2865 		else
2866 		    do {
2867 			eof = viminfo_readline(virp);
2868 		    } while (!eof && (virp->vir_line[0] == TAB
2869 						|| virp->vir_line[0] == '<'));
2870 		break;
2871 	    case '/':	    // Search string
2872 	    case '&':	    // Substitute search string
2873 	    case '~':	    // Last search string, followed by '/' or '&'
2874 		eof = read_viminfo_search_pattern(virp, forceit);
2875 		break;
2876 	    case '$':
2877 		eof = read_viminfo_sub_string(virp, forceit);
2878 		break;
2879 	    case ':':
2880 	    case '?':
2881 	    case '=':
2882 	    case '@':
2883 		// When history is in bar lines skip the old style history
2884 		// lines.
2885 		if (virp->vir_version < VIMINFO_VERSION_WITH_HISTORY)
2886 		    eof = read_viminfo_history(virp, writing);
2887 		else
2888 		    eof = viminfo_readline(virp);
2889 		break;
2890 	    case '-':
2891 	    case '\'':
2892 		// When file marks are in bar lines skip the old style lines.
2893 		if (virp->vir_version < VIMINFO_VERSION_WITH_MARKS)
2894 		    eof = read_viminfo_filemark(virp, forceit);
2895 		else
2896 		    eof = viminfo_readline(virp);
2897 		break;
2898 	    default:
2899 		if (viminfo_error("E575: ", _("Illegal starting char"),
2900 			    virp->vir_line))
2901 		    eof = TRUE;
2902 		else
2903 		    eof = viminfo_readline(virp);
2904 		break;
2905 	}
2906     }
2907 
2908     // Finish reading history items.
2909     if (!writing)
2910 	finish_viminfo_history(virp);
2911 
2912     // Change file names to buffer numbers for fmarks.
2913     FOR_ALL_BUFFERS(buf)
2914 	fmarks_check_names(buf);
2915 
2916     return eof;
2917 }
2918 
2919 /*
2920  * do_viminfo() -- Should only be called from read_viminfo() & write_viminfo().
2921  */
2922     static void
do_viminfo(FILE * fp_in,FILE * fp_out,int flags)2923 do_viminfo(FILE *fp_in, FILE *fp_out, int flags)
2924 {
2925     int		eof = FALSE;
2926     vir_T	vir;
2927     int		merge = FALSE;
2928     int		do_copy_marks = FALSE;
2929     garray_T	buflist;
2930 
2931     if ((vir.vir_line = alloc(LSIZE)) == NULL)
2932 	return;
2933     vir.vir_fd = fp_in;
2934     vir.vir_conv.vc_type = CONV_NONE;
2935     ga_init2(&vir.vir_barlines, (int)sizeof(char_u *), 100);
2936     vir.vir_version = -1;
2937 
2938     if (fp_in != NULL)
2939     {
2940 	if (flags & VIF_WANT_INFO)
2941 	{
2942 	    if (fp_out != NULL)
2943 	    {
2944 		// Registers and marks are read and kept separate from what
2945 		// this Vim is using.  They are merged when writing.
2946 		prepare_viminfo_registers();
2947 		prepare_viminfo_marks();
2948 	    }
2949 
2950 	    eof = read_viminfo_up_to_marks(&vir,
2951 					 flags & VIF_FORCEIT, fp_out != NULL);
2952 	    merge = TRUE;
2953 	}
2954 	else if (flags != 0)
2955 	    // Skip info, find start of marks
2956 	    while (!(eof = viminfo_readline(&vir))
2957 		    && vir.vir_line[0] != '>')
2958 		;
2959 
2960 	do_copy_marks = (flags & (VIF_WANT_MARKS | VIF_ONLY_CURBUF
2961 					    | VIF_GET_OLDFILES | VIF_FORCEIT));
2962     }
2963 
2964     if (fp_out != NULL)
2965     {
2966 	// Write the info:
2967 	fprintf(fp_out, _("# This viminfo file was generated by Vim %s.\n"),
2968 							  VIM_VERSION_MEDIUM);
2969 	fputs(_("# You may edit it if you're careful!\n\n"), fp_out);
2970 	write_viminfo_version(fp_out);
2971 	fputs(_("# Value of 'encoding' when this file was written\n"), fp_out);
2972 	fprintf(fp_out, "*encoding=%s\n\n", p_enc);
2973 	write_viminfo_search_pattern(fp_out);
2974 	write_viminfo_sub_string(fp_out);
2975 	write_viminfo_history(fp_out, merge);
2976 	write_viminfo_registers(fp_out);
2977 	finish_viminfo_registers();
2978 #ifdef FEAT_EVAL
2979 	write_viminfo_varlist(fp_out);
2980 #endif
2981 	write_viminfo_filemarks(fp_out);
2982 	finish_viminfo_marks();
2983 	write_viminfo_bufferlist(fp_out);
2984 	write_viminfo_barlines(&vir, fp_out);
2985 
2986 	if (do_copy_marks)
2987 	    ga_init2(&buflist, sizeof(buf_T *), 50);
2988 	write_viminfo_marks(fp_out, do_copy_marks ? &buflist : NULL);
2989     }
2990 
2991     if (do_copy_marks)
2992     {
2993 	copy_viminfo_marks(&vir, fp_out, &buflist, eof, flags);
2994 	if (fp_out != NULL)
2995 	    ga_clear(&buflist);
2996     }
2997 
2998     vim_free(vir.vir_line);
2999     if (vir.vir_conv.vc_type != CONV_NONE)
3000 	convert_setup(&vir.vir_conv, NULL, NULL);
3001     ga_clear_strings(&vir.vir_barlines);
3002 }
3003 
3004 /*
3005  * read_viminfo() -- Read the viminfo file.  Registers etc. which are already
3006  * set are not over-written unless "flags" includes VIF_FORCEIT. -- webb
3007  */
3008     int
read_viminfo(char_u * file,int flags)3009 read_viminfo(
3010     char_u	*file,	    // file name or NULL to use default name
3011     int		flags)	    // VIF_WANT_INFO et al.
3012 {
3013     FILE	*fp;
3014     char_u	*fname;
3015     stat_T	st;		// mch_stat() of existing viminfo file
3016 
3017     if (no_viminfo())
3018 	return FAIL;
3019 
3020     fname = viminfo_filename(file);	// get file name in allocated buffer
3021     if (fname == NULL)
3022 	return FAIL;
3023     fp = mch_fopen((char *)fname, READBIN);
3024 
3025     if (p_verbose > 0)
3026     {
3027 	verbose_enter();
3028 	smsg(_("Reading viminfo file \"%s\"%s%s%s%s"),
3029 		fname,
3030 		(flags & VIF_WANT_INFO) ? _(" info") : "",
3031 		(flags & VIF_WANT_MARKS) ? _(" marks") : "",
3032 		(flags & VIF_GET_OLDFILES) ? _(" oldfiles") : "",
3033 		fp == NULL ? _(" FAILED") : "");
3034 	verbose_leave();
3035     }
3036 
3037     vim_free(fname);
3038     if (fp == NULL)
3039 	return FAIL;
3040     if (mch_fstat(fileno(fp), &st) < 0 || S_ISDIR(st.st_mode))
3041     {
3042 	fclose(fp);
3043 	return FAIL;
3044     }
3045 
3046     viminfo_errcnt = 0;
3047     do_viminfo(fp, NULL, flags);
3048 
3049     fclose(fp);
3050     return OK;
3051 }
3052 
3053 /*
3054  * Write the viminfo file.  The old one is read in first so that effectively a
3055  * merge of current info and old info is done.  This allows multiple vims to
3056  * run simultaneously, without losing any marks etc.
3057  * If "forceit" is TRUE, then the old file is not read in, and only internal
3058  * info is written to the file.
3059  */
3060     void
write_viminfo(char_u * file,int forceit)3061 write_viminfo(char_u *file, int forceit)
3062 {
3063     char_u	*fname;
3064     FILE	*fp_in = NULL;	// input viminfo file, if any
3065     FILE	*fp_out = NULL;	// output viminfo file
3066     char_u	*tempname = NULL;	// name of temp viminfo file
3067     stat_T	st_new;		// mch_stat() of potential new file
3068     stat_T	st_old;		// mch_stat() of existing viminfo file
3069 #if defined(UNIX) || defined(VMS)
3070     mode_t	umask_save;
3071 #endif
3072 #ifdef UNIX
3073     int		shortname = FALSE;	// use 8.3 file name
3074 #endif
3075 #ifdef MSWIN
3076     int		hidden = FALSE;
3077 #endif
3078 
3079     if (no_viminfo())
3080 	return;
3081 
3082     fname = viminfo_filename(file);	// may set to default if NULL
3083     if (fname == NULL)
3084 	return;
3085 
3086     fp_in = mch_fopen((char *)fname, READBIN);
3087     if (fp_in == NULL)
3088     {
3089 	int fd;
3090 
3091 	// if it does exist, but we can't read it, don't try writing
3092 	if (mch_stat((char *)fname, &st_new) == 0)
3093 	    goto end;
3094 
3095 	// Create the new .viminfo non-accessible for others, because it may
3096 	// contain text from non-accessible documents. It is up to the user to
3097 	// widen access (e.g. to a group). This may also fail if there is a
3098 	// race condition, then just give up.
3099 	fd = mch_open((char *)fname,
3100 			    O_CREAT|O_EXTRA|O_EXCL|O_WRONLY|O_NOFOLLOW, 0600);
3101 	if (fd < 0)
3102 	    goto end;
3103 	fp_out = fdopen(fd, WRITEBIN);
3104     }
3105     else
3106     {
3107 	// There is an existing viminfo file.  Create a temporary file to
3108 	// write the new viminfo into, in the same directory as the
3109 	// existing viminfo file, which will be renamed once all writing is
3110 	// successful.
3111 	if (mch_fstat(fileno(fp_in), &st_old) < 0
3112 		|| S_ISDIR(st_old.st_mode)
3113 #ifdef UNIX
3114 		// For Unix we check the owner of the file.  It's not very nice
3115 		// to overwrite a user's viminfo file after a "su root", with a
3116 		// viminfo file that the user can't read.
3117 		|| (getuid() != ROOT_UID
3118 		    && !(st_old.st_uid == getuid()
3119 			    ? (st_old.st_mode & 0200)
3120 			    : (st_old.st_gid == getgid()
3121 				    ? (st_old.st_mode & 0020)
3122 				    : (st_old.st_mode & 0002))))
3123 #endif
3124 		)
3125 	{
3126 	    int	tt = msg_didany;
3127 
3128 	    // avoid a wait_return for this message, it's annoying
3129 	    semsg(_("E137: Viminfo file is not writable: %s"), fname);
3130 	    msg_didany = tt;
3131 	    fclose(fp_in);
3132 	    goto end;
3133 	}
3134 #ifdef MSWIN
3135 	// Get the file attributes of the existing viminfo file.
3136 	hidden = mch_ishidden(fname);
3137 #endif
3138 
3139 	// Make tempname, find one that does not exist yet.
3140 	// Beware of a race condition: If someone logs out and all Vim
3141 	// instances exit at the same time a temp file might be created between
3142 	// stat() and open().  Use mch_open() with O_EXCL to avoid that.
3143 	// May try twice: Once normal and once with shortname set, just in
3144 	// case somebody puts his viminfo file in an 8.3 filesystem.
3145 	for (;;)
3146 	{
3147 	    int		next_char = 'z';
3148 	    char_u	*wp;
3149 
3150 	    tempname = buf_modname(
3151 #ifdef UNIX
3152 				    shortname,
3153 #else
3154 				    FALSE,
3155 #endif
3156 				    fname,
3157 #ifdef VMS
3158 				    (char_u *)"-tmp",
3159 #else
3160 				    (char_u *)".tmp",
3161 #endif
3162 				    FALSE);
3163 	    if (tempname == NULL)		// out of memory
3164 		break;
3165 
3166 	    // Try a series of names.  Change one character, just before
3167 	    // the extension.  This should also work for an 8.3
3168 	    // file name, when after adding the extension it still is
3169 	    // the same file as the original.
3170 	    wp = tempname + STRLEN(tempname) - 5;
3171 	    if (wp < gettail(tempname))	    // empty file name?
3172 		wp = gettail(tempname);
3173 	    for (;;)
3174 	    {
3175 		// Check if tempfile already exists.  Never overwrite an
3176 		// existing file!
3177 		if (mch_stat((char *)tempname, &st_new) == 0)
3178 		{
3179 #ifdef UNIX
3180 		    // Check if tempfile is same as original file.  May happen
3181 		    // when modname() gave the same file back.  E.g.  silly
3182 		    // link, or file name-length reached.  Try again with
3183 		    // shortname set.
3184 		    if (!shortname && st_new.st_dev == st_old.st_dev
3185 						&& st_new.st_ino == st_old.st_ino)
3186 		    {
3187 			VIM_CLEAR(tempname);
3188 			shortname = TRUE;
3189 			break;
3190 		    }
3191 #endif
3192 		}
3193 		else
3194 		{
3195 		    // Try creating the file exclusively.  This may fail if
3196 		    // another Vim tries to do it at the same time.
3197 #ifdef VMS
3198 		    // fdopen() fails for some reason
3199 		    umask_save = umask(077);
3200 		    fp_out = mch_fopen((char *)tempname, WRITEBIN);
3201 		    (void)umask(umask_save);
3202 #else
3203 		    int	fd;
3204 
3205 		    // Use mch_open() to be able to use O_NOFOLLOW and set file
3206 		    // protection:
3207 		    // Unix: same as original file, but strip s-bit.  Reset
3208 		    // umask to avoid it getting in the way.
3209 		    // Others: r&w for user only.
3210 # ifdef UNIX
3211 		    umask_save = umask(0);
3212 		    fd = mch_open((char *)tempname,
3213 			    O_CREAT|O_EXTRA|O_EXCL|O_WRONLY|O_NOFOLLOW,
3214 					(int)((st_old.st_mode & 0777) | 0600));
3215 		    (void)umask(umask_save);
3216 # else
3217 		    fd = mch_open((char *)tempname,
3218 			     O_CREAT|O_EXTRA|O_EXCL|O_WRONLY|O_NOFOLLOW, 0600);
3219 # endif
3220 		    if (fd < 0)
3221 		    {
3222 			fp_out = NULL;
3223 # ifdef EEXIST
3224 			// Avoid trying lots of names while the problem is lack
3225 			// of permission, only retry if the file already
3226 			// exists.
3227 			if (errno != EEXIST)
3228 			    break;
3229 # endif
3230 		    }
3231 		    else
3232 			fp_out = fdopen(fd, WRITEBIN);
3233 #endif // VMS
3234 		    if (fp_out != NULL)
3235 			break;
3236 		}
3237 
3238 		// Assume file exists, try again with another name.
3239 		if (next_char == 'a' - 1)
3240 		{
3241 		    // They all exist?  Must be something wrong! Don't write
3242 		    // the viminfo file then.
3243 		    semsg(_("E929: Too many viminfo temp files, like %s!"),
3244 								     tempname);
3245 		    break;
3246 		}
3247 		*wp = next_char;
3248 		--next_char;
3249 	    }
3250 
3251 	    if (tempname != NULL)
3252 		break;
3253 	    // continue if shortname was set
3254 	}
3255 
3256 #if defined(UNIX) && defined(HAVE_FCHOWN)
3257 	if (tempname != NULL && fp_out != NULL)
3258 	{
3259 		stat_T	tmp_st;
3260 
3261 	    // Make sure the original owner can read/write the tempfile and
3262 	    // otherwise preserve permissions, making sure the group matches.
3263 	    if (mch_stat((char *)tempname, &tmp_st) >= 0)
3264 	    {
3265 		if (st_old.st_uid != tmp_st.st_uid)
3266 		    // Changing the owner might fail, in which case the
3267 		    // file will now be owned by the current user, oh well.
3268 		    vim_ignored = fchown(fileno(fp_out), st_old.st_uid, -1);
3269 		if (st_old.st_gid != tmp_st.st_gid
3270 			&& fchown(fileno(fp_out), -1, st_old.st_gid) == -1)
3271 		    // can't set the group to what it should be, remove
3272 		    // group permissions
3273 		    (void)mch_setperm(tempname, 0600);
3274 	    }
3275 	    else
3276 		// can't stat the file, set conservative permissions
3277 		(void)mch_setperm(tempname, 0600);
3278 	}
3279 #endif
3280     }
3281 
3282     // Check if the new viminfo file can be written to.
3283     if (fp_out == NULL)
3284     {
3285 	semsg(_("E138: Can't write viminfo file %s!"),
3286 		       (fp_in == NULL || tempname == NULL) ? fname : tempname);
3287 	if (fp_in != NULL)
3288 	    fclose(fp_in);
3289 	goto end;
3290     }
3291 
3292     if (p_verbose > 0)
3293     {
3294 	verbose_enter();
3295 	smsg(_("Writing viminfo file \"%s\""), fname);
3296 	verbose_leave();
3297     }
3298 
3299     viminfo_errcnt = 0;
3300     do_viminfo(fp_in, fp_out, forceit ? 0 : (VIF_WANT_INFO | VIF_WANT_MARKS));
3301 
3302     if (fclose(fp_out) == EOF)
3303 	++viminfo_errcnt;
3304 
3305     if (fp_in != NULL)
3306     {
3307 	fclose(fp_in);
3308 
3309 	// In case of an error keep the original viminfo file.  Otherwise
3310 	// rename the newly written file.  Give an error if that fails.
3311 	if (viminfo_errcnt == 0)
3312 	{
3313 	    if (vim_rename(tempname, fname) == -1)
3314 	    {
3315 		++viminfo_errcnt;
3316 		semsg(_("E886: Can't rename viminfo file to %s!"), fname);
3317 	    }
3318 # ifdef MSWIN
3319 	    // If the viminfo file was hidden then also hide the new file.
3320 	    else if (hidden)
3321 		mch_hide(fname);
3322 # endif
3323 	}
3324 	if (viminfo_errcnt > 0)
3325 	    mch_remove(tempname);
3326     }
3327 
3328 end:
3329     vim_free(fname);
3330     vim_free(tempname);
3331 }
3332 
3333 /*
3334  * ":rviminfo" and ":wviminfo".
3335  */
3336     void
ex_viminfo(exarg_T * eap)3337 ex_viminfo(
3338     exarg_T	*eap)
3339 {
3340     char_u	*save_viminfo;
3341 
3342     save_viminfo = p_viminfo;
3343     if (*p_viminfo == NUL)
3344 	p_viminfo = (char_u *)"'100";
3345     if (eap->cmdidx == CMD_rviminfo)
3346     {
3347 	if (read_viminfo(eap->arg, VIF_WANT_INFO | VIF_WANT_MARKS
3348 				  | (eap->forceit ? VIF_FORCEIT : 0)) == FAIL)
3349 	    emsg(_("E195: Cannot open viminfo file for reading"));
3350     }
3351     else
3352 	write_viminfo(eap->arg, eap->forceit);
3353     p_viminfo = save_viminfo;
3354 }
3355 
3356 #endif // FEAT_VIMINFO
3357