aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2023-01-19 13:27:36 +0800
committerGitHub <noreply@github.com>2023-01-19 13:27:36 +0800
commit93adf74a03f6fd2d34bdea7cec1c1f120d6643a2 (patch)
tree66756e00d861c6093fc26ccaca5a09f244eae77d
parent42e9a09a44f4203a96aabbbe2382ae9bb46096d4 (diff)
downloadrneovim-93adf74a03f6fd2d34bdea7cec1c1f120d6643a2.tar.gz
rneovim-93adf74a03f6fd2d34bdea7cec1c1f120d6643a2.tar.bz2
rneovim-93adf74a03f6fd2d34bdea7cec1c1f120d6643a2.zip
refactor(eval.c): factor out get_number_tv() (#21893)
It was refactored into a separate function in Vim in patch 8.2.0149.
-rw-r--r--src/nvim/eval.c182
1 files changed, 92 insertions, 90 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 4c880aaf92..a9ea298285 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -2887,12 +2887,7 @@ static int eval6(char **arg, typval_T *rettv, int evaluate, int want_string)
/// @return OK or FAIL.
static int eval7(char **arg, typval_T *rettv, int evaluate, int want_string)
{
- varnumber_T n;
- int len;
- char *s;
- const char *start_leader, *end_leader;
int ret = OK;
- char *alias;
static int recurse = 0;
// Initialise variable so that tv_clear() can't mistake this for a
@@ -2900,11 +2895,11 @@ static int eval7(char **arg, typval_T *rettv, int evaluate, int want_string)
rettv->v_type = VAR_UNKNOWN;
// Skip '!', '-' and '+' characters. They are handled later.
- start_leader = *arg;
+ const char *start_leader = *arg;
while (**arg == '!' || **arg == '-' || **arg == '+') {
*arg = skipwhite(*arg + 1);
}
- end_leader = *arg;
+ const char *end_leader = *arg;
// Limit recursion to 1000 levels. At least at 10000 we run out of stack
// and crash. With MSVC the stack is smaller.
@@ -2931,88 +2926,9 @@ static int eval7(char **arg, typval_T *rettv, int evaluate, int want_string)
case '6':
case '7':
case '8':
- case '9': {
- char *p = skipdigits(*arg + 1);
- int get_float = false;
-
- // We accept a float when the format matches
- // "[0-9]\+\.[0-9]\+\([eE][+-]\?[0-9]\+\)\?". This is very
- // strict to avoid backwards compatibility problems.
- // Don't look for a float after the "." operator, so that
- // ":let vers = 1.2.3" doesn't fail.
- if (!want_string && p[0] == '.' && ascii_isdigit(p[1])) {
- get_float = true;
- p = skipdigits(p + 2);
- if (*p == 'e' || *p == 'E') {
- p++;
- if (*p == '-' || *p == '+') {
- p++;
- }
- if (!ascii_isdigit(*p)) {
- get_float = false;
- } else {
- p = skipdigits(p + 1);
- }
- }
- if (ASCII_ISALPHA(*p) || *p == '.') {
- get_float = false;
- }
- }
- if (get_float) {
- float_T f;
-
- *arg += string2float(*arg, &f);
- if (evaluate) {
- rettv->v_type = VAR_FLOAT;
- rettv->vval.v_float = f;
- }
- } else if (**arg == '0' && ((*arg)[1] == 'z' || (*arg)[1] == 'Z')) {
- blob_T *blob = NULL;
- // Blob constant: 0z0123456789abcdef
- if (evaluate) {
- blob = tv_blob_alloc();
- }
- char *bp;
- for (bp = *arg + 2; ascii_isxdigit(bp[0]); bp += 2) {
- if (!ascii_isxdigit(bp[1])) {
- if (blob != NULL) {
- emsg(_("E973: Blob literal should have an even number of hex "
- "characters"));
- ga_clear(&blob->bv_ga);
- XFREE_CLEAR(blob);
- }
- ret = FAIL;
- break;
- }
- if (blob != NULL) {
- ga_append(&blob->bv_ga, (char)((hex2nr(*bp) << 4) + hex2nr(*(bp + 1))));
- }
- if (bp[2] == '.' && ascii_isxdigit(bp[3])) {
- bp++;
- }
- }
- if (blob != NULL) {
- tv_blob_set_ret(rettv, blob);
- }
- *arg = bp;
- } else {
- // decimal, hex or octal number
- vim_str2nr(*arg, NULL, &len, STR2NR_ALL, &n, NULL, 0, true);
- if (len == 0) {
- if (evaluate) {
- semsg(_(e_invexpr2), *arg);
- }
- ret = FAIL;
- break;
- }
- *arg += len;
- if (evaluate) {
- rettv->v_type = VAR_NUMBER;
- rettv->vval.v_number = n;
- }
- }
+ case '9':
+ ret = get_number_tv(arg, rettv, evaluate, want_string);
break;
- }
// String constant: "string".
case '"':
@@ -3090,8 +3006,9 @@ static int eval7(char **arg, typval_T *rettv, int evaluate, int want_string)
if (ret == NOTDONE) {
// Must be a variable or function name.
// Can also be a curly-braces kind of name: {expr}.
- s = *arg;
- len = get_name_len((const char **)arg, &alias, evaluate, true);
+ char *s = *arg;
+ char *alias;
+ int len = get_name_len((const char **)arg, &alias, evaluate, true);
if (alias != NULL) {
s = alias;
}
@@ -3716,6 +3633,91 @@ int get_option_tv(const char **const arg, typval_T *const rettv, const bool eval
return ret;
}
+/// Allocate a variable for a number constant. Also deals with "0z" for blob.
+///
+/// @return OK or FAIL.
+static int get_number_tv(char **arg, typval_T *rettv, bool evaluate, bool want_string)
+{
+ char *p = skipdigits(*arg + 1);
+ bool get_float = false;
+
+ // We accept a float when the format matches
+ // "[0-9]\+\.[0-9]\+\([eE][+-]\?[0-9]\+\)\?". This is very
+ // strict to avoid backwards compatibility problems.
+ // Don't look for a float after the "." operator, so that
+ // ":let vers = 1.2.3" doesn't fail.
+ if (!want_string && p[0] == '.' && ascii_isdigit(p[1])) {
+ get_float = true;
+ p = skipdigits(p + 2);
+ if (*p == 'e' || *p == 'E') {
+ p++;
+ if (*p == '-' || *p == '+') {
+ p++;
+ }
+ if (!ascii_isdigit(*p)) {
+ get_float = false;
+ } else {
+ p = skipdigits(p + 1);
+ }
+ }
+ if (ASCII_ISALPHA(*p) || *p == '.') {
+ get_float = false;
+ }
+ }
+ if (get_float) {
+ float_T f;
+ *arg += string2float(*arg, &f);
+ if (evaluate) {
+ rettv->v_type = VAR_FLOAT;
+ rettv->vval.v_float = f;
+ }
+ } else if (**arg == '0' && ((*arg)[1] == 'z' || (*arg)[1] == 'Z')) {
+ // Blob constant: 0z0123456789abcdef
+ blob_T *blob = NULL;
+ if (evaluate) {
+ blob = tv_blob_alloc();
+ }
+ char *bp;
+ for (bp = *arg + 2; ascii_isxdigit(bp[0]); bp += 2) {
+ if (!ascii_isxdigit(bp[1])) {
+ if (blob != NULL) {
+ emsg(_("E973: Blob literal should have an even number of hex characters"));
+ ga_clear(&blob->bv_ga);
+ XFREE_CLEAR(blob);
+ }
+ return FAIL;
+ }
+ if (blob != NULL) {
+ ga_append(&blob->bv_ga, (char)((hex2nr(*bp) << 4) + hex2nr(*(bp + 1))));
+ }
+ if (bp[2] == '.' && ascii_isxdigit(bp[3])) {
+ bp++;
+ }
+ }
+ if (blob != NULL) {
+ tv_blob_set_ret(rettv, blob);
+ }
+ *arg = bp;
+ } else {
+ // decimal, hex or octal number
+ int len;
+ varnumber_T n;
+ vim_str2nr(*arg, NULL, &len, STR2NR_ALL, &n, NULL, 0, true);
+ if (len == 0) {
+ if (evaluate) {
+ semsg(_(e_invexpr2), *arg);
+ }
+ return FAIL;
+ }
+ *arg += len;
+ if (evaluate) {
+ rettv->v_type = VAR_NUMBER;
+ rettv->vval.v_number = n;
+ }
+ }
+ return OK;
+}
+
/// Allocate a variable for a string constant.
///
/// @return OK or FAIL.