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  * alloc.c: functions for memory management
12  */
13 
14 #include "vim.h"
15 
16 /**********************************************************************
17  * Various routines dealing with allocation and deallocation of memory.
18  */
19 
20 #if defined(MEM_PROFILE) || defined(PROTO)
21 
22 # define MEM_SIZES  8200
23 static long_u mem_allocs[MEM_SIZES];
24 static long_u mem_frees[MEM_SIZES];
25 static long_u mem_allocated;
26 static long_u mem_freed;
27 static long_u mem_peak;
28 static long_u num_alloc;
29 static long_u num_freed;
30 
31     static void
mem_pre_alloc_s(size_t * sizep)32 mem_pre_alloc_s(size_t *sizep)
33 {
34     *sizep += sizeof(size_t);
35 }
36 
37     static void
mem_pre_alloc_l(size_t * sizep)38 mem_pre_alloc_l(size_t *sizep)
39 {
40     *sizep += sizeof(size_t);
41 }
42 
43     static void
mem_post_alloc(void ** pp,size_t size)44 mem_post_alloc(
45     void **pp,
46     size_t size)
47 {
48     if (*pp == NULL)
49 	return;
50     size -= sizeof(size_t);
51     *(long_u *)*pp = size;
52     if (size <= MEM_SIZES-1)
53 	mem_allocs[size-1]++;
54     else
55 	mem_allocs[MEM_SIZES-1]++;
56     mem_allocated += size;
57     if (mem_allocated - mem_freed > mem_peak)
58 	mem_peak = mem_allocated - mem_freed;
59     num_alloc++;
60     *pp = (void *)((char *)*pp + sizeof(size_t));
61 }
62 
63     static void
mem_pre_free(void ** pp)64 mem_pre_free(void **pp)
65 {
66     long_u size;
67 
68     *pp = (void *)((char *)*pp - sizeof(size_t));
69     size = *(size_t *)*pp;
70     if (size <= MEM_SIZES-1)
71 	mem_frees[size-1]++;
72     else
73 	mem_frees[MEM_SIZES-1]++;
74     mem_freed += size;
75     num_freed++;
76 }
77 
78 /*
79  * called on exit via atexit()
80  */
81     void
vim_mem_profile_dump(void)82 vim_mem_profile_dump(void)
83 {
84     int i, j;
85 
86     printf("\r\n");
87     j = 0;
88     for (i = 0; i < MEM_SIZES - 1; i++)
89     {
90 	if (mem_allocs[i] || mem_frees[i])
91 	{
92 	    if (mem_frees[i] > mem_allocs[i])
93 		printf("\r\n%s", _("ERROR: "));
94 	    printf("[%4d / %4lu-%-4lu] ", i + 1, mem_allocs[i], mem_frees[i]);
95 	    j++;
96 	    if (j > 3)
97 	    {
98 		j = 0;
99 		printf("\r\n");
100 	    }
101 	}
102     }
103 
104     i = MEM_SIZES - 1;
105     if (mem_allocs[i])
106     {
107 	printf("\r\n");
108 	if (mem_frees[i] > mem_allocs[i])
109 	    puts(_("ERROR: "));
110 	printf("[>%d / %4lu-%-4lu]", i, mem_allocs[i], mem_frees[i]);
111     }
112 
113     printf(_("\n[bytes] total alloc-freed %lu-%lu, in use %lu, peak use %lu\n"),
114 	    mem_allocated, mem_freed, mem_allocated - mem_freed, mem_peak);
115     printf(_("[calls] total re/malloc()'s %lu, total free()'s %lu\n\n"),
116 	    num_alloc, num_freed);
117 }
118 
119 #endif // MEM_PROFILE
120 
121 #ifdef FEAT_EVAL
122     int
alloc_does_fail(size_t size)123 alloc_does_fail(size_t size)
124 {
125     if (alloc_fail_countdown == 0)
126     {
127 	if (--alloc_fail_repeat <= 0)
128 	    alloc_fail_id = 0;
129 	do_outofmem_msg(size);
130 	return TRUE;
131     }
132     --alloc_fail_countdown;
133     return FALSE;
134 }
135 #endif
136 
137 /*
138  * Some memory is reserved for error messages and for being able to
139  * call mf_release_all(), which needs some memory for mf_trans_add().
140  */
141 #define KEEP_ROOM (2 * 8192L)
142 #define KEEP_ROOM_KB (KEEP_ROOM / 1024L)
143 
144 /*
145  * The normal way to allocate memory.  This handles an out-of-memory situation
146  * as well as possible, still returns NULL when we're completely out.
147  */
148     void *
alloc(size_t size)149 alloc(size_t size)
150 {
151     return lalloc(size, TRUE);
152 }
153 
154 /*
155  * alloc() with an ID for alloc_fail().
156  */
157     void *
alloc_id(size_t size,alloc_id_T id UNUSED)158 alloc_id(size_t size, alloc_id_T id UNUSED)
159 {
160 #ifdef FEAT_EVAL
161     if (alloc_fail_id == id && alloc_does_fail(size))
162 	return NULL;
163 #endif
164     return lalloc(size, TRUE);
165 }
166 
167 /*
168  * Allocate memory and set all bytes to zero.
169  */
170     void *
alloc_clear(size_t size)171 alloc_clear(size_t size)
172 {
173     void *p;
174 
175     p = lalloc(size, TRUE);
176     if (p != NULL)
177 	(void)vim_memset(p, 0, size);
178     return p;
179 }
180 
181 /*
182  * Same as alloc_clear() but with allocation id for testing
183  */
184     void *
alloc_clear_id(size_t size,alloc_id_T id UNUSED)185 alloc_clear_id(size_t size, alloc_id_T id UNUSED)
186 {
187 #ifdef FEAT_EVAL
188     if (alloc_fail_id == id && alloc_does_fail(size))
189 	return NULL;
190 #endif
191     return alloc_clear(size);
192 }
193 
194 /*
195  * Allocate memory like lalloc() and set all bytes to zero.
196  */
197     void *
lalloc_clear(size_t size,int message)198 lalloc_clear(size_t size, int message)
199 {
200     void *p;
201 
202     p = lalloc(size, message);
203     if (p != NULL)
204 	(void)vim_memset(p, 0, size);
205     return p;
206 }
207 
208 /*
209  * Low level memory allocation function.
210  * This is used often, KEEP IT FAST!
211  */
212     void *
lalloc(size_t size,int message)213 lalloc(size_t size, int message)
214 {
215     void	*p;		    // pointer to new storage space
216     static int	releasing = FALSE;  // don't do mf_release_all() recursive
217     int		try_again;
218 #if defined(HAVE_AVAIL_MEM)
219     static size_t allocated = 0;    // allocated since last avail check
220 #endif
221 
222     // Safety check for allocating zero bytes
223     if (size == 0)
224     {
225 	// Don't hide this message
226 	emsg_silent = 0;
227 	iemsg(_("E341: Internal error: lalloc(0, )"));
228 	return NULL;
229     }
230 
231 #ifdef MEM_PROFILE
232     mem_pre_alloc_l(&size);
233 #endif
234 
235     // Loop when out of memory: Try to release some memfile blocks and
236     // if some blocks are released call malloc again.
237     for (;;)
238     {
239 	// Handle three kind of systems:
240 	// 1. No check for available memory: Just return.
241 	// 2. Slow check for available memory: call mch_avail_mem() after
242 	//    allocating KEEP_ROOM amount of memory.
243 	// 3. Strict check for available memory: call mch_avail_mem()
244 	if ((p = malloc(size)) != NULL)
245 	{
246 #ifndef HAVE_AVAIL_MEM
247 	    // 1. No check for available memory: Just return.
248 	    goto theend;
249 #else
250 	    // 2. Slow check for available memory: call mch_avail_mem() after
251 	    //    allocating (KEEP_ROOM / 2) amount of memory.
252 	    allocated += size;
253 	    if (allocated < KEEP_ROOM / 2)
254 		goto theend;
255 	    allocated = 0;
256 
257 	    // 3. check for available memory: call mch_avail_mem()
258 	    if (mch_avail_mem(TRUE) < KEEP_ROOM_KB && !releasing)
259 	    {
260 		free(p);	// System is low... no go!
261 		p = NULL;
262 	    }
263 	    else
264 		goto theend;
265 #endif
266 	}
267 	// Remember that mf_release_all() is being called to avoid an endless
268 	// loop, because mf_release_all() may call alloc() recursively.
269 	if (releasing)
270 	    break;
271 	releasing = TRUE;
272 
273 	clear_sb_text(TRUE);	      // free any scrollback text
274 	try_again = mf_release_all(); // release as many blocks as possible
275 
276 	releasing = FALSE;
277 	if (!try_again)
278 	    break;
279     }
280 
281     if (message && p == NULL)
282 	do_outofmem_msg(size);
283 
284 theend:
285 #ifdef MEM_PROFILE
286     mem_post_alloc(&p, size);
287 #endif
288     return p;
289 }
290 
291 /*
292  * lalloc() with an ID for alloc_fail().
293  */
294 #if defined(FEAT_SIGNS) || defined(PROTO)
295     void *
lalloc_id(size_t size,int message,alloc_id_T id UNUSED)296 lalloc_id(size_t size, int message, alloc_id_T id UNUSED)
297 {
298 #ifdef FEAT_EVAL
299     if (alloc_fail_id == id && alloc_does_fail(size))
300 	return NULL;
301 #endif
302     return (lalloc(size, message));
303 }
304 #endif
305 
306 #if defined(MEM_PROFILE) || defined(PROTO)
307 /*
308  * realloc() with memory profiling.
309  */
310     void *
mem_realloc(void * ptr,size_t size)311 mem_realloc(void *ptr, size_t size)
312 {
313     void *p;
314 
315     mem_pre_free(&ptr);
316     mem_pre_alloc_s(&size);
317 
318     p = realloc(ptr, size);
319 
320     mem_post_alloc(&p, size);
321 
322     return p;
323 }
324 #endif
325 
326 /*
327 * Avoid repeating the error message many times (they take 1 second each).
328 * Did_outofmem_msg is reset when a character is read.
329 */
330     void
do_outofmem_msg(size_t size)331 do_outofmem_msg(size_t size)
332 {
333     if (!did_outofmem_msg)
334     {
335 	// Don't hide this message
336 	emsg_silent = 0;
337 
338 	// Must come first to avoid coming back here when printing the error
339 	// message fails, e.g. when setting v:errmsg.
340 	did_outofmem_msg = TRUE;
341 
342 	semsg(_("E342: Out of memory!  (allocating %lu bytes)"), (long_u)size);
343 
344 	if (starting == NO_SCREEN)
345 	    // Not even finished with initializations and already out of
346 	    // memory?  Then nothing is going to work, exit.
347 	    mch_exit(123);
348     }
349 }
350 
351 #if defined(EXITFREE) || defined(PROTO)
352 
353 /*
354  * Free everything that we allocated.
355  * Can be used to detect memory leaks, e.g., with ccmalloc.
356  * NOTE: This is tricky!  Things are freed that functions depend on.  Don't be
357  * surprised if Vim crashes...
358  * Some things can't be freed, esp. things local to a library function.
359  */
360     void
free_all_mem(void)361 free_all_mem(void)
362 {
363     buf_T	*buf, *nextbuf;
364 
365     // When we cause a crash here it is caught and Vim tries to exit cleanly.
366     // Don't try freeing everything again.
367     if (entered_free_all_mem)
368 	return;
369     entered_free_all_mem = TRUE;
370     // Don't want to trigger autocommands from here on.
371     block_autocmds();
372 
373     // Close all tabs and windows.  Reset 'equalalways' to avoid redraws.
374     p_ea = FALSE;
375     if (first_tabpage != NULL && first_tabpage->tp_next != NULL)
376 	do_cmdline_cmd((char_u *)"tabonly!");
377     if (!ONE_WINDOW)
378 	do_cmdline_cmd((char_u *)"only!");
379 
380 # if defined(FEAT_SPELL)
381     // Free all spell info.
382     spell_free_all();
383 # endif
384 
385 # if defined(FEAT_BEVAL_TERM)
386     ui_remove_balloon();
387 # endif
388 # ifdef FEAT_PROP_POPUP
389     if (curwin != NULL)
390 	close_all_popups(TRUE);
391 # endif
392 
393     // Clear user commands (before deleting buffers).
394     ex_comclear(NULL);
395 
396     // When exiting from mainerr_arg_missing curbuf has not been initialized,
397     // and not much else.
398     if (curbuf != NULL)
399     {
400 # ifdef FEAT_MENU
401 	// Clear menus.
402 	do_cmdline_cmd((char_u *)"aunmenu *");
403 #  ifdef FEAT_MULTI_LANG
404 	do_cmdline_cmd((char_u *)"menutranslate clear");
405 #  endif
406 # endif
407 	// Clear mappings, abbreviations, breakpoints.
408 	do_cmdline_cmd((char_u *)"lmapclear");
409 	do_cmdline_cmd((char_u *)"xmapclear");
410 	do_cmdline_cmd((char_u *)"mapclear");
411 	do_cmdline_cmd((char_u *)"mapclear!");
412 	do_cmdline_cmd((char_u *)"abclear");
413 # if defined(FEAT_EVAL)
414 	do_cmdline_cmd((char_u *)"breakdel *");
415 # endif
416 # if defined(FEAT_PROFILE)
417 	do_cmdline_cmd((char_u *)"profdel *");
418 # endif
419 # if defined(FEAT_KEYMAP)
420 	do_cmdline_cmd((char_u *)"set keymap=");
421 # endif
422     }
423 
424     free_titles();
425 # if defined(FEAT_SEARCHPATH)
426     free_findfile();
427 # endif
428 
429     // Obviously named calls.
430     free_all_autocmds();
431     clear_termcodes();
432     free_all_marks();
433     alist_clear(&global_alist);
434     free_homedir();
435     free_users();
436     free_search_patterns();
437     free_old_sub();
438     free_last_insert();
439     free_insexpand_stuff();
440     free_prev_shellcmd();
441     free_regexp_stuff();
442     free_tag_stuff();
443     free_xim_stuff();
444     free_cd_dir();
445 # ifdef FEAT_SIGNS
446     free_signs();
447 # endif
448 # ifdef FEAT_EVAL
449     set_expr_line(NULL, NULL);
450 # endif
451 # ifdef FEAT_DIFF
452     if (curtab != NULL)
453 	diff_clear(curtab);
454 # endif
455     clear_sb_text(TRUE);	      // free any scrollback text
456 
457     // Free some global vars.
458     free_username();
459 # ifdef FEAT_CLIPBOARD
460     vim_regfree(clip_exclude_prog);
461 # endif
462     vim_free(last_cmdline);
463     vim_free(new_last_cmdline);
464     set_keep_msg(NULL, 0);
465 
466     // Clear cmdline history.
467     p_hi = 0;
468     init_history();
469 # ifdef FEAT_PROP_POPUP
470     clear_global_prop_types();
471 # endif
472 
473 # ifdef FEAT_QUICKFIX
474     {
475 	win_T	    *win;
476 	tabpage_T   *tab;
477 
478 	qf_free_all(NULL);
479 	// Free all location lists
480 	FOR_ALL_TAB_WINDOWS(tab, win)
481 	    qf_free_all(win);
482     }
483 # endif
484 
485     // Close all script inputs.
486     close_all_scripts();
487 
488     if (curwin != NULL)
489 	// Destroy all windows.  Must come before freeing buffers.
490 	win_free_all();
491 
492     // Free all option values.  Must come after closing windows.
493     free_all_options();
494 
495     // Free all buffers.  Reset 'autochdir' to avoid accessing things that
496     // were freed already.
497 # ifdef FEAT_AUTOCHDIR
498     p_acd = FALSE;
499 # endif
500     for (buf = firstbuf; buf != NULL; )
501     {
502 	bufref_T    bufref;
503 
504 	set_bufref(&bufref, buf);
505 	nextbuf = buf->b_next;
506 	close_buffer(NULL, buf, DOBUF_WIPE, FALSE, FALSE);
507 	if (bufref_valid(&bufref))
508 	    buf = nextbuf;	// didn't work, try next one
509 	else
510 	    buf = firstbuf;
511     }
512 
513 # ifdef FEAT_ARABIC
514     free_arshape_buf();
515 # endif
516 
517     // Clear registers.
518     clear_registers();
519     ResetRedobuff();
520     ResetRedobuff();
521 
522 # if defined(FEAT_CLIENTSERVER) && defined(FEAT_X11)
523     vim_free(serverDelayedStartName);
524 # endif
525 
526     // highlight info
527     free_highlight();
528 
529     reset_last_sourcing();
530 
531     if (first_tabpage != NULL)
532     {
533 	free_tabpage(first_tabpage);
534 	first_tabpage = NULL;
535     }
536 
537 # ifdef UNIX
538     // Machine-specific free.
539     mch_free_mem();
540 # endif
541 
542     // message history
543     for (;;)
544 	if (delete_first_msg() == FAIL)
545 	    break;
546 
547 # ifdef FEAT_JOB_CHANNEL
548     channel_free_all();
549 # endif
550 # ifdef FEAT_TIMERS
551     timer_free_all();
552 # endif
553 # ifdef FEAT_EVAL
554     // must be after channel_free_all() with unrefs partials
555     eval_clear();
556 # endif
557 # ifdef FEAT_JOB_CHANNEL
558     // must be after eval_clear() with unrefs jobs
559     job_free_all();
560 # endif
561 
562     free_termoptions();
563     free_cur_term();
564 
565     // screenlines (can't display anything now!)
566     free_screenlines();
567 
568 # if defined(FEAT_SOUND)
569     sound_free();
570 # endif
571 # if defined(USE_XSMP)
572     xsmp_close();
573 # endif
574 # ifdef FEAT_GUI_GTK
575     gui_mch_free_all();
576 # endif
577 # ifdef FEAT_TCL
578     vim_tcl_finalize();
579 # endif
580     clear_hl_tables();
581 
582     vim_free(IObuff);
583     vim_free(NameBuff);
584 # ifdef FEAT_QUICKFIX
585     check_quickfix_busy();
586 # endif
587 }
588 #endif
589 
590 /*
591  * Copy "p[len]" into allocated memory, ignoring NUL characters.
592  * Returns NULL when out of memory.
593  */
594     char_u *
vim_memsave(char_u * p,size_t len)595 vim_memsave(char_u *p, size_t len)
596 {
597     char_u *ret = alloc(len);
598 
599     if (ret != NULL)
600 	mch_memmove(ret, p, len);
601     return ret;
602 }
603 
604 /*
605  * Replacement for free() that ignores NULL pointers.
606  * Also skip free() when exiting for sure, this helps when we caught a deadly
607  * signal that was caused by a crash in free().
608  * If you want to set NULL after calling this function, you should use
609  * VIM_CLEAR() instead.
610  */
611     void
vim_free(void * x)612 vim_free(void *x)
613 {
614     if (x != NULL && !really_exiting)
615     {
616 #ifdef MEM_PROFILE
617 	mem_pre_free(&x);
618 #endif
619 	free(x);
620     }
621 }
622 
623 /************************************************************************
624  * Functions for handling growing arrays.
625  */
626 
627 /*
628  * Clear an allocated growing array.
629  */
630     void
ga_clear(garray_T * gap)631 ga_clear(garray_T *gap)
632 {
633     vim_free(gap->ga_data);
634     ga_init(gap);
635 }
636 
637 /*
638  * Clear a growing array that contains a list of strings.
639  */
640     void
ga_clear_strings(garray_T * gap)641 ga_clear_strings(garray_T *gap)
642 {
643     int		i;
644 
645     if (gap->ga_data != NULL)
646 	for (i = 0; i < gap->ga_len; ++i)
647 	    vim_free(((char_u **)(gap->ga_data))[i]);
648     ga_clear(gap);
649 }
650 
651 /*
652  * Copy a growing array that contains a list of strings.
653  */
654     int
ga_copy_strings(garray_T * from,garray_T * to)655 ga_copy_strings(garray_T *from, garray_T *to)
656 {
657     int		i;
658 
659     ga_init2(to, sizeof(char_u *), 1);
660     if (ga_grow(to, from->ga_len) == FAIL)
661 	return FAIL;
662 
663     for (i = 0; i < from->ga_len; ++i)
664     {
665 	char_u *orig = ((char_u **)from->ga_data)[i];
666 	char_u *copy;
667 
668 	if (orig == NULL)
669 	    copy = NULL;
670 	else
671 	{
672 	    copy = vim_strsave(orig);
673 	    if (copy == NULL)
674 	    {
675 		to->ga_len = i;
676 		ga_clear_strings(to);
677 		return FAIL;
678 	    }
679 	}
680 	((char_u **)to->ga_data)[i] = copy;
681     }
682     to->ga_len = from->ga_len;
683     return OK;
684 }
685 
686 /*
687  * Initialize a growing array.	Don't forget to set ga_itemsize and
688  * ga_growsize!  Or use ga_init2().
689  */
690     void
ga_init(garray_T * gap)691 ga_init(garray_T *gap)
692 {
693     gap->ga_data = NULL;
694     gap->ga_maxlen = 0;
695     gap->ga_len = 0;
696 }
697 
698     void
ga_init2(garray_T * gap,int itemsize,int growsize)699 ga_init2(garray_T *gap, int itemsize, int growsize)
700 {
701     ga_init(gap);
702     gap->ga_itemsize = itemsize;
703     gap->ga_growsize = growsize;
704 }
705 
706 /*
707  * Make room in growing array "gap" for at least "n" items.
708  * Return FAIL for failure, OK otherwise.
709  */
710     int
ga_grow(garray_T * gap,int n)711 ga_grow(garray_T *gap, int n)
712 {
713     if (gap->ga_maxlen - gap->ga_len < n)
714 	return ga_grow_inner(gap, n);
715     return OK;
716 }
717 
718     int
ga_grow_inner(garray_T * gap,int n)719 ga_grow_inner(garray_T *gap, int n)
720 {
721     size_t	old_len;
722     size_t	new_len;
723     char_u	*pp;
724 
725     if (n < gap->ga_growsize)
726 	n = gap->ga_growsize;
727 
728     // A linear growth is very inefficient when the array grows big.  This
729     // is a compromise between allocating memory that won't be used and too
730     // many copy operations. A factor of 1.5 seems reasonable.
731     if (n < gap->ga_len / 2)
732 	n = gap->ga_len / 2;
733 
734     new_len = gap->ga_itemsize * (gap->ga_len + n);
735     pp = vim_realloc(gap->ga_data, new_len);
736     if (pp == NULL)
737 	return FAIL;
738     old_len = gap->ga_itemsize * gap->ga_maxlen;
739     vim_memset(pp + old_len, 0, new_len - old_len);
740     gap->ga_maxlen = gap->ga_len + n;
741     gap->ga_data = pp;
742     return OK;
743 }
744 
745 /*
746  * For a growing array that contains a list of strings: concatenate all the
747  * strings with a separating "sep".
748  * Returns NULL when out of memory.
749  */
750     char_u *
ga_concat_strings(garray_T * gap,char * sep)751 ga_concat_strings(garray_T *gap, char *sep)
752 {
753     int		i;
754     int		len = 0;
755     int		sep_len = (int)STRLEN(sep);
756     char_u	*s;
757     char_u	*p;
758 
759     for (i = 0; i < gap->ga_len; ++i)
760 	len += (int)STRLEN(((char_u **)(gap->ga_data))[i]) + sep_len;
761 
762     s = alloc(len + 1);
763     if (s != NULL)
764     {
765 	*s = NUL;
766 	p = s;
767 	for (i = 0; i < gap->ga_len; ++i)
768 	{
769 	    if (p != s)
770 	    {
771 		STRCPY(p, sep);
772 		p += sep_len;
773 	    }
774 	    STRCPY(p, ((char_u **)(gap->ga_data))[i]);
775 	    p += STRLEN(p);
776 	}
777     }
778     return s;
779 }
780 
781 /*
782  * Make a copy of string "p" and add it to "gap".
783  * When out of memory nothing changes and FAIL is returned.
784  */
785     int
ga_add_string(garray_T * gap,char_u * p)786 ga_add_string(garray_T *gap, char_u *p)
787 {
788     char_u *cp = vim_strsave(p);
789 
790     if (cp == NULL)
791 	return FAIL;
792 
793     if (ga_grow(gap, 1) == FAIL)
794     {
795 	vim_free(cp);
796 	return FAIL;
797     }
798     ((char_u **)(gap->ga_data))[gap->ga_len++] = cp;
799     return OK;
800 }
801 
802 /*
803  * Concatenate a string to a growarray which contains bytes.
804  * When "s" is NULL does not do anything.
805  * Note: Does NOT copy the NUL at the end!
806  */
807     void
ga_concat(garray_T * gap,char_u * s)808 ga_concat(garray_T *gap, char_u *s)
809 {
810     int    len;
811 
812     if (s == NULL || *s == NUL)
813 	return;
814     len = (int)STRLEN(s);
815     if (ga_grow(gap, len) == OK)
816     {
817 	mch_memmove((char *)gap->ga_data + gap->ga_len, s, (size_t)len);
818 	gap->ga_len += len;
819     }
820 }
821 
822 /*
823  * Concatenate 'len' bytes from string 's' to a growarray.
824  * When "s" is NULL does not do anything.
825  */
826     void
ga_concat_len(garray_T * gap,char_u * s,size_t len)827 ga_concat_len(garray_T *gap, char_u *s, size_t len)
828 {
829     if (s == NULL || *s == NUL)
830 	return;
831     if (ga_grow(gap, (int)len) == OK)
832     {
833 	mch_memmove((char *)gap->ga_data + gap->ga_len, s, len);
834 	gap->ga_len += (int)len;
835     }
836 }
837 
838 /*
839  * Append one byte to a growarray which contains bytes.
840  */
841     void
ga_append(garray_T * gap,int c)842 ga_append(garray_T *gap, int c)
843 {
844     if (ga_grow(gap, 1) == OK)
845     {
846 	*((char *)gap->ga_data + gap->ga_len) = c;
847 	++gap->ga_len;
848     }
849 }
850 
851 #if (defined(UNIX) && !defined(USE_SYSTEM)) || defined(MSWIN) \
852 	|| defined(PROTO)
853 /*
854  * Append the text in "gap" below the cursor line and clear "gap".
855  */
856     void
append_ga_line(garray_T * gap)857 append_ga_line(garray_T *gap)
858 {
859     // Remove trailing CR.
860     if (gap->ga_len > 0
861 	    && !curbuf->b_p_bin
862 	    && ((char_u *)gap->ga_data)[gap->ga_len - 1] == CAR)
863 	--gap->ga_len;
864     ga_append(gap, NUL);
865     ml_append(curwin->w_cursor.lnum++, gap->ga_data, 0, FALSE);
866     gap->ga_len = 0;
867 }
868 #endif
869 
870