aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/message.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/message.c')
-rw-r--r--src/nvim/message.c141
1 files changed, 96 insertions, 45 deletions
diff --git a/src/nvim/message.c b/src/nvim/message.c
index 66b8b9b5d2..00f4c0a85c 100644
--- a/src/nvim/message.c
+++ b/src/nvim/message.c
@@ -3037,7 +3037,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 +3103,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 +3177,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 +3188,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 +3201,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 +3212,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 +3265,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 +3285,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 +3298,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 +3333,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 +3343,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 +3374,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 +3401,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 +3421,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 +3455,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 +3513,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 +3558,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 +3569,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) {