aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/eval
diff options
context:
space:
mode:
authorJakob Schnitzer <mail@jakobschnitzer.de>2017-04-24 11:35:10 +0200
committerJakob Schnitzer <mail@jakobschnitzer.de>2017-04-24 11:35:10 +0200
commitff8b2eb435c518f0eafd0e509afe1f5ee4a81fd1 (patch)
tree526b1df09b06121bdbc6ef5254ef53821958a6cb /src/nvim/eval
parent4049492b6d7b8805686b14dbacb3b729abd03308 (diff)
parent7f6d3d305269fd1139bc2aec9a91bf98ad595199 (diff)
downloadrneovim-ff8b2eb435c518f0eafd0e509afe1f5ee4a81fd1.tar.gz
rneovim-ff8b2eb435c518f0eafd0e509afe1f5ee4a81fd1.tar.bz2
rneovim-ff8b2eb435c518f0eafd0e509afe1f5ee4a81fd1.zip
Merge branch 'master' into option-fixes
Diffstat (limited to 'src/nvim/eval')
-rw-r--r--src/nvim/eval/decode.c35
-rw-r--r--src/nvim/eval/encode.c71
-rw-r--r--src/nvim/eval/executor.c3
-rw-r--r--src/nvim/eval/gc.c3
-rw-r--r--src/nvim/eval/typval.c49
-rw-r--r--src/nvim/eval/typval.h18
-rw-r--r--src/nvim/eval/typval_encode.c.h6
7 files changed, 97 insertions, 88 deletions
diff --git a/src/nvim/eval/decode.c b/src/nvim/eval/decode.c
index 3cb68e093b..8905317f15 100644
--- a/src/nvim/eval/decode.c
+++ b/src/nvim/eval/decode.c
@@ -1,3 +1,6 @@
+// This is an open source non-commercial project. Dear PVS-Studio, please check
+// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+
#include <stddef.h>
#include <msgpack.h>
@@ -222,8 +225,6 @@ static inline int json_decoder_pop(ValuesStackItem obj,
/// Parse JSON double-quoted string
///
-/// @param[in] conv Defines conversion necessary to convert UTF-8 string to
-/// &encoding.
/// @param[in] buf Buffer being converted.
/// @param[in] buf_len Length of the buffer.
/// @param[in,out] pp Pointer to the start of the string. Must point to '"'.
@@ -240,8 +241,7 @@ static inline int json_decoder_pop(ValuesStackItem obj,
/// value when decoder is restarted, otherwise unused.
///
/// @return OK in case of success, FAIL in case of error.
-static inline int parse_json_string(vimconv_T *const conv,
- const char *const buf, const size_t buf_len,
+static inline int parse_json_string(const char *const buf, const size_t buf_len,
const char **const pp,
ValuesStack *const stack,
ContainerStack *const container_stack,
@@ -416,20 +416,6 @@ static inline int parse_json_string(vimconv_T *const conv,
}
PUT_FST_IN_PAIR(fst_in_pair, str_end);
#undef PUT_FST_IN_PAIR
- if (conv->vc_type != CONV_NONE) {
- size_t str_len = (size_t) (str_end - str);
- char *const new_str = (char *) string_convert(conv, (char_u *) str,
- &str_len);
- if (new_str == NULL) {
- emsgf(_("E474: Failed to convert string \"%.*s\" from UTF-8"),
- (int) str_len, str);
- xfree(str);
- goto parse_json_string_fail;
- }
- xfree(str);
- str = new_str;
- str_end = new_str + str_len;
- }
if (hasnul) {
typval_T obj;
list_T *const list = tv_list_alloc();
@@ -626,9 +612,6 @@ int json_decode_string(const char *const buf, const size_t buf_len,
EMSG(_("E474: Attempt to decode a blank string"));
return FAIL;
}
- vimconv_T conv = { .vc_type = CONV_NONE };
- convert_setup(&conv, (char_u *) "utf-8", p_enc);
- conv.vc_fail = true;
int ret = OK;
ValuesStack stack = KV_INITIAL_VALUE;
ContainerStack container_stack = KV_INITIAL_VALUE;
@@ -774,7 +757,7 @@ json_decode_string_cycle_start:
break;
}
case '"': {
- if (parse_json_string(&conv, buf, buf_len, &p, &stack, &container_stack,
+ if (parse_json_string(buf, buf_len, &p, &stack, &container_stack,
&next_map_special, &didcomma, &didcolon)
== FAIL) {
// Error message was already given
@@ -973,7 +956,13 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
}
break;
}
- case MSGPACK_OBJECT_FLOAT: {
+#ifdef NVIM_MSGPACK_HAS_FLOAT32
+ case MSGPACK_OBJECT_FLOAT32:
+ case MSGPACK_OBJECT_FLOAT64:
+#else
+ case MSGPACK_OBJECT_FLOAT:
+#endif
+ {
*rettv = (typval_T) {
.v_type = VAR_FLOAT,
.v_lock = VAR_UNLOCKED,
diff --git a/src/nvim/eval/encode.c b/src/nvim/eval/encode.c
index 26f9aaa27d..742497c1ca 100644
--- a/src/nvim/eval/encode.c
+++ b/src/nvim/eval/encode.c
@@ -1,3 +1,6 @@
+// This is an open source non-commercial project. Dear PVS-Studio, please check
+// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+
/// @file encode.c
///
/// File containing functions for encoding and decoding VimL values.
@@ -11,7 +14,7 @@
#include <math.h>
#include "nvim/eval/encode.h"
-#include "nvim/buffer_defs.h" // vimconv_T
+#include "nvim/buffer_defs.h"
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
#include "nvim/garray.h"
@@ -29,10 +32,6 @@
#define utf_ptr2char(b) utf_ptr2char((char_u *)b)
#define utf_ptr2len(b) ((size_t)utf_ptr2len((char_u *)b))
#define utf_char2len(b) ((size_t)utf_char2len(b))
-#define string_convert(a, b, c) \
- ((char *)string_convert((vimconv_T *)a, (char_u *)b, c))
-#define convert_setup(vcp, from, to) \
- (convert_setup(vcp, (char_u *)from, (char_u *)to))
const char *const encode_special_var_names[] = {
[kSpecialVarNull] = "null",
@@ -183,9 +182,9 @@ static int conv_error(const char *const msg, const MPConvStack *const mpstack,
}
}
}
- EMSG3(msg, objname, (kv_size(*mpstack) == 0
- ? _("itself")
- : (char *) msg_ga.ga_data));
+ emsgf(msg, _(objname), (kv_size(*mpstack) == 0
+ ? _("itself")
+ : (char *)msg_ga.ga_data));
ga_clear(&msg_ga);
return FAIL;
}
@@ -537,17 +536,6 @@ int encode_read_from_list(ListReaderState *const state, char *const buf,
} \
} while (0)
-/// Last used p_enc value
-///
-/// Generic pointer: it is not used as a string, only pointer comparisons are
-/// performed. Must not be freed.
-static const void *last_p_enc = NULL;
-
-/// Conversion setup for converting from last_p_enc to UTF-8
-static vimconv_T p_enc_conv = {
- .vc_type = CONV_NONE,
-};
-
/// Escape sequences used in JSON
static const char escapes[][3] = {
[BS] = "\\b",
@@ -579,33 +567,15 @@ static inline int convert_to_json_string(garray_T *const gap,
} else {
size_t utf_len = len;
char *tofree = NULL;
- if (last_p_enc != (const void *) p_enc) {
- p_enc_conv.vc_type = CONV_NONE;
- convert_setup(&p_enc_conv, p_enc, "utf-8");
- p_enc_conv.vc_fail = true;
- last_p_enc = p_enc;
- }
- if (p_enc_conv.vc_type != CONV_NONE) {
- tofree = string_convert(&p_enc_conv, buf, &utf_len);
- if (tofree == NULL) {
- emsgf(_("E474: Failed to convert string \"%.*s\" to UTF-8"),
- utf_len, utf_buf);
- return FAIL;
- }
- utf_buf = tofree;
- }
size_t str_len = 0;
- // Encode character as \u0000 if
- // 1. It is an ASCII control character (0x0 .. 0x1F, 0x7F).
- // 2. &encoding is not UTF-8 and code point is above 0x7F.
- // 3. &encoding is UTF-8 and code point is not printable according to
- // utf_printable().
- // This is done to make it possible to :echo values when &encoding is not
- // UTF-8.
-#define ENCODE_RAW(p_enc_conv, ch) \
- (ch >= 0x20 && (p_enc_conv.vc_type == CONV_NONE \
- ? utf_printable(ch) \
- : ch < 0x7F))
+ // Encode character as \uNNNN if
+ // 1. It is an ASCII control character (0x0 .. 0x1F; 0x7F not
+ // utf_printable and thus not checked specially).
+ // 2. Code point is not printable according to utf_printable().
+ // This is done to make resulting values displayable on screen also not from
+ // Neovim.
+#define ENCODE_RAW(ch) \
+ (ch >= 0x20 && utf_printable(ch))
for (size_t i = 0; i < utf_len;) {
const int ch = utf_ptr2char(utf_buf + i);
const size_t shift = (ch == 0? 1: utf_ptr2len(utf_buf + i));
@@ -636,7 +606,7 @@ static inline int convert_to_json_string(garray_T *const gap,
utf_len - (i - shift), utf_buf + i - shift);
xfree(tofree);
return FAIL;
- } else if (ENCODE_RAW(p_enc_conv, ch)) {
+ } else if (ENCODE_RAW(ch)) {
str_len += shift;
} else {
str_len += ((sizeof("\\u1234") - 1)
@@ -666,7 +636,7 @@ static inline int convert_to_json_string(garray_T *const gap,
break;
}
default: {
- if (ENCODE_RAW(p_enc_conv, ch)) {
+ if (ENCODE_RAW(ch)) {
ga_concat_len(gap, utf_buf + i, shift);
} else if (ch < SURROGATE_FIRST_CHAR) {
ga_concat_len(gap, ((const char[]) {
@@ -823,7 +793,7 @@ char *encode_tv2string(typval_T *tv, size_t *len)
garray_T ga;
ga_init(&ga, (int)sizeof(char), 80);
const int evs_ret = encode_vim_to_string(&ga, tv,
- "encode_tv2string() argument");
+ N_("encode_tv2string() argument"));
(void)evs_ret;
assert(evs_ret == OK);
did_echo_string_emsg = false;
@@ -851,7 +821,7 @@ char *encode_tv2echo(typval_T *tv, size_t *len)
ga_concat(&ga, tv->vval.v_string);
}
} else {
- const int eve_ret = encode_vim_to_echo(&ga, tv, ":echo argument");
+ const int eve_ret = encode_vim_to_echo(&ga, tv, N_(":echo argument"));
(void)eve_ret;
assert(eve_ret == OK);
}
@@ -874,7 +844,8 @@ char *encode_tv2json(typval_T *tv, size_t *len)
{
garray_T ga;
ga_init(&ga, (int)sizeof(char), 80);
- const int evj_ret = encode_vim_to_json(&ga, tv, "encode_tv2json() argument");
+ const int evj_ret = encode_vim_to_json(&ga, tv,
+ N_("encode_tv2json() argument"));
if (!evj_ret) {
ga_clear(&ga);
}
diff --git a/src/nvim/eval/executor.c b/src/nvim/eval/executor.c
index ec6c86ac64..91bb61323f 100644
--- a/src/nvim/eval/executor.c
+++ b/src/nvim/eval/executor.c
@@ -1,3 +1,6 @@
+// This is an open source non-commercial project. Dear PVS-Studio, please check
+// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+
#include "nvim/eval/typval.h"
#include "nvim/eval/executor.h"
#include "nvim/eval.h"
diff --git a/src/nvim/eval/gc.c b/src/nvim/eval/gc.c
index 5ce52ddd70..2bbf78d827 100644
--- a/src/nvim/eval/gc.c
+++ b/src/nvim/eval/gc.c
@@ -1,3 +1,6 @@
+// This is an open source non-commercial project. Dear PVS-Studio, please check
+// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+
#include "nvim/eval/typval.h"
#include "nvim/eval/gc.h"
diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c
index 779bb18175..786b766689 100644
--- a/src/nvim/eval/typval.c
+++ b/src/nvim/eval/typval.c
@@ -1,3 +1,6 @@
+// This is an open source non-commercial project. Dear PVS-Studio, please check
+// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+
#include <stdio.h>
#include <stddef.h>
#include <string.h>
@@ -136,7 +139,7 @@ void tv_list_watch_fix(list_T *const l, const listitem_T *const item)
///
/// @return [allocated] new list.
list_T *tv_list_alloc(void)
- FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC
+ FUNC_ATTR_NONNULL_RET
{
list_T *const list = xcalloc(1, sizeof(list_T));
@@ -1011,7 +1014,6 @@ void tv_dict_item_free(dictitem_T *const item)
/// @return [allocated] new dictionary item.
static dictitem_T *tv_dict_item_copy(dictitem_T *const di)
FUNC_ATTR_NONNULL_RET FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
- FUNC_ATTR_MALLOC
{
dictitem_T *const new_di = tv_dict_item_alloc((const char *)di->di_key);
tv_copy(&di->di_tv, &new_di->di_tv);
@@ -1040,7 +1042,7 @@ void tv_dict_item_remove(dict_T *const dict, dictitem_T *const item)
///
/// @return [allocated] new dictionary.
dict_T *tv_dict_alloc(void)
- FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT
+ FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT
{
dict_T *const d = xmalloc(sizeof(dict_T));
@@ -1577,7 +1579,7 @@ void tv_dict_set_keys_readonly(dict_T *const dict)
///
/// @return [allocated] pointer to the created list.
list_T *tv_list_alloc_ret(typval_T *const ret_tv)
- FUNC_ATTR_NONNULL_ALL FUNC_ATTR_MALLOC
+ FUNC_ATTR_NONNULL_ALL
{
list_T *const l = tv_list_alloc();
ret_tv->vval.v_list = l;
@@ -1799,11 +1801,13 @@ static inline void _nothing_conv_dict_end(typval_T *const tv,
#define TYPVAL_ENCODE_NAME nothing
#define TYPVAL_ENCODE_FIRST_ARG_TYPE const void *const
#define TYPVAL_ENCODE_FIRST_ARG_NAME ignored
+#define TYPVAL_ENCODE_TRANSLATE_OBJECT_NAME
#include "nvim/eval/typval_encode.c.h"
#undef TYPVAL_ENCODE_SCOPE
#undef TYPVAL_ENCODE_NAME
#undef TYPVAL_ENCODE_FIRST_ARG_TYPE
#undef TYPVAL_ENCODE_FIRST_ARG_NAME
+#undef TYPVAL_ENCODE_TRANSLATE_OBJECT_NAME
#undef TYPVAL_ENCODE_ALLOW_SPECIALS
#undef TYPVAL_ENCODE_CONV_NIL
@@ -1838,8 +1842,13 @@ static inline void _nothing_conv_dict_end(typval_T *const tv,
void tv_clear(typval_T *const tv)
{
if (tv != NULL && tv->v_type != VAR_UNKNOWN) {
- const int evn_ret = encode_vim_to_nothing(NULL, tv,
- _("tv_clear() argument"));
+ // WARNING: do not translate the string here, gettext is slow and function
+ // is used *very* often. At the current state encode_vim_to_nothing() does
+ // not error out and does not use the argument anywhere.
+ //
+ // If situation changes and this argument will be used, translate it in the
+ // place where it is used.
+ const int evn_ret = encode_vim_to_nothing(NULL, tv, "tv_clear() argument");
(void)evn_ret;
assert(evn_ret == OK);
}
@@ -2042,11 +2051,20 @@ bool tv_islocked(const typval_T *const tv)
///
/// @param[in] lock Lock status.
/// @param[in] name Variable name, used in the error message.
-/// @param[in] name_len Variable name length.
+/// @param[in] name_len Variable name length. Use #TV_TRANSLATE to translate
+/// variable name and compute the length. Use #TV_CSTRING
+/// to compute the length with strlen() without
+/// translating.
+///
+/// Both #TV_… values are used for optimization purposes:
+/// variable name with its length is needed only in case
+/// of error, when no error occurs computing them is
+/// a waste of CPU resources. This especially applies to
+/// gettext.
///
/// @return true if variable is locked, false otherwise.
-bool tv_check_lock(const VarLockStatus lock, const char *const name,
- const size_t name_len)
+bool tv_check_lock(const VarLockStatus lock, const char *name,
+ size_t name_len)
FUNC_ATTR_WARN_UNUSED_RESULT
{
const char *error_message = NULL;
@@ -2065,10 +2083,17 @@ bool tv_check_lock(const VarLockStatus lock, const char *const name,
}
assert(error_message != NULL);
- const char *const unknown_name = _("Unknown");
+ if (name == NULL) {
+ name = _("Unknown");
+ name_len = strlen(name);
+ } else if (name_len == TV_TRANSLATE) {
+ name = _(name);
+ name_len = strlen(name);
+ } else if (name_len == TV_CSTRING) {
+ name_len = strlen(name);
+ }
- emsgf(_(error_message), (name != NULL ? name_len : strlen(unknown_name)),
- (name != NULL ? name : unknown_name));
+ emsgf(_(error_message), (int)name_len, name);
return true;
}
diff --git a/src/nvim/eval/typval.h b/src/nvim/eval/typval.h
index 7eab22bc12..0f659727ee 100644
--- a/src/nvim/eval/typval.h
+++ b/src/nvim/eval/typval.h
@@ -17,6 +17,7 @@
#include "nvim/pos.h" // for linenr_T
#include "nvim/gettext.h"
#include "nvim/message.h"
+#include "nvim/macros.h"
/// Type used for VimL VAR_NUMBER values
typedef int varnumber_T;
@@ -423,6 +424,23 @@ static inline bool tv_is_func(const typval_T tv)
return tv.v_type == VAR_FUNC || tv.v_type == VAR_PARTIAL;
}
+/// Specify that argument needs to be translated
+///
+/// Used for size_t length arguments to avoid calling gettext() and strlen()
+/// unless needed.
+#define TV_TRANSLATE (SIZE_MAX)
+
+/// Specify that argument is a NUL-terminated C string
+///
+/// Used for size_t length arguments to avoid calling strlen() unless needed.
+#define TV_CSTRING (SIZE_MAX - 1)
+
+#ifdef UNIT_TESTING
+// Do not use enum constants, see commit message.
+EXTERN const size_t kTVCstring INIT(= TV_CSTRING);
+EXTERN const size_t kTVTranslate INIT(= TV_TRANSLATE);
+#endif
+
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "eval/typval.h.generated.h"
#endif
diff --git a/src/nvim/eval/typval_encode.c.h b/src/nvim/eval/typval_encode.c.h
index ad54eef4a0..b4a70fb188 100644
--- a/src/nvim/eval/typval_encode.c.h
+++ b/src/nvim/eval/typval_encode.c.h
@@ -489,7 +489,7 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE(
}
if (is_string) {
TYPVAL_ENCODE_CONV_STR_STRING(tv, buf, len);
- } else {
+ } else { // -V523
TYPVAL_ENCODE_CONV_STRING(tv, buf, len);
}
xfree(buf);
@@ -611,7 +611,7 @@ _convert_one_value_regular_dict: {}
typval_encode_stop_converting_one_item:
return OK;
// Prevent “unused label” warnings.
- goto typval_encode_stop_converting_one_item;
+ goto typval_encode_stop_converting_one_item; // -V779
}
TYPVAL_ENCODE_SCOPE int _TYPVAL_ENCODE_ENCODE(
@@ -814,6 +814,6 @@ encode_vim_to__error_ret:
_mp_destroy(mpstack);
return FAIL;
// Prevent “unused label” warnings.
- goto typval_encode_stop_converting_one_item;
+ goto typval_encode_stop_converting_one_item; // -V779
}
#endif // NVIM_EVAL_TYPVAL_ENCODE_C_H