aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJustin M. Keyes <justinkz@gmail.com>2017-01-07 23:13:57 +0100
committerGitHub <noreply@github.com>2017-01-07 23:13:57 +0100
commit50af8e0255c0271ff411a6af54b664d69be227e5 (patch)
tree50260092952a0d236a25d70a4aed16fa6363c6e2 /src
parent40c76741c187f5bf35101e65252226030d5b72e5 (diff)
parent3967618fa524b3840649887661584de27f7daa87 (diff)
downloadrneovim-50af8e0255c0271ff411a6af54b664d69be227e5.tar.gz
rneovim-50af8e0255c0271ff411a6af54b664d69be227e5.tar.bz2
rneovim-50af8e0255c0271ff411a6af54b664d69be227e5.zip
Merge #5903 from ZyX-I/fix-5901
Reset copyID also when dictionary is referenced
Diffstat (limited to 'src')
-rw-r--r--src/nvim/api/private/helpers.c6
-rw-r--r--src/nvim/eval.c42
-rw-r--r--src/nvim/eval/encode.c12
-rw-r--r--src/nvim/eval/typval_encode.c.h26
-rw-r--r--src/nvim/eval/typval_encode.h43
-rw-r--r--src/nvim/globals.h8
-rw-r--r--src/nvim/hashtab.c12
-rw-r--r--src/nvim/hashtab.h9
-rw-r--r--src/nvim/memory.c49
-rw-r--r--src/nvim/memory.h34
10 files changed, 182 insertions, 59 deletions
diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c
index 701a1cbf2b..7daa4d7207 100644
--- a/src/nvim/api/private/helpers.c
+++ b/src/nvim/api/private/helpers.c
@@ -387,6 +387,8 @@ static inline void typval_encode_list_start(EncodedData *const edata,
#define TYPVAL_ENCODE_CONV_LIST_START(tv, len) \
typval_encode_list_start(edata, (size_t)(len))
+#define TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START(tv, mpsv)
+
static inline void typval_encode_between_list_items(EncodedData *const edata)
FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL
{
@@ -427,6 +429,8 @@ static inline void typval_encode_dict_start(EncodedData *const edata,
#define TYPVAL_ENCODE_CONV_DICT_START(tv, dict, len) \
typval_encode_dict_start(edata, (size_t)(len))
+#define TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START(tv, dict, mpsv)
+
#define TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK(label, kv_pair)
static inline void typval_encode_after_key(EncodedData *const edata)
@@ -499,11 +503,13 @@ static inline void typval_encode_dict_end(EncodedData *const edata)
#undef TYPVAL_ENCODE_CONV_FUNC_END
#undef TYPVAL_ENCODE_CONV_EMPTY_LIST
#undef TYPVAL_ENCODE_CONV_LIST_START
+#undef TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START
#undef TYPVAL_ENCODE_CONV_EMPTY_DICT
#undef TYPVAL_ENCODE_CONV_NIL
#undef TYPVAL_ENCODE_CONV_BOOL
#undef TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER
#undef TYPVAL_ENCODE_CONV_DICT_START
+#undef TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START
#undef TYPVAL_ENCODE_CONV_DICT_END
#undef TYPVAL_ENCODE_CONV_DICT_AFTER_KEY
#undef TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 4501c2e0a6..a046b2a288 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -6445,7 +6445,7 @@ void dict_free(dict_T *d) {
*/
dictitem_T *dictitem_alloc(char_u *key) FUNC_ATTR_NONNULL_RET
{
- dictitem_T *di = xmalloc(sizeof(dictitem_T) + STRLEN(key));
+ dictitem_T *di = xmalloc(offsetof(dictitem_T, di_key) + STRLEN(key) + 1);
#ifndef __clang_analyzer__
STRCPY(di->di_key, key);
#endif
@@ -19147,23 +19147,25 @@ static inline void _nothing_conv_func_end(typval_T *const tv, const int copyID)
} \
} while (0)
-static inline int _nothing_conv_list_start(typval_T *const tv)
+static inline int _nothing_conv_real_list_after_start(
+ typval_T *const tv, MPConvStackVal *const mpsv)
FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_WARN_UNUSED_RESULT
{
- if (tv == NULL) {
- return NOTDONE;
- }
+ assert(tv != NULL);
tv->v_lock = VAR_UNLOCKED;
if (tv->vval.v_list->lv_refcount > 1) {
tv->vval.v_list->lv_refcount--;
tv->vval.v_list = NULL;
+ mpsv->data.l.li = NULL;
return OK;
}
return NOTDONE;
}
-#define TYPVAL_ENCODE_CONV_LIST_START(tv, len) \
+#define TYPVAL_ENCODE_CONV_LIST_START(tv, len)
+
+#define TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START(tv, mpsv) \
do { \
- if (_nothing_conv_list_start(tv) != NOTDONE) { \
+ if (_nothing_conv_real_list_after_start(tv, &mpsv) != NOTDONE) { \
goto typval_encode_stop_converting_one_item; \
} \
} while (0)
@@ -19183,9 +19185,9 @@ static inline void _nothing_conv_list_end(typval_T *const tv)
}
#define TYPVAL_ENCODE_CONV_LIST_END(tv) _nothing_conv_list_end(tv)
-static inline int _nothing_conv_dict_start(typval_T *const tv,
- dict_T **const dictp,
- const void *const nodictvar)
+static inline int _nothing_conv_real_dict_after_start(
+ typval_T *const tv, dict_T **const dictp, const void *const nodictvar,
+ MPConvStackVal *const mpsv)
FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_WARN_UNUSED_RESULT
{
if (tv != NULL) {
@@ -19194,15 +19196,18 @@ static inline int _nothing_conv_dict_start(typval_T *const tv,
if ((const void *)dictp != nodictvar && (*dictp)->dv_refcount > 1) {
(*dictp)->dv_refcount--;
*dictp = NULL;
+ mpsv->data.d.todo = 0;
return OK;
}
return NOTDONE;
}
-#define TYPVAL_ENCODE_CONV_DICT_START(tv, dict, len) \
+#define TYPVAL_ENCODE_CONV_DICT_START(tv, dict, len)
+
+#define TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START(tv, dict, mpsv) \
do { \
- if (_nothing_conv_dict_start(tv, (dict_T **)&dict, \
- (void *)&TYPVAL_ENCODE_NODICT_VAR) \
- != NOTDONE) { \
+ if (_nothing_conv_real_dict_after_start( \
+ tv, (dict_T **)&dict, (void *)&TYPVAL_ENCODE_NODICT_VAR, \
+ &mpsv) != NOTDONE) { \
goto typval_encode_stop_converting_one_item; \
} \
} while (0)
@@ -19253,9 +19258,11 @@ static inline void _nothing_conv_dict_end(typval_T *const tv,
#undef TYPVAL_ENCODE_CONV_EMPTY_LIST
#undef TYPVAL_ENCODE_CONV_EMPTY_DICT
#undef TYPVAL_ENCODE_CONV_LIST_START
+#undef TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START
#undef TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS
#undef TYPVAL_ENCODE_CONV_LIST_END
#undef TYPVAL_ENCODE_CONV_DICT_START
+#undef TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START
#undef TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK
#undef TYPVAL_ENCODE_CONV_DICT_AFTER_KEY
#undef TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS
@@ -21658,9 +21665,12 @@ void func_unref(char_u *name)
fp = find_func(name);
if (fp == NULL) {
#ifdef EXITFREE
- if (!entered_free_all_mem) // NOLINT(readability/braces)
-#endif
+ if (!entered_free_all_mem) {
EMSG2(_(e_intern2), "func_unref()");
+ }
+#else
+ EMSG2(_(e_intern2), "func_unref()");
+#endif
} else {
user_func_unref(fp);
}
diff --git a/src/nvim/eval/encode.c b/src/nvim/eval/encode.c
index 071fbc3923..ee66b7cf09 100644
--- a/src/nvim/eval/encode.c
+++ b/src/nvim/eval/encode.c
@@ -369,6 +369,8 @@ int encode_read_from_list(ListReaderState *const state, char *const buf,
#define TYPVAL_ENCODE_CONV_LIST_START(tv, len) \
ga_append(gap, '[')
+#define TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START(tv, mpsv)
+
#define TYPVAL_ENCODE_CONV_EMPTY_DICT(tv, dict) \
ga_concat(gap, "{}")
@@ -383,6 +385,8 @@ int encode_read_from_list(ListReaderState *const state, char *const buf,
#define TYPVAL_ENCODE_CONV_DICT_START(tv, dict, len) \
ga_append(gap, '{')
+#define TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START(tv, dict, mpsv)
+
#define TYPVAL_ENCODE_CONV_DICT_END(tv, dict) \
ga_append(gap, '}')
@@ -789,11 +793,13 @@ bool encode_check_json_key(const typval_T *const tv)
#undef TYPVAL_ENCODE_CONV_FUNC_END
#undef TYPVAL_ENCODE_CONV_EMPTY_LIST
#undef TYPVAL_ENCODE_CONV_LIST_START
+#undef TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START
#undef TYPVAL_ENCODE_CONV_EMPTY_DICT
#undef TYPVAL_ENCODE_CONV_NIL
#undef TYPVAL_ENCODE_CONV_BOOL
#undef TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER
#undef TYPVAL_ENCODE_CONV_DICT_START
+#undef TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START
#undef TYPVAL_ENCODE_CONV_DICT_END
#undef TYPVAL_ENCODE_CONV_DICT_AFTER_KEY
#undef TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS
@@ -933,6 +939,8 @@ char *encode_tv2json(typval_T *tv, size_t *len)
#define TYPVAL_ENCODE_CONV_LIST_START(tv, len) \
msgpack_pack_array(packer, (size_t)(len))
+#define TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START(tv, mpsv)
+
#define TYPVAL_ENCODE_CONV_EMPTY_DICT(tv, dict) \
msgpack_pack_map(packer, 0)
@@ -954,6 +962,8 @@ char *encode_tv2json(typval_T *tv, size_t *len)
#define TYPVAL_ENCODE_CONV_DICT_START(tv, dict, len) \
msgpack_pack_map(packer, (size_t)(len))
+#define TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START(tv, dict, mpsv)
+
#define TYPVAL_ENCODE_CONV_DICT_END(tv, dict)
#define TYPVAL_ENCODE_CONV_DICT_AFTER_KEY(tv, dict)
@@ -994,11 +1004,13 @@ char *encode_tv2json(typval_T *tv, size_t *len)
#undef TYPVAL_ENCODE_CONV_FUNC_END
#undef TYPVAL_ENCODE_CONV_EMPTY_LIST
#undef TYPVAL_ENCODE_CONV_LIST_START
+#undef TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START
#undef TYPVAL_ENCODE_CONV_EMPTY_DICT
#undef TYPVAL_ENCODE_CONV_NIL
#undef TYPVAL_ENCODE_CONV_BOOL
#undef TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER
#undef TYPVAL_ENCODE_CONV_DICT_START
+#undef TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START
#undef TYPVAL_ENCODE_CONV_DICT_END
#undef TYPVAL_ENCODE_CONV_DICT_AFTER_KEY
#undef TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS
diff --git a/src/nvim/eval/typval_encode.c.h b/src/nvim/eval/typval_encode.c.h
index 3e1170b8fa..365eb2dd77 100644
--- a/src/nvim/eval/typval_encode.c.h
+++ b/src/nvim/eval/typval_encode.c.h
@@ -129,6 +129,16 @@
/// point to a special dictionary.
/// @param len List length. Is an expression which evaluates to an integer.
+/// @def TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START
+/// @brief Macros used after pushing list onto the stack
+///
+/// Only used for real list_T* lists, not for special dictionaries or partial
+/// arguments.
+///
+/// @param tv Pointer to typval where value is stored. May be NULL. May
+/// point to a special dictionary.
+/// @param mpsv Pushed MPConvStackVal value.
+
/// @def TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS
/// @brief Macros used after finishing converting non-last list item
///
@@ -142,6 +152,9 @@
/// @def TYPVAL_ENCODE_CONV_DICT_START
/// @brief Macros used before starting to convert non-empty dictionary
///
+/// Only used for real dict_T* dictionaries, not for special dictionaries. Also
+/// used for partial self dictionary.
+///
/// @param tv Pointer to typval where dictionary is stored. May be NULL. May
/// point to a special dictionary.
/// @param dict Converted dictionary, lvalue or #TYPVAL_ENCODE_NODICT_VAR
@@ -149,6 +162,14 @@
/// @param len Dictionary length. Is an expression which evaluates to an
/// integer.
+/// @def TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START
+/// @brief Macros used after pushing dictionary onto the stack
+///
+/// @param tv Pointer to typval where dictionary is stored. May be NULL.
+/// May not point to a special dictionary.
+/// @param dict Converted dictionary, lvalue.
+/// @param mpsv Pushed MPConvStackVal value.
+
/// @def TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK
/// @brief Macros used to check special dictionary key
///
@@ -354,6 +375,7 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE(
},
},
}));
+ TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START(tv, _mp_last(*mpstack));
break;
}
case VAR_SPECIAL: {
@@ -564,6 +586,8 @@ _convert_one_value_regular_dict:
},
},
}));
+ TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START(tv, tv->vval.v_dict,
+ _mp_last(*mpstack));
break;
}
case VAR_UNKNOWN: {
@@ -732,6 +756,8 @@ typval_encode_stop_converting_one_item:
},
},
}));
+ TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START(NULL, pt->pt_dict,
+ _mp_last(mpstack));
} else {
TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF(tv, -1);
}
diff --git a/src/nvim/eval/typval_encode.h b/src/nvim/eval/typval_encode.h
index 6517efa961..ba325b8f55 100644
--- a/src/nvim/eval/typval_encode.h
+++ b/src/nvim/eval/typval_encode.h
@@ -108,37 +108,38 @@ static inline size_t tv_strlen(const typval_T *const tv)
} \
} while (0)
-#define _TYPVAL_ENCODE_CHECK_SELF_REFERENCE_INNER_2(name) \
- _typval_encode_##name##_check_self_reference
-#define _TYPVAL_ENCODE_CHECK_SELF_REFERENCE_INNER(name) \
- _TYPVAL_ENCODE_CHECK_SELF_REFERENCE_INNER_2(name)
+#define _TYPVAL_ENCODE_FUNC_NAME_INNER_2(pref, name, suf) \
+ pref##name##suf
+#define _TYPVAL_ENCODE_FUNC_NAME_INNER(pref, name, suf) \
+ _TYPVAL_ENCODE_FUNC_NAME_INNER_2(pref, name, suf)
+
+/// Construct function name, possibly using macros
+///
+/// Is used to expand macros that may appear in arguments.
+///
+/// @note Expands all arguments, even if only one is needed.
+///
+/// @param[in] pref Prefix.
+/// @param[in] suf Suffix.
+///
+/// @return Concat: pref + #TYPVAL_ENCODE_NAME + suf.
+#define _TYPVAL_ENCODE_FUNC_NAME(pref, suf) \
+ _TYPVAL_ENCODE_FUNC_NAME_INNER(pref, TYPVAL_ENCODE_NAME, suf)
/// Self reference checker function name
#define _TYPVAL_ENCODE_CHECK_SELF_REFERENCE \
- _TYPVAL_ENCODE_CHECK_SELF_REFERENCE_INNER(TYPVAL_ENCODE_NAME)
-
-#define _TYPVAL_ENCODE_ENCODE_INNER_2(name) encode_vim_to_##name
-#define _TYPVAL_ENCODE_ENCODE_INNER(name) _TYPVAL_ENCODE_ENCODE_INNER_2(name)
+ _TYPVAL_ENCODE_FUNC_NAME(_typval_encode_, _check_self_reference)
/// Entry point function name
-#define _TYPVAL_ENCODE_ENCODE _TYPVAL_ENCODE_ENCODE_INNER(TYPVAL_ENCODE_NAME)
-
-#define _TYPVAL_ENCODE_CONVERT_ONE_VALUE_INNER_2(name) \
- _typval_encode_##name##_convert_one_value
-#define _TYPVAL_ENCODE_CONVERT_ONE_VALUE_INNER(name) \
- _TYPVAL_ENCODE_CONVERT_ONE_VALUE_INNER_2(name)
+#define _TYPVAL_ENCODE_ENCODE \
+ _TYPVAL_ENCODE_FUNC_NAME(encode_vim_to_, )
/// Name of the …convert_one_value function
#define _TYPVAL_ENCODE_CONVERT_ONE_VALUE \
- _TYPVAL_ENCODE_CONVERT_ONE_VALUE_INNER(TYPVAL_ENCODE_NAME)
-
-#define _TYPVAL_ENCODE_NODICT_VAR_INNER_2(name) \
- _typval_encode_##name##_nodict_var
-#define _TYPVAL_ENCODE_NODICT_VAR_INNER(name) \
- _TYPVAL_ENCODE_NODICT_VAR_INNER_2(name)
+ _TYPVAL_ENCODE_FUNC_NAME(_typval_encode_, _convert_one_value)
/// Name of the dummy const dict_T *const variable
#define TYPVAL_ENCODE_NODICT_VAR \
- _TYPVAL_ENCODE_NODICT_VAR_INNER(TYPVAL_ENCODE_NAME)
+ _TYPVAL_ENCODE_FUNC_NAME(_typval_encode_, _nodict_var)
#endif // NVIM_EVAL_TYPVAL_ENCODE_H
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index 872ff8d5b8..5ee04ad982 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -409,10 +409,6 @@ EXTERN struct caller_scope {
} provider_caller_scope;
EXTERN int provider_call_nesting INIT(= 0);
-/* Magic number used for hashitem "hi_key" value indicating a deleted item.
- * Only the address is used. */
-EXTERN char_u hash_removed;
-
EXTERN int t_colors INIT(= 256); // int value of T_CCO
@@ -636,10 +632,6 @@ EXTERN int exiting INIT(= FALSE);
/* TRUE when planning to exit Vim. Might
* still keep on running if there is a changed
* buffer. */
-#if defined(EXITFREE)
-// true when in or after free_all_mem()
-EXTERN bool entered_free_all_mem INIT(= false);
-#endif
// volatile because it is used in signal handler deathtrap().
EXTERN volatile int full_screen INIT(= false);
// TRUE when doing full-screen output
diff --git a/src/nvim/hashtab.c b/src/nvim/hashtab.c
index fa4077f22f..376f33e23e 100644
--- a/src/nvim/hashtab.c
+++ b/src/nvim/hashtab.c
@@ -36,6 +36,8 @@
# include "hashtab.c.generated.h"
#endif
+char hash_removed;
+
/// Initialize an empty hash table.
void hash_init(hashtab_T *ht)
{
@@ -380,3 +382,13 @@ hash_T hash_hash(char_u *key)
return hash;
}
+
+/// Function to get HI_KEY_REMOVED value
+///
+/// Used for testing because luajit ffi does not allow getting addresses of
+/// globals.
+const char_u *_hash_key_removed(void)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ return HI_KEY_REMOVED;
+}
diff --git a/src/nvim/hashtab.h b/src/nvim/hashtab.h
index 7233d8c47c..0da2b13f2e 100644
--- a/src/nvim/hashtab.h
+++ b/src/nvim/hashtab.h
@@ -5,14 +5,19 @@
#include "nvim/types.h"
+/// Magic number used for hashitem "hi_key" value indicating a deleted item
+///
+/// Only the address is used.
+extern char hash_removed;
+
/// Type for hash number (hash calculation result).
typedef size_t hash_T;
/// The address of "hash_removed" is used as a magic number
/// for hi_key to indicate a removed item.
-#define HI_KEY_REMOVED &hash_removed
+#define HI_KEY_REMOVED ((char_u *)&hash_removed)
#define HASHITEM_EMPTY(hi) ((hi)->hi_key == NULL \
- || (hi)->hi_key == &hash_removed)
+ || (hi)->hi_key == (char_u *)&hash_removed)
/// A hastable item.
///
diff --git a/src/nvim/memory.c b/src/nvim/memory.c
index 1884d55999..92ead873ae 100644
--- a/src/nvim/memory.c
+++ b/src/nvim/memory.c
@@ -17,16 +17,41 @@
// Force je_ prefix on jemalloc functions.
# define JEMALLOC_NO_DEMANGLE
# include <jemalloc/jemalloc.h>
-# define malloc(size) je_malloc(size)
-# define calloc(count, size) je_calloc(count, size)
-# define realloc(ptr, size) je_realloc(ptr, size)
-# define free(ptr) je_free(ptr)
+#endif
+
+#ifdef UNIT_TESTING
+# define malloc(size) mem_malloc(size)
+# define calloc(count, size) mem_calloc(count, size)
+# define realloc(ptr, size) mem_realloc(ptr, size)
+# define free(ptr) mem_free(ptr)
+# ifdef HAVE_JEMALLOC
+MemMalloc mem_malloc = &je_malloc;
+MemFree mem_free = &je_free;
+MemCalloc mem_calloc = &je_calloc;
+MemRealloc mem_realloc = &je_realloc;
+# else
+MemMalloc mem_malloc = &malloc;
+MemFree mem_free = &free;
+MemCalloc mem_calloc = &calloc;
+MemRealloc mem_realloc = &realloc;
+# endif
+#else
+# ifdef HAVE_JEMALLOC
+# define malloc(size) je_malloc(size)
+# define calloc(count, size) je_calloc(count, size)
+# define realloc(ptr, size) je_realloc(ptr, size)
+# define free(ptr) je_free(ptr)
+# endif
#endif
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "memory.c.generated.h"
#endif
+#ifdef EXITFREE
+bool entered_free_all_mem = false;
+#endif
+
/// Try to free memory. Used when trying to recover from out of memory errors.
/// @see {xmalloc}
void try_to_free_memory(void)
@@ -353,15 +378,15 @@ char *xstpncpy(char *restrict dst, const char *restrict src, size_t maxlen)
size_t xstrlcpy(char *restrict dst, const char *restrict src, size_t size)
FUNC_ATTR_NONNULL_ALL
{
- size_t ret = strlen(src);
+ size_t ret = strlen(src);
- if (size) {
- size_t len = (ret >= size) ? size - 1 : ret;
- memcpy(dst, src, len);
- dst[len] = '\0';
- }
+ if (size) {
+ size_t len = (ret >= size) ? size - 1 : ret;
+ memcpy(dst, src, len);
+ dst[len] = '\0';
+ }
- return ret;
+ return ret;
}
/// strdup() wrapper
@@ -371,6 +396,7 @@ size_t xstrlcpy(char *restrict dst, const char *restrict src, size_t size)
/// @return pointer to a copy of the string
char *xstrdup(const char *str)
FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_RET
+ FUNC_ATTR_NONNULL_ALL
{
return xmemdupz(str, strlen(str));
}
@@ -401,6 +427,7 @@ void *xmemrchr(const void *src, uint8_t c, size_t len)
/// @return pointer to a copy of the string
char *xstrndup(const char *str, size_t len)
FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_RET
+ FUNC_ATTR_NONNULL_ALL
{
char *p = memchr(str, '\0', len);
return xmemdupz(str, p ? (size_t)(p - str) : len);
diff --git a/src/nvim/memory.h b/src/nvim/memory.h
index 62cc78360c..250ac3e08f 100644
--- a/src/nvim/memory.h
+++ b/src/nvim/memory.h
@@ -1,9 +1,41 @@
#ifndef NVIM_MEMORY_H
#define NVIM_MEMORY_H
+#include <stdbool.h> // for bool
#include <stdint.h> // for uint8_t
#include <stddef.h> // for size_t
-#include <time.h> // for time_t
+#include <time.h> // for time_t
+
+/// `malloc()` function signature
+typedef void *(*MemMalloc)(size_t);
+
+/// `free()` function signature
+typedef void (*MemFree)(void *);
+
+/// `calloc()` function signature
+typedef void *(*MemCalloc)(size_t, size_t);
+
+/// `realloc()` function signature
+typedef void *(*MemRealloc)(void *, size_t);
+
+#ifdef UNIT_TESTING
+/// When unit testing: pointer to the `malloc()` function, may be altered
+extern MemMalloc mem_malloc;
+
+/// When unit testing: pointer to the `free()` function, may be altered
+extern MemFree mem_free;
+
+/// When unit testing: pointer to the `calloc()` function, may be altered
+extern MemCalloc mem_calloc;
+
+/// When unit testing: pointer to the `realloc()` function, may be altered
+extern MemRealloc mem_realloc;
+#endif
+
+#ifdef EXITFREE
+/// Indicates that free_all_mem function was or is running
+extern bool entered_free_all_mem;
+#endif
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "memory.h.generated.h"