2009-03-27 09:10:19

by Zhao Lei

[permalink] [raw]
Subject: [PATCH 1/2] Add support of hh length modifier for printk

hh is used as length modifier for signed char or unsigned char.
It is supported by glibc, we add kernel support now.

Signed-off-by: Zhao Lei <[email protected]>
---
lib/vsprintf.c | 37 ++++++++++++++++++++++++++++++++-----
1 files changed, 32 insertions(+), 5 deletions(-)

diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index be3001f..908dd41 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -408,6 +408,8 @@ enum format_type {
FORMAT_TYPE_LONG_LONG,
FORMAT_TYPE_ULONG,
FORMAT_TYPE_LONG,
+ FORMAT_TYPE_UBYTE,
+ FORMAT_TYPE_BYTE,
FORMAT_TYPE_USHORT,
FORMAT_TYPE_SHORT,
FORMAT_TYPE_UINT,
@@ -853,11 +855,15 @@ qualifier:
spec->qualifier = -1;
if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
*fmt == 'Z' || *fmt == 'z' || *fmt == 't') {
- spec->qualifier = *fmt;
- ++fmt;
- if (spec->qualifier == 'l' && *fmt == 'l') {
- spec->qualifier = 'L';
- ++fmt;
+ spec->qualifier = *fmt++;
+ if (unlikely(spec->qualifier == *fmt)) {
+ if (spec->qualifier == 'l') {
+ spec->qualifier = 'L';
+ ++fmt;
+ } else if (spec->qualifier == 'h') {
+ spec->qualifier = 'H';
+ ++fmt;
+ }
}
}

@@ -919,6 +925,11 @@ qualifier:
spec->type = FORMAT_TYPE_SIZE_T;
} else if (spec->qualifier == 't') {
spec->type = FORMAT_TYPE_PTRDIFF;
+ } else if (spec->qualifier == 'H') {
+ if (spec->flags & SIGN)
+ spec->type = FORMAT_TYPE_BYTE;
+ else
+ spec->type = FORMAT_TYPE_UBYTE;
} else if (spec->qualifier == 'h') {
if (spec->flags & SIGN)
spec->type = FORMAT_TYPE_SHORT;
@@ -1094,6 +1105,12 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
case FORMAT_TYPE_PTRDIFF:
num = va_arg(args, ptrdiff_t);
break;
+ case FORMAT_TYPE_UBYTE:
+ num = (unsigned char) va_arg(args, int);
+ break;
+ case FORMAT_TYPE_BYTE:
+ num = (signed char) va_arg(args, int);
+ break;
case FORMAT_TYPE_USHORT:
num = (unsigned short) va_arg(args, int);
break;
@@ -1372,6 +1389,10 @@ do { \
case FORMAT_TYPE_PTRDIFF:
save_arg(ptrdiff_t);
break;
+ case FORMAT_TYPE_UBYTE:
+ case FORMAT_TYPE_BYTE:
+ save_arg(char);
+ break;
case FORMAT_TYPE_USHORT:
case FORMAT_TYPE_SHORT:
save_arg(short);
@@ -1554,6 +1575,12 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf)
case FORMAT_TYPE_PTRDIFF:
num = get_arg(ptrdiff_t);
break;
+ case FORMAT_TYPE_UBYTE:
+ num = get_arg(unsigned char);
+ break;
+ case FORMAT_TYPE_BYTE:
+ num = get_arg(signed char);
+ break;
case FORMAT_TYPE_USHORT:
num = get_arg(unsigned short);
break;
--
1.5.5.3


2009-03-27 09:12:17

by Zhao Lei

[permalink] [raw]
Subject: [PATCH 2/2] Fix wrong format string iter for printk

printk("%Q");
Output before patch:
%QQ
Output after patch:
%Q

Signed-off-by: Zhao Lei <[email protected]>
---
lib/vsprintf.c | 16 ----------------
1 files changed, 0 insertions(+), 16 deletions(-)

diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 908dd41..b56f6d0 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -1062,13 +1062,6 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
if (str < end)
*str = '%';
++str;
- if (*fmt) {
- if (str < end)
- *str = *fmt;
- ++str;
- } else {
- --fmt;
- }
break;

case FORMAT_TYPE_NRCHARS: {
@@ -1356,8 +1349,6 @@ do { \
break;

case FORMAT_TYPE_INVALID:
- if (!*fmt)
- --fmt;
break;

case FORMAT_TYPE_NRCHARS: {
@@ -1544,13 +1535,6 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf)
if (str < end)
*str = '%';
++str;
- if (*fmt) {
- if (str < end)
- *str = *fmt;
- ++str;
- } else {
- --fmt;
- }
break;

case FORMAT_TYPE_NRCHARS:
--
1.5.5.3

2009-03-27 09:36:15

by Lai Jiangshan

[permalink] [raw]
Subject: Re: [PATCH 1/2] Add support of hh length modifier for printk

Zhaolei wrote:
> hh is used as length modifier for signed char or unsigned char.
> It is supported by glibc, we add kernel support now.
>
> Signed-off-by: Zhao Lei <[email protected]>
> ---
> lib/vsprintf.c | 37 ++++++++++++++++++++++++++++++++-----
> 1 files changed, 32 insertions(+), 5 deletions(-)
>
> diff --git a/lib/vsprintf.c b/lib/vsprintf.c
> index be3001f..908dd41 100644
> --- a/lib/vsprintf.c
> +++ b/lib/vsprintf.c
> @@ -408,6 +408,8 @@ enum format_type {
> FORMAT_TYPE_LONG_LONG,
> FORMAT_TYPE_ULONG,
> FORMAT_TYPE_LONG,
> + FORMAT_TYPE_UBYTE,
> + FORMAT_TYPE_BYTE,
> FORMAT_TYPE_USHORT,
> FORMAT_TYPE_SHORT,
> FORMAT_TYPE_UINT,
> @@ -853,11 +855,15 @@ qualifier:
> spec->qualifier = -1;
> if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
> *fmt == 'Z' || *fmt == 'z' || *fmt == 't') {
> - spec->qualifier = *fmt;
> - ++fmt;
> - if (spec->qualifier == 'l' && *fmt == 'l') {
> - spec->qualifier = 'L';
> - ++fmt;
> + spec->qualifier = *fmt++;
> + if (unlikely(spec->qualifier == *fmt)) {
> + if (spec->qualifier == 'l') {
> + spec->qualifier = 'L';
> + ++fmt;
> + } else if (spec->qualifier == 'h') {
> + spec->qualifier = 'H';
> + ++fmt;
> + }
> }
> }
>
> @@ -919,6 +925,11 @@ qualifier:
> spec->type = FORMAT_TYPE_SIZE_T;
> } else if (spec->qualifier == 't') {
> spec->type = FORMAT_TYPE_PTRDIFF;
> + } else if (spec->qualifier == 'H') {
> + if (spec->flags & SIGN)
> + spec->type = FORMAT_TYPE_BYTE;
> + else
> + spec->type = FORMAT_TYPE_UBYTE;
> } else if (spec->qualifier == 'h') {
> if (spec->flags & SIGN)
> spec->type = FORMAT_TYPE_SHORT;
> @@ -1094,6 +1105,12 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
> case FORMAT_TYPE_PTRDIFF:
> num = va_arg(args, ptrdiff_t);
> break;
> + case FORMAT_TYPE_UBYTE:
> + num = (unsigned char) va_arg(args, int);
> + break;
> + case FORMAT_TYPE_BYTE:
> + num = (signed char) va_arg(args, int);
> + break;
> case FORMAT_TYPE_USHORT:
> num = (unsigned short) va_arg(args, int);
> break;
> @@ -1372,6 +1389,10 @@ do { \
> case FORMAT_TYPE_PTRDIFF:
> save_arg(ptrdiff_t);
> break;
> + case FORMAT_TYPE_UBYTE:
> + case FORMAT_TYPE_BYTE:
> + save_arg(char);
> + break;
> case FORMAT_TYPE_USHORT:
> case FORMAT_TYPE_SHORT:
> save_arg(short);
> @@ -1554,6 +1575,12 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf)
> case FORMAT_TYPE_PTRDIFF:
> num = get_arg(ptrdiff_t);
> break;
> + case FORMAT_TYPE_UBYTE:
> + num = get_arg(unsigned char);
> + break;
> + case FORMAT_TYPE_BYTE:
> + num = get_arg(signed char);
> + break;
> case FORMAT_TYPE_USHORT:
> num = get_arg(unsigned short);
> break;

It's fine. hh modifier is supported by ISO C99.
And for vbin_printf(), it will consume less memory.

Review-by: Lai Jiangshan <[email protected]>

2009-03-27 09:36:37

by Lai Jiangshan

[permalink] [raw]
Subject: Re: [PATCH 2/2] Fix wrong format string iter for printk

Zhaolei wrote:
> printk("%Q");
> Output before patch:
> %QQ
> Output after patch:
> %Q
>
> Signed-off-by: Zhao Lei <[email protected]>
> ---
> lib/vsprintf.c | 16 ----------------
> 1 files changed, 0 insertions(+), 16 deletions(-)
>
> diff --git a/lib/vsprintf.c b/lib/vsprintf.c
> index 908dd41..b56f6d0 100644
> --- a/lib/vsprintf.c
> +++ b/lib/vsprintf.c
> @@ -1062,13 +1062,6 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
> if (str < end)
> *str = '%';
> ++str;
> - if (*fmt) {
> - if (str < end)
> - *str = *fmt;
> - ++str;
> - } else {
> - --fmt;
> - }
> break;
>
> case FORMAT_TYPE_NRCHARS: {
> @@ -1356,8 +1349,6 @@ do { \
> break;
>
> case FORMAT_TYPE_INVALID:
> - if (!*fmt)
> - --fmt;
> break;
>
> case FORMAT_TYPE_NRCHARS: {
> @@ -1544,13 +1535,6 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf)
> if (str < end)
> *str = '%';
> ++str;
> - if (*fmt) {
> - if (str < end)
> - *str = *fmt;
> - ++str;
> - } else {
> - --fmt;
> - }
> break;
>
> case FORMAT_TYPE_NRCHARS:

It's nice.
Review-by: Lai Jiangshan <[email protected]>

2009-03-27 12:45:14

by Frederic Weisbecker

[permalink] [raw]
Subject: Re: [PATCH 1/2] Add support of hh length modifier for printk

On Fri, Mar 27, 2009 at 05:07:05PM +0800, Zhaolei wrote:
> hh is used as length modifier for signed char or unsigned char.
> It is supported by glibc, we add kernel support now.
>
> Signed-off-by: Zhao Lei <[email protected]>
> ---
> lib/vsprintf.c | 37 ++++++++++++++++++++++++++++++++-----
> 1 files changed, 32 insertions(+), 5 deletions(-)
>
> diff --git a/lib/vsprintf.c b/lib/vsprintf.c
> index be3001f..908dd41 100644
> --- a/lib/vsprintf.c
> +++ b/lib/vsprintf.c
> @@ -408,6 +408,8 @@ enum format_type {
> FORMAT_TYPE_LONG_LONG,
> FORMAT_TYPE_ULONG,
> FORMAT_TYPE_LONG,
> + FORMAT_TYPE_UBYTE,
> + FORMAT_TYPE_BYTE,
> FORMAT_TYPE_USHORT,
> FORMAT_TYPE_SHORT,
> FORMAT_TYPE_UINT,
> @@ -853,11 +855,15 @@ qualifier:
> spec->qualifier = -1;
> if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
> *fmt == 'Z' || *fmt == 'z' || *fmt == 't') {
> - spec->qualifier = *fmt;
> - ++fmt;
> - if (spec->qualifier == 'l' && *fmt == 'l') {
> - spec->qualifier = 'L';
> - ++fmt;
> + spec->qualifier = *fmt++;
> + if (unlikely(spec->qualifier == *fmt)) {
> + if (spec->qualifier == 'l') {
> + spec->qualifier = 'L';
> + ++fmt;
> + } else if (spec->qualifier == 'h') {
> + spec->qualifier = 'H';
> + ++fmt;
> + }
> }
> }
>
> @@ -919,6 +925,11 @@ qualifier:
> spec->type = FORMAT_TYPE_SIZE_T;
> } else if (spec->qualifier == 't') {
> spec->type = FORMAT_TYPE_PTRDIFF;
> + } else if (spec->qualifier == 'H') {
> + if (spec->flags & SIGN)
> + spec->type = FORMAT_TYPE_BYTE;
> + else
> + spec->type = FORMAT_TYPE_UBYTE;
> } else if (spec->qualifier == 'h') {
> if (spec->flags & SIGN)
> spec->type = FORMAT_TYPE_SHORT;
> @@ -1094,6 +1105,12 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
> case FORMAT_TYPE_PTRDIFF:
> num = va_arg(args, ptrdiff_t);
> break;
> + case FORMAT_TYPE_UBYTE:
> + num = (unsigned char) va_arg(args, int);
> + break;
> + case FORMAT_TYPE_BYTE:
> + num = (signed char) va_arg(args, int);
> + break;
> case FORMAT_TYPE_USHORT:
> num = (unsigned short) va_arg(args, int);
> break;
> @@ -1372,6 +1389,10 @@ do { \
> case FORMAT_TYPE_PTRDIFF:
> save_arg(ptrdiff_t);
> break;
> + case FORMAT_TYPE_UBYTE:
> + case FORMAT_TYPE_BYTE:
> + save_arg(char);
> + break;
> case FORMAT_TYPE_USHORT:
> case FORMAT_TYPE_SHORT:
> save_arg(short);
> @@ -1554,6 +1575,12 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf)
> case FORMAT_TYPE_PTRDIFF:
> num = get_arg(ptrdiff_t);
> break;
> + case FORMAT_TYPE_UBYTE:
> + num = get_arg(unsigned char);
> + break;
> + case FORMAT_TYPE_BYTE:
> + num = get_arg(signed char);
> + break;
> case FORMAT_TYPE_USHORT:
> num = get_arg(unsigned short);
> break;
> --
> 1.5.5.3
>
>


Looks good.

2009-03-27 12:54:04

by Frederic Weisbecker

[permalink] [raw]
Subject: Re: [PATCH 2/2] Fix wrong format string iter for printk

On Fri, Mar 27, 2009 at 05:09:10PM +0800, Zhaolei wrote:
> printk("%Q");
> Output before patch:
> %QQ
> Output after patch:
> %Q
>
> Signed-off-by: Zhao Lei <[email protected]>
> ---
> lib/vsprintf.c | 16 ----------------
> 1 files changed, 0 insertions(+), 16 deletions(-)
>
> diff --git a/lib/vsprintf.c b/lib/vsprintf.c
> index 908dd41..b56f6d0 100644
> --- a/lib/vsprintf.c
> +++ b/lib/vsprintf.c
> @@ -1062,13 +1062,6 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
> if (str < end)
> *str = '%';
> ++str;
> - if (*fmt) {
> - if (str < end)
> - *str = *fmt;
> - ++str;
> - } else {
> - --fmt;
> - }
> break;
>
> case FORMAT_TYPE_NRCHARS: {
> @@ -1356,8 +1349,6 @@ do { \
> break;
>
> case FORMAT_TYPE_INVALID:
> - if (!*fmt)
> - --fmt;
> break;
>
> case FORMAT_TYPE_NRCHARS: {
> @@ -1544,13 +1535,6 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf)
> if (str < end)
> *str = '%';
> ++str;
> - if (*fmt) {
> - if (str < end)
> - *str = *fmt;
> - ++str;
> - } else {
> - --fmt;
> - }
> break;
>
> case FORMAT_TYPE_NRCHARS:
> --
> 1.5.5.3
>
>


Thanks for fixing this!

2009-04-08 15:07:33

by Zhao Lei

[permalink] [raw]
Subject: [tip:core/urgent] printk: fix wrong format string iter for printk

Commit-ID: 022624a758dc9489388a99ad29577b4c8c09237c
Gitweb: http://git.kernel.org/tip/022624a758dc9489388a99ad29577b4c8c09237c
Author: Zhaolei <[email protected]>
AuthorDate: Fri, 27 Mar 2009 17:09:10 +0800
Committer: Ingo Molnar <[email protected]>
CommitDate: Wed, 8 Apr 2009 17:03:44 +0200

printk: fix wrong format string iter for printk

printk("%Q");

Output before patch: %QQ
Output after patch: %Q

Signed-off-by: Zhao Lei <[email protected]>
Acked-by: Lai Jiangshan <[email protected]>
Acked-by: Frederic Weisbecker <[email protected]>
Cc: [email protected]
Cc: Steven Rostedt <[email protected]>
LKML-Reference: <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>


---
lib/vsprintf.c | 16 ----------------
1 files changed, 0 insertions(+), 16 deletions(-)

diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index be3001f..7536ace 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -1051,13 +1051,6 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
if (str < end)
*str = '%';
++str;
- if (*fmt) {
- if (str < end)
- *str = *fmt;
- ++str;
- } else {
- --fmt;
- }
break;

case FORMAT_TYPE_NRCHARS: {
@@ -1339,8 +1332,6 @@ do { \
break;

case FORMAT_TYPE_INVALID:
- if (!*fmt)
- --fmt;
break;

case FORMAT_TYPE_NRCHARS: {
@@ -1523,13 +1514,6 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf)
if (str < end)
*str = '%';
++str;
- if (*fmt) {
- if (str < end)
- *str = *fmt;
- ++str;
- } else {
- --fmt;
- }
break;

case FORMAT_TYPE_NRCHARS:

2009-04-08 15:29:56

by Zhao Lei

[permalink] [raw]
Subject: [tip:core/printk] printk: add support of hh length modifier for printk

Commit-ID: a4e94ef0dd391eae05bdeacd12b8da3510957a97
Gitweb: http://git.kernel.org/tip/a4e94ef0dd391eae05bdeacd12b8da3510957a97
Author: Zhaolei <[email protected]>
AuthorDate: Fri, 27 Mar 2009 17:07:05 +0800
Committer: Ingo Molnar <[email protected]>
CommitDate: Wed, 8 Apr 2009 17:04:30 +0200

printk: add support of hh length modifier for printk

Impact: new feature, extend vsprintf format strings

hh is used as length modifier for signed char or unsigned char.
It is supported by glibc, we add kernel support now.

Signed-off-by: Zhao Lei <[email protected]>
Acked-by: Lai Jiangshan <[email protected]>
Acked-by: Frederic Weisbecker <[email protected]>
Cc: [email protected]
Cc: Steven Rostedt <[email protected]>
LKML-Reference: <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>


---
lib/vsprintf.c | 37 ++++++++++++++++++++++++++++++++-----
1 files changed, 32 insertions(+), 5 deletions(-)

diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 7536ace..b56f6d0 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -408,6 +408,8 @@ enum format_type {
FORMAT_TYPE_LONG_LONG,
FORMAT_TYPE_ULONG,
FORMAT_TYPE_LONG,
+ FORMAT_TYPE_UBYTE,
+ FORMAT_TYPE_BYTE,
FORMAT_TYPE_USHORT,
FORMAT_TYPE_SHORT,
FORMAT_TYPE_UINT,
@@ -853,11 +855,15 @@ qualifier:
spec->qualifier = -1;
if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
*fmt == 'Z' || *fmt == 'z' || *fmt == 't') {
- spec->qualifier = *fmt;
- ++fmt;
- if (spec->qualifier == 'l' && *fmt == 'l') {
- spec->qualifier = 'L';
- ++fmt;
+ spec->qualifier = *fmt++;
+ if (unlikely(spec->qualifier == *fmt)) {
+ if (spec->qualifier == 'l') {
+ spec->qualifier = 'L';
+ ++fmt;
+ } else if (spec->qualifier == 'h') {
+ spec->qualifier = 'H';
+ ++fmt;
+ }
}
}

@@ -919,6 +925,11 @@ qualifier:
spec->type = FORMAT_TYPE_SIZE_T;
} else if (spec->qualifier == 't') {
spec->type = FORMAT_TYPE_PTRDIFF;
+ } else if (spec->qualifier == 'H') {
+ if (spec->flags & SIGN)
+ spec->type = FORMAT_TYPE_BYTE;
+ else
+ spec->type = FORMAT_TYPE_UBYTE;
} else if (spec->qualifier == 'h') {
if (spec->flags & SIGN)
spec->type = FORMAT_TYPE_SHORT;
@@ -1087,6 +1098,12 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
case FORMAT_TYPE_PTRDIFF:
num = va_arg(args, ptrdiff_t);
break;
+ case FORMAT_TYPE_UBYTE:
+ num = (unsigned char) va_arg(args, int);
+ break;
+ case FORMAT_TYPE_BYTE:
+ num = (signed char) va_arg(args, int);
+ break;
case FORMAT_TYPE_USHORT:
num = (unsigned short) va_arg(args, int);
break;
@@ -1363,6 +1380,10 @@ do { \
case FORMAT_TYPE_PTRDIFF:
save_arg(ptrdiff_t);
break;
+ case FORMAT_TYPE_UBYTE:
+ case FORMAT_TYPE_BYTE:
+ save_arg(char);
+ break;
case FORMAT_TYPE_USHORT:
case FORMAT_TYPE_SHORT:
save_arg(short);
@@ -1538,6 +1559,12 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf)
case FORMAT_TYPE_PTRDIFF:
num = get_arg(ptrdiff_t);
break;
+ case FORMAT_TYPE_UBYTE:
+ num = get_arg(unsigned char);
+ break;
+ case FORMAT_TYPE_BYTE:
+ num = get_arg(signed char);
+ break;
case FORMAT_TYPE_USHORT:
num = get_arg(unsigned short);
break;