diff options
Diffstat (limited to 'src/nvim/message.c')
-rw-r--r-- | src/nvim/message.c | 144 |
1 files changed, 98 insertions, 46 deletions
diff --git a/src/nvim/message.c b/src/nvim/message.c index 66b8b9b5d2..1dd71baaa4 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -1396,7 +1396,8 @@ void msg_prt_line(char_u *s, int list) c = *p_extra++; } else if (has_mbyte && (l = (*mb_ptr2len)(s)) > 1) { col += (*mb_ptr2cells)(s); - if (lcs_nbsp != NUL && list && mb_ptr2char(s) == 160) { + if (lcs_nbsp != NUL && list + && (mb_ptr2char(s) == 160 || mb_ptr2char(s) == 0x202f)) { mb_char2bytes(lcs_nbsp, buf); buf[(*mb_ptr2len)(buf)] = NUL; } else { @@ -3037,7 +3038,7 @@ static double tv_float(typval_T *tvs, int *idxp) * http://www.ijs.si/software/snprintf/ * * This snprintf() only supports the following conversion specifiers: - * s, c, d, u, o, x, X, p (and synonyms: i, D, U, O - see below) + * s, c, b, B, d, u, o, x, X, p (and synonyms: i, D, U, O - see below) * with flags: '-', '+', ' ', '0' and '#'. * An asterisk is supported for field width as well as precision. * @@ -3103,8 +3104,9 @@ int vim_vsnprintf(char *str, size_t str_m, char *fmt, va_list ap, typval_T *tvs) char *p = fmt; int arg_idx = 1; - if (!p) + if (!p) { p = ""; + } while (*p) { if (*p != '%') { // copy up to the next '%' or NUL without any changes @@ -3176,9 +3178,9 @@ int vim_vsnprintf(char *str, size_t str_m, char *fmt, va_list ap, typval_T *tvs) if (*p == '*') { p++; int j = tvs ? tv_nr(tvs, &arg_idx) : va_arg(ap, int); - if (j >= 0) + if (j >= 0) { min_field_width = j; - else { + } else { min_field_width = -j; justify_left = 1; } @@ -3187,8 +3189,9 @@ int vim_vsnprintf(char *str, size_t str_m, char *fmt, va_list ap, typval_T *tvs) // argument like common implementations do unsigned int uj = *p++ - '0'; - while (ascii_isdigit((int)(*p))) + while (ascii_isdigit((int)(*p))) { uj = 10 * uj + (unsigned int)(*p++ - '0'); + } min_field_width = uj; } @@ -3199,9 +3202,9 @@ int vim_vsnprintf(char *str, size_t str_m, char *fmt, va_list ap, typval_T *tvs) if (*p == '*') { int j = tvs ? tv_nr(tvs, &arg_idx) : va_arg(ap, int); p++; - if (j >= 0) + if (j >= 0) { precision = j; - else { + } else { precision_specified = 0; precision = 0; } @@ -3210,8 +3213,9 @@ int vim_vsnprintf(char *str, size_t str_m, char *fmt, va_list ap, typval_T *tvs) // treat argument like common implementations do unsigned int uj = *p++ - '0'; - while (ascii_isdigit((int)(*p))) + while (ascii_isdigit((int)(*p))) { uj = 10 * uj + (unsigned int)(*p++ - '0'); + } precision = uj; } } @@ -3262,14 +3266,13 @@ int vim_vsnprintf(char *str, size_t str_m, char *fmt, va_list ap, typval_T *tvs) if (!str_arg) { str_arg = "[NULL]"; str_arg_l = 6; - } - // make sure not to address string beyond the specified precision - else if (!precision_specified) + } else if (!precision_specified) { + // make sure not to address string beyond the specified precision str_arg_l = strlen(str_arg); - // truncate string if necessary as requested by precision - else if (precision == 0) + } else if (precision == 0) { + // truncate string if necessary as requested by precision str_arg_l = 0; - else { + } else { // memchr on HP does not like n > 2^31 // TODO(elmart): check if this still holds / is relevant str_arg_l = (size_t)((char *)xmemscan(str_arg, @@ -3283,8 +3286,9 @@ int vim_vsnprintf(char *str, size_t str_m, char *fmt, va_list ap, typval_T *tvs) - mb_string2cells((char_u *) str_arg); if (precision) { char_u *p1 = (char_u *)str_arg; - for (size_t i = 0; i < precision && *p1; i++) + for (size_t i = 0; i < precision && *p1; i++) { p1 += mb_ptr2len(p1); + } str_arg_l = precision = p1 - (char_u *)str_arg; } } @@ -3295,9 +3299,14 @@ int vim_vsnprintf(char *str, size_t str_m, char *fmt, va_list ap, typval_T *tvs) } break; - case 'd': case 'u': case 'o': case 'x': case 'X': case 'p': { - // u, o, x, X and p conversion specifiers imply the value is unsigned; - // d implies a signed value + case 'd': + case 'u': + case 'b': case 'B': + case 'o': + case 'x': case 'X': + case 'p': { + // u, b, B, o, x, X and p conversion specifiers imply + // the value is unsigned; d implies a signed value // 0 if numeric argument is zero (or if pointer is NULL for 'p'), // +1 if greater than zero (or non NULL for 'p'), @@ -3325,8 +3334,9 @@ int vim_vsnprintf(char *str, size_t str_m, char *fmt, va_list ap, typval_T *tvs) if (fmt_spec == 'p') { length_modifier = '\0'; ptr_arg = tvs ? (void *)tv_str(tvs, &arg_idx) : va_arg(ap, void *); - if (ptr_arg) + if (ptr_arg) { arg_sign = 1; + } } else if (fmt_spec == 'd') { // signed switch (length_modifier) { @@ -3334,25 +3344,28 @@ int vim_vsnprintf(char *str, size_t str_m, char *fmt, va_list ap, typval_T *tvs) case 'h': // char and short arguments are passed as int int_arg = tvs ? tv_nr(tvs, &arg_idx) : va_arg(ap, int); - if (int_arg > 0) + if (int_arg > 0) { arg_sign = 1; - else if (int_arg < 0) + } else if (int_arg < 0) { arg_sign = -1; + } break; case 'l': long_arg = tvs ? tv_nr(tvs, &arg_idx) : va_arg(ap, long int); - if (long_arg > 0) + if (long_arg > 0) { arg_sign = 1; - else if (long_arg < 0) + } else if (long_arg < 0) { arg_sign = -1; + } break; case '2': long_long_arg = tvs ? tv_nr(tvs, &arg_idx) - : va_arg(ap, long long int); - if (long_long_arg > 0) + : va_arg(ap, long long int); // NOLINT (runtime/int) + if (long_long_arg > 0) { arg_sign = 1; - else if (long_long_arg < 0) + } else if (long_long_arg < 0) { arg_sign = -1; + } break; } } else { @@ -3362,24 +3375,23 @@ int vim_vsnprintf(char *str, size_t str_m, char *fmt, va_list ap, typval_T *tvs) case 'h': uint_arg = tvs ? (unsigned)tv_nr(tvs, &arg_idx) : va_arg(ap, unsigned int); - if (uint_arg != 0) - arg_sign = 1; + if (uint_arg != 0) { arg_sign = 1; } break; case 'l': ulong_arg = tvs ? (unsigned long)tv_nr(tvs, &arg_idx) : va_arg(ap, unsigned long int); - if (ulong_arg != 0) - arg_sign = 1; + if (ulong_arg != 0) { arg_sign = 1; } break; case '2': - ulong_long_arg = tvs ? (unsigned long long)tv_nr(tvs, &arg_idx) - : va_arg(ap, unsigned long long int); - if (ulong_long_arg) arg_sign = 1; + ulong_long_arg = tvs + ? (unsigned long long)tv_nr(tvs, &arg_idx) // NOLINT (runtime/int) + : va_arg(ap, unsigned long long int); // NOLINT (runtime/int) + if (ulong_long_arg) { arg_sign = 1; } break; case 'z': size_t_arg = tvs ? (size_t)tv_nr(tvs, &arg_idx) : va_arg(ap, size_t); - if (size_t_arg) arg_sign = 1; + if (size_t_arg) { arg_sign = 1; } break; } } @@ -3390,16 +3402,19 @@ int vim_vsnprintf(char *str, size_t str_m, char *fmt, va_list ap, typval_T *tvs) // For d, i, u, o, x, and X conversions, if precision is specified, // '0' flag should be ignored. This is so with Solaris 2.6, Digital UNIX // 4.0, HPUX 10, Linux, FreeBSD, NetBSD; but not with Perl. - if (precision_specified) + if (precision_specified) { zero_padding = 0; + } if (fmt_spec == 'd') { - if (force_sign && arg_sign >= 0) + if (force_sign && arg_sign >= 0) { tmp[str_arg_l++] = space_for_positive ? ' ' : '+'; + } // leave negative numbers for sprintf to handle, to // avoid handling tricky cases like (short int)-32768 } else if (alternate_form) { - if (arg_sign != 0 && (fmt_spec == 'x' || fmt_spec == 'X') ) { + if (arg_sign != 0 && (fmt_spec == 'x' || fmt_spec == 'X' || + fmt_spec == 'b' || fmt_spec == 'B')) { tmp[str_arg_l++] = '0'; tmp[str_arg_l++] = fmt_spec; } @@ -3407,20 +3422,20 @@ int vim_vsnprintf(char *str, size_t str_m, char *fmt, va_list ap, typval_T *tvs) } zero_padding_insertion_ind = str_arg_l; - if (!precision_specified) + if (!precision_specified) { precision = 1; // default precision is 1 + } if (precision == 0 && arg_sign == 0) { // when zero value is formatted with an explicit precision 0, - // resulting formatted string is empty (d, i, u, o, x, X, p) + // resulting formatted string is empty (d, i, u, b, B, o, x, X, p) } else { char f[5]; int f_l = 0; // construct a simple format string for sprintf f[f_l++] = '%'; - if (!length_modifier) - ; - else if (length_modifier == '2') { + if (!length_modifier) { + } else if (length_modifier == '2') { f[f_l++] = 'l'; f[f_l++] = 'l'; } else @@ -3441,6 +3456,41 @@ int vim_vsnprintf(char *str, size_t str_m, char *fmt, va_list ap, typval_T *tvs) case '2': str_arg_l += sprintf(tmp + str_arg_l, f, long_long_arg); break; } + } else if (fmt_spec == 'b' || fmt_spec == 'B') { + // binary + size_t bits = 0; + switch (length_modifier) { + case '\0': + case 'h': for (bits = sizeof(unsigned) * 8; bits > 0; bits--) { + if ((uint_arg >> (bits - 1)) & 0x1) { break; } } + + while (bits > 0) { + tmp[str_arg_l++] = + ((uint_arg >> --bits) & 0x1) ? '1' : '0'; } + break; + case 'l': for (bits = sizeof(unsigned long) * 8; bits > 0; bits--) { + if ((ulong_arg >> (bits - 1)) & 0x1) { break; } } + + while (bits > 0) { + tmp[str_arg_l++] = + ((ulong_arg >> --bits) & 0x1) ? '1' : '0'; } + break; + case '2': for (bits = sizeof(unsigned long long) * 8; // NOLINT (runtime/int) + bits > 0; bits--) { + if ((ulong_long_arg >> (bits - 1)) & 0x1) { break; } } + + while (bits > 0) { + tmp[str_arg_l++] = + ((ulong_long_arg >> --bits) & 0x1) ? '1' : '0'; } + break; + case 'z': for (bits = sizeof(size_t) * 8; bits > 0; bits--) { + if ((size_t_arg >> (bits - 1)) & 0x1) { break; } } + + while (bits > 0) { + tmp[str_arg_l++] = + ((size_t_arg >> --bits) & 0x1) ? '1' : '0'; } + break; + } } else { // unsigned switch (length_modifier) { @@ -3464,7 +3514,9 @@ int vim_vsnprintf(char *str, size_t str_m, char *fmt, va_list ap, typval_T *tvs) if (zero_padding_insertion_ind + 1 < str_arg_l && tmp[zero_padding_insertion_ind] == '0' && (tmp[zero_padding_insertion_ind + 1] == 'x' - || tmp[zero_padding_insertion_ind + 1] == 'X')) + || tmp[zero_padding_insertion_ind + 1] == 'X' + || tmp[zero_padding_insertion_ind + 1] == 'b' + || tmp[zero_padding_insertion_ind + 1] == 'B')) zero_padding_insertion_ind += 2; } @@ -3507,7 +3559,7 @@ int vim_vsnprintf(char *str, size_t str_m, char *fmt, va_list ap, typval_T *tvs) // floating point char format[40]; int l; - int remove_trailing_zeroes = FALSE; + int remove_trailing_zeroes = false; double f = tvs ? tv_float(tvs, &arg_idx) : va_arg(ap, double); double abs_f = f < 0 ? -f : f; @@ -3518,7 +3570,7 @@ int vim_vsnprintf(char *str, size_t str_m, char *fmt, va_list ap, typval_T *tvs) fmt_spec = 'f'; else fmt_spec = fmt_spec == 'g' ? 'e' : 'E'; - remove_trailing_zeroes = TRUE; + remove_trailing_zeroes = true; } if (fmt_spec == 'f' && abs_f > 1.0e307) { |