diff options
Diffstat (limited to 'src/nvim/strings.c')
| -rw-r--r-- | src/nvim/strings.c | 63 | 
1 files changed, 50 insertions, 13 deletions
| diff --git a/src/nvim/strings.c b/src/nvim/strings.c index 7768636ded..267832ed2d 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  /// @@ -909,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;        } @@ -1186,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': @@ -1201,36 +1217,51 @@ 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) { -              // avoid a buffer overflow -              memmove(tmp, "inf", sizeof("inf")); -              str_arg_l = sizeof("inf") - 1; +            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 {                format[0] = '%'; -              int l = 1; +              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' && abs_f > 1.0) { +                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 + 1, sizeof(format) - 1, ".%d", -                              (int)precision); +                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; -              assert(l + 1 < (int)sizeof(format)); + +              // 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)); @@ -1239,7 +1270,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, @@ -1281,6 +1312,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;            } | 
