Re: the printk problem

From: Vegard Nossum
Date: Sat Jul 05 2008 - 08:52:49 EST


On Sat, Jul 5, 2008 at 1:33 PM, Jan Engelhardt <jengelh@xxxxxxxxxx> wrote:
>
> On Saturday 2008-07-05 00:01, Andrew Morton wrote:
>>
>>We don't know how much interest there would be in churning NIPQUAD from
>>the net guys. Interestingly, there's also %C (wint_t) which is a
>>32-bit quantity. So we could just go and say "%C prints an ipv4
>>address" and be done with it. But there's no way of doing that for
>>ipv6 addresses so things would become asymmetrical there.
>
> struct in6_addr src;
> printk("Source address: %p{ipv6}\n", &src);
>
> How about %p{feature}?

Something like this?

(It's hard on the stack, yes, I know. We should fix kallsyms.)

Vegard


From: Vegard Nossum <vegard.nossum@xxxxxxxxx>
Date: Sat, 5 Jul 2008 14:01:00 +0200
Subject: [PATCH] printf: add %p{} extension

Signed-off-by: Vegard Nossum <vegard.nossum@xxxxxxxxx>
---
lib/vsprintf.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 44 insertions(+), 0 deletions(-)

diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 6021757..011cf3f 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -17,6 +17,7 @@
*/

#include <stdarg.h>
+#include <linux/kallsyms.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/string.h>
@@ -366,6 +367,30 @@ static noinline char* put_dec(char *buf, unsigned long long num)
#define SMALL 32 /* Must be 32 == 0x20 */
#define SPECIAL 64 /* 0x */

+static char *custom_format(char *buf, char *end,
+ const char *fmt, unsigned int fmtlen, void *arg)
+{
+ if (!strncmp(fmt, "sym", fmtlen)) {
+ char name[KSYM_SYMBOL_LEN];
+ int len;
+ int i;
+
+ len = sprint_symbol(name, (unsigned long) arg);
+ if (len < 0)
+ return buf;
+
+ i = 0;
+ while (i < len) {
+ if (buf < end)
+ *buf = name[i];
+ ++buf;
+ ++i;
+ }
+ }
+
+ return buf;
+}
+
static char *number(char *buf, char *end, unsigned long long num, int base, int size, int precision, int type)
{
/* we are called with base 8, 10 or 16, only, thus don't need "G..." */
@@ -648,6 +673,25 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
continue;

case 'p':
+ if (fmt[1] == '{') {
+ const char *cfmt;
+
+ /* Skip the '%{' */
+ ++fmt;
+ ++fmt;
+
+ cfmt = fmt;
+
+ /* Skip everything up to the '}' */
+ while (*fmt && *fmt != '}')
+ ++fmt;
+
+ str = custom_format(str, end,
+ cfmt, fmt - cfmt,
+ va_arg(args, void *));
+ continue;
+ }
+
flags |= SMALL;
if (field_width == -1) {
field_width = 2*sizeof(void *);
--
1.5.4.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/