efi/printf: Factor out flags parsing and handle '%' earlier
authorArvind Sankar <nivedita@alum.mit.edu>
Mon, 18 May 2020 19:07:00 +0000 (15:07 -0400)
committerArd Biesheuvel <ardb@kernel.org>
Tue, 19 May 2020 08:31:25 +0000 (10:31 +0200)
Move flags parsing code out into a helper function.

The '%%' case can be handled up front: it is not allowed to have flags,
width etc.

Signed-off-by: Arvind Sankar <nivedita@alum.mit.edu>
Link: https://lore.kernel.org/r/20200518190716.751506-9-nivedita@alum.mit.edu
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
drivers/firmware/efi/libstub/vsprintf.c

index 8fd15e8..fb9eb83 100644 (file)
@@ -202,6 +202,35 @@ static char *number(char *str, long long num, int base, int size, int precision,
        return str;
 }
 
+static
+int get_flags(const char **fmt)
+{
+       int flags = 0;
+
+       do {
+               switch (**fmt) {
+               case '-':
+                       flags |= LEFT;
+                       break;
+               case '+':
+                       flags |= PLUS;
+                       break;
+               case ' ':
+                       flags |= SPACE;
+                       break;
+               case '#':
+                       flags |= SPECIAL;
+                       break;
+               case '0':
+                       flags |= ZEROPAD;
+                       break;
+               default:
+                       return flags;
+               }
+               ++(*fmt);
+       } while (1);
+}
+
 int vsprintf(char *buf, const char *fmt, va_list args)
 {
        int len;
@@ -218,32 +247,13 @@ int vsprintf(char *buf, const char *fmt, va_list args)
        int qualifier;          /* 'h', 'hh', 'l' or 'll' for integer fields */
 
        for (str = buf; *fmt; ++fmt) {
-               if (*fmt != '%') {
+               if (*fmt != '%' || *++fmt == '%') {
                        *str++ = *fmt;
                        continue;
                }
 
                /* process flags */
-               flags = 0;
-             repeat:
-               ++fmt;          /* this also skips first '%' */
-               switch (*fmt) {
-               case '-':
-                       flags |= LEFT;
-                       goto repeat;
-               case '+':
-                       flags |= PLUS;
-                       goto repeat;
-               case ' ':
-                       flags |= SPACE;
-                       goto repeat;
-               case '#':
-                       flags |= SPECIAL;
-                       goto repeat;
-               case '0':
-                       flags |= ZEROPAD;
-                       goto repeat;
-               }
+               flags = get_flags(&fmt);
 
                /* get field width */
                field_width = -1;
@@ -321,10 +331,6 @@ int vsprintf(char *buf, const char *fmt, va_list args)
                                     field_width, precision, flags);
                        continue;
 
-               case '%':
-                       *str++ = '%';
-                       continue;
-
                        /* integer number formats - set up the flags and "break" */
                case 'o':
                        base = 8;