From b4cb5fa610903492f89a70d0ae2d4565ddcd1228 Mon Sep 17 00:00:00 2001 From: Jurica Bradaric Date: Tue, 7 Mar 2017 19:20:07 +0100 Subject: vim-patch:7.4.2266 Problem: printf() test fails on Windows. "-inf" is not used. Solution: Check for Windows-specific values for "nan". Add sign to "inf" when appropriate. https://github.com/vim/vim/commit/9992237a3e791fbc0c1ebf743ece1b75e1488410 --- src/nvim/strings.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'src/nvim/strings.c') diff --git a/src/nvim/strings.c b/src/nvim/strings.c index d03970108b..47ee311bd4 100644 --- a/src/nvim/strings.c +++ b/src/nvim/strings.c @@ -1209,9 +1209,10 @@ int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap, } if (fmt_spec == 'f' && abs_f > 1.0e307) { + const char inf_str[] = f < 0 ? "-inf" : "inf"; // avoid a buffer overflow - memmove(tmp, "inf", sizeof("inf")); - str_arg_l = sizeof("inf") - 1; + memmove(tmp, inf_str, sizeof(inf_str) - 1); + str_arg_l = sizeof(inf_str) - 1; } else { format[0] = '%'; int l = 1; @@ -1234,6 +1235,23 @@ int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap, str_arg_l = (size_t)snprintf(tmp, sizeof(tmp), format, f); assert(str_arg_l < sizeof(tmp)); + // Be consistent: Change "1.#IND" to "nan" and + // "1.#INF" to "inf". + char *s = *tmp == '-' ? tmp + 1 : tmp; + if (STRNCMP(s, "1.#INF", 6) == 0) { + STRCPY(s, "inf"); + } else if (STRNCMP(s, "1.#IND", 6) == 0) { + STRCPY(s, "nan"); + } + // Remove sign before "nan" + if (STRNCMP(tmp, "-nan", 4) == 0) { + STRCPY(tmp, "nan"); + } + // Add sign before "inf" if needed. + if (isinf(f) == -1 && STRNCMP(tmp, "inf", 3) == 0) { + STRCPY(tmp, "-inf"); + } + if (remove_trailing_zeroes) { int i; char *tp; -- cgit From 6ca580be9bffcccc513bfce383a6e1f9f026614c Mon Sep 17 00:00:00 2001 From: Jurica Bradaric Date: Tue, 7 Mar 2017 08:47:31 +0100 Subject: vim-patch:7.4.2280 Problem: printf() doesn't handle infinity float values correctly. Solution: Add a table with possible infinity values. (Dominique Pelle) https://github.com/vim/vim/commit/e999782e369999539a1783a7ebe4eadcc6da28a8 --- src/nvim/strings.c | 57 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 22 deletions(-) (limited to 'src/nvim/strings.c') diff --git a/src/nvim/strings.c b/src/nvim/strings.c index 47ee311bd4..e8d70f2676 100644 --- a/src/nvim/strings.c +++ b/src/nvim/strings.c @@ -753,6 +753,22 @@ int vim_snprintf(char *str, size_t str_m, const char *fmt, ...) return str_l; } +// Return the representation of infinity for printf() function: +// "-inf", "inf", "+inf", " inf", "-INF", "INF", "+INF" or " INF". +static const char *infinity_str(bool positive, char fmt_spec, + int force_sign, int space_for_positive) +{ + static const char *table[] = { + "-inf", "inf", "+inf", " inf", + "-INF", "INF", "+INF", " INF" + }; + int idx = positive * (1 + force_sign + force_sign * space_for_positive); + if (ASCII_ISUPPER(fmt_spec)) { + idx += 4; + } + return table[idx]; +} + /// Write formatted value to the string /// @@ -1209,10 +1225,10 @@ int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap, } if (fmt_spec == 'f' && abs_f > 1.0e307) { - const char inf_str[] = f < 0 ? "-inf" : "inf"; - // avoid a buffer overflow - memmove(tmp, inf_str, sizeof(inf_str) - 1); - str_arg_l = sizeof(inf_str) - 1; + STRCPY(tmp, infinity_str(f > 0.0, fmt_spec, + force_sign, space_for_positive)); + str_arg_l = STRLEN(tmp); + zero_padding = 0; } else { format[0] = '%'; int l = 1; @@ -1231,25 +1247,22 @@ int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap, } format[l] = (char)(fmt_spec == 'F' ? 'f' : fmt_spec); format[l + 1] = NUL; - assert(l + 1 < (int)sizeof(format)); - str_arg_l = (size_t)snprintf(tmp, sizeof(tmp), format, f); - assert(str_arg_l < sizeof(tmp)); - // Be consistent: Change "1.#IND" to "nan" and - // "1.#INF" to "inf". - char *s = *tmp == '-' ? tmp + 1 : tmp; - if (STRNCMP(s, "1.#INF", 6) == 0) { - STRCPY(s, "inf"); - } else if (STRNCMP(s, "1.#IND", 6) == 0) { - STRCPY(s, "nan"); - } - // Remove sign before "nan" - if (STRNCMP(tmp, "-nan", 4) == 0) { - STRCPY(tmp, "nan"); - } - // Add sign before "inf" if needed. - if (isinf(f) == -1 && STRNCMP(tmp, "inf", 3) == 0) { - STRCPY(tmp, "-inf"); + if (isnan(f)) { + // Not a number: nan or NAN + STRCPY(tmp, ASCII_ISUPPER(fmt_spec) ? "NAN" : "nan"); + str_arg_l = 3; + zero_padding = 0; + } else if (isinf(f)) { + STRCPY(tmp, infinity_str(f > 0.0, fmt_spec, + force_sign, space_for_positive)); + str_arg_l = STRLEN(tmp); + zero_padding = 0; + } else { + // Regular float number + assert(l + 1 < (int)sizeof(format)); + str_arg_l = (size_t)snprintf(tmp, sizeof(tmp), format, f); + assert(str_arg_l < sizeof(tmp)); } if (remove_trailing_zeroes) { -- cgit From cad9a76be28f2ee3bd2c48ae959243aa7cfdb02a Mon Sep 17 00:00:00 2001 From: Jurica Bradaric Date: Tue, 7 Mar 2017 21:05:02 +0100 Subject: vim-patch:7.4.2291 Problem: printf() handles floats wrong when there is a sign. Solution: Fix placing the sign. Add tests. (Dominique Pelle) https://github.com/vim/vim/commit/04186095346daa60e82e981dad114de2b641d672 --- src/nvim/strings.c | 53 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 22 deletions(-) (limited to 'src/nvim/strings.c') diff --git a/src/nvim/strings.c b/src/nvim/strings.c index e8d70f2676..a2052423e2 100644 --- a/src/nvim/strings.c +++ b/src/nvim/strings.c @@ -925,7 +925,6 @@ int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap, case 'D': fmt_spec = 'd'; length_modifier = 'l'; break; case 'U': fmt_spec = 'u'; length_modifier = 'l'; break; case 'O': fmt_spec = 'o'; length_modifier = 'l'; break; - case 'F': fmt_spec = 'f'; break; default: break; } @@ -1202,6 +1201,7 @@ int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap, } case 'f': + case 'F': case 'e': case 'E': case 'g': @@ -1217,37 +1217,19 @@ int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap, if (fmt_spec == 'g' || fmt_spec == 'G') { // can't use %g directly, cause it prints "1.0" as "1" if ((abs_f >= 0.001 && abs_f < 10000000.0) || abs_f == 0.0) { - fmt_spec = 'f'; + fmt_spec = ASCII_ISUPPER(fmt_spec) ? 'F' : 'f'; } else { fmt_spec = fmt_spec == 'g' ? 'e' : 'E'; } remove_trailing_zeroes = true; } - if (fmt_spec == 'f' && abs_f > 1.0e307) { + if ((fmt_spec == 'f' || fmt_spec == 'F') && abs_f > 1.0e307) { STRCPY(tmp, infinity_str(f > 0.0, fmt_spec, force_sign, space_for_positive)); str_arg_l = STRLEN(tmp); zero_padding = 0; } else { - format[0] = '%'; - int l = 1; - if (precision_specified) { - size_t max_prec = TMP_LEN - 10; - - // make sure we don't get more digits than we have room for - if (fmt_spec == 'f' && abs_f > 1.0) { - max_prec -= (size_t)log10(abs_f); - } - if (precision > max_prec) { - precision = max_prec; - } - l += snprintf(format + 1, sizeof(format) - 1, ".%d", - (int)precision); - } - format[l] = (char)(fmt_spec == 'F' ? 'f' : fmt_spec); - format[l + 1] = NUL; - if (isnan(f)) { // Not a number: nan or NAN STRCPY(tmp, ASCII_ISUPPER(fmt_spec) ? "NAN" : "nan"); @@ -1259,6 +1241,27 @@ int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap, str_arg_l = STRLEN(tmp); zero_padding = 0; } else { + format[0] = '%'; + int l = 1; + if (force_sign) { + format[l++] = space_for_positive ? ' ' : '+'; + } + if (precision_specified) { + size_t max_prec = TMP_LEN - 10; + + // make sure we don't get more digits than we have room for + if ((fmt_spec == 'f' || fmt_spec == 'F') && abs_f > 1.0) { + max_prec -= (size_t)log10(abs_f); + } + if (precision > max_prec) { + precision = max_prec; + } + l += snprintf(format + l, sizeof(format) - 1, ".%d", + (int)precision); + } + format[l] = (char)(fmt_spec == 'F' ? 'f' : fmt_spec); + format[l + 1] = NUL; + // Regular float number assert(l + 1 < (int)sizeof(format)); str_arg_l = (size_t)snprintf(tmp, sizeof(tmp), format, f); @@ -1270,7 +1273,7 @@ int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap, char *tp; // using %g or %G: remove superfluous zeroes - if (fmt_spec == 'f') { + if (fmt_spec == 'f' || fmt_spec == 'F') { tp = tmp + str_arg_l - 1; } else { tp = (char *)vim_strchr((char_u *)tmp, @@ -1312,6 +1315,12 @@ int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap, } } } + if (zero_padding && min_field_width > str_arg_l + && (tmp[0] == '-' || force_sign)) { + // Padding 0's should be inserted after the sign. + number_of_zeros_to_pad = min_field_width - str_arg_l; + zero_padding_insertion_ind = 1; + } str_arg = tmp; break; } -- cgit From 3e33025133e1e77c7ad3b8670e06175b9757cf30 Mon Sep 17 00:00:00 2001 From: Jurica Bradaric Date: Tue, 21 Mar 2017 22:48:01 +0100 Subject: strings: Fix problems found during code review --- src/nvim/strings.c | 71 +++++++++++++++++++++++++----------------------------- 1 file changed, 33 insertions(+), 38 deletions(-) (limited to 'src/nvim/strings.c') diff --git a/src/nvim/strings.c b/src/nvim/strings.c index a2052423e2..7ec2ea13f7 100644 --- a/src/nvim/strings.c +++ b/src/nvim/strings.c @@ -1224,49 +1224,44 @@ int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap, remove_trailing_zeroes = true; } - if ((fmt_spec == 'f' || fmt_spec == 'F') && abs_f > 1.0e307) { - STRCPY(tmp, infinity_str(f > 0.0, fmt_spec, - force_sign, space_for_positive)); - str_arg_l = STRLEN(tmp); + if (isinf(f) + || (strchr("fF", fmt_spec) != NULL && abs_f > 1.0e307)) { + xstrlcpy(tmp, infinity_str(f > 0.0, fmt_spec, + force_sign, space_for_positive), + sizeof(tmp)); + str_arg_l = strlen(tmp); + zero_padding = 0; + } else if (isnan(f)) { + // Not a number: nan or NAN + memmove(tmp, ASCII_ISUPPER(fmt_spec) ? "NAN" : "nan", 4); + str_arg_l = 3; zero_padding = 0; } else { - if (isnan(f)) { - // Not a number: nan or NAN - STRCPY(tmp, ASCII_ISUPPER(fmt_spec) ? "NAN" : "nan"); - str_arg_l = 3; - zero_padding = 0; - } else if (isinf(f)) { - STRCPY(tmp, infinity_str(f > 0.0, fmt_spec, - force_sign, space_for_positive)); - str_arg_l = STRLEN(tmp); - zero_padding = 0; - } else { - format[0] = '%'; - int l = 1; - if (force_sign) { - format[l++] = space_for_positive ? ' ' : '+'; - } - if (precision_specified) { - size_t max_prec = TMP_LEN - 10; + format[0] = '%'; + size_t l = 1; + if (force_sign) { + format[l++] = space_for_positive ? ' ' : '+'; + } + if (precision_specified) { + size_t max_prec = TMP_LEN - 10; - // make sure we don't get more digits than we have room for - if ((fmt_spec == 'f' || fmt_spec == 'F') && abs_f > 1.0) { - max_prec -= (size_t)log10(abs_f); - } - if (precision > max_prec) { - precision = max_prec; - } - l += snprintf(format + l, sizeof(format) - 1, ".%d", - (int)precision); + // make sure we don't get more digits than we have room for + if ((fmt_spec == 'f' || fmt_spec == 'F') && abs_f > 1.0) { + max_prec -= (size_t)log10(abs_f); } - format[l] = (char)(fmt_spec == 'F' ? 'f' : fmt_spec); - format[l + 1] = NUL; - - // Regular float number - assert(l + 1 < (int)sizeof(format)); - str_arg_l = (size_t)snprintf(tmp, sizeof(tmp), format, f); - assert(str_arg_l < sizeof(tmp)); + if (precision > max_prec) { + precision = max_prec; + } + l += (size_t)snprintf(format + l, sizeof(format) - l, ".%d", + (int)precision); } + format[l] = fmt_spec == 'F' ? 'f' : fmt_spec; + format[l + 1] = NUL; + + // Regular float number + assert(l + 1 < sizeof(format)); + str_arg_l = (size_t)snprintf(tmp, sizeof(tmp), format, f); + assert(str_arg_l < sizeof(tmp)); if (remove_trailing_zeroes) { int i; -- cgit From 56e400d800b9eb6c89ea8336c50d2a61cc8fd18b Mon Sep 17 00:00:00 2001 From: John Szakmeister Date: Wed, 22 Mar 2017 03:49:45 -0400 Subject: vim_vsnprintf: fix conversion warning #6333 Re-apply fix from #6311 which was accidentally regressed in #6231. --- src/nvim/strings.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/nvim/strings.c') diff --git a/src/nvim/strings.c b/src/nvim/strings.c index 7ec2ea13f7..267832ed2d 100644 --- a/src/nvim/strings.c +++ b/src/nvim/strings.c @@ -1255,7 +1255,9 @@ int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap, l += (size_t)snprintf(format + l, sizeof(format) - l, ".%d", (int)precision); } - format[l] = fmt_spec == 'F' ? 'f' : fmt_spec; + + // Cast to char to avoid a conversion warning on Ubuntu 12.04. + format[l] = (char)(fmt_spec == 'F' ? 'f' : fmt_spec); format[l + 1] = NUL; // Regular float number -- cgit From fb146e80aa1ead96518f38b9684e39249bc83485 Mon Sep 17 00:00:00 2001 From: ZyX Date: Tue, 26 Jul 2016 23:16:23 +0300 Subject: eval: Split eval.c into smaller files --- src/nvim/strings.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/strings.c') diff --git a/src/nvim/strings.c b/src/nvim/strings.c index 267832ed2d..b964fed35a 100644 --- a/src/nvim/strings.c +++ b/src/nvim/strings.c @@ -571,7 +571,7 @@ static varnumber_T tv_nr(typval_T *tvs, int *idxp) EMSG(_(e_printf)); } else { (*idxp)++; - int err = false; + bool err = false; n = (varnumber_T)get_tv_number_chk(&tvs[idx], &err); if (err) { n = 0; -- cgit From 28dafe3ff0b0dc082fb62b2251fd64a167ce7188 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 21 Aug 2016 08:16:47 +0300 Subject: eval,*: Move get_tv_string to typval.c Function was renamed and changed to return `const char *`. --- src/nvim/strings.c | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) (limited to 'src/nvim/strings.c') diff --git a/src/nvim/strings.c b/src/nvim/strings.c index b964fed35a..9cfa126a56 100644 --- a/src/nvim/strings.c +++ b/src/nvim/strings.c @@ -291,30 +291,33 @@ void vim_strup(char_u *p) } } -/* - * Make string "s" all upper-case and return it in allocated memory. - * Handles multi-byte characters as well as possible. - */ -char_u *strup_save(const char_u *orig) +/// Make given string all upper-case +/// +/// Handels multi-byte characters as good as possible. +/// +/// @param[in] orig Input string. +/// +/// @return [allocated] upper-cased string. +char *strup_save(const char *const orig) FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL { - char_u *res = vim_strsave(orig); + char *res = xstrdup(orig); - char_u *p = res; + char *p = res; while (*p != NUL) { int l; if (enc_utf8) { - int c = utf_ptr2char(p); + int c = utf_ptr2char((const char_u *)p); int uc = utf_toupper(c); - /* Reallocate string when byte count changes. This is rare, - * thus it's OK to do another malloc()/free(). */ - l = utf_ptr2len(p); + // Reallocate string when byte count changes. This is rare, + // thus it's OK to do another malloc()/free(). + l = utf_ptr2len((const char_u *)p); int newl = utf_char2len(uc); if (newl != l) { // TODO(philix): use xrealloc() in strup_save() - char_u *s = xmalloc(STRLEN(res) + (size_t)(1 + newl - l)); + char *s = xmalloc(STRLEN(res) + (size_t)(1 + newl - l)); memcpy(s, res, (size_t)(p - res)); STRCPY(s + (p - res) + newl, p + l); p = s + (p - res); @@ -322,12 +325,13 @@ char_u *strup_save(const char_u *orig) res = s; } - utf_char2bytes(uc, p); + utf_char2bytes(uc, (char_u *)p); p += newl; - } else if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1) - p += l; /* skip multi-byte character */ - else { - *p = (char_u) TOUPPER_LOC(*p); // note that toupper() can be a macro + } else if (has_mbyte && (l = (*mb_ptr2len)((const char_u *)p)) > 1) { + p += l; // Skip multi-byte character. + } else { + // note that toupper() can be a macro + *p = (char)(uint8_t)TOUPPER_LOC(*p); p++; } } -- cgit From 233b0c93bba66492d7b8b61f8ac61082f03668a1 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 28 Aug 2016 08:55:58 +0300 Subject: eval: Move get_tv_number[_chk] to eval/typval.c --- src/nvim/strings.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/strings.c') diff --git a/src/nvim/strings.c b/src/nvim/strings.c index 9cfa126a56..e20979c307 100644 --- a/src/nvim/strings.c +++ b/src/nvim/strings.c @@ -576,7 +576,7 @@ static varnumber_T tv_nr(typval_T *tvs, int *idxp) } else { (*idxp)++; bool err = false; - n = (varnumber_T)get_tv_number_chk(&tvs[idx], &err); + n = tv_get_number_chk(&tvs[idx], &err); if (err) { n = 0; } -- cgit From c8e63a8db84e9d9f7bd855085a87d93631504fc7 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 4 Sep 2016 02:25:24 +0300 Subject: eval: Move remaining get_tv_string* functions to eval/typval.c --- src/nvim/strings.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'src/nvim/strings.c') diff --git a/src/nvim/strings.c b/src/nvim/strings.c index e20979c307..5dcffe00e0 100644 --- a/src/nvim/strings.c +++ b/src/nvim/strings.c @@ -598,22 +598,21 @@ static varnumber_T tv_nr(typval_T *tvs, int *idxp) /// free "*tofree". /// /// @return String value or NULL in case of error. -static char *tv_str(typval_T *tvs, int *idxp, char ** const tofree) +static const char *tv_str(typval_T *tvs, int *idxp, char **const tofree) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { int idx = *idxp - 1; - char *s = NULL; + const char *s = NULL; if (tvs[idx].v_type == VAR_UNKNOWN) { EMSG(_(e_printf)); } else { (*idxp)++; if (tvs[idx].v_type == VAR_STRING || tvs[idx].v_type == VAR_NUMBER) { - s = (char *)get_tv_string_chk(&tvs[idx]); + s = tv_get_string_chk(&tvs[idx]); *tofree = NULL; } else { - s = encode_tv2echo(&tvs[idx], NULL); - *tofree = s; + s = *tofree = encode_tv2echo(&tvs[idx], NULL); } } return s; @@ -953,7 +952,7 @@ int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap, case 's': case 'S': str_arg = tvs ? tv_str(tvs, &arg_idx, &tofree) - : va_arg(ap, char *); + : va_arg(ap, const char *); if (!str_arg) { str_arg = "[NULL]"; str_arg_l = 6; -- cgit From 19044a15f9d41a7424e94fb3f0e257537e7afa5e Mon Sep 17 00:00:00 2001 From: ZyX Date: Thu, 6 Apr 2017 21:21:11 +0300 Subject: strings: Replace vim_strchr implementation with a saner one Removes dead code (enc_utf8, enc_dbcs and has_mbyte now have hardcoded values), relies on libc implementation being more optimized. Also where previously negative character just would never be found it is an assertion error now. Ref #1476 --- src/nvim/strings.c | 64 ++++++++++++++++-------------------------------------- 1 file changed, 19 insertions(+), 45 deletions(-) (limited to 'src/nvim/strings.c') diff --git a/src/nvim/strings.c b/src/nvim/strings.c index 5dcffe00e0..c4bc9b204a 100644 --- a/src/nvim/strings.c +++ b/src/nvim/strings.c @@ -401,54 +401,28 @@ int vim_strnicmp(const char *s1, const char *s2, size_t len) } #endif -/* - * Version of strchr() and strrchr() that handle unsigned char strings - * with characters from 128 to 255 correctly. It also doesn't return a - * pointer to the NUL at the end of the string. - */ -char_u *vim_strchr(const char_u *string, int c) - FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE +/// strchr() version which handles multibyte strings +/// +/// @param[in] string String to search in. +/// @param[in] c Character to search for. Must be a valid character. +/// +/// @return Pointer to the first byte of the found character in string or NULL +/// if it was not found. NUL character is never found, use `strlen()` +/// instead. +char_u *vim_strchr(const char_u *const string, const int c) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { - int b; - - const char_u *p = string; - if (enc_utf8 && c >= 0x80) { - while (*p != NUL) { - int l = (*mb_ptr2len)(p); - - // Avoid matching an illegal byte here. - if (l > 1 && utf_ptr2char(p) == c) { - return (char_u *) p; - } - p += l; - } + assert(c >= 0); + if (c == 0) { return NULL; + } else if (c < 0x80) { + return (char_u *)strchr((const char *)string, c); + } else { + char u8char[MB_MAXBYTES + 1]; + const int len = utf_char2bytes(c, (char_u *)u8char); + u8char[len] = NUL; + return (char_u *)strstr((const char *)string, u8char); } - if (enc_dbcs != 0 && c > 255) { - int n2 = c & 0xff; - - c = ((unsigned)c >> 8) & 0xff; - while ((b = *p) != NUL) { - if (b == c && p[1] == n2) - return (char_u *) p; - p += (*mb_ptr2len)(p); - } - return NULL; - } - if (has_mbyte) { - while ((b = *p) != NUL) { - if (b == c) - return (char_u *) p; - p += (*mb_ptr2len)(p); - } - return NULL; - } - while ((b = *p) != NUL) { - if (b == c) - return (char_u *) p; - ++p; - } - return NULL; } /* -- cgit From 171baaee93c8e257ef593b30c05405d03ac30c96 Mon Sep 17 00:00:00 2001 From: ZyX Date: Thu, 6 Apr 2017 21:31:37 +0300 Subject: strings: Remove vim_strbyte Ref #1476 --- src/nvim/strings.c | 18 ------------------ 1 file changed, 18 deletions(-) (limited to 'src/nvim/strings.c') diff --git a/src/nvim/strings.c b/src/nvim/strings.c index c4bc9b204a..ada4c108cf 100644 --- a/src/nvim/strings.c +++ b/src/nvim/strings.c @@ -425,24 +425,6 @@ char_u *vim_strchr(const char_u *const string, const int c) } } -/* - * Version of strchr() that only works for bytes and handles unsigned char - * strings with characters above 128 correctly. It also doesn't return a - * pointer to the NUL at the end of the string. - */ -char_u *vim_strbyte(const char_u *string, int c) - FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE -{ - const char_u *p = string; - - while (*p != NUL) { - if (*p == c) - return (char_u *) p; - ++p; - } - return NULL; -} - /* * Search for last occurrence of "c" in "string". * Return NULL if not found. -- cgit From db9ef6263ec5b7885782ccf0a93e06b0c71f6944 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Sat, 8 Apr 2017 16:45:38 +0200 Subject: mbyte: replace vim_tolower with mb_tolower handling locale correctly --- src/nvim/strings.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/strings.c') diff --git a/src/nvim/strings.c b/src/nvim/strings.c index 5dcffe00e0..e7c0fb8a7d 100644 --- a/src/nvim/strings.c +++ b/src/nvim/strings.c @@ -309,7 +309,7 @@ char *strup_save(const char *const orig) if (enc_utf8) { int c = utf_ptr2char((const char_u *)p); - int uc = utf_toupper(c); + int uc = mb_toupper(c); // Reallocate string when byte count changes. This is rare, // thus it's OK to do another malloc()/free(). -- cgit From 4c857dae1169f3b8c7b6a9740f50acfd3c16858d Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Sun, 9 Apr 2017 09:29:00 +0200 Subject: vim-patch:8.0.0243 Problem: When making a character lower case with tolower() changes the byte cound, it is not made lower case. Solution: Add strlow_save(). (Dominique Pelle, closes vim/vim#1406) https://github.com/vim/vim/commit/cc5b22b3bfdc0e9e835cf7871166badda31447bd Join almost identical strup_save and strlow_save functions to one Function. --- src/nvim/strings.c | 51 ++++++++++++++++++++++----------------------------- 1 file changed, 22 insertions(+), 29 deletions(-) (limited to 'src/nvim/strings.c') diff --git a/src/nvim/strings.c b/src/nvim/strings.c index e7c0fb8a7d..87e066d80a 100644 --- a/src/nvim/strings.c +++ b/src/nvim/strings.c @@ -291,14 +291,15 @@ void vim_strup(char_u *p) } } -/// Make given string all upper-case +/// Make given string all upper-case or all lower-case /// -/// Handels multi-byte characters as good as possible. +/// Handles multi-byte characters as good as possible. /// /// @param[in] orig Input string. +/// @param[in] upper If true make uppercase, otherwise lowercase /// /// @return [allocated] upper-cased string. -char *strup_save(const char *const orig) +char *strcase_save(const char *const orig, bool upper) FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL { char *res = xstrdup(orig); @@ -307,33 +308,25 @@ char *strup_save(const char *const orig) while (*p != NUL) { int l; - if (enc_utf8) { - int c = utf_ptr2char((const char_u *)p); - int uc = mb_toupper(c); - - // Reallocate string when byte count changes. This is rare, - // thus it's OK to do another malloc()/free(). - l = utf_ptr2len((const char_u *)p); - int newl = utf_char2len(uc); - if (newl != l) { - // TODO(philix): use xrealloc() in strup_save() - char *s = xmalloc(STRLEN(res) + (size_t)(1 + newl - l)); - memcpy(s, res, (size_t)(p - res)); - STRCPY(s + (p - res) + newl, p + l); - p = s + (p - res); - xfree(res); - res = s; - } - - utf_char2bytes(uc, (char_u *)p); - p += newl; - } else if (has_mbyte && (l = (*mb_ptr2len)((const char_u *)p)) > 1) { - p += l; // Skip multi-byte character. - } else { - // note that toupper() can be a macro - *p = (char)(uint8_t)TOUPPER_LOC(*p); - p++; + int c = utf_ptr2char((const char_u *)p); + int uc = upper ? mb_toupper(c) : mb_tolower(c); + + // Reallocate string when byte count changes. This is rare, + // thus it's OK to do another malloc()/free(). + l = utf_ptr2len((const char_u *)p); + int newl = utf_char2len(uc); + if (newl != l) { + // TODO(philix): use xrealloc() in strup_save() + char *s = xmalloc(STRLEN(res) + (size_t)(1 + newl - l)); + memcpy(s, res, (size_t)(p - res)); + STRCPY(s + (p - res) + newl, p + l); + p = s + (p - res); + xfree(res); + res = s; } + + utf_char2bytes(uc, (char_u *)p); + p += newl; } return res; -- cgit From f7611d74e73329a4192666ff59911ff214f462ab Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Fri, 24 Mar 2017 14:42:42 +0100 Subject: win: vim_strsave_shellescape: Handle 'shellslash'. From Vim, misc2.c:vim_strsave_shellescape --- src/nvim/strings.c | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) (limited to 'src/nvim/strings.c') diff --git a/src/nvim/strings.c b/src/nvim/strings.c index 87e066d80a..8a1a3beddd 100644 --- a/src/nvim/strings.c +++ b/src/nvim/strings.c @@ -198,8 +198,16 @@ char_u *vim_strsave_shellescape(const char_u *string, /* First count the number of extra bytes required. */ size_t length = STRLEN(string) + 3; // two quotes and a trailing NUL for (const char_u *p = string; *p != NUL; mb_ptr_adv(p)) { - if (*p == '\'') - length += 3; /* ' => '\'' */ +#ifdef WIN32 + if (!p_ssl) { + if (*p == '"') { + length++; // " -> "" + } + } else +#endif + if (*p == '\'') { + length += 3; // ' => '\'' + } if ((*p == '\n' && (csh_like || do_newline)) || (*p == '!' && (csh_like || do_special))) { ++length; /* insert backslash */ @@ -216,10 +224,25 @@ char_u *vim_strsave_shellescape(const char_u *string, escaped_string = xmalloc(length); d = escaped_string; - /* add opening quote */ + // add opening quote +#ifdef WIN32 + if (!p_ssl) { + *d++ = '"'; + } else +#endif *d++ = '\''; for (const char_u *p = string; *p != NUL; ) { +#ifdef WIN32 + if (!p_ssl) { + if (*p == '"') { + *d++ = '"'; + *d++ = '"'; + p++; + continue; + } + } else +#endif if (*p == '\'') { *d++ = '\''; *d++ = '\\'; @@ -246,7 +269,12 @@ char_u *vim_strsave_shellescape(const char_u *string, MB_COPY_CHAR(p, d); } - /* add terminating quote and finish with a NUL */ + // add terminating quote and finish with a NUL +# ifdef WIN32 + if (!p_ssl) { + *d++ = '"'; + } else +# endif *d++ = '\''; *d = NUL; -- cgit From c2f3e361c52ec4e7149ea1d8c6a1202e0873da8e Mon Sep 17 00:00:00 2001 From: ZyX Date: Wed, 19 Apr 2017 19:11:50 +0300 Subject: *: Add comment to all C files --- src/nvim/strings.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/nvim/strings.c') diff --git a/src/nvim/strings.c b/src/nvim/strings.c index 8a1a3beddd..743b43c2e5 100644 --- a/src/nvim/strings.c +++ b/src/nvim/strings.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 #include #include -- cgit From 823b35e3414dca0c77697e6e59ec30244b7f4eab Mon Sep 17 00:00:00 2001 From: ZyX Date: Tue, 9 May 2017 14:32:18 +0300 Subject: strings: Return NUL from vim_strchr for invalid input --- src/nvim/strings.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'src/nvim/strings.c') diff --git a/src/nvim/strings.c b/src/nvim/strings.c index f19cf7a261..c5fd8741b8 100644 --- a/src/nvim/strings.c +++ b/src/nvim/strings.c @@ -428,16 +428,15 @@ int vim_strnicmp(const char *s1, const char *s2, size_t len) /// strchr() version which handles multibyte strings /// /// @param[in] string String to search in. -/// @param[in] c Character to search for. Must be a valid character. +/// @param[in] c Character to search for. /// /// @return Pointer to the first byte of the found character in string or NULL -/// if it was not found. NUL character is never found, use `strlen()` -/// instead. +/// if it was not found or character is invalid. NUL character is never +/// found, use `strlen()` instead. char_u *vim_strchr(const char_u *const string, const int c) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { - assert(c >= 0); - if (c == 0) { + if (c <= 0) { return NULL; } else if (c < 0x80) { return (char_u *)strchr((const char *)string, c); -- cgit From c3efb2804a6bcf3b61695cd2b0c60bb16f1ec0a9 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Wed, 16 Nov 2016 14:30:20 -0500 Subject: vim-patch:7.4.2029 Problem: printf() does not work with 64 bit numbers. Solution: use the "L" length modifier. (Ken Takata) https://github.com/vim/vim/commit/38ee6b041e73ad31c3b6b99d56d20833b59b2b57 --- src/nvim/strings.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/nvim/strings.c') diff --git a/src/nvim/strings.c b/src/nvim/strings.c index c5fd8741b8..9b9aa6d2f4 100644 --- a/src/nvim/strings.c +++ b/src/nvim/strings.c @@ -910,6 +910,13 @@ int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap, default: break; } + switch (fmt_spec) { + case 'd': case 'u': case 'o': case 'x': case 'X': + if (tvs && length_modifier == '\0') { + length_modifier = '2'; + } + } + // get parameter value, do initial processing switch (fmt_spec) { // '%' and 'c' behave similar to 's' regarding flags and field widths -- cgit From 601bf9642fe8f3655a3090d093843ae136110f27 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Tue, 6 Jun 2017 09:56:09 -0400 Subject: strings/tv_float: Explicitly cast v_number to float_T for -Wconversion --- src/nvim/strings.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/strings.c') diff --git a/src/nvim/strings.c b/src/nvim/strings.c index 9b9aa6d2f4..687f734742 100644 --- a/src/nvim/strings.c +++ b/src/nvim/strings.c @@ -653,7 +653,7 @@ static float_T tv_float(typval_T *const tvs, int *const idxp) if (tvs[idx].v_type == VAR_FLOAT) { f = tvs[idx].vval.v_float; } else if (tvs[idx].v_type == VAR_NUMBER) { - f = tvs[idx].vval.v_number; + f = (float_T)tvs[idx].vval.v_number; } else { EMSG(_("E807: Expected Float argument for printf()")); } -- cgit