mirror of
https://github.com/neovim/neovim.git
synced 2025-09-20 02:08:17 +00:00
Introduce nvim namespace: Move files.
Move files from src/ to src/nvim/. - src/nvim/ becomes the new root dir for nvim executable sources. - src/libnvim/ is planned to become root dir of the neovim library.
This commit is contained in:
388
src/nvim/memory.c
Normal file
388
src/nvim/memory.c
Normal file
@@ -0,0 +1,388 @@
|
||||
// Various routines dealing with allocation and deallocation of memory.
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "vim.h"
|
||||
#include "misc2.h"
|
||||
#include "file_search.h"
|
||||
#include "blowfish.h"
|
||||
#include "buffer.h"
|
||||
#include "charset.h"
|
||||
#include "diff.h"
|
||||
#include "edit.h"
|
||||
#include "eval.h"
|
||||
#include "ex_cmds.h"
|
||||
#include "ex_docmd.h"
|
||||
#include "ex_getln.h"
|
||||
#include "fileio.h"
|
||||
#include "fold.h"
|
||||
#include "getchar.h"
|
||||
#include "mark.h"
|
||||
#include "mbyte.h"
|
||||
#include "memfile.h"
|
||||
#include "memline.h"
|
||||
#include "memory.h"
|
||||
#include "message.h"
|
||||
#include "misc1.h"
|
||||
#include "move.h"
|
||||
#include "option.h"
|
||||
#include "ops.h"
|
||||
#include "os_unix.h"
|
||||
#include "path.h"
|
||||
#include "quickfix.h"
|
||||
#include "regexp.h"
|
||||
#include "screen.h"
|
||||
#include "search.h"
|
||||
#include "spell.h"
|
||||
#include "syntax.h"
|
||||
#include "tag.h"
|
||||
#include "term.h"
|
||||
#include "ui.h"
|
||||
#include "window.h"
|
||||
#include "os/os.h"
|
||||
|
||||
static void try_to_free_memory();
|
||||
|
||||
/*
|
||||
* Note: if unsigned is 16 bits we can only allocate up to 64K with alloc().
|
||||
*/
|
||||
char_u *alloc(unsigned size)
|
||||
{
|
||||
return xmalloc(size);
|
||||
}
|
||||
|
||||
/// Try to free memory. Used when trying to recover from out of memory errors.
|
||||
/// @see {xmalloc}
|
||||
static void try_to_free_memory()
|
||||
{
|
||||
static bool trying_to_free = false;
|
||||
// avoid recursive calls
|
||||
if (trying_to_free)
|
||||
return;
|
||||
trying_to_free = true;
|
||||
|
||||
// free any scrollback text
|
||||
clear_sb_text();
|
||||
// Try to save all buffers and release as many blocks as possible
|
||||
mf_release_all();
|
||||
// cleanup recursive lists/dicts
|
||||
garbage_collect();
|
||||
|
||||
trying_to_free = false;
|
||||
}
|
||||
|
||||
void *try_malloc(size_t size)
|
||||
{
|
||||
void *ret = malloc(size);
|
||||
|
||||
if (!ret && !size) {
|
||||
ret = malloc(1);
|
||||
}
|
||||
if (!ret) {
|
||||
try_to_free_memory();
|
||||
ret = malloc(size);
|
||||
if (!ret && !size) {
|
||||
ret = malloc(1);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *verbose_try_malloc(size_t size)
|
||||
{
|
||||
void *ret = try_malloc(size);
|
||||
if (!ret) {
|
||||
do_outofmem_msg((long_u)size);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *xmalloc(size_t size)
|
||||
{
|
||||
void *ret = try_malloc(size);
|
||||
|
||||
if (!ret) {
|
||||
OUT_STR("Vim: Error: Out of memory.\n");
|
||||
preserve_exit();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *xcalloc(size_t count, size_t size)
|
||||
{
|
||||
void *ret = calloc(count, size);
|
||||
|
||||
if (!ret && (!count || !size))
|
||||
ret = calloc(1, 1);
|
||||
|
||||
if (!ret) {
|
||||
try_to_free_memory();
|
||||
ret = calloc(count, size);
|
||||
if (!ret && (!count || !size))
|
||||
ret = calloc(1, 1);
|
||||
if (!ret) {
|
||||
OUT_STR("Vim: Error: Out of memory.\n");
|
||||
preserve_exit();
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *xrealloc(void *ptr, size_t size)
|
||||
{
|
||||
void *ret = realloc(ptr, size);
|
||||
|
||||
if (!ret && !size)
|
||||
ret = realloc(ptr, 1);
|
||||
|
||||
if (!ret) {
|
||||
try_to_free_memory();
|
||||
ret = realloc(ptr, size);
|
||||
if (!ret && !size)
|
||||
ret = realloc(ptr, 1);
|
||||
if (!ret) {
|
||||
OUT_STR("Vim: Error: Out of memory.\n");
|
||||
preserve_exit();
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *xmallocz(size_t size)
|
||||
{
|
||||
size_t total_size = size + 1;
|
||||
void *ret;
|
||||
|
||||
if (total_size < size) {
|
||||
OUT_STR("Vim: Data too large to fit into virtual memory space\n");
|
||||
preserve_exit();
|
||||
}
|
||||
|
||||
ret = xmalloc(total_size);
|
||||
((char*)ret)[size] = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *xmemdupz(const void *data, size_t len)
|
||||
{
|
||||
return memcpy(xmallocz(len), data, len);
|
||||
}
|
||||
|
||||
char *xstpcpy(char *restrict dst, const char *restrict src)
|
||||
{
|
||||
const size_t len = strlen(src);
|
||||
return (char *)memcpy(dst, src, len + 1) + len;
|
||||
}
|
||||
|
||||
char *xstpncpy(char *restrict dst, const char *restrict src, size_t maxlen)
|
||||
{
|
||||
const char *p = memchr(src, '\0', maxlen);
|
||||
if (p) {
|
||||
size_t srclen = (size_t)(p - src);
|
||||
memcpy(dst, src, srclen);
|
||||
memset(dst + srclen, 0, maxlen - srclen);
|
||||
return dst + srclen;
|
||||
} else {
|
||||
memcpy(dst, src, maxlen);
|
||||
return dst + maxlen;
|
||||
}
|
||||
}
|
||||
|
||||
char * xstrdup(const char *str)
|
||||
{
|
||||
char *ret = strdup(str);
|
||||
|
||||
if (!ret) {
|
||||
try_to_free_memory();
|
||||
ret = strdup(str);
|
||||
if (!ret) {
|
||||
OUT_STR("Vim: Error: Out of memory.\n");
|
||||
preserve_exit();
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *xstrndup(const char *str, size_t len)
|
||||
{
|
||||
char *p = memchr(str, '\0', len);
|
||||
return xmemdupz(str, p ? (size_t)(p - str) : len);
|
||||
}
|
||||
|
||||
char *xmemdup(const char *data, size_t len)
|
||||
{
|
||||
return memcpy(xmalloc(len), data, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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(long_u 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;
|
||||
|
||||
EMSGU(_("E342: Out of memory! (allocating %" PRIu64 " bytes)"), size);
|
||||
}
|
||||
}
|
||||
|
||||
#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;
|
||||
static int entered = FALSE;
|
||||
|
||||
/* When we cause a crash here it is caught and Vim tries to exit cleanly.
|
||||
* Don't try freeing everything again. */
|
||||
if (entered)
|
||||
return;
|
||||
entered = TRUE;
|
||||
|
||||
block_autocmds(); /* don't want to trigger autocommands here */
|
||||
|
||||
/* Close all tabs and windows. Reset 'equalalways' to avoid redraws. */
|
||||
p_ea = FALSE;
|
||||
if (first_tabpage->tp_next != NULL)
|
||||
do_cmdline_cmd((char_u *)"tabonly!");
|
||||
if (firstwin != lastwin)
|
||||
do_cmdline_cmd((char_u *)"only!");
|
||||
|
||||
/* Free all spell info. */
|
||||
spell_free_all();
|
||||
|
||||
/* Clear user commands (before deleting buffers). */
|
||||
ex_comclear(NULL);
|
||||
|
||||
/* Clear menus. */
|
||||
do_cmdline_cmd((char_u *)"aunmenu *");
|
||||
do_cmdline_cmd((char_u *)"menutranslate clear");
|
||||
|
||||
/* 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");
|
||||
do_cmdline_cmd((char_u *)"breakdel *");
|
||||
do_cmdline_cmd((char_u *)"profdel *");
|
||||
do_cmdline_cmd((char_u *)"set keymap=");
|
||||
|
||||
free_titles();
|
||||
free_findfile();
|
||||
|
||||
/* Obviously named calls. */
|
||||
free_all_autocmds();
|
||||
clear_termcodes();
|
||||
free_all_options();
|
||||
free_all_marks();
|
||||
alist_clear(&global_alist);
|
||||
free_homedir();
|
||||
free_users();
|
||||
free_search_patterns();
|
||||
free_old_sub();
|
||||
free_last_insert();
|
||||
free_prev_shellcmd();
|
||||
free_regexp_stuff();
|
||||
free_tag_stuff();
|
||||
free_cd_dir();
|
||||
free_signs();
|
||||
set_expr_line(NULL);
|
||||
diff_clear(curtab);
|
||||
clear_sb_text(); /* free any scrollback text */
|
||||
|
||||
/* Free some global vars. */
|
||||
free(last_cmdline);
|
||||
free(new_last_cmdline);
|
||||
set_keep_msg(NULL, 0);
|
||||
|
||||
/* Clear cmdline history. */
|
||||
p_hi = 0;
|
||||
init_history();
|
||||
|
||||
{
|
||||
win_T *win;
|
||||
tabpage_T *tab;
|
||||
|
||||
qf_free_all(NULL);
|
||||
/* Free all location lists */
|
||||
FOR_ALL_TAB_WINDOWS(tab, win)
|
||||
qf_free_all(win);
|
||||
}
|
||||
|
||||
/* Close all script inputs. */
|
||||
close_all_scripts();
|
||||
|
||||
/* Destroy all windows. Must come before freeing buffers. */
|
||||
win_free_all();
|
||||
|
||||
/* Free all buffers. Reset 'autochdir' to avoid accessing things that
|
||||
* were freed already. */
|
||||
p_acd = FALSE;
|
||||
for (buf = firstbuf; buf != NULL; ) {
|
||||
nextbuf = buf->b_next;
|
||||
close_buffer(NULL, buf, DOBUF_WIPE, FALSE);
|
||||
if (buf_valid(buf))
|
||||
buf = nextbuf; /* didn't work, try next one */
|
||||
else
|
||||
buf = firstbuf;
|
||||
}
|
||||
|
||||
free_cmdline_buf();
|
||||
|
||||
/* Clear registers. */
|
||||
clear_registers();
|
||||
ResetRedobuff();
|
||||
ResetRedobuff();
|
||||
|
||||
|
||||
/* highlight info */
|
||||
free_highlight();
|
||||
|
||||
reset_last_sourcing();
|
||||
|
||||
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;
|
||||
|
||||
eval_clear();
|
||||
|
||||
free_termoptions();
|
||||
|
||||
/* screenlines (can't display anything now!) */
|
||||
free_screenlines();
|
||||
|
||||
clear_hl_tables();
|
||||
|
||||
free(NameBuff);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user