diff options
Diffstat (limited to 'src/nvim/strings.c')
| -rw-r--r-- | src/nvim/strings.c | 205 | 
1 files changed, 98 insertions, 107 deletions
| diff --git a/src/nvim/strings.c b/src/nvim/strings.c index 5dcffe00e0..b3a0e4816b 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 <inttypes.h>  #include <stdarg.h>  #include <stdbool.h> @@ -47,6 +50,13 @@  #include "nvim/os/shell.h"  #include "nvim/eval/encode.h" +#ifdef __MINGW32__ +# undef fpclassify +# define fpclassify __fpclassify +# undef isnan +# define isnan _isnan +#endif +  /*   * Copy "string" into newly allocated memory.   */ @@ -198,8 +208,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 +234,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 +279,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; @@ -291,14 +329,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 +346,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 = utf_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; @@ -401,72 +432,27 @@ 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. +/// +/// @return Pointer to the first byte of the found character in string or NULL +///         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  { -  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; -    } -    return NULL; -  } -  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); -    } +  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 (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; -} - -/* - * 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;  }  /* @@ -674,7 +660,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()"));      } @@ -931,6 +917,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 @@ -1152,8 +1145,8 @@ int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap,                                                f, uarg);                  break;                } -              assert(str_arg_l < sizeof(tmp));              } +            assert(str_arg_l < sizeof(tmp));              // include the optional minus sign and possible "0x" in the region              // before the zero padding insertion point @@ -1383,16 +1376,14 @@ int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap,          }          // insert zero padding as requested by precision or min field width -        if (number_of_zeros_to_pad > 0) { -          size_t zn = number_of_zeros_to_pad; -          if (str_avail) { -            size_t avail = str_m - str_l; -            memset(str + str_l, '0', MIN(zn, avail)); -            str_avail = zn < avail; -          } -          assert(zn <= SIZE_MAX - str_l); -          str_l += zn; +        size_t zn = number_of_zeros_to_pad; +        if (str_avail) { +          size_t avail = str_m - str_l; +          memset(str + str_l, '0', MIN(zn, avail)); +          str_avail = zn < avail;          } +        assert(zn <= SIZE_MAX - str_l); +        str_l += zn;        }        // insert formatted string | 
