To: vim_dev@googlegroups.com Subject: Patch 8.2.3301 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.3301 Problem: Memory allocation functions don't have their own place. Solution: Move memory allocation functions to alloc.c. (Yegappan Lakshmanan, closes #8717) Files: Filelist, src/Make_ami.mak, src/Make_cyg_ming.mak, src/Make_mvc.mak, src/Make_vms.mms, src/Makefile, src/README.md, src/alloc.c, src/misc2.c, src/proto.h, src/proto/alloc.pro, src/proto/misc2.pro *** ../vim-8.2.3300/Filelist 2021-07-10 21:28:55.323050112 +0200 --- Filelist 2021-08-06 21:45:45.293392385 +0200 *************** *** 23,28 **** --- 23,29 ---- ci/setup-xvfb.sh \ src/Make_all.mak \ src/README.md \ + src/alloc.c \ src/alloc.h \ src/arabic.c \ src/arglist.c \ *************** *** 210,215 **** --- 211,217 ---- src/testdir/popupbounce.vim \ src/proto.h \ src/protodef.h \ + src/proto/alloc.pro \ src/proto/arabic.pro \ src/proto/arglist.pro \ src/proto/autocmd.pro \ *** ../vim-8.2.3300/src/Make_ami.mak 2021-07-10 21:28:55.323050112 +0200 --- src/Make_ami.mak 2021-08-06 21:45:45.293392385 +0200 *************** *** 80,85 **** --- 80,86 ---- # Common sources SRC += \ + alloc.c \ arabic.c \ arglist.c \ autocmd.c \ *** ../vim-8.2.3300/src/Make_cyg_ming.mak 2021-07-10 21:28:55.323050112 +0200 --- src/Make_cyg_ming.mak 2021-08-06 21:45:45.293392385 +0200 *************** *** 723,728 **** --- 723,729 ---- GUIOBJ = $(OUTDIR)/gui.o $(OUTDIR)/gui_w32.o $(OUTDIR)/gui_beval.o CUIOBJ = $(OUTDIR)/iscygpty.o OBJ = \ + $(OUTDIR)/alloc.o \ $(OUTDIR)/arabic.o \ $(OUTDIR)/arglist.o \ $(OUTDIR)/autocmd.o \ *** ../vim-8.2.3300/src/Make_mvc.mak 2021-07-30 20:51:51.761101629 +0200 --- src/Make_mvc.mak 2021-08-06 21:45:45.293392385 +0200 *************** *** 733,738 **** --- 733,739 ---- spell.h structs.h term.h beval.h $(NBDEBUG_INCL) OBJ = \ + $(OUTDIR)\alloc.obj \ $(OUTDIR)\arabic.obj \ $(OUTDIR)\arglist.obj \ $(OUTDIR)\autocmd.obj \ *************** *** 1542,1547 **** --- 1543,1550 ---- .cpp{$(OUTDIR)/}.obj:: $(CC) $(CFLAGS_OUTDIR) $< + $(OUTDIR)/alloc.obj: $(OUTDIR) alloc.c $(INCL) + $(OUTDIR)/arabic.obj: $(OUTDIR) arabic.c $(INCL) $(OUTDIR)/arglist.obj: $(OUTDIR) arglist.c $(INCL) *************** *** 1932,1937 **** --- 1935,1941 ---- # End Custom Build proto.h: \ + proto/alloc.pro \ proto/arabic.pro \ proto/arglist.pro \ proto/autocmd.pro \ *** ../vim-8.2.3300/src/Make_vms.mms 2021-07-10 21:28:55.323050112 +0200 --- src/Make_vms.mms 2021-08-06 21:45:45.293392385 +0200 *************** *** 306,311 **** --- 306,312 ---- $(PERL_LIB) $(PYTHON_LIB) $(TCL_LIB) $(RUBY_LIB) $(LUA_LIB) SRC = \ + alloc.c \ arabic.c \ arglist.c \ autocmd.c \ *************** *** 425,430 **** --- 426,432 ---- $(XDIFF_SRC) OBJ = \ + alloc.obj \ arabic.obj \ arglist.obj \ autocmd.obj \ *************** *** 738,743 **** --- 740,748 ---- -@ ! .ENDIF + alloc.obj : alloc.c vim.h [.auto]config.h feature.h os_unix.h \ + ascii.h keymap.h term.h macros.h structs.h regexp.h gui.h beval.h \ + [.proto]gui_beval.pro option.h ex_cmds.h proto.h errors.h globals.h arabic.obj : arabic.c vim.h arglist.obj : arglist.c vim.h [.auto]config.h feature.h os_unix.h autocmd.obj : autocmd.c vim.h [.auto]config.h feature.h os_unix.h *** ../vim-8.2.3300/src/Makefile 2021-07-10 21:28:55.323050112 +0200 --- src/Makefile 2021-08-06 21:45:45.293392385 +0200 *************** *** 1590,1595 **** --- 1590,1596 ---- # ALL_SRC: source files used for make depend and make lint BASIC_SRC = \ + alloc.c \ arabic.c \ arglist.c \ autocmd.c \ *************** *** 1747,1752 **** --- 1748,1754 ---- #LINT_SRC = $(BASIC_SRC) OBJ_COMMON = \ + objects/alloc.o \ objects/arabic.o \ objects/arglist.o \ objects/autocmd.o \ *************** *** 1917,1922 **** --- 1919,1925 ---- PRO_AUTO = \ + alloc.pro \ arabic.pro \ arglist.pro \ autocmd.pro \ *************** *** 3150,3155 **** --- 3153,3161 ---- # time. $(ALL_OBJ): objects/.dirstamp + objects/alloc.o: alloc.c + $(CCC) -o $@ alloc.c + objects/arabic.o: arabic.c $(CCC) -o $@ arabic.c *************** *** 3711,3716 **** --- 3717,3726 ---- ############################################################################### ### (automatically generated by 'make depend') ### Dependencies: + objects/alloc.o: alloc.c vim.h protodef.h auto/config.h feature.h os_unix.h \ + auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \ + proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \ + proto.h errors.h globals.h objects/arabic.o: arabic.c vim.h protodef.h auto/config.h feature.h os_unix.h \ auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \ proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \ *** ../vim-8.2.3300/src/README.md 2021-07-10 21:28:55.323050112 +0200 --- src/README.md 2021-08-06 21:45:45.293392385 +0200 *************** *** 23,28 **** --- 23,29 ---- File name | Description --------------- | ----------- + alloc.c | memory management arglist.c | handling argument list autocmd.c | autocommands blob.c | blob data type *** ../vim-8.2.3300/src/alloc.c 2021-08-06 21:50:45.728793017 +0200 --- src/alloc.c 2021-08-06 21:45:45.293392385 +0200 *************** *** 0 **** --- 1,872 ---- + /* vi:set ts=8 sts=4 sw=4 noet: + * + * VIM - Vi IMproved by Bram Moolenaar + * + * Do ":help uganda" in Vim to read copying and usage conditions. + * Do ":help credits" in Vim to see a list of people who contributed. + * See README.txt for an overview of the Vim source code. + */ + + /* + * alloc.c: functions for memory management + */ + + #include "vim.h" + + /********************************************************************** + * Various routines dealing with allocation and deallocation of memory. + */ + + #if defined(MEM_PROFILE) || defined(PROTO) + + # define MEM_SIZES 8200 + static long_u mem_allocs[MEM_SIZES]; + static long_u mem_frees[MEM_SIZES]; + static long_u mem_allocated; + static long_u mem_freed; + static long_u mem_peak; + static long_u num_alloc; + static long_u num_freed; + + static void + mem_pre_alloc_s(size_t *sizep) + { + *sizep += sizeof(size_t); + } + + static void + mem_pre_alloc_l(size_t *sizep) + { + *sizep += sizeof(size_t); + } + + static void + mem_post_alloc( + void **pp, + size_t size) + { + if (*pp == NULL) + return; + size -= sizeof(size_t); + *(long_u *)*pp = size; + if (size <= MEM_SIZES-1) + mem_allocs[size-1]++; + else + mem_allocs[MEM_SIZES-1]++; + mem_allocated += size; + if (mem_allocated - mem_freed > mem_peak) + mem_peak = mem_allocated - mem_freed; + num_alloc++; + *pp = (void *)((char *)*pp + sizeof(size_t)); + } + + static void + mem_pre_free(void **pp) + { + long_u size; + + *pp = (void *)((char *)*pp - sizeof(size_t)); + size = *(size_t *)*pp; + if (size <= MEM_SIZES-1) + mem_frees[size-1]++; + else + mem_frees[MEM_SIZES-1]++; + mem_freed += size; + num_freed++; + } + + /* + * called on exit via atexit() + */ + void + vim_mem_profile_dump(void) + { + int i, j; + + printf("\r\n"); + j = 0; + for (i = 0; i < MEM_SIZES - 1; i++) + { + if (mem_allocs[i] || mem_frees[i]) + { + if (mem_frees[i] > mem_allocs[i]) + printf("\r\n%s", _("ERROR: ")); + printf("[%4d / %4lu-%-4lu] ", i + 1, mem_allocs[i], mem_frees[i]); + j++; + if (j > 3) + { + j = 0; + printf("\r\n"); + } + } + } + + i = MEM_SIZES - 1; + if (mem_allocs[i]) + { + printf("\r\n"); + if (mem_frees[i] > mem_allocs[i]) + puts(_("ERROR: ")); + printf("[>%d / %4lu-%-4lu]", i, mem_allocs[i], mem_frees[i]); + } + + printf(_("\n[bytes] total alloc-freed %lu-%lu, in use %lu, peak use %lu\n"), + mem_allocated, mem_freed, mem_allocated - mem_freed, mem_peak); + printf(_("[calls] total re/malloc()'s %lu, total free()'s %lu\n\n"), + num_alloc, num_freed); + } + + #endif // MEM_PROFILE + + #ifdef FEAT_EVAL + int + alloc_does_fail(size_t size) + { + if (alloc_fail_countdown == 0) + { + if (--alloc_fail_repeat <= 0) + alloc_fail_id = 0; + do_outofmem_msg(size); + return TRUE; + } + --alloc_fail_countdown; + return FALSE; + } + #endif + + /* + * Some memory is reserved for error messages and for being able to + * call mf_release_all(), which needs some memory for mf_trans_add(). + */ + #define KEEP_ROOM (2 * 8192L) + #define KEEP_ROOM_KB (KEEP_ROOM / 1024L) + + /* + * The normal way to allocate memory. This handles an out-of-memory situation + * as well as possible, still returns NULL when we're completely out. + */ + void * + alloc(size_t size) + { + return lalloc(size, TRUE); + } + + /* + * alloc() with an ID for alloc_fail(). + */ + void * + alloc_id(size_t size, alloc_id_T id UNUSED) + { + #ifdef FEAT_EVAL + if (alloc_fail_id == id && alloc_does_fail(size)) + return NULL; + #endif + return lalloc(size, TRUE); + } + + /* + * Allocate memory and set all bytes to zero. + */ + void * + alloc_clear(size_t size) + { + void *p; + + p = lalloc(size, TRUE); + if (p != NULL) + (void)vim_memset(p, 0, size); + return p; + } + + /* + * Same as alloc_clear() but with allocation id for testing + */ + void * + alloc_clear_id(size_t size, alloc_id_T id UNUSED) + { + #ifdef FEAT_EVAL + if (alloc_fail_id == id && alloc_does_fail(size)) + return NULL; + #endif + return alloc_clear(size); + } + + /* + * Allocate memory like lalloc() and set all bytes to zero. + */ + void * + lalloc_clear(size_t size, int message) + { + void *p; + + p = lalloc(size, message); + if (p != NULL) + (void)vim_memset(p, 0, size); + return p; + } + + /* + * Low level memory allocation function. + * This is used often, KEEP IT FAST! + */ + void * + lalloc(size_t size, int message) + { + void *p; // pointer to new storage space + static int releasing = FALSE; // don't do mf_release_all() recursive + int try_again; + #if defined(HAVE_AVAIL_MEM) + static size_t allocated = 0; // allocated since last avail check + #endif + + // Safety check for allocating zero bytes + if (size == 0) + { + // Don't hide this message + emsg_silent = 0; + iemsg(_("E341: Internal error: lalloc(0, )")); + return NULL; + } + + #ifdef MEM_PROFILE + mem_pre_alloc_l(&size); + #endif + + /* + * Loop when out of memory: Try to release some memfile blocks and + * if some blocks are released call malloc again. + */ + for (;;) + { + /* + * Handle three kind of systems: + * 1. No check for available memory: Just return. + * 2. Slow check for available memory: call mch_avail_mem() after + * allocating KEEP_ROOM amount of memory. + * 3. Strict check for available memory: call mch_avail_mem() + */ + if ((p = malloc(size)) != NULL) + { + #ifndef HAVE_AVAIL_MEM + // 1. No check for available memory: Just return. + goto theend; + #else + // 2. Slow check for available memory: call mch_avail_mem() after + // allocating (KEEP_ROOM / 2) amount of memory. + allocated += size; + if (allocated < KEEP_ROOM / 2) + goto theend; + allocated = 0; + + // 3. check for available memory: call mch_avail_mem() + if (mch_avail_mem(TRUE) < KEEP_ROOM_KB && !releasing) + { + free(p); // System is low... no go! + p = NULL; + } + else + goto theend; + #endif + } + /* + * Remember that mf_release_all() is being called to avoid an endless + * loop, because mf_release_all() may call alloc() recursively. + */ + if (releasing) + break; + releasing = TRUE; + + clear_sb_text(TRUE); // free any scrollback text + try_again = mf_release_all(); // release as many blocks as possible + + releasing = FALSE; + if (!try_again) + break; + } + + if (message && p == NULL) + do_outofmem_msg(size); + + theend: + #ifdef MEM_PROFILE + mem_post_alloc(&p, size); + #endif + return p; + } + + /* + * lalloc() with an ID for alloc_fail(). + */ + #if defined(FEAT_SIGNS) || defined(PROTO) + void * + lalloc_id(size_t size, int message, alloc_id_T id UNUSED) + { + #ifdef FEAT_EVAL + if (alloc_fail_id == id && alloc_does_fail(size)) + return NULL; + #endif + return (lalloc(size, message)); + } + #endif + + #if defined(MEM_PROFILE) || defined(PROTO) + /* + * realloc() with memory profiling. + */ + void * + mem_realloc(void *ptr, size_t size) + { + void *p; + + mem_pre_free(&ptr); + mem_pre_alloc_s(&size); + + p = realloc(ptr, size); + + mem_post_alloc(&p, size); + + return p; + } + #endif + + /* + * Avoid repeating the error message many times (they take 1 second each). + * Did_outofmem_msg is reset when a character is read. + */ + void + do_outofmem_msg(size_t size) + { + if (!did_outofmem_msg) + { + // Don't hide this message + emsg_silent = 0; + + // Must come first to avoid coming back here when printing the error + // message fails, e.g. when setting v:errmsg. + did_outofmem_msg = TRUE; + + semsg(_("E342: Out of memory! (allocating %lu bytes)"), (long_u)size); + + if (starting == NO_SCREEN) + // Not even finished with initializations and already out of + // memory? Then nothing is going to work, exit. + mch_exit(123); + } + } + + #if defined(EXITFREE) || defined(PROTO) + + /* + * Free everything that we allocated. + * Can be used to detect memory leaks, e.g., with ccmalloc. + * NOTE: This is tricky! Things are freed that functions depend on. Don't be + * surprised if Vim crashes... + * Some things can't be freed, esp. things local to a library function. + */ + void + free_all_mem(void) + { + buf_T *buf, *nextbuf; + + // When we cause a crash here it is caught and Vim tries to exit cleanly. + // Don't try freeing everything again. + if (entered_free_all_mem) + return; + entered_free_all_mem = TRUE; + // Don't want to trigger autocommands from here on. + block_autocmds(); + + // Close all tabs and windows. Reset 'equalalways' to avoid redraws. + p_ea = FALSE; + if (first_tabpage != NULL && first_tabpage->tp_next != NULL) + do_cmdline_cmd((char_u *)"tabonly!"); + if (!ONE_WINDOW) + do_cmdline_cmd((char_u *)"only!"); + + # if defined(FEAT_SPELL) + // Free all spell info. + spell_free_all(); + # endif + + # if defined(FEAT_BEVAL_TERM) + ui_remove_balloon(); + # endif + # ifdef FEAT_PROP_POPUP + if (curwin != NULL) + close_all_popups(TRUE); + # endif + + // Clear user commands (before deleting buffers). + ex_comclear(NULL); + + // When exiting from mainerr_arg_missing curbuf has not been initialized, + // and not much else. + if (curbuf != NULL) + { + # ifdef FEAT_MENU + // Clear menus. + do_cmdline_cmd((char_u *)"aunmenu *"); + # ifdef FEAT_MULTI_LANG + do_cmdline_cmd((char_u *)"menutranslate clear"); + # endif + # endif + // Clear mappings, abbreviations, breakpoints. + do_cmdline_cmd((char_u *)"lmapclear"); + do_cmdline_cmd((char_u *)"xmapclear"); + do_cmdline_cmd((char_u *)"mapclear"); + do_cmdline_cmd((char_u *)"mapclear!"); + do_cmdline_cmd((char_u *)"abclear"); + # if defined(FEAT_EVAL) + do_cmdline_cmd((char_u *)"breakdel *"); + # endif + # if defined(FEAT_PROFILE) + do_cmdline_cmd((char_u *)"profdel *"); + # endif + # if defined(FEAT_KEYMAP) + do_cmdline_cmd((char_u *)"set keymap="); + # endif + } + + # ifdef FEAT_TITLE + free_titles(); + # endif + # if defined(FEAT_SEARCHPATH) + free_findfile(); + # endif + + // Obviously named calls. + free_all_autocmds(); + clear_termcodes(); + free_all_marks(); + alist_clear(&global_alist); + free_homedir(); + free_users(); + free_search_patterns(); + free_old_sub(); + free_last_insert(); + free_insexpand_stuff(); + free_prev_shellcmd(); + free_regexp_stuff(); + free_tag_stuff(); + free_cd_dir(); + # ifdef FEAT_SIGNS + free_signs(); + # endif + # ifdef FEAT_EVAL + set_expr_line(NULL, NULL); + # endif + # ifdef FEAT_DIFF + if (curtab != NULL) + diff_clear(curtab); + # endif + clear_sb_text(TRUE); // free any scrollback text + + // Free some global vars. + free_username(); + # ifdef FEAT_CLIPBOARD + vim_regfree(clip_exclude_prog); + # endif + vim_free(last_cmdline); + vim_free(new_last_cmdline); + set_keep_msg(NULL, 0); + + // Clear cmdline history. + p_hi = 0; + init_history(); + # ifdef FEAT_PROP_POPUP + clear_global_prop_types(); + # endif + + # ifdef FEAT_QUICKFIX + { + win_T *win; + tabpage_T *tab; + + qf_free_all(NULL); + // Free all location lists + FOR_ALL_TAB_WINDOWS(tab, win) + qf_free_all(win); + } + # endif + + // Close all script inputs. + close_all_scripts(); + + if (curwin != NULL) + // Destroy all windows. Must come before freeing buffers. + win_free_all(); + + // Free all option values. Must come after closing windows. + free_all_options(); + + // Free all buffers. Reset 'autochdir' to avoid accessing things that + // were freed already. + # ifdef FEAT_AUTOCHDIR + p_acd = FALSE; + # endif + for (buf = firstbuf; buf != NULL; ) + { + bufref_T bufref; + + set_bufref(&bufref, buf); + nextbuf = buf->b_next; + close_buffer(NULL, buf, DOBUF_WIPE, FALSE, FALSE); + if (bufref_valid(&bufref)) + buf = nextbuf; // didn't work, try next one + else + buf = firstbuf; + } + + # ifdef FEAT_ARABIC + free_arshape_buf(); + # endif + + // Clear registers. + clear_registers(); + ResetRedobuff(); + ResetRedobuff(); + + # if defined(FEAT_CLIENTSERVER) && defined(FEAT_X11) + vim_free(serverDelayedStartName); + # endif + + // highlight info + free_highlight(); + + reset_last_sourcing(); + + if (first_tabpage != NULL) + { + free_tabpage(first_tabpage); + first_tabpage = NULL; + } + + # ifdef UNIX + // Machine-specific free. + mch_free_mem(); + # endif + + // message history + for (;;) + if (delete_first_msg() == FAIL) + break; + + # ifdef FEAT_JOB_CHANNEL + channel_free_all(); + # endif + # ifdef FEAT_TIMERS + timer_free_all(); + # endif + # ifdef FEAT_EVAL + // must be after channel_free_all() with unrefs partials + eval_clear(); + # endif + # ifdef FEAT_JOB_CHANNEL + // must be after eval_clear() with unrefs jobs + job_free_all(); + # endif + + free_termoptions(); + + // screenlines (can't display anything now!) + free_screenlines(); + + # if defined(FEAT_SOUND) + sound_free(); + # endif + # if defined(USE_XSMP) + xsmp_close(); + # endif + # ifdef FEAT_GUI_GTK + gui_mch_free_all(); + # endif + clear_hl_tables(); + + vim_free(IObuff); + vim_free(NameBuff); + # ifdef FEAT_QUICKFIX + check_quickfix_busy(); + # endif + } + #endif + + /* + * Copy "p[len]" into allocated memory, ignoring NUL characters. + * Returns NULL when out of memory. + */ + char_u * + vim_memsave(char_u *p, size_t len) + { + char_u *ret = alloc(len); + + if (ret != NULL) + mch_memmove(ret, p, len); + return ret; + } + + /* + * Replacement for free() that ignores NULL pointers. + * Also skip free() when exiting for sure, this helps when we caught a deadly + * signal that was caused by a crash in free(). + * If you want to set NULL after calling this function, you should use + * VIM_CLEAR() instead. + */ + void + vim_free(void *x) + { + if (x != NULL && !really_exiting) + { + #ifdef MEM_PROFILE + mem_pre_free(&x); + #endif + free(x); + } + } + + /************************************************************************ + * Functions for handling growing arrays. + */ + + /* + * Clear an allocated growing array. + */ + void + ga_clear(garray_T *gap) + { + vim_free(gap->ga_data); + ga_init(gap); + } + + /* + * Clear a growing array that contains a list of strings. + */ + void + ga_clear_strings(garray_T *gap) + { + int i; + + if (gap->ga_data != NULL) + for (i = 0; i < gap->ga_len; ++i) + vim_free(((char_u **)(gap->ga_data))[i]); + ga_clear(gap); + } + + /* + * Copy a growing array that contains a list of strings. + */ + int + ga_copy_strings(garray_T *from, garray_T *to) + { + int i; + + ga_init2(to, sizeof(char_u *), 1); + if (ga_grow(to, from->ga_len) == FAIL) + return FAIL; + + for (i = 0; i < from->ga_len; ++i) + { + char_u *orig = ((char_u **)from->ga_data)[i]; + char_u *copy; + + if (orig == NULL) + copy = NULL; + else + { + copy = vim_strsave(orig); + if (copy == NULL) + { + to->ga_len = i; + ga_clear_strings(to); + return FAIL; + } + } + ((char_u **)to->ga_data)[i] = copy; + } + to->ga_len = from->ga_len; + return OK; + } + + /* + * Initialize a growing array. Don't forget to set ga_itemsize and + * ga_growsize! Or use ga_init2(). + */ + void + ga_init(garray_T *gap) + { + gap->ga_data = NULL; + gap->ga_maxlen = 0; + gap->ga_len = 0; + } + + void + ga_init2(garray_T *gap, int itemsize, int growsize) + { + ga_init(gap); + gap->ga_itemsize = itemsize; + gap->ga_growsize = growsize; + } + + /* + * Make room in growing array "gap" for at least "n" items. + * Return FAIL for failure, OK otherwise. + */ + int + ga_grow(garray_T *gap, int n) + { + if (gap->ga_maxlen - gap->ga_len < n) + return ga_grow_inner(gap, n); + return OK; + } + + int + ga_grow_inner(garray_T *gap, int n) + { + size_t old_len; + size_t new_len; + char_u *pp; + + if (n < gap->ga_growsize) + n = gap->ga_growsize; + + // A linear growth is very inefficient when the array grows big. This + // is a compromise between allocating memory that won't be used and too + // many copy operations. A factor of 1.5 seems reasonable. + if (n < gap->ga_len / 2) + n = gap->ga_len / 2; + + new_len = gap->ga_itemsize * (gap->ga_len + n); + pp = vim_realloc(gap->ga_data, new_len); + if (pp == NULL) + return FAIL; + old_len = gap->ga_itemsize * gap->ga_maxlen; + vim_memset(pp + old_len, 0, new_len - old_len); + gap->ga_maxlen = gap->ga_len + n; + gap->ga_data = pp; + return OK; + } + + /* + * For a growing array that contains a list of strings: concatenate all the + * strings with a separating "sep". + * Returns NULL when out of memory. + */ + char_u * + ga_concat_strings(garray_T *gap, char *sep) + { + int i; + int len = 0; + int sep_len = (int)STRLEN(sep); + char_u *s; + char_u *p; + + for (i = 0; i < gap->ga_len; ++i) + len += (int)STRLEN(((char_u **)(gap->ga_data))[i]) + sep_len; + + s = alloc(len + 1); + if (s != NULL) + { + *s = NUL; + p = s; + for (i = 0; i < gap->ga_len; ++i) + { + if (p != s) + { + STRCPY(p, sep); + p += sep_len; + } + STRCPY(p, ((char_u **)(gap->ga_data))[i]); + p += STRLEN(p); + } + } + return s; + } + + /* + * Make a copy of string "p" and add it to "gap". + * When out of memory nothing changes and FAIL is returned. + */ + int + ga_add_string(garray_T *gap, char_u *p) + { + char_u *cp = vim_strsave(p); + + if (cp == NULL) + return FAIL; + + if (ga_grow(gap, 1) == FAIL) + { + vim_free(cp); + return FAIL; + } + ((char_u **)(gap->ga_data))[gap->ga_len++] = cp; + return OK; + } + + /* + * Concatenate a string to a growarray which contains bytes. + * When "s" is NULL does not do anything. + * Note: Does NOT copy the NUL at the end! + */ + void + ga_concat(garray_T *gap, char_u *s) + { + int len; + + if (s == NULL || *s == NUL) + return; + len = (int)STRLEN(s); + if (ga_grow(gap, len) == OK) + { + mch_memmove((char *)gap->ga_data + gap->ga_len, s, (size_t)len); + gap->ga_len += len; + } + } + + /* + * Concatenate 'len' bytes from string 's' to a growarray. + * When "s" is NULL does not do anything. + */ + void + ga_concat_len(garray_T *gap, char_u *s, size_t len) + { + if (s == NULL || *s == NUL) + return; + if (ga_grow(gap, (int)len) == OK) + { + mch_memmove((char *)gap->ga_data + gap->ga_len, s, len); + gap->ga_len += (int)len; + } + } + + /* + * Append one byte to a growarray which contains bytes. + */ + void + ga_append(garray_T *gap, int c) + { + if (ga_grow(gap, 1) == OK) + { + *((char *)gap->ga_data + gap->ga_len) = c; + ++gap->ga_len; + } + } + + #if (defined(UNIX) && !defined(USE_SYSTEM)) || defined(MSWIN) \ + || defined(PROTO) + /* + * Append the text in "gap" below the cursor line and clear "gap". + */ + void + append_ga_line(garray_T *gap) + { + // Remove trailing CR. + if (gap->ga_len > 0 + && !curbuf->b_p_bin + && ((char_u *)gap->ga_data)[gap->ga_len - 1] == CAR) + --gap->ga_len; + ga_append(gap, NUL); + ml_append(curwin->w_cursor.lnum++, gap->ga_data, 0, FALSE); + gap->ga_len = 0; + } + #endif + *** ../vim-8.2.3300/src/misc2.c 2021-07-31 12:43:19.464837526 +0200 --- src/misc2.c 2021-08-06 21:45:45.293392385 +0200 *************** *** 693,1289 **** return retval; } - /********************************************************************** - * Various routines dealing with allocation and deallocation of memory. - */ - - #if defined(MEM_PROFILE) || defined(PROTO) - - # define MEM_SIZES 8200 - static long_u mem_allocs[MEM_SIZES]; - static long_u mem_frees[MEM_SIZES]; - static long_u mem_allocated; - static long_u mem_freed; - static long_u mem_peak; - static long_u num_alloc; - static long_u num_freed; - - static void - mem_pre_alloc_s(size_t *sizep) - { - *sizep += sizeof(size_t); - } - - static void - mem_pre_alloc_l(size_t *sizep) - { - *sizep += sizeof(size_t); - } - - static void - mem_post_alloc( - void **pp, - size_t size) - { - if (*pp == NULL) - return; - size -= sizeof(size_t); - *(long_u *)*pp = size; - if (size <= MEM_SIZES-1) - mem_allocs[size-1]++; - else - mem_allocs[MEM_SIZES-1]++; - mem_allocated += size; - if (mem_allocated - mem_freed > mem_peak) - mem_peak = mem_allocated - mem_freed; - num_alloc++; - *pp = (void *)((char *)*pp + sizeof(size_t)); - } - - static void - mem_pre_free(void **pp) - { - long_u size; - - *pp = (void *)((char *)*pp - sizeof(size_t)); - size = *(size_t *)*pp; - if (size <= MEM_SIZES-1) - mem_frees[size-1]++; - else - mem_frees[MEM_SIZES-1]++; - mem_freed += size; - num_freed++; - } - - /* - * called on exit via atexit() - */ - void - vim_mem_profile_dump(void) - { - int i, j; - - printf("\r\n"); - j = 0; - for (i = 0; i < MEM_SIZES - 1; i++) - { - if (mem_allocs[i] || mem_frees[i]) - { - if (mem_frees[i] > mem_allocs[i]) - printf("\r\n%s", _("ERROR: ")); - printf("[%4d / %4lu-%-4lu] ", i + 1, mem_allocs[i], mem_frees[i]); - j++; - if (j > 3) - { - j = 0; - printf("\r\n"); - } - } - } - - i = MEM_SIZES - 1; - if (mem_allocs[i]) - { - printf("\r\n"); - if (mem_frees[i] > mem_allocs[i]) - puts(_("ERROR: ")); - printf("[>%d / %4lu-%-4lu]", i, mem_allocs[i], mem_frees[i]); - } - - printf(_("\n[bytes] total alloc-freed %lu-%lu, in use %lu, peak use %lu\n"), - mem_allocated, mem_freed, mem_allocated - mem_freed, mem_peak); - printf(_("[calls] total re/malloc()'s %lu, total free()'s %lu\n\n"), - num_alloc, num_freed); - } - - #endif // MEM_PROFILE - - #ifdef FEAT_EVAL - int - alloc_does_fail(size_t size) - { - if (alloc_fail_countdown == 0) - { - if (--alloc_fail_repeat <= 0) - alloc_fail_id = 0; - do_outofmem_msg(size); - return TRUE; - } - --alloc_fail_countdown; - return FALSE; - } - #endif - - /* - * Some memory is reserved for error messages and for being able to - * call mf_release_all(), which needs some memory for mf_trans_add(). - */ - #define KEEP_ROOM (2 * 8192L) - #define KEEP_ROOM_KB (KEEP_ROOM / 1024L) - - /* - * The normal way to allocate memory. This handles an out-of-memory situation - * as well as possible, still returns NULL when we're completely out. - */ - void * - alloc(size_t size) - { - return lalloc(size, TRUE); - } - - /* - * alloc() with an ID for alloc_fail(). - */ - void * - alloc_id(size_t size, alloc_id_T id UNUSED) - { - #ifdef FEAT_EVAL - if (alloc_fail_id == id && alloc_does_fail(size)) - return NULL; - #endif - return lalloc(size, TRUE); - } - - /* - * Allocate memory and set all bytes to zero. - */ - void * - alloc_clear(size_t size) - { - void *p; - - p = lalloc(size, TRUE); - if (p != NULL) - (void)vim_memset(p, 0, size); - return p; - } - - /* - * Same as alloc_clear() but with allocation id for testing - */ - void * - alloc_clear_id(size_t size, alloc_id_T id UNUSED) - { - #ifdef FEAT_EVAL - if (alloc_fail_id == id && alloc_does_fail(size)) - return NULL; - #endif - return alloc_clear(size); - } - - /* - * Allocate memory like lalloc() and set all bytes to zero. - */ - void * - lalloc_clear(size_t size, int message) - { - void *p; - - p = lalloc(size, message); - if (p != NULL) - (void)vim_memset(p, 0, size); - return p; - } - - /* - * Low level memory allocation function. - * This is used often, KEEP IT FAST! - */ - void * - lalloc(size_t size, int message) - { - void *p; // pointer to new storage space - static int releasing = FALSE; // don't do mf_release_all() recursive - int try_again; - #if defined(HAVE_AVAIL_MEM) - static size_t allocated = 0; // allocated since last avail check - #endif - - // Safety check for allocating zero bytes - if (size == 0) - { - // Don't hide this message - emsg_silent = 0; - iemsg(_("E341: Internal error: lalloc(0, )")); - return NULL; - } - - #ifdef MEM_PROFILE - mem_pre_alloc_l(&size); - #endif - - /* - * Loop when out of memory: Try to release some memfile blocks and - * if some blocks are released call malloc again. - */ - for (;;) - { - /* - * Handle three kind of systems: - * 1. No check for available memory: Just return. - * 2. Slow check for available memory: call mch_avail_mem() after - * allocating KEEP_ROOM amount of memory. - * 3. Strict check for available memory: call mch_avail_mem() - */ - if ((p = malloc(size)) != NULL) - { - #ifndef HAVE_AVAIL_MEM - // 1. No check for available memory: Just return. - goto theend; - #else - // 2. Slow check for available memory: call mch_avail_mem() after - // allocating (KEEP_ROOM / 2) amount of memory. - allocated += size; - if (allocated < KEEP_ROOM / 2) - goto theend; - allocated = 0; - - // 3. check for available memory: call mch_avail_mem() - if (mch_avail_mem(TRUE) < KEEP_ROOM_KB && !releasing) - { - free(p); // System is low... no go! - p = NULL; - } - else - goto theend; - #endif - } - /* - * Remember that mf_release_all() is being called to avoid an endless - * loop, because mf_release_all() may call alloc() recursively. - */ - if (releasing) - break; - releasing = TRUE; - - clear_sb_text(TRUE); // free any scrollback text - try_again = mf_release_all(); // release as many blocks as possible - - releasing = FALSE; - if (!try_again) - break; - } - - if (message && p == NULL) - do_outofmem_msg(size); - - theend: - #ifdef MEM_PROFILE - mem_post_alloc(&p, size); - #endif - return p; - } - - /* - * lalloc() with an ID for alloc_fail(). - */ - #if defined(FEAT_SIGNS) || defined(PROTO) - void * - lalloc_id(size_t size, int message, alloc_id_T id UNUSED) - { - #ifdef FEAT_EVAL - if (alloc_fail_id == id && alloc_does_fail(size)) - return NULL; - #endif - return (lalloc(size, message)); - } - #endif - - #if defined(MEM_PROFILE) || defined(PROTO) - /* - * realloc() with memory profiling. - */ - void * - mem_realloc(void *ptr, size_t size) - { - void *p; - - mem_pre_free(&ptr); - mem_pre_alloc_s(&size); - - p = realloc(ptr, size); - - mem_post_alloc(&p, size); - - return p; - } - #endif - - /* - * Avoid repeating the error message many times (they take 1 second each). - * Did_outofmem_msg is reset when a character is read. - */ - void - do_outofmem_msg(size_t size) - { - if (!did_outofmem_msg) - { - // Don't hide this message - emsg_silent = 0; - - // Must come first to avoid coming back here when printing the error - // message fails, e.g. when setting v:errmsg. - did_outofmem_msg = TRUE; - - semsg(_("E342: Out of memory! (allocating %lu bytes)"), (long_u)size); - - if (starting == NO_SCREEN) - // Not even finished with initializations and already out of - // memory? Then nothing is going to work, exit. - mch_exit(123); - } - } - - #if defined(EXITFREE) || defined(PROTO) - - /* - * Free everything that we allocated. - * Can be used to detect memory leaks, e.g., with ccmalloc. - * NOTE: This is tricky! Things are freed that functions depend on. Don't be - * surprised if Vim crashes... - * Some things can't be freed, esp. things local to a library function. - */ - void - free_all_mem(void) - { - buf_T *buf, *nextbuf; - - // When we cause a crash here it is caught and Vim tries to exit cleanly. - // Don't try freeing everything again. - if (entered_free_all_mem) - return; - entered_free_all_mem = TRUE; - // Don't want to trigger autocommands from here on. - block_autocmds(); - - // Close all tabs and windows. Reset 'equalalways' to avoid redraws. - p_ea = FALSE; - if (first_tabpage != NULL && first_tabpage->tp_next != NULL) - do_cmdline_cmd((char_u *)"tabonly!"); - if (!ONE_WINDOW) - do_cmdline_cmd((char_u *)"only!"); - - # if defined(FEAT_SPELL) - // Free all spell info. - spell_free_all(); - # endif - - # if defined(FEAT_BEVAL_TERM) - ui_remove_balloon(); - # endif - # ifdef FEAT_PROP_POPUP - if (curwin != NULL) - close_all_popups(TRUE); - # endif - - // Clear user commands (before deleting buffers). - ex_comclear(NULL); - - // When exiting from mainerr_arg_missing curbuf has not been initialized, - // and not much else. - if (curbuf != NULL) - { - # ifdef FEAT_MENU - // Clear menus. - do_cmdline_cmd((char_u *)"aunmenu *"); - # ifdef FEAT_MULTI_LANG - do_cmdline_cmd((char_u *)"menutranslate clear"); - # endif - # endif - // Clear mappings, abbreviations, breakpoints. - do_cmdline_cmd((char_u *)"lmapclear"); - do_cmdline_cmd((char_u *)"xmapclear"); - do_cmdline_cmd((char_u *)"mapclear"); - do_cmdline_cmd((char_u *)"mapclear!"); - do_cmdline_cmd((char_u *)"abclear"); - # if defined(FEAT_EVAL) - do_cmdline_cmd((char_u *)"breakdel *"); - # endif - # if defined(FEAT_PROFILE) - do_cmdline_cmd((char_u *)"profdel *"); - # endif - # if defined(FEAT_KEYMAP) - do_cmdline_cmd((char_u *)"set keymap="); - # endif - } - - # ifdef FEAT_TITLE - free_titles(); - # endif - # if defined(FEAT_SEARCHPATH) - free_findfile(); - # endif - - // Obviously named calls. - free_all_autocmds(); - clear_termcodes(); - free_all_marks(); - alist_clear(&global_alist); - free_homedir(); - free_users(); - free_search_patterns(); - free_old_sub(); - free_last_insert(); - free_insexpand_stuff(); - free_prev_shellcmd(); - free_regexp_stuff(); - free_tag_stuff(); - free_cd_dir(); - # ifdef FEAT_SIGNS - free_signs(); - # endif - # ifdef FEAT_EVAL - set_expr_line(NULL, NULL); - # endif - # ifdef FEAT_DIFF - if (curtab != NULL) - diff_clear(curtab); - # endif - clear_sb_text(TRUE); // free any scrollback text - - // Free some global vars. - vim_free(username); - # ifdef FEAT_CLIPBOARD - vim_regfree(clip_exclude_prog); - # endif - vim_free(last_cmdline); - vim_free(new_last_cmdline); - set_keep_msg(NULL, 0); - - // Clear cmdline history. - p_hi = 0; - init_history(); - # ifdef FEAT_PROP_POPUP - clear_global_prop_types(); - # endif - - # ifdef FEAT_QUICKFIX - { - win_T *win; - tabpage_T *tab; - - qf_free_all(NULL); - // Free all location lists - FOR_ALL_TAB_WINDOWS(tab, win) - qf_free_all(win); - } - # endif - - // Close all script inputs. - close_all_scripts(); - - if (curwin != NULL) - // Destroy all windows. Must come before freeing buffers. - win_free_all(); - - // Free all option values. Must come after closing windows. - free_all_options(); - - // Free all buffers. Reset 'autochdir' to avoid accessing things that - // were freed already. - # ifdef FEAT_AUTOCHDIR - p_acd = FALSE; - # endif - for (buf = firstbuf; buf != NULL; ) - { - bufref_T bufref; - - set_bufref(&bufref, buf); - nextbuf = buf->b_next; - close_buffer(NULL, buf, DOBUF_WIPE, FALSE, FALSE); - if (bufref_valid(&bufref)) - buf = nextbuf; // didn't work, try next one - else - buf = firstbuf; - } - - # ifdef FEAT_ARABIC - free_arshape_buf(); - # endif - - // Clear registers. - clear_registers(); - ResetRedobuff(); - ResetRedobuff(); - - # if defined(FEAT_CLIENTSERVER) && defined(FEAT_X11) - vim_free(serverDelayedStartName); - # endif - - // highlight info - free_highlight(); - - reset_last_sourcing(); - - if (first_tabpage != NULL) - { - free_tabpage(first_tabpage); - first_tabpage = NULL; - } - - # ifdef UNIX - // Machine-specific free. - mch_free_mem(); - # endif - - // message history - for (;;) - if (delete_first_msg() == FAIL) - break; - - # ifdef FEAT_JOB_CHANNEL - channel_free_all(); - # endif - # ifdef FEAT_TIMERS - timer_free_all(); - # endif - # ifdef FEAT_EVAL - // must be after channel_free_all() with unrefs partials - eval_clear(); - # endif - # ifdef FEAT_JOB_CHANNEL - // must be after eval_clear() with unrefs jobs - job_free_all(); - # endif - - free_termoptions(); - - // screenlines (can't display anything now!) - free_screenlines(); - - # if defined(FEAT_SOUND) - sound_free(); - # endif - # if defined(USE_XSMP) - xsmp_close(); - # endif - # ifdef FEAT_GUI_GTK - gui_mch_free_all(); - # endif - clear_hl_tables(); - - vim_free(IObuff); - vim_free(NameBuff); - # ifdef FEAT_QUICKFIX - check_quickfix_busy(); - # endif - } - #endif - - /* - * Copy "p[len]" into allocated memory, ignoring NUL characters. - * Returns NULL when out of memory. - */ - char_u * - vim_memsave(char_u *p, size_t len) - { - char_u *ret = alloc(len); - - if (ret != NULL) - mch_memmove(ret, p, len); - return ret; - } - /* * Isolate one part of a string option where parts are separated with * "sep_chars". --- 693,698 ---- *************** *** 1325,1349 **** return len; } - /* - * Replacement for free() that ignores NULL pointers. - * Also skip free() when exiting for sure, this helps when we caught a deadly - * signal that was caused by a crash in free(). - * If you want to set NULL after calling this function, you should use - * VIM_CLEAR() instead. - */ - void - vim_free(void *x) - { - if (x != NULL && !really_exiting) - { - #ifdef MEM_PROFILE - mem_pre_free(&x); - #endif - free(x); - } - } - #ifndef HAVE_MEMSET void * vim_memset(void *ptr, int c, size_t size) --- 734,739 ---- *************** *** 1367,1619 **** } /************************************************************************ - * Functions for handling growing arrays. - */ - - /* - * Clear an allocated growing array. - */ - void - ga_clear(garray_T *gap) - { - vim_free(gap->ga_data); - ga_init(gap); - } - - /* - * Clear a growing array that contains a list of strings. - */ - void - ga_clear_strings(garray_T *gap) - { - int i; - - if (gap->ga_data != NULL) - for (i = 0; i < gap->ga_len; ++i) - vim_free(((char_u **)(gap->ga_data))[i]); - ga_clear(gap); - } - - /* - * Copy a growing array that contains a list of strings. - */ - int - ga_copy_strings(garray_T *from, garray_T *to) - { - int i; - - ga_init2(to, sizeof(char_u *), 1); - if (ga_grow(to, from->ga_len) == FAIL) - return FAIL; - - for (i = 0; i < from->ga_len; ++i) - { - char_u *orig = ((char_u **)from->ga_data)[i]; - char_u *copy; - - if (orig == NULL) - copy = NULL; - else - { - copy = vim_strsave(orig); - if (copy == NULL) - { - to->ga_len = i; - ga_clear_strings(to); - return FAIL; - } - } - ((char_u **)to->ga_data)[i] = copy; - } - to->ga_len = from->ga_len; - return OK; - } - - /* - * Initialize a growing array. Don't forget to set ga_itemsize and - * ga_growsize! Or use ga_init2(). - */ - void - ga_init(garray_T *gap) - { - gap->ga_data = NULL; - gap->ga_maxlen = 0; - gap->ga_len = 0; - } - - void - ga_init2(garray_T *gap, int itemsize, int growsize) - { - ga_init(gap); - gap->ga_itemsize = itemsize; - gap->ga_growsize = growsize; - } - - /* - * Make room in growing array "gap" for at least "n" items. - * Return FAIL for failure, OK otherwise. - */ - int - ga_grow(garray_T *gap, int n) - { - if (gap->ga_maxlen - gap->ga_len < n) - return ga_grow_inner(gap, n); - return OK; - } - - int - ga_grow_inner(garray_T *gap, int n) - { - size_t old_len; - size_t new_len; - char_u *pp; - - if (n < gap->ga_growsize) - n = gap->ga_growsize; - - // A linear growth is very inefficient when the array grows big. This - // is a compromise between allocating memory that won't be used and too - // many copy operations. A factor of 1.5 seems reasonable. - if (n < gap->ga_len / 2) - n = gap->ga_len / 2; - - new_len = gap->ga_itemsize * (gap->ga_len + n); - pp = vim_realloc(gap->ga_data, new_len); - if (pp == NULL) - return FAIL; - old_len = gap->ga_itemsize * gap->ga_maxlen; - vim_memset(pp + old_len, 0, new_len - old_len); - gap->ga_maxlen = gap->ga_len + n; - gap->ga_data = pp; - return OK; - } - - /* - * For a growing array that contains a list of strings: concatenate all the - * strings with a separating "sep". - * Returns NULL when out of memory. - */ - char_u * - ga_concat_strings(garray_T *gap, char *sep) - { - int i; - int len = 0; - int sep_len = (int)STRLEN(sep); - char_u *s; - char_u *p; - - for (i = 0; i < gap->ga_len; ++i) - len += (int)STRLEN(((char_u **)(gap->ga_data))[i]) + sep_len; - - s = alloc(len + 1); - if (s != NULL) - { - *s = NUL; - p = s; - for (i = 0; i < gap->ga_len; ++i) - { - if (p != s) - { - STRCPY(p, sep); - p += sep_len; - } - STRCPY(p, ((char_u **)(gap->ga_data))[i]); - p += STRLEN(p); - } - } - return s; - } - - /* - * Make a copy of string "p" and add it to "gap". - * When out of memory nothing changes and FAIL is returned. - */ - int - ga_add_string(garray_T *gap, char_u *p) - { - char_u *cp = vim_strsave(p); - - if (cp == NULL) - return FAIL; - - if (ga_grow(gap, 1) == FAIL) - { - vim_free(cp); - return FAIL; - } - ((char_u **)(gap->ga_data))[gap->ga_len++] = cp; - return OK; - } - - /* - * Concatenate a string to a growarray which contains bytes. - * When "s" is NULL does not do anything. - * Note: Does NOT copy the NUL at the end! - */ - void - ga_concat(garray_T *gap, char_u *s) - { - int len; - - if (s == NULL || *s == NUL) - return; - len = (int)STRLEN(s); - if (ga_grow(gap, len) == OK) - { - mch_memmove((char *)gap->ga_data + gap->ga_len, s, (size_t)len); - gap->ga_len += len; - } - } - - /* - * Concatenate 'len' bytes from string 's' to a growarray. - * When "s" is NULL does not do anything. - */ - void - ga_concat_len(garray_T *gap, char_u *s, size_t len) - { - if (s == NULL || *s == NUL) - return; - if (ga_grow(gap, (int)len) == OK) - { - mch_memmove((char *)gap->ga_data + gap->ga_len, s, len); - gap->ga_len += (int)len; - } - } - - /* - * Append one byte to a growarray which contains bytes. - */ - void - ga_append(garray_T *gap, int c) - { - if (ga_grow(gap, 1) == OK) - { - *((char *)gap->ga_data + gap->ga_len) = c; - ++gap->ga_len; - } - } - - #if (defined(UNIX) && !defined(USE_SYSTEM)) || defined(MSWIN) \ - || defined(PROTO) - /* - * Append the text in "gap" below the cursor line and clear "gap". - */ - void - append_ga_line(garray_T *gap) - { - // Remove trailing CR. - if (gap->ga_len > 0 - && !curbuf->b_p_bin - && ((char_u *)gap->ga_data)[gap->ga_len - 1] == CAR) - --gap->ga_len; - ga_append(gap, NUL); - ml_append(curwin->w_cursor.lnum++, gap->ga_data, 0, FALSE); - gap->ga_len = 0; - } - #endif - - /************************************************************************ * functions that use lookup tables for various things, generally to do with * special key codes. */ --- 757,762 ---- *************** *** 3282,3287 **** --- 2425,2439 ---- return OK; } + /* + * Free the memory allocated by get_user_name() + */ + void + free_username(void) + { + vim_free(username); + } + #ifndef HAVE_QSORT /* * Our own qsort(), for systems that don't have it. *** ../vim-8.2.3300/src/proto.h 2021-08-02 18:07:15.186473836 +0200 --- src/proto.h 2021-08-06 21:45:45.293392385 +0200 *************** *** 58,63 **** --- 58,64 ---- # include "crypt.pro" # include "crypt_zip.pro" # endif + # include "alloc.pro" # include "arglist.pro" # include "autocmd.pro" # include "buffer.pro" *** ../vim-8.2.3300/src/proto/alloc.pro 2021-08-06 21:50:45.744792984 +0200 --- src/proto/alloc.pro 2021-08-06 21:47:27.585199367 +0200 *************** *** 0 **** --- 1,29 ---- + /* alloc.c */ + void vim_mem_profile_dump(void); + int alloc_does_fail(size_t size); + void *alloc(size_t size); + void *alloc_id(size_t size, alloc_id_T id); + void *alloc_clear(size_t size); + void *alloc_clear_id(size_t size, alloc_id_T id); + void *lalloc_clear(size_t size, int message); + void *lalloc(size_t size, int message); + void *lalloc_id(size_t size, int message, alloc_id_T id); + void *mem_realloc(void *ptr, size_t size); + void do_outofmem_msg(size_t size); + void free_all_mem(void); + char_u *vim_memsave(char_u *p, size_t len); + void vim_free(void *x); + void ga_clear(garray_T *gap); + void ga_clear_strings(garray_T *gap); + int ga_copy_strings(garray_T *from, garray_T *to); + void ga_init(garray_T *gap); + void ga_init2(garray_T *gap, int itemsize, int growsize); + int ga_grow(garray_T *gap, int n); + int ga_grow_inner(garray_T *gap, int n); + char_u *ga_concat_strings(garray_T *gap, char *sep); + int ga_add_string(garray_T *gap, char_u *p); + void ga_concat(garray_T *gap, char_u *s); + void ga_concat_len(garray_T *gap, char_u *s, size_t len); + void ga_append(garray_T *gap, int c); + void append_ga_line(garray_T *gap); + /* vim: set ft=c : */ *** ../vim-8.2.3300/src/proto/misc2.pro 2021-07-29 20:22:10.738009542 +0200 --- src/proto/misc2.pro 2021-08-06 21:47:31.377191966 +0200 *************** *** 19,53 **** void check_cursor(void); void adjust_cursor_col(void); int leftcol_changed(void); - void vim_mem_profile_dump(void); - int alloc_does_fail(size_t size); - void *alloc(size_t size); - void *alloc_id(size_t size, alloc_id_T id); - void *alloc_clear(size_t size); - void *alloc_clear_id(size_t size, alloc_id_T id); - void *lalloc_clear(size_t size, int message); - void *lalloc(size_t size, int message); - void *lalloc_id(size_t size, int message, alloc_id_T id); - void *mem_realloc(void *ptr, size_t size); - void do_outofmem_msg(size_t size); - void free_all_mem(void); - char_u *vim_memsave(char_u *p, size_t len); int copy_option_part(char_u **option, char_u *buf, int maxlen, char *sep_chars); - void vim_free(void *x); int vim_isspace(int x); - void ga_clear(garray_T *gap); - void ga_clear_strings(garray_T *gap); - int ga_copy_strings(garray_T *from, garray_T *to); - void ga_init(garray_T *gap); - void ga_init2(garray_T *gap, int itemsize, int growsize); - int ga_grow(garray_T *gap, int n); - int ga_grow_inner(garray_T *gap, int n); - char_u *ga_concat_strings(garray_T *gap, char *sep); - int ga_add_string(garray_T *gap, char_u *p); - void ga_concat(garray_T *gap, char_u *s); - void ga_concat_len(garray_T *gap, char_u *s, size_t len); - void ga_append(garray_T *gap, int c); - void append_ga_line(garray_T *gap); int simplify_key(int key, int *modifiers); int handle_x_keys(int key); char_u *get_special_key_name(int c, int modifiers); --- 19,26 ---- *************** *** 75,80 **** --- 48,54 ---- void update_mouseshape(int shape_idx); int vim_chdir(char_u *new_dir); int get_user_name(char_u *buf, int len); + void free_username(void); int filewritable(char_u *fname); int get2c(FILE *fd); int get3c(FILE *fd); *** ../vim-8.2.3300/src/version.c 2021-08-06 21:34:34.630972197 +0200 --- src/version.c 2021-08-06 21:47:07.149238948 +0200 *************** *** 757,758 **** --- 757,760 ---- { /* Add new patch number below this line */ + /**/ + 3301, /**/ -- A computer programmer is a device for turning requirements into undocumented features. It runs on cola, pizza and Dilbert cartoons. Bram Moolenaar /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///