os: support pnprintf length modifiers for integers
Mainly for %ld, smaller than int is propagated anyway, and %lld isn't really used. Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> Reviewed-by: Keith Packard <keithp@keithp.com>
This commit is contained in:
parent
d3d4af5f9e
commit
5ea21560dd
90
os/log.c
90
os/log.c
|
@ -279,6 +279,55 @@ LogSetParameter(LogParameter param, int value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum {
|
||||||
|
LMOD_LONG = 0x1,
|
||||||
|
LMOD_LONGLONG = 0x2,
|
||||||
|
LMOD_SHORT = 0x4,
|
||||||
|
LMOD_SIZET = 0x8,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse non-digit length modifiers and set the corresponding flag in
|
||||||
|
* flags_return.
|
||||||
|
*
|
||||||
|
* @return the number of bytes parsed
|
||||||
|
*/
|
||||||
|
static int parse_length_modifier(const char *format, size_t len, int *flags_return)
|
||||||
|
{
|
||||||
|
int idx = 0;
|
||||||
|
int length_modifier = 0;
|
||||||
|
|
||||||
|
while (idx < len) {
|
||||||
|
switch (format[idx]) {
|
||||||
|
case 'l':
|
||||||
|
BUG_RETURN_VAL(length_modifier & LMOD_SHORT, 0);
|
||||||
|
|
||||||
|
if (length_modifier & LMOD_LONG)
|
||||||
|
length_modifier |= LMOD_LONGLONG;
|
||||||
|
else
|
||||||
|
length_modifier |= LMOD_LONG;
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
BUG_RETURN_VAL(length_modifier & (LMOD_LONG|LMOD_LONGLONG), 0);
|
||||||
|
length_modifier |= LMOD_SHORT;
|
||||||
|
/* gcc says 'short int' is promoted to 'int' when
|
||||||
|
* passed through '...', so ignored during
|
||||||
|
* processing */
|
||||||
|
break;
|
||||||
|
case 'z':
|
||||||
|
length_modifier |= LMOD_SIZET;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
*flags_return = length_modifier;
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signal-safe snprintf, with some limitations over snprintf. Be careful
|
* Signal-safe snprintf, with some limitations over snprintf. Be careful
|
||||||
* which directives you use.
|
* which directives you use.
|
||||||
|
@ -297,6 +346,7 @@ pnprintf(char *string, size_t size, const char *f, va_list args)
|
||||||
int64_t si;
|
int64_t si;
|
||||||
|
|
||||||
for (; f_idx < f_len && s_idx < size - 1; f_idx++) {
|
for (; f_idx < f_len && s_idx < size - 1; f_idx++) {
|
||||||
|
int length_modifier = 0;
|
||||||
if (f[f_idx] != '%') {
|
if (f[f_idx] != '%') {
|
||||||
string[s_idx++] = f[f_idx];
|
string[s_idx++] = f[f_idx];
|
||||||
continue;
|
continue;
|
||||||
|
@ -304,10 +354,18 @@ pnprintf(char *string, size_t size, const char *f, va_list args)
|
||||||
|
|
||||||
f_idx++;
|
f_idx++;
|
||||||
|
|
||||||
/* silently swallow length modifiers */
|
/* silently swallow digit length modifiers */
|
||||||
while (f_idx < f_len && ((f[f_idx] >= '0' && f[f_idx] <= '9') || f[f_idx] == '.'))
|
while (f_idx < f_len && ((f[f_idx] >= '0' && f[f_idx] <= '9') || f[f_idx] == '.'))
|
||||||
f_idx++;
|
f_idx++;
|
||||||
|
|
||||||
|
/* non-digit length modifiers */
|
||||||
|
if (f_idx < f_len) {
|
||||||
|
int parsed_bytes = parse_length_modifier(&f[f_idx], f_len - f_idx, &length_modifier);
|
||||||
|
if (parsed_bytes < 0)
|
||||||
|
return 0;
|
||||||
|
f_idx += parsed_bytes;
|
||||||
|
}
|
||||||
|
|
||||||
if (f_idx >= f_len)
|
if (f_idx >= f_len)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -321,7 +379,15 @@ pnprintf(char *string, size_t size, const char *f, va_list args)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'u':
|
case 'u':
|
||||||
ui = va_arg(args, unsigned);
|
if (length_modifier & LMOD_LONGLONG)
|
||||||
|
ui = va_arg(args, unsigned long long);
|
||||||
|
else if (length_modifier & LMOD_LONG)
|
||||||
|
ui = va_arg(args, unsigned long);
|
||||||
|
else if (length_modifier & LMOD_SIZET)
|
||||||
|
ui = va_arg(args, size_t);
|
||||||
|
else
|
||||||
|
ui = va_arg(args, unsigned);
|
||||||
|
|
||||||
FormatUInt64(ui, number);
|
FormatUInt64(ui, number);
|
||||||
p_len = strlen_sigsafe(number);
|
p_len = strlen_sigsafe(number);
|
||||||
|
|
||||||
|
@ -330,7 +396,15 @@ pnprintf(char *string, size_t size, const char *f, va_list args)
|
||||||
break;
|
break;
|
||||||
case 'i':
|
case 'i':
|
||||||
case 'd':
|
case 'd':
|
||||||
si = va_arg(args, int);
|
if (length_modifier & LMOD_LONGLONG)
|
||||||
|
si = va_arg(args, long long);
|
||||||
|
else if (length_modifier & LMOD_LONG)
|
||||||
|
si = va_arg(args, long);
|
||||||
|
else if (length_modifier & LMOD_SIZET)
|
||||||
|
si = va_arg(args, ssize_t);
|
||||||
|
else
|
||||||
|
si = va_arg(args, int);
|
||||||
|
|
||||||
FormatInt64(si, number);
|
FormatInt64(si, number);
|
||||||
p_len = strlen_sigsafe(number);
|
p_len = strlen_sigsafe(number);
|
||||||
|
|
||||||
|
@ -351,7 +425,15 @@ pnprintf(char *string, size_t size, const char *f, va_list args)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'x':
|
case 'x':
|
||||||
ui = va_arg(args, unsigned);
|
if (length_modifier & LMOD_LONGLONG)
|
||||||
|
ui = va_arg(args, unsigned long long);
|
||||||
|
else if (length_modifier & LMOD_LONG)
|
||||||
|
ui = va_arg(args, unsigned long);
|
||||||
|
else if (length_modifier & LMOD_SIZET)
|
||||||
|
ui = va_arg(args, size_t);
|
||||||
|
else
|
||||||
|
ui = va_arg(args, unsigned);
|
||||||
|
|
||||||
FormatUInt64Hex(ui, number);
|
FormatUInt64Hex(ui, number);
|
||||||
p_len = strlen_sigsafe(number);
|
p_len = strlen_sigsafe(number);
|
||||||
|
|
||||||
|
|
|
@ -158,6 +158,8 @@ static void logging_format(void)
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
int i;
|
int i;
|
||||||
unsigned int ui;
|
unsigned int ui;
|
||||||
|
long li;
|
||||||
|
unsigned long lui;
|
||||||
FILE *f;
|
FILE *f;
|
||||||
char read_buf[2048];
|
char read_buf[2048];
|
||||||
char *logmsg;
|
char *logmsg;
|
||||||
|
@ -207,6 +209,14 @@ static void logging_format(void)
|
||||||
LogMessageVerbSigSafe(X_ERROR, -1, "\n");
|
LogMessageVerbSigSafe(X_ERROR, -1, "\n");
|
||||||
fseek(f, 0, SEEK_END);
|
fseek(f, 0, SEEK_END);
|
||||||
|
|
||||||
|
#warning Ignore compiler warning below "unknown conversion type character". This is intentional.
|
||||||
|
/* %hld is bogus */
|
||||||
|
LogMessageVerbSigSafe(X_ERROR, -1, "%hld\n", 4);
|
||||||
|
read_log_msg(logmsg);
|
||||||
|
assert(strstr(logmsg, "BUG") != NULL);
|
||||||
|
LogMessageVerbSigSafe(X_ERROR, -1, "\n");
|
||||||
|
fseek(f, 0, SEEK_END);
|
||||||
|
|
||||||
/* number substitution */
|
/* number substitution */
|
||||||
ui = 0;
|
ui = 0;
|
||||||
do {
|
do {
|
||||||
|
@ -215,12 +225,47 @@ static void logging_format(void)
|
||||||
LogMessageVerbSigSafe(X_ERROR, -1, "%u\n", ui);
|
LogMessageVerbSigSafe(X_ERROR, -1, "%u\n", ui);
|
||||||
read_log_msg(logmsg);
|
read_log_msg(logmsg);
|
||||||
assert(strcmp(logmsg, expected) == 0);
|
assert(strcmp(logmsg, expected) == 0);
|
||||||
|
|
||||||
|
sprintf(expected, "(EE) %x\n", ui);
|
||||||
|
LogMessageVerbSigSafe(X_ERROR, -1, "%x\n", ui);
|
||||||
|
read_log_msg(logmsg);
|
||||||
|
assert(strcmp(logmsg, expected) == 0);
|
||||||
|
|
||||||
if (ui == 0)
|
if (ui == 0)
|
||||||
ui = 1;
|
ui = 1;
|
||||||
else
|
else
|
||||||
ui <<= 1;
|
ui <<= 1;
|
||||||
} while(ui);
|
} while(ui);
|
||||||
|
|
||||||
|
lui = 0;
|
||||||
|
do {
|
||||||
|
char expected[30];
|
||||||
|
sprintf(expected, "(EE) %lu\n", lui);
|
||||||
|
LogMessageVerbSigSafe(X_ERROR, -1, "%lu\n", lui);
|
||||||
|
read_log_msg(logmsg);
|
||||||
|
|
||||||
|
sprintf(expected, "(EE) %lld\n", (unsigned long long)ui);
|
||||||
|
LogMessageVerbSigSafe(X_ERROR, -1, "%lld\n", (unsigned long long)ui);
|
||||||
|
read_log_msg(logmsg);
|
||||||
|
assert(strcmp(logmsg, expected) == 0);
|
||||||
|
|
||||||
|
sprintf(expected, "(EE) %lx\n", lui);
|
||||||
|
printf("%s\n", expected);
|
||||||
|
LogMessageVerbSigSafe(X_ERROR, -1, "%lx\n", lui);
|
||||||
|
read_log_msg(logmsg);
|
||||||
|
assert(strcmp(logmsg, expected) == 0);
|
||||||
|
|
||||||
|
sprintf(expected, "(EE) %llx\n", (unsigned long long)ui);
|
||||||
|
LogMessageVerbSigSafe(X_ERROR, -1, "%llx\n", (unsigned long long)ui);
|
||||||
|
read_log_msg(logmsg);
|
||||||
|
assert(strcmp(logmsg, expected) == 0);
|
||||||
|
|
||||||
|
if (lui == 0)
|
||||||
|
lui = 1;
|
||||||
|
else
|
||||||
|
lui <<= 1;
|
||||||
|
} while(lui);
|
||||||
|
|
||||||
/* signed number substitution */
|
/* signed number substitution */
|
||||||
i = 0;
|
i = 0;
|
||||||
do {
|
do {
|
||||||
|
@ -230,7 +275,6 @@ static void logging_format(void)
|
||||||
read_log_msg(logmsg);
|
read_log_msg(logmsg);
|
||||||
assert(strcmp(logmsg, expected) == 0);
|
assert(strcmp(logmsg, expected) == 0);
|
||||||
|
|
||||||
|
|
||||||
sprintf(expected, "(EE) %d\n", i | INT_MIN);
|
sprintf(expected, "(EE) %d\n", i | INT_MIN);
|
||||||
LogMessageVerbSigSafe(X_ERROR, -1, "%d\n", i | INT_MIN);
|
LogMessageVerbSigSafe(X_ERROR, -1, "%d\n", i | INT_MIN);
|
||||||
read_log_msg(logmsg);
|
read_log_msg(logmsg);
|
||||||
|
@ -242,19 +286,35 @@ static void logging_format(void)
|
||||||
i <<= 1;
|
i <<= 1;
|
||||||
} while(i > INT_MIN);
|
} while(i > INT_MIN);
|
||||||
|
|
||||||
/* hex number substitution */
|
li = 0;
|
||||||
ui = 0;
|
|
||||||
do {
|
do {
|
||||||
char expected[30];
|
char expected[30];
|
||||||
sprintf(expected, "(EE) %x\n", ui);
|
sprintf(expected, "(EE) %ld\n", li);
|
||||||
LogMessageVerbSigSafe(X_ERROR, -1, "%x\n", ui);
|
LogMessageVerbSigSafe(X_ERROR, -1, "%ld\n", li);
|
||||||
read_log_msg(logmsg);
|
read_log_msg(logmsg);
|
||||||
assert(strcmp(logmsg, expected) == 0);
|
assert(strcmp(logmsg, expected) == 0);
|
||||||
if (ui == 0)
|
|
||||||
ui = 1;
|
sprintf(expected, "(EE) %ld\n", li | LONG_MIN);
|
||||||
|
LogMessageVerbSigSafe(X_ERROR, -1, "%ld\n", li | LONG_MIN);
|
||||||
|
read_log_msg(logmsg);
|
||||||
|
assert(strcmp(logmsg, expected) == 0);
|
||||||
|
|
||||||
|
sprintf(expected, "(EE) %lld\n", (long long)li);
|
||||||
|
LogMessageVerbSigSafe(X_ERROR, -1, "%lld\n", (long long)li);
|
||||||
|
read_log_msg(logmsg);
|
||||||
|
assert(strcmp(logmsg, expected) == 0);
|
||||||
|
|
||||||
|
sprintf(expected, "(EE) %lld\n", (long long)(li | LONG_MIN));
|
||||||
|
LogMessageVerbSigSafe(X_ERROR, -1, "%lld\n", (long long)(li | LONG_MIN));
|
||||||
|
read_log_msg(logmsg);
|
||||||
|
assert(strcmp(logmsg, expected) == 0);
|
||||||
|
|
||||||
|
if (li == 0)
|
||||||
|
li = 1;
|
||||||
else
|
else
|
||||||
ui <<= 1;
|
li <<= 1;
|
||||||
} while(ui);
|
} while(li > LONG_MIN);
|
||||||
|
|
||||||
|
|
||||||
/* pointer substitution */
|
/* pointer substitution */
|
||||||
/* we print a null-pointer differently to printf */
|
/* we print a null-pointer differently to printf */
|
||||||
|
|
Loading…
Reference in New Issue