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