vsprintf: avoid nested switch statement on same variable

Now that we have simplified the number format types, the top-level
switch table can easily just handle all the remaining cases, and we
don't need to have a case statement with a conditional on the same
expression as the switch statement.

We do want to fall through to the common 'number()' case, but that's
trivially done by making the other case statements use 'continue'
instead of 'break'.  They are just looping back to the top, after all.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Linus Torvalds 2024-12-16 10:26:53 -08:00
parent be503db4d0
commit 03d23941bf
1 changed files with 47 additions and 52 deletions

View File

@ -2816,16 +2816,16 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
memcpy(str, old_fmt, copy); memcpy(str, old_fmt, copy);
} }
str += read; str += read;
break; continue;
} }
case FORMAT_TYPE_WIDTH: case FORMAT_TYPE_WIDTH:
set_field_width(&spec, va_arg(args, int)); set_field_width(&spec, va_arg(args, int));
break; continue;
case FORMAT_TYPE_PRECISION: case FORMAT_TYPE_PRECISION:
set_precision(&spec, va_arg(args, int)); set_precision(&spec, va_arg(args, int));
break; continue;
case FORMAT_TYPE_CHAR: { case FORMAT_TYPE_CHAR: {
char c; char c;
@ -2847,25 +2847,25 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
*str = ' '; *str = ' ';
++str; ++str;
} }
break; continue;
} }
case FORMAT_TYPE_STR: case FORMAT_TYPE_STR:
str = string(str, end, va_arg(args, char *), spec); str = string(str, end, va_arg(args, char *), spec);
break; continue;
case FORMAT_TYPE_PTR: case FORMAT_TYPE_PTR:
str = pointer(fmt, str, end, va_arg(args, void *), str = pointer(fmt, str, end, va_arg(args, void *),
spec); spec);
while (isalnum(*fmt)) while (isalnum(*fmt))
fmt++; fmt++;
break; continue;
case FORMAT_TYPE_PERCENT_CHAR: case FORMAT_TYPE_PERCENT_CHAR:
if (str < end) if (str < end)
*str = '%'; *str = '%';
++str; ++str;
break; continue;
case FORMAT_TYPE_INVALID: case FORMAT_TYPE_INVALID:
/* /*
@ -2878,15 +2878,17 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
*/ */
goto out; goto out;
default: case FORMAT_TYPE_8BYTE:
if (spec.type == FORMAT_TYPE_8BYTE)
num = va_arg(args, long long); num = va_arg(args, long long);
else break;
default:
num = convert_num_spec(va_arg(args, int), spec); num = convert_num_spec(va_arg(args, int), spec);
break;
}
str = number(str, end, num, spec); str = number(str, end, num, spec);
} }
}
out: out:
if (size > 0) { if (size > 0) {
@ -3154,8 +3156,6 @@ int vbin_printf(u32 *bin_buf, size_t size, const char *fmt, va_list args)
fmt++; fmt++;
break; break;
default:
switch (spec.type) {
case FORMAT_TYPE_8BYTE: case FORMAT_TYPE_8BYTE:
save_arg(long long); save_arg(long long);
break; break;
@ -3169,7 +3169,6 @@ int vbin_printf(u32 *bin_buf, size_t size, const char *fmt, va_list args)
save_arg(int); save_arg(int);
} }
} }
}
out: out:
return (u32 *)(PTR_ALIGN(str, sizeof(u32))) - bin_buf; return (u32 *)(PTR_ALIGN(str, sizeof(u32))) - bin_buf;
@ -3235,6 +3234,7 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf)
while (*fmt) { while (*fmt) {
const char *old_fmt = fmt; const char *old_fmt = fmt;
int read = format_decode(fmt, &spec); int read = format_decode(fmt, &spec);
unsigned long long num;
fmt += read; fmt += read;
@ -3247,16 +3247,16 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf)
memcpy(str, old_fmt, copy); memcpy(str, old_fmt, copy);
} }
str += read; str += read;
break; continue;
} }
case FORMAT_TYPE_WIDTH: case FORMAT_TYPE_WIDTH:
set_field_width(&spec, get_arg(int)); set_field_width(&spec, get_arg(int));
break; continue;
case FORMAT_TYPE_PRECISION: case FORMAT_TYPE_PRECISION:
set_precision(&spec, get_arg(int)); set_precision(&spec, get_arg(int));
break; continue;
case FORMAT_TYPE_CHAR: { case FORMAT_TYPE_CHAR: {
char c; char c;
@ -3277,14 +3277,14 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf)
*str = ' '; *str = ' ';
++str; ++str;
} }
break; continue;
} }
case FORMAT_TYPE_STR: { case FORMAT_TYPE_STR: {
const char *str_arg = args; const char *str_arg = args;
args += strlen(str_arg) + 1; args += strlen(str_arg) + 1;
str = string(str, end, (char *)str_arg, spec); str = string(str, end, (char *)str_arg, spec);
break; continue;
} }
case FORMAT_TYPE_PTR: { case FORMAT_TYPE_PTR: {
@ -3319,22 +3319,18 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf)
while (isalnum(*fmt)) while (isalnum(*fmt))
fmt++; fmt++;
break; continue;
} }
case FORMAT_TYPE_PERCENT_CHAR: case FORMAT_TYPE_PERCENT_CHAR:
if (str < end) if (str < end)
*str = '%'; *str = '%';
++str; ++str;
break; continue;
case FORMAT_TYPE_INVALID: case FORMAT_TYPE_INVALID:
goto out; goto out;
default: {
unsigned long long num;
switch (spec.type) {
case FORMAT_TYPE_8BYTE: case FORMAT_TYPE_8BYTE:
num = get_arg(long long); num = get_arg(long long);
break; break;
@ -3346,11 +3342,10 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf)
break; break;
default: default:
num = convert_num_spec(get_arg(int), spec); num = convert_num_spec(get_arg(int), spec);
break;
} }
str = number(str, end, num, spec); str = number(str, end, num, spec);
} /* default: */
} /* switch(spec.type) */
} /* while(*fmt) */ } /* while(*fmt) */
out: out: