kern/misc: Add a format specifier GUIDs

Extend the printf format specifier for pointers (%p) to accept a suffix
specifier G to print GUIDs: %pG can be used to print grub_guid structs.
This does not interfere with the -Wformat checking of gcc. Note that
the data type is not checked though (%p accepts void *).

Signed-off-by: Oliver Steffen <osteffen@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
This commit is contained in:
Oliver Steffen authored and Daniel Kiper committed 2023-06-01 11:45:00 +02:00
1 parent 06edd40db7
commit f82dbf2bd8
1 file changed
+60 -21
+60 -21
View File
@@ -24,6 +24,7 @@
#include <grub/term.h> #include <grub/term.h>
#include <grub/env.h> #include <grub/env.h>
#include <grub/i18n.h> #include <grub/i18n.h>
#include <grub/types.h>
union printf_arg union printf_arg
{ {
@@ -34,7 +35,8 @@ union printf_arg
{ {
INT, LONG, LONGLONG, INT, LONG, LONGLONG,
UNSIGNED_INT = 3, UNSIGNED_LONG, UNSIGNED_LONGLONG, UNSIGNED_INT = 3, UNSIGNED_LONG, UNSIGNED_LONGLONG,
STRING STRING,
GUID
} type; } type;
long long ll; long long ll;
}; };
@@ -772,6 +774,9 @@ parse_printf_arg_fmt (const char *fmt0, struct printf_args *args,
switch (c) switch (c)
{ {
case 'p': case 'p':
if (*(fmt) == 'G')
++fmt;
/* Fall through. */
case 'x': case 'x':
case 'X': case 'X':
case 'u': case 'u':
@@ -885,6 +890,10 @@ parse_printf_arg_fmt (const char *fmt0, struct printf_args *args,
args->ptr[curn].type = UNSIGNED_LONGLONG; args->ptr[curn].type = UNSIGNED_LONGLONG;
else else
args->ptr[curn].type = UNSIGNED_INT; args->ptr[curn].type = UNSIGNED_INT;
if (*(fmt) == 'G') {
args->ptr[curn].type = GUID;
++fmt;
}
break; break;
case 's': case 's':
args->ptr[curn].type = STRING; args->ptr[curn].type = STRING;
@@ -926,6 +935,7 @@ parse_printf_args (const char *fmt0, struct printf_args *args, va_list args_in)
args->ptr[n].ll = va_arg (args_in, long long); args->ptr[n].ll = va_arg (args_in, long long);
break; break;
case STRING: case STRING:
case GUID:
if (sizeof (void *) == sizeof (long long)) if (sizeof (void *) == sizeof (long long))
args->ptr[n].ll = va_arg (args_in, long long); args->ptr[n].ll = va_arg (args_in, long long);
else else
@@ -943,6 +953,27 @@ write_char (char *str, grub_size_t *count, grub_size_t max_len, unsigned char ch
(*count)++; (*count)++;
} }
static void
write_number (char *str, grub_size_t *count, grub_size_t max_len, grub_size_t format1,
char rightfill, char zerofill, char c, long long value)
{
char tmp[32];
const char *p = tmp;
grub_size_t len;
grub_size_t fill;
len = grub_lltoa (tmp, c, value) - tmp;
fill = len < format1 ? format1 - len : 0;
if (! rightfill)
while (fill--)
write_char (str, count, max_len, zerofill);
while (*p)
write_char (str, count, max_len, *p++);
if (rightfill)
while (fill--)
write_char (str, count, max_len, zerofill);
}
static int static int
grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt0, grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt0,
struct printf_args *args) struct printf_args *args)
@@ -1025,31 +1056,39 @@ grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt0,
switch (c) switch (c)
{ {
case 'p': case 'p':
write_char (str, &count, max_len, '0'); if (*(fmt) == 'G')
write_char (str, &count, max_len, 'x'); {
c = 'x'; ++fmt;
grub_guid_t *guid = (grub_guid_t *)(grub_addr_t) curarg;
write_number (str, &count, max_len, 8, 0, '0', 'x', guid->data1);
write_char (str, &count, max_len, '-');
write_number (str, &count, max_len, 4, 0, '0', 'x', guid->data2);
write_char (str, &count, max_len, '-');
write_number (str, &count, max_len, 4, 0, '0', 'x', guid->data3);
write_char (str, &count, max_len, '-');
write_number (str, &count, max_len, 2, 0, '0', 'x', guid->data4[0]);
write_number (str, &count, max_len, 2, 0, '0', 'x', guid->data4[1]);
write_char (str, &count, max_len, '-');
write_number (str, &count, max_len, 2, 0, '0', 'x', guid->data4[2]);
write_number (str, &count, max_len, 2, 0, '0', 'x', guid->data4[3]);
write_number (str, &count, max_len, 2, 0, '0', 'x', guid->data4[4]);
write_number (str, &count, max_len, 2, 0, '0', 'x', guid->data4[5]);
write_number (str, &count, max_len, 2, 0, '0', 'x', guid->data4[6]);
write_number (str, &count, max_len, 2, 0, '0', 'x', guid->data4[7]);
break;
}
else
{
write_char (str, &count, max_len, '0');
write_char (str, &count, max_len, 'x');
c = 'x';
}
/* Fall through. */ /* Fall through. */
case 'x': case 'x':
case 'X': case 'X':
case 'u': case 'u':
case 'd': case 'd':
{ write_number (str, &count, max_len, format1, rightfill, zerofill, c, curarg);
char tmp[32];
const char *p = tmp;
grub_size_t len;
grub_size_t fill;
len = grub_lltoa (tmp, c, curarg) - tmp;
fill = len < format1 ? format1 - len : 0;
if (! rightfill)
while (fill--)
write_char (str, &count, max_len, zerofill);
while (*p)
write_char (str, &count, max_len, *p++);
if (rightfill)
while (fill--)
write_char (str, &count, max_len, zerofill);
}
break; break;
case 'c': case 'c':